import { useEffect, useState } from "react"; import { AdminPageLayout, Button, Card, FormField, ToggleSwitch, adminErrorMessage, hasAnyScope, useUnsavedDraftGuard, type ApiSettings, type AuthInfo } from "@govoplan/core-webui"; import { getOrganizationSettings, patchOrganizationSettings, type OrganizationAuditDetailLevel, type OrganizationSettingsItem } from "../../api/organizations"; const FALLBACK_SETTINGS: OrganizationSettingsItem = { tenant_id: "", allow_tenant_model_customization: true, require_model_change_requests: false, audit_detail_level: "standard", change_retention_days: null, settings: {} }; const AUDIT_DETAIL_LEVELS: Array<{ value: OrganizationAuditDetailLevel; label: string }> = [ { value: "summary", label: "i18n:govoplan-organizations.audit_summary.6a7d68a5" }, { value: "standard", label: "i18n:govoplan-organizations.audit_standard.785d981f" }, { value: "full", label: "i18n:govoplan-organizations.audit_full.0c83669c" } ]; export default function OrganizationsAdminPanel({ settings, auth }: { settings: ApiSettings; auth: AuthInfo }) { const [draft, setDraft] = useState(FALLBACK_SETTINGS); const [savedDraft, setSavedDraft] = useState(FALLBACK_SETTINGS); const [loading, setLoading] = useState(true); const [busy, setBusy] = useState(false); const [error, setError] = useState(""); const [success, setSuccess] = useState(""); const canWrite = hasAnyScope(auth, ["organizations:settings:write", "admin:settings:write"]); const dirty = settingsKey(draft) !== settingsKey(savedDraft); useUnsavedDraftGuard({ dirty, onSave: save, onDiscard: () => setDraft(savedDraft) }); useEffect(() => { void load(); }, [settings.accessToken, settings.apiBaseUrl]); async function load() { setLoading(true); setError(""); try { const next = await getOrganizationSettings(settings); setDraft(next); setSavedDraft(next); } catch (caught) { setError(adminErrorMessage(caught)); } finally { setLoading(false); } } async function save(): Promise { setBusy(true); setError(""); setSuccess(""); try { const saved = await patchOrganizationSettings(settings, { allow_tenant_model_customization: draft.allow_tenant_model_customization, require_model_change_requests: draft.require_model_change_requests, audit_detail_level: draft.audit_detail_level, change_retention_days: draft.change_retention_days ?? null, settings: draft.settings }); setDraft(saved); setSavedDraft(saved); setSuccess("i18n:govoplan-organizations.organization_settings_saved.bfbcfdfa"); return true; } catch (caught) { setError(adminErrorMessage(caught)); return false; } finally { setBusy(false); } } return ( } >
setDraft({ ...draft, allow_tenant_model_customization: checked })} label="i18n:govoplan-organizations.allow_tenant_model_customization.2425d751" /> setDraft({ ...draft, require_model_change_requests: checked })} label="i18n:govoplan-organizations.require_model_change_requests.83454cad" />

i18n:govoplan-organizations.model_governance_help.0fa69021

setDraft({ ...draft, change_retention_days: event.target.value === "" ? null : Math.max(0, Number(event.target.value)) })} />

i18n:govoplan-organizations.audit_retention_help.42dec57d

); } function settingsKey(settings: OrganizationSettingsItem): string { return JSON.stringify({ allow_tenant_model_customization: settings.allow_tenant_model_customization, require_model_change_requests: settings.require_model_change_requests, audit_detail_level: settings.audit_detail_level, change_retention_days: settings.change_retention_days ?? null, settings: settings.settings }); }