/** * 庫存表格元件 (扁平化列表版) * 顯示庫存項目列表,不進行折疊分組 */ import { useState, useMemo } from "react"; import { AlertTriangle, Trash2, Eye, CheckCircle, Package, ArrowUpDown, ArrowUp, ArrowDown } from "lucide-react"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/Components/ui/table"; import { Button } from "@/Components/ui/button"; import { Badge } from "@/Components/ui/badge"; import { WarehouseInventory } from "@/types/warehouse"; import { getSafetyStockStatus } from "@/utils/inventory"; import { formatDate } from "@/utils/format"; import { Can } from "@/Components/Permission/Can"; interface InventoryTableProps { inventories: WarehouseInventory[]; onView: (id: string) => void; onDelete: (id: string) => void; } type SortField = "productName" | "quantity" | "lastInboundDate" | "lastOutboundDate" | "safetyStock" | "status"; type SortDirection = "asc" | "desc" | null; export default function InventoryTable({ inventories, onView, onDelete, }: InventoryTableProps) { const [sortField, setSortField] = useState("status"); const [sortDirection, setSortDirection] = useState("asc"); // "asc" for status means Priority High (Low Stock) first // 處理排序 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 sortedInventories = useMemo(() => { if (!sortField || !sortDirection) { return inventories; } return [...inventories].sort((a, b) => { let aValue: string | number; let bValue: string | number; // Status Priority map for sorting: Low > Near > Normal const statusPriority: Record = { "低於": 1, "接近": 2, "正常": 3 }; switch (sortField) { case "productName": aValue = a.productName; bValue = b.productName; break; case "quantity": aValue = a.quantity; bValue = b.quantity; break; case "lastInboundDate": aValue = a.lastInboundDate || ""; bValue = b.lastInboundDate || ""; break; case "lastOutboundDate": aValue = a.lastOutboundDate || ""; bValue = b.lastOutboundDate || ""; break; case "safetyStock": aValue = a.safetyStock ?? -1; // null as -1 or Infinity depending on desired order bValue = b.safetyStock ?? -1; break; case "status": const aStatus = (a.safetyStock !== null && a.safetyStock !== undefined) ? getSafetyStockStatus(a.quantity, a.safetyStock) : "正常"; const bStatus = (b.safetyStock !== null && b.safetyStock !== undefined) ? getSafetyStockStatus(b.quantity, b.safetyStock) : "正常"; aValue = statusPriority[aStatus] || 3; bValue = statusPriority[bStatus] || 3; 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); } }); }, [inventories, sortField, sortDirection]); const SortIcon = ({ field }: { field: SortField }) => { if (sortField !== field) { return ; } if (sortDirection === "asc") { return ; } if (sortDirection === "desc") { return ; } return ; }; if (inventories.length === 0) { return (

無符合條件的品項

請調整搜尋或篩選條件

); } // 獲取狀態徽章 const getStatusBadge = (quantity: number, safetyStock: number) => { const status = getSafetyStockStatus(quantity, safetyStock); switch (status) { case "正常": return ( 正常 ); case "接近": // 數量 <= 安全庫存 * 1.2 return ( 接近 ); case "低於": // 數量 < 安全庫存 return ( 低於 ); default: return null; } }; return (
#
操作
{sortedInventories.map((item, index) => ( {index + 1} {/* 商品資訊 */}
{item.productName}
{item.productCode}
{/* 庫存數量 */} {item.quantity} {item.unit} {/* 最新入庫 */} {item.lastInboundDate ? formatDate(item.lastInboundDate) : "-"} {/* 最新出庫 */} {item.lastOutboundDate ? formatDate(item.lastOutboundDate) : "-"} {/* 安全庫存 */} {item.safetyStock !== null && item.safetyStock >= 0 ? ( {item.safetyStock} {item.unit} ) : ( 未設定 )} {/* 狀態 */} {(item.safetyStock !== null && item.safetyStock !== undefined) ? getStatusBadge(item.quantity, item.safetyStock) : ( 正常 )} {/* 操作 */}
))}
); }