From 5002ab911b779f3b3ed9b40dcda0f175269e8872 Mon Sep 17 00:00:00 2001
From: "Indoteknik ." <andrifebriyadiputra@gmail.com>
Date: Thu, 17 Jul 2025 09:44:17 +0700
Subject: (andri) fix

---
 src/lib/home/components/PopupBannerPromotion.jsx | 339 +++++++++--------------
 1 file changed, 131 insertions(+), 208 deletions(-)

(limited to 'src/lib/home/components/PopupBannerPromotion.jsx')

diff --git a/src/lib/home/components/PopupBannerPromotion.jsx b/src/lib/home/components/PopupBannerPromotion.jsx
index 1ef166f2..eff2ba59 100644
--- a/src/lib/home/components/PopupBannerPromotion.jsx
+++ b/src/lib/home/components/PopupBannerPromotion.jsx
@@ -2,14 +2,15 @@ import { useRouter } from 'next/router';
 import { useEffect, useState, useRef } from 'react';
 import Image from 'next/image';
 import Link from 'next/link';
-import { getAuth } from '~/libs/auth';
 import { X } from 'lucide-react';
+import { getAuth } from '~/libs/auth';
 import useDevice from '@/core/hooks/useDevice';
 
 const PagePopupInformation = () => {
   const router = useRouter();
   const isHomePage = router.pathname === '/';
   const auth = getAuth();
+  const { isDesktop } = useDevice();
 
   const [active, setActive] = useState(false);
   const [data, setData] = useState(null);
@@ -20,26 +21,43 @@ const PagePopupInformation = () => {
   const dragStartPos = useRef({ x: 0, y: 0 });
   const isDragging = useRef(false);
   const isTouching = useRef(false);
-  const { isDesktop } = useDevice();
+  const [isSnapping, setIsSnapping] = useState(false);
+  const [containerLeft, setContainerLeft] = useState(0);
 
-  const [isSnapping, setIsSnapping] = useState(false); // 🔥 Penanda kapan transisi diaktifkan
+  useEffect(() => {
+    if (isHomePage && !auth) {
+      setActive(true);
+      fetchData();
+    }
+  }, [isHomePage, auth]);
 
-  const [containerLeft, setContainerLeft] = useState(0);
+  const fetchData = async () => {
+    try {
+      const res = await fetch(`/api/hero-banner?type=dragable-banner`);
+      const { data } = await res.json();
+      if (Array.isArray(data) && data[0]?.image) {
+        setData(data[0]);
+      } else {
+        setActive(false);
+      }
+    } catch (error) {
+      console.error('Failed to fetch popup banner:', error);
+    } finally {
+      setLoading(false);
+    }
+  };
 
   const updateContainerLeft = () => {
     const container = document.querySelector('.container');
     if (container) {
-      const left = container.getBoundingClientRect().left;
-      setContainerLeft(left);
+      setContainerLeft(container.getBoundingClientRect().left);
     }
   };
 
   useEffect(() => {
     updateContainerLeft();
-
     window.addEventListener('resize', updateContainerLeft);
     window.addEventListener('scroll', updateContainerLeft);
-
     return () => {
       window.removeEventListener('resize', updateContainerLeft);
       window.removeEventListener('scroll', updateContainerLeft);
@@ -47,100 +65,31 @@ const PagePopupInformation = () => {
   }, []);
 
   useEffect(() => {
-    const getData = async () => {
-      try {
-        const res = await fetch(`/api/hero-banner?type=dragable-banner`);
-        const { data } = await res.json();
-        if (Array.isArray(data) && data.length > 0 && data[0]?.image) {
-          setData(data);
-        } else {
-          setActive(false);
-        }
-      } catch (error) {
-        console.error('Failed to fetch popup banner:', error);
-      }
-      setLoading(false);
-    };
-
-    if (isHomePage && !auth) {
-      setActive(true);
-      getData();
+    if (isDesktop && containerLeft) {
+      const popupWidth = popupRef.current?.offsetWidth || 85;
+      setPosition({
+        x: containerLeft - popupWidth - 20,
+        y: window.innerHeight - 130,
+      });
     }
-  }, [isHomePage, auth]);
-
-  useEffect(() => {
-    const handleGlobalTouchMove = (e) => {
-      if (isTouching.current) {
-        e.preventDefault();
-        isDragging.current = true;
-        setIsSnapping(false); // 🔥 Matikan transisi saat drag
-
-        let newX = e.touches[0].clientX - dragStartPos.current.x;
-        let newY = e.touches[0].clientY - dragStartPos.current.y;
-
-        const popupWidth = popupRef.current?.offsetWidth || 0;
-        const popupHeight = popupRef.current?.offsetHeight || 0;
-        const maxX = window.innerWidth - popupWidth - 20;
-        const maxY = window.innerHeight - popupHeight - 20;
-        const minX = -containerLeft;
-
-        newX = Math.max(minX, Math.min(newX, maxX));
-        newY = Math.max(0, Math.min(newY, maxY));
-
-        setPosition({ x: newX, y: newY });
-      }
-    };
-
-    const handleGlobalTouchEnd = () => {
-      if (isDragging.current) {
-        const popupWidth = popupRef.current?.offsetWidth || 0;
-        const screenMiddle = window.innerWidth / 2;
+  }, [isDesktop, containerLeft]);
 
-        setIsSnapping(true); // 🔥 Aktifkan transisi saat snap
-
-        if (position.x + popupWidth / 2 < screenMiddle) {
-          // Snap ke kiri
-          setPosition({ x: 20, y: position.y });
-        } else {
-          // Snap ke kanan
-          setPosition({ x: window.innerWidth - popupWidth - 20, y: position.y });
-        }
-      }
-
-      isTouching.current = false;
-      isDragging.current = false;
-    };
-
-    window.addEventListener('touchmove', handleGlobalTouchMove, { passive: false });
-    window.addEventListener('touchend', handleGlobalTouchEnd);
-
-    return () => {
-      window.removeEventListener('touchmove', handleGlobalTouchMove);
-      window.removeEventListener('touchend', handleGlobalTouchEnd);
-    };
-  }, [position]);
-
-  const handleMouseDown = (e) => {
-    e.preventDefault();
-    dragStartPos.current = { x: e.clientX - position.x, y: e.clientY - position.y };
+  const startDrag = (clientX, clientY) => {
+    dragStartPos.current = { x: clientX - position.x, y: clientY - position.y };
     isDragging.current = false;
-    setIsSnapping(false); // 🔥 Matikan transisi saat drag
-
-    window.addEventListener('mousemove', handleMouseMove);
-    window.addEventListener('mouseup', handleMouseUp);
+    setIsSnapping(false);
   };
 
-  const handleMouseMove = (e) => {
+  const moveDrag = (clientX, clientY) => {
     isDragging.current = true;
-
-    let newX = e.clientX - dragStartPos.current.x;
-    let newY = e.clientY - dragStartPos.current.y;
-
-    const popupWidth = popupRef.current?.offsetWidth || 0;
-    const popupHeight = popupRef.current?.offsetHeight || 0;
+    const popupWidth = popupRef.current?.offsetWidth || 85;
+    const popupHeight = popupRef.current?.offsetHeight || 85;
     const maxX = window.innerWidth - popupWidth - 20;
     const maxY = window.innerHeight - popupHeight - 20;
-    const minX = -containerLeft;
+    const minX = isDesktop ? containerLeft - popupWidth - 20 : 0;
+
+    let newX = clientX - dragStartPos.current.x;
+    let newY = clientY - dragStartPos.current.y;
 
     newX = Math.max(minX, Math.min(newX, maxX));
     newY = Math.max(0, Math.min(newY, maxY));
@@ -148,146 +97,120 @@ const PagePopupInformation = () => {
     setPosition({ x: newX, y: newY });
   };
 
-  const handleMouseUp = () => {
+  const endDrag = () => {
     if (isDragging.current) {
-      const popupWidth = popupRef.current?.offsetWidth || 0;
+      const popupWidth = popupRef.current?.offsetWidth || 85;
       const screenMiddle = window.innerWidth / 2;
 
-      setIsSnapping(true); // 🔥 Aktifkan transisi saat snap
-
-      if (position.x + popupWidth / 2 < screenMiddle) {
-        // Snap ke kiri
-        setPosition({ x: 20, y: position.y });
-      } else {
-        // Snap ke kanan
-        setPosition({ x: window.innerWidth - popupWidth - 20, y: position.y });
-      }
+      setIsSnapping(true);
+      setPosition(pos => ({
+        x: pos.x + popupWidth / 2 < screenMiddle ? 20 : window.innerWidth - popupWidth - 20,
+        y: pos.y,
+      }));
     }
+    isDragging.current = false;
+    isTouching.current = false;
+  };
+
+  const handleMouseDown = e => {
+    e.preventDefault();
+    startDrag(e.clientX, e.clientY);
+    window.addEventListener('mousemove', handleMouseMove);
+    window.addEventListener('mouseup', handleMouseUp);
+  };
+
+  const handleMouseMove = e => moveDrag(e.clientX, e.clientY);
 
+  const handleMouseUp = () => {
+    endDrag();
     window.removeEventListener('mousemove', handleMouseMove);
     window.removeEventListener('mouseup', handleMouseUp);
-
-    isDragging.current = false;
   };
 
-  const handleTouchStart = (e) => {
+  const handleTouchStart = e => {
     if (e.touches.length === 1) {
-      dragStartPos.current = { x: e.touches[0].clientX - position.x, y: e.touches[0].clientY - position.y };
-      isDragging.current = false;
       isTouching.current = true;
-      setIsSnapping(false); // 🔥 Matikan transisi saat drag
+      startDrag(e.touches[0].clientX, e.touches[0].clientY);
     }
   };
 
-  if (!active || !data || loading || !Array.isArray(data) || !data[0]?.image) return null;
+  useEffect(() => {
+    const handleTouchMove = e => {
+      if (isTouching.current) {
+        e.preventDefault();
+        moveDrag(e.touches[0].clientX, e.touches[0].clientY);
+      }
+    };
 
-  const banner = data[0];
+    const handleTouchEnd = () => endDrag();
 
-  if (isDesktop) {
-    // ✅ RENDER UNTUK DESKTOP
-    return (
-      <div
-        className="fixed z-[9999] pointer-events-none"
-        style={{
-          top: '40px',
-          left: `${Math.max(containerLeft - 120, 0)}px`
-        }}
-      >
-        <div
-          ref={popupRef}
-          className="relative pointer-events-auto"
-          style={{
-            transform: `translate(${position.x}px, ${position.y}px)`,
-            cursor: 'grab',
-            width: '85px',
-          }}
-          onMouseDown={handleMouseDown}
-          onTouchStart={handleTouchStart}
-        >
-          <Link
-            href={typeof banner.url === 'boolean' && banner.url === false ? '/' : banner.url}
-            onClick={(e) => {
-              if (isDragging.current) {
-                e.preventDefault();
-                isDragging.current = false;
-              } else {
-                setActive(false);
-              }
-            }}
-            draggable="false"
-          >
-            <Image
-              src={banner.image}
-              alt={banner.name || 'popup'}
-              width={85}
-              height={85}
-              className="w-full h-auto select-none"
-              draggable="false"
-            />
-          </Link>
+    window.addEventListener('touchmove', handleTouchMove, { passive: false });
+    window.addEventListener('touchend', handleTouchEnd);
+    return () => {
+      window.removeEventListener('touchmove', handleTouchMove);
+      window.removeEventListener('touchend', handleTouchEnd);
+    };
+  }, []);
 
-          <button
-            onClick={() => setActive(false)}
-            className="absolute -top-2 -right-2 z-10 p-1 bg-red-500 rounded-full hover:bg-red-600 transition-colors"
-            aria-label="Close popup"
-          >
-            <X className="w-3 h-3 text-white" />
-          </button>
-        </div>
-      </div>
-    );
-  }
+  if (!active || !data || loading) return null;
 
-  // ✅ RENDER UNTUK MOBILE
-  return (
-    <div className="fixed z-[9999] pointer-events-none"
+  const popupContent = (
+    <div
+      ref={popupRef}
+      className={`relative pointer-events-auto ${isSnapping ? 'transition-transform duration-300 ease-out' : ''}`}
       style={{
-            top: '40px',
-          }}>
-      <div
-        ref={popupRef}
-        className={`absolute pointer-events-auto ${isSnapping ? 'transition-transform duration-300 ease-out' : ''}`}
-        style={{
-          transform: `translate(${position.x}px, ${position.y}px)`,
-          cursor: 'grab',
-          width: '85px',
+        transform: `translate(${position.x}px, ${position.y}px)`,
+        cursor: 'grab',
+        width: '85px',
+      }}
+      onMouseDown={handleMouseDown}
+      onTouchStart={handleTouchStart}
+    >
+      <Link
+        href={typeof data.url === 'boolean' && data.url === false ? '/' : data.url}
+        onClick={e => {
+          if (isDragging.current) {
+            e.preventDefault();
+            isDragging.current = false;
+          } else {
+            setActive(false);
+          }
         }}
-        onMouseDown={handleMouseDown}
-        onTouchStart={handleTouchStart}
+        draggable="false"
       >
-        <Link
-          href={typeof banner.url === 'boolean' && banner.url === false ? '/' : banner.url}
-          onClick={(e) => {
-            if (isDragging.current) {
-              e.preventDefault();
-              isDragging.current = false;
-            } else {
-              setActive(false);
-            }
-          }}
+        <Image
+          src={data.image}
+          alt={data.name || 'popup'}
+          width={85}
+          height={85}
+          className="w-full h-auto select-none"
           draggable="false"
-        >
-          <Image
-            src={banner.image}
-            alt={banner.name || 'popup'}
-            width={85}
-            height={85}
-            className="w-full h-auto select-none"
-            draggable="false"
-          />
-        </Link>
+        />
+      </Link>
 
-        <button
-          onClick={() => setActive(false)}
-          className="absolute -top-2 -right-2 z-10 p-1 bg-red-500 rounded-full hover:bg-red-600 transition-colors"
-          aria-label="Close popup"
-        >
-          <X className="w-3 h-3 text-white" />
-        </button>
-      </div>
+      <button
+        onClick={() => setActive(false)}
+        className="absolute -top-2 -right-2 z-10 p-1 bg-red-500 rounded-full hover:bg-red-600 transition-colors"
+        aria-label="Close popup"
+      >
+        <X className="w-3 h-3 text-white" />
+      </button>
     </div>
   );
 
+  if (isDesktop) {
+    return (
+      <div className="fixed z-[9999] pointer-events-none top-0 left-0 w-screen h-screen">
+        {popupContent}
+      </div>
+    );
+  }
+
+  return (
+    <div className="fixed z-[9999] pointer-events-none top-[40px] left-0">
+      {popupContent}
+    </div>
+  );
 };
 
 export default PagePopupInformation;
-- 
cgit v1.2.3

