Skip to content

Commit

Permalink
Refactor table and utilize memoization
Browse files Browse the repository at this point in the history
  • Loading branch information
samau3 committed Oct 27, 2024
1 parent ab089de commit 45996d2
Showing 1 changed file with 57 additions and 70 deletions.
127 changes: 57 additions & 70 deletions client/src/pages/patients/PatientsTable.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
import PropTypes from 'prop-types';

import { useState, useContext } from 'react';
import { Link } from 'react-router-dom';
import { Paper, Table, ActionIcon, Menu, Modal, Button } from '@mantine/core';
import { useState, useContext, useMemo, useCallback } from 'react';
import { Paper, Table, Modal, Button } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { useDeletePatient } from './useDeletePatient';
import { notifications } from '@mantine/notifications';
import {
IconDotsVertical,
IconUser,
IconQrcode,
IconTrash,
} from '@tabler/icons-react';
import classes from './Patients.module.css';
import Context from '../../Context';

import PatientTableRow from './PatientTableRow';

const patientTableProps = {
headers: PropTypes.arrayOf(
PropTypes.shape({
Expand All @@ -41,14 +36,16 @@ const patientTableProps = {
export default function PatientsTable({ headers, data }) {
const [opened, { open, close }] = useDisclosure(false);
const [selectedPatient, setSelectedPatient] = useState(null);
const { mutate: deletePatient } = useDeletePatient();
const { mutateAsync: deletePatient, isPending } = useDeletePatient();
const { user } = useContext(Context);

const showDeleteConfirmation = (patient) => {
setSelectedPatient(patient);
open();
};

const showDeleteConfirmation = useCallback(
(patient) => {
setSelectedPatient(patient);
open();
},
[open],
);
const confirmPatientDeletion = async () => {
try {
await deletePatient(selectedPatient.id);
Expand All @@ -65,9 +62,40 @@ export default function PatientsTable({ headers, data }) {
color: 'red',
});
}
if (!isPending) {
setSelectedPatient(null);
close();
}
};

const cancelPatientDeletion = () => {
setSelectedPatient(null);
close();
};

const emptyStateRow = useMemo(
() => (
<Table.Tr>
<Table.Td colSpan={headers.length}>No patients found.</Table.Td>
</Table.Tr>
),
[headers.length],
);

const headersMemo = useMemo(() => headers, [headers]);

const patientRows = useMemo(() => {
return data?.map((patient) => (
<PatientTableRow
key={patient.id}
patient={patient}
headers={headers}
onDelete={showDeleteConfirmation}
showDeleteMenu={user?.role === 'ADMIN'}
/>
));
}, [data, headers, user.role, showDeleteConfirmation]);

return (
<>
<Paper withBorder className={classes.tableWrapper}>
Expand All @@ -80,74 +108,33 @@ export default function PatientsTable({ headers, data }) {
>
<Table.Thead>
<Table.Tr>
{headers.map((header) => (
{headersMemo.map((header) => (
<Table.Th key={header.key}>{header.text}</Table.Th>
))}
</Table.Tr>
</Table.Thead>
<Table.Tbody>
{data?.length > 0 ? (
data?.map((patient) => (
<Table.Tr key={patient.id}>
{headers.map((header) => (
<Table.Td key={patient[header.key] + header.key}>
{patient[header.key]}
</Table.Td>
))}
<Table.Td>
<Menu shadow="md">
<Menu.Target>
<ActionIcon variant="subtle" color="gray">
<IconDotsVertical size={18} />
</ActionIcon>
</Menu.Target>
<Menu.Dropdown>
<Menu.Item
leftSection={<IconUser size={18} />}
component={Link}
to={`/patients/${patient.id}`}
>
View/Edit
</Menu.Item>
<Menu.Item leftSection={<IconQrcode size={18} />}>
Reprint QR Code
</Menu.Item>
{user?.role === 'ADMIN' && (
<Menu.Item
leftSection={<IconTrash size={18} />}
color="red"
onClick={() =>
showDeleteConfirmation({
id: patient.id,
name: patient.name,
})
}
>
Delete
</Menu.Item>
)}
</Menu.Dropdown>
</Menu>
</Table.Td>
</Table.Tr>
))
) : (
<Table.Tr>
<Table.Td colSpan={headers.length}>
No patients found.
</Table.Td>
</Table.Tr>
)}
{data?.length > 0 ? patientRows : emptyStateRow}
</Table.Tbody>
</Table>
</Table.ScrollContainer>
</Paper>
<Modal opened={opened} onClose={close} title="Delete Patient">
<p>Are you sure you want to delete this patient record?</p>
<Button color="red" fullWidth onClick={confirmPatientDeletion}>
<Button
color="red"
fullWidth
onClick={confirmPatientDeletion}
loading={isPending}
>
Yes
</Button>
<Button color="blue" fullWidth onClick={close}>
<Button
color="blue"
fullWidth
onClick={cancelPatientDeletion}
disabled={isPending}
>
No
</Button>
</Modal>
Expand Down

0 comments on commit 45996d2

Please sign in to comment.