From 918ece5f2c351895c83653fb71d3065e2d2992a0 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 24 Jun 2025 14:34:49 +0700 Subject: dragable banner --- src/lib/home/components/PopupBannerPromotion.jsx | 108 ++++++++++++++++------- 1 file changed, 76 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/lib/home/components/PopupBannerPromotion.jsx b/src/lib/home/components/PopupBannerPromotion.jsx index c5466009..347617d6 100644 --- a/src/lib/home/components/PopupBannerPromotion.jsx +++ b/src/lib/home/components/PopupBannerPromotion.jsx @@ -18,6 +18,9 @@ const PagePopupInformation = () => { const [position, setPosition] = useState({ x: 20, y: window.innerHeight - 170 }); const dragStartPos = useRef({ x: 0, y: 0 }); const isDragging = useRef(false); + const isTouching = useRef(false); + + const [isSnapping, setIsSnapping] = useState(false); // 🔥 Penanda kapan transisi diaktifkan useEffect(() => { const getData = async () => { @@ -41,10 +44,62 @@ const PagePopupInformation = () => { } }, [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; + + newX = Math.max(0, 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; + + 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 }; isDragging.current = false; + setIsSnapping(false); // 🔥 Matikan transisi saat drag window.addEventListener('mousemove', handleMouseMove); window.addEventListener('mouseup', handleMouseUp); @@ -68,47 +123,36 @@ const PagePopupInformation = () => { }; const handleMouseUp = () => { + if (isDragging.current) { + const popupWidth = popupRef.current?.offsetWidth || 0; + 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 }); + } + } + window.removeEventListener('mousemove', handleMouseMove); window.removeEventListener('mouseup', handleMouseUp); + + isDragging.current = false; }; - // Touch Events (Mobile) const handleTouchStart = (e) => { if (e.touches.length === 1) { - const touch = e.touches[0]; - dragStartPos.current = { x: touch.clientX - position.x, y: touch.clientY - position.y }; + dragStartPos.current = { x: e.touches[0].clientX - position.x, y: e.touches[0].clientY - position.y }; isDragging.current = false; - - window.addEventListener('touchmove', handleTouchMove, { passive: false }); - window.addEventListener('touchend', handleTouchEnd); - } - }; - - const handleTouchMove = (e) => { - if (e.touches.length === 1) { - e.preventDefault(); - isDragging.current = true; - - 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; - - newX = Math.max(0, Math.min(newX, maxX)); - newY = Math.max(0, Math.min(newY, maxY)); - - setPosition({ x: newX, y: newY }); + isTouching.current = true; + setIsSnapping(false); // 🔥 Matikan transisi saat drag } }; - const handleTouchEnd = () => { - window.removeEventListener('touchmove', handleTouchMove); - window.removeEventListener('touchend', handleTouchEnd); - }; - if (!active || !data || loading || !Array.isArray(data) || !data[0]?.image) return null; const banner = data[0]; @@ -117,7 +161,7 @@ const PagePopupInformation = () => {