import { useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import type { StampWithStatus, RedemptionRuleInfo, RedemptionRecord } from "@stamp/shared"; import { apiFetch } from "../lib/api"; import { useAuth } from "../lib/auth"; import StampGrid from "../components/StampGrid"; import RedeemModal from "../components/RedeemModal"; import RegisterModal from "../components/RegisterModal"; export default function AlbumPage() { const navigate = useNavigate(); const { user, isLoading: authLoading } = useAuth(); const [stamps, setStamps] = useState([]); const [rules, setRules] = useState([]); const [history, setHistory] = useState([]); const [loading, setLoading] = useState(true); const [showRedeem, setShowRedeem] = useState(false); const [showRegister, setShowRegister] = useState(false); const collectedCount = stamps.filter((s) => s.collected).length; const fetchData = async () => { setLoading(true); try { const [stampsData, rulesData] = await Promise.all([ apiFetch("/stamps"), apiFetch("/redemption/rules"), ]); setStamps(stampsData); setRules(rulesData); if (user) { const historyData = await apiFetch("/redemption/history"); setHistory(historyData); } } catch { // Stamps endpoint works without auth } finally { setLoading(false); } }; useEffect(() => { if (!authLoading) fetchData(); }, [authLoading, user]); const handleRedeem = async (ruleId: string) => { await apiFetch("/redemption/redeem", { method: "POST", body: JSON.stringify({ ruleId }), }); await fetchData(); }; const handleRedeemClick = () => { if (!user) { setShowRegister(true); return; } setShowRedeem(true); }; if (loading || authLoading) { return (
); } return (
{/* Header */}

图章集册

{/* Progress */}
收集进度
{collectedCount} / {stamps.length}
{stamps.length > 0 && collectedCount < stamps.length && ( 还差 {stamps.length - collectedCount} 枚集齐 )} {stamps.length > 0 && collectedCount === stamps.length && ( 已集齐全部图章 ✨ )}
{/* Stamp Grid */}
{/* Redeem Section */} {rules.length > 0 && (() => { const availableCount = rules.filter((r) => collectedCount >= r.threshold).length; const canRedeem = availableCount > 0; return (
); })()} {/* Redemption History */} {history.length > 0 && (

兑换记录

{history.map((r) => (

{r.ruleName}

{new Date(r.redeemedAt).toLocaleDateString("zh-CN")}

已兑换
))}
)} {/* Modals */} {showRedeem && ( setShowRedeem(false)} /> )} {showRegister && ( { setShowRegister(false); fetchData(); }} onClose={() => setShowRegister(false)} /> )}
); }