Files
star-erp/resources/js/Pages/Production/Recipe/Components/RecipeDetailModal.tsx
sky121113 4fa87925a2
All checks were successful
Koori-ERP-Deploy-System / deploy-demo (push) Has been skipped
Koori-ERP-Deploy-System / deploy-production (push) Successful in 1m8s
UI優化: 全系統狀態標籤 (StatusBadge) 統一化重構完成 (Phase 3 & 4)
2026-02-13 13:16:05 +08:00

167 lines
9.6 KiB
TypeScript

import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from "@/Components/ui/dialog";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/Components/ui/table";
import { StatusBadge } from "@/Components/shared/StatusBadge";
import { Loader2, Package, Calendar, Clock, BookOpen } from "lucide-react";
interface RecipeDetailModalProps {
isOpen: boolean;
onClose: () => void;
recipe: any | null; // Detailed recipe object with items
isLoading?: boolean;
}
export function RecipeDetailModal({ isOpen, onClose, recipe, isLoading }: RecipeDetailModalProps) {
if (!isOpen) return null;
return (
<Dialog open={isOpen} onOpenChange={onClose}>
<DialogContent className="max-w-3xl max-h-[90vh] overflow-y-auto p-0 gap-0">
<DialogHeader className="p-6 pb-4 border-b pr-12">
<div className="flex items-center gap-3 mb-2">
<DialogTitle className="text-xl font-bold text-gray-900">
</DialogTitle>
{recipe && (
<StatusBadge variant={recipe.is_active ? "success" : "neutral"} className="text-xs font-normal">
{recipe.is_active ? "啟用中" : "已停用"}
</StatusBadge>
)}
</div>
{/* 現代化元數據條 */}
{recipe && (
<div className="flex flex-wrap items-center gap-6 pt-2 text-sm text-gray-500">
<div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-gray-400" />
<span className="font-medium text-gray-700">{recipe.code}</span>
</div>
<div className="flex items-center gap-2">
<Calendar className="w-4 h-4 text-gray-400" />
<span> {new Date(recipe.created_at).toLocaleDateString()}</span>
</div>
<div className="flex items-center gap-2">
<Clock className="w-4 h-4 text-gray-400" />
<span> {new Date(recipe.updated_at).toLocaleDateString()}</span>
</div>
</div>
)}
</DialogHeader>
<div className="bg-gray-50/50 p-6 min-h-[300px]">
{isLoading ? (
<div className="flex justify-center items-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-primary-main" />
</div>
) : recipe ? (
<div className="space-y-6">
{/* 基本資訊區塊 */}
<div className="border rounded-md overflow-hidden bg-white shadow-sm">
<Table>
<TableHeader>
<TableRow className="bg-gray-50/50 hover:bg-gray-50/50">
<TableHead className="w-[150px]"></TableHead>
<TableHead></TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="font-medium text-gray-700"></TableCell>
<TableCell className="text-gray-900 font-medium">{recipe.name}</TableCell>
</TableRow>
<TableRow>
<TableCell className="font-medium text-gray-700"></TableCell>
<TableCell className="text-gray-900 font-medium">
<div className="flex items-center gap-2">
<span>{recipe.product?.name || '-'}</span>
<span className="text-gray-400 text-xs bg-gray-100 px-1.5 py-0.5 rounded">{recipe.product?.code}</span>
</div>
</TableCell>
</TableRow>
<TableRow>
<TableCell className="font-medium text-gray-700"></TableCell>
<TableCell className="text-gray-900 font-medium">
{Number(recipe.yield_quantity).toLocaleString()} {recipe.product?.base_unit?.name || '份'}
</TableCell>
</TableRow>
{recipe.description && (
<TableRow>
<TableCell className="font-medium text-gray-700 align-top pt-3"></TableCell>
<TableCell className="text-gray-600 leading-relaxed py-3">
{recipe.description}
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
{/* BOM 表格區塊 */}
<div>
<h3 className="text-sm font-bold text-gray-900 flex items-center gap-2 px-1 mb-3">
<Package className="w-4 h-4 text-primary-main" />
(BOM)
</h3>
<div className="border rounded-md overflow-hidden bg-white shadow-sm">
<Table>
<TableHeader className="bg-gray-50/50">
<TableRow>
<TableHead> / </TableHead>
<TableHead className="text-right"></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{recipe.items?.length > 0 ? (
recipe.items.map((item: any, index: number) => (
<TableRow key={index} className="hover:bg-gray-50/50">
<TableCell className="font-medium">
<div className="flex flex-col">
<span className="text-gray-900">{item.product?.name || 'Unknown'}</span>
<span className="text-xs text-gray-400">{item.product?.code}</span>
</div>
</TableCell>
<TableCell className="text-right font-medium text-gray-900">
{Number(item.quantity).toLocaleString()}
</TableCell>
<TableCell className="text-gray-600">
{item.unit?.name || '-'}
</TableCell>
<TableCell className="text-gray-500 text-sm">
{item.remark || '-'}
</TableCell>
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={4} className="h-24 text-center text-gray-500">
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
</div>
</div>
) : (
<div className="py-12 text-center text-gray-500"></div>
)}
</div>
</DialogContent>
</Dialog>
);
}