antragstracker/static/_app/immutable/nodes/2.D2rnNjUq.js
Dotty Dotter ea3e5cd329 feat: Intuitivere Bedienung — klickbare Stats + Abstimmungs-Filter + Fraktions-Normalisierung (#14)
Dashboard:
- Neuer Endpoint GET /api/stats/dashboard mit allen Kennzahlen
- Klickbare Kacheln: Vorlagen nach Typ, Ketten nach Status → navigieren zu Filterlisten
- Umsetzungsquote als horizontaler Balken mit klickbaren Segmenten

Abstimmungen:
- Stimmverhalten-Tabelle klickbar: Fraktion oder Ja/Nein/Enthaltung → filtert
- Neuer Endpoint GET /api/abstimmungen/details (?fraktion=&stimme=) mit Pagination
- Neuer Endpoint GET /api/abstimmungen/vergleich (?f1=&f2=) für Koalitionsmatrix-Drill-Down
- Koalitionsmatrix-Zellen klickbar → zeigt Abstimmungsvergleich beider Fraktionen

Fraktions-Normalisierung:
- fraktionen_mapping.py: 40+ DB-Varianten → kanonische Namen
- 'Bündnis 90 / Die Grünen' / 'Bündnis 90/Die Grünen' / 'Grüne' → 'Grüne'
- 'Die Linke' / 'Die Linke.' / 'Linke' → 'Linke'
- BfHo-Varianten, Hagen Aktiv, Einzelvertreter etc. normalisiert
- Mapping in allen Abstimmungs-Endpoints aktiv
- ist_ratsfraktion Flag in Fraktionen-Response

Closes #14
2026-04-01 14:32:06 +02:00

2 lines
11 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import{d as Re,a as i,f as m,b as f,t as T}from"../chunks/B89f14j0.js";import{p as Fe,s as M,a as He,b as n,f as xe,c as Me,d as U,e as Oe,$ as Ze,g as e,h as a,r,t as u,n as O,u as Ge}from"../chunks/reyx9_7L.js";import{s as o}from"../chunks/BwTTNG21.js";import{i as p}from"../chunks/Do7Yo2YN.js";import{h as Je,e as te,i as re}from"../chunks/D5EBvEcH.js";import{s as V}from"../chunks/B-WTs0fq.js";import{s as K}from"../chunks/C7sCDBjT.js";import{s as D}from"../chunks/DnBxR3jh.js";/* empty css */import{g as w}from"../chunks/BHBF0lbh.js";var Ne=m('<div class="bg-red-50 text-red-700 p-4 rounded-lg mb-6"> </div>'),Qe=m('<div class="flex justify-center py-20"><div class="animate-spin rounded-full h-12 w-12 border-b-2 border-green-600"></div></div>'),We=m('<button class="border border-gray-200 rounded-lg p-4 text-left cursor-pointer hover:shadow-md hover:border-green-300 transition-all group"><div class="text-2xl mb-1"> </div> <div class="text-xl font-bold text-gray-900 group-hover:text-green-700"> </div> <div class="text-sm text-gray-500"> </div></button>'),Xe=m('<button><div class="text-xl font-bold"> </div> <div class="text-sm opacity-80"> </div></button>'),Ye=m("<button><!></button>"),et=m("<button><!></button>"),tt=m("<button><!></button>"),rt=m("<button><!></button>"),at=m("<button><!></button>"),st=m('<section class="bg-white rounded-xl shadow-sm border border-gray-200 p-5 mb-8"><h2 class="text-lg font-semibold text-gray-900 mb-1">📈 Umsetzungsquote</h2> <p class="text-sm text-gray-500 mb-4"> </p> <div class="flex rounded-full overflow-hidden h-8 mb-4"><!> <!> <!> <!> <!></div> <div class="flex flex-wrap gap-4 text-sm"><span class="flex items-center gap-1.5"><span class="w-3 h-3 rounded-full bg-green-500"></span> </span> <span class="flex items-center gap-1.5"><span class="w-3 h-3 rounded-full bg-amber-400"></span> </span> <span class="flex items-center gap-1.5"><span class="w-3 h-3 rounded-full bg-blue-400"></span> </span> <span class="flex items-center gap-1.5"><span class="w-3 h-3 rounded-full bg-gray-400"></span> </span> <span class="flex items-center gap-1.5"><span class="w-3 h-3 rounded-full bg-red-400"></span> </span></div></section>'),nt=m('<div class="p-6 text-center text-gray-500">Keine Anträge gefunden</div>'),ot=m('<li><a class="block px-5 py-4 hover:bg-gray-50 transition-colors"><div class="flex justify-between items-start"><div class="flex-1 min-w-0"><div class="flex items-center gap-2 flex-wrap"><span class="font-mono text-sm text-green-700 bg-green-50 px-2 py-0.5 rounded"> </span> <span class="text-xs text-gray-400"> </span></div> <p class="mt-1 text-gray-700 text-sm line-clamp-2"> </p></div></div></a></li>'),it=m('<ul class="divide-y divide-gray-100"></ul>'),lt=m('<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8"><button class="bg-white rounded-xl shadow-sm border border-gray-200 p-5 text-center cursor-pointer hover:shadow-md transition-shadow"><div class="text-3xl font-bold text-green-600"> </div> <div class="text-gray-500 text-sm mt-1">Vorlagen</div></button> <button class="bg-white rounded-xl shadow-sm border border-gray-200 p-5 text-center cursor-pointer hover:shadow-md transition-shadow"><div class="text-3xl font-bold text-blue-600"> </div> <div class="text-gray-500 text-sm mt-1">Ketten</div></button> <button class="bg-white rounded-xl shadow-sm border border-gray-200 p-5 text-center cursor-pointer hover:shadow-md transition-shadow"><div class="text-3xl font-bold text-purple-600"> </div> <div class="text-gray-500 text-sm mt-1">Abstimmungen</div></button> <div class="bg-white rounded-xl shadow-sm border border-gray-200 p-5 text-center"><div class="text-3xl font-bold text-orange-600">20042026</div> <div class="text-gray-500 text-sm mt-1">Zeitraum</div></div></div> <section class="bg-white rounded-xl shadow-sm border border-gray-200 p-5 mb-8"><h2 class="text-lg font-semibold text-gray-900 mb-4">📊 Vorlagen nach Typ</h2> <div class="grid grid-cols-2 md:grid-cols-4 gap-3"></div></section> <section class="bg-white rounded-xl shadow-sm border border-gray-200 p-5 mb-8"><h2 class="text-lg font-semibold text-gray-900 mb-4">🔗 Ketten nach Status</h2> <div class="grid grid-cols-2 md:grid-cols-4 gap-3"></div></section> <!> <section class="bg-white rounded-xl shadow-sm border border-gray-200"><div class="px-5 py-4 border-b border-gray-200 flex items-center justify-between"><h2 class="text-lg font-semibold text-gray-900">📋 Aktuelle Anträge</h2> <a href="/vorlagen?typ=antrag" class="text-sm text-green-600 hover:text-green-800 font-medium">Alle →</a></div> <!></section>',1),dt=m('<div class="mb-6"><h1 class="text-2xl font-bold text-gray-900">🏛️ Dashboard</h1> <p class="text-gray-500 text-sm mt-1">Kommunale Anträge & Anfragen auf einen Blick</p></div> <!> <!>',1);function ft(he,pe){Fe(pe,!0);let y=M(null),Z=M(He([])),ae=M(!0),I=M("");const se=typeof window<"u"&&window.location.port==="5173"?`http://${window.location.hostname}:8099/api`:"/api",_e={umgesetzt:"bg-green-100 text-green-800 border-green-200",teilweise_umgesetzt:"bg-amber-100 text-amber-800 border-amber-200",versandet:"bg-gray-100 text-gray-700 border-gray-200",beschlossen:"bg-blue-100 text-blue-800 border-blue-200",abgelehnt:"bg-red-100 text-red-800 border-red-200",in_beratung:"bg-purple-100 text-purple-800 border-purple-200",angefragt:"bg-cyan-100 text-cyan-800 border-cyan-200",beantwortet:"bg-teal-100 text-teal-800 border-teal-200",verwiesen:"bg-indigo-100 text-indigo-800 border-indigo-200",offen:"bg-yellow-100 text-yellow-800 border-yellow-200"},fe={umgesetzt:"Umgesetzt",teilweise_umgesetzt:"Teilw. umgesetzt",versandet:"Versandet",beschlossen:"Beschlossen",abgelehnt:"Abgelehnt",in_beratung:"In Beratung",angefragt:"Angefragt",beantwortet:"Beantwortet",verwiesen:"Verwiesen",offen:"Offen"},we={antrag:"Anträge",anfrage:"Anfragen",bericht:"Berichte",beschlussvorlage:"Beschlussvorlagen",mitteilungsvorlage:"Mitteilungen",stellungnahme:"Stellungnahmen",sonstig:"Sonstige"},ye={antrag:"📋",anfrage:"❓",bericht:"📄",beschlussvorlage:"📑",mitteilungsvorlage:"📨",stellungnahme:"💬",sonstig:"📁"},q={umgesetzt:"bg-green-500",teilweise:"bg-amber-400",beschlossen:"bg-blue-400",versandet:"bg-gray-400",abgelehnt:"bg-red-400"};async function $e(){try{const[g,_]=await Promise.all([fetch(`${se}/stats/dashboard`),fetch(`${se}/vorlagen?typ=antrag&page_size=10`)]);if(g.ok?U(y,await g.json(),!0):U(I,`Dashboard-Stats fehler: ${g.status}`),_.ok){const S=await _.json();U(Z,S.items,!0)}}catch(g){U(I,`Fehler: ${g}`)}finally{U(ae,!1)}}$e();var ne=dt();Je("1uha8ag",g=>{Oe(()=>{Ze.title="Antragstracker Hagen"})});var oe=n(xe(ne),2);{var ze=g=>{var _=Ne(),S=a(_,!0);r(_),u(()=>o(S,e(I))),i(g,_)};p(oe,g=>{e(I)&&g(ze)})}var ke=n(oe,2);{var Ae=g=>{var _=Qe();i(g,_)},je=g=>{var _=lt(),S=xe(_),C=a(S),ie=a(C),Be=a(ie,!0);r(ie),O(2),r(C);var E=n(C,2),le=a(E),Se=a(le,!0);r(le),O(2),r(E);var G=n(E,2),de=a(G),Le=a(de,!0);r(de),O(2),r(G),O(2),r(S);var J=n(S,2),ve=n(a(J),2);te(ve,21,()=>e(y).vorlagen_nach_typ,re,(b,t)=>{var v=We(),c=a(v),$=a(c,!0);r(c);var x=n(c,2),z=a(x,!0);r(x);var k=n(x,2),B=a(k,!0);r(k),r(v),u(L=>{o($,ye[e(t).typ]||"📁"),o(z,L),o(B,we[e(t).typ]||e(t).typ)},[()=>e(t).anzahl.toLocaleString()]),f("click",v,()=>w(`/vorlagen?typ=${e(t).typ}`)),i(b,v)}),r(ve),r(J);var N=n(J,2),ge=n(a(N),2);te(ge,21,()=>e(y).ketten_nach_status,re,(b,t)=>{var v=Xe(),c=a(v),$=a(c,!0);r(c);var x=n(c,2),z=a(x,!0);r(x),r(v),u(k=>{K(v,1,`border rounded-lg p-4 text-left cursor-pointer hover:shadow-md transition-all ${(_e[e(t).status]||"bg-gray-50 text-gray-700 border-gray-200")??""}`),o($,k),o(z,fe[e(t).status]||e(t).status)},[()=>e(t).anzahl.toLocaleString()]),f("click",v,()=>w(`/ketten?status=${e(t).status}`)),i(b,v)}),r(ge),r(N);var be=n(N,2);{var Ve=b=>{const t=Ge(()=>e(y).umsetzungsquote);var v=st(),c=n(a(v),2),$=a(c);r(c);var x=n(c,2),z=a(x);{var k=l=>{var s=Ye(),A=a(s);{var j=d=>{var h=T();u(()=>o(h,e(t).umgesetzt)),i(d,h)};p(A,d=>{e(t).umgesetzt/e(t).total_bewertet>.05&&d(j)})}r(s),u(()=>{K(s,1,`${q.umgesetzt} hover:brightness-110 transition-all cursor-pointer flex items-center justify-center text-white text-xs font-medium`),D(s,`width: ${e(t).umgesetzt/e(t).total_bewertet*100}%`),V(s,"title",`Umgesetzt: ${e(t).umgesetzt??""}`)}),f("click",s,()=>w("/ketten?status=umgesetzt")),i(l,s)};p(z,l=>{e(t).umgesetzt>0&&l(k)})}var B=n(z,2);{var L=l=>{var s=et(),A=a(s);{var j=d=>{var h=T();u(()=>o(h,e(t).teilweise)),i(d,h)};p(A,d=>{e(t).teilweise/e(t).total_bewertet>.05&&d(j)})}r(s),u(()=>{K(s,1,`${q.teilweise} hover:brightness-110 transition-all cursor-pointer flex items-center justify-center text-white text-xs font-medium`),D(s,`width: ${e(t).teilweise/e(t).total_bewertet*100}%`),V(s,"title",`Teilweise umgesetzt: ${e(t).teilweise??""}`)}),f("click",s,()=>w("/ketten?status=teilweise_umgesetzt")),i(l,s)};p(B,l=>{e(t).teilweise>0&&l(L)})}var P=n(B,2);{var R=l=>{var s=tt(),A=a(s);{var j=d=>{var h=T();u(()=>o(h,e(t).beschlossen)),i(d,h)};p(A,d=>{e(t).beschlossen/e(t).total_bewertet>.05&&d(j)})}r(s),u(()=>{K(s,1,`${q.beschlossen} hover:brightness-110 transition-all cursor-pointer flex items-center justify-center text-white text-xs font-medium`),D(s,`width: ${e(t).beschlossen/e(t).total_bewertet*100}%`),V(s,"title",`Beschlossen: ${e(t).beschlossen??""}`)}),f("click",s,()=>w("/ketten?status=beschlossen")),i(l,s)};p(P,l=>{e(t).beschlossen>0&&l(R)})}var F=n(P,2);{var H=l=>{var s=rt(),A=a(s);{var j=d=>{var h=T();u(()=>o(h,e(t).versandet)),i(d,h)};p(A,d=>{e(t).versandet/e(t).total_bewertet>.05&&d(j)})}r(s),u(()=>{K(s,1,`${q.versandet} hover:brightness-110 transition-all cursor-pointer flex items-center justify-center text-white text-xs font-medium`),D(s,`width: ${e(t).versandet/e(t).total_bewertet*100}%`),V(s,"title",`Versandet: ${e(t).versandet??""}`)}),f("click",s,()=>w("/ketten?status=versandet")),i(l,s)};p(F,l=>{e(t).versandet>0&&l(H)})}var Q=n(F,2);{var Ue=l=>{var s=at(),A=a(s);{var j=d=>{var h=T();u(()=>o(h,e(t).abgelehnt)),i(d,h)};p(A,d=>{e(t).abgelehnt/e(t).total_bewertet>.05&&d(j)})}r(s),u(()=>{K(s,1,`${q.abgelehnt} hover:brightness-110 transition-all cursor-pointer flex items-center justify-center text-white text-xs font-medium`),D(s,`width: ${e(t).abgelehnt/e(t).total_bewertet*100}%`),V(s,"title",`Abgelehnt: ${e(t).abgelehnt??""}`)}),f("click",s,()=>w("/ketten?status=abgelehnt")),i(l,s)};p(Q,l=>{e(t).abgelehnt>0&&l(Ue)})}r(x);var ue=n(x,2),W=a(ue),De=n(a(W));r(W);var X=n(W,2),Ie=n(a(X));r(X);var Y=n(X,2),Ce=n(a(Y));r(Y);var ee=n(Y,2),Ee=n(a(ee));r(ee);var me=n(ee,2),Pe=n(a(me));r(me),r(ue),r(v),u(()=>{o($,`${e(t).total_bewertet??""} Ketten mit Endergebnis`),o(De,` Umgesetzt (${e(t).umgesetzt??""})`),o(Ie,` Teilweise (${e(t).teilweise??""})`),o(Ce,` Beschlossen (${e(t).beschlossen??""})`),o(Ee,` Versandet (${e(t).versandet??""})`),o(Pe,` Abgelehnt (${e(t).abgelehnt??""})`)}),i(b,v)};p(be,b=>{e(y).umsetzungsquote.total_bewertet>0&&b(Ve)})}var ce=n(be,2),Ke=n(a(ce),2);{var qe=b=>{var t=nt();i(b,t)},Te=b=>{var t=it();te(t,21,()=>e(Z),re,(v,c)=>{var $=ot(),x=a($),z=a(x),k=a(z),B=a(k),L=a(B),P=a(L,!0);r(L);var R=n(L,2),F=a(R,!0);r(R),r(B);var H=n(B,2),Q=a(H,!0);r(H),r(k),r(z),r(x),r($),u(()=>{V(x,"href",`/vorlagen/${e(c).id??""}`),o(P,e(c).aktenzeichen),o(F,e(c).datum_eingang),o(Q,e(c).betreff)}),i(v,$)}),r(t),i(b,t)};p(Ke,b=>{e(Z).length===0?b(qe):b(Te,-1)})}r(ce),u((b,t,v)=>{o(Be,b),o(Se,t),o(Le,v)},[()=>e(y).vorlagen_total.toLocaleString(),()=>e(y).ketten_total.toLocaleString(),()=>e(y).abstimmungen_total.toLocaleString()]),f("click",C,()=>w("/vorlagen")),f("click",E,()=>w("/ketten")),f("click",G,()=>w("/abstimmungen")),i(g,_)};p(ke,g=>{e(ae)?g(Ae):e(y)&&g(je,1)})}i(he,ne),Me()}Re(["click"]);export{ft as component};