import { useState, useEffect } from 'react'; import { TogglePill } from '@/components/ui/toggle-pill'; import { Skeleton } from '@/components/ui/skeleton'; import { useAuth } from '@/context/AuthContext'; import { RefreshCw } from 'lucide-react'; import { apiFetch } from '@/lib/api'; import { toast } from '@/components/ui/toast-store'; import { useNodes } from '@/context/NodeContext'; import { DEFAULT_SETTINGS } from './types'; import type { PatchableSettings } from './types'; import { SettingsSection } from './SettingsSection'; import { SettingsField } from './SettingsField'; import { SettingsActions, SettingsPrimaryButton } from './SettingsActions'; import { useMastheadStats } from './MastheadStatsContext'; import { useSettingsDirty } from './useSettingsDirty'; interface ContainerAlertsSectionProps { onDirtyChange?: (dirty: boolean) => void; } function SectionSkeleton() { return (
); } type ContainerAlertFields = Pick; const DEFAULT_CONTAINER_ALERTS: ContainerAlertFields = { global_crash: DEFAULT_SETTINGS.global_crash, }; export function ContainerAlertsSection({ onDirtyChange }: ContainerAlertsSectionProps) { const { isAdmin } = useAuth(); const { activeNode } = useNodes(); const readOnly = !isAdmin; const { settings, setSettings, dirtyCount, hasChanges, reset, markSaved } = useSettingsDirty({ ...DEFAULT_CONTAINER_ALERTS }); const [isLoading, setIsLoading] = useState(false); const [isSaving, setIsSaving] = useState(false); useEffect(() => { onDirtyChange?.(hasChanges); }, [hasChanges, onDirtyChange]); useMastheadStats( isLoading ? null : [ { label: 'EDITED', value: hasChanges ? `${dirtyCount} pending` : 'saved', tone: hasChanges ? 'warn' : 'value', }, ], ); useEffect(() => { const fetchSettings = async () => { setIsLoading(true); try { const nodeRes = await apiFetch('/settings'); const nodeData: Record = nodeRes.ok ? await nodeRes.json() : {}; const safe: ContainerAlertFields = { global_crash: (nodeData.global_crash as '0' | '1') ?? DEFAULT_SETTINGS.global_crash, }; reset(safe); } catch (e) { console.error('Failed to fetch container alert settings', e); } finally { setIsLoading(false); } }; fetchSettings(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [activeNode?.id]); const onSettingChange = (key: K, value: ContainerAlertFields[K]) => { setSettings(prev => ({ ...prev, [key]: value })); }; const saveSettings = async () => { const submitted = { ...settings }; setIsSaving(true); try { const res = await apiFetch('/settings', { method: 'PATCH', body: JSON.stringify({ global_crash: submitted.global_crash }), }); if (!res.ok) { const err = await res.json().catch(() => ({})); toast.error(err?.error || err?.message || 'Failed to save settings.'); return; } markSaved(submitted); toast.success('Container alert settings saved.'); } catch (e: unknown) { toast.error((e as Error)?.message || 'Something went wrong.'); } finally { setIsSaving(false); } }; if (isLoading) return ; return (
onSettingChange('global_crash', c ? '1' : '0')} /> {!readOnly && ( {isSaving ? ( <> Saving ) : ( 'Save settings' )} )}
); }