2025-11-27 09:09:43 +01:00

135 lines
4.2 KiB
TypeScript

"use client";
import React, { useState, useCallback, useMemo } from "react";
import { DataGrid, GridPaginationModel } from "@mui/x-data-grid";
import { Box, Paper, Alert } from "@mui/material";
import DataTableHeader from "./DataTableHeader";
import StatusChangeDialog from "./StatusChangeDialog";
import Spinner from "@/app/components/Spinner/Spinner";
import {
selectStatus,
selectError,
selectPagination,
selectPaginationModel,
} from "@/app/redux/advanedSearch/selectors";
import { makeSelectEnhancedColumns } from "./re-selectors";
import { useDispatch, useSelector } from "react-redux";
import { DataRowBase } from "./types";
import { setPagination } from "@/app/redux/advanedSearch/advancedSearchSlice";
import { AppDispatch } from "@/app/redux/store";
interface DataTableProps<TRow extends DataRowBase> {
rows: TRow[];
extraColumns?: string[];
enableStatusActions?: boolean;
totalRows?: number;
}
const DataTable = <TRow extends DataRowBase>({
rows: localRows,
extraColumns,
enableStatusActions = false,
totalRows: totalRows,
}: DataTableProps<TRow>) => {
const dispatch = useDispatch<AppDispatch>();
const [showExtraColumns, setShowExtraColumns] = useState(false);
const [statusDialogData, setStatusDialogData] = useState<{
rowId: number;
newStatus: string;
} | null>(null);
const status = useSelector(selectStatus);
const errorMessage = useSelector(selectError);
const pagination = useSelector(selectPagination);
const paginationModel = useSelector(selectPaginationModel);
const handlePaginationModelChange = useCallback(
(model: GridPaginationModel) => {
const nextPage = model.page + 1;
const nextLimit = model.pageSize;
if (nextPage !== pagination.page || nextLimit !== pagination.limit) {
dispatch(setPagination({ page: nextPage, limit: nextLimit }));
}
},
[dispatch, pagination.page, pagination.limit]
);
const handleStatusChange = useCallback((rowId: number, newStatus: string) => {
setStatusDialogData({ rowId, newStatus });
}, []);
const handleDialogClose = useCallback(() => {
setStatusDialogData(null);
}, []);
const selectEnhancedColumns = useMemo(makeSelectEnhancedColumns, []);
const enhancedColumns = useSelector(state =>
selectEnhancedColumns(state, {
enableStatusActions,
extraColumns,
showExtraColumns,
localRows,
handleStatusChange,
})
);
return (
<>
{status === "loading" && <Spinner size="small" color="#fff" />}
{status === "failed" && (
<Alert severity="error">
{errorMessage || "Failed to load transactions."}
</Alert>
)}
<Paper sx={{ width: "100%", overflowX: "hidden" }}>
<DataTableHeader
extraColumns={extraColumns}
showExtraColumns={showExtraColumns}
onToggleExtraColumns={() => setShowExtraColumns(prev => !prev)}
onOpenExport={() => {}}
/>
<Box sx={{ width: "85vw" }}>
<Box sx={{ minWidth: 1200 }}>
<DataGrid
rows={localRows}
columns={enhancedColumns}
paginationModel={paginationModel}
onPaginationModelChange={handlePaginationModelChange}
paginationMode={totalRows ? "server" : "client"}
rowCount={totalRows}
pageSizeOptions={[10, 25, 50, 100]}
sx={{
border: 0,
cursor: "pointer",
"& .MuiDataGrid-cell": {
py: 1,
textAlign: "center",
justifyContent: "center",
display: "flex",
alignItems: "center",
},
"& .MuiDataGrid-columnHeader": {
textAlign: "center",
justifyContent: "center",
},
}}
/>
</Box>
</Box>
<StatusChangeDialog
open={Boolean(statusDialogData)}
transactionId={statusDialogData?.rowId}
newStatus={statusDialogData?.newStatus ?? ""}
onClose={handleDialogClose}
/>
</Paper>
</>
);
};
// Memoize to avoid unnecessary re-renders
export default React.memo(DataTable);