import { useEffect, useMemo, useRef, useState } from "preact/hooks"; import "../../styles/channels-search.css"; export default function JamboxChannelsSearch() { const [q, setQ] = useState(""); const [items, setItems] = useState([]); const [loading, setLoading] = useState(false); const [err, setErr] = useState(""); const abortRef = useRef(null); useEffect(() => { const qq = q.trim(); setErr(""); if (qq.length < 2) { setItems([]); setLoading(false); return; } const t = setTimeout(async () => { try { if (abortRef.current) abortRef.current.abort(); const ac = new AbortController(); abortRef.current = ac; setLoading(true); const params = new URLSearchParams(); params.set("q", qq); params.set("limit", "80"); const res = await fetch( `/api/jambox/channels-search?${params.toString()}`, { signal: ac.signal, headers: { Accept: "application/json" }, } ); const json = await res.json(); if (!res.ok || !json.ok) throw new Error(json?.error || "API_ERROR"); setItems(Array.isArray(json.data) ? json.data : []); } catch (e) { if (e?.name !== "AbortError") { console.error("❌ channels search:", e); setErr("Błąd wyszukiwania."); } } finally { setLoading(false); } }, 250); return () => clearTimeout(t); }, [q]); const meta = useMemo(() => { const qq = q.trim(); if (qq.length < 2) return "Wpisz min. 2 znaki"; if (loading) return "Szukam…"; if (err) return err; return `Znaleziono: ${items.length}`; }, [q, loading, err, items]); function scrollToPackage(packageId) { const el = document.getElementById(`pkg-${packageId}`); if (!el) return; el.scrollIntoView({ behavior: "smooth", block: "start" }); el.classList.add("is-target"); window.setTimeout(() => el.classList.remove("is-target"), 1200); } return (