import { Panel } from './Panel'; import { getRpcBaseUrl } from '@/services/rpc-client'; import { getHydratedData } from '@/services/bootstrap'; import type { GetEnergyCrisisPoliciesResponse, EnergyCrisisPolicy } from '@/generated/client/worldmonitor/economic/v1/service_client'; import { escapeHtml, unsafeRawHtml } from '@/utils/sanitize'; import { EconomicServiceClient } from '@/services/generated-rpc-clients'; type PolicyData = GetEnergyCrisisPoliciesResponse; const CATEGORY_LABELS: Record = { conservation: 'Energy Conservation', consumer_support: 'Consumer Support', }; const SECTOR_LABELS: Record = { transport: 'Transport', buildings: 'Buildings', industry: 'Industry', electricity: 'Electricity', agriculture: 'Agriculture', general: 'General', }; const STATUS_CLASS: Record = { active: 'ecp-status-active', planned: 'ecp-status-planned', ended: 'ecp-status-ended', }; export class EnergyCrisisPanel extends Panel { private data: PolicyData | null = null; private loading = true; private error: string | null = null; private activeFilter: string = 'all'; constructor() { super({ id: 'energy-crisis', title: 'Energy Crisis Tracker', showCount: true, trackActivity: true, defaultRowSpan: 2, infoTooltip: 'IEA 2026 Energy Crisis Policy Response Tracker. Tracks government measures to conserve energy and support consumers in response to Middle East conflict and Strait of Hormuz supply disruptions.', }); this.showLoading('Loading energy crisis policies...'); } public async fetchData(): Promise { const hydrated = getHydratedData('energyCrisisPolicies') as PolicyData | undefined; if (hydrated?.policies?.length) { this.data = hydrated; this.error = null; this.loading = false; this.setCount(hydrated.policies.length); this.render(); void this.refreshFromRpc(); return; } await this.refreshFromRpc(); } private async refreshFromRpc(): Promise { try { const client = new EconomicServiceClient(getRpcBaseUrl(), { fetch: (...args) => globalThis.fetch(...args) }); const fresh = await client.getEnergyCrisisPolicies({ countryCode: '', category: '' }); if (!this.element?.isConnected) return; if (fresh.policies?.length || !this.data) { this.data = fresh; this.error = null; this.loading = false; this.setCount(fresh.policies.length); this.render(); } } catch (err) { if (this.isAbortError(err)) return; if (!this.element?.isConnected) return; if (!this.data) { console.warn('[EnergyCrisis] Fetch error:', err); this.error = 'Energy crisis data unavailable'; this.loading = false; this.render(); } } } private getFilteredPolicies(): EnergyCrisisPolicy[] { if (!this.data?.policies) return []; if (this.activeFilter === 'all') return this.data.policies; return this.data.policies.filter(p => p.category === this.activeFilter); } private buildSummary(): { conservationCount: number; supportCount: number; countryCount: number } { const policies = this.data?.policies ?? []; const conservationCount = policies.filter(p => p.category === 'conservation').length; const supportCount = policies.filter(p => p.category === 'consumer_support').length; const countryCount = new Set(policies.map(p => p.countryCode)).size; return { conservationCount, supportCount, countryCount }; } private render(): void { if (this.loading) { this.showLoading('Loading energy crisis policies...'); return; } if (this.error || !this.data) { this.showError(this.error || 'No data available', () => void this.fetchData()); return; } if (!this.data.policies?.length) { this.setSafeContent(unsafeRawHtml('
No energy crisis policies tracked.
', 'legacy Panel.setContent() migration')); return; } const summary = this.buildSummary(); const filtered = this.getFilteredPolicies(); const summaryHtml = `
${summary.countryCount} Countries
${summary.conservationCount} Conservation
${summary.supportCount} Consumer Support
`; const filterHtml = `
`; const policyRows = filtered.map(p => { const categoryLabel = CATEGORY_LABELS[p.category] || p.category; const sectorLabel = SECTOR_LABELS[p.sector] || p.sector; const statusClass = STATUS_CLASS[p.status] || ''; const categoryClass = p.category === 'conservation' ? 'ecp-cat-conservation' : 'ecp-cat-support'; return `
${escapeHtml(p.country)} ${escapeHtml(categoryLabel)} ${escapeHtml(sectorLabel)} ${escapeHtml(p.status)}
${escapeHtml(p.measure)}
${escapeHtml(p.dateAnnounced)}
`; }).join(''); const sourceUrl = this.data.sourceUrl || 'https://www.iea.org/data-and-statistics/data-tools/2026-energy-crisis-policy-response-tracker'; const footer = [ this.data.updatedAt ? `Updated ${new Date(this.data.updatedAt).toLocaleDateString()}` : '', 'Source: IEA', ].filter(Boolean).join(' · '); this.setSafeContent(unsafeRawHtml(`
${summaryHtml} ${filterHtml}
${policyRows}
`, 'legacy Panel.setContent() migration')); this.content?.querySelectorAll('.ecp-filter-btn').forEach(btn => { btn.addEventListener('click', (e) => { const filter = (e.currentTarget as HTMLElement).dataset.filter || 'all'; this.activeFilter = filter; this.render(); }); }); } }