feat: 修正 BOM 單位顯示與完工入庫彈窗 UI 統一規範
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* 生產工單狀態流程條組件
|
||||
*/
|
||||
|
||||
import { Check } from "lucide-react";
|
||||
import { ProductionOrderStatus, PRODUCTION_ORDER_STATUS } from "@/constants/production-order";
|
||||
|
||||
interface ProductionStatusProgressBarProps {
|
||||
currentStatus: ProductionOrderStatus;
|
||||
}
|
||||
|
||||
// 流程步驟定義
|
||||
const FLOW_STEPS: { key: ProductionOrderStatus; label: string }[] = [
|
||||
{ key: PRODUCTION_ORDER_STATUS.DRAFT, label: "草稿" },
|
||||
{ key: PRODUCTION_ORDER_STATUS.PENDING, label: "簽核中" },
|
||||
{ key: PRODUCTION_ORDER_STATUS.APPROVED, label: "已核准" },
|
||||
{ key: PRODUCTION_ORDER_STATUS.IN_PROGRESS, label: "製作中" },
|
||||
{ key: PRODUCTION_ORDER_STATUS.COMPLETED, label: "製作完成" },
|
||||
];
|
||||
|
||||
export function ProductionStatusProgressBar({ currentStatus }: ProductionStatusProgressBarProps) {
|
||||
// 對於已作廢狀態,我們顯示到它作廢前的最後一個有效狀態(通常顯示到核准後或簽核中)
|
||||
// 這裡我們比照採購單邏輯,如果已作廢,可能停在最後一個有效位置
|
||||
const effectiveStatus = currentStatus === PRODUCTION_ORDER_STATUS.CANCELLED ? PRODUCTION_ORDER_STATUS.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;
|
||||
const isRejectedAtThisStep = currentStatus === PRODUCTION_ORDER_STATUS.CANCELLED && step.key === PRODUCTION_ORDER_STATUS.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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user