import { useState, useCallback, useEffect } from "react"; import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout"; import { Head, Link, router } from "@inertiajs/react"; import { debounce } from "lodash"; import { SearchableSelect } from "@/Components/ui/searchable-select"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/Components/ui/table"; import { Button } from "@/Components/ui/button"; import { Input } from "@/Components/ui/input"; import { Badge } from "@/Components/ui/badge"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/Components/ui/alert-dialog"; import Pagination from "@/Components/shared/Pagination"; import { toast } from "sonner"; import { Can } from "@/Components/Permission/Can"; import { usePermission } from "@/hooks/usePermission"; import { Plus, Search, Store, Eye, Pencil, Trash2, X, } from "lucide-react"; import { formatDate } from "@/lib/date"; const statusMap: Record = { draft: { label: "草稿", variant: "secondary" }, pending: { label: "待審核", variant: "warning" }, approved: { label: "已核准", variant: "success" }, rejected: { label: "已駁回", variant: "destructive" }, completed: { label: "已完成", variant: "default" }, cancelled: { label: "已取消", variant: "outline" }, }; function getStatusBadge(status: string) { const config = statusMap[status]; if (!config) return {status}; const variantClass: Record = { secondary: "", warning: "bg-amber-500 hover:bg-amber-600 text-white", success: "bg-green-500 hover:bg-green-600 text-white", destructive: "", default: "bg-blue-500 hover:bg-blue-600 text-white", outline: "", }; const variant = ["secondary", "destructive", "outline"].includes(config.variant) ? (config.variant as "secondary" | "destructive" | "outline") : "default"; return ( {config.label} ); } export default function Index({ requisitions, filters, warehouses, }: { requisitions: any; filters: any; warehouses: { id: number; name: string }[]; }) { const { can } = usePermission(); const [searchTerm, setSearchTerm] = useState(filters.search || ""); const [statusFilter, setStatusFilter] = useState(filters.status || "all"); const [warehouseFilter, setWarehouseFilter] = useState(filters.warehouse_id || "all"); const [perPage, setPerPage] = useState(filters.per_page || "10"); const [deleteId, setDeleteId] = useState(null); useEffect(() => { setSearchTerm(filters.search || ""); setStatusFilter(filters.status || "all"); setWarehouseFilter(filters.warehouse_id || "all"); setPerPage(filters.per_page || "10"); }, [filters]); const applyFilters = useCallback( (overrides: Record = {}) => { const params: Record = { search: searchTerm, status: statusFilter === "all" ? "" : statusFilter, warehouse_id: warehouseFilter === "all" ? "" : warehouseFilter, per_page: perPage, ...overrides, }; // 清理空值 Object.keys(params).forEach((key) => { if (!params[key]) delete params[key]; }); router.get(route("store-requisitions.index"), params, { preserveState: true, replace: true, preserveScroll: true, }); }, [searchTerm, statusFilter, warehouseFilter, perPage] ); const debouncedSearch = useCallback( debounce((term: string) => { applyFilters({ search: term }); }, 500), [applyFilters] ); const handleSearchChange = (term: string) => { setSearchTerm(term); debouncedSearch(term); }; const handleClearSearch = () => { setSearchTerm(""); applyFilters({ search: "" }); }; const handleStatusChange = (value: string) => { setStatusFilter(value); applyFilters({ status: value === "all" ? "" : value }); }; const handleWarehouseChange = (value: string) => { setWarehouseFilter(value); applyFilters({ warehouse_id: value === "all" ? "" : value }); }; const handlePerPageChange = (value: string) => { setPerPage(value); applyFilters({ per_page: value }); }; const handleDelete = () => { if (deleteId) { router.delete(route("store-requisitions.destroy", [deleteId]), { onSuccess: () => { setDeleteId(null); toast.success("已成功刪除"); }, onError: () => setDeleteId(null), }); } }; return (
{/* 頁面標題 */}

門市叫貨管理

門市人員依庫存與銷售需求,向總倉提出商品補貨申請。

{/* 篩選工具列 */}
{/* 搜尋 */}
handleSearchChange(e.target.value)} className="pl-10 pr-10 h-9" /> {searchTerm && ( )}
{/* 狀態篩選 */} {/* 倉庫篩選 */} ({ label: w.name, value: w.id.toString(), })), ]} placeholder="選擇倉庫" className="w-full md:w-[200px] h-9" /> {/* 操作按鈕 */}
{/* 資料表格 */}
# 單號 申請倉庫 供貨倉庫 申請人 建立日期 狀態 操作 {requisitions.data.length === 0 ? ( 尚無叫貨紀錄 ) : ( requisitions.data.map((req: any, index: number) => ( router.visit(route("store-requisitions.show", [req.id])) } > {(requisitions.current_page - 1) * requisitions.per_page + index + 1} {req.doc_no} {req.store_warehouse_name} {req.supply_warehouse_name} {req.creator_name} {formatDate(req.created_at)} {getStatusBadge(req.status)}
e.stopPropagation()} > {(() => { const isEditable = ["draft", "rejected"].includes(req.status); const canEdit = can("store_requisitions.edit"); if (isEditable && canEdit) { return ( ); } return ( ); })()} {req.status === "draft" && ( )}
)) )}
{/* 分頁 */}
每頁顯示
共 {requisitions.total} 筆紀錄
{/* 刪除確認對話框 */} !open && setDeleteId(null)}> 確定要刪除此叫貨單嗎? 此動作無法復原。如果單據已存在重要資料,請謹慎操作。 取消 確認刪除
); }