import { useEffect, useMemo, useState } from "react"; import type { OrganizationFunctionLabelContext, OrganizationFunctionPickerContext, OrganizationFunctionSelection } from "@govoplan/core-webui"; import { getOrganizationModel, type OrganizationFunctionItem, type OrganizationModel, type OrganizationUnitItem } from "../../api/organizations"; type FunctionOption = OrganizationFunctionSelection & { slug: string; active: boolean; }; export function OrganizationFunctionPicker({ settings, auth, value, disabled, onChange }: OrganizationFunctionPickerContext) { const [model, setModel] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); const tenantId = (auth.active_tenant ?? auth.tenant).id; useEffect(() => { let cancelled = false; setLoading(true); setError(""); getOrganizationModel(settings) .then((nextModel) => { if (!cancelled) setModel(nextModel); }) .catch((err: unknown) => { if (!cancelled) setError(err instanceof Error ? err.message : String(err)); }) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, [settings.accessToken, settings.apiBaseUrl, tenantId]); const options = useMemo(() => functionOptions(model), [model]); const selectedId = value?.functionId ?? ""; return ( <> {error &&

i18n:govoplan-organizations.functions_unavailable.4fd6765d

} ); } export function OrganizationFunctionLabel({ settings, auth, sourceModule, functionId, fallback }: OrganizationFunctionLabelContext) { const [model, setModel] = useState(null); const tenantId = (auth.active_tenant ?? auth.tenant).id; useEffect(() => { let cancelled = false; getOrganizationModel(settings) .then((nextModel) => { if (!cancelled) setModel(nextModel); }) .catch(() => { if (!cancelled) setModel(null); }); return () => { cancelled = true; }; }, [settings.accessToken, settings.apiBaseUrl, tenantId]); const option = useMemo(() => functionOptions(model).find((item) => item.functionId === functionId), [functionId, model]); if (sourceModule !== "organizations" || !option) return <>{fallback ?? functionId}; return (
{option.label}
{option.organizationUnitLabel ?? option.slug}
); } function functionOptions(model: OrganizationModel | null): FunctionOption[] { if (!model) return []; const unitById = new Map(model.units.map((unit) => [unit.id, unit])); return model.functions .filter((item) => item.is_active) .map((item) => toOption(item, unitById.get(item.organization_unit_id))) .sort((left, right) => { const unitDelta = (left.organizationUnitLabel ?? "").localeCompare(right.organizationUnitLabel ?? ""); return unitDelta !== 0 ? unitDelta : (left.label ?? left.functionId).localeCompare(right.label ?? right.functionId); }); } function toOption(item: OrganizationFunctionItem, unit: OrganizationUnitItem | undefined): FunctionOption { return { sourceModule: "organizations", functionId: item.id, label: item.name, organizationUnitId: item.organization_unit_id, organizationUnitLabel: unit?.name ?? null, slug: item.slug, active: item.is_active }; }