import type { IServiceStatus, IIncidentDetails, IStatusPageConfig, IMonitorFormData, IIncidentFormData, } from '../interfaces/index.js'; type TStateChangeListener = (data: T) => void; /** * Simple observable implementation for state changes */ class SimpleObservable { private listeners: Set> = new Set(); subscribe(listener: TStateChangeListener): () => void { this.listeners.add(listener); return () => this.listeners.delete(listener); } next(value: T): void { for (const listener of this.listeners) { listener(value); } } } /** * Centralized state management for the admin dashboard. * Handles cross-view data passing and state synchronization. */ export class AdminState { // Observable subjects for reactive updates public monitors$ = new SimpleObservable(); public incidents$ = new SimpleObservable(); public config$ = new SimpleObservable(); // Current data private _monitors: IServiceStatus[] = []; private _incidents: IIncidentDetails[] = []; private _config: IStatusPageConfig | null = null; // Selected items for navigation context private _selectedMonitor: IServiceStatus | null = null; private _selectedIncident: IIncidentDetails | null = null; // Monitors get monitors(): IServiceStatus[] { return this._monitors; } set monitors(value: IServiceStatus[]) { this._monitors = value; this.monitors$.next(value); } // Incidents get incidents(): IIncidentDetails[] { return this._incidents; } set incidents(value: IIncidentDetails[]) { this._incidents = value; this.incidents$.next(value); } // Config get config(): IStatusPageConfig | null { return this._config; } set config(value: IStatusPageConfig | null) { this._config = value; if (value) { this.config$.next(value); } } // Selected monitor for edit navigation setSelectedMonitor(monitor: IServiceStatus | null): void { this._selectedMonitor = monitor; } getSelectedMonitor(): IServiceStatus | null { return this._selectedMonitor; } clearSelectedMonitor(): void { this._selectedMonitor = null; } // Selected incident for edit navigation setSelectedIncident(incident: IIncidentDetails | null): void { this._selectedIncident = incident; } getSelectedIncident(): IIncidentDetails | null { return this._selectedIncident; } clearSelectedIncident(): void { this._selectedIncident = null; } // Helper methods getCategories(): string[] { const categories = new Set(); for (const monitor of this._monitors) { if (monitor.category) { categories.add(monitor.category); } } return Array.from(categories).sort(); } getAvailableServices(): IServiceStatus[] { return [...this._monitors]; } getMonitorById(id: string): IServiceStatus | undefined { return this._monitors.find(m => m.id === id); } getIncidentById(id: string): IIncidentDetails | undefined { return this._incidents.find(i => i.id === id); } getActiveIncidents(): IIncidentDetails[] { return this._incidents.filter( i => !['resolved', 'postmortem'].includes(i.status) ); } getPastIncidents(): IIncidentDetails[] { return this._incidents.filter( i => ['resolved', 'postmortem'].includes(i.status) ); } // CRUD operations (these would typically call an API) addMonitor(monitor: IServiceStatus): void { this.monitors = [...this._monitors, monitor]; } updateMonitor(id: string, data: Partial): void { this.monitors = this._monitors.map(m => m.id === id ? { ...m, ...data } : m ); } deleteMonitor(id: string): void { this.monitors = this._monitors.filter(m => m.id !== id); } addIncident(incident: IIncidentDetails): void { this.incidents = [...this._incidents, incident]; } updateIncident(id: string, data: Partial): void { this.incidents = this._incidents.map(i => i.id === id ? { ...i, ...data } : i ); } deleteIncident(id: string): void { this.incidents = this._incidents.filter(i => i.id !== id); } } // Singleton instance export const adminState = new AdminState();