1import{r as n,j as e}from"./react-vendor-CAvUCgBg.js";import{k as U,S as T,B as m,C as j,I as C,b as E,s as x}from"./index-BD5OT4An.js";import{ab as $,$ as A,P,a4 as W,a5 as G,T as O,a2 as S,p as z}from"./icons-B1xxNXCI.js";import{R as D,C as M,X as Y,Y as q,T as X}from"./generateCategoricalChart--4UFDH3P.js";import{L as J,a as F}from"./LineChart-i6r_0qI8.js";import"./query-C7ekqVw8.js";import"./class-utils-B2rm_Apj.js";import"./supabase-L6Z3U_Fd.js";import"./radix-5feLYWdW.js";import"./index-CS5oWzk7.js";import"./quantize-CPKWUwO6.js";import"./string-3NetaFjT.js";const H=["https://postadz.com/","https://postadz.com/category/housing","https://postadz.com/category/jobs","https://postadz.com/category/for-sale","https://postadz.com/category/services","https://postadz.com/category/gigs","https://postadz.com/category/community-meetups","https://postadz.com/category/events","https://postadz.com/category/pets","https://postadz.com/category/remote-work","https://postadz.com/category/wanted","https://postadz.com/second-chance","https://postadz.com/directory","https://postadz.com/u","https://postadz.com/chat"];function Q({keywords:u}){const{toast:i}=U(),[g,p]=n.useState(!1),[w,y]=n.useState(""),l=n.useMemo(()=>{const t=u.map(c=>c.target_url).filter(c=>c.startsWith("https://postadz.com")),o=w.split(/\s+/).map(c=>c.trim()).filter(c=>c.startsWith("https://postadz.com"));return Array.from(new Set([...H,...t,...o]))}
1,[u,w]),N=async()=>{p(!0);const{data:t,error:o}=await x.functions.invoke("submit-indexnow",{body:{urls:l}});p(!1),i(o?{title:"IndexNow failed",description:o.message,variant:"destructive"}:{title:"IndexNow submitted",description:`${(t==null?void 0:t.submitted)??l.length} URLs sent to Bing/Yandex/Seznam/Naver`})},v=async()=>{p(!0);const{data:t,error:o}=await x.functions.invoke("submit-bing-webmaster",{body:{urls:l}});p(!1),o?i({title:"Bing submit failed",description:o.message,variant:"destructive"}):t!=null&&t.ok?i({title:"Bing Webmaster submitted",description:`${(t==null?void 0:t.submitted)??l.length} URLs across ${t==null?void 0:t.batches} batch(es)`}):i({title:"Bing partial failure",description:JSON.stringify((t==null?void 0:t.results)??t),variant:"destructive"})},h=encodeURIComponent("sc-domain:postadz.com"),k=`https://search.google.com/search-console/sitemaps?resource_id=${h}`,b=t=>`https://search.google.com/search-console/inspect?resource_id=${h}&id=${encodeURIComponent(t)}`;return e.jsxs(j,{className:"p-4 space-y-4",children:[e.jsxs("div",{children:[e.jsxs("h2",{className:"font-semibold flex items-center gap-2",children:[e.jsx(S,{className:"h-4 w-4"}),"One-click recrawl"]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Pings IndexNow (Bing, Yandex, Seznam, Naver) instantly. Google deprecated their public sitemap-ping endpoint, so for Google use the deep-links below to open Search Console."})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-muted-foreground",children:"Optional extra URLs (whitespace-separated)"}),e.jsx(C,{value:w,onChange:t=>y(t.target.value),placeholder:"https://postadz.com/c/us/austin/jobs ..."}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-1",children:[l.length," URLs queued."]})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(m,{onClick:N,disabled:g,children:[e.jsx(S,{className:"h-4 w-4 mr-2"}),g?"Submittingâ¦":"Ping IndexNow now"]}),e.jsxs(m,{onClick:v,disabled:g,variant:"secondary",children:[e.jsx(S,{className:"h-4 w-4 mr-2"}),g?"Submittingâ¦":"Submit to Bing Webmaster"]}),e.jsx(m,{variant:"outline",asChild:!0,children:e.jsxs("a",{href:k,target:"_blank",rel:"noopener noreferrer",children:[e.jsx(z,{className:"h-4 w-4 mr-2"}),"Open Google Sitemaps"]})}),e.jsx(m,{variant:"outline",asChild:!0,children:e.jsxs("a",{href:`https://search.google.com/search-console?resource_id=${h}`,target:"_blank",rel:"noopener noreferrer",children:[e.jsx(z,{className:"h-4 w-4 mr-2"}),"Search Console home"]})})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-medium mb-2",children:"Inspect a single URL in Google Search Console"}),e.jsx("div",{className:"grid sm:grid-cols-2 gap-1 max-h-60 overflow-y-auto",children:l.map(t=>e.jsxs("a",{href:b(t),target:"_blank",rel:"noopener noreferrer",className:"text-xs text-primary hover:underline truncate flex items-center gap-1",children:[e.jsx(z,{className:"h-3 w-3 shrink-0"}),t.replace("https://postadz.com","")||"/"]},t))})]})]})}function de(){const{toast:u}=U(),[i,g]=n.useState([]),[p,w]=n.useState([]),[y,l]=n.useState(!0),[N,v]=n.useState(!1),[h,k]=n.useState(""),[b,t]=n.useState("https://postadz.com/"),o=async()=>{l(!0);const[s,a]=await Promise.all([x.from("seo_tracked_keywords").select("*").order("added_at",{ascending:!1}),x.from("seo_keyword_rankings").select("*").order("fetched_at",{ascending:!1}).limit(2e3)]);g(s.data||[]),w(a.data||[]),l(!1)};n.useEffect(()=>{o()},[]);const c=n.useMemo(()=>{const s=new Map;for(const a of p)s.has(a.keyword_id)||s.set(a.keyword_id,[]),s.get(a.keyword_id).push(a);for(const a of s.values())a.sort((r,d)=>r.fetched_at.localeCompare(d.fetched_at));return s},[p]),_=n.useMemo(()=>{const s=[];for(const a of i){const r=c.get(a.id)||[];if(r.length<2)continue;const d=r[r.length-1].position,f=r[r.length-2].position;d==null||f==null||s.push({kw:a,delta:f-d,latest:d,prev:f})}return s.sort((a,r)=>r.delta-a.delta),s},[i,c]),B=async()=>{if(!h.trim())return;const{error:s}=await x.from("seo_tracked_keywords").insert({keyword:h.trim().toLowerCase(),target_url:b.trim()||"https://postadz.com/",country:"us"});s?u({title:"Error",description:s.message,variant:"destructive"}):(k(""),o())},I=async s=>{await x.from("seo_tracked_keywords").delete().eq("id",s),o()},K=async()=>{v(!0);const{error:s}=await x.functions.invoke("track-keyword-rankings",{body:{}});v(!1),s?u({title:"Error",description:s.message,variant:"destructive"}):(u({title:"Tracker run complete"}),o())},R=_.slice(0,5),L=[..._].reverse().slice(0,5);return e.jsx(T,{children:e.jsxs("div",{className:"container max-w-6xl py-8 space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-3",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold",children:"SEO Keyword Tracker"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Daily AI-estimated Google rankings for postadz.com."})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(m,{variant:"outline",onClick:o,disabled:y,children:[e.jsx($,{className:"h-4 w-4 mr-2"}),"Refresh"]}),e.jsxs(m,{onClick:K,disabled:N,children:[e.jsx(A,{className:"h-4 w-4 mr-2"}),N?"Runningâ¦":"Run tracker now"]})]})]}),e.jsx(j,{className:"p-4",children:e.jsxs("div",{className:"flex flex-wrap gap-2 items-end",children:[e.jsxs("div",{className:"flex-1 min-w-[200px]",children:[e.jsx("label",{className:"text-xs text-muted-foreground",children:"Keyword"}),e.jsx(C,{value:h,onChange:s=>k(s.target.value),placeholder:"e.g. free classifieds boston"})]}),e.jsxs("div",{className:"flex-1 min-w-[200px]",children:[e.jsx("label",{className:"text-xs text-muted-foreground",children:"Target URL"}),e.jsx(C,{value:b,onChange:s=>t(s.target.value)})]}),e.jsxs(m,{onClick:B,children:[e.jsx(P,{className:"h-4 w-4 mr-2"}),"Add"]})]})}),e.jsx(Q,{keywords:i}),e.jsxs("div",{className:"grid md:grid-cols-2 gap-4",children:[e.jsxs(j,{className:"p-4",children:[e.jsxs("h2",{className:"font-semibold mb-3 flex items-center gap-2",children:[e.jsx(W,{className:"h-4 w-4 text-green-500"}),"Best movers"]}),R.length===0?e.jsx("p",{className:"text-sm text-muted-foreground",children:"Need 2+ data points per keyword."}):e.jsx("ul",{className:"space-y-2 text-sm",children:R.map(s=>e.jsxs("li",{className:"flex justify-between gap-2",children:[e.jsx("span",{className:"truncate",children:s.kw.keyword}),e.jsxs("span",{className:"text-green-600 font-mono",children:["#",s.prev,"â#",s.latest," (",s.delta>0?"+":"",s.delta,")"]})]},s.kw.id))})]}),e.jsxs(j,{className:"p-4",children:[e.jsxs("h2",{className:"font-semibold mb-3 flex items-center gap-2",children:[e.jsx(G,{className:"h-4 w-4 text-red-500"}),"Worst movers"]}),L.length===0?e.jsx("p",{className:"text-sm text-muted-foreground",children:"Need 2+ data points per keyword."}):e.jsx("ul",{className:"space-y-2 text-sm",children:L.map(s=>e.jsxs("li",{className:"flex justify-between gap-2",children:[e.jsx("span",{className:"truncate",children:s.kw.keyword}),e.jsxs("span",{className:"text-red-600 font-mono",children:["#",s.prev,"â#",s.latest," (",s.delta>0?"+":"",s.delta,")"]})]},s.kw.id))})]})]}),e.jsxs("div",{className:"space-y-4",children:[i.map(s=>{var d;const a=(c.get(s.id)||[]).map(f=>({t:new Date(f.fetched_at).toLocaleDateString(),position:f.position??101})),r=(d=a[a.length-1])==null?void 0:d.position;return e.jsxs(j,{className:"p-4",children:[e.jsxs("div",{className:"flex justify-between items-start gap-2 mb-2 flex-wrap",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium",children:s.keyword}),e.jsx("div",{className:"text-xs text-muted-foreground truncate",children:s.target_url})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(E,{variant:r&&r<=10?"default":"secondary",children:r==null?"no data":r>=101?"unranked":`#${r}`}),e.jsx(m,{size:"sm",variant:"ghost",onClick:()=>I(s.id),children:e.jsx(O,{className:"h-4 w-4"})})]})]}),a.length>0?e.jsx("div",{className:"h-32",children:e.jsx(D,{width:"100%",height:"100%",children:e.jsxs(J,{data:a,children:[e.jsx(M,{strokeDasharray:"3 3",opacity:.2}),e.jsx(Y,{dataKey:"t",fontSize:10}),e.jsx(q,{reversed:!0,domain:[1,101],fontSize:10}),e.jsx(X,{}),e.jsx(F,{type:"monotone",dataKey:"position",stroke:"hsl(var(--primary))",strokeWidth:2,dot:{r:2}})]})})}):e.jsx("p",{className:"text-xs text-muted-foreground",children:'No rankings recorded yet â click "Run tracker now".'})]},s.id)}),i.length===0&&!y&&e.jsx(j,{className:"p-8 text-center text-muted-foreground",children:"No keywords tracked yet."})]})]})})}export{de 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.