import { useState, useEffect, useRef } from 'react'; import { apiClient } from '../../lib/api-client'; interface AnilistMedia { id: number; episodes: number | null; season: string | null; seasonYear: number | null; description: string | null; coverImage: { large: string | null; medium: string | null } | null; title: { romaji: string | null; english: string | null; native: string | null } | null; } interface AnilistSelectorProps { animeId: number; initialQuery: string; onClose: () => void; onLinked: () => void; } export function AnilistSelector({ animeId, initialQuery, onClose, onLinked, }: AnilistSelectorProps) { const [query, setQuery] = useState(initialQuery); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); const [linking, setLinking] = useState(null); const inputRef = useRef(null); const debounceRef = useRef>(); useEffect(() => { inputRef.current?.focus(); if (initialQuery) doSearch(initialQuery); }, []); const doSearch = async (q: string) => { if (!q.trim()) { setResults([]); return; } setLoading(true); try { const data = await apiClient.searchAnilist(q.trim()); setResults(data); } catch { setResults([]); } setLoading(false); }; const handleInput = (value: string) => { setQuery(value); clearTimeout(debounceRef.current); debounceRef.current = setTimeout(() => doSearch(value), 400); }; const handleSelect = async (media: AnilistMedia) => { setLinking(media.id); try { await apiClient.reassignAnimeAnilist(animeId, { anilistId: media.id, titleRomaji: media.title?.romaji ?? null, titleEnglish: media.title?.english ?? null, titleNative: media.title?.native ?? null, episodesTotal: media.episodes ?? null, description: media.description ?? null, coverUrl: media.coverImage?.large ?? media.coverImage?.medium ?? null, }); onLinked(); } catch { setLinking(null); } }; return (
e.stopPropagation()} >

Select AniList Entry

handleInput(e.target.value)} placeholder="Search AniList..." className="w-full bg-ctp-surface0 border border-ctp-surface1 rounded-lg px-3 py-2 text-sm text-ctp-text placeholder:text-ctp-overlay2 focus:outline-none focus:border-ctp-blue" />
{loading &&
Searching...
} {!loading && results.length === 0 && query.trim() && (
No results
)} {results.map((media) => ( ))}
); }