-
Notifications
You must be signed in to change notification settings - Fork 44
Expand file tree
/
Copy pathuseSpaceSort.ts
More file actions
116 lines (100 loc) · 3.1 KB
/
useSpaceSort.ts
File metadata and controls
116 lines (100 loc) · 3.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { useState, useEffect } from 'react'
import type { Space } from '@storacha/ui-react'
/**
* Sort options for spaces list (name-based only)
*/
export type SortOption = 'name-asc' | 'name-desc'
const SORT_STORAGE_KEY = 'storacha_space_sort_option'
const VALID_SORT_OPTIONS: SortOption[] = ['name-asc', 'name-desc']
/**
* Hook to manage space sorting with localStorage persistence.
*
* - Persists the selected option in localStorage until logout.
* - Also updates URL query param when on home page for shareability.
*/
export function useSpaceSort() {
const [sortOption, setSortOption] = useState<SortOption>(() => {
if (typeof window === 'undefined') return 'name-asc'
try {
const stored = window.localStorage.getItem(SORT_STORAGE_KEY)
if (stored && VALID_SORT_OPTIONS.includes(stored as SortOption)) {
return stored as SortOption
}
} catch {
// ignore storage errors
}
try {
const url = new URL(window.location.href)
const sortParam = url.searchParams.get('sort')
if (sortParam && VALID_SORT_OPTIONS.includes(sortParam as SortOption)) {
try {
window.localStorage.setItem(SORT_STORAGE_KEY, sortParam)
} catch {
// ignore
}
return sortParam as SortOption
}
} catch {
// ignore URL errors
}
return 'name-asc'
})
useEffect(() => {
if (typeof window === 'undefined') return
try {
const stored = window.localStorage.getItem(SORT_STORAGE_KEY)
if (stored && VALID_SORT_OPTIONS.includes(stored as SortOption)) {
setSortOption((current) =>
current !== stored ? (stored as SortOption) : current
)
}
} catch {
// ignore
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
useEffect(() => {
if (typeof window === 'undefined') return
if (!VALID_SORT_OPTIONS.includes(sortOption)) return
try {
window.localStorage.setItem(SORT_STORAGE_KEY, sortOption)
} catch (e) {
console.warn('Failed to save sort option to localStorage:', e)
}
try {
const currentPath = window.location.pathname
if (currentPath === '/' || currentPath === '') {
const url = new URL(window.location.href)
if (sortOption === 'name-asc') {
url.searchParams.delete('sort')
} else {
url.searchParams.set('sort', sortOption)
}
window.history.replaceState(null, '', url.toString())
}
} catch (e) {
// ignore URL errors
}
}, [sortOption])
return {
sortOption,
setSortOption,
}
}
/**
* Sort spaces array by name (A-Z or Z-A).
*
* @param spaces - Array of spaces to sort
* @param sortOption - The sort option to apply
* @returns Sorted array of spaces
*/
export function sortSpaces(spaces: Space[], sortOption: SortOption): Space[] {
const sorted = [...spaces]
return sorted.sort((a, b) => {
const nameA = (a.name || a.did()).toLowerCase()
const nameB = (b.name || b.did()).toLowerCase()
return sortOption === 'name-desc'
? nameB.localeCompare(nameA)
: nameA.localeCompare(nameB)
})
}