Files
iiEasy/components/StoriesAllSection.tsx

151 lines
5.0 KiB
TypeScript
Executable File
Raw Permalink 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, Post } from '../types';
import { SECTION_IDS, STORIES_ALL_CONTENT } from '../constants';
import Button from './Button';
import { ArrowUturnLeftIcon } from './icons';
import PostCard from './PostCard';
import FilterSortBar, { ViewMode, SortOptionKey, SortOption } from './FilterSortBar';
interface StoriesAllSectionProps {
posts: Post[];
setCurrentView: (view: CurrentView) => void;
setSelectedItemId: (id: string | null) => void;
}
const sortOptions: SortOption[] = [
{ key: 'newest', label: 'Сначала новые' },
{ key: 'oldest', label: 'Сначала старые' },
{ key: 'alphabetical', label: 'По алфавиту (А-Я)' },
];
const StoriesAllSection: React.FC<StoriesAllSectionProps> = ({ posts, setCurrentView, setSelectedItemId }) => {
const [viewMode, setViewMode] = useState<ViewMode>('grid');
const [selectedCategories, setSelectedCategories] = useState<string[]>([]);
const [selectedSort, setSelectedSort] = useState<SortOptionKey>('newest');
const handleBackClick = () => {
setCurrentView('main');
setSelectedItemId(null);
setTimeout(() => {
document.getElementById(SECTION_IDS.story)?.scrollIntoView({ behavior: 'smooth' });
}, 0);
};
const availableCategories = useMemo(() => {
if (!posts) return [];
return Array.from(new Set(posts.map(p => p.category))).sort();
}, [posts]);
const handleCategoryChange = (category: string) => {
setSelectedCategories(prev =>
prev.includes(category)
? prev.filter(c => c !== category)
: [...prev, category]
);
};
const filteredAndSortedPosts = useMemo(() => {
if (!posts) return [];
const filtered = selectedCategories.length > 0
? posts.filter(p => selectedCategories.includes(p.category))
: posts;
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;
}
});
}, [posts, selectedCategories, selectedSort]);
if (!posts) {
return (
<section
id={SECTION_IDS.storiesAllPage}
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.storiesAllPage}
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">
{STORIES_ALL_CONTENT.title}
</h1>
<Button
variant="outline"
size="md"
onClick={handleBackClick}
leftIcon={<ArrowUturnLeftIcon />}
className="self-start sm:self-center"
>
{STORIES_ALL_CONTENT.backButtonTextPrefix} {STORIES_ALL_CONTENT.backButtonTextSuffix}
</Button>
</div>
<p className="mt-4 text-lg md:text-xl text-slate-700 max-w-3xl">
{STORIES_ALL_CONTENT.subtitle}
</p>
</header>
<FilterSortBar
viewMode={viewMode}
onViewChange={setViewMode}
availableCategories={availableCategories}
selectedCategories={selectedCategories}
onCategoryChange={handleCategoryChange}
onClearCategories={() => setSelectedCategories([])}
sortOptions={sortOptions}
selectedSort={selectedSort}
onSortChange={setSelectedSort}
/>
{filteredAndSortedPosts.length > 0 ? (
<div className={layoutClasses}>
{filteredAndSortedPosts.map(post => (
<PostCard
key={post.id}
post={post}
isFeatured={false}
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">{STORIES_ALL_CONTENT.emptyStateTitle}</h2>
<p className="text-slate-600 font-inter">
{STORIES_ALL_CONTENT.emptyStateMessage}
</p>
</div>
)}
</div>
</section>
);
};
export default StoriesAllSection;