1. 倉庫管理:新增業務類型 (Owned/External/Customer) 與車牌資訊與司機欄位。 2. 庫存管理:實作成本追蹤 (unit_cost, total_value),更新列表與撥補單顯示。 3. 採購單:新增採購日期 (order_date),調整欄位名稱與順序。 4. 前端優化:更新相關 TS Type 定義與 UI 顯示。
174 lines
10 KiB
TypeScript
174 lines
10 KiB
TypeScript
/**
|
||
* 查看採購單詳情頁面
|
||
*/
|
||
|
||
import { ArrowLeft, ShoppingCart } from "lucide-react";
|
||
import { Button } from "@/Components/ui/button";
|
||
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
|
||
import { Head, Link } from "@inertiajs/react";
|
||
import { StatusProgressBar } from "@/Components/PurchaseOrder/StatusProgressBar";
|
||
import PurchaseOrderStatusBadge from "@/Components/PurchaseOrder/PurchaseOrderStatusBadge";
|
||
import CopyButton from "@/Components/shared/CopyButton";
|
||
import { PurchaseOrderItemsTable } from "@/Components/PurchaseOrder/PurchaseOrderItemsTable";
|
||
import type { PurchaseOrder } from "@/types/purchase-order";
|
||
import { formatCurrency, formatDateTime } from "@/utils/format";
|
||
import { getShowBreadcrumbs } from "@/utils/breadcrumb";
|
||
|
||
interface Props {
|
||
order: PurchaseOrder;
|
||
}
|
||
|
||
export default function ViewPurchaseOrderPage({ order }: Props) {
|
||
return (
|
||
<AuthenticatedLayout breadcrumbs={getShowBreadcrumbs("purchaseOrders", `詳情 (#${order.poNumber})`)}>
|
||
<Head title={`採購單詳情 - ${order.poNumber}`} />
|
||
<div className="container mx-auto p-6 max-w-7xl">
|
||
{/* Header */}
|
||
<div className="mb-6">
|
||
<Link href="/purchase-orders">
|
||
<Button
|
||
variant="outline"
|
||
className="gap-2 button-outlined-primary mb-6"
|
||
>
|
||
<ArrowLeft className="h-4 w-4" />
|
||
返回採購單列表
|
||
</Button>
|
||
</Link>
|
||
|
||
<div className="flex items-center justify-between mb-6">
|
||
<div>
|
||
<h1 className="text-2xl font-bold text-grey-0 flex items-center gap-2">
|
||
<ShoppingCart className="h-6 w-6 text-primary-main" />
|
||
查看採購單
|
||
</h1>
|
||
<p className="text-gray-500 mt-1">單號:{order.poNumber}</p>
|
||
</div>
|
||
<div className="flex items-center gap-3">
|
||
<Link href={`/purchase-orders/${order.id}/edit`}>
|
||
<Button variant="outline" className="button-outlined-primary">
|
||
編輯採購單
|
||
</Button>
|
||
</Link>
|
||
<PurchaseOrderStatusBadge status={order.status} />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{/* 狀態流程條 */}
|
||
<div className="mb-8">
|
||
<StatusProgressBar currentStatus={order.status} />
|
||
</div>
|
||
|
||
<div className="space-y-8">
|
||
{/* 基本資訊與品項 */}
|
||
<div className="space-y-8">
|
||
|
||
|
||
{/* 基本資訊卡片 */}
|
||
<div className="bg-white rounded-lg border shadow-sm p-6">
|
||
<h2 className="text-lg font-bold text-gray-900 mb-6">基本資訊</h2>
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-6">
|
||
<div>
|
||
<span className="text-sm text-gray-500 block mb-1">採購單編號</span>
|
||
<div className="flex items-center gap-1.5">
|
||
<span className="font-mono font-medium text-gray-900">{order.poNumber}</span>
|
||
<CopyButton text={order.poNumber} label="複製單號" />
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<span className="text-sm text-gray-500 block mb-1">供應商</span>
|
||
<span className="font-medium text-gray-900">{order.supplierName}</span>
|
||
</div>
|
||
<div>
|
||
<span className="text-sm text-gray-500 block mb-1">申請單位 (申請人)</span>
|
||
<span className="font-medium text-gray-900">
|
||
{order.warehouse_name} ({order.createdBy})
|
||
</span>
|
||
</div>
|
||
<div>
|
||
<span className="text-sm text-gray-500 block mb-1">建立日期</span>
|
||
<span className="font-medium text-gray-900">{formatDateTime(order.createdAt)}</span>
|
||
</div>
|
||
<div>
|
||
<span className="text-sm text-gray-500 block mb-1">採購日期</span>
|
||
<span className="font-medium text-gray-900">{order.orderDate || "-"}</span>
|
||
</div>
|
||
<div>
|
||
<span className="text-sm text-gray-500 block mb-1">預計到貨日期</span>
|
||
<span className="font-medium text-gray-900">{order.expectedDate || "-"}</span>
|
||
</div>
|
||
</div>
|
||
{order.remark && (
|
||
<div className="mt-8 pt-6 border-t border-gray-100">
|
||
<span className="text-sm text-gray-500 block mb-2">備註</span>
|
||
<p className="text-sm text-gray-700 bg-gray-50 p-4 rounded-lg leading-relaxed">
|
||
{order.remark}
|
||
</p>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{/* 發票資訊卡片 */}
|
||
{(order.invoiceNumber || order.invoiceDate || (order.invoiceAmount !== null && order.invoiceAmount !== undefined)) && (
|
||
<div className="bg-white rounded-lg border shadow-sm p-6">
|
||
<h2 className="text-lg font-bold text-gray-900 mb-6">發票資訊</h2>
|
||
<div className="grid grid-cols-1 md:grid-cols-3 gap-x-8 gap-y-6">
|
||
{order.invoiceNumber && (
|
||
<div>
|
||
<span className="text-sm text-gray-500 block mb-1">發票號碼</span>
|
||
<div className="flex items-center gap-1.5">
|
||
<span className="font-mono font-medium text-gray-900">{order.invoiceNumber}</span>
|
||
<CopyButton text={order.invoiceNumber} label="複製發票號碼" />
|
||
</div>
|
||
</div>
|
||
)}
|
||
{order.invoiceDate && (
|
||
<div>
|
||
<span className="text-sm text-gray-500 block mb-1">發票日期</span>
|
||
<span className="font-medium text-gray-900">{order.invoiceDate}</span>
|
||
</div>
|
||
)}
|
||
{order.invoiceAmount !== null && order.invoiceAmount !== undefined && (
|
||
<div>
|
||
<span className="text-sm text-gray-500 block mb-1">發票金額</span>
|
||
<span className="font-medium text-gray-900">{formatCurrency(order.invoiceAmount)}</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* 採購項目卡片 */}
|
||
<div className="bg-white rounded-lg border shadow-sm overflow-hidden">
|
||
<div className="p-6 border-b border-gray-100">
|
||
<h2 className="text-lg font-bold text-gray-900">採購項目清單</h2>
|
||
</div>
|
||
<div className="p-6">
|
||
<PurchaseOrderItemsTable
|
||
items={order.items}
|
||
isReadOnly={true}
|
||
/>
|
||
<div className="mt-4 flex flex-col items-end gap-2 border-t pt-4">
|
||
<div className="flex items-center gap-8 text-gray-600">
|
||
<span className="font-medium">小計</span>
|
||
<span>{formatCurrency(order.totalAmount)}</span>
|
||
</div>
|
||
<div className="flex items-center gap-8 text-gray-600">
|
||
<span className="font-medium">稅額</span>
|
||
<span>{formatCurrency(order.tax_amount || 0)}</span>
|
||
</div>
|
||
<div className="flex items-center gap-8 pt-2 mt-2 border-t border-gray-100">
|
||
<span className="font-bold text-lg">總計</span>
|
||
<span className="text-xl font-bold text-primary">
|
||
{formatCurrency(order.grand_total || (order.totalAmount + (order.tax_amount || 0)))}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</AuthenticatedLayout>
|
||
);
|
||
}
|