PageSourceSearch

https://medifit-nienburg.de/assets/TrialSyncLog-C8uSuU-7.js

js medifit-nienburg.de collected 2026-10-04 03:32:09 UTC 11,933 bytes, 1 lines download raw bytes

1import{a as l,j as e}from"./trpc-vendor-Bta84Nsh.js";import{u as Q}from"./react-vendor-DpXpH6G7.js";import{t as u,B as o}from"./index-_3-B0itT.js";import{S as q,a as K,b as U,c as Y,d as I}from"./select-DqcHU93A.js";import{q as Z,g as _,b as j,bI as G,aY as J,t as r}from"./ui-vendor-NEZNvIbV.js";const X={"Online-Buchung":"bg-blue-100 text-blue-700","Walk-In / vor Ort":"bg-gray-100 text-gray-600","Telefon / Call-Center":"bg-amber-100 text-amber-700",Empfehlung:"bg-emerald-100 text-emerald-700",Werbeanzeige:"bg-violet-100 text-violet-700","Studio / Manuell":"bg-gray-100 text-gray-500"};function ee(d){if(!d)return{d:"—",t:""};const a=new Date(d);return{d:a.toLocaleDateString("de-DE",{weekday:"short",day:"2-digit",month:"2-digit"}),t:a.toLocaleTimeString("de-DE",{hour:"2-digit",minute:"2-digit"})}}function ae(){const[,d]=Q(),[a,F]=l.useState(void 0),[g,E]=l.useState(!1),[b,$]=l.useState(""),[N,k]=l.useState(null),[f,w]=l.useState(!1),{data:P}=u.brands.list.useQuery(),s=u.magicline?.trialSyncLog?.useQuery?.({brandId:a,onlyMissing:g,limit:150},{refetchOnWindowFocus:!1}),v=s?.data?.rows??[],c=s?.data?.summary??{total:0,inMagicline:0,missing:0,internal:0},m=s?.data?.webhookLastAt??null,p=s?.data?.webhookAnyHitAt??null,W=s?.data?.webhookLastTokenPrefix??null,y=n=>{if(!n)return null;const t=Math.floor((Date.now()-n)/6e4);if(t<60)return`vor ${t} Min`;const i=Math.floor(t/60);return i<24?`vor ${i} Std`:`vor ${Math.floor(i/24)} Tag(en)`},S=y(m),R=m!=null&&(Date.now()-m)/864e5<=7,D=p!=null&&(Date.now()-p)/864e5<=7,M=R?"ok":D?"wrong_token":"none",T=u.magicline?.rePushAppointment?.useMutation?.(),B=u.magicline?.pollFeedbackNow?.useMutation?.(),[A,L]=l.useState(!1),O=async()=>{L(!0);try{const n=await B?.mutateAsync?.({});n?.success?r.success("Feedback aus Magicline abgeglichen (Show/No-Show aktualisiert)."):r.error(String(n?.error??"Abgleich fehlgeschlagen"))}catch(n){r.error(n?.message??"Fehler")}L(!1),s?.refetch?.()},V=async n=>{k(n);try{const t=await T.mutateAsync({appointmentId:n});t?.already?r.success("War bereits in Magicline."):t?.success?r.success(`In Magicline gebucht ✓ (ID ${t.bookingId??"—"})`):r.error(String(t?.error??"Push fehlgeschlagen"),{duration:9e3})}catch(t){r.error(t?.message??"Fehler")}k(null),s?.refetch?.()},H=async()=>{const n=v.filter(h=>!h.inMagicline&&h.eligible);if(!n.length){r.info("Keine fehlenden Termine zum Senden.");return}w(!0);let t=0,i=0;for(const h of n)try{const z=await T.mutateAsync({appointmentId:h.id});z?.success||z?.already?t++:i++}catch{i++}w(!1),r[i?"warning":"success"](`Fertig: ${t} gebucht${i?`, ${i} fehlgeschlagen`:""}.`,{duration:8e3}),s?.refetch?.()},C=v.filter(n=>{if(!b.trim())return!0;const t=b.toLowerCase();return String(n.name).toLowerCase().includes(t)||String(n.phone??"").includes(t)}),x=({n,l:t,cls:i})=>e.jsxs("div",{className:"bg-card border border-border rounded-xl px-4 py-2.5 min-w-[130px]",children:[e.jsx("div",{className:`text-xl font-black ${i??"text-foreground"}`,children:n}),e.jsx("div",{className:"text-[10.5px] text-muted-foreground uppercase tracking-wide mt-0.5",children:t})]});return e.jsxs("div",{className:"p-5 md:p-6 max-w-[1400px] mx-auto",children:[e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-3",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-bold text-foreground flex items-center gap-2",children:[e.jsx(Z,{className:"w-5 h-5"})," Termin-Sync (Magicline)"]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Alle gebuchten Termine mit ihrem Magicline-Status — zum Nachverfolgen, Zwischenkontrollieren und Nachbuchen. Zeigt auch, woher der Termin gebucht wurde."})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(o,{variant:"outline",size:"sm",onClick:()=>s?.refetch?.(),disabled:s?.isFetching,children:s?.isFetching?"Lädt…":"Aktualisieren"}),e.jsx(o,{variant:"outline",size:"sm",onClick:O,disabled:A,children:A?"Prüfe…":"Feedback jetzt abgleichen"}),e.jsx(o,{size:"sm",onClick:H,disabled:f||c.missing===0,children:f?"Sende…":"Alle fehlenden erneut senden"})]})]}),(s?.data?.error||s?.error)&&e.jsxs("div",{className:"my-3 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",children:["⚠ Fehler beim Laden: ",String(s?.data?.error??s?.error?.message??"unbekannt")]}),M==="ok"?e.jsxs("div",{className:"my-3 rounded-lg border border-emerald-500/40 bg-emerald-500/10 px-3 py-2 text-xs text-emerald-600 flex items-center gap-2",children:[e.jsx(_,{className:"w-4 h-4"})," Magicline-Webhook aktiv — letztes Event ",S,'. „Wahrgenommen/No-Show" wird automatisch übernommen.']}):M==="wrong_token"?e.jsxs("div",{className:"my-3 rounded-lg border border-amber-500/50 bg-amber-500/10 px-3.5 py-3 text-sm text-amber-700",children:[e.jsxs("div",{className:"flex items-center gap-2 font-bold",children:[e.jsx(j,{className:"w-4 h-4"})," Magicline erreicht uns — aber der ",e.jsx("u",{children:"Token stimmt nicht"})]}),e.jsxs("p",{className:"mt-1 text-amber-700/90",children:["Es kommen Webhook-Anfragen an (",y(p),"), aber keine wird einem Studio zugeordnet. Der zuletzt empfangene Token beginnt mit ",e.jsx("code",{className:"font-mono",children:W??"?"}),". → In Magicline muss der ",e.jsx("code",{children:"x-api-key"})," ",e.jsx("b",{children:"exakt"})," dem ",e.jsx("b",{children:"Webhook-Token"}
1)," im CRM entsprechen (Studio → Magicline → Webhook-Token). Gleicht ihr die an, wird der Banner grün."]})]}):e.jsxs("div",{className:"my-3 rounded-lg border border-red-500/50 bg-red-500/10 px-3.5 py-3 text-sm text-red-600",children:[e.jsxs("div",{className:"flex items-center gap-2 font-bold",children:[e.jsx(j,{className:"w-4 h-4"})," Magicline-Webhook: ",m?`seit ${S} kein Event`:"noch nie ein Event empfangen"]}),e.jsxs("p",{className:"mt-1 text-red-600/90",children:["Bei uns kommt ",e.jsx("b",{children:"gar keine"})," Webhook-Anfrage an — d. h. die ",e.jsx("b",{children:"URL"})," in Magicline zeigt (noch) nicht auf uns. In Magicline den Webhook auf ",e.jsx("code",{children:"…/api/magicline/webhook?brandId=…"})," setzen (Studio → Magicline → Webhook-URL) + Token als ",e.jsx("code",{children:"x-api-key"}),". Danach kommt Show/No-Show automatisch hier + im Lead an."]})]}),e.jsxs("div",{className:"flex gap-2.5 flex-wrap my-4",children:[e.jsx(x,{n:c.total,l:"Termine (Liste)"}),e.jsx(x,{n:c.inMagicline,l:"✓ in Magicline",cls:"text-emerald-600"}),e.jsx(x,{n:c.missing,l:"⚠ nicht synchronisiert",cls:"text-amber-600"}),e.jsx(x,{n:c.internal,l:"– intern (kein Push)",cls:"text-blue-600"})]}),e.jsxs("div",{className:"flex gap-2 flex-wrap items-center mb-3",children:[e.jsxs(q,{value:a?String(a):"all",onValueChange:n=>F(n==="all"?void 0:parseInt(n)),children:[e.jsx(K,{className:"w-48 h-9 text-sm",children:e.jsx(U,{placeholder:"Studio"})}),e.jsxs(Y,{children:[e.jsx(I,{value:"all",children:"Alle Studios"}),(P??[]).map(n=>e.jsx(I,{value:String(n.id),children:n.studioName||n.name},n.id))]})]}),e.jsxs("button",{type:"button",onClick:()=>E(n=>!n),className:`h-9 px-3 rounded-md border text-sm flex items-center gap-2 ${g?"border-primary bg-primary/10 text-primary font-semibold":"border-border text-muted-foreground"}`,children:[e.jsx("span",{className:`w-3 h-3 rounded-[3px] border ${g?"bg-primary border-primary":"border-muted-foreground/40"}`})," Nur nicht synchronisiert"]}),e.jsx("input",{value:b,onChange:n=>$(n.target.value),placeholder:"🔎 Name / Telefon suchen…",className:"flex-1 min-w-[180px] h-9 px-3 rounded-md border border-border bg-card text-sm"})]}),e.jsxs("div",{className:"bg-card border border-border rounded-xl overflow-hidden",children:[e.jsxs("div",{className:"grid grid-cols-[120px_1.3fr_1fr_1fr_1.2fr_0.9fr_110px] gap-2.5 px-4 py-2.5 bg-muted/40 text-[10.5px] font-bold uppercase tracking-wide text-muted-foreground",children:[e.jsx("div",{children:"Termin"}),e.jsx("div",{children:"Name"}),e.jsx("div",{children:"Studio"}),e.jsx("div",{children:"Quelle / Ort"}),e.jsx("div",{children:"Magicline-Sync"}),e.jsx("div",{children:"Feedback"}),e.jsx("div",{children:"Aktion"})]}),s?.isLoading?e.jsx("div",{className:"px-4 py-10 text-center text-sm text-muted-foreground",children:"Lade…"}):C.length===0?e.jsx("div",{className:"px-4 py-10 text-center text-sm text-muted-foreground",children:"Keine Termine gefunden."}):C.map(n=>{const t=ee(n.scheduledAt),i=!n.inMagicline&&n.eligible&&n.note&&/magicline|fehl|error|not_|available|closed|horizon|daysAhead|slot|e-?mail/i.test(n.note);return e.jsxs("div",{className:"grid grid-cols-[120px_1.3fr_1fr_1fr_1.2fr_0.9fr_110px] gap-2.5 px-4 py-3 border-t border-border items-center text-[13px]",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-bold text-foreground",children:t.d}),e.jsx("div",{className:"text-muted-foreground text-xs",children:t.t})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"font-bold text-foreground truncate",children:n.name}),e.jsx("div",{className:"text-muted-foreground text-xs truncate",children:n.phone||"—"})]}),e.jsx("div",{className:"truncate text-foreground",children:n.studioName||"—"}),e.jsx("div",{children:e.jsx("span",{className:`inline-flex items-center gap-1.5 text-[11.5px] font-semibold px-2.5 py-1 rounded-full ${X[n.origin]??"bg-gray-100 text-gray-600"}`,children:n.origin})}),e.jsx("div",{children:n.inMagicline?e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-emerald-600 font-semibold text-xs",children:[e.jsx(_,{className:"w-4 h-4"})," in Magicline"]}):n.eligible?e.jsxs("div",{children:[e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-amber-600 font-semibold text-xs",children:[e.jsx(j,{className:"w-4 h-4"})," nicht synchronisiert"]}),i&&e.jsx("div",{className:"text-[10.5px] text-amber-600/90 max-w-[320px] whitespace-pre-wrap break-words mt-0.5",title:n.note,children:n.note})]}):e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-muted-foreground font-semibold text-xs",children:[e.jsx(G,{className:"w-4 h-4"})," intern (kein Push)"]})}),e.jsx("div",{children:n.status==="showed_up"?e.jsx("span",{className:"inline-flex items-center gap-1 text-emerald-600 font-semibold text-xs",children:"✅ wahrgenommen"}):n.status==="no_show"?e.jsx("span",{className:"inline-flex items-center gap-1 text-red-600 font-semibold text-xs",children:"🚪 N
1o-Show"}):n.status==="closed"?e.jsx("span",{className:"inline-flex items-center gap-1 text-emerald-700 font-semibold text-xs",children:"✔ Vertrag"}):e.jsx("span",{className:"text-xs text-muted-foreground",children:"— offen"})}),e.jsx("div",{children:n.inMagicline?n.leadId?e.jsx(o,{variant:"outline",size:"sm",className:"h-7",onClick:()=>d(`/leads/${n.leadId}`),children:e.jsx(J,{className:"w-3.5 h-3.5"})}):e.jsx("span",{className:"text-xs text-muted-foreground",children:"—"}):n.eligible?e.jsx(o,{size:"sm",className:"h-7",disabled:N===n.id||f,onClick:()=>V(n.id),children:N===n.id?"Sende…":"Erneut senden"}):n.leadId?e.jsx(o,{variant:"outline",size:"sm",className:"h-7",onClick:()=>d(`/leads/${n.leadId}`),children:"Lead"}):e.jsx("span",{className:"text-xs text-muted-foreground",children:"—"})})]},n.id)})]}),e.jsxs("div",{className:"mt-4 bg-card border border-border rounded-xl p-3.5 text-xs text-muted-foreground leading-relaxed",children:[e.jsx("b",{className:"text-foreground",children:"Legende:"})," ",e.jsx("span",{className:"text-emerald-600 font-semibold",children:"✓ in Magicline"})," = erfolgreich synchronisiert ·",e.jsx("span",{className:"text-amber-600 font-semibold",children:" ⚠ nicht synchronisiert"}),' = sollte in Magicline, ist aber (noch) nicht — „Erneut senden" bucht nach (nur wenn ein Magicline-Slot zur Terminzeit existiert, also Buchungshorizont/Verfügbarkeit passt) ·',e.jsx("span",{className:"text-muted-foreground font-semibold",children:" – intern"})," = Studio ohne Magicline oder manueller/Telefontermin (bewusst kein Push)."]})]})}export{ae as default};

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.