From d4f0020c2c81aa3ea868c086fc2e9d4c07865a05 Mon Sep 17 00:00:00 2001 From: jze9 Date: Sun, 12 Jul 2026 22:13:32 +0500 Subject: [PATCH] =?UTF-8?q?feat:=20=D1=84=D0=B8=D0=BB=D1=8C=D1=82=D1=80?= =?UTF-8?q?=D1=8B=20=D0=BB=D0=B5=D0=BD=D1=82=D1=8B=20=D1=81=D0=B8=D0=BD?= =?UTF-8?q?=D1=85=D1=80=D0=BE=D0=BD=D0=B8=D0=B7=D0=B8=D1=80=D1=83=D1=8E?= =?UTF-8?q?=D1=82=D1=81=D1=8F=20=D1=81=20URL=20(=D1=80=D0=B0=D1=81=D1=88?= =?UTF-8?q?=D0=B0=D1=80=D0=B8=D0=B2=D0=B0=D0=B5=D0=BC=D1=8B=D0=B5=20=D1=81?= =?UTF-8?q?=D1=81=D1=8B=D0=BB=D0=BA=D0=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NewsFeed читает category/tag/period/q из query-параметров при загрузке и пишет их обратно в URL при изменении фильтров. Теперь адрес в строке браузера — готовая ссылка: ?category=slug1,slug2 открывает ленту сразу с выбранными колледжами (для кнопок на внешнем сайте). Co-Authored-By: Claude Opus 4.8 --- web-react/src/pages/NewsFeed.jsx | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/web-react/src/pages/NewsFeed.jsx b/web-react/src/pages/NewsFeed.jsx index 57ffdc0..d59af4d 100644 --- a/web-react/src/pages/NewsFeed.jsx +++ b/web-react/src/pages/NewsFeed.jsx @@ -1,4 +1,5 @@ import React, { useState, useEffect, useCallback, useRef } from 'react' +import { useSearchParams } from 'react-router-dom' import { useTheme } from '../hooks/useTheme' import { getNews, getCategories, getTags, getArticle } from '../api/index' import NewsCard from '../components/NewsCard' @@ -19,6 +20,7 @@ function presetToDateFrom(preset) { export default function NewsFeed() { const { dark, toggle } = useTheme() + const [searchParams, setSearchParams] = useSearchParams() const [articles, setArticles] = useState([]) const [total, setTotal] = useState(0) const [categories, setCategories] = useState([]) @@ -26,15 +28,20 @@ export default function NewsFeed() { const [loading, setLoading] = useState(true) const [loadingMore, setLoadingMore] = 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 busyRef = useRef(false) const sentinelRef = useRef(null) - // Поиск с debounce - const [searchInput, setSearchInput] = useState('') - const [searchQuery, setSearchQuery] = useState('') + // Поиск с debounce (тоже инициализируется из URL) + const [searchInput, setSearchInput] = useState(() => searchParams.get('q') || '') + const [searchQuery, setSearchQuery] = useState(() => searchParams.get('q') || '') const debounceRef = useRef(null) const handleSearch = e => { @@ -68,6 +75,16 @@ export default function NewsFeed() { return params }, [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(() => { let cancelled = false