import { Panel } from './Panel'; import { joinSafeHtml, safeHtml } from '@/utils/sanitize'; import { type ClimateAnomaly, getSeverityIcon, formatDelta } from '@/services/climate'; import { t } from '@/services/i18n'; export class ClimateAnomalyPanel extends Panel { private anomalies: ClimateAnomaly[] = []; private hasLoadedAnomalies = false; private onZoneClick?: (lat: number, lon: number) => void; constructor() { super({ id: 'climate', title: t('panels.climate'), showCount: true, trackActivity: true, infoTooltip: t('components.climate.infoTooltip'), }); this.showLoading(t('common.loadingClimateData')); } public setZoneClickHandler(handler: (lat: number, lon: number) => void): void { this.onZoneClick = handler; } public setAnomalies(anomalies: ClimateAnomaly[]): void { this.anomalies = anomalies; this.hasLoadedAnomalies = true; this.setCount(anomalies.length); this.renderContent(); } public hasData(): boolean { return this.hasLoadedAnomalies; } private renderContent(): void { if (this.anomalies.length === 0) { this.setSafeContent(safeHtml`
${t('components.climate.noAnomalies')}
`); return; } const sorted = [...this.anomalies].sort((a, b) => { const severityOrder = { extreme: 0, moderate: 1, normal: 2 }; return (severityOrder[a.severity] || 2) - (severityOrder[b.severity] || 2); }); const rows = joinSafeHtml(sorted.map(a => { const icon = getSeverityIcon(a); const tempClass = a.tempDelta > 0 ? 'climate-warm' : 'climate-cold'; const precipClass = a.precipDelta > 0 ? 'climate-wet' : 'climate-dry'; const sevClass = `severity-${a.severity}`; const rowClass = a.severity === 'extreme' ? ' climate-extreme-row' : ''; return safeHtml` ${icon}${a.zone} ${formatDelta(a.tempDelta, '°C')} ${formatDelta(a.precipDelta, 'mm')} ${t(`components.climate.severity.${a.severity}`)} `; })); this.setSafeContent(safeHtml`
${rows}
${t('components.climate.zone')} ${t('components.climate.temp')} ${t('components.climate.precip')} ${t('components.climate.severityLabel')}
`); this.content.querySelectorAll('.climate-row').forEach(el => { el.addEventListener('click', () => { const lat = Number((el as HTMLElement).dataset.lat); const lon = Number((el as HTMLElement).dataset.lon); if (Number.isFinite(lat) && Number.isFinite(lon)) this.onZoneClick?.(lat, lon); }); }); } }