mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
Adjusted
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, useMemo, useRef, useEffect } from "react";
|
||||
import { useState, useMemo, useRef, useEffect, useCallback } from "react";
|
||||
import { useReactTable, getCoreRowModel, flexRender, } from "@tanstack/react-table";
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
@@ -35,31 +35,62 @@ export default function DataTable({
|
||||
}) {
|
||||
// ─── Refs — always hold latest filters and sort ───────────────────────────
|
||||
const filtersRef = useRef([]);
|
||||
const sortRef = useRef([]);
|
||||
|
||||
const sortRef = useRef([]);
|
||||
|
||||
// ─── State ────────────────────────────────────────────────────────────────
|
||||
const [activeColumn, setActiveColumn] = useState(null);
|
||||
const [sorting, setSorting] = useState([]);
|
||||
const [columnFilters, setColumnFilters] = useState([]);
|
||||
const [columnVisibility, setColumnVisibility] = useState({});
|
||||
const [rowSelection, setRowSelection] = useState({});
|
||||
const [filterState, setFilterState] = useState({
|
||||
const [activeColumn, setActiveColumn] = useState(null);
|
||||
const [sorting, setSorting] = useState([]);
|
||||
const [columnFilters, setColumnFilters] = useState([]);
|
||||
const [columnVisibility, setColumnVisibility] = useState({});
|
||||
const [rowSelection, setRowSelection] = useState({});
|
||||
const [filterState, setFilterState] = useState({
|
||||
open: false, column: null, attr: null, data: [],
|
||||
});
|
||||
|
||||
const activeFilters = columnFilters.filter((f) => f.value !== "");
|
||||
|
||||
// ─── Initial fetch on mount only ─────────────────────────────────────────
|
||||
// ─── setFilters — called externally by dashboard charts ──────────────────
|
||||
// Merges incoming filters with existing ones (replaces by id, appends new).
|
||||
// Pass an empty array [] to clear all filters.
|
||||
const setFilters = useCallback((incomingFilters) => {
|
||||
setColumnFilters((prev) => {
|
||||
let next;
|
||||
|
||||
if (!incomingFilters.length) {
|
||||
next = [];
|
||||
} else {
|
||||
// Replace matching ids, keep the rest
|
||||
const incomingIds = new Set(incomingFilters.map((f) => f.id));
|
||||
const kept = prev.filter((f) => !incomingIds.has(f.id));
|
||||
next = [...kept, ...incomingFilters];
|
||||
}
|
||||
|
||||
const newFilters = next.filter((f) => f.value !== "");
|
||||
filtersRef.current = newFilters;
|
||||
|
||||
onFetch({
|
||||
page: 1,
|
||||
limit: pagination.limit,
|
||||
filters: newFilters,
|
||||
sort: sortRef.current,
|
||||
});
|
||||
|
||||
return next;
|
||||
});
|
||||
}, [onFetch, pagination.limit]);
|
||||
|
||||
// ─── Expose refs to parent ────────────────────────────────────────────────
|
||||
useEffect(() => {
|
||||
onRefsReady?.({
|
||||
getFilters: () => filtersRef.current,
|
||||
getSort: () => sortRef.current,
|
||||
resetSelection: () => table.resetRowSelection(), // ← expose this
|
||||
getFilters: () => filtersRef.current,
|
||||
getSort: () => sortRef.current,
|
||||
resetSelection: () => table.resetRowSelection(),
|
||||
setFilters, // ← new
|
||||
});
|
||||
|
||||
onFetch({ page: 1, limit: pagination.limit, filters: [], sort: [] });
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
}, [setFilters]);
|
||||
|
||||
const handleOpenFilterSheet = async (e, column, attr) => {
|
||||
e.preventDefault();
|
||||
@@ -79,61 +110,60 @@ export default function DataTable({
|
||||
rowSelection,
|
||||
pagination: {
|
||||
pageIndex: pagination.page - 1,
|
||||
pageSize: pagination.limit,
|
||||
pageSize: pagination.limit,
|
||||
},
|
||||
},
|
||||
enableRowSelection: true,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
manualPagination: true,
|
||||
manualSorting: true,
|
||||
manualFiltering: true,
|
||||
pageCount: pagination.totalPages,
|
||||
enableRowSelection: true,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
manualPagination: true,
|
||||
manualSorting: true,
|
||||
manualFiltering: true,
|
||||
pageCount: pagination.totalPages,
|
||||
|
||||
// ─── Sort change ────────────────────────────────────────────────────────
|
||||
// ─── Sort change ──────────────────────────────────────────────────────
|
||||
onSortingChange: (updater) => {
|
||||
const next = typeof updater === "function" ? updater(sorting) : updater;
|
||||
const next = typeof updater === "function" ? updater(sorting) : updater;
|
||||
const newSort = next.length ? [{ id: next[0].id, desc: next[0].desc }] : [];
|
||||
|
||||
setSorting(next);
|
||||
sortRef.current = newSort;
|
||||
|
||||
onFetch({
|
||||
page: 1,
|
||||
limit: pagination.limit,
|
||||
page: 1,
|
||||
limit: pagination.limit,
|
||||
filters: filtersRef.current,
|
||||
sort: newSort,
|
||||
sort: newSort,
|
||||
});
|
||||
},
|
||||
|
||||
// ─── Filter change ──────────────────────────────────────────────────────
|
||||
// ─── Filter change ────────────────────────────────────────────────────
|
||||
onColumnFiltersChange: (updater) => {
|
||||
const next = typeof updater === "function" ? updater(columnFilters) : updater;
|
||||
const next = typeof updater === "function" ? updater(columnFilters) : updater;
|
||||
const newFilters = next.filter((f) => f.value !== "");
|
||||
|
||||
setColumnFilters(next);
|
||||
filtersRef.current = newFilters;
|
||||
|
||||
onFetch({
|
||||
page: 1,
|
||||
limit: pagination.limit,
|
||||
page: 1,
|
||||
limit: pagination.limit,
|
||||
filters: newFilters,
|
||||
sort: sortRef.current,
|
||||
sort: sortRef.current,
|
||||
});
|
||||
},
|
||||
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
});
|
||||
|
||||
// ─── Single handler for all page changes ──────────────────────────────────────
|
||||
// ─── Page change ──────────────────────────────────────────────────────────
|
||||
const handlePageChange = (page) => {
|
||||
setPagination((p) => ({ ...p, page }));
|
||||
onFetch({
|
||||
page,
|
||||
limit: pagination.limit,
|
||||
limit: pagination.limit,
|
||||
filters: filtersRef.current,
|
||||
sort: sortRef.current,
|
||||
sort: sortRef.current,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -169,7 +199,7 @@ export default function DataTable({
|
||||
onFetch({ page: 1, limit: pagination.limit, filters: [], sort: sortRef.current });
|
||||
}}
|
||||
onRemove={(id) => {
|
||||
const next = columnFilters.filter((c) => c.id !== id);
|
||||
const next = columnFilters.filter((c) => c.id !== id);
|
||||
const newFilters = next.filter((f) => f.value !== "");
|
||||
setColumnFilters(next);
|
||||
filtersRef.current = newFilters;
|
||||
@@ -187,7 +217,7 @@ export default function DataTable({
|
||||
filters={activeFilters}
|
||||
attributes={attributes}
|
||||
onRemove={(id) => {
|
||||
const next = columnFilters.filter((c) => c.id !== id);
|
||||
const next = columnFilters.filter((c) => c.id !== id);
|
||||
const newFilters = next.filter((f) => f.value !== "");
|
||||
setColumnFilters(next);
|
||||
filtersRef.current = newFilters;
|
||||
@@ -204,8 +234,8 @@ export default function DataTable({
|
||||
<TableRow key={hg.id} className="bg-muted/40 hover:bg-muted/40">
|
||||
{hg.headers.map((header) => {
|
||||
const isPinned = header.column.getIsPinned();
|
||||
const attr = header.column.columnDef.meta?.attr;
|
||||
const isPlain = header.column.id === "select" || header.column.id === "actions";
|
||||
const attr = header.column.columnDef.meta?.attr;
|
||||
const isPlain = header.column.id === "select" || header.column.id === "actions";
|
||||
|
||||
return (
|
||||
<TableHead
|
||||
@@ -213,10 +243,10 @@ export default function DataTable({
|
||||
className={cn("align-middle whitespace-nowrap", isPinned ? "bg-muted" : "")}
|
||||
style={{
|
||||
position: isPinned ? "sticky" : "relative",
|
||||
right: isPinned === "right" ? header.column.getStart("right") : undefined,
|
||||
left: isPinned === "left" ? header.column.getStart("left") : undefined,
|
||||
zIndex: isPinned ? 2 : 0,
|
||||
width: header.column.columnDef.size,
|
||||
right: isPinned === "right" ? header.column.getStart("right") : undefined,
|
||||
left: isPinned === "left" ? header.column.getStart("left") : undefined,
|
||||
zIndex: isPinned ? 2 : 0,
|
||||
width: header.column.columnDef.size,
|
||||
}}
|
||||
>
|
||||
{isPlain ? (
|
||||
@@ -238,11 +268,11 @@ export default function DataTable({
|
||||
</TableHeader>
|
||||
|
||||
{renderFilterSheet?.({
|
||||
open: filterState.open,
|
||||
open: filterState.open,
|
||||
onOpenChange: (v) => setFilterState((p) => ({ ...p, open: v })),
|
||||
column: filterState.column,
|
||||
attr: filterState.attr,
|
||||
data: filterState.data,
|
||||
column: filterState.column,
|
||||
attr: filterState.attr,
|
||||
data: filterState.data,
|
||||
loading,
|
||||
})}
|
||||
|
||||
@@ -271,9 +301,9 @@ export default function DataTable({
|
||||
className={cn("m-0", isPinned && "bg-card")}
|
||||
style={{
|
||||
position: isPinned ? "sticky" : "relative",
|
||||
right: isPinned === "right" ? 0 : undefined,
|
||||
left: isPinned === "left" ? cell.column.getStart("left") : undefined,
|
||||
zIndex: isPinned ? 1 : 0,
|
||||
right: isPinned === "right" ? 0 : undefined,
|
||||
left: isPinned === "left" ? cell.column.getStart("left") : undefined,
|
||||
zIndex: isPinned ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
@@ -298,16 +328,16 @@ export default function DataTable({
|
||||
<TablePagination
|
||||
table={table}
|
||||
pagination={pagination}
|
||||
onPageChange={handlePageChange} // ← replaces setPagination
|
||||
onPageChange={handlePageChange}
|
||||
totalRecords={pagination.totalRecords}
|
||||
rowCount={data.length}
|
||||
onPageSizeChange={(size) => {
|
||||
setPagination((p) => ({ ...p, limit: size, page: 1 })); // ← updates your state
|
||||
setPagination((p) => ({ ...p, limit: size, page: 1 }));
|
||||
onFetch({
|
||||
page: 1,
|
||||
limit: size,
|
||||
page: 1,
|
||||
limit: size,
|
||||
filters: filtersRef.current,
|
||||
sort: sortRef.current,
|
||||
sort: sortRef.current,
|
||||
});
|
||||
}}
|
||||
pageSizeOptions={pageSizeOptions}
|
||||
|
||||
Reference in New Issue
Block a user