Files
iiEasy/components/NewsAllSection.tsx

149 lines
5.0 KiB
TypeScript
Executable File
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 React, { useState, useMemo } from 'react';
import { CurrentView, NewsArticle } from '../types';
import { SECTION_IDS, NEWS_ALL_CONTENT } from '../constants';
import Button from './Button';
import { ArrowUturnLeftIcon } from './icons';
import NewsCard from './NewsCard';
import FilterSortBar, { ViewMode, SortOptionKey, SortOption } from './FilterSortBar';
interface NewsAllSectionProps {
newsArticles: NewsArticle[];
setCurrentView: (view: CurrentView) => void;
setSelectedItemId: (id: string | null) => void;
}
const sortOptions: SortOption[] = [
{ key: 'newest', label: 'Сначала новые' },
{ key: 'oldest', label: 'Сначала старые' },
{ key: 'alphabetical', label: 'По алфавиту (А-Я)' },
];
const NewsAllSection: React.FC<NewsAllSectionProps> = ({ newsArticles, setCurrentView, setSelectedItemId }) => {
const [viewMode, setViewMode] = useState<ViewMode>('list');
const [selectedCategories, setSelectedCategories] = useState<string[]>([]);
const [selectedSort, setSelectedSort] = useState<SortOptionKey>('newest');
const handleBackClick = () => {
setCurrentView('main');
setSelectedItemId(null);
setTimeout(() => {
document.getElementById(SECTION_IDS.latestNews)?.scrollIntoView({ behavior: 'smooth' });
}, 0);
};
const availableCategories = useMemo(() => {
if (!newsArticles) return [];
return Array.from(new Set(newsArticles.map(p => p.category))).sort();
}, [newsArticles]);
const handleCategoryChange = (category: string) => {
setSelectedCategories(prev =>
prev.includes(category)
? prev.filter(c => c !== category)
: [...prev, category]
);
};
const filteredAndSortedArticles = useMemo(() => {
if (!newsArticles) return [];
const filtered = selectedCategories.length > 0
? newsArticles.filter(p => selectedCategories.includes(p.category))
: newsArticles;
return [...filtered].sort((a, b) => {
switch (selectedSort) {
case 'newest':
return new Date(b.publishedAt || 0).getTime() - new Date(a.publishedAt || 0).getTime();
case 'oldest':
return new Date(a.publishedAt || 0).getTime() - new Date(b.publishedAt || 0).getTime();
case 'alphabetical':
return a.title.localeCompare(b.title);
default:
return 0;
}
});
}, [newsArticles, selectedCategories, selectedSort]);
if (!newsArticles) {
return (
<section
id={SECTION_IDS.newsAllPage}
className="py-16 md:py-24 bg-white min-h-screen flex justify-center items-center"
>
<p className="text-slate-600 font-inter">Загрузка новостей...</p>
</section>
);
}
const layoutClasses = viewMode === 'grid'
? "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-8"
: "flex flex-col gap-4";
return (
<section
id={SECTION_IDS.newsAllPage}
className="py-16 md:py-24 bg-white min-h-screen"
>
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<header className="mb-8 md:mb-8">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between">
<h1 className="font-quicksand text-4xl sm:text-5xl md:text-6xl font-bold text-slate-900 mb-4 sm:mb-0">
{NEWS_ALL_CONTENT.title}
</h1>
<Button
variant="outline"
size="md"
onClick={handleBackClick}
leftIcon={<ArrowUturnLeftIcon />}
className="self-start sm:self-center"
>
{NEWS_ALL_CONTENT.backButtonTextPrefix} {NEWS_ALL_CONTENT.backButtonTextSuffix}
</Button>
</div>
<p className="mt-4 text-lg md:text-xl text-slate-700 max-w-3xl">
{NEWS_ALL_CONTENT.subtitle}
</p>
</header>
<FilterSortBar
viewMode={viewMode}
onViewChange={setViewMode}
availableCategories={availableCategories}
selectedCategories={selectedCategories}
onCategoryChange={handleCategoryChange}
onClearCategories={() => setSelectedCategories([])}
sortOptions={sortOptions}
selectedSort={selectedSort}
onSortChange={setSelectedSort}
/>
{filteredAndSortedArticles.length > 0 ? (
<div className={layoutClasses}>
{filteredAndSortedArticles.map(article => (
<NewsCard
key={article.id}
article={article}
setCurrentView={setCurrentView}
setSelectedItemId={setSelectedItemId}
viewMode={viewMode}
/>
))}
</div>
) : (
<div className="text-center py-10">
<h2 className="text-2xl font-quicksand font-semibold text-slate-700 mb-3">{NEWS_ALL_CONTENT.emptyStateTitle}</h2>
<p className="text-slate-600 font-inter">
{NEWS_ALL_CONTENT.emptyStateMessage}
</p>
</div>
)}
</div>
</section>
);
};
export default NewsAllSection;