Company › Department › Employee | Employees › Birth date |
---|---|
export default function NestedTablesExampleAsyncWithSorting() {const [expandedRecordIds, setExpandedRecordIds] = useState<string[]>([]);const [sortStatus, setSortStatus] = useState<DataTableSortStatus>({ columnAccessor: 'name', direction: 'asc' });const { records, loading } = useCompaniesAsync({ sortStatus });const { cx, classes } = useStyles();return (<DataTableminHeight={160}withBorderwithColumnBordershighlightOnHoversortStatus={sortStatus}onSortStatusChange={setSortStatus}columns={[{accessor: 'name',sortable: true,title: 'Company › Department › Employee',render: ({ id, name }) => (<Group spacing="xs"><IconChevronRightsize="0.9em"className={cx(classes.expandIcon, {[classes.expandIconRotated]: expandedRecordIds.includes(id),})}/><IconBuilding size="0.9em" /><Text>{name}</Text></Group>),},{accessor: 'details',sortable: true,title: 'Employees › Birth date',render: ({ employees }) => employees,textAlignment: 'right',width: 200,},]}records={records}fetching={loading}rowExpansion={{allowMultiple: true,expanded: { recordIds: expandedRecordIds, onRecordIdsChange: setExpandedRecordIds },content: ({ record }) => <DepartmentsTable companyId={record.id} sortStatus={sortStatus} />,}}/>);}
function DepartmentsTable({ companyId, sortStatus }: { companyId: string; sortStatus: DataTableSortStatus }) {const { records, loading } = useDepartmentsAsync({ companyId, sortStatus });const [expandedRecordIds, setExpandedRecordIds] = useState<string[]>([]);const { cx, classes } = useStyles();return (<DataTablenoHeaderminHeight={100}columns={[{accessor: 'name',render: ({ id, name }) => (<Group ml="lg" spacing="xs" noWrap><IconChevronRightsize="0.9em"className={cx(classes.expandIcon, {[classes.expandIconRotated]: expandedRecordIds.includes(id),})}/><IconUsers size="0.9em" /><Text>{name}</Text></Group>),},{ accessor: 'employees', textAlignment: 'right', width: 200 },]}records={records}fetching={loading && !records.length}rowExpansion={{allowMultiple: true,expanded: { recordIds: expandedRecordIds, onRecordIdsChange: setExpandedRecordIds },content: ({ record }) => <EmployeesTable departmentId={record.id} sortStatus={sortStatus} />,}}/>);}
function EmployeesTable({ departmentId, sortStatus }: { departmentId: string; sortStatus: DataTableSortStatus }) {const { records, loading } = useEmployeesAsync({ departmentId, sortStatus });const { classes } = useStyles();return (<DataTablenoHeaderminHeight={100}columns={[{accessor: 'name',render: ({ firstName, lastName }) => (<Group spacing="xs" noWrap className={classes.employeeName}><IconUser size="0.9em" /><Text>{firstName} {lastName}</Text></Group>),},{accessor: 'birthDate',render: ({ birthDate }) => dayjs(birthDate).format('DD MMM YYYY'),textAlignment: 'right',width: 200,},]}records={records}fetching={loading && !records.length}/>);}
const useStyles = createStyles((theme) => ({expandIcon: {transition: 'transform 0.2s ease',},expandIconRotated: {transform: 'rotate(90deg)',},employeeName: {marginLeft: px(theme.spacing.xl) * 2,},}));
import { sortBy } from 'lodash';import { useEffect, useState } from 'react';import { DataTableSortStatus } from '~/../package';import delay from '~/lib/delay';import useIsMounted from '~/lib/useIsMounted';import { companies as companyData, departments as departmentData, employees } from './index';// Departments with employees countexport const departments = departmentData.map((department) => ({...department,employees: employees.filter((employee) => employee.department.id === department.id)?.length || 0,}));// Companies with employees countexport const companies = companyData.map((company) => ({...company,employees: departments.filter((department) => department.company.id === company.id).reduce((sum, department) => sum + department.employees, 0),}));// Employeesexport { employees };// Hook simulating async companies fetchingexport function useCompaniesAsync({ sortStatus }: { sortStatus: DataTableSortStatus }) {const isMounted = useIsMounted();const [records, setRecords] = useState<typeof companies>([]);const [loading, setLoading] = useState(true);useEffect(() => {if (isMounted()) {(async () => {setLoading(true);await delay({ min: 500, max: 800 });if (isMounted()) {const newRecords = sortBy(companies,sortStatus.columnAccessor === 'details' ? 'employees' : sortStatus.columnAccessor);if (sortStatus.direction === 'desc') newRecords.reverse();setRecords(newRecords);setLoading(false);}})();}}, [isMounted, sortStatus]);return { records, loading };}// Hook simulating async departments fetching by company idexport function useDepartmentsAsync({companyId,sortStatus,}: {companyId: string;sortStatus?: DataTableSortStatus;}) {const isMounted = useIsMounted();const [records, setRecords] = useState<typeof departments>([]);const [loading, setLoading] = useState(true);useEffect(() => {if (isMounted()) {(async () => {setLoading(true);await delay({ min: 500, max: 800 });if (isMounted()) {let newRecords = departments.filter((department) => department.company.id === companyId);if (sortStatus) {newRecords = sortBy(newRecords,sortStatus.columnAccessor === 'details' ? 'employees' : sortStatus.columnAccessor);if (sortStatus.direction === 'desc') newRecords.reverse();}setRecords(newRecords);setLoading(false);}})();}}, [companyId, isMounted, sortStatus]);return { records, loading };}// Hook simulating async employees fetching by department idexport function useEmployeesAsync({departmentId,sortStatus,}: {departmentId: string;sortStatus?: DataTableSortStatus;}) {const isMounted = useIsMounted();const [records, setRecords] = useState<typeof employees>([]);const [loading, setLoading] = useState(true);useEffect(() => {if (isMounted()) {(async () => {setLoading(true);await delay({ min: 500, max: 800 });if (isMounted()) {let newRecords = employees.filter((employee) => employee.department.id === departmentId);if (sortStatus) {newRecords = sortBy(newRecords,sortStatus.columnAccessor === 'name'? ({ firstName, lastName }) => `${firstName} ${lastName}`: 'birthDate');if (sortStatus.direction === 'desc') newRecords.reverse();}setRecords(newRecords);setLoading(false);}})();}}, [departmentId, isMounted, sortStatus]);return { records, loading };}