"use client" import { useState } from "react" import Link from "next/link" import { useRouter } from "next/navigation" import { toast } from "sonner" import { useTranslations } from "next-intl" import { Pin } from "lucide-react" import { Badge } from "@/shared/components/ui/badge" import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card" import { cn, formatDate } from "@/shared/lib/utils" import { toggleAnnouncementPinAction } from "../actions" import type { Announcement } from "../types" export function AnnouncementCard({ announcement, href, canManage, }: { announcement: Announcement href?: string canManage?: boolean }) { const t = useTranslations("announcements") const router = useRouter() const [isPinned, setIsPinned] = useState(announcement.isPinned) const [isToggling, setIsToggling] = useState(false) const handleTogglePin = async (e: React.MouseEvent) => { e.preventDefault() e.stopPropagation() setIsToggling(true) const prevPinned = isPinned // 乐观更新 setIsPinned(!prevPinned) try { const res = await toggleAnnouncementPinAction(announcement.id) if (res.success) { toast.success(t("messages.pinToggled")) router.refresh() } else { // 回滚 setIsPinned(prevPinned) toast.error(res.message) } } catch { // 回滚 setIsPinned(prevPinned) toast.error(t("messages.publishFailed")) } finally { setIsToggling(false) } } const statusVariant: Record = { draft: "secondary", published: "default", archived: "outline", } const card = ( {isPinned ? (
{isPinned ? ( {t("status.pinned")} ) : null} {t(`status.${announcement.status}`)} {canManage ? ( ) : null}

{announcement.content}

{t(`type.${announcement.type}`)} {announcement.publishedAt ? t("meta.publishedAt", { date: formatDate(announcement.publishedAt) }) : t("meta.updatedAt", { date: formatDate(announcement.updatedAt) })} {announcement.authorName ? ( {t("meta.author", { name: announcement.authorName })} ) : null}
) if (href) { return ( {card} ) } return card }