Porządkowanie kodu, dodanie sekcji wyszukiwania kanałów
This commit is contained in:
137
src/islands/jambox/JamboxChannelsSearch.jsx
Normal file
137
src/islands/jambox/JamboxChannelsSearch.jsx
Normal file
@@ -0,0 +1,137 @@
|
||||
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]);
|
||||
|
||||
return (
|
||||
<div class="fuz-chsearch">
|
||||
<h1 class="f-section-title">Wyszukiwanie kanałów w pakietach telewizji</h1>
|
||||
<div class="fuz-chsearch__top">
|
||||
<input
|
||||
class="fuz-chsearch__input"
|
||||
type="search"
|
||||
value={q}
|
||||
onInput={(e) => setQ(e.currentTarget.value)}
|
||||
placeholder="Szukaj kanału po nazwie…"
|
||||
aria-label="Szukaj kanału po nazwie"
|
||||
/>
|
||||
|
||||
<div class="fuz-chsearch__meta">
|
||||
{meta}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fuz-chsearch__list" role="list">
|
||||
{items.map((c) => (
|
||||
<div class="fuz-chsearch__row" role="listitem" key={`${c.name}-${c.logo_url || ""}`}>
|
||||
{/* kolumna 1 */}
|
||||
<div class="fuz-chsearch__left">
|
||||
{c.logo_url && (
|
||||
<img
|
||||
src={c.logo_url}
|
||||
alt={c.name}
|
||||
class="fuz-chsearch__logo"
|
||||
loading="lazy"
|
||||
/>
|
||||
)}
|
||||
|
||||
<div class="fuz-chsearch__channel-name">
|
||||
{c.name}
|
||||
</div>
|
||||
|
||||
<div class="fuz-chsearch__channel-number">
|
||||
kanał {c.min_number || "—"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{/* kolumna 2 */}
|
||||
<div class="fuz-chsearch__right">
|
||||
<div
|
||||
class="fuz-chsearch__desc fuz-chsearch__desc--html"
|
||||
dangerouslySetInnerHTML={{ __html: c.description || "<em>—</em>" }}
|
||||
/>
|
||||
|
||||
{Array.isArray(c.packages) && c.packages.length > 0 && (
|
||||
<div class="fuz-chsearch__packages">
|
||||
Dostępny w:
|
||||
{c.packages.map((p, i) => (
|
||||
<span class="fuz-chsearch__pkg" key={p.id}>
|
||||
{p.name}{" "}
|
||||
<span class="fuz-chsearch__pkgnum">({p.number})</span>
|
||||
{i < c.packages.length - 1 ? ", " : ""}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{q.trim().length >= 2 && !loading && items.length === 0 && (
|
||||
<div class="fuz-chsearch__empty">
|
||||
Brak wyników dla: <strong>{q}</strong>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user