import { useState } from "react"; import { Button } from "@/Components/ui/button"; import { Input } from "@/Components/ui/input"; import { SearchableSelect } from "@/Components/ui/searchable-select"; import { Plus, Search, X, Pencil, Trash2, FileText, Calendar, RotateCcw, ArrowUpDown, ArrowUp, ArrowDown, ChevronDown, ChevronUp } from 'lucide-react'; import { Label } from "@/Components/ui/label"; import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout"; import { Head, router } from "@inertiajs/react"; import Pagination from "@/Components/shared/Pagination"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/Components/ui/table"; import { Badge } from "@/Components/ui/badge"; import { toast } from "sonner"; import UtilityFeeDialog, { UtilityFee } from "@/Components/UtilityFee/UtilityFeeDialog"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/Components/ui/alert-dialog"; import { Can } from "@/Components/Permission/Can"; import { formatDateWithDayOfWeek, formatInvoiceNumber, getDateRange } from "@/utils/format"; interface PageProps { fees: { data: UtilityFee[]; links: any[]; from: number; to: number; total: number; current_page: number; last_page: number; per_page: number; }; availableCategories: string[]; filters: { search?: string; category?: string; date_start?: string; date_end?: string; sort_field?: string | null; sort_direction?: "asc" | "desc" | null; per_page?: string; }; } export default function UtilityFeeIndex({ fees, availableCategories, filters }: PageProps) { const [searchTerm, setSearchTerm] = useState(filters.search || ""); const [categoryFilter, setCategoryFilter] = useState(filters.category || "all"); const [dateStart, setDateStart] = useState(filters.date_start || ""); const [dateEnd, setDateEnd] = useState(filters.date_end || ""); const [dateRangeType, setDateRangeType] = useState("custom"); const [perPage, setPerPage] = useState(filters.per_page || "10"); const [isDialogOpen, setIsDialogOpen] = useState(false); const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); const [editingFee, setEditingFee] = useState(null); const [deletingFeeId, setDeletingFeeId] = useState(null); // Advanced Filter Toggle const [showAdvancedFilter, setShowAdvancedFilter] = useState( !!(filters.date_start || filters.date_end) ); // Sorting const [sortField, setSortField] = useState(filters.sort_field || null); const [sortDirection, setSortDirection] = useState<"asc" | "desc" | null>(filters.sort_direction as "asc" | "desc" || null); const handleDateRangeChange = (type: string) => { setDateRangeType(type); if (type === "custom") return; const { start, end } = getDateRange(type); setDateStart(start); setDateEnd(end); }; const handleSearch = () => { router.get( route("utility-fees.index"), { search: searchTerm, category: categoryFilter, date_start: dateStart, date_end: dateEnd, sort_field: sortField, sort_direction: sortDirection, per_page: perPage, }, { preserveState: true } ); }; const handlePerPageChange = (value: string) => { setPerPage(value); router.get( route("utility-fees.index"), { search: searchTerm, category: categoryFilter, date_start: dateStart, date_end: dateEnd, sort_field: sortField, sort_direction: sortDirection, per_page: value, }, { preserveState: false, preserveScroll: true } ); }; const handleClearFilters = () => { setSearchTerm(""); setCategoryFilter("all"); setDateStart(""); setDateEnd(""); setDateRangeType("custom"); router.get(route("utility-fees.index"), { per_page: perPage }, { preserveState: false }); }; const handleSort = (field: string) => { let newField: string | null = field; let newDirection: "asc" | "desc" | null = "asc"; if (sortField === field) { if (sortDirection === "asc") { newDirection = "desc"; } else { newDirection = null; newField = null; } } setSortField(newField); setSortDirection(newDirection); router.get( route("utility-fees.index"), { search: searchTerm, category: categoryFilter, date_start: dateStart, date_end: dateEnd, sort_field: newField, sort_direction: newDirection, per_page: perPage, }, { preserveState: true } ); }; const openAddDialog = () => { setEditingFee(null); setIsDialogOpen(true); }; const openEditDialog = (fee: UtilityFee) => { setEditingFee(fee); setIsDialogOpen(true); }; const confirmDelete = (id: number) => { setDeletingFeeId(id); setIsDeleteDialogOpen(true); }; const handleDelete = () => { if (deletingFeeId) { router.delete(route("utility-fees.destroy", deletingFeeId), { onSuccess: () => { toast.success("紀錄已刪除"); setIsDeleteDialogOpen(false); }, }); } }; const SortIcon = ({ field }: { field: string }) => { if (sortField !== field) { return ; } if (sortDirection === "asc") { return ; } if (sortDirection === "desc") { return ; } return ; }; return (

公共事業費管理

管理店鋪水、電、瓦斯等各項公共事業費用支出

{/* Row 1: Search and Category */}
setSearchTerm(e.target.value)} onKeyDown={(e) => e.key === "Enter" && handleSearch()} className="pl-10 h-9 block" /> {searchTerm && ( )}
({ label: c, value: c })) ]} placeholder="篩選類別" className="h-9" />
{/* Row 2: Date Filters (Collapsible) */} {showAdvancedFilter && (
{[ { label: "今日", value: "today" }, { label: "昨日", value: "yesterday" }, { label: "本週", value: "this_week" }, { label: "本月", value: "this_month" }, { label: "上月", value: "last_month" }, ].map((opt) => ( ))}
{ setDateStart(e.target.value); setDateRangeType('custom'); }} className="pl-9 block w-full h-9 bg-white" />
{ setDateEnd(e.target.value); setDateRangeType('custom'); }} className="pl-9 block w-full h-9 bg-white" />
)} {/* Action Buttons */}
{/* Table */}
#
說明 / 備註 操作
{fees.data.length === 0 ? (

找不到符合條件的費用紀錄

) : ( fees.data.map((fee, index) => ( {fees.from + index} {formatDateWithDayOfWeek(fee.transaction_date)} {fee.category} {formatInvoiceNumber(fee.invoice_number)} $ {Number(fee.amount).toLocaleString()} {fee.description || '-'}
)) )}
每頁顯示
確認刪除? 這將永久刪除此筆費用紀錄,此操作無法撤銷。 取消 確認刪除
); }