Skip to content

Commit 9a62b46

Browse files
fix(sorting): update handleSort to support dropdown sorting behavior and prevent rapid clicks
1 parent 02639af commit 9a62b46

File tree

3 files changed

+33
-19
lines changed

3 files changed

+33
-19
lines changed

dashboard/src/components/users/columns.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ export const setupColumns = ({
1515
dir,
1616
}: {
1717
t: (key: string) => string
18-
handleSort: (column: string) => void
18+
handleSort: (column: string, fromDropdown?: boolean) => void
1919
filters: { sort: string; status?: string }
2020
handleStatusFilter: (value: string) => void
2121
dir: string
2222
}): ColumnDef<UserResponse>[] => [
2323
{
2424
accessorKey: 'username',
2525
header: () => (
26-
<button onClick={handleSort.bind(null, 'username')} className="flex w-full items-center gap-1 px-2 py-3">
26+
<button onClick={() => handleSort('username')} className="flex w-full items-center gap-1 px-2 py-3">
2727
<div className="text-xs">
2828
<span className="md:hidden">{t('users')}</span>
2929
<span className="hidden capitalize md:block">{t('username')}</span>
@@ -77,7 +77,7 @@ export const setupColumns = ({
7777
{/* Desktop expire sorting */}
7878
<div className="hidden items-center sm:flex">
7979
<span>/</span>
80-
<button className="flex w-full items-center gap-1 px-2 py-3" onClick={handleSort.bind(null, 'expire')}>
80+
<button className="flex w-full items-center gap-1 px-2 py-3" onClick={() => handleSort('expire')}>
8181
<div className="text-xs capitalize">
8282
<span className="md:hidden">{t('expire')}</span>
8383
<span className="hidden md:block">{t('expire')}</span>
@@ -115,7 +115,7 @@ export const setupColumns = ({
115115
{
116116
id: 'details',
117117
header: () => (
118-
<button className="flex w-full items-center gap-1 px-0 py-3" onClick={handleSort.bind(null, 'used_traffic')}>
118+
<button className="flex w-full items-center gap-1 px-0 py-3" onClick={() => handleSort('used_traffic')}>
119119
<div className="text-xs capitalize">
120120
<span className="md:hidden">{t('dataUsage')}</span>
121121
<span className="hidden md:block">{t('dataUsage')}</span>

dashboard/src/components/users/filters.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ interface FiltersProps {
6161
advanceSearchOnOpen: (status: boolean) => void
6262
advanceSearchForm?: UseFormReturn<Record<string, unknown>>
6363
onClearAdvanceSearch?: () => void
64-
handleSort?: (column: string) => void
64+
handleSort?: (column: string, fromDropdown?: boolean) => void
6565
}
6666

6767
export const Filters = ({ filters, onFilterChange, refetch, advanceSearchOnOpen, advanceSearchForm, onClearAdvanceSearch, handleSort }: FiltersProps) => {
@@ -196,7 +196,7 @@ export const Filters = ({ filters, onFilterChange, refetch, advanceSearchOnOpen,
196196
{section.items.map(item => (
197197
<DropdownMenuItem
198198
key={item.value}
199-
onClick={() => handleSort && handleSort(item.value)}
199+
onClick={() => handleSort && handleSort(item.value, true)}
200200
className={`whitespace-nowrap px-2 py-1.5 text-xs md:px-3 md:py-2 ${filters.sort === item.value ? 'bg-accent' : ''}`}
201201
>
202202
<section.icon className="mr-1.5 h-3 w-3 flex-shrink-0 md:mr-2 md:h-4 md:w-4" />

dashboard/src/components/users/users-table.tsx

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ const UsersTable = memo(() => {
126126
// Filters will trigger new queries automatically
127127

128128
const handleSort = useCallback(
129-
(column: string) => {
129+
(column: string, fromDropdown = false) => {
130130
// Prevent rapid clicking
131131
if (isSorting) return
132132

@@ -136,24 +136,38 @@ const UsersTable = memo(() => {
136136

137137
// Clean the column name in case it comes with prefix
138138
const cleanColumn = column.startsWith('-') ? column.slice(1) : column
139-
const isDescending = column.startsWith('-')
140139

141-
if (isDescending) {
142-
// User clicked on descending option
143-
if (filters.sort === '-' + cleanColumn) {
144-
// If already descending, reset to default
145-
newSort = '-created_at'
140+
if (fromDropdown) {
141+
// Dropdown behavior: click to sort, click again to reset
142+
if (column.startsWith('-')) {
143+
// Dropdown descending option clicked
144+
if (filters.sort === '-' + cleanColumn) {
145+
// If already descending, reset to default
146+
newSort = '-created_at'
147+
} else {
148+
// Set to descending
149+
newSort = '-' + cleanColumn
150+
}
146151
} else {
147-
// Set to descending
148-
newSort = '-' + cleanColumn
152+
// Dropdown ascending option clicked
153+
if (filters.sort === cleanColumn) {
154+
// If already ascending, reset to default
155+
newSort = '-created_at'
156+
} else {
157+
// Set to ascending
158+
newSort = cleanColumn
159+
}
149160
}
150161
} else {
151-
// User clicked on ascending option
162+
// Table column behavior: traditional 3-state cycling (asc → desc → asc)
152163
if (filters.sort === cleanColumn) {
153-
// If already ascending, reset to default
154-
newSort = '-created_at'
164+
// If currently ascending, make it descending
165+
newSort = '-' + cleanColumn
166+
} else if (filters.sort === '-' + cleanColumn) {
167+
// If currently descending, make it ascending
168+
newSort = cleanColumn
155169
} else {
156-
// Set to ascending
170+
// If different column or default, make it ascending
157171
newSort = cleanColumn
158172
}
159173
}

0 commit comments

Comments
 (0)