1import{r as l,e as re,a as ie,s as C,j as e,B as d,aq as ne,L as v,N as le,y as oe}from"./index-KSWbwNeY.js";import{A as ce}from"./AdminNav-DsaLvjFx.js";import{P as de}from"./progress-inmS6jmN.js";import{C as me}from"./checkbox-CU8ALz2k.js";import{C as B}from"./circle-check-8n8_Yy4E.js";import{T as O}from"./triangle-alert-D2A9IHcD.js";import{S as xe}from"./square-pen-CRmh_xc0.js";import{C as he,a as ue}from"./chevrons-right-kQ_1KW5C.js";import{C as fe}from"./chevron-left-C0OR5oyH.js";import"./index-DsYLezIw.js";import"./user-cog-DvqSS7bY.js";import"./trash-2-CwcwS_bf.js";import"./book-open-DS7Nmuzn.js";import"./receipt-DgWJf9Ou.js";import"./chevron-down-D7IdZFzc.js";const _=50,Ae=()=>{const[P,K]=l.useState([]),[E,H]=l.useState(0),[r,Z]=l.useState(null),[N,q]=l.useState(!0),[z,D]=l.useState(!0),[i,J]=l.useState(1),[g,f]=l.useState(new Set),[A,$]=l.useState(!1),[L,M]=l.useState({current:0,total:0}),[T,V]=l.useState("all"),Q=re(),{toast:w}=ie(),m=Math.ceil(E/_);l.useEffect(()=>{I()},[]),l.useEffect(()=>{R()},[i]);const I=async()=>{D(!0);try{const t=[];let a=0,o=!0;for(;o;){const{data:n,error:u}=await C.from("posts").select("id, seo_title, seo_description, seo_keywords, image_url, slug, published").range(a,a+1e3-1);if(u)throw u;n&&n.length>0?(t.push(...n),a+=1e3,o=n.length===1e3):o=!1}let c=0,x=0;const W=[];let b=0,y=0,j=0,p=0,h=0,k=0;t.forEach(n=>{let u=100;n.seo_title||(u-=10,b++),n.seo_description||(u-=15,y++),n.seo_keywords||(u-=10,j++),n.image_url||(u-=10,p++),n.slug||(u-=15,h++),n.published&&k++,c+=Math.max(0,u),u<70&&(x++,W.push(n.id))}),Z({total:t.length,published:k,missingTitle:b,missingDesc:y,missingKeywords:j,missingImage:p,missingSlug:h,avgScore:t.length>0?Math.round(c/t.length):0,needsWork:x,needsWorkIds:W}),H(t.length)}catch(t){console.error("Error fetching global stats:",t)}finally{D(!1)}},R=async()=>{q(!0);try{const t=(i-1)*_,s=t+_-1,{data:a,error:o}=await C.from("posts").select("id, title, slug, seo_title, seo_description, seo_keywords, excerpt, content, image_url, published").order("created_at",{ascending:!1}).range(t,s);if(o)throw o;K(a||[])}catch(t){w({variant:"destructive",title:"Error fetching posts",description:t.message})}finally{q(!1)}},F=t=>{let s=100,a=!1;return t.seo_title?t.seo_title.length>60&&(s-=5,a=!0):(s-=10,a=!0),t.seo_description?t.seo_description.length>160&&(s-=5,a=!0):(s-=15,a=!0),t.seo_keywords||(s-=10,a=!0),t.image_url||(s-=10,a=!0),t.slug||(s-=15,a=!0),{post:t,score:Math.max(0,s),hasIssues:a}},G=l.useMemo(()=>{const t=P.map(F);return T==="needs-attention"?t.filter(s=>s.score<70):t},[P,T]);l.useMemo(()=>{const t=P.map(F),s=t.length>0?Math.round(t.reduce((c,x)=>c+x.score,0)/t.length):0,a=t.filter(c=>c.score<70).length,o=t.filter(c=>c.post.published).length;return{avgScore:s,needsAttention:a,published:o,total:t.length}},[P]);const U=t=>t>=90?"text-emerald-600 bg-emerald-50":t>=70?"text-amber-600 bg-amber-50":"text-red-600 bg-red-50",X=()=>{I(),R(),f(new Set),w({title:"Refreshed",description:"SEO data updated"})},Y=t=>{const s=new Set(g);s.has(t)?s.delete(t):s.add(t),f(s)},ee=()=>f(new Set(G.map(t=>t.post.id))),te=()=>f(new Set),se=()=>{r!=null&&r.needsWorkIds&&(f(new Set(r.needsWorkIds)),w({title:`${r.needsWorkIds.length.toLocaleString()} posts selected`,description:"All posts with SEO score <70% across all pages"}))},ae=async()=>{var o,c;if(g.size===0){w({variant:"destructive",title:"No posts selected"});return}$(!0);const t=Array.from(g);M({current:0,total:t.length});let s=0;const a=50;for(let x=0;x<t.length;x+=a){const W=t.slice(x,x+a),{data:b,error:y}=await C.from("posts").select("id, title, content, excerpt").in("id",W);if(y||!b){console.error("Error fetching batch:",y);continue}for(let j=0;j<b.length;j++){const p=b[j];M({current:x+j+1,total:t.length});try{const{data:h,error:k}=await C.functions.invoke("generate-seo",{body:{title:p.title,content:p.content||p.excerpt,excerpt:p.excerpt}});if(k)throw k;h&&(await C.from("posts").update({seo_title:h.seo_title,seo_description:h.seo_de
1scription,seo_keywords:h.seo_keywords}).eq("id",p.id),s++),await new Promise(n=>setTimeout(n,1e3))}catch(h){if((o=h.message)!=null&&o.includes("Rate limit")||(c=h.message)!=null&&c.includes("429")){w({variant:"destructive",title:"Rate limit reached",description:`Generated ${s} before limit.`}),$(!1),M({current:0,total:0}),f(new Set),await R(),await I();return}}}}$(!1),M({current:0,total:0}),f(new Set),await R(),await I(),w({title:"Complete",description:`Generated SEO for ${s} posts.`})},S=t=>{t>=1&&t<=m&&(J(t),f(new Set))};return e.jsxs("div",{className:"min-h-screen bg-background",children:[e.jsx(ce,{}),e.jsx("main",{className:"md:ml-52 p-4 md:p-6",children:e.jsxs("div",{className:"max-w-7xl mx-auto space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-xl font-semibold",children:"SEO Validator"}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[E.toLocaleString()," posts · Page ",i," of ",m]})]}),e.jsxs(d,{onClick:X,variant:"outline",size:"sm",className:"gap-1.5 h-8",children:[e.jsx(ne,{className:"h-3.5 w-3.5"}),"Refresh"]})]}),e.jsxs("div",{className:"grid grid-cols-4 gap-3",children:[e.jsxs("div",{className:"bg-muted/30 border p-3 rounded-none",children:[e.jsx("div",{className:"text-xs text-muted-foreground mb-1",children:"Average Score (All)"}),z?e.jsx(v,{className:"h-5 w-5 animate-spin text-muted-foreground"}):e.jsxs("div",{className:`text-2xl font-bold ${((r==null?void 0:r.avgScore)??0)>=90?"text-emerald-600":((r==null?void 0:r.avgScore)??0)>=70?"text-amber-600":"text-red-600"}`,children:[(r==null?void 0:r.avgScore)??0,"%"]})]}),e.jsxs("div",{className:"bg-muted/30 border p-3 rounded-none",children:[e.jsx("div",{className:"text-xs text-muted-foreground mb-1",children:"Total Posts"}),z?e.jsx(v,{className:"h-5 w-5 animate-spin text-muted-foreground"}):e.jsx("div",{className:"text-2xl font-bold",children:(r==null?void 0:r.total.toLocaleString())??0})]}),e.jsxs("div",{className:"bg-muted/30 border p-3 rounded-none",children:[e.jsx("div",{className:"text-xs text-muted-foreground mb-1",children:"Published"}),z?e.jsx(v,{className:"h-5 w-5 animate-spin text-muted-foreground"}):e.jsx("div",{className:"text-2xl font-bold",children:(r==null?void 0:r.published.toLocaleString())??0})]}),e.jsxs("div",{className:"bg-muted/30 border p-3 rounded-none",children:[e.jsx("div",{className:"text-xs text-muted-foreground mb-1",children:"Needs Work (All)"}),z?e.jsx(v,{className:"h-5 w-5 animate-spin text-muted-foreground"}):e.jsx("div",{className:"text-2xl font-bold text-red-600",children:(r==null?void 0:r.needsWork.toLocaleString())??0})]})]}),g.size>0&&e.jsxs("div",{className:"bg-primary/5 border border-primary/20 p-3 flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"text-sm font-medium",children:[g.size," selected"]}),e.jsx(d,{onClick:te,variant:"ghost",size:"sm",className:"h-7 text-xs",children:"Clear"})]}),e.jsx(d,{onClick:ae,disabled:A,size:"sm",className:"h-7 gap-1.5",children:A?e.jsxs(e.Fragment,{children:[e.jsx(v,{className:"h-3 w-3 animate-spin"}),L.current,"/",L.total]}):"Generate SEO"})]}),A&&e.jsx(de,{value:L.current/L.total*100,className:"h-1"}),g.size===0&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(d,{onClick:ee,variant:"outline",size:"sm",className:"h-7 text-xs",children:"Select All"}),e.jsx(d,{onClick:se,variant:"outline",size:"sm",className:"h-7 text-xs",children:"Select <70%"}),e.jsx("div",{className:"flex-1"}),e.jsxs("div",{className:"flex border rounded-none overflow-hidden",children:[e.jsx("button",{onClick:()=>V("all"),className:`px-3 py-1 text-xs transition-colors ${T==="all"?"bg-primary text-primary-foreground":"bg-muted/50 hover:bg-muted"}`,children:"All"}),e.jsx("button",{onClick:()=>V("needs-attention"),className:`px-3 py-1 text-xs transition-colors ${T==="needs-attention"?"bg-primary text-primary-foreground":"bg-muted/50 hover:bg-muted"}`,children:"Needs Work"})]})]}),N?e.jsx("div",{className:"flex items-center justify-center py-12",children:e.jsx(v,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):e.jsxs("div",{className:"border rounded-none overflow-hidden",children:[e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-muted/50 border-b",children:e.jsxs("tr",{children:[e.jsx("th",{className:"w-8 p-2"}),e.jsx("th",{className:"text-left p-2 font-medium",children:"Title"}),e.jsx("th",{className:"w-16 text-center p-2 font-medium",children:"Score"}),e.jsx("th",{className:"w-14 text-center p-2 font-medium",children:"Title"}),e.jsx("th",{className:"w-14 text-center p-2 font-medium",children:"Desc"}),e.jsx("th",{className:"w-14 text-center p-2 font-medium",children:"Keys"}),e.jsx("th",{className:"w-14 text-center p-2 font-medium",children:"Img"}),e.jsx("th",{className:"w-20 p-2"})]})}),e.jsx("tbody",{className:"divide-y",children:G.map(t=>e.jsxs("tr",{className:"hover:bg-muted/30 transition-colors",children:[e.jsx("td",{className:"p-2 text-center",children:e.jsx(me,{checked:g.has(t.post.id),onCheckedChange:()=>Y(t.post.id),disabled:A,className:"h-3.5 w-3.5"})}),e.jsxs("td",{className:"p-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium line-clamp-1 max-w-md",children:t.post.title}),!t.post.published&&e.jsx(le,{variant:"outline",className:"text-[10px] px-1.5 py-0",children:"Draft"})]}),e.jsx("div",{className:"text-xs text-muted-foreground truncate max-w-md",children:t.post.slug||t.post.id})]}),e.jsx("td",{className:"p-2 text-center",children:e.jsxs("span",{className:`inline-flex items-center justify-center w-10 h-6 text-xs font-semibold ${U(t.score)}`,children:[t.score,"%"]})}),e.jsx("td",{className:"p-2 text-center",children:t.post.seo_title?e.jsx(B,{className:"h-3.5 w-3.5 text-emerald-500 mx-auto"}):e.jsx(O,{className:"h-3.5 w-3.5 text-amber-500 mx-auto"})}),e.jsx("td",{className:"p-2 text-center",children:t.post.seo_description?e.jsx(B,{className:"h-3.5 w-3.5 text-emerald-500 mx-auto"}):e.jsx(O,{className:"h-3.5 w-3.5 text-amber-500 mx-auto"})}),e.jsx("td",{className:"p-2 text-center",children:t.post.seo_keywords?e.jsx(B,{className:"h-3.5 w-3.5 text-emerald-500 mx-auto"}):e.jsx(O,{className:"h-3.5 w-3.5 text-amber-500 mx-auto"})}),e.jsx("td",{className:"p-2 text-center",children:t.post.image_url?e.jsx(B,{className:"h-3.5 w-3.5 text-emerald-500 mx-auto"}):e.jsx(O,{className:"h-3.5 w-3.5 text-amber-500 mx-auto"})}),e.jsx("td",{className:"p-2 text-right",children:e.jsxs(d,{variant:"ghost",size:"sm",onClick:()=>Q(`/admin/posts/edit/${t.post.id}`),className:"h-6 px-2 text-xs gap-1",children:[e.jsx(xe,{className:"h-3 w-3"}),"Edit"]})})]},t.post.id))})]}),G.length===0&&e.jsx("div",{className:"text-center py-8 text-muted-foreground text-sm",children:"No posts found"})]}),m>1&&e.jsxs("div",{className:"flex items-center justify-between pt-2",children:[e.jsxs("div",{className:"text-xs text-muted-foreground",children:["Showing ",(i-1)*_+1,"â",Math.min(i*_,E)," of ",E.toLocaleStr
1ing()]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(d,{variant:"outline",size:"sm",onClick:()=>S(1),disabled:i===1||N,className:"h-7 w-7 p-0",children:e.jsx(he,{className:"h-3.5 w-3.5"})}),e.jsx(d,{variant:"outline",size:"sm",onClick:()=>S(i-1),disabled:i===1||N,className:"h-7 w-7 p-0",children:e.jsx(fe,{className:"h-3.5 w-3.5"})}),e.jsx("div",{className:"flex items-center gap-1 mx-2",children:Array.from({length:Math.min(5,m)},(t,s)=>{let a;return m<=5||i<=3?a=s+1:i>=m-2?a=m-4+s:a=i-2+s,e.jsx(d,{variant:a===i?"default":"outline",size:"sm",onClick:()=>S(a),disabled:N,className:"h-7 w-7 p-0 text-xs",children:a},a)})}),e.jsx(d,{variant:"outline",size:"sm",onClick:()=>S(i+1),disabled:i===m||N,className:"h-7 w-7 p-0",children:e.jsx(oe,{className:"h-3.5 w-3.5"})}),e.jsx(d,{variant:"outline",size:"sm",onClick:()=>S(m),disabled:i===m||N,className:"h-7 w-7 p-0",children:e.jsx(ue,{className:"h-3.5 w-3.5"})})]})]})]})})]})};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.