mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
feat(resilience): energy domain tooltip from energy profile data (#2762)
* feat(resilience): energy domain tooltip from energy profile data When CountryDeepDivePanel receives energy profile data, it now passes it to ResilienceWidget via setEnergyMix(). The energy domain row in the widget gains a native title-attribute tooltip showing: Import dep: X% | Gas: X% | Coal: X% | Renew: X% ...and if EU gas storage is available: | EU storage: X% No new fetch — reuses the CountryEnergyProfileData already fetched by the energy section (PR C). Zero JS/CSS overhead: native browser tooltip. * fix(resilience): hide energy tooltip in locked preview mode
This commit is contained in:
@@ -485,6 +485,7 @@ export class CountryDeepDivePanel implements CountryBriefPanel {
|
||||
public updateEnergyProfile(data: CountryEnergyProfileData): void {
|
||||
if (!this.energyBody) return;
|
||||
this.renderEnergyProfile(data);
|
||||
this.resilienceWidget?.setEnergyMix(data);
|
||||
}
|
||||
|
||||
private renderEnergyProfile(data: CountryEnergyProfileData): void {
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
getResilienceTrendArrow,
|
||||
getResilienceVisualLevel,
|
||||
} from './resilience-widget-utils';
|
||||
import type { CountryEnergyProfileData } from './CountryBriefPanel';
|
||||
|
||||
const LOCKED_PREVIEW: ResilienceScoreResponse = {
|
||||
countryCode: 'US',
|
||||
@@ -51,6 +52,7 @@ export class ResilienceWidget {
|
||||
private loading = false;
|
||||
private errorMessage: string | null = null;
|
||||
private requestVersion = 0;
|
||||
private energyMixData: CountryEnergyProfileData | null = null;
|
||||
|
||||
constructor(countryCode?: string | null) {
|
||||
this.element = document.createElement('section');
|
||||
@@ -78,6 +80,7 @@ export class ResilienceWidget {
|
||||
|
||||
this.currentCountryCode = normalized;
|
||||
this.currentData = null;
|
||||
this.energyMixData = null;
|
||||
this.errorMessage = null;
|
||||
this.loading = false;
|
||||
this.requestVersion += 1;
|
||||
@@ -122,6 +125,11 @@ export class ResilienceWidget {
|
||||
}
|
||||
}
|
||||
|
||||
public setEnergyMix(data: CountryEnergyProfileData | null): void {
|
||||
this.energyMixData = data;
|
||||
this.render();
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
this.requestVersion += 1;
|
||||
this.unsubscribeAuth?.();
|
||||
@@ -257,7 +265,7 @@ export class ResilienceWidget {
|
||||
h(
|
||||
'div',
|
||||
{ className: 'resilience-widget__domains' },
|
||||
...data.domains.map((domain) => this.renderDomainRow(domain)),
|
||||
...data.domains.map((domain) => this.renderDomainRow(domain, preview)),
|
||||
),
|
||||
h(
|
||||
'div',
|
||||
@@ -275,13 +283,27 @@ export class ResilienceWidget {
|
||||
);
|
||||
}
|
||||
|
||||
private renderDomainRow(domain: ResilienceDomain): HTMLElement {
|
||||
private renderDomainRow(domain: ResilienceDomain, preview = false): HTMLElement {
|
||||
const score = clampScore(domain.score);
|
||||
const levelColor = RESILIENCE_VISUAL_LEVEL_COLORS[getResilienceVisualLevel(score)];
|
||||
|
||||
const attrs: Record<string, string> = { className: 'resilience-widget__domain-row' };
|
||||
|
||||
if (!preview && domain.id === 'energy' && this.energyMixData?.mixAvailable) {
|
||||
const d = this.energyMixData;
|
||||
const parts = [
|
||||
`Import dep: ${d.importShare.toFixed(1)}%`,
|
||||
`Gas: ${d.gasShare.toFixed(1)}%`,
|
||||
`Coal: ${d.coalShare.toFixed(1)}%`,
|
||||
`Renew: ${d.renewShare.toFixed(1)}%`,
|
||||
];
|
||||
if (d.gasStorageAvailable) parts.push(`EU storage: ${d.gasStorageFillPct.toFixed(1)}%`);
|
||||
attrs['title'] = parts.join(' | ');
|
||||
}
|
||||
|
||||
return h(
|
||||
'div',
|
||||
{ className: 'resilience-widget__domain-row' },
|
||||
attrs,
|
||||
h('span', { className: 'resilience-widget__domain-label' }, getResilienceDomainLabel(domain.id)),
|
||||
this.renderBarBlock(score, levelColor),
|
||||
h('span', { className: 'resilience-widget__domain-score' }, String(Math.round(score))),
|
||||
|
||||
@@ -160,6 +160,8 @@ describe('Product ID guard', () => {
|
||||
const result = execSync(
|
||||
`grep -rn 'pdt_' --include='*.ts' --include='*.tsx' --include='*.mjs' --include='*.js' . ` +
|
||||
`| grep -v node_modules ` +
|
||||
`| grep -v '.claude/worktrees/' ` +
|
||||
`| grep -v 'convex/_generated/' ` +
|
||||
`| grep -v 'convex/config/productCatalog' ` +
|
||||
`| grep -v 'api/product-catalog' ` +
|
||||
`| grep -v 'api/_product-fallback-prices' ` +
|
||||
|
||||
Reference in New Issue
Block a user