PageSourceSearch

https://www.brutto-netto-gehaltsrechner.de/assets/AdminCacheManagement-vObjuBvX.js

js brutto-netto-gehaltsrechner.de collected 2026-10-07 12:56:56 UTC 44,173 bytes, 11 lines download raw bytes

1import{r as d,j as e}from"./vendor-query-grCcowPe.js";import{i as Ie,s as re,b as S,j as v,B as R,a7 as I,aF as Ke,m as k,n as C,T as X,Y as B,C as Ue,ah as as,ad as U,a8 as me,S as is,H as ls,a as cs,Z as we,aa as Te,L as We,I as Be,af as Me,F as os}from"./index-DhefWqWw.js";import{S as Q}from"./scroll-area-BSP2Dp4I.js";import{T as hs,a as ds,b as de,c as ue}from"./tabs-e_XJIvit.js";import{P as us}from"./progress-DBDNDmZk.js";import{D as qe}from"./database-B4cM9mH5.js";import{A as Ge}from"./activity-Cfats5Da.js";import{C as ye}from"./circle-check-big-vD3FZXSS.js";import{A as ms}from"./AdminAuth-B55h5CiH.js";import{R as Ne}from"./rotate-cw-DKooJH3U.js";import{S as Oe}from"./square-DPtm3XRo.js";import"./vendor-radix-C0yaWf-q.js";import"./vendor-router-BEPqyM9l.js";import"./vendor-supabase-DKDXnbXH.js";import"./NotFound-CrmlEJdL.js";/**
2 * @license lucide-react v0.462.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 Se=Ie("Flame",[["path",{d:"M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z",key:"96xj49"}]]);/**
7 * @license lucide-react v0.462.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 gs=Ie("Server",[["rect",{width:"20",height:"8",x:"2",y:"2",rx:"2",ry:"2",key:"ngkwjq"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2",ry:"2",key:"iecqi9"}],["line",{x1:"6",x2:"6.01",y1:"6",y2:"6",key:"16zg32"}],["line",{x1:"6",x2:"6.01",y1:"18",y2:"18",key:"nzw8ys"}]]);async function Y(a={}){const{data:y}=await re.auth.getSession(),j=y.session?.access_token;return{"Content-Type":"application/json",apikey:"sb_publishable_bdcL4T_mmnozYO_iAzbBgA_b6YjgUSj",...j?{Authorization:`Bearer ${j}`}:{},...a}}function xs(){const[a,y]=d.useState([]),[j,D]=d.useState([]),[M,T]=d.useState(null),[ge,ee]=d.useState(!1),[z,ne]=d.useState(!1),q=d.useCallback(async()=>{ee(!0);try{const[t,G]=await Promise.all([re.from("system_alerts").select("*").eq("alert_type","cache_warming_health").order("created_at",{ascending:!1}).limit(10),re.from("cache_warming_runs").select("*").order("started_at",{ascending:!1}).limit(10)]);t.data&&y(t.data),G.data&&D(G.data)}finally{ee(!1)}},[]);d.useEffect(()=>{q()},[q]);const Z=async()=>{ne(!0);try{const ie=await(await fetch("https://kpptrnpnifundvtmecqk.supabase.co/functions/v1/cache-warming-health",{method:"POST",headers:await Y()})).json();
11T(ie),await q()}catch(t){console.error("Health check failed:",t)}finally{ne(!1)}},m=a.filter(t=>!t.resolved),h=j[0],$=(()=>{if(m.some(G=>G.severity==="critical"))return"critical";if(m.length>0)return"warning";if(!h)return"unknown";const t=(Date.now()-new Date(h.started_at).getTime())/(1e3*60*60);return t>8?"critical":t>7?"warning":"healthy"})(),A={healthy:{color:"bg-green-500",text:"Gesund",icon:is,bgClass:"bg-green-50 border-green-200 dark:bg-green-950/30 dark:border-green-800"},warning:{color:"bg-yellow-500",text:"Warnung",icon:X,bgClass:"bg-yellow-50 border-yellow-200 dark:bg-yellow-950/30 dark:border-yellow-800"},critical:{color:"bg-red-500",text:"Kritisch",icon:me,bgClass:"bg-red-50 border-red-200 dark:bg-red-950/30 dark:border-red-800"},unknown:{color:"bg-gray-500",text:"Unbekannt",icon:Ge,bgClass:"bg-muted border-border"}}[$],f=A.icon;return e.jsxs("div",{className:"space-y-6",children:[e.jsx(S,{className:`border-2 ${A.bgClass}`,children:e.jsx(v,{className:"pt-6",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("div",{className:`p-3 rounded-full ${A.color}/10`,children:e.jsx(f,{className:`h-8 w-8 ${$==="healthy"?"text-green-600":$==="warning"?"text-yellow-600":$==="critical"?"text-red-600":"text-muted-foreground"}`})}),e.jsxs("div",{children:[e.jsxs("h3",{className:"text-xl font-bold",children:["Cache-Warming: ",A.text]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:h?e.jsxs(e.Fragment,{children:["Letzter Run: ",new Date(h.started_at).toLocaleString("de-DE")," (",h.triggered_by,") • ",h.total_pages," Seiten • ",h.errors," Fehler"]}):"Keine Runs gefunden"}),m.length>0&&e.jsxs("p",{className:"text-sm font-medium text-destructive mt-1",children:[m.length," offene",m.length===1?"r":""," Alert",m.length!==1?"s":""]})]})]}),e.jsxs(R,{onClick:Z,disabled:z,variant:"outline",size:"sm",children:[z?e.jsx(I,{className:"h-4 w-4 animate-spin mr-2"}):e.jsx(Ke,{className:"h-4 w-4 mr-2"}),"Health-Check"]})]})})}),M?.r2_stats&&e.jsx(fs,{stats:M.r2_stats}),M&&e.jsx(ps,{result:M}),e.jsxs("div",{className:"grid gap-6 md:grid-cols-2",children:[e.jsxs(S,{children:[e.jsx(k,{children:e.jsxs(C,{className:"flex items-center justify-between",children:[e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(X,{className:"h-5 w-5"}),"System Alerts"]}),e.jsxs(B,{variant:m.length>0?"destructive":"secondary",children:[m.length," offen"]})]})}),e.jsx(v,{children:e.jsx(Q,{className:"h-[300px]",children:a.length===0?e.jsx("div",{className:"flex items-center justify-center h-full text-muted-foreground text-sm",children:"Keine Alerts vorhanden – System läuft stabil."}):e.jsx("div",{className:"space-y-3",children:a.map(t=>e.jsxs("div",{className:`p-3 rounded-lg border text-sm ${t.resolved?"bg-muted/50 opacity-60":t.severity==="critical"?"bg-red-50 border-red-200 dark:bg-red-950/20":"bg-yellow-50 border-yellow-200 dark:bg-yellow-950/20"}`,children:[e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsx("span",{className:"font-medium",children:t.title}),t.resolved&&e.jsx(B,{variant:"outline",className:"text-xs",children:"gelöst"}),t.auto_healed&&e.jsx(B,{variant:"secondary",className:"text-xs",children:"auto-healed"})]}),e.jsx("p",{className:"text-muted-foreground whitespace-pre-line",children:t.message}),t.healing_action&&e.jsxs("p",{className:"text-xs text-green-600 mt-1",children:["🔧 ",t.healing_action]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:new Date(t.created_at).toLocaleString("de-DE")})]},t.id))})})})]}),e.jsxs(S,{children:[e.jsx(k,{children:e.jsxs(C,{className:"flex items-center gap-2",children:[e.jsx(I,{className:"h-5 w-5"}),"Letzte Warming-Runs"]})}),e.jsx(v,{children:e.jsx(Q,{className:"h-[300px]",children:e.jsx("div",{className:"space-y-2",children:j.map(t=>e.jsxs("div",{className:"p-3 rounded-lg border bg-background text-sm",children:[e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsx(B,{variant:t.status==="success"?"secondary":t.
11status==="running"?"default":"destructive",children:t.status}),e.jsx("span",{className:"text-xs text-muted-foreground",children:t.triggered_by})]}),e.jsxs("div",{className:"text-xs text-muted-foreground space-y-0.5",children:[e.jsx("div",{children:new Date(t.started_at).toLocaleString("de-DE")}),e.jsxs("div",{children:[t.total_pages," Seiten • ",t.cache_hits," Hits • ",t.cache_misses," Misses • ",t.errors," Fehler"]}),t.duration_ms&&e.jsxs("div",{children:["Dauer: ",(t.duration_ms/1e3).toFixed(0),"s"]})]})]},t.id))})})})]})]})]})}function ve({status:a}){const y={healthy:"bg-green-500",warning:"bg-yellow-500",critical:"bg-red-500"};return e.jsx("span",{className:`inline-block w-3 h-3 rounded-full ${y[a]}`})}function fs({stats:a}){const[y,j]=d.useState(!1),[D,M]=d.useState(!1);return e.jsxs("div",{className:"grid gap-4 md:grid-cols-3",children:[e.jsxs(S,{children:[e.jsx(k,{className:"pb-2",children:e.jsxs(C,{className:"text-sm flex items-center gap-2",children:[e.jsx(qe,{className:"h-4 w-4"}),"Coverage",e.jsx(ve,{status:a.coverage_status})]})}),e.jsxs(v,{children:[e.jsxs("div",{className:"text-3xl font-bold tabular-nums",children:[a.coverage_pct,"%"]}),e.jsxs("p",{className:"text-sm text-muted-foreground mt-1",children:[a.total_cached," / ",a.total_expected," Seiten gecacht"]}),e.jsx("div",{className:"mt-2 h-2 rounded-full bg-muted overflow-hidden",children:e.jsx("div",{className:`h-full rounded-full transition-all ${a.coverage_status==="healthy"?"bg-green-500":a.coverage_status==="warning"?"bg-yellow-500":"bg-red-500"}`,style:{width:`${Math.min(100,a.coverage_pct)}%`}})}),a.missing_slugs.length>0&&e.jsxs(R,{variant:"ghost",size:"sm",className:"mt-2 h-auto p-0 text-xs text-muted-foreground hover:text-foreground",onClick:()=>j(!y),children:[y?"▾":"▸"," ",a.missing_slugs.length," fehlende Seiten"]}),y&&e.jsx(Q,{className:"mt-2 max-h-[200px]",children:e.jsx("div",{className:"space-y-0.5",children:a.missing_slugs.map(T=>e.jsxs("div",{className:"text-xs text-muted-foreground font-mono truncate",children:["/",T]},T))})})]})]}),e.jsxs(S,{children:[e.jsx(k,{className:"pb-2",children:e.jsxs(C,{className:"text-sm flex items-center gap-2",children:[e.jsx(Ue,{className:"h-4 w-4"}),"Freshness",e.jsx(ve,{status:a.freshness_status})]})}),e.jsxs(v,{children:[e.jsxs("div",{className:"text-3xl font-bold tabular-nums",children:[a.median_age_hours,"h"]}),e.jsxs("p",{className:"text-sm text-muted-foreground mt-1",children:["Median-Alter • Älteste: ",a.max_age_hours,"h"]}),a.stale_count>0&&e.jsxs("p",{className:"text-sm text-yellow-600 mt-1",children:["⚠️ ",a.stale_count," Seiten älter als 48h (",a.stale_pct,"%)"]}),a.oldest_pages.length>0&&e.jsxs(R,{variant:"ghost",size:"sm",className:"mt-2 h-auto p-0 text-xs text-muted-foreground hover:text-foreground",onClick:()=>M(!D),children:[D?"▾":"▸"," Top 10 älteste Seiten"]}),D&&e.jsx("div",{className:"mt-2 space-y-1",children:a.oldest_pages.map(T=>e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsxs("span",{className:"font-mono truncate text-muted-foreground",children:["/",T.key]}),e.jsxs("span",{className:"text-muted-foreground shrink-0 ml-2",children:[T.age_hours,"h"]})]},T.key))})]})]}),e.jsxs(S,{children:[e.jsx(k,{className:"pb-2",children:e.jsxs(C,{className:"text-sm flex items-center gap-2",children:[e.jsx(as,{className:"h-4 w-4"}),"Run-Qualität",e.jsx(ve,{status:a.coverage_status==="critical"||a.freshness_status==="critical"?"critical":a.coverage_status==="warning"||a.freshness_status==="warning"?"warning":"healthy"})]})}),e.jsx(v,{children:e.jsxs("div",{className:"space-y-2 text-sm",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Coverage"}),e.jsxs("span",{className:a.coverage_status==="healthy"?"text-green-600 font-medium":a.coverage_status==="warning"?"text-yellow-600 font-medium":"text-red-600 font-medium",children:[a.coverage_status==="healthy"?"🟢":a.coverage_status==="warning"?"🟡":"🔴"," ",a.coverage_pct,"%"]})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Freshness"}),e.jsxs("span",{className:a.freshness_status==="healthy"?"text-green-600 font-medium":a.freshness_status==="warning"?"text-yellow-600 font-medium":"text-red-600 font-medium",children:[a.freshness_status==="healthy"?"🟢":a.freshness_status==="warning"?"🟡":"🔴"," ",a.median_age_hours,"h"]})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Stale (>48h)"}),e.jsxs("span",{className:a.stale_count===0?"text-green-600 font-medium":"text-yellow-600 font-medium",children:[a.stale_count===0?"🟢":"🟡"," ",a.stale_count]})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Fehlend"}),e.jsxs("span",{className:a.missing_slugs.length===0?"text-green-600 font-medium":"text-red-600 font-medium",children:[a.missing_slugs.length===0?"🟢":"🔴"," ",a.missing_slugs.length]})]})]})})]})]})}function ps({result:a}){return e.jsxs(S,{children:[e.jsxs(k,{children:[e.jsxs(C,{className:"flex items-center gap-2",children:[e.jsx(Ge,{className:"h-5 w-5"}),"Health-Check Details"]}
11),e.jsxs(U,{children:["Status: ",e.jsx(B,{variant:a.status==="healthy"?"secondary":"destructive",children:a.status})]})]}),e.jsx(v,{children:e.jsxs("div",{className:"space-y-2",children:[Object.entries(a.checks).map(([y,j])=>e.jsxs("div",{className:"flex items-start gap-2 text-sm",children:[j.ok?e.jsx(ye,{className:"h-4 w-4 text-green-500 mt-0.5 shrink-0"}):e.jsx(me,{className:"h-4 w-4 text-red-500 mt-0.5 shrink-0"}),e.jsxs("div",{children:[e.jsxs("span",{className:"font-medium",children:[y,":"]})," ",j.detail]})]},y)),a.actions_taken.length>0&&e.jsxs("div",{className:"mt-3 p-2 bg-muted rounded text-sm",children:[e.jsx("span",{className:"font-medium",children:"Self-Healing:"})," ",a.actions_taken.join("; ")]})]})})]})}const F=["/berufe","/hochschulstudium","/duales-studium","/schulische-ausbildung","/aufstiegsfortbildung","/anpassungsweiterbildung","/helfer-anlerntaetigkeit","/berufliche-rolle","/selbststaendige-taetigkeit","/oeffentlicher-dienst"],He=["/","/gehaltsrechner",...F,"/impressum","/datenschutz","/autor/markusschmitz"];function Ds(){return e.jsx(ms,{children:e.jsx(js,{})})}function js(){const[a,y]=d.useState("idle"),[j,D]=d.useState([]),[M,T]=d.useState(null),[ge,ee]=d.useState(null),[z,ne]=d.useState(""),[q,Z]=d.useState("idle"),[m,h]=d.useState("idle"),[E,$]=d.useState({current:0,total:0}),[ae,A]=d.useState({hits:0,misses:0,errors:0}),f=d.useRef(!1),t=d.useCallback((s,r)=>{D(l=>[...l,{timestamp:new Date().toISOString(),level:s,message:r}])},[]),G=async()=>{y("running"),D([]),T(new Date),ee(null),t("info","Starte Purge für ALLE Seiten (statisch + Berufe)...");try{const r=await fetch("https://kpptrnpnifundvtmecqk.supabase.co/functions/v1/purge-cache?slug=all",{method:"POST",headers:await Y()}),l=await r.json();r.ok?(t("success","Purge erfolgreich abgeschlossen!"),t("info",`Modus: ${l.mode} | Seiten: ${l.totalPages}`),t("info",`R2: ${l.r2Purge?.deleted} gelöscht, ${l.r2Purge?.errorsTotal} Fehler`),t("info",`CDN: ${l.cdnPurge?.purged} URLs gepurged`),t("info",`Dauer: ${l.durationFormatted}`),l.r2Purge?.errors?.length>0&&l.r2Purge.errors.forEach(n=>t("warning",n)),y("success")):(t("error",`Fehler: ${r.status} ${r.statusText}`),t("error",JSON.stringify(l)),y("error"))}catch(s){t("error",`Exception: ${s instanceof Error?s.message:String(s)}`),y("error")}finally{ee(new Date)}},ie=async()=>
11{if(z.trim()){Z("running"),t("info",`Starte CDN-Purge für: ${z}`);try{const s=z.trim(),r=`https://kpptrnpnifundvtmecqk.supabase.co/functions/v1/purge-cache?slug=${encodeURIComponent(s)}`,l=await fetch(r,{method:"POST",headers:await Y()}),n=await l.json();l.ok?(t("success",`CDN-Purge erfolgreich für: ${n.paths?.join(", ")}`),t("info",`CDN purged: ${n.cdnPurge?.purged} URLs`),t("info",n.note),Z("success")):(t("error",`Single-Purge Fehler: ${l.status} – ${JSON.stringify(n)}`),Z("error"))}catch(s){t("error",`Single-Purge Exception: ${s instanceof Error?s.message:String(s)}`),Z("error")}}},le=d.useRef(new Set),Pe=async(s,r,l,n=!1)=>{const i=new AbortController,c=window.setTimeout(()=>i.abort(),l);n&&le.current.add(i);try{return await fetch(s,{...r,signal:i.signal})}finally{window.clearTimeout(c),n&&le.current.delete(i)}},ce=async(s,r,l,n)=>{const i="https://kpptrnpnifundvtmecqk.supabase.co/functions/v1/manual-warm-batch",c={method:"POST",headers:await Y(),body:JSON.stringify({paths:s,concurrency:r,delay_ms:l})};return(n?await Pe(i,c,n.timeoutMs??45e3,n.manageAbort??!1):await fetch(i,c)).json()},Je=async s=>{for(const r of s){const l=r.startsWith("/")?r:`/${r}`,n=`https://kpptrnpnifundvtmecqk.supabase.co/functions/v1/purge-cache?slug=${encodeURIComponent(l)}`;await fetch(n,{method:"POST",headers:await Y()})}},Ve=async()=>{f.current=!1,h("running"),$({current:0,total:F.length}),A({hits:0,misses:0,errors:0}),t("info",`Starte Purge für ${F.length} Kategorieseiten...`);try{await Je(F),t("success",`Purge für ${F.length} Kategorieseiten abgeschlossen.`),t("info","Starte gedrosseltes Warming (1 Seite, 10s Pause)...");let s=0,r=0,l=0;for(let n=0;n<F.length;n++){if(f.current){t("warning",`Warming abgebrochen bei ${n}/${F.length}`),h("aborted");return}const i=F[n];t("info",`Wärme ${i} (${n+1}/${F.length})...`);const c=await ce([i],1,0);c.errors>0?(l++,t("error",`Fehler bei ${i}`)):(r++,t("success",`${i} gewärmt (${c.results?.[0]?.durationMs||"?"}ms)`)),$({current:n+1,total:F.length}),A({hits:s,misses:r,errors:l}),n<F.length-1&&!f.current&&await new Promise(N=>setTimeout(N,1e4))}h("success"),t("success",`Alle ${F.length} Kategorieseiten gewärmt! (${r} neu, ${l} Fehler)`)}catch(s){t("error",`Fehler: ${s instanceof Error?s.message:String(s)}`),h("error")}},Ye=async()=>{f.current=!1,h("running"),A({hits:0,misses:0,errors:0}),t("info","Lade alle Beruf-Slugs aus der Datenbank...");try{const s=[];let r=0;for(;;){const{data:u,error:_}=await re.from("beruf_master_profile").select("beruf_slug").range(r,r+999);if(_||!u?.length||(s.push(...u.map(w=>w.beruf_slug)),u.length<1e3))break;r+=1e3}const l=s.map(u=>`/berufe/${u}`),n=[...He,...l],i=n.length;$({current:0,total:i}),t("info",`${i} Seiten gefunden. Starte gedrosseltes Warming (2 parallel, 10s Pause)...`);let c=0,N=0,x=0;const P=2,p=1e4;for(let u=0;u<n.length;u+=P){if(f.current){t("warning",`Warming abgebrochen bei ${u}/${i}`),h("aborted");return}const _=n.slice(u,u+P);try{const O=await ce(_,P,0);c+=O.hits||0,N+=O.misses||0,x+=O.errors||0}catch{x+=_.length}const w=Math.min(u+P,i);$({current:w,total:i}),A({hits:c,misses:N,errors:x}),(w%50===0||w===i)&&t("info",`${w}/${i} verarbeitet (${c} HIT, ${N} neu, ${x} Fehler)`),u+P<i&&!f.current&&await new Promise(O=>setTimeout(O,p))}h("success"),t("success",`Komplett-Warming abgeschlossen! ${i} Seiten (${c} HIT, ${N} neu gerendert, ${x} Fehler)`)}catch(s){t("error",`Fehler: ${s instanceof Error?s.message:String(s)}`),h("error")}},ke=()=>{f.current=!0,le.current.forEach(s=>s.abort()),le.current.clear(),b(),t("warning","Abbruch angefordert... Fortschritt wird sofort gesichert.")},oe="rolling-cache-refresh-state",Ze=s=>s==="paused"||s==="purging"||s==="warming"||s==="cooldown",xe=s=>!!(s&&s.allPaths.length>0&&s.remainingPaths.length>0),o=d.useRef(null),fe=s=>{if(!s||typeof s!="object")return null;const r=s;if(r.status!=="interrupted"&&r.status!=="running")return null;const l=Array.from(new Set((Array.isArray(r.allPaths)?r.allPaths:[]).filter(g=>typeof g=="string"&&g.length>0)));if(l.length===0)return null;const n=new Set(l),i=Array.from(new Set((Array.isArray(r.completedPaths)?r.completedPaths:[]).filter(g=>typeof g=="string"&&n.has(g)))),c=new Set(i),N=Array.from(new Set((Array.isArray(r.remainingPaths)?r.remainingPaths:[]).filter(g=>typeof g=="string"&&n.has(g)&&!c.has(g)))),x=new Set(N);for(const g of l)!c.has(g)&&!x.has(g)&&(N.push(g),x.add(g));const P=typeof r.currentPath=="string"&&n.has(r.currentPath)&&!c.has(r.currentPath)?r.currentPath:null,p=P?[P,...N.filter(g=>g!==P)]:N,u=Number(r.stats?.errors),_=Number.isFinite(u)?Math.max(0,u):0,w=Number(r.batchSize),O=Number.isFinite(w)?Math.min(20,Math.max(5,w)):10;return{allPaths:l,remainingPaths:p,completedPaths:i,completedCount:i.length,stats:{misses:i.length,errors:_},currentPath:P,phase:Ze(r.phase)?r.phase:"paused",batchSize:O}},[K,Ce]=d.useState(10),[$e,Ae]=d.useState(()=>{if(typeof window>"u")return!1;try{const s=localStorage.getItem(oe);return s?xe(fe(JSON.parse(s))):!1}catch{return!1}}),_e=d.useCallback((s,r,l,n)=>{if(typeof window>"u")return;const i=fe({completedPaths:s,allPaths:r,remainingPaths:n?.remainingPaths,currentPath:n?.currentPath,phase:n?.phase,batchSize:n?.batchSize,stats:l,status:"interrupted"});i&&(localStorage.setItem(oe,JSON.stringify({version:2,completedPaths:i.completedPaths,remainingPaths:i.remainingPaths,allPaths:i.allPaths,currentPath:i.currentPath,phase:i.phase,batchSize:i.batchSize,stats:i.stats,status:"interrupted",savedAt:new Date().toISOString()})),Ae(xe(i)))},[]),se=d.useCallback(()=>{typeof window<"u"&&localStorage.removeItem(oe),o.current=null,Ae(!1)},[]),Ee=d.useCallback(()=>
11{if(typeof window>"u")return null;try{const s=localStorage.getItem(oe);if(!s)return null;const r=fe(JSON.parse(s));return xe(r)?r:null}catch{return null}},[]),b=d.useCallback(()=>{const s=o.current;s&&_e(s.completedPaths,s.allPaths,{misses:s.completedPaths.length,errors:s.totalErrors},{remainingPaths:s.remainingPaths,currentPath:s.currentPath,phase:s.phase,batchSize:s.batchSize})},[_e]),J=d.useCallback(async s=>{let r=0;const l=500;for(;r<s;){if(f.current)return b(),!1;const n=Math.min(l,s-r);await new Promise(i=>setTimeout(i,n)),r+=n}return!f.current},[b]),Xe=d.useCallback(async s=>{const r=s.startsWith("/")?s:`/${s}`,l=`https://kpptrnpnifundvtmecqk.supabase.co/functions/v1/purge-cache?slug=${encodeURIComponent(r)}`;let n=null;for(let i=1;i<=3;i++){if(f.current)throw new Error("Abgebrochen");try{const c=await Pe(l,{method:"POST",headers:await Y()},3e4,!0);if(!c.ok)throw new Error(`HTTP ${c.status}`);return}catch(c){const N=c instanceof DOMException&&c.name==="AbortError";if(f.current&&N)throw new Error("Abgebrochen");if(n=c instanceof Error?c:new Error(String(c)),i<3&&(t("warning",`  ↺ Purge-Retry ${i}/2 für ${s}`),!await J(1500*i)))throw new Error("Abgebrochen")}}throw n??new Error(`Purge fehlgeschlagen: ${s}`)},[t,J]),Qe=d.useCallback(async s=>{let r=null;for(let l=1;l<=3;l++){if(f.current)throw new Error("Abgebrochen");try{const n=await ce([s],1,0,{timeoutMs:45e3,manageAbort:!0});if(n?.errors>0)throw new Error(n?.results?.[0]?.error||`Warming fehlgeschlagen: ${s}`);return n}catch(n){const i=n instanceof DOMException&&n.name==="AbortError";if(f.current&&i)throw new Error("Abgebrochen");if(r=n instanceof Error?n:new Error(String(n)),l<3&&(t("warning",`  ↺ Warm-Retry ${l}/2 für ${s}`),!await J(2e3*l)))throw new Error("Abgebrochen")}}throw r??new Error(`Warming fehlgeschlagen: ${s}`)},[t,J]);d.useEffect(()=>{if(typeof window>"u")return;const s=()=>{o.current&&b()},r=()=>{document.visibilityState==="hidden"&&s()};return window.addEventListener("pagehide",s),window.addEventListener("beforeunload",s),document.addEventListener("visibilitychange",r),()=>{window.removeEventListener("pagehide",s),window.removeEventListener("beforeunload",s),document.removeEventListener("visibilitychange",r)}},[b]);const Re=async({allPaths:s,remainingPaths:r,completedPaths:l=[],resumeStats:n,batchSize:i})=>{f.current=!1,h("running");const c=Array.from(new Set(s)),N=new Set(c),x=Array.from(new Set(l.filter(g=>N.has(g)))),P=new Set(x),p=Array.from(new Set(r.filter(g=>N.has(g)&&!P.has(g))));n||D([]);const u=Math.min(20,Math.max(5,i??K)),_=n?.errors??0;if(o.current={allPaths:c,remainingPaths:[...p],completedPaths:[...x],currentPath:null,phase:"paused",batchSize:u,totalErrors:_},A({hits:0,misses:x.length,errors:_}),$({current:x.length,total:c.length}),b(),p.length===0){se(),h("success"),t("success","Keine verbleibenden Seiten – alles bereits erneuert.");return}t("info",n?`▶ Fortsetzen: ${p.length} verbleibende Seiten (${x.length} bereits gewärmt).`:`${c.length} Seiten gefunden. Rolling Refresh in ${u}er-Batches.`);let w=_;const O=Math.ceil(p.length/u);try{for(let V=0;V<p.length;V+=u){if(f.current){b(),t("warning",`⏸ Abgebrochen bei ${V}/${p.length}. Fortschritt gespeichert – kann fortgesetzt werden.`),h("aborted");return}const te=p.slice(V,V+u),ze=Math.floor(V/u)+1,je=new Set;o.current&&(o.current.phase="purging",o.current.currentPath=null,b()),t("info",`── Batch ${ze}/${O}: ${te.length} Seiten ──`);let Le=0,he=0;for(const L of te){if(f.current){b(),t("warning","⏸ Abgebrochen während der Purge-Phase. Fortschritt gespeichert."),h("aborted");return}o.current&&(o.current.phase="purging",o.current.currentPath=L,b());try{await Xe(L),Le++}catch(W){if(f.current||W instanceof Error&&W.message==="Abgebrochen"){b(),t("warning",`⏸ Abgebrochen während Purge von ${L}. Fortschritt gespeichert.`),h("aborted");return}he++,w++,je.add(L),o.current&&(o.current.currentPath=null,o.current.totalErrors=w,b()),t("warning",`  Purge fehlgeschlagen: ${L}`)}}if(A({hits:0,misses:x.length,errors:w}),t(he>0?"warning":"success",`  Purge: ${Le} OK, ${he} Fehler`),o.current&&(o.current.phase="cooldown",o.current.currentPath=null,o.current.totalErrors=w,b()),!await J(2e3)){t("warning","⏸ Abgebrochen n
11ach der Purge-Phase. Fortschritt gespeichert."),h("aborted");return}let De=0,be=he;for(let L=0;L<te.length;L++){const W=te[L];if(je.has(W))continue;if(f.current){b(),t("warning","⏸ Abgebrochen. Fortschritt gespeichert."),h("aborted");return}o.current&&(o.current.phase="warming",o.current.currentPath=W,o.current.totalErrors=w,b());try{await Qe(W),De++,x.push(W),o.current&&(o.current.completedPaths=[...x],o.current.remainingPaths=o.current.remainingPaths.filter(H=>H!==W),o.current.currentPath=null,b())}catch(H){if(f.current||H instanceof Error&&H.message==="Abgebrochen"){b(),t("warning",`⏸ Abgebrochen während ${W}. Fortschritt gespeichert.`),h("aborted");return}be++,w++,o.current&&(o.current.currentPath=null,o.current.totalErrors=w,b()),t("error",`  ✗ ${W} (${H instanceof Error?H.message:"Fehler"})`)}if(o.current&&(o.current.totalErrors=w,b()),A({hits:0,misses:x.length,errors:w}),$({current:x.length,total:c.length}),te.slice(L+1).some(H=>!je.has(H))&&!await J(8e3)){t("warning","⏸ Abgebrochen zwischen zwei Seiten. Fortschritt gespeichert."),h("aborted");return}}if(o.current&&(o.current.phase="cooldown",o.current.currentPath=null,o.current.totalErrors=w,b()),$({current:x.length,total:c.length}),A({hits:0,misses:x.length,errors:w}),t(be>0?"warning":"success",`  Batch ${ze} fertig: ${De} gewärmt, ${be} Fehler`),V+u<p.length&&!f.current&&!await J(3e3)){t("warning","⏸ Abgebrochen im Batch-Cooldown. Fortschritt gespeichert."),h("aborted");return}}const g=o.current?.remainingPaths.length??0;if(g>0){b(),h("error"),t("warning",`⚠ Rolling Refresh pausiert mit ${g} verbleibenden Seiten. Einfach fortsetzen.`);return}se(),h("success"),t("success",`✅ Rolling Refresh komplett! ${c.length} Seiten (${x.length} gewärmt, ${w} Fehler)`)}catch(g){b(),t("error",`Fehler: ${g instanceof Error?g.message:String(g)}. Fortschritt gespeichert.`),h("error")}},es=async()=>{t("info","Rolling Cache Refresh: Lade alle Pfade...");const s=[];let r=0;for(;;){const{data:i,error:c}=await re.from("beruf_master_profile").select("beruf_slug").range(r,r+999);if(c||!i?.length||(s.push(...i.map(N=>N.beruf_slug)),i.length<1e3))break;r+=1e3}const l=s.map(i=>`/berufe/${i}`),n=[...He,...l];se(),await Re({allPaths:n,remainingPaths:n,batchSize:K})},ss=async()=>{const s=Ee();if(!s){t("info","Kein gespeicherter Fortschritt vorhanden oder bereits komplett."),se();return}Ce(s.batchSize),t("info",`Gespeicherter Fortschritt gefunden: ${s.remainingPaths.length} Seiten verbleibend.`),await Re({allPaths:s.allPaths,remainingPaths:s.remainingPaths,completedPaths:s.completedPaths,resumeStats:s.stats,batchSize:s.batchSize})},ts=()=>{se(),t("info","Gespeicherter Fortschritt verworfen.")},rs=async()=>{f.current=!1,h("running"),A({hits:0,misses:0,errors:0}),D([]),t("info","Lade fehlende Seiten vom Health-Endpoint...");try{const n=(await(await fetch("https://kpptrnpnifundvtmecqk.supabase.co/functions/v1/cache-warming-health",{method:"POST",headers:await Y()})).json())?.r2_stats?.missing_slugs||[];if(n.length===0){t("success","Keine fehlenden Seiten gefunden – alle Seiten sind gecacht!"),h("success"),$({current:0,total:0});return}const i=n.map(p=>p.startsWith("/")?p:`/${p}`),c=i.length;$({current:0,total:c}),t("info",`${c} fehlende Seiten gefunden. Starte Warming (1 parallel, 10s Pause)...`);let N=0,x=0,P=0;for(let p=0;p<i.length;p++){if(f.current){t("warning",`Warming abgebrochen bei ${p}/${c}`),h("aborted");return}const u=i[p];t("info",`Wärme ${u} (${p+1}/${c})...`);try{const _=await ce([u],1,0);_.errors>0?(P++,t("error",`Fehler bei ${u}`)):(x++,t("success",`${u} gewärmt (${_.results?.[0]?.durationMs||"?"}ms)`))}catch{P++,t("error",`Exception bei ${u}`)}$({current:p+1,total:c}),A({hits:N,misses:x,errors:P}),p<i.length-1&&!f.current&&await new Promise(_=>setTimeout(_,1e4))}h("success"),t("success",`Fertig! ${c} fehlende Seiten gewärmt (${x} neu, ${P} Fehler)`)}catch(s){t("error",`Fehler: ${s instanceof Error?s.message:String(s)}`),h("error")}},ns=()=>{switch(a){case"running":return e.jsx(I,{className:"h-5 w-5 animate-spin text-primary"});case"success":return e.jsx(ye,{className:"h-5 w-5 text-secondary"});case"error":return e.jsx(me,{className:"h-5 w-5 text-destructive"});default:return e.jsx(gs,{className:"h-5 w-5 text-muted-foreground"})}},pe=s=>{switch(s){case"success":return e.jsx(ye,{className:"h-4 w-4 text-secondary shrink-0"});case"error":return e.jsx(me,{className:"h-4 w-4 text-destructive shrink-0"});case"warning":return e.jsx(X,{className:"h-4 w-4 text-accent shrink-0"});default:return e.jsx(Ue,{className:"h-4 w-4 text-muted-foreground shrink-0"})}},Fe=M&&ge?`${((ge.getTime()-M.getTime())/1e3).toFixed(1)}s`:null;return e.jsxs("div",{className:"min-h-screen bg-muted",children:[e.jsxs(ls,{children:[e.jsx("title",{children:"Cache Management | Admin"}),e.jsx("meta",{name:"robots",content:"noindex, nofollow"})]}),e.jsx(cs,{}),e.jsxs("main",{className:"container py-8",children:[e.jsxs("div",{className:"mb-8",children:[e.jsx("h1",{className:"text-3xl font-bold text-primary mb-2",children:"Cache Management"}),e.jsx("p",{className:"text-muted-foreground",children:"Verwalte den R2-Cache und Cloudflare CDN für alle Seiten."})]}),e.jsxs(hs,{defaultValue:"health",className:"space-y-6",children:[e.jsxs(ds,{className:"grid w-full max-w-2xl grid-cols-4",children:[e.jsxs(de,{value:"health",className:"flex items-center gap-2",children:[e.jsx(Ke,{className:"h-4 w-4"}),"Health"]}),e.jsxs(de,{value:"warming",className:"flex items-center gap-2",children:[e.jsx(Se,{className:"h-4 w-4"}),"Warming"]}),e.jsxs(de,{value:"batch",className:"flex items-center gap-2",children:[e.jsx(qe,{className:"h-4 w-4"}),"Batch-Purge"]}),e.jsxs(de,{value:"single",className:"flex items-center gap-2",children:[e.jsx(we,{className:"h-4 w-4"}),"Single-Slug"]})]}),e.jsx(ue,{value:"health",children:e.jsx(xs,{})}),e.jsx(ue,{value:"warming",children:e.jsxs("div",{className:"grid gap-6 md:grid-cols-2",children:[e.jsxs("div",{className:"space-y-6",children:[e.jsxs(S,{children:[e.jsxs(k,{children:[e.jsxs(C,{className:"flex items-center gap-2",children:[e.jsx(Te,{className:"h-5 w-5"}),"Kategorieseiten Purge + Warm"]}),e.jsx(U,{children:"Purgt und wärmt die 10 Kategorieseiten sequentiell (10s Pause zwischen jeder Seite)."})]}),e.jsx(v,{children:e.jsx(R,{onClick:Ve,disabled:m==="running",className:"w-full",children:m==="running"?e.jsxs(e.Fragment,{children:[e.jsx(I,{className:"mr-2 h-4 w-4 animate-spin"}),"Läuft..."]}
11):e.jsxs(e.Fragment,{children:[e.jsx(Te,{className:"mr-2 h-4 w-4"}),"10 Kategorieseiten purgen & wärmen"]})})})]}),e.jsxs(S,{children:[e.jsxs(k,{children:[e.jsxs(C,{className:"flex items-center gap-2",children:[e.jsx(X,{className:"h-5 w-5"}),"Fehlende Seiten wärmen"]}),e.jsx(U,{children:"Wärmt nur die Seiten, die laut Health-Check noch nicht im R2-Cache liegen. Holt die Liste automatisch vom Health-Endpoint."})]}),e.jsx(v,{className:"space-y-4",children:e.jsx(R,{onClick:rs,disabled:m==="running",className:"w-full",children:m==="running"?e.jsxs(e.Fragment,{children:[e.jsx(I,{className:"mr-2 h-4 w-4 animate-spin"}),"Läuft..."]}):e.jsxs(e.Fragment,{children:[e.jsx(X,{className:"mr-2 h-4 w-4"}),"Nur fehlende Seiten wärmen"]})})})]}),e.jsxs(S,{className:"border-2 border-primary/30",children:[e.jsxs(k,{children:[e.jsxs(C,{className:"flex items-center gap-2",children:[e.jsx(Ne,{className:"h-5 w-5 text-primary"}),"Rolling Cache Refresh",e.jsx(B,{variant:"default",className:"ml-auto",children:"Empfohlen"})]}),e.jsxs(U,{children:["Purgt und wärmt ALLE Seiten in kleinen Batches. Jeder Batch wird erst gepurgt, dann sofort gewärmt, bevor der nächste Batch beginnt. ",e.jsxs("strong",{children:["Zu keinem Zeitpunkt sind mehr als ",K," Seiten ohne Cache."]})]})]}),e.jsxs(v,{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx(We,{htmlFor:"rollingBatchSize",className:"whitespace-nowrap text-sm",children:"Batch-Größe:"}),e.jsx(Be,{id:"rollingBatchSize",type:"number",min:5,max:20,value:K,onChange:s=>Ce(Math.min(20,Math.max(5,parseInt(s.target.value)||10))),className:"w-20",disabled:m==="running"}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:["(5–20 Seiten pro Batch, ~",Math.round(K*10/60)," Min/Batch)"]})]}),e.jsxs("div",{className:"p-3 rounded-lg bg-primary/5 text-sm space-y-1",children:[e.jsxs("p",{children:["📋 ",e.jsx("strong",{children:"Ablauf pro Batch:"})]}),e.jsxs("ol",{className:"list-decimal list-inside ml-2 space-y-0.5 text-muted-foreground",children:[e.jsxs("li",{children:["R2 + CDN Cache für ",K," Seiten löschen"]}),e.jsx("li",{children:"2s CDN-Propagation abwarten"}),e.jsx("li",{children:"Jede Seite sequenziell wärmen (8s Abstand)"}),e.jsx("li",{children:"3s Cooldown → nächster Batch"})]}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-2",children:["Geschätzte Gesamtdauer: ~",Math.round(1400/K*(K*10+5)/3600*10)/10,"h für ~1.400 Seiten"]})]}),$e&&m!=="running"&&(()=>{const s=Ee();return s?e.jsxs("div",{className:"p-3 rounded-lg bg-accent/10 border border-accent/30 space-y-2",children:[e.jsxs("p",{className:"text-sm font-medium flex items-center gap-2",children:[e.jsx(X,{className:"h-4 w-4 text-accent"}),"Unterbrochener Durchlauf gefunden"]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[s.remainingPaths.length," Seiten verbleibend · ",s.completedCount," bereits gewärmt · ",s.stats.errors," Fehler"]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(R,{onClick:ss,size:"sm",className:"flex-1",children:[e.jsx(Ne,{className:"mr-2 h-4 w-4"}),"Fortsetzen (",s.remainingPaths.length," Seiten)"]}),e.jsx(R,{onClick:ts,variant:"outline",size:"sm",children:"Verwerfen"})]})]}):null})(),e.jsx(R,{onClick:es,disabled:m==="running",className:"w-full",size:"lg",children:m==="running"?e.jsxs(e.Fragment,{children:[e.jsx(I,{className:"mr-2 h-4 w-4 animate-spin"}),"Läuft..."]}):e.jsxs(e.Fragment,{children:[e.jsx(Ne,{className:"mr-2 h-4 w-4"}),$e?"Neu starten (alle Seiten)":"Rolling Refresh starten"]})}),m==="running"&&e.jsxs(R,{onClick:ke,variant:"destructive",className:"w-full",children:[e.jsx(Oe,{className:"mr-2 h-4 w-4"}),"Abbrechen (Fortschritt wird gespeichert)"]})]})]}),e.jsxs(S,{children:[e.jsxs(k,{children:[e.jsxs(C,{className:"flex items-center gap-2",children:[e.jsx(Se,{className:"h-5 w-5"}),"Komplett-Warming"]}),e.jsx(U,{children:"Wärmt ALLE ~1.385 Seiten gedrosselt (2 parallel, 10s Pause). Geschätzte Dauer: ~2h. Der Tab muss geöffnet bleiben."})]}),e.jsxs(v,{className:"space-y-4",children:[e.jsx(R,{onClick:Ye,disabled:m==="running",className:"w-full",size:"lg",children:m==="running"?e.jsxs(e.Fragment,{children:[e.jsx(I,{className:"mr-2 h-4 w-4 animate-spin"}),"Läuft..."]}
11):e.jsxs(e.Fragment,{children:[e.jsx(Se,{className:"mr-2 h-4 w-4"}),"Komplett-Warming starten"]})}),m==="running"&&e.jsxs(R,{onClick:ke,variant:"destructive",className:"w-full",children:[e.jsx(Oe,{className:"mr-2 h-4 w-4"}),"Abbrechen"]})]})]}),E.total>0&&e.jsxs(S,{children:[e.jsx(k,{className:"pb-3",children:e.jsxs(C,{className:"text-base flex items-center justify-between",children:[e.jsx("span",{children:"Fortschritt"}),e.jsxs(B,{variant:m==="running"?"default":m==="success"?"secondary":m==="aborted"?"outline":"destructive",children:[m==="running"&&"Läuft",m==="success"&&"Fertig",m==="aborted"&&"Abgebrochen",m==="error"&&"Fehler"]})]})}),e.jsxs(v,{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between text-sm mb-1",children:[e.jsxs("span",{className:"font-medium",children:[E.current," / ",E.total]}),e.jsx("span",{className:"text-muted-foreground",children:E.total>0?`${Math.round(E.current/E.total*100)}%`:"0%"})]}),e.jsx(us,{value:E.total>0?E.current/E.total*100:0,className:"h-3"})]}),e.jsxs("div",{className:"grid grid-cols-3 gap-3 text-center",children:[e.jsxs("div",{className:"p-2 bg-muted rounded-lg",children:[e.jsx("div",{className:"text-lg font-bold text-primary",children:ae.hits}),e.jsx("div",{className:"text-xs text-muted-foreground",children:"Cache HIT"})]}),e.jsxs("div",{className:"p-2 bg-muted rounded-lg",children:[e.jsx("div",{className:"text-lg font-bold text-secondary",children:ae.misses}),e.jsx("div",{className:"text-xs text-muted-foreground",children:"Neu gerendert"})]}),e.jsxs("div",{className:"p-2 bg-muted rounded-lg",children:[e.jsx("div",{className:"text-lg font-bold text-destructive",children:ae.errors}),e.jsx("div",{className:"text-xs text-muted-foreground",children:"Fehler"})]})]}),m==="running"&&E.total>10&&E.current>0&&e.jsxs("p",{className:"text-xs text-muted-foreground text-center",children:["Geschätzte Restzeit: ~",Math.round((E.total-E.current)/2*12/60)," Minuten"]})]})]})]}),e.jsxs(S,{children:[e.jsx(k,{children:e.jsxs(C,{className:"flex items-center justify-between",children:[e.jsx("span",{children:"Warming-Logs"}),j.length>0&&e.jsxs(B,{variant:"secondary",children:[j.length," Einträge"]})]})}),e.jsx(v,{children:e.jsx(Q,{className:"h-[500px] rounded-lg border bg-background p-4",children:j.length===0?e.jsx("div",{className:"flex items-center justify-center h-full text-muted-foreground",children:"Keine Logs vorhanden. Starte eine Warming-Operation."}):e.jsx("div",{className:"space-y-2 font-mono text-sm",children:j.map((s,r)=>e.jsxs("div",{className:"flex items-start gap-2",children:[pe(s.level),e.jsxs("div",{className:"flex-1 break-all",children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:new Date(s.timestamp).toLocaleTimeString("de-DE")})," ",e.jsx("span",{className:s.level==="error"?"text-destructive":s.level==="success"?"text-secondary":s.level==="warning"?"text-accent":"text-foreground",children:s.message})]})]},r))})})})]})]})}),e.jsx(ue,{value:"batch",children:e.jsxs("div",{className:"grid gap-6 md:grid-cols-2",children:[e.jsxs(S,{children:[e.jsxs(k,{children:[e.jsxs(C,{className:"flex items-center gap-2",children:[e.jsx(Me,{className:"h-5 w-5"}),"Komplett-Purge (Alle Seiten)"]}),e.jsx(U,{children:"Purge aller Seiten: 15 statische + ~1.370 Berufsseiten. R2-Keys werden gelöscht und CDN invalidiert."})]}),e.jsxs(v,{className:"space-y-6",children:[e.jsxs("div",{className:"p-4 border rounded-lg bg-background space-y-2",children:[e.jsx("div",{className:"font-medium text-sm",children:"SWR-Architektur"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Der Cloudflare Worker prüft automatisch das R2-Alter (6h TTL). Veraltete Inhalte werden sofort ausgeliefert und im Hintergrund erneuert. Dieser Button purgt nur den CDN-Layer für sofortige Aktualisierung."})]}),e.jsxs("div",{className:"flex items-center gap-3 p-3 bg-muted rounded-lg",children:[ns(),e.jsxs("div",{children:[e.jsxs("div",{className:"font-medium",children:[a==="idle"&&"Bereit",a==="running"&&"Läuft...",a==="success"&&"Erfolgreich",a==="error"&&"Fehler aufgetreten"]}),Fe&&e.jsxs("div",{className:"text-sm text-muted-foreground",children:["Dauer: ",Fe]})]})]}),e.jsx(R,{onClick:G,disabled:a==="running",className:"w-full",size:"lg",children:a==="running"?e.jsxs(e.Fragment,{children:[e.jsx(I,{className:"mr-2 h-4 w-4 animate-spin"}),"Läuft..."]}
11):e.jsxs(e.Fragment,{children:[e.jsx(Me,{className:"mr-2 h-4 w-4"}),"Alle Seiten purgen (~1.385)"]})})]})]}),e.jsxs(S,{children:[e.jsxs(k,{children:[e.jsxs(C,{className:"flex items-center justify-between",children:[e.jsx("span",{children:"Logs"}),j.length>0&&e.jsxs(B,{variant:"secondary",children:[j.length," Einträge"]})]}),e.jsx(U,{children:"Echtzeit-Logs der aktuellen Operation."})]}),e.jsx(v,{children:e.jsx(Q,{className:"h-[400px] rounded-lg border bg-background p-4",children:j.length===0?e.jsx("div",{className:"flex items-center justify-center h-full text-muted-foreground",children:"Keine Logs vorhanden. Starte eine Operation."}):e.jsx("div",{className:"space-y-2 font-mono text-sm",children:j.map((s,r)=>e.jsxs("div",{className:"flex items-start gap-2",children:[pe(s.level),e.jsxs("div",{className:"flex-1 break-all",children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:new Date(s.timestamp).toLocaleTimeString("de-DE")})," ",e.jsx("span",{className:s.level==="error"?"text-destructive":s.level==="success"?"text-secondary":s.level==="warning"?"text-accent":"text-foreground",children:s.message})]})]},r))})})})]})]})}),e.jsx(ue,{value:"single",children:e.jsxs("div",{className:"grid gap-6 md:grid-cols-2",children:[e.jsxs(S,{children:[e.jsxs(k,{children:[e.jsxs(C,{className:"flex items-center gap-2",children:[e.jsx(we,{className:"h-5 w-5"}),"Einzelne Seite Purgen"]}),e.jsx(U,{children:"Purge & Warm für einen einzelnen Pfad oder Beruf-Slug."})]}),e.jsxs(v,{className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(We,{htmlFor:"singleSlug",children:"Pfad oder Beruf-Slug"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(Be,{id:"singleSlug",placeholder:"z.B. / oder /gehaltsrechner oder zerspanungsmechaniker",value:z,onChange:s=>ne(s.target.value),onKeyDown:s=>{s.key==="Enter"&&ie()}}),e.jsx(R,{onClick:ie,disabled:q==="running"||!z.trim(),children:q==="running"?e.jsx(I,{className:"h-4 w-4 animate-spin"}):e.jsx(we,{className:"h-4 w-4"})})]})]}),e.jsxs("div",{className:"text-sm text-muted-foreground space-y-2",children:[e.jsx("p",{className:"font-medium",children:"Eingabe-Formate:"}),e.jsxs("ul",{className:"list-disc list-inside ml-2 space-y-1",children:[e.jsxs("li",{children:[e.jsx("code",{className:"bg-muted px-1 rounded",children:"/"})," → Homepage"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-muted px-1 rounded",children:"/gehaltsrechner"})," → Statische Seite"]}),e.jsxs("li",{children:[e.jsx("code",{className:"bg-muted px-1 rounded",children:"zerspanungsmechaniker"})," → Beruf /berufe/zerspanungsmechaniker"]})]})]}),q==="success"&&e.jsxs("div",{className:"p-3 bg-secondary/10 text-secondary rounded-lg text-sm",children:["✅ Purge & Warm für ",e.jsx("strong",{children:z.startsWith("/")?z:`/berufe/${z}`})," gestartet!"]})]})]}),e.jsxs(S,{children:[e.jsx(k,{children:e.jsxs(C,{className:"flex items-center justify-between",children:[e.jsx("span",{children:"Logs"}),j.length>0&&e.jsxs(B,{variant:"secondary",children:[j.length," Einträge"]})]})}),e.jsx(v,{children:e.jsx(Q,{className:"h-[300px] rounded-lg border bg-background p-4",children:j.length===0?e.jsx("div",{className:"flex items-center justify-center h-full text-muted-foreground",children:"Keine Logs vorhanden."}):e.jsx("div",{className:"space-y-2 font-mono text-sm",children:j.map((s,r)=>e.jsxs("div",{className:"flex items-start gap-2",children:[pe(s.level),e.jsxs("div",{className:"flex-1 break-all",children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:new Date(s.timestamp).toLocaleTimeString("de-DE")})," ",e.jsx("span",{className:s.level==="error"?"text-destructive":s.level==="success"?"text-secondary":"text-foreground",children:s.message})]})]},r))})})})]})]})})]}),e.jsxs(S,{className:"mt-6",children:[e.jsx(k,{children:e.jsx(C,{children:"ℹ️ SWR-Architektur"})}),e.jsx(v,{className:"prose prose-sm max-w-none text-muted-foreground",children:e.jsxs("ul",{className:"list-disc list-inside space-y-1",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"Automatisch"}),": Der Worker prüft das R2-Alter (>6h = stale). Stale Content wird sofort ausgeliefert, R2-Key im Hintergrund gelöscht → nächster Request rendert frisch."]}),e.jsxs("li",{children:[e.jsx("strong",{children:"CDN-Purge"}),": Invalidiert nur den Cloudflare CDN-Cache. Nötig wenn Änderungen sofort sichtbar sein müssen (z.B. nach Deployments)."]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Single-Slug"}),": Für schnelles Debugging einzelner Seiten nach Content-Änderungen."]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Verifizierung"}),": ",e.jsx("code",{children:'curl -H "User-Agent: Googlebot" URL'})," → prüfe ",e.jsx("code",{children:"X-R2-Cached"})," und ",e.jsx("code",{children:"X-Rendered-At"})," Header."]})]})})]})]}),e.jsx(os,{})]})}
11export{Ds 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.