/** * 進貨單列表表格 */ import { useState, useMemo } from "react"; import { ArrowUpDown, ArrowUp, ArrowDown } from "lucide-react"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/Components/ui/table"; import GoodsReceiptActions, { GoodsReceipt } from "./GoodsReceiptActions"; import GoodsReceiptStatusBadge from "./GoodsReceiptStatusBadge"; import CopyButton from "@/Components/shared/CopyButton"; import { formatCurrency, formatDate } from "@/utils/format"; interface GoodsReceiptTableProps { receipts: GoodsReceipt[]; } type SortField = "code" | "type" | "warehouse_name" | "vendor_name" | "received_date" | "total_amount" | "status"; type SortDirection = "asc" | "desc" | null; export default function GoodsReceiptTable({ receipts, }: GoodsReceiptTableProps) { const [sortField, setSortField] = useState(null); const [sortDirection, setSortDirection] = useState(null); // 處理排序 const handleSort = (field: SortField) => { if (sortField === field) { if (sortDirection === "asc") { setSortDirection("desc"); } else if (sortDirection === "desc") { setSortDirection(null); setSortField(null); } else { setSortDirection("asc"); } } else { setSortField(field); setSortDirection("asc"); } }; // 類型翻譯映射 const typeMap: Record = { standard: "標準採購", miscellaneous: "雜項入庫", other: "其他入庫", }; // 排序後的進貨單列表 const sortedReceipts = useMemo(() => { if (!sortField || !sortDirection) { return receipts; } return [...receipts].sort((a, b) => { let aValue: string | number; let bValue: string | number; switch (sortField) { case "code": aValue = a.code; bValue = b.code; break; case "type": aValue = typeMap[a.status] || a.status; // status here might actually refer to type in existing code logic? Let's use a.type if it exists. // Checking if 'type' is in receipt - based on implementation plan we want it. // Currently GoodsReceipt model HAS type. // @ts-ignore aValue = typeMap[a.type] || a.type || ""; // @ts-ignore bValue = typeMap[b.type] || b.type || ""; break; case "warehouse_name": aValue = a.warehouse?.name || ""; bValue = b.warehouse?.name || ""; break; case "vendor_name": aValue = a.vendor?.name || ""; bValue = b.vendor?.name || ""; break; case "received_date": aValue = a.received_date; bValue = b.received_date; break; case "total_amount": aValue = a.items_sum_total_amount || 0; bValue = b.items_sum_total_amount || 0; break; case "status": aValue = a.status; bValue = b.status; break; default: return 0; } if (typeof aValue === "string" && typeof bValue === "string") { return sortDirection === "asc" ? aValue.localeCompare(bValue, "zh-TW") : bValue.localeCompare(aValue, "zh-TW"); } else { return sortDirection === "asc" ? (aValue as number) - (bValue as number) : (bValue as number) - (aValue as number); } }); }, [receipts, sortField, sortDirection]); const SortIcon = ({ field }: { field: SortField }) => { if (sortField !== field) { return ; } if (sortDirection === "asc") { return ; } if (sortDirection === "desc") { return ; } return ; }; return (
# 操作 {sortedReceipts.length === 0 ? ( 尚無進貨單 ) : ( sortedReceipts.map((receipt, index) => ( {index + 1}
{receipt.code}
{/* @ts-ignore */} {typeMap[receipt.type] || receipt.type || "-"}
{receipt.warehouse?.name || "-"}
{receipt.vendor?.name || "-"} {formatDate(receipt.received_date)} {formatCurrency(receipt.items_sum_total_amount)}
)) )}
); }