|
1 | 1 |
|
2 | 2 | 'use client'; |
3 | 3 |
|
| 4 | +import { useRouter, useSearchParams } from 'next/navigation'; |
4 | 5 | import { useTranslations } from 'next-intl'; |
5 | 6 | import { Title, BaseCardsBlock, Pagination, SearchInput, Filter, Button } from '@/components'; |
6 | 7 | import { BlogsPageMeta, BlogsPageData } from './page'; |
7 | | -import { useState, useMemo } from 'react'; |
| 8 | +import { useState, useMemo, useCallback } from 'react'; |
8 | 9 | import { getPressReleaseLink } from '@/lib/utils'; |
| 10 | +import { usePagination } from '@/hooks/usePagination'; |
9 | 11 | import clsx from 'clsx'; |
10 | 12 |
|
11 | 13 |
|
@@ -114,21 +116,29 @@ function transformBlogsData(resources: NonNullable<BlogsPageData>): TransformedR |
114 | 116 | }); |
115 | 117 | } |
116 | 118 |
|
| 119 | +function getSearchParamValues(params: URLSearchParams, key: string): string[] { |
| 120 | + const val = params.get(key); |
| 121 | + return val ? val.split(',').filter(Boolean) : []; |
| 122 | +} |
| 123 | + |
117 | 124 | type BlogsPageProps = { |
118 | 125 | data: BlogsPageData |
119 | 126 | pagination: BlogsPageMeta |
120 | 127 | } |
121 | 128 |
|
122 | 129 | export default function BlogPage({data, pagination: _pagination}: BlogsPageProps) { |
123 | 130 | const t = useTranslations('blog'); |
| 131 | + const router = useRouter(); |
| 132 | + const searchParams = useSearchParams(); |
124 | 133 | const allResources = useMemo(() => transformBlogsData(data), [data]); |
125 | 134 |
|
126 | | - const [searchQuery, setSearchQuery] = useState(''); |
127 | | - const [activeYears, setActiveYears] = useState<string[]>([]); |
128 | | - const [activeTypes, setActiveTypes] = useState<string[]>([]); |
129 | | - const [activeNewsletters, setActiveNewsletters] = useState<string[]>([]); |
| 135 | + const [searchQuery, setSearchQuery] = useState(searchParams.get('search') ?? ''); |
| 136 | + const [activeYears, setActiveYears] = useState<string[]>(() => getSearchParamValues(searchParams, 'years')); |
| 137 | + const [activeTypes, setActiveTypes] = useState<string[]>(() => getSearchParamValues(searchParams, 'types')); |
| 138 | + const [activeNewsletters, setActiveNewsletters] = useState<string[]>(() => getSearchParamValues(searchParams, 'newsletters')); |
130 | 139 | const [hideFilters, setHideFilters] = useState(true); |
131 | | - const [currentPage, setCurrentPage] = useState(1); |
| 140 | + |
| 141 | + const { currentPage, handlePageChange } = usePagination(1); |
132 | 142 |
|
133 | 143 | const pageSize = 12; |
134 | 144 |
|
@@ -163,37 +173,53 @@ export default function BlogPage({data, pagination: _pagination}: BlogsPageProps |
163 | 173 |
|
164 | 174 | const pageCount = Math.ceil(filteredResources.length / pageSize); |
165 | 175 |
|
| 176 | + const syncFiltersToUrl = useCallback((years: string[], types: string[], newsletters: string[], search: string, page: number) => { |
| 177 | + const params = new URLSearchParams(searchParams.toString()); |
| 178 | + if (years.length > 0) params.set('years', years.join(',')); |
| 179 | + else params.delete('years'); |
| 180 | + if (types.length > 0) params.set('types', types.join(',')); |
| 181 | + else params.delete('types'); |
| 182 | + if (newsletters.length > 0) params.set('newsletters', newsletters.join(',')); |
| 183 | + else params.delete('newsletters'); |
| 184 | + if (search) params.set('search', search); |
| 185 | + else params.delete('search'); |
| 186 | + if (page > 1) params.set('page', String(page)); |
| 187 | + else params.delete('page'); |
| 188 | + router.push(`?${params.toString()}`, { scroll: false }); |
| 189 | + }, [router, searchParams]); |
| 190 | + |
166 | 191 | const handleSearchChange = (e: any) => { |
167 | | - if (searchQuery !== e.value) { |
168 | | - setSearchQuery(e.value); |
169 | | - setCurrentPage(1); |
170 | | - } |
| 192 | + const query = e.value ?? ''; |
| 193 | + setSearchQuery(query); |
| 194 | + syncFiltersToUrl(activeYears, activeTypes, activeNewsletters, query, 1); |
171 | 195 | }; |
172 | 196 |
|
173 | 197 | const handleFilterClick = (e: any) => { |
174 | 198 | const filterValue = e.value as string; |
175 | 199 | const filterType = e.getAttribute('data-type'); |
176 | 200 |
|
| 201 | + let newYears = activeYears; |
| 202 | + let newTypes = activeTypes; |
| 203 | + let newNewsletters = activeNewsletters; |
| 204 | + |
177 | 205 | if (filterType === 'year') { |
178 | | - setActiveYears(prev => |
179 | | - prev.includes(filterValue) |
180 | | - ? prev.filter(v => v !== filterValue) |
181 | | - : [...prev, filterValue] |
182 | | - ); |
| 206 | + newYears = activeYears.includes(filterValue) |
| 207 | + ? activeYears.filter(v => v !== filterValue) |
| 208 | + : [...activeYears, filterValue]; |
| 209 | + setActiveYears(newYears); |
183 | 210 | } else if (filterType === 'type') { |
184 | | - setActiveTypes(prev => |
185 | | - prev.includes(filterValue) |
186 | | - ? prev.filter(v => v !== filterValue) |
187 | | - : [...prev, filterValue] |
188 | | - ); |
| 211 | + newTypes = activeTypes.includes(filterValue) |
| 212 | + ? activeTypes.filter(v => v !== filterValue) |
| 213 | + : [...activeTypes, filterValue]; |
| 214 | + setActiveTypes(newTypes); |
189 | 215 | } else if (filterType === 'newsletter') { |
190 | | - setActiveNewsletters(prev => |
191 | | - prev.includes(filterValue) |
192 | | - ? prev.filter(v => v !== filterValue) |
193 | | - : [...prev, filterValue] |
194 | | - ); |
| 216 | + newNewsletters = activeNewsletters.includes(filterValue) |
| 217 | + ? activeNewsletters.filter(v => v !== filterValue) |
| 218 | + : [...activeNewsletters, filterValue]; |
| 219 | + setActiveNewsletters(newNewsletters); |
195 | 220 | } |
196 | | - setCurrentPage(1); |
| 221 | + |
| 222 | + syncFiltersToUrl(newYears, newTypes, newNewsletters, searchQuery, 1); |
197 | 223 | }; |
198 | 224 |
|
199 | 225 | const yearFilters = [ |
@@ -295,7 +321,7 @@ export default function BlogPage({data, pagination: _pagination}: BlogsPageProps |
295 | 321 | <Pagination |
296 | 322 | pageCount={pageCount} |
297 | 323 | currentPage={currentPage} |
298 | | - setCurrentPage={setCurrentPage} |
| 324 | + setCurrentPage={handlePageChange} |
299 | 325 | className="mt-sm mb-lg mx-auto max-w-max" |
300 | 326 | color="black" |
301 | 327 | /> |
|
0 commit comments