import { AppstoreOutlined, CheckCircleOutlined, ClockCircleOutlined, CloseCircleOutlined, PlusOutlined, } from "@ant-design/icons"; import { Button, Empty, Segmented, Skeleton } from "antd"; import { useMemo, useState } from "react"; import type { Material } from "../types"; import { MaterialCard } from "./MaterialCard"; import { MaterialGroup } from "./MaterialGroup"; type DateGroup = "earlier" | "thisMonth" | "thisWeek" | "today" | "yesterday"; interface MaterialListProps { loading: boolean; materials: readonly Material[]; onAddClick: () => void; onDelete: (id: string) => void; onSelect: (id: string) => void; selectedId: null | string; } const GROUP_LABELS: Record = { earlier: "更早", thisMonth: "本月", thisWeek: "本周", today: "今天", yesterday: "昨天", }; const GROUP_ORDER: readonly DateGroup[] = ["today", "yesterday", "thisWeek", "thisMonth", "earlier"]; interface MaterialGroupData { items: Material[]; key: DateGroup; } function getDateGroup(dateStr: string, now: Date): DateGroup { const date = new Date(dateStr); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const yesterday = new Date(today.getTime() - 86_400_000); const dateDay = new Date(date.getFullYear(), date.getMonth(), date.getDate()); if (dateDay.getTime() >= today.getTime()) return "today"; if (dateDay.getTime() >= yesterday.getTime()) return "yesterday"; const dayOfWeek = today.getDay(); const mondayOffset = dayOfWeek === 0 ? 6 : dayOfWeek - 1; const monday = new Date(today.getTime() - mondayOffset * 86_400_000); if (dateDay.getTime() >= monday.getTime()) return "thisWeek"; if (dateDay.getFullYear() === today.getFullYear() && dateDay.getMonth() === today.getMonth()) { return "thisMonth"; } return "earlier"; } function groupMaterialsByDate(materials: readonly Material[]): MaterialGroupData[] { const now = new Date(); const groups = new Map(); for (const m of materials) { const group = getDateGroup(m.createdAt, now); if (!groups.has(group)) groups.set(group, []); groups.get(group)!.push(m); } return GROUP_ORDER.map((key) => ({ items: groups.get(key) ?? [], key })); } const STATUS_FILTER_OPTIONS = [ { icon: , label: "全部", value: "all" }, { color: "#faad14", icon: , label: "待审核", value: "pending" }, { color: "#52c41a", icon: , label: "已通过", value: "approved" }, { color: "#ff4d4f", icon: , label: "已放弃", value: "discarded" }, ] as const; type FilterValue = (typeof STATUS_FILTER_OPTIONS)[number]["value"]; export function MaterialList({ loading, materials, onAddClick, onDelete, onSelect, selectedId }: MaterialListProps) { const [filterStatus, setFilterStatus] = useState("all"); const filteredMaterials = useMemo(() => { if (filterStatus === "all") return materials; return materials.filter((m) => m.status === filterStatus); }, [materials, filterStatus]); const groupedMaterials = useMemo(() => groupMaterialsByDate(filteredMaterials), [filteredMaterials]); const segmentedOptions = useMemo( () => STATUS_FILTER_OPTIONS.map((opt) => ({ label: ( {"color" in opt && opt.color ? {opt.icon} : opt.icon} {getStatusCount(materials, opt.value)} ), value: opt.value, })), [materials], ); const showAllGroups = filterStatus === "all"; return (
setFilterStatus(value)} options={segmentedOptions} value={filterStatus} />
{loading ? ( ) : materials.length === 0 ? ( ) : filteredMaterials.length === 0 ? ( ) : ( groupedMaterials.map((group) => { if (!showAllGroups && group.items.length === 0) return null; return ( {group.items.map((material) => ( onDelete(material.id)} onSelect={() => onSelect(material.id)} selected={material.id === selectedId} /> ))} ); }) )}
); } function getStatusCount(materials: readonly Material[], status: string): number { if (status === "all") return materials.length; return materials.filter((m) => m.status === status).length; }