From 638c592d2dc3bb77c8b9da36ea6c84afc5505df0 Mon Sep 17 00:00:00 2001
From: "Indoteknik ." <andrifebriyadiputra@gmail.com>
Date: Wed, 16 Jul 2025 09:23:59 +0700
Subject: (andri) fix layout popup bottom

---
 src/lib/home/components/PopupBannerPromotion.jsx | 28 +++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

(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 347617d6..6700030a 100644
--- a/src/lib/home/components/PopupBannerPromotion.jsx
+++ b/src/lib/home/components/PopupBannerPromotion.jsx
@@ -22,6 +22,28 @@ const PagePopupInformation = () => {
 
   const [isSnapping, setIsSnapping] = useState(false); // 🔥 Penanda kapan transisi diaktifkan
 
+  const [containerLeft, setContainerLeft] = useState(0);
+
+  const updateContainerLeft = () => {
+    const container = document.querySelector('.container');
+    if (container) {
+      const left = container.getBoundingClientRect().left;
+      setContainerLeft(left);
+    }
+  };
+
+  useEffect(() => {
+    updateContainerLeft();
+
+    window.addEventListener('resize', updateContainerLeft);
+    window.addEventListener('scroll', updateContainerLeft);
+
+    return () => {
+      window.removeEventListener('resize', updateContainerLeft);
+      window.removeEventListener('scroll', updateContainerLeft);
+    };
+  }, []);
+
   useEffect(() => {
     const getData = async () => {
       try {
@@ -158,7 +180,11 @@ const PagePopupInformation = () => {
   const banner = data[0];
 
   return (
-    <div className="fixed inset-0 z-[9999] pointer-events-none">
+    <div className="fixed top-[50px] left-[120px] z-[9999] pointer-events-none"
+        style={{
+        top: '50px',
+        left: `${containerLeft - 125}px`,
+      }}>
       <div
         ref={popupRef}
         className={`absolute pointer-events-auto ${isSnapping ? 'transition-transform duration-300 ease-out' : ''}`}
-- 
cgit v1.2.3


From 39b37aa1309a4d3755678bac39e0ba4132317a74 Mon Sep 17 00:00:00 2001
From: "Indoteknik ." <andrifebriyadiputra@gmail.com>
Date: Wed, 16 Jul 2025 10:23:17 +0700
Subject: (andri) fix

---
 src/lib/home/components/PopupBannerPromotion.jsx | 6 +++---
 1 file changed, 3 insertions(+), 3 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 6700030a..1463840a 100644
--- a/src/lib/home/components/PopupBannerPromotion.jsx
+++ b/src/lib/home/components/PopupBannerPromotion.jsx
@@ -180,16 +180,16 @@ const PagePopupInformation = () => {
   const banner = data[0];
 
   return (
-    <div className="fixed top-[50px] left-[120px] z-[9999] pointer-events-none"
+    <div className="fixed z-[9999] pointer-events-none"
         style={{
-        top: '50px',
+        bottom: '125px',
         left: `${containerLeft - 125}px`,
       }}>
       <div
         ref={popupRef}
         className={`absolute pointer-events-auto ${isSnapping ? 'transition-transform duration-300 ease-out' : ''}`}
         style={{
-          transform: `translate(${position.x}px, ${position.y}px)`,
+          transform: `translate(${position.x}px, 0px)`,
           cursor: 'grab',
           width: '85px',
         }}
-- 
cgit v1.2.3


From c42dfc0b052a50d43d0bf665ea9959129e87d99c Mon Sep 17 00:00:00 2001
From: "Indoteknik ." <andrifebriyadiputra@gmail.com>
Date: Thu, 17 Jul 2025 08:49:25 +0700
Subject: (andri) rev button close popup bottom & fix layout mobile

---
 src/lib/home/components/PopupBannerPromotion.jsx | 134 ++++++++++++++++-------
 1 file changed, 94 insertions(+), 40 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 1463840a..1ef166f2 100644
--- a/src/lib/home/components/PopupBannerPromotion.jsx
+++ b/src/lib/home/components/PopupBannerPromotion.jsx
@@ -4,6 +4,7 @@ import Image from 'next/image';
 import Link from 'next/link';
 import { getAuth } from '~/libs/auth';
 import { X } from 'lucide-react';
+import useDevice from '@/core/hooks/useDevice';
 
 const PagePopupInformation = () => {
   const router = useRouter();
@@ -19,6 +20,7 @@ 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); // 🔥 Penanda kapan transisi diaktifkan
 
@@ -80,8 +82,9 @@ const PagePopupInformation = () => {
         const popupHeight = popupRef.current?.offsetHeight || 0;
         const maxX = window.innerWidth - popupWidth - 20;
         const maxY = window.innerHeight - popupHeight - 20;
+        const minX = -containerLeft;
 
-        newX = Math.max(0, Math.min(newX, maxX));
+        newX = Math.max(minX, Math.min(newX, maxX));
         newY = Math.max(0, Math.min(newY, maxY));
 
         setPosition({ x: newX, y: newY });
@@ -137,8 +140,9 @@ const PagePopupInformation = () => {
     const popupHeight = popupRef.current?.offsetHeight || 0;
     const maxX = window.innerWidth - popupWidth - 20;
     const maxY = window.innerHeight - popupHeight - 20;
+    const minX = -containerLeft;
 
-    newX = Math.max(0, Math.min(newX, maxX));
+    newX = Math.max(minX, Math.min(newX, maxX));
     newY = Math.max(0, Math.min(newY, maxY));
 
     setPosition({ x: newX, y: newY });
@@ -179,61 +183,111 @@ const PagePopupInformation = () => {
 
   const banner = data[0];
 
-  return (
-    <div className="fixed z-[9999] pointer-events-none"
-        style={{
-        bottom: '125px',
-        left: `${containerLeft - 125}px`,
-      }}>
+  if (isDesktop) {
+    // ✅ RENDER UNTUK DESKTOP
+    return (
       <div
-        ref={popupRef}
-        className={`absolute pointer-events-auto ${isSnapping ? 'transition-transform duration-300 ease-out' : ''}`}
+        className="fixed z-[9999] pointer-events-none"
         style={{
-          transform: `translate(${position.x}px, 0px)`,
-          cursor: 'grab',
-          width: '85px',
+          top: '40px',
+          left: `${Math.max(containerLeft - 120, 0)}px`
         }}
       >
-        <div className="relative w-full h-auto">
-          <div
-            onMouseDown={handleMouseDown}
-            onTouchStart={handleTouchStart}
-            className="cursor-grab active:cursor-grabbing"
+        <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"
           >
-            <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={banner.image}
+              alt={banner.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>
-          </div>
+            />
+          </Link>
 
           <button
             onClick={() => setActive(false)}
-            className="absolute -top-2 -right-2 z-10 p-1 bg-gray-500 rounded-full hover:bg-gray-600 transition-colors"
+            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>
+    );
+  }
+
+  // ✅ RENDER UNTUK MOBILE
+  return (
+    <div className="fixed z-[9999] pointer-events-none"
+      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',
+        }}
+        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>
+
+        <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>
   );
+
 };
 
 export default PagePopupInformation;
-- 
cgit v1.2.3


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


From 126a61f234218ec4553bdcf2ab0c19cfeff5a921 Mon Sep 17 00:00:00 2001
From: "Indoteknik ." <andrifebriyadiputra@gmail.com>
Date: Thu, 17 Jul 2025 15:55:10 +0700
Subject: (andri) fix popup

---
 src/lib/home/components/PopupBannerPromotion.jsx | 53 ++++++++++++++++++++----
 1 file changed, 44 insertions(+), 9 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 eff2ba59..1392a246 100644
--- a/src/lib/home/components/PopupBannerPromotion.jsx
+++ b/src/lib/home/components/PopupBannerPromotion.jsx
@@ -47,6 +47,27 @@ const PagePopupInformation = () => {
     }
   };
 
+  useEffect(() => {
+    const handleResizeOrZoom = () => {
+      if (!popupRef.current) return;
+
+      const popupWidth = popupRef.current.offsetWidth || 85;
+      const popupHeight = popupRef.current.offsetHeight || 85;
+
+      setPosition({
+        x: 20,
+        y: window.innerHeight - popupHeight - 20,
+      });
+    };
+
+    window.addEventListener('resize', handleResizeOrZoom);
+
+    return () => {
+      window.removeEventListener('resize', handleResizeOrZoom);
+    };
+  }, []);
+
+
   const updateContainerLeft = () => {
     const container = document.querySelector('.container');
     if (container) {
@@ -85,8 +106,11 @@ const PagePopupInformation = () => {
     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 = isDesktop ? containerLeft - popupWidth - 20 : 0;
+    
+    const bottomPadding = 80; // batas bawah minimal
+    const maxY = window.innerHeight - popupHeight - bottomPadding;
+    
+    const minX = 0;
 
     let newX = clientX - dragStartPos.current.x;
     let newY = clientY - dragStartPos.current.y;
@@ -99,19 +123,30 @@ const PagePopupInformation = () => {
 
   const endDrag = () => {
     if (isDragging.current) {
-      const popupWidth = popupRef.current?.offsetWidth || 85;
-      const screenMiddle = window.innerWidth / 2;
-
       setIsSnapping(true);
-      setPosition(pos => ({
-        x: pos.x + popupWidth / 2 < screenMiddle ? 20 : window.innerWidth - popupWidth - 20,
-        y: pos.y,
-      }));
+
+      if (isDesktop) {
+        const popupWidth = popupRef.current?.offsetWidth || 85;
+        setPosition({
+          x: containerLeft - popupWidth - 20,
+          y: window.innerHeight - 130,
+        });
+      } else {
+        const popupWidth = popupRef.current?.offsetWidth || 85;
+        const screenMiddle = window.innerWidth / 2;
+
+        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);
-- 
cgit v1.2.3


From 7494d68e936833d3958563a99a5fe977f24d7536 Mon Sep 17 00:00:00 2001
From: "Indoteknik ." <andrifebriyadiputra@gmail.com>
Date: Thu, 17 Jul 2025 16:19:40 +0700
Subject: (andri) fix padding drag popup

---
 src/lib/home/components/PopupBannerPromotion.jsx | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 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 1392a246..538f35e6 100644
--- a/src/lib/home/components/PopupBannerPromotion.jsx
+++ b/src/lib/home/components/PopupBannerPromotion.jsx
@@ -5,6 +5,7 @@ import Link from 'next/link';
 import { X } from 'lucide-react';
 import { getAuth } from '~/libs/auth';
 import useDevice from '@/core/hooks/useDevice';
+import { createPortal } from 'react-dom';
 
 const PagePopupInformation = () => {
   const router = useRouter();
@@ -23,6 +24,12 @@ const PagePopupInformation = () => {
   const isTouching = useRef(false);
   const [isSnapping, setIsSnapping] = useState(false);
   const [containerLeft, setContainerLeft] = useState(0);
+  
+  const [isClient, setIsClient] = useState(false);
+
+  useEffect(() => {
+    setIsClient(true);
+  }, []);
 
   useEffect(() => {
     if (isHomePage && !auth) {
@@ -106,17 +113,18 @@ const PagePopupInformation = () => {
     const popupWidth = popupRef.current?.offsetWidth || 85;
     const popupHeight = popupRef.current?.offsetHeight || 85;
     const maxX = window.innerWidth - popupWidth - 20;
-    
-    const bottomPadding = 80; // batas bawah minimal
+
+    const topPadding = isDesktop ? 0 : 130;
+    const bottomPadding = isDesktop ? 0 : 80;
     const maxY = window.innerHeight - popupHeight - bottomPadding;
-    
+
     const minX = 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));
+    newY = Math.max(topPadding, Math.min(newY, maxY));
 
     setPosition({ x: newX, y: newY });
   };
@@ -233,11 +241,12 @@ const PagePopupInformation = () => {
     </div>
   );
 
-  if (isDesktop) {
-    return (
+  if (isDesktop && isClient) {
+    return createPortal(
       <div className="fixed z-[9999] pointer-events-none top-0 left-0 w-screen h-screen">
         {popupContent}
-      </div>
+      </div>,
+      document.body
     );
   }
 
-- 
cgit v1.2.3

