This commit is contained in:
rgrgogu
2026-05-07 23:35:31 +08:00
parent 42b842c480
commit ca6eae1d56
35 changed files with 1637 additions and 207 deletions
@@ -0,0 +1,120 @@
import { useMemo, useRef, useState } from "react";
import { useNavigate } from "react-router-dom";
import { useUsers } from "@/contexts/AdminUserContext";
import DataTable from "@/components/generic/Table/DataTable";
import { FilterSheet } from "@/components/generic/Sheet/FilterSheet";
import { RestoreDialog } from "@/components/generic/Dialogs/RestoreDialog";
import { buildUserColumns, columnPinning } from "../../config/users/archive/columns.config";
import { buildToolbarActions } from "../../config/users/archive/toolbar.config";
import { buildSelectionActions } from "../../config/users/archive/selection.config";
import { buildRowActions } from "../../config/users/archive/rowActions.config";
import { getTimestamp } from "@/utils/timestamp.util";
export default function ArchiveGroupTable() {
const [restoreTarget, setRestoreTarget] = useState(null); // single: row object
const [restoreIds, setRestoreIds] = useState(null); // bulk: array of ids
const tableRefsRef = useRef({ getFilters: () => [], getSort: () => [], resetSelection: () => { } });
const navigate = useNavigate();
const {
users,
attributes,
pagination,
setPagination,
loading,
fetchArchivedUsers,
fetchUserFieldValues,
restoreUser,
restoreUsers
} = useUsers();
// Shared export config — passed into toolbar + selection configs
const exportConfig = {
allData: users,
attributes,
filename: `${getTimestamp()}_ArchivedUserGroups`,
sheetName: "ArchivedUserGroups",
};
const rowActions = buildRowActions({
navigate,
onRestore: (row) => setRestoreTarget(row),
});
const toolbarActions = buildToolbarActions({
fetchArchivedUsers, pagination, exportConfig, navigate,
getFilters: () => tableRefsRef.current.getFilters(),
getSort: () => tableRefsRef.current.getSort(),
});
const selectionActions = buildSelectionActions({
exportConfig,
restoreUser: (row) => setRestoreTarget(row),
restoreUsers: (ids) => setRestoreIds(ids),
});
const columns = useMemo(() => buildUserColumns(attributes, rowActions), [attributes]);
const handleRestoreSuccess = () => {
setRestoreTarget(null);
setRestoreIds(null);
tableRefsRef.current.resetSelection?.(); // ← clear selection
fetchArchivedUsers({ page: 1, limit: pagination.limit });
};
return (
<>
<DataTable
title="Archived Users"
data={users}
columns={columns}
attributes={attributes}
pagination={pagination}
setPagination={setPagination}
loading={loading}
onFetch={fetchArchivedUsers}
onFetchFilterData={fetchUserFieldValues}
onRefsReady={(refs) => tableRefsRef.current = refs}
renderFilterSheet={({ open, onOpenChange, column, attr, data, loading }) => (
<FilterSheet
open={open}
onOpenChange={onOpenChange}
column={column}
attr={attr}
data={data}
loading={loading}
/>
)}
columnPinning={columnPinning}
toolbarActions={toolbarActions}
selectionActions={selectionActions}
recordLabel="user"
emptyMessage="No users match the current filters."
/>
{/* Single restore */}
<RestoreDialog
open={!!restoreTarget}
onOpenChange={(v) => !v && setRestoreTarget(null)}
entity={restoreTarget}
entityLabel="User"
getName={(u) => u?.personal_info?.name?.full_name ?? u?.email}
onRestore={(u) => restoreUser(u?.user_id)}
loading={loading}
onSuccess={handleRestoreSuccess}
/>
{/* Bulk restore */}
<RestoreDialog
open={!!restoreIds}
onOpenChange={(v) => !v && setRestoreIds(null)}
ids={restoreIds ?? []}
entityLabel="User"
onRestore={restoreUsers}
loading={loading}
onSuccess={handleRestoreSuccess}
/>
</>
);
}