PageSourceSearch

https://wolfs-hotel.de/assets/buchungen-CL-2ZFuo.js

js wolfs-hotel.de collected 2026-10-07 05:06:19 UTC 48,724 bytes, 7 lines download raw bytes

1import{c as he,r as l,j as e,B as v,s as I,t as k,C as Pe,i as Fe,I as Je,L as Ye,J as We}from"./index-Ch2YoLWu.js";import{A as Qe,T as Xe}from"./AppLayout-CgENYHrH.js";import{R as es}from"./RequireRole-Dz5ojPPx.js";import{I as $}from"./input-DK_m2ngw.js";import{L as y}from"./label-CNVm_Fkv.js";import{T as Ge}from"./textarea-BTb9HKQQ.js";import{C as ae,a as oe,b as Be,c as De}from"./card-BN6QeaMX.js";import{D as ge,a as xe,b as pe,c as fe,d as je}from"./dialog-CQv4BJ8P.js";import{C as ss,S as se,a as te,b as ne,c as re,d as H}from"./select-Cg7nl58_.js";import{C as Y}from"./checkbox-1LjUOb_M.js";import{B as W}from"./badge-CyU3yHho.js";import{h as K,f as T,n as ce}from"./datum-CcDpj18J.js";import{P as ye}from"./plus-CRZ0fQHk.js";import{T as de}from"./trash-2-C-F7d23e.js";import{G as ts,P as ns}from"./GroupBlockDialog-CeghRgLi.js";import{C as rs}from"./chevron-left-BrAylzol.js";import{C as as}from"./chevron-right-pvNY5rb1.js";import{j as is,k as Ee,m as ls,n as cs,r as os,p as ds}from"./rateSettings-D49jJekQ.js";import{U as us}from"./upload-BZdsFm72.js";import{U as ms}from"./users-zu1MXLDI.js";import{D as Ae}from"./download-hGJ9YaKi.js";import{M as hs}from"./mail-B2esMP5g.js";import{S as gs}from"./sparkles-DzF9IO2m.js";import"./useLocation-oK4Cfs_I.js";import"./wolfs-hotel-logo-AR_Gx9na.js";import"./index-BmreDDth.js";import"./Combination-DoV2_22I.js";import"./x-Dt4XN4R_.js";import"./tabs-QC9fqtyi.js";import"./index-CsEM1CIP.js";const xs=[["path",{d:"M16 14v2.2l1.6 1",key:"fo4ql5"}],["path",{d:"M16 2v4",key:"4m81vk"}],["path",{d:"M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5",key:"1osxxc"}],["path",{d:"M3 10h5",key:"r794hk"}],["path",{d:"M8 2v4",key:"1cmpym"}],["circle",{cx:"16",cy:"16",r:"6",key:"qoo3c4"}]],ps=he("calendar-clock",xs);const fs=[["path",{d:"M4.2 4.2A2 2 0 0 0 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 1.82-1.18",key:"16swn3"}],["path",{d:"M21 15.5V6a2 2 0 0 0-2-2H9.5",key:"yhw86o"}],["path",{d:"M16 2v4",key:"4m81vk"}],["path",{d:"M3 10h7",key:"1wap6i"}],["path",{d:"M21 10h-5.5",key:"quycpq"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]],js=he("calendar-off",fs);const vs=[["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2",key:"1hopcy"}],["path",{d:"M16 2v4",key:"4m81vk"}],["path",{d:"M3 10h18",key:"8toen8"}],["path",{d:"M8 2v4",key:"1cmpym"}],["path",{d:"M17 14h-6",key:"bkmgh3"}],["path",{d:"M13 18H7",key:"bb0bb7"}],["path",{d:"M7 14h.01",key:"1qa3f1"}],["path",{d:"M17 18h.01",key:"1bdyru"}]],Te=he("calendar-range",vs);const Ns=[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]],ks=he("search",Ns);function bs(){const[u,m]=l.useState([]),[h,p]=l.useState(!1),[w,s]=l.useState(K()),[c,_]=l.useState(K()),[g,z]=l.useState(""),[B,S]=l.useState(!1);async function D(){const{data:a,error:N}=await I.from("online_booking_blackouts").select("*").order("von",{ascending:!0});N?k.error(N.message):m(a??[])}l.useEffect(()=>{D()},[]);async function R(){if(c<=w){k.error("Bis-Datum muss nach Von-Datum liegen");return}S(!0);const{error:a}=await I.from("online_booking_blackouts").insert({von:w,bis:c,grund:g||null});S(!1),a?k.error(a.message):(k.success("Sperrzeit angelegt"),p(!1),z(""),D())}async function j(a){const{error:N}=await I.from("online_booking_blackouts").delete().eq("id",a);N?k.error(N.message):(k.success("Sperrzeit gelöscht"),D())}const M=K(),E=u.filter(a=>a.bis>M),F=u.filter(a=>a.bis<=M);return e.jsxs(e.Fragment,{children:[e.jsx(ae,{className:"border-amber-500/40 bg-amber-50/30 dark:bg-amber-950/20",children:e.jsxs(oe,{className:"pt-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 mb-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(js,{className:"h-4 w-4 text-amber-600"}),e.jsx("span",{className:"font-medium text-sm",children:"Online-Buchungssperre"}),E.length>0&&e.jsxs(W,{variant:"destructive",className:"text-xs",children:[E.length," aktiv"]})]}),e.jsxs(v,{size:"sm",variant:"outline",onClick:()=>{s(K()),_(K()),z(""),p(!0)},children:[e.jsx(ye,{className:"h-3 w-3 mr-1"}),"Sperrzeit"]})]}),E.length===0&&F.length===0&&e.jsx("p",{className:"text-xs text-muted-foreground",children:"Keine Sperrzeiten definiert. Online-Buchungen sind uneingeschränkt möglich."}),E.length>0&&e.jsx("div",{className:"space-y-1",children:E.map(a=>e.jsxs("div",{className:"flex items-center justify-between gap-2 text-sm bg-amber-100/60 dark:bg-amber-900/30 rounded px-2 py-1",children:[e.jsxs("span",{children:[e.jsx("strong",{children:T(a.von)})," – ",e.jsx("strong",{children:T(a.bis)}),a.grund&&e.jsxs("span",{className:"ml-2 text-muted-foreground",children:["(",a.grund,")"]})]}),e.jsx(v,{size:"icon",variant:"ghost",className:"h-6 w-6",onClick:()=>j(a.id),children:e.jsx(de,{className:"h-3 w-3 text-destructive"})})]},a.id))}),F.length>0&&e.jsxs("details",{className:"mt-2",children:[e.jsxs("summary",{className:"text-xs text-muted-foreground cursor-pointer",children:["Vergangene Sperrzeiten (",F.length,")"]}),e.jsx("div",{className:"space-y-1 mt-1",children:F.map(a=>e.jsxs("div",{className:"flex items-center justify-between gap-2 text-xs opacity-60 px-2 py-0.5",children:[e.jsxs("span",{children:[T(a.von)," – ",T
1(a.bis)," ",a.grund&&`(${a.grund})`]}),e.jsx(v,{size:"icon",variant:"ghost",className:"h-5 w-5",onClick:()=>j(a.id),children:e.jsx(de,{className:"h-3 w-3"})})]},a.id))})]})]})}),e.jsx(ge,{open:h,onOpenChange:p,children:e.jsxs(xe,{className:"max-w-md",children:[e.jsx(pe,{children:e.jsx(fe,{children:"Online-Buchungssperre anlegen"})}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Online-Buchungen werden für den gewählten Zeitraum blockiert. Manuelle Buchungen und Zimmerzuweisungen bleiben weiterhin möglich."}),e.jsxs("div",{className:"grid gap-3 mt-2",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx(y,{children:"Von"}),e.jsx($,{type:"date",value:w,onChange:a=>s(a.target.value)})]}),e.jsxs("div",{children:[e.jsx(y,{children:"Bis"}),e.jsx($,{type:"date",value:c,onChange:a=>_(a.target.value)})]})]}),e.jsxs("div",{children:[e.jsx(y,{children:"Grund (optional)"}),e.jsx($,{value:g,onChange:a=>z(a.target.value),placeholder:"z.B. Renovierung, Betriebsferien…"})]})]}),e.jsxs(je,{children:[e.jsx(v,{variant:"outline",onClick:()=>p(!1),children:"Abbrechen"}),e.jsx(v,{onClick:R,disabled:B,children:B?"Speichert…":"Sperrzeit anlegen"})]})]})})]})}function ys(){const[u,m]=l.useState([]),[h,p]=l.useState(!1),[w,s]=l.useState(K()),[c,_]=l.useState(K()),[g,z]=l.useState(2),[B,S]=l.useState(""),[D,R]=l.useState(!1);async function j(){const{data:i,error:x}=await I.from("online_booking_min_stay").select("*").order("von",{ascending:!0});x?k.error(x.message):m(i??[])}l.useEffect(()=>{j()},[]);async function M(){if(c<=w){k.error("Bis-Datum muss nach Von-Datum liegen");return}if(g<2||g>14){k.error("Mindestaufenthalt: 2–14 Nächte");return}R(!0);const{error:i}=await I.from("online_booking_min_stay").insert({von:w,bis:c,min_naechte:g,grund:B||null});R(!1),i?k.error(i.message):(k.success("Mindestaufenthalt angelegt"),p(!1),S(""),j())}async function E(i){const{error:x}=await I.from("online_booking_min_stay").delete().eq("id",i);x?k.error(x.message):(k.success("Regel gelöscht"),j())}const F=K(),a=u.filter(i=>i.bis>F),N=u.filter(i=>i.bis<=F);return e.jsxs(e.Fragment,{children:[e.jsx(ae,{className:"border-blue-500/40 bg-blue-50/30 dark:bg-blue-950/20",children:e.jsxs(oe,{className:"pt-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 mb-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(ps,{className:"h-4 w-4 text-blue-600"}),e.jsx("span",{className:"font-medium text-sm",children:"Mindestaufenthalt (Online-Buchung)"}),a.length>0&&e.jsxs(W,{variant:"secondary",className:"text-xs",children:[a.length," aktiv"]})]}),e.jsxs(v,{size:"sm",variant:"outline",onClick:()=>{s(K()),_(K()),z(2),S(""),p(!0)},children:[e.jsx(ye,{className:"h-3 w-3 mr-1"}),"Regel"]})]}),a.length===0&&N.length===0&&e.jsx("p",{className:"text-xs text-muted-foreground",children:"Keine Mindestaufenthalts-Regeln. Online-Buchungen ab 1 Nacht möglich."}),a.length>0&&e.jsx("div",{className:"space-y-1",children:a.map(i=>e.jsxs("div",{className:"flex items-center justify-between gap-2 text-sm bg-blue-100/60 dark:bg-blue-900/30 rounded px-2 py-1",children:[e.jsxs("span",{children:[e.jsx("strong",{children:T(i.von)})," – ",e.jsx("strong",{children:T(i.bis)})," · min. ",e.jsx("strong",{children:i.min_naechte})," Nächte",i.grund&&e.jsxs("span",{className:"ml-2 text-muted-foreground",children:["(",i.grund,")"]})]}),e.jsx(v,{size:"icon",variant:"ghost",className:"h-6 w-6",onClick:()=>E(i.id),children:e.jsx(de,{className:"h-3 w-3 text-destructive"})})]},i.id))}),N.length>0&&e.jsxs("details",{className:"mt-2",children:[e.jsxs("summary",{className:"text-xs text-muted-foreground cursor-pointer",children:["Vergangene Regeln (",N.length,")"]}),e.jsx("div",{className:"space-y-1 mt-1",children:N.map(i=>e.jsxs("div",{className:"flex items-center justify-between gap-2 text-xs opacity-60 px-2 py-0.5",children:[e.jsxs("span",{children:[T(i.von)," – ",T(i.bis)," · min. ",i.min_naechte," N. ",i.grund&&`(${i.grund})`]}),e.jsx(v,{size:"icon",variant:"ghost",className:"h-5 w-5",onClick:()=>E(i.id),children:e.jsx(de,{className:"h-3 w-3"})})]},i.id))})]})]})}),e.jsx(ge,{open:h,onOpenChange:p,children:e.jsxs(xe,{className:"max-w-md",children:[e.jsx(pe,{children:e.jsx(fe,{children:"Mindestaufenthalt anlegen"})}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Online-Buchungen, deren Aufenthalt in diesen Zeitraum fällt, müssen mindestens die angegebene Anzahl Nächte umfassen. Manuelle Buchungen bleiben unberührt."}),e.jsxs("div",{className:"grid gap-3 mt-2",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx(y,{children:"Von"}),e.jsx($,{type:"date",value:w,onChange:i=>s(i.target.value)})]}),e.jsxs("div",{children:[e.jsx(y,{children:"Bis"}),e.jsx($,{type:"date",value:c,onChange:i=>_(i.target.value)})]})]}),e.jsxs("div",{children:[e.jsx(y,{children:"Mindestnächte"}),e.jsx($,{type:"number",min:2,max:14,value:g,onChange:i=>z(Number(i.target.value))})]}),e.jsxs("div",{children:[e.jsx(y,{children:"Grund (optional)"}),e.jsx($,{value:B,onChange:i=>S(i.target.value),placeholder:"z.B. Feiertag, Messe, Hochsaison…"})]})]}),e.jsxs(je,{children:[e.jsx(v,{variant:"outline",onClick:()=>p(!1),children:"Abbrechen"}),e.jsx(v,{onClick:M,disabled:D,children:D?"Speichert…":"Regel anlegen"})]})]})})]})}function ke(u,m){const[h,p,w]=u.split("-").map(Number),s=new Date(Date.UTC(h,p-1,w));return s.setUTCDate(s.getUTCDate()+m),s.toISOString().slice(0,10)}function _s(u,m){const h=new Date(Date.UTC(u,m,1)),p=new Date(Date.UTC(u,m+1,0)),w=(h.getUTCDay()+6)%7,s=[];for(let _=0;_<w;_++)s.push(null);for(let _=1;_<=p.getUTCDate();_++)s.push(`${u}-${String(m+1).padStart(2,"0")}-${String(_).padStart(2,"0")}`);for(;s.length%7!==0;)s.push(null);const c=[];for(let _=0;_<s.length;_+=7)c.push(s.slice(_,_+7));return c}function Le(u){const m=Math.max(0,Math.min(1,u));return m<.1?{bg:"var(--occupancy-0)",fg:"var(--occupancy-dark-fg)"}:m<.25?{bg:"var(--occupancy-10)",fg:"var(--occupancy-light-fg)"}:m<.4?{bg:"var(--occupancy-25)",fg:"var(--occupancy-light-fg)"}:m<.55?{bg:"var(--occupancy-40)",fg:"var(--occupancy-light-fg)"}:m<.7?{bg:"var(--occupancy-55)",fg:"var(--occupancy-light-fg)"}:m<.75?{bg:"var(--occupancy-70)",fg:"var(--occupancy-dark-fg)"}:{bg:"var(--occupancy-75)",fg:"var(--occupancy-dark-fg)"}}function Oe(u,m){return m<=0?0:Math.max(0,Math.min(1,u/m))}const ws=["Mo","Di","Mi","Do","Fr","Sa","So"],zs=["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],Ie="wh_heatmap_open";function Ss(u,m){return u>m?u:m}function Cs(u,m){return u<m?u:m}function Re(u){return typeof u=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(u)}function $s({onDayClick:u}={}){const[m,h]=l.useState(!1),[p,w]=l.useState(3),[s,c]=l.useState(0),[_,g]=l.useState(0),[z,B]=l.useState(new Map),[S,D]=l.useState(!1);l.useEffect(()=>{typeof window>"u"||h(window.localStorage.getItem(Ie)==="1")},[]);function R(){h(a=>{const N=!a;return typeof window<"u"&&window.localStorage.setItem(Ie,N?"1":"0"),N})}const j=K(),M=l.useMemo(()=>{const[a,N]=j.split("-").map(Number),i=new Date(Date.UTC(a,N-1+s,1));return`${i.getUTCFullYear()}
1-${String(i.getUTCMonth()+1).padStart(2,"0")}-01`},[j,s]),E=l.useMemo(()=>{const[a,N]=M.split("-").map(Number),i=new Date(Date.UTC(a,N-1+p,0));return`${i.getUTCFullYear()}-${String(i.getUTCMonth()+1).padStart(2,"0")}-${String(i.getUTCDate()).padStart(2,"0")}`},[M,p]);l.useEffect(()=>{if(!m)return;let a=!1;return(async()=>{D(!0);const[{data:N},{data:i}]=await Promise.all([I.from("zimmer").select("zimmer_nr").eq("aktiv",!0).neq("zimmer_nr","BOOKING-?"),I.from("buchungen").select("anreise,abreise,storniert,zimmer_nr").eq("storniert",!1).lt("anreise",ke(E,1)).gt("abreise",M).limit(5e3)]);if(a)return;const x=new Map,P=new Set((N??[]).map(C=>C.zimmer_nr)),n=27,O=ke(E,1),L=new Map,A=new Map,V=400;for(const C of i??[]){if(!C.zimmer_nr)continue;const Z=C.zimmer_nr==="BOOKING-?";if(!Z&&!P.has(C.zimmer_nr)||!Re(C.anreise)||!Re(C.abreise)||C.anreise>=C.abreise)continue;let U=Ss(C.anreise,M);const Q=Cs(C.abreise,O);let ue=0;for(;U<Q&&ue<V;){if(Z)A.set(U,(A.get(U)??0)+1);else{const X=L.get(U)??new Set;X.add(C.zimmer_nr),L.set(U,X)}U=ke(U,1),ue++}}const G=new Set([...L.keys(),...A.keys()]);for(const C of G){const Z=L.get(C)?.size??0,U=A.get(C)??0;x.set(C,Math.min(Z+U,n))}B(x),g(n),D(!1)})(),()=>{a=!0}},[m,M,E]);const F=l.useMemo(()=>{const[a,N]=M.split("-").map(Number);return Array.from({length:p},(i,x)=>{const P=new Date(Date.UTC(a,N-1+x,1));return{year:P.getUTCFullYear(),month:P.getUTCMonth()}})},[M,p]);return m?e.jsxs(ae,{children:[e.jsxs(Be,{className:"pb-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Te,{className:"h-4 w-4 text-muted-foreground"}),e.jsx(De,{className:"text-base",children:"Belegungs-Heatmap"})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("div",{className:"flex gap-1",children:[e.jsx(v,{size:"sm",variant:p===3?"default":"outline",onClick:()=>w(3),children:"3 Monate"}),e.jsx(v,{size:"sm",variant:p===6?"default":"outline",onClick:()=>w(6),children:"6 Monate"})]}),e.jsxs("div",{className:"flex gap-1",children:[e.jsx(v,{size:"sm",variant:"outline",onClick:()=>c(a=>a-1),children:e.jsx(rs,{className:"h-4 w-4"})}),e.jsx(v,{size:"sm",variant:"outline",onClick:()=>c(0),disabled:s===0,children:"Heute"}),e.jsx(v,{size:"sm",variant:"outline",onClick:()=>c(a=>a+1),children:e.jsx(as,{className:"h-4 w-4"})})]}),e.jsxs(v,{size:"sm",variant:"outline",onClick:R,children:[e.jsx(ss,{className:"h-4 w-4 mr-1"}),"Ausblenden"]})]})]}),e.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-2 text-xs text-muted-foreground",children:[e.jsx("span",{children:"Auslastung:"}),[{l:"<10%",p:.05},{l:"10–24%",p:.18},{l:"25–39%",p:.32},{l:"40–54%",p:.48},{l:"55–69%",p:.62},{l:"70–74%",p:.72},{l:"≥75%",p:.9}].map(a=>{const N=Le(a.p);return e.jsx("span",{className:"inline-flex h-5 items-center justify-center rounded px-2 text-[10px] font-medium",style:{background:N.bg,color:N.fg},children:a.l},a.l)}),e.jsxs("span",{className:"ml-2",children:["Kapazität: ",_," Zimmer"]})]})]}),e.jsx(oe,{children:S?e.jsx("div",{className:"text-sm text-muted-foreground py-6 text-center",children:"Lade…"}):e.jsx("div",{className:"grid gap-4 md:grid-cols-2 lg:grid-cols-3",children:F.map(({year:a,month:N})=>e.jsx(Ms,{year:a,month:N,kapazitaet:_,belegung:z,heute:j,onDayClick:u},`${a}-${N}`))})})]}):e.jsx(ae,{children:e.jsx(Be,{className:"py-3",children:e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Te,{className:"h-4 w-4 text-muted-foreground"}),e.jsx(De,{className:"text-base",children:"Belegungs-Heatmap"})]}),e.jsxs(v,{size:"sm",variant:"outline",onClick:R,children:[e.jsx(Pe,{className:"h-4 w-4 mr-1"}),"Anzeigen"]})]})})})}function Ms({year:u,month:m,kapazitaet:h,belegung:p,heute:w,onDayClick:s}){const c=l.useMemo(()=>_s(u,m),[u,m]),_=l.useMemo(()=>{let g=0,z=0;for(const B of c)for(const S of B){if(!S)continue;const D=Math.min(p.get(S)??0,h);g+=Oe(D,h),z++}return{avg:z>0?g/z:0,tage:z}},[c,p,h]);return e.jsxs("div",{className:"rounded-lg border p-3",children:[e.jsxs("div",{className:"mb-2 flex items-baseline justify-between",children:[e.jsxs("div",{className:"font-medium",children:[zs[m]," ",u]}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:["Ø ",Math.round(_.avg*100),"%"]})]}),e.jsx("div",{className:"grid grid-cols-7 gap-1 text-center text-[10px] text-muted-foreground mb-1",children:ws.map(g=>e.jsx("div",{children:g},g))}),e.jsx("div",{className:"grid grid-cols-7 gap-1",children:c.flat().map((g,z)=>{if(!g)return e.jsx("div",{className:"aspect-square"},z);const B=Math.min(p.get(g)??0,h),S=Oe(B,h),D=Le(S),R=Number(g.slice(8,10)),j=g===w,M=g<w,E=!!s;return e.jsxs("button",{type:"button",onClick:E?()=>s(g):void 0,disabled:!E,title:`${T(g)} — ${B}/${h} Zimmer (${Math.round(S*100)}%)${E?" · Klicken für Buchungen dieses Tages":""}`,className:`aspect-square rounded text-[10px] font-medium flex flex-col items-center justify-center leading-none ${M?"opacity-40":""} ${j?"ring-2 ring-foreground":""} ${E?"cursor-pointer hover:ring-2 hover:ring-primary transition-shadow":"cursor-default"}`,style:{background:D.bg,color:D.fg},children:[e.jsx("div",{children:R}),e.jsxs("div",{className:"text-[9px] opacity-80",children:[Math.round(S*100),"%"]})]},g)})})]})}const _e=[{value:"direkt",label:"Direkt",badge:"default"},{value:"walk_in",label:"Walk-in",badge:"default"},{value:"telefon",label:"Telefon",badge:"default"},{value:"website",label:"🌐 Website (Online-Buchung)",badge:"destructive"},{value:"booking.com",label:"Booking.com",badge:"secondary"},{value:"hrs",label:"HRS",badge:"outline"},{value:"bz_oharz",label:"BZ OHarz",badge:"outline"}];function be(u){return _e.find(m=>m.value===u)?.label??u??"—"}function Bs(u){return _e.find(m=>m.value===u)?.badge??"outline"}const Ke={nachname:"",vorname:"",zimmer_nr:"",anreise:K(),abreise:K(),erwachsene:1,kinder:0,hunde:0,angekommen:!1,angekommen_am:null,spaetankunft:!1,kontakt_email:"",kontakt_telefon:null,strasse:"",plz:"",ort:"",land:"",externe_buchungsnr:"",abgereist:!1,abgereist_am:null,tagessatz:null,reiseart:"freizeit",kurkarte_ausgefuellt:!1,haustuerschluessel_erhalten:!1,notizen:"",import_quelle:"direkt",geplante_kategorie:null,storniert:!1,bezahlt:!1,bezahlt_am:null};function Ds(){const u=new Date,m=u.getFullYear().toString().slice(-2),h=String(u.getMonth()+1).padStart(2,"0"),p=String(u.getDate()).padStart(2,"0"),w=Math.random().toString(36).slice(2,6).toUpperCase();return`WH-${m}${h}${p}-${w}`}function Es(u){const m=u.trim();if(!m)return null;if(/^\d{4}-\d{2}-\d{2}$/.test(m))return m;const h=m.match(/^(\d{1,2})\.(\d{1,2})\.?(\d{0,4})$/);if(!h)return null;const p=parseInt(h[1],10),w=parseInt(h[2],10);let s;if(!h[3])s=new Date().getFullYear();else if(h[3].length===2)s=2e3+parseInt(h[3],10);else if(h[3].length===4)s=parseInt(h[3],10);else return null;return p<1||p>31||w<1||w>12?null:`${String(s).padStart(4,"0")}-${String(w).padStart(2,"0")}-${String(p).padStart(2,"0")}`}function As(){const{role:u}=Fe(),m=u==="management",[h,p]=l.useState([]),[w,s]=l.useState([]),[c,_]=l.useState(""),[g,z]=l.useState(null),[B,S]=l.useState("kommend"),[D,R]=l.useState(!1),[j,M]=l.useState(null),[E,F]=l.useState(!1),[a,N]=l.useState(null),[i,x]=l.useState(new Set);function P(t){x(o=>{const r=new Set(o);return r.has(t)?r.delete(t):r.add(t),r})}function ie(){x(new Set)}function n(t){const o="=".repeat(60);return t.map((r,b)=>
1{const d=ce(r.anreise,r.abreise),f=`${r.nachname}${r.vorname?", "+r.vorname:""}`,ee=[r.strasse,[r.plz,r.ort].filter(Boolean).join(" "),r.land].filter(Boolean).join(", "),Me=r.tagessatz!=null?(Number(r.tagessatz)*d).toFixed(2):null;return[o,`Buchung ${b+1} von ${t.length}`,o,`Name:           ${f}`,`Zimmer:         ${r.zimmer_nr}${r.geplante_kategorie?" ("+r.geplante_kategorie+")":""}`,`Anreise:        ${T(r.anreise)}`,`Abreise:        ${T(r.abreise)}`,`Nächte:         ${d}`,`Gäste:          ${r.erwachsene} Erw.${r.kinder?", "+r.kinder+" Kind(er)":""}${r.hunde?", "+r.hunde+" Hund(e)":""}`,`Reiseart:       ${r.reiseart==="geschaeftlich"?"Geschäftlich":"Freizeit"}`,r.kontakt_email?`E-Mail:         ${r.kontakt_email}`:null,r.kontakt_telefon?`Telefon:        ${r.kontakt_telefon}`:null,ee?`Adresse:        ${ee}`:null,r.tagessatz!=null?`Tagessatz:      € ${Number(r.tagessatz).toFixed(2)}`:null,Me?`Gesamtpreis:    € ${Me}`:null,r.externe_buchungsnr?`Buchungsnr.:    ${r.externe_buchungsnr}`:null,r.import_quelle?`Quelle:         ${be(r.import_quelle)}`:null,r.notizen?`Notizen:        ${r.notizen}`:null].filter(Boolean).join(`
2`)}).join(`
3
4`)+`
5`+"=".repeat(60)+`
6`}function O(t){const o=["Nachname","Vorname","Zimmer","Kategorie","Anreise","Abreise","Nächte","Erwachsene","Kinder","Hunde","Reiseart","Email","Telefon","Strasse","PLZ","Ort","Land","Tagessatz","Gesamtpreis","Buchungsnr","Quelle","Notizen"],r=d=>{const f=d==null?"":String(d);return/[";\n,]/.test(f)?`"${f.replace(/"/g,'""')}"`:f},b=[o.join(",")];for(const d of t){const f=ce(d.anreise,d.abreise),ee=d.tagessatz!=null?(Number(d.tagessatz)*f).toFixed(2):"";b.push([d.nachname,d.vorname??"",d.zimmer_nr,d.geplante_kategorie??"",d.anreise,d.abreise,f,d.erwachsene,d.kinder,d.hunde,d.reiseart==="geschaeftlich"?"Geschäftlich":"Freizeit",d.kontakt_email??"",d.kontakt_telefon??"",d.strasse??"",d.plz??"",d.ort??"",d.land??"",d.tagessatz!=null?Number(d.tagessatz).toFixed(2):"",ee,d.externe_buchungsnr??"",be(d.import_quelle),(d.notizen??"").replace(/\n/g," ")].map(r).join(","))}return b.join(`
7`)}function L(t,o,r){const b=new Blob([t],{type:r+";charset=utf-8"}),d=URL.createObjectURL(b),f=document.createElement("a");f.href=d,f.download=o,document.body.appendChild(f),f.click(),document.body.removeChild(f),URL.revokeObjectURL(d)}function A(t){const o=h.filter(b=>i.has(b.id));if(o.length===0){k.error("Keine Buchungen ausgewählt");return}o.sort((b,d)=>b.anreise.localeCompare(d.anreise));const r=new Date().toISOString().slice(0,10);t==="txt"?L(n(o),`buchungen-${r}.txt`,"text/plain"):L("\uFEFF"+O(o),`buchungen-${r}.csv`,"text/csv"),k.success(`${o.length} Buchung(en) exportiert`)}async function V(t){if(!t.kontakt_email){k.error("Keine E-Mail-Adresse hinterlegt");return}N(t.id);try{const o=await We({data:{buchungId:t.id}});o.ok?k.success(`Bestätigung erneut gesendet an ${t.kontakt_email}`):k.error(o.error||"Fehler beim Senden")}catch{k.error("Fehler beim Senden der Bestätigung")}finally{N(null)}}async function G(){const{data:t,error:o}=await I.from("buchungen").select("*").order("anreise",{ascending:!0});o?k.error(o.message):p(t??[])}async function C(){const{data:t}=await I.from("zimmer").select("zimmer_nr, kategorie, max_belegung, notizen, aktiv, rack_rate, hunde_erlaubt").eq("aktiv",!0),o=(t??[]).slice().sort((r,b)=>{const d=parseInt(r.zimmer_nr,10),f=parseInt(b.zimmer_nr,10);return isNaN(d)||isNaN(f)?r.zimmer_nr.localeCompare(b.zimmer_nr):d-f});s(o)}l.useEffect(()=>{G(),C()},[]);const Z=Je.useSearch();l.useEffect(()=>{Z.neu===1&&we()},[Z.neu]),l.useEffect(()=>{if(Z.edit&&h.length>0){const t=h.find(o=>o.id===Z.edit);t&&ze(t)}},[Z.edit,h]);const U=K(),Q=h.filter(t=>{const o=c.trim().toLowerCase();if(o&&!`${t.nachname} ${t.vorname??""} ${t.zimmer_nr}`.toLowerCase().includes(o))return!1;if(g){const r=t.anreise<=g&&g<t.abreise,b=t.abreise===g;return!r&&!b?!1:B==="storniert"?t.storniert===!0:!t.storniert}return B==="storniert"?t.storniert===!0:!(t.storniert||B==="kommend"&&t.anreise<U||B==="aktuell"&&(!t.angekommen||t.abgereist||t.abreise<=U)||B==="vergangen"&&t.abreise>=U&&!t.abgereist)}),ue=Date.now()-1440*60*1e3,X=t=>!!t.erstellt_am&&new Date(t.erstellt_am).getTime()>ue,le=[...Q].sort((t,o)=>{const r=X(t),b=X(o);return r&&!b?-1:!r&&b?1:r&&b?new Date(o.erstellt_am).getTime()-new Date(t.erstellt_am).getTime():0}),Ze=l.useMemo(()=>{const t=new Map;for(const r of h){if(!r.externe_buchungsnr)continue;const b=r.externe_buchungsnr.replace(/-\d+$/,""),d=t.get(b)||[];
7d.push(r.id),t.set(b,d)}const o=new Map;for(const[,r]of t)r.length<2||r.forEach((b,d)=>o.set(b,{index:d+1,total:r.length}));return o},[h]);function Ue(t){return g?t.anreise===g?"Anreise":t.abreise===g?"Abreise":t.anreise<g&&g<t.abreise?"Bleiber":null:null}function we(){M({id:"",...Ke}),R(!0)}function ze(t){M(t),R(!0)}const[q,me]=l.useState(null),[J,Se]=l.useState("kunde_storniert"),[ve,Ce]=l.useState(""),[Ne,$e]=l.useState(!1);function qe(t){me(t),Se("kunde_storniert"),Ce("")}async function Ve(){if(!q)return;if(J==="sonstiges"&&ve.trim().length<3){k.error("Bitte einen kurzen Grund angeben");return}$e(!0);const t=J==="kunde_storniert"?"Kunde storniert":J==="doppelbuchung"?"Doppelbuchung":J==="fehlbuchung"?"Fehlbuchung":"Sonstiges";await I.from("audit_log").insert({aktion:"DELETE_REASON",tabelle:"buchungen",datensatz_id:q.id,details:{grund:J,grund_label:t,notiz:ve.trim()||null,zimmer_nr:q.zimmer_nr,nachname:q.nachname,anreise:q.anreise,abreise:q.abreise}});const{error:o}=await I.from("buchungen").delete().eq("id",q.id);if($e(!1),o){k.error(o.message);return}k.success(`Gelöscht (${t})`),me(null),G()}async function He(t,o){p(b=>b.map(d=>d.id===t.id?{...d,...o}:d));const{error:r}=await I.from("buchungen").update(o).eq("id",t.id);r&&k.error(r.message),G()}return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[e.jsx("h1",{className:"text-2xl font-semibold",children:"Buchungen"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(v,{variant:"outline",asChild:!0,children:e.jsxs(Ye,{to:"/import",children:[e.jsx(us,{className:"h-4 w-4 mr-1"}),"Import"]})}),e.jsxs(v,{variant:"outline",onClick:()=>F(!0),children:[e.jsx(ms,{className:"h-4 w-4 mr-1"}),"Gruppenblock"]}),e.jsxs(v,{onClick:we,children:[e.jsx(ye,{className:"h-4 w-4 mr-1"}),"Neue Buchung"]})]})]}),e.jsx(ts,{open:E,onOpenChange:F,onSaved:G}),e.jsxs("div",{className:"grid gap-3 md:grid-cols-2",children:[e.jsx(bs,{}),e.jsx(ys,{})]}),e.jsx($s,{onDayClick:t=>{z(t),S("alle")}}),e.jsx(ae,{children:e.jsxs(oe,{className:"pt-4 flex flex-wrap gap-2",children:[e.jsxs("div",{className:"relative flex-1 min-w-[200px]",children:[e.jsx(ks,{className:"h-4 w-4 absolute left-2 top-2.5 text-muted-foreground"}),e.jsx($,{className:"pl-8",placeholder:"Name, Zimmer oder Datum (TT.MM.JJJJ)…",value:c,onChange:t=>{const o=t.target.value;_(o);const r=Es(o);r?(z(r),S("alle")):g&&!o.trim()&&z(null)}})]}),e.jsx("div",{className:"flex gap-1 flex-wrap",children:["kommend","aktuell","vergangen","alle","storniert"].map(t=>{const o=t==="storniert"?h.filter(r=>r.storniert).length:null;return e.jsx(v,{variant:B===t?"default":"outline",size:"sm",onClick:()=>{S(t),z(null)},children:t==="kommend"?"Kommend":t==="aktuell"?"Im Haus":t==="vergangen"?"Vergangen":t==="storniert"?`Storniert${o?` (${o})`:""}`:"Alle"},t)})}),g&&e.jsxs("div",{className:"w-full flex items-center gap-2 pt-1",children:[e.jsxs(W,{variant:"secondary",className:"gap-2",children:["Tagesansicht: ",T(g)," · Anreisen ",Q.filter(t=>t.anreise===g&&!t.storniert).length," · Abreisen ",Q.filter(t=>t.abreise===g&&!t.storniert).length," · Bleiber ",Q.filter(t=>t.anreise<g&&g<t.abreise&&!t.storniert).length]}),e.jsx(v,{size:"sm",variant:"ghost",onClick:()=>{z(null),_("")},children:"Filter aufheben"})]})]})}),e.jsx(ae,{children:e.jsxs(oe,{className:"p-0",children:[i.size>0&&e.jsxs("div",{className:"flex items-center justify-between gap-2 px-3 py-2 border-b bg-primary/5",children:[e.jsxs("div",{className:"text-sm",children:[e.jsx("strong",{children:i.size})," Buchung(en) ausgewählt"]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(v,{size:"sm",variant:"outline",onClick:()=>A("txt"),children:[e.jsx(Ae,{className:"h-4 w-4 mr-1"}),"Als TXT"]}),e.jsxs(v,{size:"sm",variant:"outline",onClick:()=>A("csv"),children:[e.jsx(Ae,{className:"h-4 w-4 mr-1"}),"Als CSV"]}),e.jsx(v,{size:"sm",variant:"ghost",onClick:ie,children:"Auswahl leeren"})]})]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"text-left text-muted-foreground border-b bg-muted/50",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-2 py-2 border-r w-[36px]",children:e.jsx(Y,{checked:le.length>0&&le.every(t=>i.has(t.id)),onCheckedChange:t=>{t?x(new Set(le.map(o=>o.id))):ie()}
7,"aria-label":"Alle auswählen"})}),e.jsx("th",{className:"px-3 py-2 border-r",children:"Erstellt"}),e.jsx("th",{className:"px-2 py-2 border-r w-[110px]",children:"Zi."}),e.jsx("th",{className:"px-2 py-2 border-r",children:"Name"}),e.jsx("th",{className:"px-2 py-2 border-r",children:"Quelle"}),e.jsx("th",{className:"px-2 py-2 border-r",children:"Anreise"}),e.jsx("th",{className:"px-2 py-2 border-r",children:"Abreise"}),e.jsx("th",{className:"px-2 py-2 border-r",children:"Nächte"}),e.jsx("th",{className:"px-2 py-2 border-r",children:"Gäste"}),e.jsx("th",{className:"px-2 py-2 border-r",children:"🐕"}),e.jsx("th",{className:"px-2 py-2 border-r",children:"Satz"}),e.jsx("th",{className:"px-2 py-2 border-r",children:"Reise"}),e.jsx("th",{className:"px-2 py-2 border-r",children:"Status"}),e.jsx("th",{className:"px-2 py-2 text-right pr-3",children:"Aktion"})]})}),e.jsxs("tbody",{children:[le.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:14,className:"text-center py-6 text-muted-foreground",children:"Keine Buchungen."})}),le.map(t=>{const o=ce(t.anreise,t.abreise),r=t.tagessatz!=null?t.tagessatz*o:null,b=t.zimmer_nr?.startsWith("BOOKING-")||/entwurf/i.test(t.zimmer_nr??""),d=X(t);return e.jsxs("tr",{className:`border-b hover:bg-muted/30 ${t.storniert?"opacity-60":""} ${d?"border-l-4 border-l-primary bg-primary/5":""}`,children:[e.jsx("td",{className:"px-2 py-2 border-r",children:e.jsx(Y,{checked:i.has(t.id),onCheckedChange:()=>P(t.id),"aria-label":"Buchung auswählen"})}),e.jsxs("td",{className:"px-3 py-2 border-r whitespace-nowrap text-muted-foreground",title:t.erstellt_am?new Date(t.erstellt_am).toLocaleString("de-DE"):"",children:[t.erstellt_am?T(t.erstellt_am):"—",d&&e.jsx(W,{variant:"default",className:"ml-1.5 text-[10px] px-1 py-0 leading-tight",children:"Neu"})]}),e.jsx("td",{className:"px-2 py-2 border-r font-medium w-[110px]",children:e.jsxs(se,{value:t.zimmer_nr,onValueChange:f=>{f!==t.zimmer_nr&&He(t,{zimmer_nr:f})},children:[e.jsx(te,{className:`h-7 px-2 py-0 text-xs w-full min-w-0 gap-1 ${b?"border-amber-500 text-amber-700 dark:text-amber-400":"border-transparent hover:border-input"}`,children:e.jsx(ne,{children:b?"Room tba":t.zimmer_nr})}),e.jsx(re,{children:w.map(f=>e.jsxs(H,{value:f.zimmer_nr,children:[f.zimmer_nr," — ",f.kategorie," (max ",f.max_belegung,")"]},f.zimmer_nr))})]})}),e.jsx("td",{className:"px-2 py-2 border-r",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("span",{children:[t.nachname,t.vorname?`, ${t.vorname}`:""]}),(()=>{const f=Ze.get(t.id);return f?e.jsxs(W,{variant:"outline",className:"font-normal text-[10px] bg-blue-50 dark:bg-blue-950 border-blue-200 dark:border-blue-800",children:[f.index,"/",f.total," Zi."]}):null})(),(()=>{const f=Ue(t);if(!f)return null;const ee=f==="Anreise"?"default":f==="Abreise"?"outline":"secondary";return e.jsx(W,{variant:ee,className:"font-normal text-[10px]",children:f})})()]})}),e.jsx("td",{className:"px-2 py-2 border-r",children:e.jsx(W,{variant:Bs(t.import_quelle),className:"font-normal",children:be(t.import_quelle)})}),e.jsx("td",{className:"px-2 py-2 border-r",children:T(t.anreise)}),e.jsx("td",{className:"px-2 py-2 border-r",children:T(t.abreise)}),e.jsx("td",{className:"px-2 py-2 border-r",children:o}),e.jsx("td",{className:"px-2 py-2 border-r",children:t.erwachsene+t.kinder}),e.jsx("td",{className:"px-2 py-2 border-r",children:t.hunde||""}),e.jsx("td",{className:"px-2 py-2 border-r whitespace-nowrap",children:t.tagessatz!=null?e.jsxs("span",{title:`${o} × € ${Number(t.tagessatz).toFixed(2)} = € ${r?.toFixed(2)}`,children:["€ ",Number(t.tagessatz).toFixed(2)]}):e.jsx("span",{className:"text-muted-foreground",children:"—"})}),e.jsx("td",{className:"px-2 py-2 border-r",title:t.reiseart==="geschaeftlich"?"Geschäftlich":"Freizeit",children:t.reiseart==="geschaeftlich"?"💼":"🏖"}),e.jsx("td",{className:"px-2 py-2 border-r",children:t.storniert?e.jsx(W,{variant:"destructive",className:"font-normal",children:"Storniert"}):t.abgereist?e.jsxs("span",{className:"text-muted-foreground",children:["⮕ ",t.abgereist_am?new Date(t.abgereist_am).toLocaleTimeString("de-DE",{hour:"2-digit",minute:"2-digit"}):"ab"]}):t.angekommen?e.jsxs("span",{className:"text-accent-foreground",title:`🔑 ${t.haustuerschluessel_erhalten?"ja":"nein"} · Kurkarte ${t.kurkarte_ausgefuellt?"✓":"—"}`,children:["✓",t.angekommen_am?` ${new Date(t.angekommen_am).toLocaleTimeString("de-DE",{hour:"2-digit",minute:"2-digit"})}`:""]}):e.jsx("span",{className:"text-muted-foreground",children:t.spaetankunft?"🌙 spät":"–"})}),e.jsxs("td",{className:"px-2 py-2 text-right pr-3 whitespace-nowrap",children:[t.kontakt_email&&!t.storniert&&e.jsx(v,{size:"sm",variant:"ghost",title:"Bestätigung erneut senden",disabled:a===t.id,onClick:()=>V(t),children:e.jsx(hs,{className:"h-4 w-4"})}),e.jsx(v,{size:"sm",variant:"ghost",onClick:()=>ze(t),children:e.jsx(ns,{className:"h-4 w-4"})}),m&&e.jsx(v,{size:"sm",variant:"ghost",onClick:()=>qe(t),children:e.jsx(de,{className:"h-4 w-4 text-destructive"})})]})]},t.id)})]})]})})]})}),e.jsx(Ts,{open:D,onOpenChange:R,buchung:j,onSaved:()=>{R(!1),G()}}),e.jsx(ge,{open:!!q,onOpenChange:t=>!t&&me(null),children:e.jsxs(xe,{className:"max-w-md",children:[e.jsx(pe,{children:e.jsx(fe,{children:"Buchung löschen"})}),q&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"rounded-md border bg-muted/30 p-3 text-sm",children:[e.jsxs("div",{children:[e.jsx("strong",{children:q.nachname})," · Zi. ",q.zimmer_nr]}),e.jsxs("div",{className:"text-muted-foreground",children:[T(q.anreise)," → ",T(q.abreise)]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(y,{children:"Grund *"}),e.jsxs(se,{value:J,onValueChange:t=>Se(t),children:[e.jsx(te,{children:e.jsx(ne,{})}),e.jsxs(re,{children:[e.jsx(H,{value:"kunde_storniert",children:"Kunde storniert"}),e.jsx(H,{value:"doppelbuchung",children:"Doppelbuchung"}),e.jsx(H,{value:"fehlbuchung",children:"Fehlbuchung"}),e.jsx(H,{value:"sonstiges",children:"Sonstiges"})]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs(y,{children:["Notiz ",J==="sonstiges"?"*":"(optional)"]}),e.jsx(Ge,{value:ve,onChange:t=>Ce(t.target.value),maxLength:500,placeholder:J==="sonstiges"?"Bitte Grund angeben…"
7:"Zusätzliche Information…"})]})]}),e.jsxs(je,{children:[e.jsx(v,{variant:"outline",onClick:()=>me(null),disabled:Ne,children:"Abbrechen"}),e.jsx(v,{variant:"destructive",onClick:Ve,disabled:Ne,children:Ne?"Lösche…":"Endgültig löschen"})]})]})})]})}function Ts({open:u,onOpenChange:m,buchung:h,onSaved:p}){const{user:w}=Fe(),[s,c]=l.useState(Ke),[_,g]=l.useState(!1),[z,B]=l.useState([]),[S,D]=l.useState(null);l.useEffect(()=>{if(h){const{id:n,...O}=h;c(O)}},[h]);const[,R]=l.useState(0);l.useEffect(()=>{u&&(I.from("zimmer").select("zimmer_nr, kategorie, max_belegung, notizen, aktiv, rack_rate, hunde_erlaubt").eq("aktiv",!0).then(({data:n,error:O})=>{if(O){k.error(O.message);return}const L=(n??[]).slice().sort((A,V)=>{const G=parseInt(A.zimmer_nr,10),C=parseInt(V.zimmer_nr,10);return isNaN(G)||isNaN(C)?A.zimmer_nr.localeCompare(V.zimmer_nr):G-C});B(L)}),ds()||is().then(()=>R(n=>n+1)))},[u]);const j=z.find(n=>n.zimmer_nr===s.zimmer_nr),M=s.zimmer_nr==="BOOKING-?"||s.zimmer_nr==="",E=s.erwachsene+s.kinder,F=!M&&j&&E>j.max_belegung,a=!M&&!!j&&s.hunde>0&&!j.hunde_erlaubt,N=Array.from(new Set(z.filter(n=>n.zimmer_nr!=="BOOKING-?").map(n=>n.kategorie))).sort(),i=h?.id==="",x=(()=>
7{if(!s.anreise||!s.abreise||s.abreise<=s.anreise)return null;let n=null;if(j&&!M)n=Ee(j.kategorie,j.max_belegung);else if(s.geplante_kategorie){const C=z.find(Z=>Z.kategorie===s.geplante_kategorie&&Z.zimmer_nr!=="BOOKING-?");C&&(n=Ee(C.kategorie,C.max_belegung))}if(!n)return null;const{budgetAvg:O,clzAvg:L,budgetComps:A,clzComps:V,discountPct:G}=ls();return cs(os(n),s.anreise,s.abreise,O,L,G,A,V)})();l.useEffect(()=>{i&&x&&s.tagessatz==null&&c(n=>({...n,tagessatz:x.avg}))},[s.zimmer_nr,s.geplante_kategorie,s.anreise,s.abreise,i]);const P=x&&s.tagessatz!=null&&s.tagessatz>0?s.tagessatz<x.avg*.9:!1;if(l.useEffect(()=>{if(!u||!s.zimmer_nr||!s.anreise||!s.abreise){D(null);return}if(s.abreise<=s.anreise){D(null);return}if(s.zimmer_nr==="BOOKING-?"){D(null);return}const n=new AbortController;return(async()=>{const{data:O,error:L}=await I.from("buchungen").select("id, anreise, abreise, nachname, storniert").eq("zimmer_nr",s.zimmer_nr).eq("storniert",!1).lt("anreise",s.abreise).gt("abreise",s.anreise);if(L||n.signal.aborted)return;const A=(O??[]).find(V=>V.id!==h?.id);D(A?`Konflikt: ${A.nachname} (${T(A.anreise)} → ${T(A.abreise)})`:null)})(),()=>n.abort()},[u,s.zimmer_nr,s.anreise,s.abreise,h?.id]),!h)return null;async function ie(){if(!s.nachname.trim()||!s.zimmer_nr.trim()){k.error("Nachname und Zimmer sind erforderlich");return}if(s.abreise<=s.anreise){k.error("Abreise muss nach Anreise liegen");return}if(F){k.error(`Zimmer ${s.zimmer_nr} erlaubt max. ${j?.max_belegung} Gäste`);return}if(a){k.error(`Zimmer ${s.zimmer_nr} erlaubt keine Hunde`);return}if(S){k.error(S);return}g(!0);const n=new Set(["direkt","walk_in","telefon"]),O=s.import_quelle??"direkt",L=s.externe_buchungsnr&&s.externe_buchungsnr.trim().length>0?s.externe_buchungsnr.trim():i&&n.has(O)?Ds():null,A={...s,notizen:s.notizen||null,vorname:s.vorname||null,kontakt_email:s.kontakt_email||null,strasse:s.strasse||null,plz:s.plz||null,ort:s.ort||null,land:s.land||null,externe_buchungsnr:L},V=i?I.from("buchungen").insert({...A,erstellt_von:w?.id}):I.from("buchungen").update(A).eq("id",h.id),{error:G}=await V;g(!1),G?k.error(G.message):(k.success(i?"Angelegt":"Aktualisiert"),p())}return e.jsx(ge,{open:u,onOpenChange:m,children:e.jsxs(xe,{className:"flex h-[min(720px,calc(100dvh-2rem))] max-h-[calc(100dvh-2rem)] w-[calc(100vw-2rem)] max-w-xl flex-col overflow-hidden p-4",children:[e.jsx(pe,{className:"shrink-0 pr-8",children:e.jsx(fe,{children:i?"Neue Buchung":"Buchung bearbeiten"})}),e.jsxs("div",{className:"grid min-h-0 flex-1 grid-cols-1 gap-3 overflow-y-auto pr-1 sm:grid-cols-2",children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"Nachname *"}),e.jsx($,{value:s.nachname,onChange:n=>c({...s,nachname:n.target.value})})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"Vorname"}),e.jsx($,{value:s.vorname??"",onChange:n=>c({...s,vorname:n.target.value})})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"Telefon"}),e.jsx($,{type:"tel",value:s.kontakt_telefon??"",onChange:n=>c({...s,kontakt_telefon:n.target.value||null})})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"E-Mail"}),e.jsx($,{type:"email",value:s.kontakt_email??"",onChange:n=>c({...s,kontakt_email:n.target.value||null})})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"Erwachsene"}),e.jsx($,{type:"number",min:0,value:s.erwachsene,onChange:n=>c({...s,erwachsene:+n.target.value})})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"Kinder"}),e.jsx($,{type:"number",min:0,value:s.kinder,onChange:n=>c({...s,kinder:+n.target.value})})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"Hunde"}),e.jsx($,{type:"number",min:0,value:s.hunde,onChange:n=>c({...s,hunde:+n.target.value})})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"Anreise"}),e.jsx($,{type:"date",value:s.anreise,onChange:n=>c({...s,anreise:n.target.value})})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"Abreise"}),e.jsx($,{type:"date",value:s.abreise,onChange:n=>c({...s,abreise:n.target.value})})]}),e.jsxs("div",{className:"space-y-1.5 col-span-2",children:[e.jsxs(y,{children:["Tagessatz (€)",x&&e.jsxs("span",{className:"text-xs text-muted-foreground ml-1",children:["Engine-Ø: € ",x.avg,x.hasVariance&&` (${x.min}–${x.max})`]}),j?.rack_rate!=null&&e.jsxs("span",{className:"text-xs text-muted-foreground ml-2",children:["· Rack: € ",Number(j.rack_rate).toFixed(2)]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx($,{type:"number",min:0,step:"0.01",value:s.tagessatz??"",onChange:n=>c({...s,tagessatz:n.target.value===""?null:+n.target.value}),placeholder:x?String(x.avg):j?.rack_rate!=null?String(j.rack_rate):"z.B. 120.00",className:"max-w-[160px]"}),x&&e.jsxs(v,{type:"button",size:"sm",variant:"outline",onClick:()=>c({...s,tagessatz:x.avg}),title:"Engine-Empfehlung als Tagessatz übernehmen",children:[e.jsx(gs,{className:"h-3.5 w-3.5 mr-1"})," Engine € ",x.avg]}),s.tagessatz!=null&&s.tagessatz>0&&s.abreise>s.anreise&&e.jsxs("span",{className:"text-sm text-muted-foreground whitespace-nowrap",children:["× ",ce(s.anreise,s.abreise)," N. = € ",(s.tagessatz*ce(s.anreise,s.abreise)).toFixed(2)]})]}
7),P&&x&&e.jsxs("p",{className:"text-xs text-amber-600 dark:text-amber-500 flex items-center gap-1",children:[e.jsx(Xe,{className:"h-3.5 w-3.5"}),"Tagessatz liegt ",Math.round((1-s.tagessatz/x.avg)*100),"% unter Engine-Empfehlung (€ ",x.avg,")."]}),!i&&x&&s.tagessatz!=null&&Math.abs(s.tagessatz-x.avg)>1&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:["ℹ Gebuchte Rate € ",Number(s.tagessatz).toFixed(2)," bleibt erhalten (folgt dem Gast). Engine-Empfehlung für aktuelles Zimmer/Zeitraum: € ",x.avg,"."]}),x&&x.hasVariance&&e.jsxs("details",{className:"text-xs",children:[e.jsxs("summary",{className:"cursor-pointer text-muted-foreground hover:text-foreground",children:["Pro-Nacht-Aufschlüsselung anzeigen (",x.nights.length," Nächte, Gesamt € ",x.total,")"]}),e.jsx("div",{className:"mt-2 overflow-x-auto rounded border",children:e.jsxs("table",{className:"w-full text-xs",children:[e.jsx("thead",{className:"bg-muted/50 text-left",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-2 py-1",children:"Datum"}),e.jsx("th",{className:"px-2 py-1",children:"Tag"}),e.jsx("th",{className:"px-2 py-1 text-right",children:"Rate"}),e.jsx("th",{className:"px-2 py-1",children:"Event"})]})}),e.jsx("tbody",{children:x.nights.map(n=>e.jsxs("tr",{className:"border-t",children:[e.jsx("td",{className:"px-2 py-1",children:T(n.date)}),e.jsx("td",{className:"px-2 py-1",children:n.dow}),e.jsxs("td",{className:"px-2 py-1 text-right font-medium",children:["€ ",n.rate]}),e.jsx("td",{className:"px-2 py-1 text-muted-foreground",children:n.event??""})]},n.date))})]})})]})]}),e.jsxs("div",{className:"col-span-2 rounded-md border bg-muted/20 p-3 space-y-2",children:[e.jsx("p",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wide mb-1",children:"Status"}),e.jsxs("div",{className:"flex flex-wrap gap-x-6 gap-y-2",children:[e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[e.jsx(Y,{checked:s.angekommen,onCheckedChange:n=>c({...s,angekommen:!!n})}),e.jsxs("span",{className:"text-sm",children:["Angekommen",s.angekommen_am&&` (${new Date(s.angekommen_am).toLocaleString("de-DE",{dateStyle:"short",timeStyle:"short"})})`]})]}),e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[e.jsx(Y,{checked:s.spaetankunft,onCheckedChange:n=>c({...s,spaetankunft:!!n})}),e.jsx("span",{className:"text-sm",children:"Spätankunft"})]}),e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[e.jsx(Y,{checked:s.abgereist,onCheckedChange:n=>c({...s,abgereist:!!n})}),e.jsxs("span",{className:"text-sm",children:["Abgereist",s.abgereist_am&&` (${new Date(s.abgereist_am).toLocaleString("de-DE",{dateStyle:"short",timeStyle:"short"})})`]})]}),e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[e.jsx(Y,{checked:s.kurkarte_ausgefuellt,onCheckedChange:n=>c({...s,kurkarte_ausgefuellt:!!n})}),e.jsx("span",{className:"text-sm",children:"Kurkarte"})]}),e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[e.jsx(Y,{checked:s.haustuerschluessel_erhalten,onCheckedChange:n=>c({...s,haustuerschluessel_erhalten:!!n})}),e.jsx("span",{className:"text-sm",children:"🔑 Schlüssel"})]}),e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[e.jsx(Y,{checked:s.bezahlt,onCheckedChange:n=>{const O=!!n;c({...s,bezahlt:O,bezahlt_am:O?new Date().toISOString():null})}}),e.jsxs("span",{className:"text-sm",children:["💰 Bezahlt",s.bezahlt_am&&` (${new Date(s.bezahlt_am).toLocaleString("de-DE",{dateStyle:"short",timeStyle:"short"})})`]})]})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"Zimmer"}),e.jsxs(se,{value:s.zimmer_nr,onValueChange:n=>c({...s,zimmer_nr:n}),children:[e.jsx(te,{children:e.jsx(ne,{placeholder:"Zimmer wählen…"})}),e.jsxs(re,{children:[e.jsx(H,{value:"BOOKING-?",children:"🕒 Room tba (später zuweisen)"}),z.filter(n=>n.zimmer_nr!=="BOOKING-?").map(n=>e.jsxs(H,{value:n.zimmer_nr,children:[n.zimmer_nr," — ",n.kategorie," (max ",n.max_belegung,")",n.hunde_erlaubt?" 🐕":"",n.notizen?" ⚠":""]},n.zimmer_nr))]})]}),j?.notizen&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:["⚠ ",j.notizen]}),F&&e.jsxs("p",{className:"text-xs text-destructive",children:["Zimmer ",j?.zimmer_nr," erlaubt max. ",j?.max_belegung," Gäste"]}),a&&e.jsxs("p",{className:"text-xs text-destructive",children:["Zimmer ",j?.zimmer_nr," erlaubt keine Hunde"]}
7),S&&e.jsx("p",{className:"text-xs text-destructive",children:S})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs(y,{children:["Kategorie",M&&e.jsx("span",{className:"text-xs text-muted-foreground ml-1",children:"(für Rate & spätere Zuweisung)"})]}),e.jsxs(se,{value:s.geplante_kategorie??"",onValueChange:n=>c({...s,geplante_kategorie:n||null}),children:[e.jsx(te,{children:e.jsx(ne,{placeholder:j?.kategorie??"Kategorie wählen…"})}),e.jsx(re,{children:N.map(n=>e.jsx(H,{value:n,children:n},n))})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"Quelle"}),e.jsxs(se,{value:s.import_quelle??"direkt",onValueChange:n=>c({...s,import_quelle:n}),children:[e.jsx(te,{children:e.jsx(ne,{})}),e.jsx(re,{children:_e.map(n=>e.jsx(H,{value:n.value,children:n.label},n.value))})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"Reiseart (Kurtaxe)"}),e.jsxs(se,{value:s.reiseart,onValueChange:n=>c({...s,reiseart:n}),children:[e.jsx(te,{children:e.jsx(ne,{})}),e.jsxs(re,{children:[e.jsx(H,{value:"freizeit",children:"🏖 Freizeit (kurtaxepflichtig)"}),e.jsx(H,{value:"geschaeftlich",children:"💼 Geschäftlich (kurtaxefrei)"})]})]})]}),e.jsxs("div",{className:"space-y-1.5 col-span-2",children:[e.jsx(y,{children:"Straße & Hausnummer"}),e.jsx($,{value:s.strasse??"",onChange:n=>c({...s,strasse:n.target.value||null})})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"PLZ"}),e.jsx($,{value:s.plz??"",onChange:n=>c({...s,plz:n.target.value||null})})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"Ort"}),e.jsx($,{value:s.ort??"",onChange:n=>c({...s,ort:n.target.value||null})})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(y,{children:"Land"}),e.jsx($,{value:s.land??"",onChange:n=>c({...s,land:n.target.value||null})})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs(y,{children:["Buchungsnummer",e.jsx("span",{className:"text-xs text-muted-foreground ml-1",children:"(Anbieter / wird bei Direktbuchung erzeugt)"})]}),e.jsx($,{value:s.externe_buchungsnr??"",onChange:n=>c({...s,externe_buchungsnr:n.target.value||null}),placeholder:"z.B. 1234567890 (Booking.com) oder leer für auto"})]}),e.jsxs("div",{className:"space-y-1.5 col-span-2",children:[e.jsx(y,{children:"Notizen"}),e.jsx(Ge,{rows:3,value:s.notizen??"",onChange:n=>c({...s,notizen:n.target.value})})]})]}),e.jsxs(je,{className:"shrink-0 border-t pt-3",children:[e.jsx(v,{variant:"outline",onClick:()=>m(!1),children:"Abbrechen"}),e.jsx(v,{onClick:ie,disabled:_||F||a||!!S,children:_?"Speichern…":"Speichern"})]})]})})}const ht=()=>e.jsx(es,{roles:["rezeption","management"],children:e.jsx(Qe,{children:e.jsx(As,{})})});export{ht as component};

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.