Skip to content
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
'use client';
import * as React from 'react';
import { usePathname, useRouter } from 'next/navigation';
import { CrudProvider, List, Create, Edit, Show } from '@toolpad/core/Crud';
import { employeesDataSource, Employee, employeesCache } from '../../../mocks/employees';
import CustomDataGrid from '../../../components/CustomDataGrid';

function matchPath(pattern: string, pathname: string): string | null {
const regex = new RegExp(`^${pattern.replace(/:[^/]+/g, '([^/]+)')}$`);
const match = pathname.match(regex);
return match ? match[1] : null;
}

export default function EmployeesCrudPage() {
const pathname = usePathname();
const router = useRouter();

const rootPath = '/employees';
const listPath = rootPath;
const showPath = `${rootPath}/:employeeId`;
const createPath = `${rootPath}/new`;
const editPath = `${rootPath}/:employeeId/edit`;

const showEmployeeId = matchPath(showPath, pathname);
const editEmployeeId = matchPath(editPath, pathname);

const handleRowClick = React.useCallback(
(employeeId: string | number) => {
console.log('Clicked on row with ID', employeeId);
router.push(`${rootPath}/${String(employeeId)}`);
},
[router],
);

const handleCreateClick = React.useCallback(() => {
router.push(createPath);
}, [createPath, router]);

const handleEditClick = React.useCallback(
(employeeId: string | number) => {
router.push(`${rootPath}/${String(employeeId)}/edit`);
},
[router],
);

const handleCreate = React.useCallback(() => {
router.push(listPath);
}, [listPath, router]);

const handleEdit = React.useCallback(() => {
router.push(listPath);
}, [listPath, router]);

const handleDelete = React.useCallback(() => {
router.push(listPath);
}, [listPath, router]);

return (
<CrudProvider<Employee> dataSource={employeesDataSource} dataSourceCache={employeesCache}>
Copy link
Collaborator

@apedroferreira apedroferreira Mar 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll expose the dataGrid slot to the Crud component so we can just use that component here.

Copy link
Collaborator

@apedroferreira apedroferreira Mar 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to just add a TODO comment here for this for now as i guess we will only be able to adjust here after the next release once we merge #4786

{pathname === listPath ? (
<List<Employee>
initialPageSize={20}
onRowClick={handleRowClick}
onCreateClick={handleCreateClick}
onEditClick={handleEditClick}
slots={{
dataGrid: CustomDataGrid,
}}
/>
) : null}
{pathname === createPath ? (
<Create<Employee>
initialValues={{ title: 'New Employee' }}
onSubmitSuccess={handleCreate}
resetOnSubmit={false}
/>
) : null}
{pathname !== createPath && showEmployeeId ? (
<Show<Employee> id={showEmployeeId} onEditClick={handleEditClick} onDelete={handleDelete} />
) : null}
{editEmployeeId ? <Edit<Employee> id={editEmployeeId} onSubmitSuccess={handleEdit} /> : null}
</CrudProvider>
);
}
21 changes: 20 additions & 1 deletion examples/core/auth-nextjs-themed/app/(dashboard)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
'use client';
import * as React from 'react';
import { DashboardLayout } from '@toolpad/core/DashboardLayout';
import { usePathname, useParams } from 'next/navigation';
import { PageContainer } from '@toolpad/core/PageContainer';
import Copyright from '../components/Copyright';
import SidebarFooterAccount, { ToolbarAccountOverride } from './SidebarFooterAccount';

export default function Layout(props: { children: React.ReactNode }) {
const pathname = usePathname();
const params = useParams();
const [employeeId] = params.segments ?? [];

const title = React.useMemo(() => {
if (pathname === '/employees/new') {
return 'New Employee';
}
if (employeeId && pathname.includes('/edit')) {
return `Employee ${employeeId} - Edit`;
}
if (employeeId) {
return `Employee ${employeeId}`;
}
return undefined;
}, [employeeId, pathname]);

return (
<DashboardLayout
slots={{
toolbarAccount: ToolbarAccountOverride,
sidebarFooter: SidebarFooterAccount,
}}
>
<PageContainer>
<PageContainer title={title}>
{props.children}
<Copyright sx={{ my: 4 }} />
</PageContainer>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use client';
import * as React from 'react';
import CustomDataGrid from '../../components/CustomDataGrid';
import { rows, columns } from '../../mocks/gridOrdersData';

export default function OrdersPage() {
return <CustomDataGrid />;
return <CustomDataGrid rows={rows} columns={columns} />;
}
24 changes: 14 additions & 10 deletions examples/core/auth-nextjs-themed/app/components/CustomDataGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
import * as React from 'react';
import { DataGrid } from '@mui/x-data-grid';
import { columns, rows } from '../mocks/gridOrdersData';
import { DataGrid, DataGridProps } from '@mui/x-data-grid';

export default function CustomizedDataGrid() {
export default function CustomizedDataGrid(props: DataGridProps) {
return (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<DataGrid
{...props}
checkboxSelection
rows={rows}
columns={columns}
getRowClassName={(params) => (params.indexRelativeToCurrentPage % 2 === 0 ? 'even' : 'odd')}
initialState={{
pagination: { paginationModel: { pageSize: 20 } },
}}
sx={(theme) => ({
borderColor:
sx={{
...props.sx,
borderColor: (theme) =>
theme.palette.mode === 'dark' ? theme.palette.grey[700] : theme.palette.grey[200],
'& .MuiDataGrid-cell': {
borderColor:
borderColor: (theme) =>
theme.palette.mode === 'dark' ? theme.palette.grey[700] : theme.palette.grey[200],
},
})}
}}
pageSizeOptions={[10, 20, 50]}
disableColumnResize
density="compact"
slotProps={{
filterPanel: {
sx: {
'& .MuiDataGrid-filterForm': {
columnGap: 1.5,
marginTop: 2,
},
},
filterFormProps: {
logicOperatorInputProps: {
variant: 'outlined',
Expand Down
7 changes: 7 additions & 0 deletions examples/core/auth-nextjs-themed/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { NextAppProvider } from '@toolpad/core/nextjs';
import PersonIcon from '@mui/icons-material/Person';
import DashboardIcon from '@mui/icons-material/Dashboard';
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';
Expand All @@ -22,6 +23,12 @@ const NAVIGATION: Navigation = [
title: 'Orders',
icon: <ShoppingCartIcon />,
},
{
segment: 'employees',
title: 'Employees',
icon: <PersonIcon />,
pattern: 'employees{/:employeeId}*',
},
];

const AUTHENTICATION = {
Expand Down
Loading