b406acc813
滑卡时进度条下方展示所有人的进度(如 🐸你 12/15 🐱 8/15), 等待页面也改为详细进度卡片,减少等待焦虑并增强社交临场感。 每个用户根据 userId 确定性分配 emoji 头像,无需手动输入。
68 lines
2.0 KiB
TypeScript
68 lines
2.0 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState, useCallback } from "react";
|
|
import { useParams } from "next/navigation";
|
|
import TopNav from "@/components/TopNav";
|
|
import SwipeDeck from "@/components/SwipeDeck";
|
|
import { useRoomPolling } from "@/hooks/useRoomPolling";
|
|
import { getUserId } from "@/lib/userId";
|
|
|
|
export default function RoomPage() {
|
|
const params = useParams<{ id: string }>();
|
|
const roomId = params.id;
|
|
|
|
const [userId, setUserId] = useState("");
|
|
const [joined, setJoined] = useState(false);
|
|
|
|
const {
|
|
userCount, match, matchType, matchLikes, likeCounts, swipeCounts, restaurants, 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(() => setJoined(true));
|
|
}, [roomId]);
|
|
|
|
const handleReset = useCallback(async () => {
|
|
await fetch(`/api/room/${roomId}/reset`, { method: "POST" });
|
|
await mutate();
|
|
}, [roomId, mutate]);
|
|
|
|
const initialIndex = swipeCounts[userId] ?? 0;
|
|
const ready = joined && userId && restaurants.length > 0;
|
|
|
|
if (!ready) {
|
|
return (
|
|
<div className="flex h-dvh flex-col items-center justify-center gap-3 bg-background">
|
|
<div className="h-6 w-6 animate-spin rounded-full border-2 border-zinc-300 border-t-emerald-500" />
|
|
<p className="text-sm text-zinc-400">正在加载餐厅数据...</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="flex h-dvh flex-col bg-background">
|
|
<TopNav roomId={roomId} userCount={userCount} />
|
|
<SwipeDeck
|
|
restaurants={restaurants}
|
|
roomId={roomId}
|
|
userId={userId}
|
|
initialIndex={initialIndex}
|
|
matchedRestaurantId={match}
|
|
matchType={matchType}
|
|
matchLikes={matchLikes}
|
|
likeCounts={likeCounts}
|
|
swipeCounts={swipeCounts}
|
|
userCount={userCount}
|
|
onReset={handleReset}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|