Advanced Filters - Build optimizations

This commit is contained in:
Stefan Hardegger
2025-09-04 15:49:24 +02:00
parent 702fcb33c1
commit f92dcc5314
14 changed files with 1426 additions and 109 deletions

View File

@@ -4,7 +4,8 @@ import { useState } from 'react';
import { Input } from '../ui/Input';
import Button from '../ui/Button';
import TagDisplay from '../tags/TagDisplay';
import { Story, Tag } from '../../types/api';
import AdvancedFilters from './AdvancedFilters';
import type { Story, Tag, AdvancedFilters as AdvancedFiltersType } from '../../types/api';
interface SidebarLayoutProps {
stories: Story[];
@@ -15,11 +16,13 @@ interface SidebarLayoutProps {
viewMode: 'grid' | 'list';
sortOption: string;
sortDirection: 'asc' | 'desc';
advancedFilters?: AdvancedFiltersType;
onSearchChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
onTagToggle: (tagName: string) => void;
onViewModeChange: (mode: 'grid' | 'list') => void;
onSortChange: (option: string) => void;
onSortDirectionToggle: () => void;
onAdvancedFiltersChange?: (filters: AdvancedFiltersType) => void;
onRandomStory: () => void;
onClearFilters: () => void;
children: React.ReactNode;
@@ -34,26 +37,34 @@ export default function SidebarLayout({
viewMode,
sortOption,
sortDirection,
advancedFilters = {},
onSearchChange,
onTagToggle,
onViewModeChange,
onSortChange,
onSortDirectionToggle,
onAdvancedFiltersChange,
onRandomStory,
onClearFilters,
children
}: SidebarLayoutProps) {
const [tagSearch, setTagSearch] = useState('');
const [showAdvancedFilters, setShowAdvancedFilters] = useState(false);
// Filter tags based on search query
const filteredTags = tags.filter(tag =>
tag.name.toLowerCase().includes(tagSearch.toLowerCase())
);
// Count active advanced filters
const activeAdvancedFiltersCount = Object.values(advancedFilters).filter(value =>
value !== undefined && value !== '' && value !== 'all' && value !== false
).length;
return (
<div className="flex min-h-screen">
{/* Left Sidebar */}
<div className="w-80 bg-white dark:bg-gray-800 p-4 border-r theme-border sticky top-0 h-screen overflow-y-auto max-md:w-full max-md:h-auto max-md:static max-md:border-r-0 max-md:border-b max-md:max-h-96">
<div className="w-80 min-w-80 max-w-80 bg-white dark:bg-gray-800 p-4 border-r theme-border sticky top-0 h-screen overflow-y-auto overflow-x-hidden max-md:w-full max-md:min-w-full max-md:max-w-full max-md:h-auto max-md:static max-md:border-r-0 max-md:border-b max-md:max-h-96">
{/* Random Story Button */}
<div className="mb-6">
<Button
@@ -185,7 +196,7 @@ export default function SidebarLayout({
)}
</div>
</div>
<div className="mt-2">
<div className="mt-2 space-y-2">
<Button
variant="ghost"
onClick={onClearFilters}
@@ -193,7 +204,35 @@ export default function SidebarLayout({
>
Clear All
</Button>
{/* Advanced Filters Toggle */}
{onAdvancedFiltersChange && (
<Button
variant={showAdvancedFilters || activeAdvancedFiltersCount > 0 ? "primary" : "ghost"}
onClick={() => setShowAdvancedFilters(!showAdvancedFilters)}
className={`w-full text-xs py-1 ${showAdvancedFilters || activeAdvancedFiltersCount > 0 ? '' : 'border-dashed border-2'}`}
>
Advanced Filters
{activeAdvancedFiltersCount > 0 && (
<span className="ml-1 bg-white text-blue-500 px-1 rounded text-xs">
{activeAdvancedFiltersCount}
</span>
)}
</Button>
)}
</div>
{/* Advanced Filters Section */}
{showAdvancedFilters && onAdvancedFiltersChange && (
<div className="mt-4 pt-4 border-t theme-border">
<AdvancedFilters
filters={advancedFilters}
onChange={onAdvancedFiltersChange}
onReset={() => onAdvancedFiltersChange({})}
className="space-y-3 max-w-full overflow-hidden"
/>
</div>
)}
</div>
</div>