import { useState } from "react"; import { useNavigate } from "react-router-dom"; import { useQuery } from "@tanstack/react-query"; import { api, type MediaItem, type TagsByCategory, type BrowseEntry } from "../api/client"; import MediaViewer from "../components/MediaViewer/MediaViewer"; import DoomScrollViewer from "../components/DoomScrollViewer/DoomScrollViewer"; export default function SearchPage() { const routerNavigate = useNavigate(); const [q, setQ] = useState(""); const [selectedTags, setSelectedTags] = useState([]); const [submitted, setSubmitted] = useState(false); const [viewingId, setViewingId] = useState(null); const [doomScrollItems, setDoomScrollItems] = useState(null); function handleViewInLibrary(item: MediaItem) { const dirPath = item.rel_path.split("/").slice(0, -1).join("/"); routerNavigate(`/library/${item.library_id}?path=${encodeURIComponent(dirPath)}`); } const { data: grouped = [] } = useQuery({ queryKey: ["tags"], queryFn: api.tags.list, }); const { data: results = [], isFetching } = useQuery({ queryKey: ["search", q, selectedTags], queryFn: () => api.search({ q, tags: selectedTags }), enabled: submitted, }); function toggleTag(id: number) { setSelectedTags((prev) => prev.includes(id) ? prev.filter((t) => t !== id) : [...prev, id] ); } function handleSubmit(e: React.FormEvent) { e.preventDefault(); setSubmitted(true); } return (

Search

setQ(e.target.value)} style={{ flex: 1, minWidth: 200 }} />
{grouped.length > 0 && (
Filter by tag:
{grouped.map((group) => (
{group.category} {group.tags.map((tag) => ( ))}
))}
)} {isFetching &&

Searching…

} {results.length > 0 && ( )}
{results.map((item) => (
setViewingId(item.id)} style={{ border: "1px solid var(--border)", borderRadius: 6, overflow: "hidden", background: "var(--bg-card)", cursor: "pointer" }}> {item.filename}
{item.filename}
{item.tags.length > 0 && (
{item.tags.map((t) => ( {t.name} ))}
)}
))}
{submitted && !isFetching && results.length === 0 && (

No results found.

)} {doomScrollItems && ( setDoomScrollItems(null)} onViewInLibrary={handleViewInLibrary} /> )} {viewingId !== null && (() => { const siblings: BrowseEntry[] = results.map((item) => ({ name: item.filename, type: item.media_type, rel_path: item.rel_path, media_item_id: item.id, })); return ( setViewingId(null)} onNavigate={(id) => setViewingId(id)} /> ); })()}
); }