/** * 配方管理主頁面 */ import { useState, useEffect } from "react"; import { Plus, Search, Pencil, Trash2, BookOpen, Eye } from 'lucide-react'; import { Button } from "@/Components/ui/button"; import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout"; import { Head, router, Link } from "@inertiajs/react"; import Pagination from "@/Components/shared/Pagination"; import { getBreadcrumbs } from "@/utils/breadcrumb"; import { SearchableSelect } from "@/Components/ui/searchable-select"; import { Input } from "@/Components/ui/input"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/Components/ui/table"; import { Badge } from "@/Components/ui/badge"; import { Can } from "@/Components/Permission/Can"; import { RecipeDetailModal } from "./Components/RecipeDetailModal"; import axios from 'axios'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "@/Components/ui/alert-dialog"; interface Recipe { id: number; code: string; name: string; product_id: number; product?: { id: number; name: string; code: string }; yield_quantity: number; is_active: boolean; description: string; updated_at: string; } interface Props { recipes: { data: Recipe[]; links: any[]; total: number; from: number; to: number; }; filters: { search?: string; per_page?: string; sort_field?: string; sort_direction?: string; }; } export default function RecipeIndex({ recipes, filters }: Props) { const [search, setSearch] = useState(filters.search || ""); const [perPage, setPerPage] = useState(filters.per_page || "10"); // View Modal State const [viewRecipe, setViewRecipe] = useState(null); const [isViewModalOpen, setIsViewModalOpen] = useState(false); const [isViewLoading, setIsViewLoading] = useState(false); useEffect(() => { setSearch(filters.search || ""); setPerPage(filters.per_page || "10"); }, [filters]); const handleFilter = () => { router.get( route('recipes.index'), { search, per_page: perPage, }, { preserveState: true, replace: true } ); }; const handlePerPageChange = (value: string) => { setPerPage(value); router.get( route("recipes.index"), { ...filters, per_page: value }, { preserveState: false, replace: true, preserveScroll: true } ); }; const handleDelete = (id: number) => { if (confirm("確定要刪除此配方嗎?")) { router.delete(route('recipes.destroy', id)); } }; const handleView = async (id: number) => { setIsViewModalOpen(true); setIsViewLoading(true); setViewRecipe(null); try { const response = await axios.get(route('recipes.show', id)); setViewRecipe(response.data); } catch (error) { console.error("Failed to load recipe details", error); } finally { setIsViewLoading(false); } }; return (

配方管理

管理產品的標準生產配方與用量

{/* Toolbar */}
{/* Search */}
setSearch(e.target.value)} className="pl-10 pr-10 h-9" onKeyDown={(e) => e.key === 'Enter' && handleFilter()} /> {search && ( )}
{/* Action Buttons */}
{/* 配方列表 */}
配方代號 配方名稱 對應成品 標準產量 狀態 更新時間 操作 {recipes.data.length === 0 ? (

尚無配方資料

) : ( recipes.data.map((recipe) => ( {recipe.code}
{recipe.name} {recipe.description && ( {recipe.description} )}
{recipe.product ? (
{recipe.product.name} {recipe.product.code}
) : '-'}
{recipe.yield_quantity} {recipe.is_active ? "啟用" : "停用"} {new Date(recipe.updated_at).toLocaleDateString()}
確認刪除 確定要刪除配方「{recipe.name}」嗎?此操作無法復原。 取消 handleDelete(recipe.id)} className="bg-red-600 hover:bg-red-700" > 刪除
)) )}
{/* 分頁 */}
每頁顯示
setIsViewModalOpen(false)} recipe={viewRecipe} isLoading={isViewLoading} />
); }