diff options
| -rw-r--r-- | src/lib/home/components/PopupBannerPromotion.jsx | 136 | ||||
| -rw-r--r-- | src/pages/index.jsx | 3 |
2 files changed, 139 insertions, 0 deletions
diff --git a/src/lib/home/components/PopupBannerPromotion.jsx b/src/lib/home/components/PopupBannerPromotion.jsx new file mode 100644 index 00000000..03855fbb --- /dev/null +++ b/src/lib/home/components/PopupBannerPromotion.jsx @@ -0,0 +1,136 @@ +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'; + +const PagePopupInformation = () => { + const router = useRouter(); + const isHomePage = router.pathname === '/'; + const auth = getAuth(); + + const [active, setActive] = useState(false); + const [data, setData] = useState(null); + const [loading, setLoading] = useState(true); + + const popupRef = useRef(null); + const [position, setPosition] = useState({ x: 20, y: window.innerHeight - 170 }); + const dragStartPos = useRef({ x: 0, y: 0 }); + const isDragging = useRef(false); + + useEffect(() => { + const getData = async () => { + try { + const res = await fetch(`/api/hero-banner?type=dragable-banner`); + const { data } = await res.json(); + // Cek apakah data array dan ada image-nya + if (Array.isArray(data) && data.length > 0 && data[0]?.image) { + setData(data); + } else { + setActive(false); // Tidak tampil jika tidak valid + } + } catch (error) { + console.error('Failed to fetch popup banner:', error); + } + setLoading(false); + }; + + if (isHomePage && !auth) { + setActive(true); + getData(); + } + }, [isHomePage, auth]); + + const handleMouseDown = (e) => { + e.preventDefault(); + dragStartPos.current = { + x: e.clientX - position.x, + y: e.clientY - position.y, + }; + isDragging.current = false; + + window.addEventListener('mousemove', handleMouseMove); + window.addEventListener('mouseup', handleMouseUp); + }; + + const handleMouseMove = (e) => { + 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 maxX = window.innerWidth - popupWidth - 20; + const maxY = window.innerHeight - popupHeight - 20; + + newX = Math.max(0, Math.min(newX, maxX)); + newY = Math.max(0, Math.min(newY, maxY)); + + setPosition({ x: newX, y: newY }); + }; + + const handleMouseUp = () => { + window.removeEventListener('mousemove', handleMouseMove); + window.removeEventListener('mouseup', handleMouseUp); + }; + + // Jika data tidak valid, langsung return null + if (!active || !data || loading || !Array.isArray(data) || !data[0]?.image) return null; + + const banner = data[0]; // Data sudah aman di sini + + return ( + <div className="fixed inset-0 z-[9999] pointer-events-none"> + <div + ref={popupRef} + className="absolute pointer-events-auto" + style={{ + transform: `translate(${position.x}px, ${position.y}px)`, + cursor: 'grab', + width: '150px', + }} + > + <div className="relative w-full h-auto"> + <div + onMouseDown={handleMouseDown} + className="cursor-grab active:cursor-grabbing" + > + <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={150} + height={150} + className="w-full h-auto select-none" + draggable="false" + /> + </Link> + </div> + + <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" + aria-label="Close popup" + > + <X className="w-3 h-3 text-white" /> + </button> + </div> + </div> + </div> + ); +}; + +export default PagePopupInformation; diff --git a/src/pages/index.jsx b/src/pages/index.jsx index df5047a3..809f00ae 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -5,6 +5,7 @@ import DelayRender from '@/core/components/elements/DelayRender/DelayRender'; import DesktopView from '@/core/components/views/DesktopView'; import MobileView from '@/core/components/views/MobileView'; import PreferredBrandSkeleton from '@/lib/home/components/Skeleton/PreferredBrandSkeleton'; +import PagePopupInformation from '@/lib/home/components/PopupBannerPromotion'; import dynamic from 'next/dynamic'; import { useRef } from 'react'; import { getAuth } from '~/libs/auth'; @@ -116,6 +117,7 @@ export default function Home({ categoryId }) { <PagePopupIformation /> <DesktopView> + <PagePopupInformation /> <div className='container mx-auto'> <div className='flex min-h-[400px] h-[460px]' @@ -160,6 +162,7 @@ export default function Home({ categoryId }) { </div> </DesktopView> <MobileView> + <PagePopupInformation /> <DelayRender renderAfter={200}> <HeroBanner /> </DelayRender> |
