/** * SortDropdown - TASK-043 * * Dropdown for selecting sort order in lists. * Supports: space, alphabet, participants, date */ import { useState, useRef, useEffect } from 'react'; import { ArrowUpDown, Folder, SortAsc, Users, Calendar, Check, ChevronDown } from 'lucide-react'; import { cn } from '@/shared/utils/cn'; export type SortOption = 'date' | 'space' | 'alphabet' | 'participants'; interface SortConfig { value: SortOption; label: string; icon: React.ReactNode; } const SORT_OPTIONS: SortConfig[] = [ { value: 'date', label: 'По дате', icon: }, { value: 'space', label: 'По спейсу', icon: }, { value: 'alphabet', label: 'По алфавиту', icon: }, { value: 'participants', label: 'По участникам', icon: }, ]; interface SortDropdownProps { value: SortOption; onChange: (value: SortOption) => void; options?: SortOption[]; className?: string; } export function SortDropdown({ value, onChange, options, className, }: SortDropdownProps) { const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); // Filter available options const availableOptions = options ? SORT_OPTIONS.filter(opt => options.includes(opt.value)) : SORT_OPTIONS; const currentOption = SORT_OPTIONS.find(opt => opt.value === value) || SORT_OPTIONS[0]; // Close on click outside useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { setIsOpen(false); } }; if (isOpen) { document.addEventListener('mousedown', handleClickOutside); } return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, [isOpen]); return ( {/* Trigger */} setIsOpen(!isOpen)} className={cn( "flex items-center gap-1.5 px-2 py-1.5 rounded-lg text-xs transition-colors", isOpen ? "bg-[var(--color-primary-500)]/20 text-[var(--color-primary-500)]" : "bg-[var(--bg-tertiary)] text-[var(--text-secondary)] hover:text-[var(--text-primary)]" )} title="Сортировка" > {currentOption.icon} {currentOption.label} {/* Dropdown menu */} {isOpen && ( {availableOptions.map(option => ( { onChange(option.value); setIsOpen(false); }} className={cn( "w-full flex items-center gap-2 px-3 py-2 text-xs text-left transition-colors", value === option.value ? "text-[var(--color-primary-500)] bg-[var(--color-primary-500)]/10" : "text-[var(--text-secondary)] hover:bg-[var(--bg-tertiary)]" )} > {option.icon} {option.label} {value === option.value && } ))} )} ); } export default SortDropdown;