import { Search } from "lucide-react"; import { useEffect, useMemo, useState, type FormEvent } from "react"; import { Button, DocumentationHelpLink, DismissibleAlert, LoadingIndicator, PageScrollViewport, StatusBadge, i18nMessage, useGuardedNavigate, type PlatformRouteContext } from "@govoplan/core-webui"; import { listCaseCatalog, listCases, type CaseCatalog, type CaseRecord } from "../../api/cases"; import { CASES_DOCUMENTATION, CASES_I18N } from "./interfacePatterns"; export default function CasesPage({ settings }: PlatformRouteContext) { const navigate = useGuardedNavigate(); const [query, setQuery] = useState(""); const [submittedQuery, setSubmittedQuery] = useState(""); const [status, setStatus] = useState(""); const [cases, setCases] = useState([]); const [catalog, setCatalog] = useState({ statuses: [], types: [] }); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); useEffect(() => { const controller = new AbortController(); setLoading(true); setError(""); Promise.all([ listCases(settings, { query: submittedQuery, statuses: status ? [status] : undefined, limit: 200 }, controller.signal), listCaseCatalog(settings, controller.signal) ]). then(([result, nextCatalog]) => { setCases(result.cases); setTotal(result.total); setCatalog(nextCatalog); }). catch((reason) => { if ((reason as Error).name !== "AbortError") { setError(reason instanceof Error ? reason.message : "Cases could not be loaded."); } }). finally(() => setLoading(false)); return () => controller.abort(); }, [settings, status, submittedQuery]); const statusLabels = useMemo( () => new Map(catalog.statuses.map((item) => [item.status_key, item])), [catalog.statuses] ); const typeLabels = useMemo( () => new Map(catalog.types.map((item) => [item.type_key, item.label])), [catalog.types] ); function submit(event: FormEvent) { event.preventDefault(); setSubmittedQuery(query.trim()); } return (
{error && setError("")}> {error} } {loading && } {!loading && !error && cases.length === 0 &&
No matching cases.
} {!loading && cases.length > 0 &&
{cases.map((item) => { const statusDefinition = statusLabels.get(item.status_key); return ( ); })}
}
); } function formatDate(value?: string | null): string { return value ? new Intl.DateTimeFormat(undefined, { dateStyle: "medium" }).format(new Date(value)) : "No deadline"; } function humanize(value: string): string { return value.replace(/[_:.\-]+/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase()); }