import { useEffect, useMemo, useState } from "react"; import { useParams, useSearchParams } from "react-router-dom"; import { getJSON, itemsOrEmpty, type Category, type Resource } from "../api"; import { ResourceCard } from "../components/ResourceCard"; import { ResourceListFooter } from "../components/ResourceListFooter"; import { useI18n } from "../i18n"; import { typeFilterLabel } from "../resourceTypeLabels"; const TYPE_FILTERS = [ "all", "image", "video", "ppt", "pdf", "text", "link", "archive", ] as const; const resourceLangCodes = ["", "zh-TW", "zh-CN", "en"] as const; function resourceLangLabel(t: (k: string) => string, code: string) { if (!code) return t("filterLanguageAll"); if (code === "zh-TW") return t("lang_zh_TW"); if (code === "zh-CN") return t("lang_zh_CN"); return t("lang_en"); } export function CategoryPage() { const { slug } = useParams(); const { t, lang } = useI18n(); const [sp, setSp] = useSearchParams(); const type = sp.get("type") || "all"; const resourceLang = sp.get("language") || ""; const page = Math.max(1, parseInt(sp.get("page") || "1", 10) || 1); const limit = 24; const [items, setItems] = useState([]); const [total, setTotal] = useState(0); const [categoryTitle, setCategoryTitle] = useState(""); const [err, setErr] = useState(null); const query = useMemo(() => { const p = new URLSearchParams(); p.set("lang", lang); p.set("category", slug || ""); p.set("limit", String(limit)); p.set("page", String(page)); if (type !== "all") p.set("type", type); if (resourceLang) p.set("language", resourceLang); return p.toString(); }, [lang, slug, type, resourceLang, page]); useEffect(() => { if (!slug) return; setErr(null); getJSON<{ items: Resource[]; total?: number }>(`/api/resources?${query}`) .then((r) => { setItems(itemsOrEmpty(r.items)); setTotal(typeof r.total === "number" ? r.total : 0); }) .catch((e) => setErr(String(e))); }, [query, slug]); useEffect(() => { if (!slug) return; const langQ = encodeURIComponent(lang); getJSON(`/api/categories?lang=${langQ}`) .then((cats) => { const c = itemsOrEmpty(cats).find((x) => x.slug === slug); setCategoryTitle(c?.name ?? slug); }) .catch(() => setCategoryTitle(slug)); }, [slug, lang]); const setPage = (next: number) => { const n = new URLSearchParams(sp); if (next <= 1) n.delete("page"); else n.set("page", String(next)); setSp(n); }; return (

{categoryTitle || slug}

{TYPE_FILTERS.map((tp) => ( ))}
{t("resourceLangFilter")}
{resourceLangCodes.map((code) => ( ))}
{err ?
{err}
: null} {!err && items.length === 0 ? (

{t("noResults")}

) : null}
{items.map((r) => ( ))}
setPage(page - 1)} onNext={() => setPage(page + 1)} />
); }