// Copyright: © 2026 TWWIM UG. All rights reserved. (www.twwim.com) /** * usePluginSettingsForm * * Owns the local form state for PluginSettingsPage: seeding from the server * response, exposing setter, validating, and computing the dirty flag against * a baseline snapshot of the last server-loaded (or saved) state. * * @layer Presentation */ import { useEffect, useMemo, useRef, useState, type Dispatch, type SetStateAction, } from 'react'; import type { PluginSettingsResponse } from '@archer/api-interface'; import { DEFAULT_FORM, type FormState } from '../lib/constants'; import { normaliseForWire } from '../lib/wire'; import { validate, type ValidationResult } from '../lib/validate'; interface UsePluginSettingsFormApi { form: FormState; setForm: Dispatch>; isDirty: boolean; validation: ValidationResult; /** Update the dirty baseline (e.g. after a successful save). */ resetBaseline: (next: FormState) => void; } function seedFromServer(data: PluginSettingsResponse): FormState { return { visibility: { ...data.visibility }, snippet: { ...data.snippet }, attention: { enabled: data.attention.enabled, welcome: { ...data.attention.welcome, messages: { en: data.attention.welcome.messages.en ?? [], de: data.attention.welcome.messages.de ?? [], ...data.attention.welcome.messages, }, }, idle: { ...data.attention.idle, messages: { en: data.attention.idle.messages.en ?? [], de: data.attention.idle.messages.de ?? [], ...data.attention.idle.messages, }, }, }, }; } export function usePluginSettingsForm( data: PluginSettingsResponse | undefined, ): UsePluginSettingsFormApi { const [form, setForm] = useState(DEFAULT_FORM); const baselineRef = useRef(JSON.stringify(DEFAULT_FORM)); useEffect(() => { if (!data) return; const seeded = seedFromServer(data); setForm(seeded); baselineRef.current = JSON.stringify(normaliseForWire(seeded)); }, [data]); const validation = useMemo(() => validate(form), [form]); const isDirty = useMemo( () => JSON.stringify(normaliseForWire(form)) !== baselineRef.current, [form], ); const resetBaseline = (next: FormState) => { baselineRef.current = JSON.stringify(normaliseForWire(next)); }; return { form, setForm, isDirty, validation, resetBaseline }; }