feat(#169): eigene /stimmverhalten-View als linker Nav-Eintrag

Neue Route /stimmverhalten rendert dieselbe auswertungen.html, aber
mit default_tab='stimmverhalten' und v2_active_nav='stimmverhalten'.
Linker Nav-Eintrag 'Stimmverhalten' (Icon scales) zwischen
Auswertungen und Aktuelle Themen.

Beim Page-Load aktiviert das DOMContentLoaded-Handler den im Context
gesetzten Tab — fuer /auswertungen ist es 'bl-partei' (Default), fuer
/stimmverhalten direkt 'stimmverhalten'. Kein Code-Duplikat im
Tab-Inhalt.

Refs: #169

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dotty Dotter 2026-05-06 15:52:09 +02:00
parent 5823828fec
commit 741faae8ff
3 changed files with 36 additions and 1 deletions

View File

@ -2062,6 +2062,28 @@ async def auswertungen_page(request: Request, current_user: dict = Depends(requi
"v2_active_nav": "auswertungen",
"wahlperioden": wahlperioden,
"bl_codes": bl_codes,
"default_tab": "bl-partei",
**_v2_template_context(current_user),
})
@app.get("/stimmverhalten", response_class=HTMLResponse)
async def stimmverhalten_page(request: Request, current_user: dict = Depends(require_auth)):
"""Eigene View für Stimmverhalten × GWÖ (#169). Rendert auswertungen.html
mit default_tab=stimmverhalten und Active-Nav 'stimmverhalten'."""
from .auswertungen import get_wahlperioden
from .bundeslaender import alle_bundeslaender
wahlperioden = get_wahlperioden()
bl_codes = sorted(bl.code for bl in alle_bundeslaender() if bl.aktiv)
return templates.TemplateResponse("v2/screens/auswertungen.html", {
"request": request,
"app_name": settings.app_name,
"v2_active_nav": "stimmverhalten",
"wahlperioden": wahlperioden,
"bl_codes": bl_codes,
"default_tab": "stimmverhalten",
**_v2_template_context(current_user),
})

View File

@ -56,6 +56,7 @@
<div class="v2-nav-group">
<div class="v2-nav-label">— Daten</div>
<a href="/auswertungen" class="v2-nav-item {% if v2_active_nav == 'auswertungen' %}active{% endif %}">{{ icon("chart-bar", 14) }} Auswertungen</a>
<a href="/stimmverhalten" class="v2-nav-item {% if v2_active_nav == 'stimmverhalten' %}active{% endif %}">{{ icon("scales", 14) }} Stimmverhalten</a>
<a href="/aktuelle-themen" class="v2-nav-item {% if v2_active_nav == 'aktuelle-themen' %}active{% endif %}">{{ icon("book-open", 14) }} Aktuelle Themen</a>
<a href="/api/auswertungen/export.csv" class="v2-nav-item">{{ icon("file-csv", 14) }} Export · API</a>
<a href="/v2/feed" class="v2-nav-item {% if v2_active_nav == 'feed' %}active{% endif %}">{{ icon("rss", 14) }} Atom-Feed</a>

View File

@ -518,7 +518,19 @@ window.addEventListener('v2-bl-changed', function () {
// Stimmverhalten reagiert NICHT auf globalen BL-Filter — eigener Selector.
});
document.addEventListener('DOMContentLoaded', function () { loadBlMatrix(); });
document.addEventListener('DOMContentLoaded', function () {
// Default-Tab aus Server-Context — z.B. /stimmverhalten setzt 'stimmverhalten'
const initialTab = {{ default_tab | default('bl-partei') | tojson }};
if (initialTab && initialTab !== 'bl-partei') {
const tabBtn = document.querySelector(`.auswert-tab[onclick*="'${initialTab}'"]`);
if (tabBtn) {
switchTab(initialTab, tabBtn);
tabBtn.scrollIntoView({block: 'nearest', inline: 'center'});
return;
}
}
loadBlMatrix();
});
function scoreClass(avg) {
if (avg == null) return '';