This commit is contained in:
vfs committed 2026-05-10 10:49:20 +02:00
1 parent 136a1c34b3
commit cb87af4f3b
108 files changed
+49079 -41

No files matched your search

+1
View File
@@ -17,6 +17,7 @@
<a href="/" class="link">Start</a>
<a href="/issues" class="link">Abstimmungen</a>
<a href="/mps" class="link">Nationalrat</a>
<a href="/parlament" class="link">Parlament</a>
<a href="/users/me" class="link">Mein Profil</a>
{{if hasPermission "users:read"}}<a href="/users" class="link">Users</a>{{end}}
<form method="POST" action="/logout" style="margin-left:auto;">
+1 -1
View File
@@ -19,7 +19,7 @@
<thead>
<tr style="background: var(--bg); border-bottom: 1px solid var(--border);">
<th style="text-align: left; padding: 10px 16px; font-weight: 600; color: var(--text-muted); font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase;">Name</th>
<th style="text-align: left; padding: 10px 16px; font-weight: 600; color: var(--text-muted); font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase;">Fraktion</th>
<th style="text-align: left; padding: 10px 16px; font-weight: 600; color: var(--text-muted); font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase;">Partei</th>
<th style="text-align: left; padding: 10px 16px; font-weight: 600; color: var(--text-muted); font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase;">Wahlkreis</th>
</tr>
</thead>
+117
View File
@@ -0,0 +1,117 @@
{{template "base" .}}
{{define "title"}}{{.Detail.Title}}{{end}}
{{define "body"}}
<div style="margin-bottom: 20px;">
<a href="/parlament" style="font-size: 13px; color: var(--text-muted); text-decoration: none;">&larr; Parlamentsgeschehen</a>
</div>
{{with .Detail}}
<div class="page-header" style="margin-bottom: 24px;">
<div style="display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;">
<h1 class="page-title" style="margin: 0;">{{.Title}}</h1>
{{if .Zitation}}<span style="font-size: 15px; color: var(--text-muted); font-weight: 500;">{{.Zitation}}</span>{{end}}
</div>
<p class="page-subtitle" style="margin-top: 6px;">
{{.DocType}}{{if .Date}} · {{.Date}}{{end}}
</p>
{{if .Description}}<p style="margin-top: 10px; font-size: 14px; color: var(--text-muted); max-width: 720px; line-height: 1.5;">{{.Description}}</p>{{end}}
{{if .Topics}}
<div style="margin-top: 10px; display: flex; gap: 6px; flex-wrap: wrap;">
{{range .Topics}}<span style="display: inline-block; padding: 2px 10px; border-radius: 20px; font-size: 12px; background: var(--bg); border: 1px solid var(--border); color: var(--text-muted);">{{.}}</span>{{end}}
</div>
{{end}}
</div>
{{/* ── Vote result card ─────────────────────────────────────────────────── */}}
<div style="background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px 24px; box-shadow: var(--shadow); margin-bottom: 20px;">
{{/* Result badge + seat counts */}}
<div style="display: flex; align-items: center; gap: 16px; margin-bottom: 16px; flex-wrap: wrap;">
<span style="display: inline-block; padding: 4px 14px; border-radius: 4px; font-size: 14px; font-weight: 700;
{{if .Passed}}background: #d1fae5; color: #065f46;{{else}}background: #fee2e2; color: #991b1b;{{end}}">
{{if .Passed}}Angenommen{{else}}Abgelehnt{{end}}
</span>
<span style="font-size: 22px; font-weight: 700; color: #065f46;">{{.ForSeats}} Ja</span>
<span style="font-size: 18px; color: var(--text-muted);">/</span>
<span style="font-size: 22px; font-weight: 700; color: #991b1b;">{{.AgainstSeats}} Nein</span>
<a href="https://www.parlament.gv.at{{$.Path}}" target="_blank" rel="noopener"
style="margin-left: auto; font-size: 13px; color: var(--text-muted); text-decoration: none; white-space: nowrap;">
parlament.gv.at &rarr;
</a>
</div>
{{/* Seat bar */}}
<div style="height: 10px; border-radius: 5px; background: #fee2e2; overflow: hidden; margin-bottom: 6px;">
<div style="height: 100%; width: {{.ForPercent}}%; background: #10b981; border-radius: 5px;"></div>
</div>
<div style="font-size: 12px; color: var(--text-muted); margin-top: 4px;">{{.ForPercent}}% Dafür</div>
</div>
{{/* ── Two-column faction breakdown ─────────────────────────────────────── */}}
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 20px;">
{{/* Yes column */}}
<div>
<div style="font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #065f46; margin-bottom: 10px; padding-bottom: 6px; border-bottom: 2px solid #10b981;">
✓ Dafür
</div>
{{range .Factions}}{{if .InFavor}}
<div style="display: flex; align-items: center; gap: 10px; padding: 10px 12px; margin-bottom: 8px;
border-radius: var(--radius); border-left: 3px solid {{.Color}}; background: var(--bg-card); border-top: 1px solid var(--border); border-right: 1px solid var(--border); border-bottom: 1px solid var(--border);">
<span style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: {{.Color}}; flex-shrink: 0;"></span>
<span style="font-weight: 600; font-size: 15px; flex: 1;">{{.Name}}</span>
<span style="font-size: 13px; color: var(--text-muted); font-weight: 500;">{{.Seats}} Mandate</span>
</div>
{{end}}{{end}}
</div>
{{/* No column */}}
<div>
<div style="font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #991b1b; margin-bottom: 10px; padding-bottom: 6px; border-bottom: 2px solid #ef4444;">
✗ Dagegen
</div>
{{range .Factions}}{{if not .InFavor}}
<div style="display: flex; align-items: center; gap: 10px; padding: 10px 12px; margin-bottom: 8px;
border-radius: var(--radius); border-left: 3px solid {{.Color}}; background: var(--bg-card); border-top: 1px solid var(--border); border-right: 1px solid var(--border); border-bottom: 1px solid var(--border);">
<span style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: {{.Color}}; flex-shrink: 0;"></span>
<span style="font-weight: 600; font-size: 15px; flex: 1;">{{.Name}}</span>
<span style="font-size: 13px; color: var(--text-muted); font-weight: 500;">{{.Seats}} Mandate</span>
</div>
{{end}}{{end}}
</div>
</div>
{{/* ── Documents ─────────────────────────────────────────────────────────── */}}
{{if .DocGroups}}
<div style="background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px 24px; box-shadow: var(--shadow); margin-bottom: 20px;">
<h2 style="font-size: 14px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.06em; margin: 0 0 14px;">Dokumente</h2>
<div style="display: flex; gap: 24px; flex-wrap: wrap;">
{{range .DocGroups}}
<div>
<div style="font-size: 13px; font-weight: 600; color: var(--dark); margin-bottom: 6px;">{{.Title}}</div>
{{range .Files}}
<a href="https://www.parlament.gv.at{{.Link}}" target="_blank" rel="noopener"
style="display: inline-block; margin-right: 6px; margin-bottom: 4px; padding: 2px 10px; border-radius: 4px;
font-size: 12px; font-weight: 600; text-decoration: none;
{{if eq .Type "PDF"}}background: #fee2e2; color: #991b1b;{{else}}background: #dbeafe; color: #1e40af;{{end}}">
{{.Type}}
</a>
{{end}}
</div>
{{end}}
</div>
</div>
{{end}}
{{/* ── Per-person votes ─────────────────────────────────────────────────── */}}
<div style="background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px 24px; box-shadow: var(--shadow);">
<h2 style="font-size: 14px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.06em; margin: 0 0 10px;">Abstimmung je Abgeordnetem</h2>
<p style="font-size: 13px; color: var(--text-muted); margin: 0;">
Einzelne Abgeordnetenstimmen sind nur bei <em>namentlichen Abstimmungen</em> öffentlich verfügbar.
Für diesen Beschluss liegt nur das Fraktionsergebnis vor.
</p>
</div>
{{end}}
{{end}}
+14
View File
@@ -0,0 +1,14 @@
{{template "base" .}}
{{define "title"}}Parlamentsgeschehen{{end}}
{{define "body"}}
<div class="page-header">
<h1 class="page-title">Parlamentsgeschehen</h1>
<p style="font-size: 20px; font-weight: 600; color: var(--text-muted); margin: 4px 0 0;">{{.Period}}. Gesetzgebungsperiode</p>
</div>
<div id="vote-groups" hx-get="/parlament/rows" hx-trigger="load" hx-swap="innerHTML">
<p style="color: var(--text-muted); text-align: center; padding: 40px 0;">Lade Daten…</p>
</div>
{{end}}
+97
View File
@@ -0,0 +1,97 @@
{{define "parlvotesrows"}}
<div style="display: flex; align-items: center; gap: 24px; padding: 16px 20px; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: 24px; flex-wrap: wrap;">
<div>
<div style="font-size: 28px; font-weight: 700; line-height: 1;">{{.TotalVotes}}</div>
<div style="font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); margin-top: 3px;">Abstimmungen</div>
</div>
<div style="width: 1px; height: 40px; background: var(--border);"></div>
{{range .Parties}}
<div style="display: flex; align-items: center; gap: 10px;">
<span style="background: {{partyColor .Code}}; color: #fff; padding: 2px 8px; border-radius: 4px; font-size: 12px; font-weight: 700; letter-spacing: 0.03em;">{{.Code}}</span>
<div style="font-size: 12px; line-height: 1.6;">
<div><span style="color: #16a34a; font-weight: 600;">{{.For}}×</span> <span style="color: var(--text-muted);">dafür</span></div>
<div><span style="color: #dc2626; font-weight: 600;">{{.Against}}×</span> <span style="color: var(--text-muted);">dagegen</span></div>
</div>
</div>
{{end}}
</div>
{{range .Groups}}
<details {{if .HasVotes}}open{{end}} style="margin-bottom: 12px;">
<summary style="
list-style: none;
display: flex;
align-items: center;
gap: 10px;
padding: 10px 16px;
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius);
cursor: pointer;
font-weight: 600;
font-size: 14px;
user-select: none;
">
<span>{{.Label}}</span>
<span style="font-size: 12px; font-weight: 400; color: var(--text-muted);">{{len .Docs}}</span>
</summary>
<div style="border: 1px solid var(--border); border-top: none; border-radius: 0 0 var(--radius) var(--radius); overflow: hidden; background: var(--bg-card);">
<table style="width: 100%; border-collapse: collapse; font-size: 14px;">
<thead>
<tr style="background: var(--bg); border-bottom: 1px solid var(--border);">
<th style="text-align: left; padding: 8px 16px; font-weight: 600; color: var(--text-muted); font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap;">Datum</th>
<th style="text-align: left; padding: 8px 16px; font-weight: 600; color: var(--text-muted); font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase;">Nr.</th>
<th style="text-align: left; padding: 8px 16px; font-weight: 600; color: var(--text-muted); font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase;">Betreff</th>
<th style="text-align: left; padding: 8px 16px; font-weight: 600; color: var(--text-muted); font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase;">Abstimmung</th>
</tr>
</thead>
<tbody>
{{range .Docs}}
<tr style="border-bottom: 1px solid var(--border);">
<td style="padding: 10px 16px; color: var(--text-muted); white-space: nowrap; font-size: 13px;">{{.Date}}</td>
<td style="padding: 10px 16px; color: var(--text-muted); white-space: nowrap; font-size: 12px;">{{.Number}}</td>
<td style="padding: 10px 16px;">
{{if .RouteID}}
<a href="/parlament/{{.RouteID}}" style="color: var(--text); font-weight: 500; text-decoration: none;">{{.Title}}</a>
{{else}}
<span style="font-weight: 500;">{{.Title}}</span>
{{end}}
{{if .Topics}}
<div style="display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px;">
{{range .Topics}}
<span style="background: var(--bg); border: 1px solid var(--border); color: var(--text-muted); padding: 1px 7px; border-radius: 99px; font-size: 11px;">{{.}}</span>
{{end}}
</div>
{{end}}
</td>
<td style="padding: 10px 16px;">
{{if or .VotesFor .VotesAgainst}}
<div style="display: flex; flex-direction: column; gap: 4px;">
{{if .VotesFor}}
<div style="display: flex; align-items: center; gap: 4px;">
<span style="font-size: 10px; font-weight: 600; color: #16a34a; text-transform: uppercase; letter-spacing: 0.05em; min-width: 42px;">Dafür</span>
{{range .VotesFor}}
<span style="background: {{partyColor .}}; color: #fff; padding: 1px 6px; border-radius: 4px; font-size: 11px; font-weight: 700; letter-spacing: 0.03em;">{{.}}</span>
{{end}}
</div>
{{end}}
{{if .VotesAgainst}}
<div style="display: flex; align-items: center; gap: 4px;">
<span style="font-size: 10px; font-weight: 600; color: #dc2626; text-transform: uppercase; letter-spacing: 0.05em; min-width: 42px;">Dagegen</span>
{{range .VotesAgainst}}
<span style="background: {{partyColor .}}; color: #fff; padding: 1px 6px; border-radius: 4px; font-size: 11px; font-weight: 700; letter-spacing: 0.03em; opacity: 0.75;">{{.}}</span>
{{end}}
</div>
{{end}}
</div>
{{else}}
<span style="color: var(--text-muted); font-size: 13px;">—</span>
{{end}}
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
</details>
{{end}}
{{end}}