diff --git a/src_generic/components/EnhancedTable.tsx b/src_generic/components/EnhancedTable.tsx index 8ee8207..754a1d8 100644 --- a/src_generic/components/EnhancedTable.tsx +++ b/src_generic/components/EnhancedTable.tsx @@ -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', diff --git a/src_generic/components/ResourceView.tsx b/src_generic/components/ResourceView.tsx index a4dbc2c..4ec0c49 100644 --- a/src_generic/components/ResourceView.tsx +++ b/src_generic/components/ResourceView.tsx @@ -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({ + 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 ? ( = { display: false } }, + pagination: true, }, }; diff --git a/src_generic/hooks/useResource.ts b/src_generic/hooks/useResource.ts index 1c7a10a..a7057ad 100644 --- a/src_generic/hooks/useResource.ts +++ b/src_generic/hooks/useResource.ts @@ -13,7 +13,11 @@ export function useResource(config: ResourceConfig) { queryFn: async () => { // @ts-ignore const res = await api.get(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(config: ResourceConfig) { queryFn: async () => { // @ts-ignore const res = await api.get(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 + }; }, }); diff --git a/src_generic/types/config.ts b/src_generic/types/config.ts index 78d6989..b8b434c 100644 --- a/src_generic/types/config.ts +++ b/src_generic/types/config.ts @@ -29,6 +29,7 @@ export interface ResourceConfig { endpoint: string; primaryKey: string; fields: Record; + pagination?: boolean; } export interface AppConfig { diff --git a/src_generic/types/overrides.ts b/src_generic/types/overrides.ts index 31cfe04..797604f 100644 --- a/src_generic/types/overrides.ts +++ b/src_generic/types/overrides.ts @@ -11,4 +11,5 @@ export interface FieldOverride { export interface ResourceOverride { fields?: Record; + pagination?: boolean; }