/** * Компонент списка персон * Отображает список всех персон с возможностью поиска и фильтрации */ import { Edit, Search, Trash2, User } from "lucide-react" import { useState } from "react" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { ScrollArea } from "@/components/ui/scroll-area" import type { PersonProfile } from "../types/person" interface PersonListProps { persons: PersonProfile[] selectedPersonId?: string onSelectPerson: (personId: string) => void onEditPerson: (personId: string) => void onDeletePerson: (personId: string) => void onCreatePerson: () => void isLoading?: boolean } export function PersonList({ persons, selectedPersonId, onSelectPerson, onEditPerson, onDeletePerson, onCreatePerson, isLoading = false, }: PersonListProps) { const [searchQuery, setSearchQuery] = useState("") const [filterTag, setFilterTag] = useState(null) // Фильтрация персон по поисковому запросу и тегам const filteredPersons = persons.filter((person) => { const matchesSearch = (person.name?.toLowerCase() || "").includes(searchQuery.toLowerCase()) || (person.notes?.toLowerCase() || "").includes(searchQuery.toLowerCase()) const matchesTag = !filterTag || person.tags?.includes(filterTag) return matchesSearch && matchesTag }) // Получаем все уникальные теги const allTags = Array.from(new Set(persons.flatMap((p) => p.tags || []))) return (
{/* Заголовок и кнопка создания */}

Персоны

{/* Поиск */}
setSearchQuery(e.target.value)} className="pl-10" />
{/* Фильтры по тегам */} {allTags.length > 0 && (
{allTags.map((tag) => ( ))}
)} {/* Список персон */} {isLoading ? (
Загрузка...
) : filteredPersons.length === 0 ? (

{searchQuery || filterTag ? "Персоны не найдены" : "Пока нет добавленных персон"}

) : (
{filteredPersons.map((person) => (
onSelectPerson(person.id)} > {/* Аватар */}
{person.thumbnails && person.thumbnails.length > 0 && person.thumbnails[0].imageUrl ? ( {person.name} ) : ( )}
{/* Информация о персоне */}

{person.name || "Без имени"}

{person.notes &&

{person.notes}

} {/* Теги */} {person.tags && person.tags.length > 0 && (
{person.tags.slice(0, 2).map((tag) => ( {tag} ))} {person.tags.length > 2 && ( +{person.tags.length - 2} )}
)}
{/* Статистика */}
{person.faceEmbeddings?.length || 0} лиц
{person.appearances?.length || 0} появлений
{/* Действия */}
))}
)}
) }