2025-12-30 15:03:19 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 查看採購單詳情頁面
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2026-01-13 17:00:58 +08:00
|
|
|
|
import { ArrowLeft, ShoppingCart } from "lucide-react";
|
2025-12-30 15:03:19 +08:00
|
|
|
|
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";
|
2026-01-08 16:32:10 +08:00
|
|
|
|
import { PurchaseOrderItemsTable } from "@/Components/PurchaseOrder/PurchaseOrderItemsTable";
|
2025-12-30 15:03:19 +08:00
|
|
|
|
import type { PurchaseOrder } from "@/types/purchase-order";
|
|
|
|
|
|
import { formatCurrency, formatDateTime } from "@/utils/format";
|
2026-01-07 13:06:49 +08:00
|
|
|
|
import { getShowBreadcrumbs } from "@/utils/breadcrumb";
|
2025-12-30 15:03:19 +08:00
|
|
|
|
|
|
|
|
|
|
interface Props {
|
|
|
|
|
|
order: PurchaseOrder;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export default function ViewPurchaseOrderPage({ order }: Props) {
|
|
|
|
|
|
return (
|
2026-01-07 13:06:49 +08:00
|
|
|
|
<AuthenticatedLayout breadcrumbs={getShowBreadcrumbs("purchaseOrders", `詳情 (#${order.poNumber})`)}>
|
2025-12-30 15:03:19 +08:00
|
|
|
|
<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>
|
2026-01-13 17:00:58 +08:00
|
|
|
|
<h1 className="text-2xl font-bold text-grey-0 flex items-center gap-2">
|
|
|
|
|
|
<ShoppingCart className="h-6 w-6 text-[#01ab83]" />
|
|
|
|
|
|
查看採購單
|
|
|
|
|
|
</h1>
|
|
|
|
|
|
<p className="text-gray-500 mt-1">單號:{order.poNumber}</p>
|
2025-12-30 15:03:19 +08:00
|
|
|
|
</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>
|
|
|
|
|
|
|
2026-01-09 10:18:52 +08:00
|
|
|
|
{/* 發票資訊卡片 */}
|
|
|
|
|
|
{(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>
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
2025-12-30 15:03:19 +08:00
|
|
|
|
{/* 採購項目卡片 */}
|
|
|
|
|
|
<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>
|
2026-01-08 16:32:10 +08:00
|
|
|
|
<div className="p-6">
|
|
|
|
|
|
<PurchaseOrderItemsTable
|
|
|
|
|
|
items={order.items}
|
|
|
|
|
|
isReadOnly={true}
|
|
|
|
|
|
/>
|
|
|
|
|
|
<div className="mt-4 flex justify-end items-center gap-4 border-t pt-4">
|
|
|
|
|
|
<span className="text-gray-600 font-medium">總金額</span>
|
|
|
|
|
|
<span className="text-xl font-bold text-primary">
|
|
|
|
|
|
{formatCurrency(order.totalAmount)}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
2025-12-30 15:03:19 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</AuthenticatedLayout>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|