Skip to content

Commit 453427d

Browse files
committed
feat: KeyValueTable - implement sorting functionality
1 parent 2090a19 commit 453427d

File tree

2 files changed

+66
-15
lines changed

2 files changed

+66
-15
lines changed

src/Shared/Components/KeyValueTable/KeyValueTable.component.tsx

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,16 @@
1616

1717
import { useEffect, useMemo, useState } from 'react'
1818

19+
import { useEffectAfterMount } from '@Common/Helper'
1920
import { useStateFilters } from '@Common/Hooks'
2021

2122
import { DynamicDataTable } from '../DynamicDataTable'
22-
import { KeyValueTableDataType, KeyValueTableInternalProps, KeyValueTableProps } from './KeyValueTable.types'
23+
import {
24+
KeyValueTableDataType,
25+
KeyValueTableInternalProps,
26+
KeyValueTableProps,
27+
KeyValueTableRowType,
28+
} from './KeyValueTable.types'
2329
import {
2430
getEmptyRow,
2531
getKeyValueHeaders,
@@ -49,6 +55,7 @@ export const KeyValueTable = ({
4955
}: KeyValueTableProps) => {
5056
// STATES
5157
const [cellError, setCellError] = useState<KeyValueTableInternalProps['cellError']>({})
58+
const [sortedRows, setSortedRows] = useState<KeyValueTableInternalProps['rows']>([])
5259

5360
// HOOKS
5461
const { sortBy, sortOrder, handleSorting } = useStateFilters<KeyValueTableDataType>({
@@ -61,8 +68,21 @@ export const KeyValueTable = ({
6168
[initialRows, placeholder, maskValue, isSortable, sortOrder, sortBy],
6269
)
6370

64-
// Set cell error on mount
71+
/** Function to update the sorted rows based on the current sorting configuration */
72+
const updateSortedRows = () => {
73+
if (isSortable) {
74+
setSortedRows(
75+
getKeyValueTableSortedRows({
76+
rows,
77+
sortBy,
78+
sortOrder,
79+
}),
80+
)
81+
}
82+
}
83+
6584
useEffect(() => {
85+
// Set cell error on mount
6686
const { isValid, updatedCellError } = getKeyValueTableCellError({
6787
rows,
6888
validateDuplicateKeys,
@@ -72,8 +92,46 @@ export const KeyValueTable = ({
7292

7393
setCellError(updatedCellError)
7494
onError?.(!isValid)
95+
96+
// Set sorted rows on mount
97+
updateSortedRows()
7598
}, [])
7699

100+
// Sort rows for display purposes only. \
101+
// The `sortedRows` state is used internally to render the data, while the original `rows` prop remains unaltered during sorting.
102+
useEffectAfterMount(() => {
103+
if (isSortable) {
104+
// Create a map of rows using their IDs for quick lookup
105+
const rowMap = rows.reduce<Record<KeyValueTableRowType['id'], KeyValueTableInternalProps['rows'][number]>>(
106+
(acc, row) => {
107+
acc[row.id] = row
108+
return acc
109+
},
110+
{},
111+
)
112+
113+
// Create a set of IDs from the currently sorted rows for efficient lookup
114+
const sortedRowSet = new Set(sortedRows.map(({ id }) => id))
115+
116+
// Update the sorted rows by filtering out rows that no longer exist and mapping them to the latest data
117+
const updatedSortedRows = sortedRows.filter(({ id }) => rowMap[id]).map(({ id }) => rowMap[id])
118+
119+
// Identify rows that are not part of the current sorted set (new or unsorted rows)
120+
const unsortedRows = rows.filter(({ id }) => !sortedRowSet.has(id))
121+
122+
// Combine unsorted rows with updated sorted rows and set them as the new sorted rows
123+
setSortedRows([...unsortedRows, ...updatedSortedRows])
124+
} else {
125+
// If sorting is disabled, directly set the rows as the sorted rows
126+
setSortedRows(rows)
127+
}
128+
}, [rows])
129+
130+
// Update the sorted rows whenever the sorting configuration changes
131+
useEffectAfterMount(() => {
132+
updateSortedRows()
133+
}, [sortBy, sortOrder])
134+
77135
// METHODS
78136
const setUpdatedRows = (updatedRows: typeof rows) => {
79137
const { isValid, updatedCellError } = getKeyValueTableCellError({
@@ -124,7 +182,7 @@ export const KeyValueTable = ({
124182
return (
125183
<DynamicDataTable
126184
headers={getKeyValueHeaders({ headerLabel, isSortable })}
127-
rows={getKeyValueTableSortedRows({ isSortable, rows, sortBy, sortOrder })}
185+
rows={sortedRows}
128186
cellError={showError ? cellError : {}}
129187
onRowAdd={onRowAdd}
130188
onRowDelete={onRowDelete}

src/Shared/Components/KeyValueTable/utils.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,14 @@ export const getKeyValueTableRows = ({
6464
}
6565

6666
export const getKeyValueTableSortedRows = ({
67-
isSortable,
6867
rows,
6968
sortBy,
7069
sortOrder,
71-
}: Required<Pick<KeyValueTableProps, 'isSortable'>> &
72-
Required<Pick<UseStateFiltersReturnType<KeyValueTableDataType>, 'sortBy' | 'sortOrder'>> &
73-
Pick<KeyValueTableInternalProps, 'rows'>) => {
74-
if (isSortable) {
75-
return rows
76-
.map((item) => item)
77-
.sort((a, b) => stringComparatorBySortOrder(a.data[sortBy].value, b.data[sortBy].value, sortOrder))
78-
}
79-
80-
return rows
81-
}
70+
}: Required<Pick<UseStateFiltersReturnType<KeyValueTableDataType>, 'sortBy' | 'sortOrder'>> &
71+
Pick<KeyValueTableInternalProps, 'rows'>) =>
72+
rows
73+
.map((item) => item)
74+
.sort((a, b) => stringComparatorBySortOrder(a.data[sortBy].value, b.data[sortBy].value, sortOrder))
8275

8376
export const getKeyValueHeaders = ({
8477
headerLabel,

0 commit comments

Comments
 (0)