diff --git a/src/components/SwipeDeck.tsx b/src/components/SwipeDeck.tsx index 1de4ee2..7970ec5 100644 --- a/src/components/SwipeDeck.tsx +++ b/src/components/SwipeDeck.tsx @@ -5,6 +5,7 @@ import { AnimatePresence, motion } from "framer-motion"; import SwipeableCard from "./SwipeableCard"; import ActionButtons from "./ActionButtons"; import MatchResult from "./MatchResult"; +import SwipeGuide from "./SwipeGuide"; import { Restaurant, SwipeDirection, MatchType } from "@/types"; import { Heart } from "lucide-react"; @@ -36,6 +37,7 @@ export default function SwipeDeck({ const [localMatchId, setLocalMatchId] = useState(null); const [resetting, setResetting] = useState(false); const [bubble, setBubble] = useState(""); + const [guideVisible, setGuideVisible] = useState(true); const swipeFnRef = useRef<((direction: SwipeDirection) => void) | null>(null); const swipingRef = useRef(false); const prevLikeCounts = useRef>({}); @@ -97,6 +99,7 @@ export default function SwipeDeck({ if (!current) return; swipingRef.current = false; + if (guideVisible) setGuideVisible(false); const action = direction === "right" ? "like" : "nope"; sendSwipe(current.id, action); @@ -163,6 +166,9 @@ export default function SwipeDeck({
+ {currentIndex === 0 && !resolvedMatchId && guideVisible && ( + setGuideVisible(false)} /> + )} {!resolvedMatchId && ( {restaurants.map((restaurant, index) => { diff --git a/src/components/SwipeGuide.tsx b/src/components/SwipeGuide.tsx new file mode 100644 index 0000000..951f060 --- /dev/null +++ b/src/components/SwipeGuide.tsx @@ -0,0 +1,97 @@ +"use client"; + +import { useEffect, useState, useCallback } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { ThumbsDown, ThumbsUp } from "lucide-react"; + +const STORAGE_KEY = "nw_guide_v2"; + +interface SwipeGuideProps { + onDismiss: () => void; +} + +export default function SwipeGuide({ onDismiss }: SwipeGuideProps) { + const [visible, setVisible] = useState(() => { + if (typeof window === "undefined") return false; + return !localStorage.getItem(STORAGE_KEY); + }); + + const dismiss = useCallback(() => { + setVisible(false); + localStorage.setItem(STORAGE_KEY, "1"); + onDismiss(); + }, [onDismiss]); + + useEffect(() => { + if (!visible) { + onDismiss(); + return; + } + + const timer = setTimeout(dismiss, 3000); + return () => clearTimeout(timer); + }, []); // eslint-disable-line react-hooks/exhaustive-deps + + return ( + + {visible && ( + +
+ +
+ +
+ 不想去 + ← 左滑 +
+ + + + 滑动卡片 + + + + +
+ +
+ 想去 + 右滑 → +
+
+
+ )} +
+ ); +}