108 lines
3.4 KiB
TypeScript
108 lines
3.4 KiB
TypeScript
import { useEffect, useState } from 'react';
|
||
import { useSearchParams } from 'react-router-dom';
|
||
import { ArticleCard } from './ArticleCard';
|
||
import { Pagination } from './Pagination';
|
||
import { Article, CategoryTitles, CityTitles } from '../types';
|
||
import axios from "axios";
|
||
|
||
|
||
const ARTICLES_PER_PAGE = 6;
|
||
|
||
export function FeaturedSection() {
|
||
const [searchParams, setSearchParams] = useSearchParams();
|
||
const category = searchParams.get('category');
|
||
const city = searchParams.get('city');
|
||
const currentPage = Math.max(1, parseInt(searchParams.get('page') || '1', 10));
|
||
const [articles, setArticles] = useState<Article[]>([]);
|
||
const [totalPages, setTotalPages] = useState(1);
|
||
const [totalArticles, setTotalArticles] = useState(0);
|
||
const [error, setError] = useState<string | null>(null);
|
||
|
||
// Загрузка статей
|
||
useEffect(() => {
|
||
const fetchArticles = async () => {
|
||
try {
|
||
const response = await axios.get('/api/articles/', {
|
||
params: {
|
||
page: currentPage,
|
||
categoryId: category || undefined,
|
||
cityId: city || undefined,
|
||
},
|
||
});
|
||
console.log(response.data.articles[0]);
|
||
|
||
setArticles(response.data.articles);
|
||
setTotalPages(response.data.totalPages);
|
||
setTotalArticles(response.data.total);
|
||
} catch (error) {
|
||
setError('Не удалось загрузить статьи');
|
||
console.error(error);
|
||
}
|
||
};
|
||
|
||
fetchArticles();
|
||
}, [category, city, currentPage]);
|
||
|
||
const handlePageChange = (page: number) => {
|
||
searchParams.set('page', page.toString());
|
||
setSearchParams(searchParams);
|
||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||
};
|
||
|
||
if (articles.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>
|
||
);
|
||
}
|
||
|
||
const shouldShowFeatured = currentPage === 1 && !category && !city;
|
||
|
||
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 ? `${CityTitles[Number(city)]} ` : ''}
|
||
{category ? `${CategoryTitles[Number(category)]}` : 'Читайте сегодня'}
|
||
</h2>
|
||
<p className="font-bold text-gray-600">
|
||
Статьи {Math.min((currentPage - 1) * ARTICLES_PER_PAGE + 1, totalArticles)}
|
||
-
|
||
{Math.min(currentPage * ARTICLES_PER_PAGE, totalArticles)} из {totalArticles}
|
||
</p>
|
||
</div>
|
||
|
||
{error && (
|
||
<div className="mb-6 bg-red-50 text-red-700 p-4 rounded-md">
|
||
{error}
|
||
</div>
|
||
)}
|
||
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8">
|
||
{articles.map((article, index) => (
|
||
<ArticleCard
|
||
key={article.id}
|
||
article={article}
|
||
featured={shouldShowFeatured && index === 0}
|
||
/>
|
||
))}
|
||
</div>
|
||
|
||
{totalPages > 1 && (
|
||
<Pagination
|
||
currentPage={currentPage}
|
||
totalPages={totalPages}
|
||
onPageChange={handlePageChange}
|
||
/>
|
||
)}
|
||
</section>
|
||
);
|
||
} |