Skip to content

Commit 9c0f234

Browse files
committed
use hooks
1 parent 277cd72 commit 9c0f234

File tree

4 files changed

+244
-269
lines changed

4 files changed

+244
-269
lines changed

src/components/ChangelogFilters/ChangelogFilters.tsx

Lines changed: 2 additions & 199 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import styles from "./styles.module.css"
2-
import { useState, useEffect } from "react"
32
import type { ChangelogItem } from "~/components/ChangelogSnippet/types.ts"
4-
import { matchesFilters } from "~/utils/changelogFilters.ts"
5-
import { parseURLParams, updateFilterURL, toggleItemInArray } from "~/utils/changelogFilterUtils.ts"
63
import { DesktopFilters } from "./DesktopFilters.tsx"
74
import { MobileFilters } from "./MobileFilters.tsx"
85

@@ -14,207 +11,13 @@ export interface ChangelogFiltersProps {
1411
}
1512

1613
export const ChangelogFilters = ({ products, networks, types, items }: ChangelogFiltersProps) => {
17-
const [searchExpanded, setSearchExpanded] = useState(false)
18-
const [searchTerm, setSearchTerm] = useState("")
19-
const [selectedProducts, setSelectedProducts] = useState<string[]>([])
20-
const [selectedNetworks, setSelectedNetworks] = useState<string[]>([])
21-
const [selectedTypes, setSelectedTypes] = useState<string[]>([])
22-
23-
// Read URL parameters on mount
24-
useEffect(() => {
25-
const urlParams = parseURLParams()
26-
27-
setSelectedProducts(urlParams.products)
28-
setSelectedNetworks(urlParams.networks)
29-
setSelectedTypes(urlParams.types)
30-
setSearchTerm(urlParams.searchTerm)
31-
setSearchExpanded(urlParams.searchExpanded)
32-
}, [])
33-
34-
// Update URL when filters change
35-
useEffect(() => {
36-
updateFilterURL(selectedProducts, selectedNetworks, selectedTypes, searchTerm)
37-
}, [selectedProducts, selectedNetworks, selectedTypes, searchTerm])
38-
39-
// Filter items and update the display
40-
useEffect(() => {
41-
if (typeof window === "undefined") return
42-
43-
const changelogItems = document.querySelectorAll(".changelog-item")
44-
const loadMoreSection = document.querySelector(".load-more-section") as HTMLElement
45-
const visibleCountSpan = document.getElementById("visible-count")
46-
const emptyState = document.querySelector(".empty-state") as HTMLElement
47-
const changelogList = document.querySelector(".changelog-list") as HTMLElement
48-
49-
if (searchTerm) {
50-
// Search takes priority - filter by search term
51-
const searchLower = searchTerm.toLowerCase()
52-
let visibleCount = 0
53-
54-
changelogItems.forEach((item) => {
55-
const index = parseInt(item.getAttribute("data-index") || "0")
56-
const changelogItem = items[index]
57-
58-
const matchesSearch =
59-
changelogItem?.name.toLowerCase().includes(searchLower) ||
60-
changelogItem?.["text-description"]?.toLowerCase().includes(searchLower)
61-
62-
if (matchesSearch) {
63-
;(item as HTMLElement).style.display = ""
64-
visibleCount++
65-
} else {
66-
;(item as HTMLElement).style.display = "none"
67-
}
68-
})
69-
70-
// Hide load more section when searching
71-
if (loadMoreSection) {
72-
loadMoreSection.style.display = "none"
73-
}
74-
75-
// Show/hide empty state
76-
if (emptyState && changelogList) {
77-
if (visibleCount === 0) {
78-
emptyState.style.display = "flex"
79-
changelogList.style.display = "none"
80-
} else {
81-
emptyState.style.display = "none"
82-
changelogList.style.display = "flex"
83-
}
84-
}
85-
} else {
86-
// Apply filter logic
87-
let visibleCount = 0
88-
const hasFilters = selectedProducts.length > 0 || selectedNetworks.length > 0 || selectedTypes.length > 0
89-
90-
changelogItems.forEach((item) => {
91-
const index = parseInt(item.getAttribute("data-index") || "0")
92-
const changelogItem = items[index]
93-
94-
if (hasFilters && changelogItem) {
95-
const matches = matchesFilters(changelogItem, selectedProducts, selectedNetworks, selectedTypes)
96-
if (matches) {
97-
;(item as HTMLElement).style.display = ""
98-
visibleCount++
99-
} else {
100-
;(item as HTMLElement).style.display = "none"
101-
}
102-
} else {
103-
// No filters - show first 25 items by default
104-
if (visibleCount < 25) {
105-
;(item as HTMLElement).style.display = ""
106-
visibleCount++
107-
} else {
108-
;(item as HTMLElement).style.display = "none"
109-
}
110-
}
111-
})
112-
113-
// Show/hide load more section based on filters
114-
if (loadMoreSection) {
115-
if (hasFilters) {
116-
loadMoreSection.style.display = "none"
117-
} else {
118-
loadMoreSection.style.display = visibleCount >= items.length ? "none" : "flex"
119-
}
120-
}
121-
122-
// Update visible count
123-
if (visibleCountSpan) {
124-
visibleCountSpan.textContent = visibleCount.toString()
125-
}
126-
127-
// Show/hide empty state
128-
if (emptyState && changelogList) {
129-
if (hasFilters && visibleCount === 0) {
130-
emptyState.style.display = "flex"
131-
changelogList.style.display = "none"
132-
} else {
133-
emptyState.style.display = "none"
134-
changelogList.style.display = "flex"
135-
}
136-
}
137-
}
138-
}, [searchTerm, selectedProducts, selectedNetworks, selectedTypes, items])
139-
140-
const handleSearchChange = (value: string) => {
141-
setSearchTerm(value)
142-
}
143-
144-
const handleSearchToggle = (expanded: boolean) => {
145-
setSearchExpanded(expanded)
146-
}
147-
148-
const toggleSelection = (type: "product" | "network" | "type", value: string) => {
149-
switch (type) {
150-
case "product":
151-
setSelectedProducts((prev) => toggleItemInArray(prev, value))
152-
break
153-
case "network":
154-
setSelectedNetworks((prev) => toggleItemInArray(prev, value))
155-
break
156-
case "type":
157-
setSelectedTypes((prev) => toggleItemInArray(prev, value))
158-
break
159-
}
160-
}
161-
162-
const clearProductFilters = () => {
163-
setSelectedProducts([])
164-
}
165-
166-
const clearNetworkFilters = () => {
167-
setSelectedNetworks([])
168-
}
169-
170-
const clearTypeFilters = () => {
171-
setSelectedTypes([])
172-
}
173-
174-
const clearAllFilters = () => {
175-
setSelectedProducts([])
176-
setSelectedNetworks([])
177-
setSelectedTypes([])
178-
}
179-
18014
return (
18115
<div className={styles.wrapper}>
18216
<div className={styles.desktopFilters}>
183-
<DesktopFilters
184-
products={products}
185-
networks={networks}
186-
types={types}
187-
selectedProducts={selectedProducts}
188-
selectedNetworks={selectedNetworks}
189-
selectedTypes={selectedTypes}
190-
onToggleSelection={toggleSelection}
191-
onClearProducts={clearProductFilters}
192-
onClearNetworks={clearNetworkFilters}
193-
onClearTypes={clearTypeFilters}
194-
searchTerm={searchTerm}
195-
searchExpanded={searchExpanded}
196-
onSearchChange={handleSearchChange}
197-
onSearchToggle={handleSearchToggle}
198-
/>
17+
<DesktopFilters products={products} networks={networks} types={types} items={items} />
19918
</div>
20019
<div className={styles.mobileFilters}>
201-
<MobileFilters
202-
products={products}
203-
networks={networks}
204-
types={types}
205-
selectedProducts={selectedProducts}
206-
selectedNetworks={selectedNetworks}
207-
selectedTypes={selectedTypes}
208-
onToggleSelection={toggleSelection}
209-
onClearProducts={clearProductFilters}
210-
onClearNetworks={clearNetworkFilters}
211-
onClearTypes={clearTypeFilters}
212-
onClearAll={clearAllFilters}
213-
searchTerm={searchTerm}
214-
searchExpanded={searchExpanded}
215-
onSearchChange={handleSearchChange}
216-
onSearchToggle={handleSearchToggle}
217-
/>
20+
<MobileFilters products={products} networks={networks} types={types} items={items} />
21821
</div>
21922
</div>
22023
)

src/components/ChangelogFilters/DesktopFilters.tsx

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { SvgSearch, SvgTaillessArrowDownSmall, SvgX } from "@chainlink/blocks"
22
import styles from "./styles.module.css"
33
import { useState } from "react"
44
import { clsx } from "~/lib/clsx/clsx.ts"
5+
import type { ChangelogItem } from "~/components/ChangelogSnippet/types.ts"
6+
import { useChangelogFilters } from "./useChangelogFilters.ts"
57

68
type FilterType = "product" | "network" | "type" | null
79

@@ -114,37 +116,26 @@ interface DesktopFiltersProps {
114116
products: string[]
115117
networks: string[]
116118
types: string[]
117-
selectedProducts: string[]
118-
selectedNetworks: string[]
119-
selectedTypes: string[]
120-
onToggleSelection: (type: "product" | "network" | "type", value: string) => void
121-
onClearProducts: () => void
122-
onClearNetworks: () => void
123-
onClearTypes: () => void
124-
searchTerm: string
125-
searchExpanded: boolean
126-
onSearchChange: (value: string) => void
127-
onSearchToggle: (expanded: boolean) => void
119+
items: ChangelogItem[]
128120
}
129121

130-
export const DesktopFilters = ({
131-
products,
132-
networks,
133-
types,
134-
selectedProducts,
135-
selectedNetworks,
136-
selectedTypes,
137-
onToggleSelection,
138-
onClearProducts,
139-
onClearNetworks,
140-
onClearTypes,
141-
searchTerm,
142-
searchExpanded,
143-
onSearchChange,
144-
onSearchToggle,
145-
}: DesktopFiltersProps) => {
122+
export const DesktopFilters = ({ products, networks, types, items }: DesktopFiltersProps) => {
146123
const [activeFilter, setActiveFilter] = useState<FilterType>(null)
147124

125+
const {
126+
searchExpanded,
127+
searchTerm,
128+
selectedProducts,
129+
selectedNetworks,
130+
selectedTypes,
131+
handleSearchChange,
132+
handleSearchToggle,
133+
toggleSelection,
134+
clearProductFilters,
135+
clearNetworkFilters,
136+
clearTypeFilters,
137+
} = useChangelogFilters({ products, networks, types, items })
138+
148139
const toggleFilter = (filterType: FilterType) => {
149140
setActiveFilter(filterType)
150141
}
@@ -190,7 +181,7 @@ export const DesktopFilters = ({
190181
isSelected={getSelectedValues().includes(option)}
191182
onClick={() => {
192183
const type = activeFilter as "product" | "network" | "type"
193-
onToggleSelection(type, option)
184+
toggleSelection(type, option)
194185
}}
195186
/>
196187
))}
@@ -205,27 +196,27 @@ export const DesktopFilters = ({
205196
isActive={activeFilter === "product"}
206197
onClick={() => toggleFilter("product")}
207198
onClose={closeFilter}
208-
onClearAll={onClearProducts}
199+
onClearAll={clearProductFilters}
209200
/>
210201
<Trigger
211202
label="Network"
212203
count={selectedNetworks.length}
213204
isActive={activeFilter === "network"}
214205
onClick={() => toggleFilter("network")}
215206
onClose={closeFilter}
216-
onClearAll={onClearNetworks}
207+
onClearAll={clearNetworkFilters}
217208
/>
218209
<Trigger
219210
label="Type"
220211
count={selectedTypes.length}
221212
isActive={activeFilter === "type"}
222213
onClick={() => toggleFilter("type")}
223214
onClose={closeFilter}
224-
onClearAll={onClearTypes}
215+
onClearAll={clearTypeFilters}
225216
/>
226217
</>
227218
)}
228-
<SearchInput isExpanded={searchExpanded} onClick={onSearchToggle} value={searchTerm} onChange={onSearchChange} />
219+
<SearchInput isExpanded={searchExpanded} onClick={handleSearchToggle} value={searchTerm} onChange={handleSearchChange} />
229220
</div>
230221
</>
231222
)

0 commit comments

Comments
 (0)