"use client"; import { useMemo, useState, type FormEvent } from "react"; import { useApiList } from "@/hooks/use-api-list"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; // Shape returned by GET /api/assets — snake_case per this repo's // API-boundary convention (see src/lib/assets.ts's toRecord()). interface AssetItemRecord { id: string; serial_number: string; asset_tag: string | null; model_id: string; purchase_date: string | null; warranty_end_date: string | null; status: "in_stock" | "assigned" | "repair" | "retired" | "lost"; cost: number | null; cost_currency: string | null; purchase_order_id: string | null; external_po_number: string | null; created_at: string; } // Shape returned by GET /api/asset-models — only the fields used to populate // the modelId here. interface AssetCategoryRecord { id: string; name: string; } // Shape returned by GET /api/purchase-orders — only the id, used to populate // the purchaseOrderId setSearchText(event.target.value)} placeholder="e.g. DANLAP001" className="w-64" />

{filteredAssetItems.length} / {assetItems.length} assets

{loading ? (

Loading...

) : error ? (

{error}

) : ( # Serial Number Asset Tag Model Purchase Date Warranty End Date Status Cost Purchase Order ID External PO Number Created At {filteredAssetItems.map((assetItem, index) => ( {index + 1} {assetItem.serial_number} {assetItem.asset_tag ?? "-"} {modelNameById.get(assetItem.model_id) ?? assetItem.model_id} {assetItem.purchase_date ?? "-"} {assetItem.warranty_end_date ?? "-"} {assetItem.status} {assetItem.cost !== null ? `${assetItem.cost}${assetItem.cost_currency ? " " + assetItem.cost_currency : ""}` : "-"} {assetItem.purchase_order_id ?? "-"} {assetItem.external_po_number ?? "-"} {assetItem.created_at} ))}
)}

Import / Export CSV

Cột nhận diện theo tên (không phân biệt hoa/thường): serial number,{" "} manufacturer, model (phải khớp Asset Model đã có sẵn ở{" "} /asset-models ), purchase date (không bắt buộc -- cũng nhận order received). Tuỳ chọn: asset tag, warranty end date (bỏ trống thì tự tính từ warranty của model), status/state (nhận{" "} In use → assigned, In stock → in_stock, bỏ trống thì mặc định in_stock), cost, cost currency,{" "} po number (text tự do, khác purchase order id là UUID trong hệ thống). Dòng có asset tag hoặc serial number đã tồn tại sẽ{" "} cập nhật thay vì báo lỗi trùng -- import lại file mới để đồng bộ dữ liệu.

{importMessage ? (

{importMessage}

) : null}

New Asset

setSerialNumber(event.target.value)} required />
setAssetTag(event.target.value)} />
setPurchaseDate(event.target.value)} required />
setWarrantyEndDate(event.target.value)} />
setCost(event.target.value)} />
setCostCurrency(event.target.value)} placeholder="e.g. VND, USD" />
setExternalPoNumber(event.target.value)} placeholder="PO number from an external system, if any" />
{submitError ?

{submitError}

: null}
); }