Files
star-erp/resources/js/Components/PurchaseOrder/StatusProgressBar.tsx
sky121113 95d8dc2e84
All checks were successful
Koori-ERP-Deploy-System / deploy-demo (push) Successful in 51s
Koori-ERP-Deploy-System / deploy-production (push) Has been skipped
feat: 統一進貨單 UI、修復庫存異動紀錄與廠商詳情顯示報錯
2026-01-27 17:23:31 +08:00

96 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 狀態流程條組件
*/
import { Check } from "lucide-react";
import type { PurchaseOrderStatus } from "@/types/purchase-order";
interface StatusProgressBarProps {
currentStatus: PurchaseOrderStatus;
}
// 流程步驟定義
const FLOW_STEPS: { key: PurchaseOrderStatus; label: string }[] = [
{ key: "draft", label: "草稿" },
{ key: "pending", label: "簽核中" },
{ key: "approved", label: "已核准" },
{ key: "partial", label: "部分收貨" },
{ key: "completed", label: "全數收貨" },
{ key: "closed", label: "已結案" },
];
export function StatusProgressBar({ currentStatus }: StatusProgressBarProps) {
// 對於 cancelled 狀態,進度條通常不顯示或顯示特殊樣式,這裡我們顯示到最後一個有效狀態
const effectiveStatus = currentStatus === "cancelled" ? "pending" : currentStatus;
// 找到當前狀態在流程中的位置
const currentIndex = FLOW_STEPS.findIndex((step) => step.key === effectiveStatus);
return (
<div className="bg-white rounded-lg border shadow-sm p-6">
<h3 className="text-sm font-semibold text-gray-700 mb-6"></h3>
<div className="relative px-4">
{/* 進度條背景 */}
<div className="absolute top-5 left-8 right-8 h-0.5 bg-gray-100" />
{/* 進度條進度 */}
{currentIndex >= 0 && (
<div
className="absolute top-5 left-8 h-0.5 bg-primary transition-all duration-500"
style={{
width: `${(currentIndex / (FLOW_STEPS.length - 1)) * 100}%`,
maxWidth: "calc(100% - 4rem)"
}}
/>
)}
{/* 步驟標記 */}
<div className="relative flex justify-between">
{FLOW_STEPS.map((step, index) => {
const isCompleted = index < currentIndex;
const isCurrent = index === currentIndex;
// 如果當前是 cancelled且我們正在渲染 pending 步驟,可以加點提示
const isRejectedAtThisStep = currentStatus === "cancelled" && step.key === "pending";
return (
<div key={step.key} className="flex flex-col items-center flex-1">
{/* 圓點 */}
<div
className={`w-10 h-10 rounded-full flex items-center justify-center border-2 z-10 transition-all duration-300 ${isRejectedAtThisStep
? "bg-red-500 border-red-500 text-white"
: isCompleted
? "bg-primary border-primary text-white"
: isCurrent
? "bg-white border-primary text-primary ring-4 ring-primary/10 font-bold"
: "bg-white border-gray-200 text-gray-400"
}`}
>
{isCompleted && !isRejectedAtThisStep ? (
<Check className="h-5 w-5" />
) : (
<span className="text-sm">{index + 1}</span>
)}
</div>
{/* 標籤 */}
<div className="mt-3 text-center">
<p
className={`text-xs whitespace-nowrap transition-colors ${isRejectedAtThisStep
? "text-red-600 font-bold"
: isCompleted || isCurrent
? "text-gray-900 font-bold"
: "text-gray-400"
}`}
>
{isRejectedAtThisStep ? "已作廢" : step.label}
</p>
</div>
</div>
);
})}
</div>
</div>
</div>
);
}