import { useRef, useCallback, useState } from 'react'; import { Box, Typography } from '@mui/material'; const THRESHOLD = 80; // px to trigger decision const MAX_ROTATE = 12; // degrees at full drag const MAX_DRAG = 180; // px reference for scale calculations export default function SwipeCard({ children, onSwipeLeft, onSwipeRight }) { const touchStart = useRef(null); const [dx, setDx] = useState(0); const [exiting, setExiting] = useState(null); // 'left' | 'right' | null const handleTouchStart = useCallback((e) => { touchStart.current = e.touches[0].clientX; setExiting(null); }, []); const handleTouchMove = useCallback((e) => { if (touchStart.current === null) return; const delta = e.touches[0].clientX - touchStart.current; setDx(delta); }, []); const handleTouchEnd = useCallback(() => { if (touchStart.current === null) return; touchStart.current = null; if (dx <= -THRESHOLD) { setExiting('left'); setTimeout(() => { setDx(0); setExiting(null); onSwipeLeft?.(); }, 220); } else if (dx >= THRESHOLD) { setExiting('right'); setTimeout(() => { setDx(0); setExiting(null); onSwipeRight?.(); }, 220); } else { // snap back setDx(0); } }, [dx, onSwipeLeft, onSwipeRight]); const progress = Math.min(Math.abs(dx) / THRESHOLD, 1); const rotate = (dx / MAX_DRAG) * MAX_ROTATE; const translateX = exiting === 'left' ? -window.innerWidth : exiting === 'right' ? window.innerWidth : dx; const isLeft = dx < -10; const isRight = dx > 10; const overlayOpacity = Math.min(Math.abs(dx) / THRESHOLD, 0.7); return ( {/* Draggable card */} {children} {/* ABSENT overlay — left swipe — red */} ABSENT {/* PRESENT overlay — right swipe — green */} PRESENT ); }