russ_react/src/components/FeaturedSection.tsx

92 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useState, useMemo } from 'react';
import { useLocation, useSearchParams } from 'react-router-dom';
import { ArticleCard } from './ArticleCard';
import { Pagination } from './Pagination';
import { articles } from '../data/mock';
import { getCategoryId } from '../utils/categories';
import { CategoryName } from '../types';
const ARTICLES_PER_PAGE = 6;
export function FeaturedSection() {
const location = useLocation();
const [searchParams, setSearchParams] = useSearchParams();
const categoryParam = searchParams.get('category') as CategoryName | null;
const city = searchParams.get('city');
const currentPage = parseInt(searchParams.get('page') || '1', 10);
const filteredArticles = useMemo(() => {
return articles.filter(article => {
if (categoryParam && city) {
return article.categoryId === getCategoryId(categoryParam) && article.city === city;
}
if (categoryParam) {
return article.categoryId === getCategoryId(categoryParam);
}
if (city) {
return article.city === city;
}
return true;
});
}, [categoryParam, city]);
const totalPages = Math.ceil(filteredArticles.length / ARTICLES_PER_PAGE);
const currentArticles = useMemo(() => {
const startIndex = (currentPage - 1) * ARTICLES_PER_PAGE;
return filteredArticles.slice(startIndex, startIndex + ARTICLES_PER_PAGE);
}, [filteredArticles, currentPage]);
const handlePageChange = (page: number) => {
searchParams.set('page', page.toString());
setSearchParams(searchParams);
window.scrollTo({ top: 0, behavior: 'smooth' });
};
if (filteredArticles.length === 0) {
return (
<section className="py-12 px-4 sm:px-6 lg:px-8 max-w-7xl mx-auto">
<div className="text-center py-12">
<h3 className="text-xl font-medium text-gray-900 mb-2">
Еще нет заметок
</h3>
<p className="text-gray-500">
Выберите другой раздел или город
</p>
</div>
</section>
);
}
return (
<section className="py-12 px-4 sm:px-6 lg:px-8 max-w-7xl mx-auto">
<div className="flex justify-between items-center mb-8">
<h2 className="text-3xl font-bold text-gray-900">
{city ? `${city} ` : ''}
{categoryParam ? `${categoryParam} Статьи` : 'Тематические статьи'}
</h2>
<p className="text-gray-600">
Показано {Math.min(currentPage * ARTICLES_PER_PAGE, filteredArticles.length)} из {filteredArticles.length} статей
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{currentArticles.map((article, index) => (
<ArticleCard
key={article.id}
article={article}
featured={currentPage === 1 && index === 0 && !categoryParam && !city}
/>
))}
</div>
{totalPages > 1 && (
<Pagination
currentPage={currentPage}
totalPages={totalPages}
onPageChange={handlePageChange}
/>
)}
</section>
);
}