UI-UX/src/components/auth/RemainingVotesBadge.tsx
iye 10878ddb3f
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
feat(vote): 重构投票模型为终身 12 票 + 每艺人 1 票
前端:
- store 改为 votedArtists[] + zustand persist
- VoteModal 删除 1/3/5/ALL 选择器,改三态(待投/已投/满额)
- 卡片/排行/详情页加 hasVoted 状态 + ✓ 角标
- Hero 右上角 Countdown 替换为 HeroVoteProgress(12 格点亮进度)
- /me 改为终身额度叙事(QuotaCard / StatsGrid / MyFanSupport)

后端:
- votes 表加 @@unique([userId, artistId])(已 apply 到生产 RDS)
- /api/vote 重写:12 票上限 + P2002 ALREADY_VOTED + P2003 NOT_FOUND 兜底
- /api/me 新增 votedArtists[] + voteQuota,移除 dailyQuota
- 新增 ERR.ALREADY_VOTED 错误码

测试:
- DB 层 5/5 + E2E 18/18 通过(scripts/e2e-vote-flow.sh)
- 修复 P2003 FK 违反未识别的 bug

详情见 docs/todo/voting-refactor-完成报告.md 与 voting-refactor-backend-完成报告.md

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 20:14:57 +08:00

37 lines
1.2 KiB
TypeScript

"use client";
import { useSession } from "next-auth/react";
import { useVoteStore, selectRemaining, TOTAL_VOTE_QUOTA } from "@/lib/store";
/**
* 导航栏的"剩余票数"徽章。
* - 始终显示(位于 AuthMenu 左侧)
* - 未登录:数值固定为 0
* - 已登录:实时从 vote store 取剩余票
* - 视觉为中性轻盈胶囊,与 AuthMenu 的紫色实心胶囊明显区分(信息 vs 操作)
*/
export default function RemainingVotesBadge() {
const { status } = useSession();
const storeRemaining = useVoteStore(selectRemaining);
const authed = status === "authenticated";
// 未登录显示 0 / 12 引导登录后投票;登录后实时剩余
const remaining = authed ? storeRemaining : 0;
return (
<div
className="hidden md:inline-flex items-center gap-1.5 h-9 px-4 rounded-full bg-white/[0.04] border border-white/10"
aria-label={`剩余 ${remaining}`}
>
<span className="text-[11px] text-white/75 leading-none tracking-wide">
</span>
<span className="font-display text-sm text-purple-300 tabular-nums leading-none">
{remaining}
</span>
<span className="text-[11px] text-white/45 leading-none">
/ {TOTAL_VOTE_QUOTA}
</span>
</div>
);
}