174 lines
10 KiB
TypeScript
174 lines
10 KiB
TypeScript
/**
|
||
* 查看採購單詳情頁面
|
||
*/
|
||
|
||
import { ArrowLeft } 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 type { PurchaseOrder } from "@/types/purchase-order";
|
||
import { formatCurrency, formatDateTime } from "@/utils/format";
|
||
|
||
interface Props {
|
||
order: PurchaseOrder;
|
||
}
|
||
|
||
export default function ViewPurchaseOrderPage({ order }: Props) {
|
||
return (
|
||
<AuthenticatedLayout>
|
||
<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="mb-2">查看採購單</h1>
|
||
<p className="text-gray-600">單號:{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.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>
|
||
|
||
{/* 採購項目卡片 */}
|
||
<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="overflow-x-auto">
|
||
<table className="w-full">
|
||
<thead>
|
||
<tr className="bg-gray-50/50">
|
||
<th className="text-left py-4 px-6 text-xs font-semibold text-gray-500 uppercase tracking-wider w-[50px]">
|
||
#
|
||
</th>
|
||
<th className="text-left py-4 px-6 text-xs font-semibold text-gray-500 uppercase tracking-wider">
|
||
商品名稱
|
||
</th>
|
||
<th className="text-right py-4 px-6 text-xs font-semibold text-gray-500 uppercase tracking-wider">
|
||
單價
|
||
</th>
|
||
<th className="text-right py-4 px-6 text-xs font-semibold text-gray-500 uppercase tracking-wider w-32">
|
||
數量
|
||
</th>
|
||
<th className="text-right py-4 px-6 text-xs font-semibold text-gray-500 uppercase tracking-wider">
|
||
小計
|
||
</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody className="divide-y divide-gray-100">
|
||
{order.items.map((item, index) => (
|
||
<tr key={index} className="hover:bg-gray-50/30 transition-colors">
|
||
<td className="py-4 px-6 text-gray-500 font-medium text-center">
|
||
{index + 1}
|
||
</td>
|
||
<td className="py-4 px-6">
|
||
<div className="flex flex-col">
|
||
<span className="font-medium text-gray-900">{item.productName}</span>
|
||
<span className="text-xs text-gray-400">ID: {item.productId}</span>
|
||
</div>
|
||
</td>
|
||
<td className="py-4 px-6 text-right">
|
||
<div className="flex flex-col items-end">
|
||
<span className="text-gray-900">{formatCurrency(item.unitPrice)}</span>
|
||
</div>
|
||
</td>
|
||
<td className="py-4 px-6 text-right">
|
||
<span className="text-gray-900 font-medium">
|
||
{item.quantity} {item.unit}
|
||
</span>
|
||
</td>
|
||
<td className="py-4 px-6 text-right font-bold text-gray-900">
|
||
{formatCurrency(item.subtotal)}
|
||
</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
<tfoot className="bg-gray-50/50 border-t border-gray-100">
|
||
<tr>
|
||
<td colSpan={4} className="py-5 px-6 text-right font-medium text-gray-600">
|
||
總金額
|
||
</td>
|
||
<td className="py-5 px-6 text-right font-bold text-xl text-primary">
|
||
{formatCurrency(order.totalAmount)}
|
||
</td>
|
||
</tr>
|
||
</tfoot>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</AuthenticatedLayout>
|
||
);
|
||
}
|