"use client"; import { useEffect, useState, useCallback, useRef } from "react"; import { useParams, useRouter } from "next/navigation"; import TopNav from "@/components/TopNav"; import SwipeDeck from "@/components/SwipeDeck"; import LeaveConfirmModal from "@/components/LeaveConfirmModal"; import { useRoomPolling } from "@/hooks/useRoomPolling"; import { getUserId } from "@/lib/userId"; export default function RoomPage() { const params = useParams<{ id: string }>(); const router = useRouter(); const roomId = params.id; const [userId, setUserId] = useState(""); const [joined, setJoined] = useState(false); const [joinFailed, setJoinFailed] = useState(false); const [showLeaveConfirm, setShowLeaveConfirm] = useState(false); const leavingRef = useRef(false); const { userCount, match, matchType, matchLikes, runnerUps, likeCounts, swipeCounts, restaurants, notFound, mutate, } = useRoomPolling(roomId); useEffect(() => { const id = getUserId(); setUserId(id); fetch(`/api/room/${roomId}/join`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ userId: id }), }).then((res) => { if (res.ok) setJoined(true); else setJoinFailed(true); }).catch(() => setJoinFailed(true)); }, [roomId]); useEffect(() => { window.history.pushState({ roomGuard: true }, ""); const handlePopState = () => { if (leavingRef.current) return; window.history.pushState({ roomGuard: true }, ""); setShowLeaveConfirm(true); }; const handleBeforeUnload = (e: BeforeUnloadEvent) => { if (leavingRef.current) return; e.preventDefault(); }; window.addEventListener("popstate", handlePopState); window.addEventListener("beforeunload", handleBeforeUnload); return () => { window.removeEventListener("popstate", handlePopState); window.removeEventListener("beforeunload", handleBeforeUnload); }; }, []); const confirmLeave = useCallback(() => { leavingRef.current = true; setShowLeaveConfirm(false); router.push("/"); }, [router]); const cancelLeave = useCallback(() => { setShowLeaveConfirm(false); }, []); const handleExitRequest = useCallback(() => { setShowLeaveConfirm(true); }, []); const handleReset = useCallback(async () => { await fetch(`/api/room/${roomId}/reset`, { method: "POST" }); await mutate(); }, [roomId, mutate]); const handleNarrow = useCallback(async (restaurantIds: string[]) => { await fetch(`/api/room/${roomId}/reset`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ restaurantIds }), }); await mutate(); }, [roomId, mutate]); if (notFound || joinFailed) { return (

🍜

房间不存在或已过期

房间号可能有误,或房间已超过 24 小时

); } const initialIndex = swipeCounts[userId] ?? 0; const ready = joined && userId && restaurants.length > 0; if (!ready) { return (

正在加载餐厅数据...

); } return (
); }