import { Badge } from "@workspace/ui/components/badge"; import { Sheet, SheetContent, SheetHeader, SheetTitle, } from "@workspace/ui/components/sheet"; import { Tabs, TabsContent, TabsList, TabsTrigger, } from "@workspace/ui/components/tabs"; import { getLotteryActivityDetail } from "@workspace/ui/services/admin/lottery"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import PrizeGrid from "./prize-grid"; import RuleEditor from "./rule-editor"; interface ActivityDetailProps { activity: API.LotteryActivity | null; open: boolean; onOpenChange: (open: boolean) => void; onChanged?: () => void; } type TranslateFn = (key: string, defaultValue: string) => string; const STATUS_BADGE_VARIANTS: Record< API.LotteryActivityStatus, "default" | "secondary" | "destructive" | "outline" > = { draft: "secondary", running: "default", paused: "outline", ended: "destructive", }; function statusLabel( status: API.LotteryActivityStatus, t: TranslateFn ): string { const labels: Record = { draft: t("status.draft", "Draft"), running: t("status.running", "Running"), paused: t("status.paused", "Paused"), ended: t("status.ended", "Ended"), }; return labels[status] ?? status; } export default function ActivityDetail({ activity, open, onOpenChange, onChanged, }: ActivityDetailProps) { const { t } = useTranslation("lottery"); // 抽屉打开时拉取详情作为数据源,避免列表行数据不完整时被全量 PUT 覆盖 const [detail, setDetail] = useState(null); const activityId = activity?.id; useEffect(() => { setDetail(null); if (!(open && activityId)) return; let cancelled = false; getLotteryActivityDetail({ id: activityId }) .then(({ data }) => { if (!cancelled && data.data) setDetail(data.data); }) .catch(() => { // Request layer already surfaces the error toast; fall back to prop data }); return () => { cancelled = true; }; }, [open, activityId]); const current = detail ?? activity; return ( {current && ( <> {current.title} {statusLabel(current.status, t)}
{t("detail.prizesTab", "Prizes")} {t("detail.rulesTab", "Rules")}
)}
); }