import { Link2, RefreshCw, ShieldCheck, UserRoundPlus } from "lucide-react"; import { useCallback, useEffect, useState } from "react"; import { ActionToolbar, Button, DocumentationHelpLink, DismissibleAlert, LoadingIndicator, PageScrollViewport, SelectionList, SelectionListItem, SelectionListItemContent, StatePanel, StatusBadge, hasScope, i18nMessage, useGuardedNavigate, usePlatformLanguage, WorkspaceFrame, type PlatformRouteContext } from "@govoplan/core-webui"; import { listFormInstances, type FormInstance } from "../../api/formsRuntime"; import { FORMS_RUNTIME_DOCUMENTATION, FORMS_RUNTIME_I18N } from "./interfacePatterns"; import IntakeProfilesDialog from "./IntakeProfilesDialog"; import AssistedIntakeDialog from "./AssistedIntakeDialog"; import StatusAccessPoliciesDialog from "./StatusAccessPoliciesDialog"; const OPEN_STATUSES = ["started", "draft", "submitted", "validated", "needs_review"]; export default function FormsRuntimePage({ settings, auth }: PlatformRouteContext) { const navigate = useGuardedNavigate(); const { language } = usePlatformLanguage(); const [items, setItems] = useState([]); const [total, setTotal] = useState(0); const [status, setStatus] = useState("open"); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); const [intakeOpen, setIntakeOpen] = useState(false); const [assistedOpen, setAssistedOpen] = useState(false); const [statusAccessOpen, setStatusAccessOpen] = useState(false); const canAdmin = hasScope(auth, "forms_runtime:workspace:admin"); const canAssist = hasScope(auth, "forms_runtime:submission:assist") || hasScope(auth, "forms_runtime:workspace:write"); const load = useCallback((signal?: AbortSignal) => { setLoading(true); setError(""); return listFormInstances(settings, { statuses: status === "open" ? OPEN_STATUSES : status ? [status] : undefined, limit: 200 }, signal). then((result) => { setItems(result.instances); setTotal(result.total); }). finally(() => setLoading(false)); }, [settings, status]); useEffect(() => { const controller = new AbortController(); load(controller.signal).catch((reason) => { if ((reason as Error).name !== "AbortError") { setError(reason instanceof Error ? reason.message : "Forms could not be loaded."); } }); return () => controller.abort(); }, [load]); return (
{canAdmin && } {canAdmin && } {canAssist && } {i18nMessage("i18n:govoplan-forms-runtime.form_count", { total })} {error && {error} } {loading && } {!loading && !error && items.length === 0 && } {!loading && items.length > 0 && {items.map((item) => navigate(`/forms-runtime/${encodeURIComponent(item.instance_id)}`)}> )} } setIntakeOpen(false)} /> setStatusAccessOpen(false)} /> setAssistedOpen(false)} onStarted={(instanceId) => { setAssistedOpen(false); navigate(`/forms-runtime/${encodeURIComponent(instanceId)}`); }} />
); } function isOpen(status: string): boolean { return OPEN_STATUSES.includes(status); } function formatDateTime(value: string, locale?: string): string { return new Intl.DateTimeFormat(locale, { dateStyle: "medium", timeStyle: "short" }).format(new Date(value)); } function humanize(value: string): string { return value.replace(/[_:.-]+/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase()); } function stateLabel(value: string): string { return `i18n:govoplan-forms-runtime.state_${value}`; }