Skip to content

Commit 0aff0e1

Browse files
committed
refactor: support checkboxes in BaseTable
add better support for checkboxes in the `BaseTable` as the previous implementation inside of `TableAction` was a mess.
1 parent 25e257b commit 0aff0e1

File tree

8 files changed

+207
-280
lines changed

8 files changed

+207
-280
lines changed

src/components/tables/AdminReviewsTable.tsx

Lines changed: 35 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import {
2-
CheckboxGroup,
32
Flex,
43
Td,
54
Text,
@@ -18,6 +17,7 @@ import { dateFormatGeneral } from "@/utils";
1817
import { getReviewStatus } from "@/utils/review";
1918
import { format } from "date-fns";
2019
import { useHasPermission } from "@/hooks/useHasPermissions";
20+
import { useRouter } from "next/router";
2121

2222
const tableStructure = [
2323
{
@@ -114,23 +114,23 @@ type Props = {
114114
refetch: () => void;
115115
};
116116

117-
type AdminResetSelectProps = {
118-
children: (props: {
119-
handleReset: () => Promise<void>;
120-
hasAdminSelected: boolean;
121-
isResetting: boolean;
122-
}) => React.ReactNode;
123-
};
124-
const AdminResetSelect = ({ children }: AdminResetSelectProps) => {
117+
const AdminReviewsTable = ({
118+
isLoading,
119+
isError,
120+
hasFilters,
121+
reviews,
122+
}: Props) => {
125123
const [selectedIds, setSelectedIds] = useState<string[]>([]);
126124
const toast = useToast();
125+
const router = useRouter();
127126
const { data: userSession } = useSession();
128127

129128
const queryClient = useQueryClient();
130129
const resetReview = useResetReview();
131-
const handleCheckboxToggle = (values: (string | number)[]) => {
132-
setSelectedIds(values.map(String));
133-
};
130+
131+
const canResetReviews = useHasPermission("resetReviews");
132+
const { status } = router.query;
133+
134134
const handleReset = async () => {
135135
const ids = selectedIds.map(Number);
136136

@@ -164,46 +164,29 @@ const AdminResetSelect = ({ children }: AdminResetSelectProps) => {
164164
};
165165

166166
return (
167-
<CheckboxGroup colorScheme="orange" onChange={handleCheckboxToggle}>
168-
{children({
169-
handleReset,
170-
hasAdminSelected: selectedIds.length > 0,
171-
isResetting: resetReview.isLoading,
172-
})}
173-
</CheckboxGroup>
174-
);
175-
};
176-
177-
const AdminReviewsTable = ({
178-
isLoading,
179-
isError,
180-
hasFilters,
181-
reviews,
182-
}: Props) => {
183-
const canResetReviews = useHasPermission("resetReviews");
184-
return (
185-
<AdminResetSelect>
186-
{({ handleReset, hasAdminSelected, isResetting }) => (
187-
<BaseTable
188-
data={reviews}
189-
emptyView={<EmptyView hasFilters={hasFilters} />}
190-
isLoading={isLoading}
191-
isError={isError}
192-
tableStructure={tableStructure}
193-
showAdminControls={canResetReviews}
194-
actionItems={
195-
<>
196-
{hasAdminSelected && (
197-
<ResetButton
198-
isLoading={isResetting}
199-
handleRequest={handleReset}
200-
/>
201-
)}
202-
</>
203-
}
204-
/>
205-
)}
206-
</AdminResetSelect>
167+
<>
168+
<BaseTable
169+
data={reviews}
170+
emptyView={<EmptyView hasFilters={hasFilters} />}
171+
isLoading={isLoading}
172+
isError={isError}
173+
tableStructure={tableStructure}
174+
enableCheckboxes={canResetReviews && status == "active"}
175+
selectedRowIds={selectedIds}
176+
onSelectedRowIdsChange={setSelectedIds}
177+
getRowId={(row) => `${row.id}`}
178+
actionItems={
179+
<>
180+
{selectedIds.length > 0 && (
181+
<ResetButton
182+
isLoading={resetReview.isLoading}
183+
handleRequest={handleReset}
184+
/>
185+
)}
186+
</>
187+
}
188+
/>
189+
</>
207190
);
208191
};
209192

src/components/tables/BaseTable.tsx

Lines changed: 68 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
import { Box, Flex, Heading, Table, Tbody, Thead, Tr } from "@chakra-ui/react";
1+
import {
2+
Box,
3+
Checkbox,
4+
CheckboxGroup,
5+
Flex,
6+
Heading,
7+
Table,
8+
Tbody,
9+
Thead,
10+
Tr,
11+
Td,
12+
} from "@chakra-ui/react";
213
import {
314
QueryObserverResult,
415
RefetchOptions,
@@ -26,7 +37,10 @@ type Props<T> = {
2637
tableStructure: TableStructure<T>[];
2738
tableHeader?: string;
2839
tableHeaderComponent?: React.ReactNode;
29-
showAdminControls?: boolean;
40+
enableCheckboxes?: boolean;
41+
selectedRowIds?: string[];
42+
onSelectedRowIdsChange?: (selectedRowIds: string[]) => void;
43+
getRowId?: (row: T) => string;
3044
};
3145

3246
const BaseTable = <T extends object>({
@@ -38,7 +52,10 @@ const BaseTable = <T extends object>({
3852
tableStructure,
3953
tableHeader,
4054
tableHeaderComponent,
41-
showAdminControls = false,
55+
enableCheckboxes = false, // Default to no checkboxes
56+
selectedRowIds = [],
57+
onSelectedRowIdsChange: setSelectedIds,
58+
getRowId,
4259
}: Props<T>) => {
4360
return (
4461
<Box fontSize="sm" py={4} isolation="isolate">
@@ -53,58 +70,70 @@ const BaseTable = <T extends object>({
5370
{actionItems}
5471
{refetch && <RefetchButton refetch={refetch} />}
5572
</Flex>
56-
<Table
57-
boxShadow="lg"
58-
borderTop="4px solid"
59-
borderTopColor="orange.400"
60-
borderRadius="xl"
73+
<CheckboxGroup
74+
colorScheme="orange"
75+
value={selectedRowIds}
76+
onChange={setSelectedIds}
6177
>
62-
<Thead>
63-
<TableHeader tableStructure={tableStructure} />
64-
</Thead>
65-
<Tbody fontWeight="medium">
66-
{isLoading ? (
67-
<LoadingSkeleton rowsLength={tableStructure.length} />
68-
) : !data ? (
69-
<DataEmpty />
70-
) : data?.length ? (
71-
data.map((dataRow, idx) => (
72-
<TableRow
73-
showControls={showAdminControls}
74-
key={`data-id-${
75-
"id" in dataRow ? dataRow.id : ""
76-
}-data-row-${idx}`}
77-
row={dataRow}
78-
ts={tableStructure}
78+
<Table
79+
boxShadow="lg"
80+
borderTop="4px solid"
81+
borderTopColor="orange.400"
82+
borderRadius="xl"
83+
>
84+
<Thead>
85+
<TableHeader
86+
tableStructure={tableStructure}
87+
showCheckboxes={enableCheckboxes}
88+
/>
89+
</Thead>
90+
<Tbody fontWeight="medium">
91+
{isLoading ? (
92+
<LoadingSkeleton
93+
rowsLength={tableStructure.length + (enableCheckboxes ? 1 : 0)}
7994
/>
80-
))
81-
) : (
82-
<DataEmpty message={emptyView} />
83-
)}
84-
</Tbody>
85-
</Table>
95+
) : !data ? (
96+
<DataEmpty />
97+
) : data?.length ? (
98+
data.map((dataRow, idx) => (
99+
<TableRow
100+
key={getRowId ? getRowId(dataRow) : idx}
101+
row={dataRow}
102+
ts={tableStructure}
103+
enableCheckboxes={enableCheckboxes}
104+
rowId={getRowId ? getRowId(dataRow) : `${idx}`}
105+
/>
106+
))
107+
) : (
108+
<DataEmpty message={emptyView} />
109+
)}
110+
</Tbody>
111+
</Table>
112+
</CheckboxGroup>
86113
</Box>
87114
);
88115
};
89116

90117
const TableRow = <T extends object>({
91118
row,
92119
ts,
93-
showControls,
120+
enableCheckboxes,
121+
rowId,
94122
}: {
95123
row: T;
96124
ts: TableStructure<T>[];
97-
showControls: boolean;
125+
enableCheckboxes: boolean;
126+
rowId: string;
98127
}) => {
99128
return (
100129
<Tr>
130+
{enableCheckboxes && (
131+
<Td>
132+
<Checkbox value={rowId} key={rowId} width="1%" />
133+
</Td>
134+
)}
101135
{ts.map((tableItem) => (
102-
<RowData
103-
showControls={showControls}
104-
key={tableItem.name}
105-
tableItem={tableItem}
106-
row={row}
107-
/>
136+
<RowData key={tableItem.name} tableItem={tableItem} row={row} />
108137
))}
109138
</Tr>
110139
);

0 commit comments

Comments
 (0)