"use client"; import { useState, useEffect } from "react"; import { useSession } from "next-auth/react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { BrandFormDialog, AddBrandButton, } from "@/components/brand/BrandFormDialog"; import { api } from "@/lib/api"; import { PLATFORM_MAP } from "@/lib/platforms"; import { useNotificationStore, useBrandStore } from "@/lib/stores"; import type { BrandListItem, BrandListResponse } from "@/types/brand"; import { Search, Star, Calendar, Edit, Trash2 } from "lucide-react"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { useApi } from "@/lib/hooks/use-api"; import { LoadingState, ErrorState, EmptyState } from "@/components/ui/api-states"; export default function BrandsPage() { const { data: session } = useSession(); const router = useRouter(); const [deleteBrand, setDeleteBrand] = useState(null); const [deleting, setDeleting] = useState(false); const { data: brandsResponse, isLoading: loading, error: apiError, refresh: fetchBrands } = useApi("/api/v1/brands/"); const brands: BrandListItem[] = brandsResponse?.items ?? []; const error = apiError?.message ?? null; // 同步 SWR 数据到 brand-store const syncFromSWR = useBrandStore((s) => s.syncFromSWR); useEffect(() => { if (brands.length > 0) { syncFromSWR(brands); } }, [brands, syncFromSWR]); const addNotification = useNotificationStore((s) => s.addNotification); const optimisticDelete = useBrandStore((s) => s.optimisticDelete); const handleDelete = async () => { if (!deleteBrand || !session?.accessToken) return; try { setDeleting(true); const success = await optimisticDelete( session.accessToken, deleteBrand.id, fetchBrands ); if (success) { setDeleteBrand(null); } } catch (err) { addNotification({ type: "error", message: err instanceof Error ? err.message : "删除失败", }); } finally { setDeleting(false); } }; const formatDate = (dateString: string | null) => { if (!dateString) return "暂无"; const date = new Date(dateString); return date.toLocaleDateString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", }); }; const getFrequencyLabel = (frequency: string) => { const labels: Record = { daily: "每日", weekly: "每周", monthly: "每月", }; return labels[frequency] || frequency; }; const getStatusBadge = (status: string) => { switch (status) { case "active": return 活跃; case "inactive": return 停用; case "pending": return 待处理; default: return {status}; } }; if (loading) { return (

品牌管理

管理您的品牌监控列表

); } if (error) { return (

品牌管理

管理您的品牌监控列表

); } if (brands.length === 0) { return (

品牌管理

管理您的品牌监控列表

} message="暂无品牌" description="添加您的第一个品牌,开始监控其在AI搜索中的表现" action={} />
); } return (

品牌管理

管理您的品牌监控列表

{brands.map((brand) => ( router.push(`/brands/${brand.id}`)} > {brand.name} {getStatusBadge(brand.status)}
{/* 评分 */}
{brand.score ?? "-"} {brand.score !== null && ( )}
{/* 平台 */}
{brand.platforms.map((platform) => ( {PLATFORM_MAP[platform] || platform} ))}
{/* 查询频率 */}
{getFrequencyLabel(brand.frequency)}查询
{/* 上次查询 */}
上次查询: {formatDate(brand.last_queried_at)}
{/* 操作按钮 */}
e.stopPropagation()} > } />
))}
{/* 删除确认对话框 */} setDeleteBrand(null)}> 确认删除 确定要删除品牌 “{deleteBrand?.name}” 吗?此操作不可恢复, 所有相关的引用记录也将被删除。
); }