import { DeesElement, customElement, html, state, css, cssManager, } from '@design.estate/dees-element'; import type { DeesAppuiBase } from '@design.estate/dees-catalog'; // View lifecycle interfaces (defined locally as they're not exported from dees-catalog) interface IViewActivationContext { appui: DeesAppuiBase; viewId: string; params?: Record; } interface IViewLifecycle { onActivate?: (context: IViewActivationContext) => void | Promise; onDeactivate?: () => void | Promise; } import { adminState } from '../../services/admin-state.js'; import type { IIncidentDetails, TIncidentSeverity, TIncidentStatus } from '../../interfaces/index.js'; import '../../elements/upladmin-incident-list/upladmin-incident-list.js'; import '../../elements/upladmin-incident-form/upladmin-incident-form.js'; import '../../elements/upladmin-incident-update/upladmin-incident-update.js'; type TViewMode = 'list' | 'form' | 'update'; type TTimeFilter = 'current' | 'past' | 'all'; @customElement('upladmin-incidents-view') export class UpladminIncidentsView extends DeesElement implements IViewLifecycle { @state() accessor currentMode: TViewMode = 'list'; @state() accessor selectedIncidentId: string | null = null; @state() accessor timeFilter: TTimeFilter = 'current'; @state() accessor severityFilter: TIncidentSeverity | 'all' = 'all'; @state() accessor loading: boolean = false; private appuiRef: DeesAppuiBase | null = null; public static styles = [ cssManager.defaultStyles, css` :host { display: block; height: 100%; } `, ]; async onActivate(context: IViewActivationContext): Promise { this.appuiRef = context.appui; // Check route params and view ID if (context.params?.id) { if (context.viewId === 'incident-update') { this.currentMode = 'update'; this.selectedIncidentId = context.params.id; } else { this.currentMode = 'form'; this.selectedIncidentId = context.params.id === 'create' ? null : context.params.id; } } else { this.currentMode = 'list'; this.selectedIncidentId = null; } // Set secondary menu this.updateSecondaryMenu(); // No content tabs - incident-list has internal tabs context.appui.setContentTabs([]); } private updateSecondaryMenu(): void { if (!this.appuiRef) return; const activeCount = adminState.getActiveIncidents().length; const pastCount = adminState.incidents.filter((i) => i.status === 'resolved' || i.status === 'postmortem').length; this.appuiRef.setSecondaryMenu({ heading: 'Incidents', groups: [ { name: 'Filter', iconName: 'lucide:filter', items: [ { key: 'current', iconName: 'lucide:alertCircle', action: () => this.setTimeFilter('current'), badge: activeCount, badgeVariant: activeCount > 0 ? 'error' : 'default', }, { key: 'past', iconName: 'lucide:history', action: () => this.setTimeFilter('past'), badge: pastCount, }, { key: 'all', iconName: 'lucide:list', action: () => this.setTimeFilter('all'), badge: adminState.incidents.length, }, ], }, { name: 'Severity', iconName: 'lucide:alertTriangle', collapsed: true, items: [ { key: 'critical', iconName: 'lucide:xCircle', action: () => this.setSeverityFilter('critical'), }, { key: 'major', iconName: 'lucide:alertOctagon', action: () => this.setSeverityFilter('major'), }, { key: 'minor', iconName: 'lucide:alertTriangle', action: () => this.setSeverityFilter('minor'), }, { key: 'maintenance', iconName: 'lucide:wrench', action: () => this.setSeverityFilter('maintenance'), }, ], }, { name: 'Actions', iconName: 'lucide:zap', items: [ { key: 'create', iconName: 'lucide:plus', action: () => this.showForm(null), }, ], }, ], }); // Select current filter this.appuiRef.setSecondaryMenuSelection(this.timeFilter); } private setTimeFilter(filter: TTimeFilter): void { this.timeFilter = filter; this.severityFilter = 'all'; this.appuiRef?.setSecondaryMenuSelection(filter); } private setSeverityFilter(severity: TIncidentSeverity): void { this.severityFilter = severity; this.appuiRef?.setSecondaryMenuSelection(severity); } private showForm(incidentId: string | null): void { this.currentMode = 'form'; this.selectedIncidentId = incidentId; } private showUpdate(incidentId: string): void { this.currentMode = 'update'; this.selectedIncidentId = incidentId; } private showList(): void { this.currentMode = 'list'; this.selectedIncidentId = null; } private get filteredIncidents(): IIncidentDetails[] { let incidents = adminState.incidents; // Apply time filter if (this.timeFilter === 'current') { incidents = incidents.filter( (i) => i.status !== 'resolved' && i.status !== 'postmortem' ); } else if (this.timeFilter === 'past') { incidents = incidents.filter( (i) => i.status === 'resolved' || i.status === 'postmortem' ); } // Apply severity filter if (this.severityFilter !== 'all') { incidents = incidents.filter((i) => i.severity === this.severityFilter); } return incidents; } private handleIncidentSave = (e: CustomEvent): void => { console.log('Incident saved:', e.detail); this.showList(); }; private handleUpdateSave = (e: CustomEvent): void => { console.log('Update saved:', e.detail); this.showList(); }; private handleCancel = (): void => { this.showList(); }; private handleIncidentEdit = (e: CustomEvent): void => { const incident = e.detail?.incident as IIncidentDetails; if (incident) { this.showForm(incident.id); } }; private handleIncidentAddUpdate = (e: CustomEvent): void => { const incident = e.detail?.incident as IIncidentDetails; if (incident) { this.showUpdate(incident.id); } }; render() { if (this.currentMode === 'update') { const incident = this.selectedIncidentId ? adminState.incidents.find((i) => i.id === this.selectedIncidentId) : null; return html` `; } if (this.currentMode === 'form') { const incident = this.selectedIncidentId ? adminState.incidents.find((i) => i.id === this.selectedIncidentId) : null; return html` `; } return html` this.showForm(null)} @incidentEdit=${this.handleIncidentEdit} @incidentAddUpdate=${this.handleIncidentAddUpdate} > `; } }