1import{c as V,j as e,e as A,f as K,g as F,h as _,ao as B,ap as L,r as u,z,x as C,aj as G,ae as Y,C as le,aq as oe,ar as ce,as as H,at as de,au as ue,P as me,a4 as xe,a5 as he,a6 as pe,a7 as W,a8 as y,a9 as ge,aa as S,av as fe}from"./index-Cn3juDuU.js";import{B as I}from"./Badge-BD4P7wqJ.js";import{F as $}from"./FilterTabs-BNzu6gGz.js";import{C as M}from"./ConfirmDialog-B8KhezE6.js";import{S as be}from"./Sheet-C5pC30t9.js";import{i as je}from"./validation-CAl8HSYE.js";import{S as ve}from"./scan-line-D4eAxu1A.js";import{S as ke}from"./shield-check-B0fmU7f6.js";import{P as Ne}from"./pencil-CPLCel5F.js";import{C as we}from"./copy-CYaFR680.js";/** 2 * @license lucide-react v0.487.0 - ISC 3 * 4 * This source code is licensed under the ISC license. 5 * See the LICENSE file in the root directory of this source tree. 6 */const ye=[["path",{d:"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z",key:"1s6t7t"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor",key:"w0ekpg"}]],Q=V("key-round",ye);/** 7 * @license lucide-react v0.487.0 - ISC 8 * 9 * This source code is licensed under the ISC license. 10 * See the LICENSE file in the root directory of this source tree. 11 */const Se=[["path",{d:"M12 2v10",key:"mnfbl"}],["path",{d:"M18.4 6.6a9 9 0 1 1-12.77.04",key:"obofu9"}]],Ee=V("power",Se);function ze({icon:n,title:i,description:r,action:c,className:m}){return e.jsxs("div",{className:A("flex flex-col items-center justify-center text-center px-6 py-12",m),children:[n&&e.jsx("div",{className:"mb-3 flex h-10 w-10 items-center justify-center rounded-full bg-brand-50 text-brand-700",children:e.jsx(n,{size:18,strokeWidth:1.75})}),e.jsx("h2",{className:"m-0 text-base font-semibold text-ink-900",children:i}),r&&e.jsx("p",{className:"mt-1 max-w-sm text-sm text-ink-500",children:r}),c&&e.jsx("div",{className:"mt-4",children:c})]})}const O=["users"],J=["roles"];function Ae(){return K({queryKey:O,queryFn:()=>B.list()})}function X(){return K({queryKey:J,queryFn:()=>L.list()})}function Ce(){const n=F();return _({mutationFn:i=>B.create(i),onSuccess:()=>n.invalidateQueries({queryKey:O})})}function ee(){const n=F();return _({mutationFn:({id:i,patch:r})=>B.update(i,r),onSuccess:()=>n.invalidateQueries({queryKey:O})})}function _e(){return _({mutationFn:n=>B.resetPassword(n)})}function Be(n,i){const[r,c]=u.useState(n),[m,x]=u.useState(new Set),[b,j]=u.useState(!1),l=i(r),g=Object.keys(l).length>0;function f(d,h){c(s=>({...s,[d]:h}))}function p(d){x(h=>new Set(h).add(d))}function k(d){return b||m.has(d)?l[d]:void 0}function v(){j(!0)}function o(d=n){c(d),x(new Set),j(!1)}return{draft:r,setDraft:c,clientErrors:l,hasErrors:g,submitted:b,setField:f,touch:p,fieldError:k,markSubmitted:v,reset:o}}const Z={username:"",firstName:"",lastName:"",email:"",roleId:"",password:""},U=10;function Re(n,i){const r={};return n.username.trim()||(r.username="Benutzername ist erforderlich."),n.roleId||(r.roleId="Bitte eine Rolle wählen."),n.email.trim()&&!je(n.email.trim())&&(r.email="Ungültige E-Mail-Adresse."),!i&&n.password.length<U&&(r.password=`Das Passwort muss mindestens ${U} Zeichen lang sein.`),r}function Ie(n){if(n instanceof G)switch(n.code){case"USERNAME_TAKEN":return"Dieser Benutzername ist bereits vergeben.";case"CANNOT_DEACTIVATE_SELF":return"Sie können Ihr eigenes Konto nicht deaktivieren.";case"SUPER_ADMIN_REQUIRED":return"Diese Aktion erfordert Super-Admin-Rechte.";case"CANNOT_DEMOTE_LAST_SUPER_ADMIN":return"Der letzte Super-Admin kann nicht herabgestuft werden.";case"BUILT_IN_ROLE_LOCKED":return"Integrierte Rollen können nicht bearbeitet werden.";default:return n.message||"Speichern fehlgeschlagen. Bitte erneut versuchen."}return"Speichern fehlgeschlagen. Bitte erneut versuchen."}function Me({open:n,user:i,onClose:r}){const c=i!=null,{data:m}=X(),x=(m==null?void 0:m.items)??[],b=Ce(),j=ee(),{draft:l,setField:g,touch:f,fieldError:p,hasErrors:k,markSubmitted:v,reset:o}=Be(Z,t=>Re(t,c));u.useEffect(()=>{n&&o(i?{username:i.username,firstName:i.firstName??"",lastName:i.lastName??"",email:i.email??"",roleId:i.roleId,password:""}:Z)},[n,i]);const d=b.isPending||j.isPending,h=b.error??j.error;function s(){if(v(),k)return;const t={email:l.email.trim()||null,firstName:l.firstName.trim()||null,lastName:l.lastName.trim()||null,roleId:l.roleId};c&&i?j.mutate({id:i.id,patch:t},{onSuccess:r}):b.mutate({username:l.username.trim(),password:l.password,...t},{onSuccess:r})}return e.jsx(be,{open:n,onClose:r,title:c?"Benutzer bearbeiten":"Neuer Benutzer",description:c?"Stammdaten und Rolle anpassen.":"Konto und Rolle für ein Teammitglied anlegen.",footer:e.jsxs("div",{className:"flex items-center justify-end gap-2",children:[e.jsx("button",{type:"button",onClick:r,className:"inline-flex h-8 cursor-pointer items-center rounded-md px-3 text-[13px] font-medium text-ink-600 transition-colors hover:bg-ink-100",children:"Abbrechen"}),e.jsxs("button",{type:"button",disabled:d,onClick:s,className:"inline-flex h-8 cursor-pointer items-center gap-1 rounded-md bg-brand-600 px-3.5 text-[13px] font-medium text-white transition-colors hover:bg-brand-700 disabled:cursor-not-allowed disabled:opacity-50",children:[d&&e.jsx(C,{size:13,className:"animate-spin"}),c?"Speichern":"Anlegen"]})]}),children:e.jsxs("div",{className:"grid gap-4 px-5 py-5",children:[h&&e.jsx("div",{className:"rounded-md border border-red-100 bg-red-50 px-3 py-2 text-[12px] text-red-600",children:Ie(h)}),e.jsx(E,{label:"Benutzername",error:p("username"),children:e.jsx(z,{value:l.username,invali
11d:!!p("username"),disabled:c,onChange:t=>g("username",t.target.value),onBlur:()=>f("username"),placeholder:"z. B. m.huber"})}),e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[e.jsx(E,{label:"Vorname",children:e.jsx(z,{value:l.firstName,onChange:t=>g("firstName",t.target.value),placeholder:"Vorname"})}),e.jsx(E,{label:"Nachname",children:e.jsx(z,{value:l.lastName,onChange:t=>g("lastName",t.target.value),placeholder:"Nachname"})})]}),e.jsx(E,{label:"E-Mail",error:p("email"),children:e.jsx(z,{type:"email",value:l.email,invalid:!!p("email"),onChange:t=>g("email",t.target.value),onBlur:()=>f("email"),placeholder:"[email protected]"})}),e.jsx(E,{label:"Rolle",error:p("roleId"),children:e.jsxs("select",{value:l.roleId,onChange:t=>g("roleId",t.target.value),onBlur:()=>f("roleId"),className:A("h-9 w-full rounded-md border bg-white px-3 text-sm text-ink-900 outline-none transition-colors",p("roleId")?"border-red-300 focus-visible:ring-2 focus-visible:ring-red-500/20":"border-ink-200 focus-visible:border-brand-700 focus-visible:ring-2 focus-visible:ring-brand-700/10"),children:[e.jsx("option",{value:"",children:"Rolle wählenâ¦"}),x.map(t=>e.jsx("option",{value:t.id,children:t.name},t.id))]})}),!c&&e.jsx(E,{label:"Passwort",error:p("password"),hint:`Mindestens ${U} Zeichen.`,children:e.jsx(z,{type:"password",value:l.password,invalid:!!p("password"),onChange:t=>g("password",t.target.value),onBlur:()=>f("password"),placeholder:"â¢â¢â¢â¢â¢â¢â¢â¢â¢â¢",autoComplete:"new-password"})})]})})}function E({label:n,error:i,hint:r,children:c}){return e.jsxs("label",{className:"grid gap-1",children:[e.jsx("span",{className:"text-[12px] font-medium text-ink-700",children:n}),c,i?e.jsx("span",{className:"text-[11px] text-red-600",children:i}):r?e.jsx("span",{className:"text-[11px] text-ink-400",children:r}):null]})}const P={reservations:"Reservierungen",inquiries:"Anfragen",crm:"Kundenverwaltung",financials:"Finanzen",analytics:"Analytics",ai:"KI-Assistenz",users:"Benutzerverwaltung",settings_invoice:"Rechnungsaussteller",settings_email:"E-Mail / SMTP",settings_email_templates:"E-Mail-Vorlagen",settings_email_log:"E-Mail-Protokoll",settings_payment_reminders:"Zahlungserinnerungen",settings_ticket_pricing:"Ticketpreise",settings_ticket_disclaimer:"Ticket-Disclaimer",settings_halls:"Hall Designer",settings_scan_points:"Scan Punkte",checkin:"Check-in App"},Pe=new Set(H),Te=ue.filter(n=>!Pe.has(n));function De(n){return{module:n,canCreate:!0,canRead:!0,canUpdate:!0,canDelete:!0}}function Le(){const n=F(),i=Y(),{data:r,isPending:c}=X(),m=u.useMemo(()=>(r==null?void 0:r.items)??[],[r]),[x,b]=u.useState(null);u.useEffect(()=>{x==null&&m.length>0&&b(m[0].id)},[m,x]);const j=m.find(s=>s.id===x)??null,l=(j==null?void 0:j.isBuiltIn)??!1,g=["role-permissions",x],{data:f,isFetching:p}=K({queryKey:g,queryFn:()=>L.permissions(x),enabled:x!=null}),k=p&&f==null,[v,o]=u.useState(new Set);u.useEffect(()=>{if(!f)return;const s=new Set;for(const t of f.items)(t.canCreate||t.canRead||t.canUpdate||t.canDelete)&&s.add(t.module);o(s)},[f]);const d=_({mutationFn:()=>{const s=[...v].map(t=>De(t));return L.replacePermissions(x,s)},onSuccess:()=>{n.invalidateQueries({queryKey:g}),n.invalidateQueries({queryKey:J}),i("Berechtigungen gespeichert.")},onError:s=>{const t=s instanceof G&&s.code==="BUILT_IN_ROLE_LOCKED"?"Integrierte Rollen können nicht bearbeitet werden.":"Speichern fehlgeschlagen. Bitte erneut versuchen.";i(t)}});function h(s){l||o(t=>{const N=new Set(t);return N.has(s)?N.delete(s):N.add(s),N})}return e.jsxs("div",{className:"rounded-xl border border-ink-200 bg-white shadow-sm",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 border-b border-ink-100 bg-ink-50/40 px-4 py-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-[12px] font-bold uppercase tracking-[0.06em] text-ink-400",children:"Rolle"}),e.jsx("select",{"aria-label":"Rolle",value:x??"",onChange:s=>b(s.target.value),disabled:c,className:"h-8 rounded-md border border-ink-200 bg-white px-2.5 text-[13px] text-ink-900 outline-none transition-colors focus:border-brand-400 focus:ring-2 focus:ring-brand-600/[0.08]",children:m.map(s=>e.jsxs("option",{value:s.id,children:[s.name,s.isBuiltIn?" (integriert)":""]},s.id))})]}),!l&&x!=null&&e.jsxs("button",{type:"button",disabled:d.isPending||k,onClick:()=>d.mutate(),className:"inline-flex h-8 cursor-pointer items-center gap-1 rounded-md bg-brand-600 px-3 text-[12px] font-medium text-white transition-colors hover:bg-brand-700 disabled:cursor-not-allowed disabled:opacity-50",children:[d.isPending?e.jsx(C,{size:13,className:"animate-spin"}):e.jsx(le,{size:13,strokeWidth:2}
11),"Speichern"]})]}),l&&e.jsxs("div",{className:"flex items-center gap-2 border-b border-amber-100 bg-amber-50 px-4 py-2 text-[12px] text-amber-700",children:[e.jsx(oe,{size:13,strokeWidth:1.75}),"Integrierte Rolle â schreibgeschützt"]}),k?e.jsx("div",{className:"flex items-center justify-center py-12",children:e.jsx(C,{size:18,className:"animate-spin text-ink-400"})}):e.jsxs("div",{className:"grid gap-6 p-4",children:[e.jsxs("section",{className:"grid gap-2",children:[e.jsx("h3",{className:"text-[11px] font-bold uppercase tracking-[0.06em] text-ink-400",children:"Modulzugriff"}),e.jsx("div",{className:"grid gap-1.5 sm:grid-cols-2",children:Te.map(s=>e.jsx(T,{label:P[s],checked:v.has(s),disabled:l,onToggle:()=>h(s)},s))})]}),e.jsxs("section",{className:"grid gap-2",children:[e.jsxs("h3",{className:"flex items-center gap-1.5 text-[11px] font-bold uppercase tracking-[0.06em] text-ink-400",children:[e.jsx(ce,{size:13,strokeWidth:1.75}),"Einstellungen"]}),e.jsx("div",{className:"grid gap-1.5 sm:grid-cols-2",children:H.map(s=>e.jsx(T,{label:P[s],checked:v.has(s),disabled:l,onToggle:()=>h(s)},s))}),e.jsx("p",{className:"text-[11px] text-ink-400",children:"Jede Einstellungsseite wird einzeln freigegeben."})]}),e.jsxs("section",{className:"grid gap-2",children:[e.jsxs("h3",{className:"flex items-center gap-1.5 text-[11px] font-bold uppercase tracking-[0.06em] text-brand-700",children:[e.jsx(ve,{size:13,strokeWidth:1.75}),"Check-in App"]}),e.jsx("div",{className:"grid gap-1.5",children:de.map(s=>e.jsx(T,{label:P[s],checked:v.has(s),disabled:l,onToggle:()=>h(s),accent:!0},s))}),e.jsx("p",{className:"text-[11px] text-ink-400",children:"Eigener Zugang zur Check-in App (Eingangskontrolle am Ballabend)."})]})]})]})}function T({label:n,checked:i,disabled:r,onToggle:c,accent:m}){return e.jsxs("label",{className:A("flex items-center justify-between gap-3 rounded-lg border px-3 py-2 text-[13px] transition-colors",m?"border-brand-200 bg-brand-50/40":"border-ink-200 bg-white",r?"cursor-not-allowed opacity-70":"cursor-pointer hover:bg-ink-50/60"),children:[e.jsx("span",{className:"text-ink-800",children:n}),e.jsx("input",{type:"checkbox",checked:i,disabled:r,onChange:c,className:"h-4 w-4 cursor-pointer accent-brand-600 disabled:cursor-not-allowed"})]})}function Ue(n){return[n.firstName,n.lastName].filter(Boolean).join(" ").trim()||"â"}function Ye(){const n=Y(),{data:i,isPending:r,isError:c}=Ae(),m=ee(),x=_e(),[b,j]=u.useState("users"),[l,g]=u.useState("all"),[f,p]=u.useState(!1),[k,v]=u.useState(null),[o,d]=u.useState(null),[h,s]=u.useState(null),[t,N]=u.useState(null),w=u.useMemo(()=>(i==null?void 0:i.items)??[],[i]),R=u.useMemo(()=>({all:w.length,active:w.filter(a=>a.isActive).length,inactive:w.filter(a=>!a.isActive).length}),[w]),q=u.useMemo(()=>w.filter(a=>l==="all"?!0:l==="active"?a.isActive:!a.isActive),[w,l]);function ne(){v(null),p(!0)}function se(a){v(a),p(!0)}function te(){if(!o)return;const a=o;m.mutate({id:a.id,patch:{isActive:!a.isActive}},{onSuccess:()=>{n(a.isActive?"Benutzer deaktiviert.":"Benutzer reaktiviert."),d(null)},onError:()=>n("Aktion fehlgeschlagen. Bitte erneut versuchen.")})}function ie(){if(!h)return;const a=h;x.mutate(a.id,{onSuccess:ae=>{s(null),N({username:a.username,tempPassword:ae})},onError:()=>n("Zurücksetzen fehlgeschlagen. Bitte erneut versuchen.")})}async function re(){if(t)try{await navigator.clipboard.writeText(t.tempPassword),n("Passwort kopiert")}catch{n("Kopieren fehlgeschlagen. Bitte manuell kopieren.")}}return e.jsxs("div",{style:{maxWidth:"1040px",margin:"0 auto",padding:"40px 32px 80px"},children:[e.jsxs("div",{style:{marginBottom:"24px"},children:[e.jsx("h1",{style:{margin:"0 0 6px",fontSize:"22px",fontWeight:700,color:"#111827"},children:"Benutzerverwaltung"}),e.jsx("p",{style:{margin:0,fontSize:"13px",color:"#6b7280"},children:"Benutzerkonten, Rollen und Modulzugriffe verwalten."})]}),e.jsx("div",{className:"mb-4",children:e.jsx($,{tabs:[{id:"users",label:"Benutzer"},{id:"roles",label:"Rollen & Zugriffe"}],value:b,onChange:j,size:"md"})}),b==="roles"?e.jsx(Le,{}):e.jsxs("div",{className:"overflow-hidden rounded-xl border border-ink-200 bg-white shadow-sm",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 border-b border-ink-100 bg-ink-50/40 px-4 py-3",children:[e.jsx($,{tabs:[{id:"all",label:"Alle",count:R.all},{id:"active",label:"Aktiv",count:R.active},{id:"inactive",label:"Inaktiv",count:R.inactive}
11],value:l,onChange:g}),e.jsxs("button",{type:"button",onClick:ne,className:"inline-flex h-7 cursor-pointer items-center gap-1 rounded-md bg-brand-600 px-2.5 text-[12px] font-medium text-white transition-colors hover:bg-brand-700",children:[e.jsx(me,{size:13,strokeWidth:2}),"Neuer Benutzer"]})]}),r?e.jsx("div",{className:"flex items-center justify-center py-16",children:e.jsx(C,{size:18,className:"animate-spin text-ink-400"})}):c?e.jsx("div",{className:"px-4 py-8 text-center text-[13px] text-red-600",children:"Benutzer konnten nicht geladen werden."}):q.length===0?e.jsx(ze,{icon:ke,title:"Keine Benutzer in dieser Ansicht."}):e.jsx(xe,{children:e.jsxs(he,{children:[e.jsx(pe,{children:e.jsxs(W,{children:[e.jsx(y,{children:"Benutzername"}),e.jsx(y,{children:"Name"}),e.jsx(y,{children:"E-Mail"}),e.jsx(y,{children:"Rolle"}),e.jsx(y,{children:"Status"}),e.jsx(y,{align:"right",children:"Aktionen"})]})}),e.jsx(ge,{children:q.map(a=>e.jsxs(W,{children:[e.jsx(S,{children:e.jsx("span",{className:"font-medium text-ink-900",children:a.username})}),e.jsx(S,{children:Ue(a)}),e.jsx(S,{children:e.jsx("span",{className:"text-ink-600",children:a.email??"â"})}),e.jsx(S,{children:e.jsx(I,{variant:"brand",children:a.roleName})}),e.jsx(S,{children:e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[e.jsxs(I,{variant:a.isActive?"success":"neutral",className:"gap-1.5",children:[e.jsx("span",{className:A("h-1.5 w-1.5 rounded-full",a.isActive?"bg-emerald-500":"bg-ink-400"),"aria-hidden":!0}),a.isActive?"Aktiv":"Inaktiv"]}),a.passwordResetRequired&&e.jsx(I,{variant:"warning",children:"Passwort-Reset"})]})}),e.jsx(S,{align:"right",children:e.jsxs("div",{className:"flex items-center justify-end gap-0.5",children:[e.jsx(D,{label:`${a.username} bearbeiten`,onClick:()=>se(a),children:e.jsx(Ne,{size:14,strokeWidth:1.75})}),e.jsx(D,{label:`Passwort zurücksetzen für ${a.username}`,onClick:()=>s(a),children:e.jsx(Q,{size:14,strokeWidth:1.75})}),e.jsx(D,{label:`${a.username} ${a.isActive?"deaktivieren":"aktivieren"}`,danger:a.isActive,onClick:()=>d(a),children:e.jsx(Ee,{size:14,strokeWidth:1.75})})]})})]},a.id))})]})})]}),e.jsx(Me,{open:f,user:k,onClose:()=>p(!1)}),e.jsx(M,{open:o!=null,title:o!=null&&o.isActive?"Benutzer deaktivieren?":"Benutzer reaktivieren?",description:o!=null&&o.isActive?`"${o==null?void 0:o.username}" kann sich danach nicht mehr anmelden.`:`"${o==null?void 0:o.username}" erhält wieder Zugang.`,confirmLabel:o!=null&&o.isActive?"Deaktivieren":"Reaktivieren",busy:m.isPending,onConfirm:te,onCancel:()=>d(null)}),e.jsx(M,{open:h!=null,title:"Passwort zurücksetzen?",description:`Für "${h==null?void 0:h.username}" wird ein temporäres Passwort erzeugt. Es wird einmalig angezeigt.`,confirmLabel:"Zurücksetzen",busy:x.isPending,onConfirm:ie,onCancel:()=>s(null)}),e.jsx(M,{open:t!=null,title:"Temporäres Passwort",icon:e.jsx(Q,{size:18,strokeWidth:1.75}),confirmLabel:"SchlieÃen",cancelLabel:"SchlieÃen",onConfirm:()=>N(null),onCancel:()=>N(null),children:e.jsxs("div",{className:"flex flex-col gap-3 px-6 pb-4",children:[e.jsxs("p",{className:"m-0 text-[13px] text-ink-600",children:["Temporäres Passwort für"," ",e.jsx("span",{className:"font-semibold text-ink-900",children:t==null?void 0:t.username}),":"]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("code",{className:"flex-1 select-all rounded-md border border-ink-200 bg-ink-50 px-3 py-2 font-mono text-[14px] text-ink-900",children:t==null?void 0:t.tempPassword}),e.jsxs("button",{type:"button",onClick:re,className:"inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-md border border-ink-200 bg-white px-3 text-[13px] font-medium text-ink-700 transition-colors hover:bg-ink-50",children:[e.jsx(we,{size:13,strokeWidth:1.75}),"Kopieren"]})]}),e.jsx("p",{className:"m-0 text-[12px] text-ink-500",children:"Dieses Passwort wird nur einmal angezeigt. Bitte jetzt sicher kopieren und an den Benutzer übergeben."})]})})]})}function D({label:n,onClick:i,danger:r,children:c}){return e.jsx("button",{type:"button","aria-label":n,title:n,onClick:i,className:A("cursor-pointer rounded-md p-1.5 text-ink-400 transition-colors",r?"hover:bg-red-50 hover:text-red-600":"hover:bg-ink-100 hover:text-ink-700"),children:c})}function He({children:n}){return e.jsx(fe,{module:"users",children:n})}export{He as UsersGuard,Ye as UsersPage};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.