summaryrefslogtreecommitdiff
path: root/src/lib/home
diff options
context:
space:
mode:
authorIndoteknik . <andrifebriyadiputra@gmail.com>2025-07-17 09:44:17 +0700
committerIndoteknik . <andrifebriyadiputra@gmail.com>2025-07-17 09:44:17 +0700
commit5002ab911b779f3b3ed9b40dcda0f175269e8872 (patch)
treeb0797b5e5328555eb10e2e3f05461e4e1fd65fb2 /src/lib/home
parentc42dfc0b052a50d43d0bf665ea9959129e87d99c (diff)
(andri) fix
Diffstat (limited to 'src/lib/home')
-rw-r--r--src/lib/home/components/PopupBannerPromotion.jsx339
1 files changed, 131 insertions, 208 deletions
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;