"use client"; import { useEffect, useState, useCallback } from "react"; import ComponentCard from "@/components/common/ComponentCard"; import PageBreadcrumb from "@/components/common/PageBreadCrumb"; import Pagination from "@/components/tables/Pagination"; import Swal from "sweetalert2"; import ApplicationTable, { AppSortColumn, } from "@/components/tables/ApplicationTable"; import { apiGetUserApplications } from "@/service/historianService"; import { ApplicationDto, ApplicationResponse, GetApplicationsParams, } from "@/interface/historian"; import ApplicationDetailModal from "@/components/tables/ApplicationDetailModal"; import { LIMIT_ITEM_TABLE } from "../../../../../../constant"; import { toast } from "sonner"; const formatDateTimeToISO = ( dateStr: string, timeStr: string, isEndOfDay: boolean = false, ): string | undefined => { if (!dateStr) return undefined; const time = timeStr || (isEndOfDay ? "23:59" : "00:00"); return `${dateStr}T${time}:00.000000+07:00`; }; export default function HistorianApplicationPage() { const [page, setPage] = useState(1); const [limitInput, setLimitInput] = useState( LIMIT_ITEM_TABLE.toString(), ); const [searchTerm, setSearchTerm] = useState(""); const [statusFilter, setStatusFilter] = useState(""); const [verifyTypeFilter, setVerifyTypeFilter] = useState(""); const [fromDate, setFromDate] = useState(""); const [fromTime, setFromTime] = useState(""); const [toDate, setToDate] = useState(""); const [toTime, setToTime] = useState(""); const [selectedApp, setSelectedApp] = useState(null); const [isModalOpen, setIsModalOpen] = useState(false); const [debouncedParams, setDebouncedParams] = useState({ search: "", limit: LIMIT_ITEM_TABLE, status: "", verifyType: "", fromDate: "", fromTime: "", toDate: "", toTime: "", }); const [tableData, setTableData] = useState(null); const [loading, setLoading] = useState(true); const [sortBy, setSortBy] = useState("created_at"); const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc"); const handleReset = () => { setSearchTerm(""); setStatusFilter(""); setVerifyTypeFilter(""); setLimitInput(LIMIT_ITEM_TABLE.toString()); setFromDate(""); setFromTime(""); setToDate(""); setToTime(""); setPage(1); setDebouncedParams({ search: "", limit: LIMIT_ITEM_TABLE, status: "", verifyType: "", fromDate: "", fromTime: "", toDate: "", toTime: "", }); }; useEffect(() => { const handler = setTimeout(() => { setDebouncedParams({ search: searchTerm, limit: parseInt(limitInput) || LIMIT_ITEM_TABLE, status: statusFilter, verifyType: verifyTypeFilter, fromDate, fromTime, toDate, toTime, }); setPage(1); }, 600); return () => clearTimeout(handler); }, [ searchTerm, limitInput, statusFilter, verifyTypeFilter, fromDate, fromTime, toDate, toTime, ]); useEffect(() => { fetchApplications(); }, [ page, debouncedParams, sortBy, sortOrder, ]); const fetchApplications = useCallback(async () => { setLoading(true); try { const payload: GetApplicationsParams = { page: page, limit: debouncedParams.limit, search: debouncedParams.search || undefined, sort: sortBy, order: sortOrder, }; if (debouncedParams.status) payload.statuses = [debouncedParams.status]; if (debouncedParams.verifyType) payload.verify_types = debouncedParams.verifyType; const createdFrom = formatDateTimeToISO( debouncedParams.fromDate, debouncedParams.fromTime, false, ); if (createdFrom) payload.created_from = createdFrom; const createdTo = formatDateTimeToISO( debouncedParams.toDate, debouncedParams.toTime, true, ); if (createdTo) payload.created_to = createdTo; // console.log("Payload sent to API:", payload); const response = await apiGetUserApplications(payload); if (response?.status) { setTableData(response); } } catch (err) { toast.error("Lỗi lấy danh sách hồ sơ"); console.error("Lỗi lấy danh sách hồ sơ:", err); setTableData(null); } finally { setLoading(false); } }, [page, debouncedParams, sortBy, sortOrder]); const handleSort = (column: AppSortColumn) => { setPage(1); if (sortBy === column) { setSortOrder(sortOrder === "asc" ? "desc" : "asc"); } else { setSortBy(column); setSortOrder("desc"); } }; const handleViewDetail = (app: ApplicationDto) => { setSelectedApp(app); setIsModalOpen(true); }; const pagination = tableData?.pagination; console.log(tableData) // console.log("Pagination info:", pagination); return (
} > {/* Cập nhật Grid để chứa đủ các ô filter */}
setSearchTerm(e.target.value)} className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" />
setFromDate(e.target.value)} className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" /> setFromTime(e.target.value)} className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" />
setToDate(e.target.value)} className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" /> setToTime(e.target.value)} className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" />
setLimitInput(e.target.value)} className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" />
{loading && (
)}

Hiển thị {pagination?.total_records || 0} hồ sơ

{pagination && pagination.total_pages > 1 && ( setPage(newPage)} /> )}
setIsModalOpen(false)} application={selectedApp || null} onRefresh={fetchApplications} />
); }