feat: фильтры ленты синхронизируются с URL (расшариваемые ссылки)
NewsFeed читает category/tag/period/q из query-параметров при загрузке и пишет их обратно в URL при изменении фильтров. Теперь адрес в строке браузера — готовая ссылка: ?category=slug1,slug2 открывает ленту сразу с выбранными колледжами (для кнопок на внешнем сайте). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import React, { useState, useEffect, useCallback, useRef } from 'react'
|
import React, { useState, useEffect, useCallback, useRef } from 'react'
|
||||||
|
import { useSearchParams } from 'react-router-dom'
|
||||||
import { useTheme } from '../hooks/useTheme'
|
import { useTheme } from '../hooks/useTheme'
|
||||||
import { getNews, getCategories, getTags, getArticle } from '../api/index'
|
import { getNews, getCategories, getTags, getArticle } from '../api/index'
|
||||||
import NewsCard from '../components/NewsCard'
|
import NewsCard from '../components/NewsCard'
|
||||||
@@ -19,6 +20,7 @@ function presetToDateFrom(preset) {
|
|||||||
|
|
||||||
export default function NewsFeed() {
|
export default function NewsFeed() {
|
||||||
const { dark, toggle } = useTheme()
|
const { dark, toggle } = useTheme()
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams()
|
||||||
const [articles, setArticles] = useState([])
|
const [articles, setArticles] = useState([])
|
||||||
const [total, setTotal] = useState(0)
|
const [total, setTotal] = useState(0)
|
||||||
const [categories, setCategories] = useState([])
|
const [categories, setCategories] = useState([])
|
||||||
@@ -26,15 +28,20 @@ export default function NewsFeed() {
|
|||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
const [loadingMore, setLoadingMore] = useState(false)
|
const [loadingMore, setLoadingMore] = useState(false)
|
||||||
const [hasMore, setHasMore] = useState(false)
|
const [hasMore, setHasMore] = useState(false)
|
||||||
const [filters, setFilters] = useState({ category: [], tag: null, datePreset: '' })
|
// Начальное состояние фильтров читаем из URL — ссылка открывает ленту с этими колледжами
|
||||||
|
const [filters, setFilters] = useState(() => ({
|
||||||
|
category: (searchParams.get('category') || '').split(',').filter(Boolean),
|
||||||
|
tag: searchParams.get('tag') || null,
|
||||||
|
datePreset: searchParams.get('period') || '',
|
||||||
|
}))
|
||||||
|
|
||||||
const offsetRef = useRef(0)
|
const offsetRef = useRef(0)
|
||||||
const busyRef = useRef(false)
|
const busyRef = useRef(false)
|
||||||
const sentinelRef = useRef(null)
|
const sentinelRef = useRef(null)
|
||||||
|
|
||||||
// Поиск с debounce
|
// Поиск с debounce (тоже инициализируется из URL)
|
||||||
const [searchInput, setSearchInput] = useState('')
|
const [searchInput, setSearchInput] = useState(() => searchParams.get('q') || '')
|
||||||
const [searchQuery, setSearchQuery] = useState('')
|
const [searchQuery, setSearchQuery] = useState(() => searchParams.get('q') || '')
|
||||||
const debounceRef = useRef(null)
|
const debounceRef = useRef(null)
|
||||||
|
|
||||||
const handleSearch = e => {
|
const handleSearch = e => {
|
||||||
@@ -68,6 +75,16 @@ export default function NewsFeed() {
|
|||||||
return params
|
return params
|
||||||
}, [filters, searchQuery])
|
}, [filters, searchQuery])
|
||||||
|
|
||||||
|
// Синхронизируем фильтры/поиск в URL, чтобы адрес можно было скопировать и расшарить
|
||||||
|
useEffect(() => {
|
||||||
|
const p = {}
|
||||||
|
if (filters.category.length) p.category = filters.category.join(',')
|
||||||
|
if (filters.tag) p.tag = filters.tag
|
||||||
|
if (filters.datePreset) p.period = filters.datePreset
|
||||||
|
if (searchQuery) p.q = searchQuery
|
||||||
|
setSearchParams(p, { replace: true })
|
||||||
|
}, [filters, searchQuery, setSearchParams])
|
||||||
|
|
||||||
// Сброс и первая загрузка при смене фильтров/поиска
|
// Сброс и первая загрузка при смене фильтров/поиска
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false
|
let cancelled = false
|
||||||
|
|||||||
Reference in New Issue
Block a user