pagination

This commit is contained in:
2026-04-03 19:58:56 +05:30
parent 9b87fb31a7
commit f8cea025a3
6 changed files with 62 additions and 9 deletions

View File

@@ -23,6 +23,7 @@ import {
GridColDef,
GridActionsCellItem,
GridRenderCellParams,
GridPaginationModel,
} from '@mui/x-data-grid';
import EditIcon from '@mui/icons-material/Edit';
import DeleteIcon from '@mui/icons-material/Delete';
@@ -34,6 +35,10 @@ import { ResourceConfig } from '../types/config';
interface EnhancedTableProps {
config: ResourceConfig;
data: any[];
total?: number;
paginationModel?: GridPaginationModel;
onPaginationModelChange?: (model: GridPaginationModel) => void;
loading?: boolean;
onEdit: (item: any) => void;
onDelete: (id: string) => void;
onCreate: () => void;
@@ -43,6 +48,10 @@ interface EnhancedTableProps {
export default function EnhancedTable({
config,
data,
total,
paginationModel,
onPaginationModelChange,
loading = false,
onEdit,
onDelete,
onCreate,
@@ -152,6 +161,23 @@ export default function EnhancedTable({
rows={data || []}
columns={columns}
autoHeight
paginationMode={config.pagination ? 'server' : 'client'}
rowCount={(() => {
if (!config.pagination) return data.length;
if (total !== undefined) return total;
// Graceful fallback for missing total count
const page = paginationModel?.page || 0;
const pageSize = paginationModel?.pageSize || 10;
if (data.length < pageSize) {
return page * pageSize + data.length;
}
// Enable 'Next' button by pretending there's at least one more page
return (page + 2) * pageSize;
})()}
loading={loading}
paginationModel={paginationModel || { page: 0, pageSize: 10 }}
onPaginationModelChange={onPaginationModelChange}
getRowId={(row) => {
const pk = config.primaryKey;
if (row[pk] !== undefined && row[pk] !== null) return row[pk];
@@ -162,11 +188,6 @@ export default function EnhancedTable({
return `temp-id-${data.indexOf(row)}`;
}}
disableRowSelectionOnClick
initialState={{
pagination: {
paginationModel: { page: 0, pageSize: 10 },
},
}}
pageSizeOptions={[10, 25, 50]}
sx={{
border: 'none',

View File

@@ -11,6 +11,8 @@ interface ResourceViewProps {
onNavigateToResource?: (resourceName: string, id: string) => void;
}
import { GridPaginationModel } from '@mui/x-data-grid';
export default function ResourceView({ config, onNavigateToResource }: ResourceViewProps) {
const { id } = useParams();
const location = useLocation();
@@ -21,11 +23,26 @@ export default function ResourceView({ config, onNavigateToResource }: ResourceV
const isView = !!id && !isEdit;
const isList = !id && !isCreate;
const [paginationModel, setPaginationModel] = React.useState<GridPaginationModel>({
page: 0,
pageSize: 10,
});
const { useList, useRead, useCreate, useUpdate, useDelete } = useResource(config);
const listQuery = useList();
// Determine query parameters based on pagination config
const queryParams = React.useMemo(() => {
if (!config.pagination) return {};
return {
skip: paginationModel.page * paginationModel.pageSize,
limit: paginationModel.pageSize,
};
}, [config.pagination, paginationModel]);
const listQuery = useList(queryParams);
const itemQuery = useRead(id || "");
const paginatedData = listQuery.data || { data: [], total: undefined };
const createMutation = useCreate();
const updateMutation = useUpdate();
const deleteMutation = useDelete();
@@ -65,7 +82,11 @@ export default function ResourceView({ config, onNavigateToResource }: ResourceV
{isList ? (
<EnhancedTable
config={config}
data={listQuery.data || []}
data={paginatedData.data || []}
total={paginatedData.total}
paginationModel={paginationModel}
onPaginationModelChange={setPaginationModel}
loading={listQuery.isFetching}
onEdit={handleEdit}
onDelete={handleDelete}
onCreate={handleCreate}

View File

@@ -38,6 +38,7 @@ export const configuration: Record<string, ResourceOverride> = {
display: false
}
},
pagination: true,
},
};

View File

@@ -13,7 +13,11 @@ export function useResource<T = any>(config: ResourceConfig) {
queryFn: async () => {
// @ts-ignore
const res = await api.get<T[]>(endpoint, { params });
return res.data;
const total = res.headers ? parseInt(res.headers['x-total-count'] || res.headers['X-Total-Count']) : undefined;
return {
data: res.data,
total: isNaN(total as any) ? undefined : total
};
}
});
@@ -77,7 +81,11 @@ export function useResource<T = any>(config: ResourceConfig) {
queryFn: async () => {
// @ts-ignore
const res = await api.get<T[]>(endpoint, { params });
return res.data;
const total = res.headers ? parseInt(res.headers['x-total-count'] || res.headers['X-Total-Count']) : undefined;
return {
data: res.data,
total: isNaN(total as any) ? undefined : total
};
},
});

View File

@@ -29,6 +29,7 @@ export interface ResourceConfig {
endpoint: string;
primaryKey: string;
fields: Record<string, ResourceField>;
pagination?: boolean;
}
export interface AppConfig {

View File

@@ -11,4 +11,5 @@ export interface FieldOverride {
export interface ResourceOverride {
fields?: Record<string, FieldOverride>;
pagination?: boolean;
}