diff --git a/.claude/launch.json b/.claude/launch.json new file mode 100644 index 0000000..0263f15 --- /dev/null +++ b/.claude/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.0.1", + "configurations": [ + { + "name": "static", + "runtimeExecutable": "python3", + "runtimeArgs": ["-m", "http.server", "4567"], + "port": 4567 + } + ] +} diff --git a/index.html b/index.html index 8c7b99d..8bae1a3 100644 --- a/index.html +++ b/index.html @@ -128,9 +128,19 @@ .chart-box { position: relative; height: 260px; } .chart-box-tall { position: relative; height: 320px; } + /* Tab bar */ + .tab-btn { color: rgb(82 82 91); } + .dark .tab-btn { color: rgb(161 161 170); } + .tab-btn:not([aria-selected="true"]):hover { background: rgb(244 244 245); } + .dark .tab-btn:not([aria-selected="true"]):hover { background: rgb(39 39 42); } + .tab-btn[aria-selected="true"] { background: rgb(16 185 129); color: #fff; } + /* Print friendly */ @media print { .no-print { display: none !important; } + /* Print the full report regardless of the active tab */ + [role="tablist"] { display: none !important; } + [role="tabpanel"][hidden] { display: block !important; } html, body { background: #ffffff !important; color: #000000 !important; } .dark, .dark * { color: #000 !important; } .dark .bg-zinc-900, .dark .bg-zinc-950, .dark .bg-zinc-800\/40 { background: #fff !important; } @@ -323,9 +333,21 @@ - +
+ + + +
+
@@ -455,9 +477,9 @@

Terugverdiend van de aanschaf - ? + ?

- over levensduur, verschil EUR 0,15 + over levensduur
@@ -472,20 +494,23 @@
-
- - -
-
-

Scenario vergelijker

-

Bij spread EUR 0,15 per kWh doorzet

-
-
-
+ +
+
+

Scenario vergelijker

+

Bij ingestelde spread per kWh doorzet

+
+
+
- -
+
+ + + + + + + + + + @@ -1167,7 +1202,9 @@ function renderPaybackChart() { // Donut: lifetime revenue vs aanschafprijs. - const spread = 0.15; + const spread = state.peakPrice - state.refPrice; + const paybackLabel = document.getElementById('payback-spread-label'); + if (paybackLabel) paybackLabel.textContent = 'over levensduur, spread ' + fmtEur(spread, 3); const perCycle = profitPerCycle(state, spread); const lifetimeRev = Math.max(0, perCycle * state.cycles); const aanschaf = state.price; @@ -1257,7 +1294,9 @@ ]; function renderScenarios() { - const spread = 0.15; // EUR / kWh doorzet, vast + const spread = state.peakPrice - state.refPrice; // dynamische marktspread (hoog - laag) + const spreadLabel = document.getElementById('scenario-spread-label'); + if (spreadLabel) spreadLabel.textContent = 'Bij spread ' + fmtEur(spread, 3) + ' per kWh doorzet (hoog - laag)'; const parent = document.getElementById('scenarios'); const cards = SCENARIOS.map(sc => { const s = Object.assign({}, state, { rte: sc.rte, cycles: sc.cycles }); @@ -1394,6 +1433,40 @@ }); } + /* ============================================================ + * Tabs + * ============================================================ */ + + const TAB_KEY = 'thuisbatterij_tab'; + const TAB_NAMES = ['model', 'day', 'history']; + + function activateTab(name) { + if (!TAB_NAMES.includes(name)) name = 'model'; + for (const t of TAB_NAMES) { + const panel = document.getElementById('tab-' + t); + const btn = document.getElementById('tab-btn-' + t); + const active = t === name; + if (panel) panel.hidden = !active; + if (btn) btn.setAttribute('aria-selected', active ? 'true' : 'false'); + } + try { localStorage.setItem(TAB_KEY, name); } catch (e) { /* ignore */ } + // Charts created inside a hidden panel render at 0px; resize once visible. + requestAnimationFrame(() => { + for (const k of Object.keys(charts)) { + if (charts[k] && charts[k].resize) charts[k].resize(); + } + }); + } + + function bindTabs() { + document.querySelectorAll('[role="tab"]').forEach(btn => { + btn.addEventListener('click', () => activateTab(btn.dataset.tab)); + }); + let initial = 'model'; + try { initial = localStorage.getItem(TAB_KEY) || 'model'; } catch (e) { /* ignore */ } + activateTab(initial); + } + /* ============================================================ * EPEX dag-strategie via EasyEnergy * ============================================================ */ @@ -1767,6 +1840,7 @@ bindInputs(); bindTheme(); bindReset(); + bindTabs(); document.getElementById('fetch-day').addEventListener('click', handleFetchDay); document.getElementById('fetch-history').addEventListener('click', handleFetchHistory); renderAll();