antragstracker/static/_app/immutable/nodes/9.CAAaOvUh.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
12 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{e as Ve,d as nt,b as M,a as v,f as u,c as re,t as ue}from"../chunks/B89f14j0.js";import{o as dt}from"../chunks/DrzKg1h1.js";import{N as ge,Z as je,_ as se,t as b,a0 as Oe,l as vt,a1 as ct,a2 as qe,a3 as pt,a4 as ft,a5 as ut,a6 as gt,a7 as mt,a8 as xt,a9 as _t,p as bt,s as P,a as Be,b as i,f as q,g as e,c as ht,e as yt,h as s,d,$ as wt,r,u as kt}from"../chunks/reyx9_7L.js";import{s as g}from"../chunks/BwTTNG21.js";import{i as z}from"../chunks/Do7Yo2YN.js";import{h as St,e as W,i as Y}from"../chunks/D5EBvEcH.js";import{r as zt,s as Ne}from"../chunks/B-WTs0fq.js";import{s as $t}from"../chunks/C7sCDBjT.js";import{s as Ze}from"../chunks/DnBxR3jh.js";import{b as At}from"../chunks/DUDgQzMC.js";import{b as Ge}from"../chunks/Be1Vm8i2.js";import{g as oe}from"../chunks/BHBF0lbh.js";import{g as Tt,h as Et,f as Mt}from"../chunks/nhOotKLT.js";import{f as Ke}from"../chunks/utcFFRIM.js";function B(ie,me,y=!1,I=!1,L=!1,le=!1){var C=ie,h="";if(y){var p=ie;ge&&(C=je(se(p)))}b(()=>{var w=vt;if(h===(h=me()??"")){ge&&Oe();return}if(y&&!ge){w.nodes=null,p.innerHTML=h,h!==""&&Ve(se(p),p.lastChild);return}if(w.nodes!==null&&(ct(w.nodes.start,w.nodes.end),w.nodes=null),h!==""){if(ge){qe.data;for(var f=Oe(),A=f;f!==null&&(f.nodeType!==pt||f.data!=="");)A=f,f=ft(f);if(f===null)throw ut(),gt;Ve(qe,A),C=je(f);return}var $=I?xt:L?_t:void 0,U=mt(I?"svg":L?"math":"template",$);U.innerHTML=h;var m=I||L?U:U.content;if(Ve(se(m),m.lastChild),I||L)for(;se(m);)C.before(se(m));else C.before(m)}})}var Pt=u('<div class="text-xs text-gray-500 mt-0.5 line-clamp-1"></div>'),Rt=u('<button><div class="flex items-center gap-2"><span class="font-mono text-xs text-green-700 shrink-0"> </span> <span class="text-xs text-gray-400 capitalize"> </span></div> <div class="text-sm text-gray-800 truncate"> </div> <!></button>'),Dt=u('<div class="absolute z-50 top-full left-0 mt-1 w-full sm:w-96 bg-white rounded-lg shadow-lg border border-gray-200 max-h-80 overflow-y-auto"></div>'),Lt=u("<option> </option>"),Vt=u('<div class="bg-red-50 text-red-700 p-4 rounded-lg"> </div>'),Nt=u('<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>'),Ct=u('<div class="text-xs text-gray-500 mt-1 line-clamp-2"></div>'),Ft=u('<a class="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium hover:opacity-80"> </a>'),Ht=u('<div class="flex flex-wrap gap-1"></div>'),It=u('<span class="text-gray-400 text-xs"></span>'),Ut=u('<tr class="hover:bg-gray-50 transition-colors cursor-pointer"><td class="px-4 py-3"><a class="font-mono text-sm font-medium text-green-700 hover:underline"><!></a></td><td class="px-4 py-3 text-sm text-gray-700 max-w-lg"><div class="truncate"><!></div> <!></td><td class="px-4 py-3"><!></td><td class="px-4 py-3 text-sm text-gray-600 capitalize"> </td><td class="px-4 py-3 text-sm text-gray-500"> </td></tr>'),jt=u('<div class="text-xs text-gray-500 line-clamp-2 mb-2"></div>'),Ot=u('<span class="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium"> </span>'),qt=u('<span class="text-xs text-gray-500 capitalize"> </span>'),Bt=u('<a class="block bg-white rounded-xl shadow-sm border border-gray-200 p-4 hover:shadow-md transition-shadow"><div class="flex items-start justify-between gap-2 mb-2"><span class="font-mono text-sm font-medium text-green-700"><!></span> <span class="text-xs text-gray-500 shrink-0"> </span></div> <div class="text-sm text-gray-700 line-clamp-2 mb-2"><!></div> <!> <div class="flex items-center justify-between"><div class="flex flex-wrap gap-1"><!></div> <!></div></a>'),Zt=u('<div class="flex justify-center mt-6 space-x-2"><button class="px-3 py-3 sm:py-2 rounded-lg text-sm border border-gray-300 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed">&laquo; Zurück</button> <span class="px-3 py-3 sm:py-2 text-sm text-gray-600"> </span> <button class="px-3 py-3 sm:py-2 rounded-lg text-sm border border-gray-300 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed">Weiter &raquo;</button></div>'),Gt=u('<div class="text-sm text-gray-500 mb-3"> </div> <div class="hidden md:block bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden"><table class="w-full"><thead class="bg-gray-50"><tr><th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Aktenzeichen</th><th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Betreff</th><th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Partei</th><th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Typ</th><th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Datum</th></tr></thead><tbody class="divide-y divide-gray-100"></tbody></table></div> <div class="md:hidden space-y-3"></div> <!>',1),Kt=u('<div class="mb-6"><h1 class="text-2xl font-bold text-gray-900">Vorlagen</h1> <p class="text-gray-500 text-sm mt-1">Alle importierten Vorlagen aus dem ALLRIS-System</p></div> <div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4 mb-6"><div class="flex flex-col sm:flex-row flex-wrap gap-3 sm:items-end"><div class="relative w-full sm:w-auto"><label for="suche" class="block text-xs font-medium text-gray-500 mb-1">Suche</label> <input id="suche" type="text" placeholder="Volltextsuche..." class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-green-500 focus:border-green-500 w-full sm:w-64" autocomplete="off"/> <!></div> <div class="flex gap-3 w-full sm:w-auto"><div class="flex-1 sm:flex-none"><label for="typ" class="block text-xs font-medium text-gray-500 mb-1">Typ</label> <select id="typ" class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-green-500 w-full"><option>Alle</option><option>Antrag</option><option>Anfrage</option><option>Stellungnahme</option><option>Bericht</option></select></div> <div class="flex-1 sm:flex-none"><label for="partei" class="block text-xs font-medium text-gray-500 mb-1">Partei</label> <select id="partei" class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-green-500 w-full"><option>Alle</option><!></select></div></div> <button class="bg-green-600 text-white px-4 py-3 sm:py-2 rounded-lg text-sm font-medium hover:bg-green-700 transition-colors w-full sm:w-auto">Filtern</button></div></div> <!>',1);function da(ie,me){bt(me,!0);let y=P(null),I=P(Be([]));function L(t,c){if(!t||!c)return t||"-";const x=c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return t.replace(new RegExp(`(${x})`,"gi"),'<mark class="bg-yellow-200 rounded px-0.5">$1</mark>')}let le=P(null),C=P(!1),h=P(""),p=P(""),w=P(""),f=P(1),A=P(Be([])),$=P(!1),U=null,m=P(-1);function We(){d(m,-1),U&&clearTimeout(U);const t=e(p).trim();if(t.length<2){d(A,[],!0),d($,!1);return}U=setTimeout(async()=>{try{const c=await Tt(t);d(A,c.items,!0),d($,e(A).length>0)}catch{d(A,[],!0),d($,!1)}},300)}function Ye(t){if(!e($)){t.key==="Enter"&&J();return}t.key==="ArrowDown"?(t.preventDefault(),d(m,Math.min(e(m)+1,e(A).length-1),!0)):t.key==="ArrowUp"?(t.preventDefault(),d(m,Math.max(e(m)-1,-1),!0)):t.key==="Enter"?(t.preventDefault(),e(m)>=0&&e(m)<e(A).length?(oe(`/vorlagen/${e(A)[e(m)].id}`),d($,!1)):(d($,!1),J())):t.key==="Escape"&&d($,!1)}function Je(t){d($,!1),oe(`/vorlagen/${t.id}`)}function Qe(){const t=new URL(window.location.href).searchParams;d(h,t.get("typ")||"",!0),d(p,t.get("suche")||"",!0),d(w,t.get("partei")||"",!0),d(f,parseInt(t.get("page")||"1"),!0)}async function xe(){d(C,!0);try{const t={page:String(e(f)),page_size:"50"};e(h)&&(t.typ=e(h)),e(p)&&(t.suche=e(p)),e(w)&&(t.partei=e(w)),d(y,await Et(t),!0)}catch(t){d(le,t instanceof Error?t.message:"Fehler",!0)}finally{d(C,!1)}}function J(){const t=new URLSearchParams;e(h)&&t.set("typ",e(h)),e(p)&&t.set("suche",e(p)),e(w)&&t.set("partei",e(w)),d(f,1),t.set("page","1"),oe(`/vorlagen?${t.toString()}`,{replaceState:!0}),xe()}function Ce(t){d(f,t,!0);const c=new URLSearchParams(window.location.search);c.set("page",String(t)),oe(`/vorlagen?${c.toString()}`,{replaceState:!0}),xe()}dt(async()=>{d(I,await Mt(),!0),Qe(),xe()});var Fe=Kt();St("1oqo6v",t=>{yt(()=>{wt.title="Vorlagen - Antragstracker Hagen"})});var _e=i(q(Fe),2),He=s(_e),be=s(He),Z=i(s(be),2);zt(Z);var Xe=i(Z,2);{var et=t=>{var c=Dt();W(c,21,()=>e(A),Y,(x,T,F)=>{var H=Rt(),G=s(H),j=s(G),Ae=s(j,!0);r(j);var ve=i(j,2),V=s(ve,!0);r(ve),r(G);var o=i(G,2),_=s(o,!0);r(o);var k=i(o,2);{var S=N=>{var R=Pt();B(R,()=>e(T).snippet,!0),r(R),v(N,R)};z(k,N=>{e(T).snippet&&N(S)})}r(H),b(()=>{$t(H,1,`w-full text-left px-3 py-2 hover:bg-green-50 border-b border-gray-100 last:border-0 transition-colors ${F===e(m)?"bg-green-50":""}`),g(Ae,e(T).aktenzeichen||`#${e(T).id}`),g(V,e(T).typ||""),g(_,e(T).betreff||"")}),M("mousedown",H,()=>Je(e(T))),v(x,H)}),r(c),v(t,c)};z(Xe,t=>{e($)&&t(et)})}r(be);var he=i(be,2),ye=s(he),ne=i(s(ye),2),we=s(ne);we.value=we.__value="";var ke=i(we);ke.value=ke.__value="antrag";var Se=i(ke);Se.value=Se.__value="anfrage";var ze=i(Se);ze.value=ze.__value="stellungnahme";var Ie=i(ze);Ie.value=Ie.__value="bericht",r(ne),r(ye);var Ue=i(ye,2),de=i(s(Ue),2),$e=s(de);$e.value=$e.__value="";var tt=i($e);W(tt,17,()=>e(I),Y,(t,c)=>{var x=Lt(),T=s(x);r(x);var F={};b(()=>{g(T,`${e(c).kuerzel??""} (${e(c).anzahl??""})`),F!==(F=e(c).kuerzel)&&(x.value=(x.__value=e(c).kuerzel)??"")}),v(t,x)}),r(de),r(Ue),r(he);var at=i(he,2);r(He),r(_e);var rt=i(_e,2);{var st=t=>{var c=Vt(),x=s(c,!0);r(c),b(()=>g(x,e(le))),v(t,c)},ot=t=>{var c=Nt();v(t,c)},it=t=>{var c=Gt(),x=q(c),T=s(x);r(x);var F=i(x,2),H=s(F),G=i(s(H));W(G,21,()=>e(y).items,Y,(V,o)=>{var _=Ut(),k=s(_),S=s(k),N=s(S);{var R=a=>{var n=re(),O=q(n);B(O,()=>L(e(o).aktenzeichen||`#${e(o).id}`,e(p))),v(a,n)},Te=a=>{var n=ue();b(()=>g(n,e(o).aktenzeichen||`#${e(o).id}`)),v(a,n)};z(N,a=>{e(p)?a(R):a(Te,-1)})}r(S),r(k);var K=i(k),Q=s(K),X=s(Q);{var Ee=a=>{var n=re(),O=q(n);B(O,()=>L(e(o).betreff,e(p))),v(a,n)},Me=a=>{var n=ue();b(()=>g(n,e(o).betreff||"-")),v(a,n)};z(X,a=>{e(p)?a(Ee):a(Me,-1)})}r(Q);var Pe=i(Q,2);{var ce=a=>{var n=Ct();B(n,()=>e(o).snippet,!0),r(n),v(a,n)};z(Pe,a=>{e(o).snippet&&a(ce)})}r(K);var ee=i(K),pe=s(ee);{var te=a=>{var n=Ht();W(n,21,()=>e(o).antragsteller,Y,(O,D)=>{var E=Ft(),Le=s(E,!0);r(E),b(()=>{Ne(E,"href",`/vorlagen?partei=${e(D).kuerzel??""}`),Ze(E,`background-color: ${(e(D).farbe||"#6b7280")??""}20; color: ${(e(D).farbe||"#6b7280")??""}; border: 1px solid ${(e(D).farbe||"#6b7280")??""}40;`),g(Le,e(D).kuerzel)}),M("click",E,lt=>lt.stopPropagation()),v(O,E)}),r(n),v(a,n)},Re=a=>{var n=It();v(a,n)};z(pe,a=>{e(o).antragsteller?.length?a(te):a(Re,-1)})}r(ee);var ae=i(ee),De=s(ae,!0);r(ae);var fe=i(ae),l=s(fe,!0);r(fe),r(_),b(a=>{Ne(S,"href",`/vorlagen/${e(o).id??""}`),g(De,e(o).typ||"-"),g(l,a)},[()=>Ke(e(o).datum_eingang)]),M("click",_,()=>oe(`/vorlagen/${e(o).id}`)),v(V,_)}),r(G),r(H),r(F);var j=i(F,2);W(j,21,()=>e(y).items,Y,(V,o)=>{var _=Bt(),k=s(_),S=s(k),N=s(S);{var R=l=>{var a=re(),n=q(a);B(n,()=>L(e(o).aktenzeichen||`#${e(o).id}`,e(p))),v(l,a)},Te=l=>{var a=ue();b(()=>g(a,e(o).aktenzeichen||`#${e(o).id}`)),v(l,a)};z(N,l=>{e(p)?l(R):l(Te,-1)})}r(S);var K=i(S,2),Q=s(K,!0);r(K),r(k);var X=i(k,2),Ee=s(X);{var Me=l=>{var a=re(),n=q(a);B(n,()=>L(e(o).betreff,e(p))),v(l,a)},Pe=l=>{var a=ue();b(()=>g(a,e(o).betreff||"-")),v(l,a)};z(Ee,l=>{e(p)?l(Me):l(Pe,-1)})}r(X);var ce=i(X,2);{var ee=l=>{var a=jt();B(a,()=>e(o).snippet,!0),r(a),v(l,a)};z(ce,l=>{e(o).snippet&&l(ee)})}var pe=i(ce,2),te=s(pe),Re=s(te);{var ae=l=>{var a=re(),n=q(a);W(n,17,()=>e(o).antragsteller,Y,(O,D)=>{var E=Ot(),Le=s(E,!0);r(E),b(()=>{Ze(E,`background-color: ${(e(D).farbe||"#6b7280")??""}20; color: ${(e(D).farbe||"#6b7280")??""}; border: 1px solid ${(e(D).farbe||"#6b7280")??""}40;`),g(Le,e(D).kuerzel)}),v(O,E)}),v(l,a)};z(Re,l=>{e(o).antragsteller?.length&&l(ae)})}r(te);var De=i(te,2);{var fe=l=>{var a=qt(),n=s(a,!0);r(a),b(()=>g(n,e(o).typ)),v(l,a)};z(De,l=>{e(o).typ&&l(fe)})}r(pe),r(_),b(l=>{Ne(_,"href",`/vorlagen/${e(o).id??""}`),g(Q,l)},[()=>Ke(e(o).datum_eingang)]),v(V,_)}),r(j);var Ae=i(j,2);{var ve=V=>{const o=kt(()=>Math.ceil(e(y).total/e(y).page_size));var _=Zt(),k=s(_),S=i(k,2),N=s(S);r(S);var R=i(S,2);r(_),b(()=>{k.disabled=e(f)<=1,g(N,`Seite ${e(f)??""} von ${e(o)??""}`),R.disabled=e(f)>=e(o)}),M("click",k,()=>Ce(e(f)-1)),M("click",R,()=>Ce(e(f)+1)),v(V,_)};z(Ae,V=>{e(y).total>e(y).page_size&&V(ve)})}b(()=>g(T,`${e(y).total??""} Vorlagen gefunden`)),v(t,c)};z(rt,t=>{e(le)?t(st):e(C)&&!e(y)?t(ot,1):e(y)&&t(it,2)})}M("input",Z,We),M("keydown",Z,Ye),M("focusout",Z,()=>{setTimeout(()=>d($,!1),200)}),At(Z,()=>e(p),t=>d(p,t)),M("change",ne,J),Ge(ne,()=>e(h),t=>d(h,t)),M("change",de,J),Ge(de,()=>e(w),t=>d(w,t)),M("click",at,J),v(ie,Fe),ht()}nt(["input","keydown","focusout","mousedown","change","click"]);export{da as component};