vendor: 3,983 bytes, lines 1-16
1import{c as te,r as b,s as L,j as e,f as W,B as k,ar as _e,L as Q,S as G,a as ye,ac as Se,w as Ce,d as ke,as as oe}from"./index-Bidt7FvI.js";import{u as J}from"./useQuery-Bia0V7jv.js";import{C as R,a as B,b as P,c as T}from"./card-0GvRfV9r.js";import{R as U,P as z}from"./progress-eG3z80zC.js";import{g as je,r as Ee,a as Ie,f as Ae,b as de,c as Re,d as Te}from"./radar-DJ8NsNk4.js";import{u as Le,E as Me,S as be,c as qe,I as $e}from"./stringify-DxryBauX.js";import{L as se}from"./loader-circle-Du3tBUeG.js";import{I as Ge}from"./input-Cm9-CwpP.js";import{L as Be}from"./label-GLhTkpJY.js";import{D as Pe,a as De,b as Oe,c as Ue,d as We,e as Fe}from"./dialog-BZ1qSJHU.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 we=te("CircleCheck",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]]);/** 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 ze=te("CircleX",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m15 9-6 6",key:"1uzhvr"}],["path",{d:"m9 9 6 6",key:"z0biqf"}]]);/** 12 * @license lucide-react v0.462.0 - ISC 13 * 14 * This source code is licensed under the ISC license. 15 * See the LICENSE file in the root directory of this source tree. 16 */const He=te("Undo2",[["path",{d:"M9 14 4 9l5-5",key:"102s5s"}],["path",{d:"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11",key:"f3b9sd"}]]),Qe=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;function Je(t){return typeof t=="string"&&Qe.test(t)}function ue(t){if(!Je(t))throw TypeError("Invalid UUID");let s;return Uint8Array.of((s=parseInt(t.slice(0,8),16))>>>24,s>>>16&255,s>>>8&255,s&255,(s=parseInt(t.slice(9,13),16))>>>8,s&255,(s=parseInt(t.slice(14,18),16))>>>8,s&255,(s=parseInt(t.slice(19,23),16))>>>8,s&255,(s=parseInt(t.slice(24,36),16))/1099511627776&255,s/4294967296&255,s>>>24&255,s>>>16&255,s>>>8&255,s&255)}function Ke(t){t=unescape(encodeURIComponent(t));const s=new Uint8Array(t.length);for(let n=0;n<t.length;++n)s[n]=t.charCodeAt(n);return s}const Xe="6ba7b810-9dad-11d1-80b4-00c04fd430c8",Ye="6ba7b811-9dad-11d1-80b4-00c04fd430c8";function Ve(t,s,n,r,h,u){const m=typeof n=="string"?Ke(n):n,c=typeof r=="string"?ue(r):r;if(typeof r=="string"&&(r=ue(r)),(r==null?void 0:r.length)!==16)throw TypeError("Namespace must be array-like (16 iterable integer values, 0-255)");let a=new Uint8Array(16+m.length);if(a.set(c),a.set(m,c.length),a=s(a),a[6]=a[6]&15|t,a[8]=a[8]&63|128,h){u=u||0;for(let p=0;p<16;++p)h[u+p]=a[p];return h}return Le(a)}function Ze(t,s,n,r){switch(t){case 0:return s&n^~s&r;case 1:return s^n^r;case 2:return s&n^s&r^n&r;case 3:return s^n^r}}function K(t,s){return t<<s|t>>>32-s}function et(t){const s=[1518500249,1859775393,2400959708,3395469782],n=[1732584193,4023233417,2562383102,271733878,3285377520],r=new Uint8Array(t.length+1);r.set(t),r[t.length]=128,t=r;const h=t.length/4+2,u=Math.ceil(h/16),m=new Array(u);for(let c=0;c<u;++c){const a=new Uint32Array(16);for(let p=0;p<16;++p)a[p]=t[c*64+p*4]<<24|t[c*64+p*4+1]<<16|t[c*64+p*4+2]<<8|t[c*64+p*4+3];m[c]=a}m[u-1][14]=(t.length-1)*8/Math.pow(2,32),m[u-1][14]=Math.floor(m[u-1][14]),m[u-1][15]=(t.length-1)*8&4294967295;for(let c=0;c<u;++c){const a=new Uint32Array(80);for(let d=0;d<16;++d)a[d]=m[c][d];for(let d=16;d<80;++d)a[d]=K(a[d-3]^a[d-8]^a[d-14]^a[d-16],1);let p=n[0],v=n[1],w=n[2],o=n[3],i=n[4];for(let d=0;d<80;++d){const N=Math.floor(d/20),_=K(p,5)+Ze(N,v,w,o)+i+s[N]+a[d]>>>0;i=o,o=w,w=K(v,30)>>>0,v=p,p=_}n[0]=n[0]+p>>>0,n[1]=n[1]+v>>>0,n[2]=n[2]+w>>>0,n[3]=n[3]+o>>>0,n[4]=n[4]+i>>>0}return Uint8Array.of(n[0]>>24,n[0]>>16,n[0]>>8,n[0],n[1]>>24,n[1]>>16,n[1]>>8,n[1],n[2]>>24,n[2]>>16,n[2]>>8,n[2],n[3]>
16>24,n[3]>>16,n[3]>>8,n[3],n[4]>>24,n[4]>>16,n[4]>>8,n[4])}function ne(t,s,n,r){return Ve(80,et,t,s,n,r)}ne.DNS=Xe;ne.URL=Ye;const tt=2e4,st=5e3,nt=8e3,rt=12,me=new Set(["completed","failed"]),D=t=>`radar-drive-${t}`,H=t=>new Promise(s=>setTimeout(s,t)),at=async(t,s)=>{try{const n=localStorage.getItem(D(t));if(n){const{ts:h,o:u}=JSON.parse(n);if(u!==s&&Date.now()-h<tt)return!1}localStorage.setItem(D(t),JSON.stringify({ts:Date.now(),o:s})),await H(50+Math.random()*100);const r=localStorage.getItem(D(t));return r?JSON.parse(r).o===s:!1}catch{return!0}},it=(t,s)=>{try{const n=localStorage.getItem(D(t));if(n&&JSON.parse(n).o!==s)return;localStorage.setItem(D(t),JSON.stringify({ts:Date.now(),o:s}))}catch{}},ct=(t,s)=>{try{const n=localStorage.getItem(D(t));n&&JSON.parse(n).o===s&&localStorage.removeItem(D(t))}catch{}},lt=()=>{try{return crypto.randomUUID()}catch{return`o-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}},X={panelId:null,batchId:null,runs:[],checks:[],mentions:[],isScanning:!1,isComplete:!1,error:null},fe=t=>[...t].sort((s,n)=>s.engine.localeCompare(n.engine)),ot=()=>{const[t,s]=b.useState(X),n=b.useRef(0),r=b.useRef(!1),h=b.useRef(lt()),u=b.useRef(null),m=b.useRef(null),c=b.useCallback(()=>{u.current&&(L.removeChannel(u.current),u.current=null),m.current&&(L.removeChannel(m.current),m.current=null)},[]);b.useEffect(()=>(r.current=!1,()=>{r.current=!0,n.current+=1,c()}),[c]);const a=b.useCallback(g=>!r.current&&g===n.current,[]),p=b.useCallback((g,f)=>{a(f)&&s(l=>{const x=new Map(l.runs.map(y=>[y.engine,y]));for(const y of g)x.set(y.engine,{...x.get(y.engine),...y});return{...l,runs:fe([...x.values()])}})},[a]),v=b.useCallback((g,f)=>{a(f)&&s(l=>l.checks.some(x=>x.id===g.id)?l:{...l,checks:[...l.checks,g]})},[a]),w=b.useCallback(async(g,f)=>{const l=await je(g);return a(f)&&s(x=>({...x,runs:fe(l.runs),checks:l.checks,mentions:l.mentions})),l},[a]),o=b.useCallback((g,f)=>{!a(f)||u.current||(u.current=L.channel(`radar-checks-${g}-${f}`).on("postgres_changes",{event:"INSERT",schema:"public",table:"ai_visibility_checks",filter:`panel_id=eq.${g}`},l=>{const x=l.new;x&&typeof x.id=="string"&&v({id:x.id,engine:String(x.engine??""),prompt_id:x.prompt_id??null,query:String(x.query??""),brand_cited:!!x.brand_cited},f)}).subscribe())},[v,a]),i=b.useCallback((g,f)=>{!a(f)||m.current||(m.current=L.channel(`radar-runs-${g}-${f}`).on("postgres_changes",{event:"UPDATE",schema:"public",table:"engine_runs",filter:`scan_batch_id=eq.${g}`},l=>{const x=l.new;x&&typeof x.engine=="string"&&p([x],f)}).subscribe())},[a,p]),d=b.useCallback((g,f)=>{a(g)&&(n.current+=1,c(),s(l=>({...l,isScanning:!1,...f})))},[a,c]),N=b.useCallback(async(g,f)=>{for(let l=0;l<3;l++)try{await w(g,f),d(f,{isComplete:!0,error:null});return}catch{if(await H(1500),!a(f))return}d(f,{error:"The scan finished, but loading the full results failed. Resume to reload them."})},[d,a,w]),_=b.useCallback(async(g,f)=>{const l=h.current;let x=0,y=null;const I=S=>S.length>0&&S.every(M=>me.has(M.status));try{for(;a(f);)if(await at(g,l)){if(!a(f))return;if(x>=rt){d(f,{error:"This scan is taking unusually long. You can resume it â progress so far is saved."});return}x+=1,y=setInterval(()=>it(g,l),st);let S;try{S=await Ee(g)}finally{clearInterval(y),y=null}if(!a(f))return;if(p(S.engine_runs,f),S.done){await N(g,f);return}}else{if(await H(nt),!a(f))return;try{const S=await w(g,f);if(I(S.runs)){d(f,{isComplete:!0,error:null});return}}catch{}}}catch(S){a(f)&&d(f,{error:S instanceof Error?S.message:"Scan failed"})}finally{y&&clearInterval(y),ct(g,l)}},[d,N,a,p,w]),C=b.useCallback(async g=>{const f=++n.current;c(),s({...X,panelId:g,isScanning:!0}),o(g,f);const l=Ie(g);(async()=>{for(let I=0;I<20&&a(f);I++){try{const S=await Ae(g);if(S){if(!a(f))return;s(M=>M.batchId?M:{...M,batchId:S}),i(S,f),await w(S,f).catch(()=>{});return}}catch{}await H(2e3)}})();let x;try{x=await l}catch(I){d(f,{error:I instanceof Error?I.message:"Could not start scan"});return}if(!a(f))return;const y=x.scan_batch_id;if(s(I=>({...I,batchId:y})),i(y,f),p(x.engine_runs,f),x.done){await N(y,f);return}await _(y,f)},[_,d,N,a,p,w,c,o,i]),E=b.useCallback(async(g,f)=>{const l=++n.current;c(),s({...X,panelId:g,batchId:f,isScanning:!0}),o(g,l),i(f,l);try{const x=await w(f,l);if(x.runs.length>0&&x.runs.every(y=>me.has(y.status))){d(l,{isComplete:!0,error:null});return}}catch{}await _(f,l)},[_,d,w,c,o,i]);return{...t,start:C,adopt:E}},Y=(t,s)=>s===0?0:Math.round(t/s*100),he=t=>t.prompt_id??`q:${t.query}`;function xe(t,s){const n=new Map;for(const o of s){const i=n.get(o.check_id)??[];i.push(o),n.set(o.check_id,i)}const r=new Map;for(const o of t){const i=he(o),d=r.get(i)??[];d.push(o),r.set(i,d)}const h=r.size;let u=0;const m=[];for(const[,o]of r){if(o.some(C=>C.brand_cited)){u+=1;continue}const d=new Map,N=new Map;
16for(const C of o)for(const E of n.get(C.id)??[]){d.set(E.competitor_name,(d.get(E.competitor_name)??0)+1);const g=N.get(E.competitor_name);E.cited_url&&(g===void 0||E.cited_url<g)&&N.set(E.competitor_name,E.cited_url)}const _=[...d.entries()].sort((C,E)=>E[1]-C[1]||Number(N.has(E[0]))-Number(N.has(C[0]))||C[0].localeCompare(E[0])).map(([C])=>C);m.push({query:o[0].query,engines:[...new Set(o.map(C=>C.engine))].sort(),winners:_,winningUrl:_.length>0?N.get(_[0])??null:null})}m.sort((o,i)=>i.winners.length-o.winners.length||o.query.localeCompare(i.query));const c=new Map;for(const o of t){const i=c.get(o.engine)??{cited:0,total:0};i.total+=1,o.brand_cited&&(i.cited+=1),c.set(o.engine,i)}const a=[...c.entries()].map(([o,i])=>({engine:o,cited:i.cited,total:i.total,pct:Y(i.cited,i.total)})).sort((o,i)=>o.engine.localeCompare(i.engine)),p=new Map,v=new Map(t.map(o=>[o.id,o]));for(const o of s){const i=v.get(o.check_id);if(!i)continue;const d=p.get(o.competitor_name)??new Set;d.add(he(i)),p.set(o.competitor_name,d)}const w=[...p.entries()].map(([o,i])=>({name:o,mentioned:i.size,total:h,pct:Y(i.size,h)})).sort((o,i)=>i.mentioned-o.mentioned||o.name.localeCompare(i.name));return{promptsWon:u,promptsTotal:h,sharePct:Y(u,h),perEngine:a,competitors:w,lostPrompts:m,checksTotal:t.length}}const dt={perplexity:"Perplexity",chatgpt:"ChatGPT",google_ai:"Google AI",claude:"Claude"},F=t=>dt[t]??t,ut={comparison:"Comparison page",stats:"Stats / original data",faq:"FAQ page",best_x_for_y:"Best X for Y",answer_page:"Answer page"},mt=t=>ut[t]??"Answer page",pe={open:{label:"Losing",variant:"destructive"},brief_ready:{label:"Brief ready",variant:"secondary"},generating:{label:"Generating",variant:"secondary"},drafted:{label:"Drafted",variant:"secondary"},published:{label:"Published",variant:"outline"},won:{label:"Won",variant:"default"},dismissed:{label:"Dismissed",variant:"outline"}},ft=t=>pe[t]??pe.open,V=({gap:t,onOpenBrief:s,onDismiss:n,onReopen:r,busy:h=!1})=>{const u=ft(t.status),m=t.winners[0],c=t.status==="won",a=t.status==="dismissed";return e.jsxs("li",{className:`border rounded-md p-3 space-y-2 ${c?"border-emerald-500/50 bg-emerald-500/5":""} ${a?"opacity-60":""}`,children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"text-sm font-medium",children:["â",t.query,"â"]}),e.jsxs(W,{variant:c?"default":u.variant,className:"shrink-0",children:[c&&e.jsx(we,{className:"h-3 w-3 mr-1"}),u.label]})]}),e.jsx("div",{className:"text-sm text-muted-foreground",children:c?e.jsx("span",{className:"text-emerald-600 dark:text-emerald-400 font-medium",children:"You won this prompt â you're cited here now."}):m?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-destructive font-medium",children:m.name})," is winning this answer",t.winning_url&&e.jsxs(e.Fragment,{children:[" · ",e.jsxs("a",{href:t.winning_url,target:"_blank",rel:"noopener noreferrer",className:"underline break-all inline-flex items-center gap-1",children:["cited page ",e.jsx(Me,{className:"h-3 w-3"})]})]})]}):"No one owns this answer yet â first mover wins it."}),t.engines.length>0&&e.jsx("div",{className:"flex flex-wrap gap-1",children:t.engines.map(p=>e.jsx(W,{variant:"outline",className:"font-normal text-xs",children:F(p)},p))}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 pt-1",children:[(t.status==="open"||t.status==="brief_ready")&&e.jsxs(e.Fragment,{children:[e.jsxs(k,{size:"sm",onClick:()=>s(t),disabled:h,children:[e.jsx(be,{className:"h-4 w-4 mr-2"}),t.status==="brief_ready"?"Review the brief":"Generate the page that wins this"]}),e.jsxs(k,{variant:"ghost",size:"sm",onClick:()=>n(t),disabled:h,children:[e.jsx(_e,{className:"h-4 w-4 mr-1"})," Not relevant"]})]}),t.status==="generating"&&e.jsxs("span",{className:"text-sm text-muted-foreground inline-flex items-center",children:[e.jsx(se,{className:"h-4 w-4 mr-2 animate-spin"})," Writing the pageâ¦"]}),(t.status==="drafted"||t.status==="published")&&(t.article_id?e.jsx(k,{variant:"outline",size:"sm",asChild:!0,children:e.jsx(Q,{to:`/articles/${t.article_id}`,children:"Open the draft"})}):e.jsx("span",{className:"text-sm text-muted-foreground",children:"Draft ready"})),a&&e.jsxs(k,{variant:"ghost",size:"sm",onClick:()=>r(t),disabled:h,children:[e.jsx(He,{className:"h-4 w-4 mr-1"})," Bring back"]}),c&&t.article_id&&e.jsx(k,{variant:"outline",size:"sm",asChild:!0,children:e.jsx(Q,{to:`/articles/${t.article_id}`,children:"See the page that won it"})})]})]})},ht=300,xt=4e3,pt="6f1d5b02-9c1e-4a63-b0f4-2d7a8c5e41aa",gt=["open","brief_ready","generating","drafted","published"],Ne=t=>{if(typeof t!="string")return null;try{const s=new URL(t);return s.protocol==="http:"||s.protocol==="https:"?t:null}catch{return null}},yt=t=>Array.isArray(t)?t.filter(s=>!!s&&typeof s=="object").map(s=>({name:typeof s.name=="string"?s.name:"",mentions:typeof s.mentions=="number"?s.mentions:void 0,cited_url:Ne(s.cited_url)})).filter(s=>s.name.length>0):[],ve=t=>{if(!t||typeof t!="object")return null;const s=t,n=h=>Array.isArray(h)?h.filter(u=>typeof u=="string"):[],r=h=>typeof h=="string"?h:"";return r(s.title)?{page_type:r(s.page_type)||"answer_page",title:r(s.title),angle:r(s.angle),outline:n(s.outline),entities:n(s.entities),answer_block:r(s.answer_block),h2s:n(s.h2s)}:null},jt=t=>({id:String(t.id),panel_id:String(t.panel_id),prompt_id:String(t.prompt_id),query:String(t.query??""),winners:yt(t.winners
16),winning_url:Ne(t.winning_url),engines:Array.isArray(t.engines)?t.engines.filter(s=>typeof s=="string"):[],status:t.status??"open",brief:ve(t.brief),job_id:typeof t.job_id=="string"?t.job_id:null,article_id:typeof t.article_id=="string"?t.article_id:null,first_seen_at:String(t.first_seen_at??""),last_seen_at:String(t.last_seen_at??""),won_at:typeof t.won_at=="string"?t.won_at:null}),bt=(t,s)=>ne(`${t}:${s??""}`,pt),wt=async t=>{const{data:s,error:n}=await L.functions.invoke("radar-gaps-sync",{body:{scan_batch_id:t}});if(n)throw n;return s},Nt=async t=>{const{data:s,error:n}=await L.from("citation_gaps").select("*").eq("panel_id",t).order("last_seen_at",{ascending:!1});if(n)throw n;return(s??[]).map(jt)},ge=async(t,s=!1)=>{const{data:n,error:r}=await L.functions.invoke("radar-brief",{body:{gap_id:t,regenerate:s}});if(r)throw r;const h=ve(n==null?void 0:n.brief);if(!h)throw new Error("The brief came back incomplete. Try again.");return h},re=async(t,s)=>{const{error:n}=await L.from("citation_gaps").update(s).eq("id",t);if(n)throw n},vt=t=>re(t,{status:"dismissed"}),_t=t=>re(t,{status:"open"}),St=async t=>{const s=t.filter(a=>a.status==="generating"&&a.job_id);if(s.length===0)return t;const{data:n,error:r}=await L.from("content_jobs").select("id, status, article_id").in("id",s.map(a=>a.job_id));if(r||!n)return t;const h=new Map(n.map(a=>[a.id,a])),u=new Map,m=new Set,c=new Set(["failed","canceled"]);return await Promise.all(s.map(async a=>{const p=h.get(a.job_id);if(!p)return;const v=p.status==="completed"&&typeof p.article_id=="string";if(c.has(p.status)||p.status==="completed"&&typeof p.article_id!="string"){const o=a.brief?"brief_ready":"open";try{const{data:i,error:d}=await L.from("citation_gaps").update({status:o}).eq("id",a.id).eq("status","generating").select("id");if(d)throw d;i&&i.length>0&&m.add(a.id)}catch{}return}if(v)try{const{data:o,error:i}=await L.from("citation_gaps").update({article_id:p.article_id,status:"drafted"}).eq("id",a.id).eq("status","generating").select("id");if(i)throw i;if(!o||o.length===0)return;u.set(a.id,p.article_id)}catch{}})),u.size===0&&m.size===0?t:t.map(a=>u.has(a.id)?{...a,status:"drafted",article_id:u.get(a.id)??null}:m.has(a.id)?{...a,status:a.brief?"brief_ready":"open"}:a)},Ct=(t,s="- ")=>t.map(n=>`${s}${n}`).join(` 17`),q={query:300,angle:350,answerBlock:350,h2:110,h2Count:8,outline:120,outlineCount:9,entity:55,entityCount:8},Z=(t,s,n)=>t.slice(0,s).map(r=>r.slice(0,n)),kt=(t,s)=>{const n=Z(t.h2s,q.h2Count,q.h2),r=Z(t.outline,q.outlineCount,q.outline),h=Z(t.entities,q.entityCount,q.entity),u=[`Write a ${t.page_type.replace(/_/g," ")} page that directly answers this buying-intent question: "${s.slice(0,q.query)}".`];return t.angle&&u.push(`ANGLE 18${t.angle.slice(0,q.angle)}`),t.answer_block&&u.push(`OPENING ANSWER BLOCK 19Open with a direct, quotable answer of at most 60 words, along these lines: 20${t.answer_block.slice(0,q.answerBlock)}`),n.length>0&&u.push(`REQUIRED H2 HEADINGS (keep them in question form) 21${Ct(n)}`),r.length>0&&u.push(`SECTION OUTLINE (in order) 22${r.map((m,c)=>`${c+1}. ${m}`).join(` 23`)}`),h.length>0&&u.push(`MENTION THESE ENTITIES/TERMS 24${h.join(", ")}`),u.join(` 25 26`).slice(0,xt)},Et=async(t,s)=>{var m;if(!t.brief)throw new Error("Build the brief before generating.");const n=(s??t.brief.title).trim().slice(0,ht);if(!n)throw new Error("The page needs a title.");const r={title:n,summary:kt(t.brief,t.query)},h=await qe([r],bt(t.id,t.job_id)),u=((m=h.job_ids)==null?void 0:m[0])??null;if(!u)return console.error("Gap generation returned no job id;
26 leaving gap recoverable."),{batchId:h.batch_id,jobId:null};try{await re(t.id,{job_id:u,status:"generating"})}catch(c){console.error("Gap generation started but the gap could not be updated:",c instanceof Error?c.message:String(c))}return{batchId:h.batch_id,jobId:u}},ee=new Map(gt.map((t,s)=>[t,s])),It=({gaps:t,isLoading:s,isError:n=!1,onRetry:r,onOpenBrief:h,onDismiss:u,onReopen:m,busyGapIds:c})=>{const[a,p]=b.useState(!1),{active:v,won:w,dismissed:o}=b.useMemo(()=>({active:t.filter(d=>ee.has(d.status)).sort((d,N)=>(ee.get(d.status)??0)-(ee.get(N.status)??0)),won:t.filter(d=>d.status==="won"),dismissed:t.filter(d=>d.status==="dismissed")}),[t]);return s?e.jsxs(R,{children:[e.jsx(B,{children:e.jsx(P,{className:"text-base",children:"Prompts you're losing"})}),e.jsxs(T,{className:"space-y-3",children:[e.jsx(G,{className:"h-20 w-full"}),e.jsx(G,{className:"h-20 w-full"})]})]}):n?e.jsx(R,{className:"border-destructive/50",children:e.jsxs(T,{className:"pt-6 text-center space-y-4",children:[e.jsx("p",{className:"text-sm text-destructive",children:"Could not load your citation gaps."}),r&&e.jsx(k,{variant:"outline",onClick:r,children:"Try again"})]})}):t.length===0?null:e.jsxs("div",{className:"space-y-6",children:[v.length>0&&e.jsxs(R,{children:[e.jsx(B,{children:e.jsxs(P,{className:"text-base",children:["Prompts you're losing (",v.length,")"]})}),e.jsx(T,{children:e.jsx("ul",{className:"space-y-3",children:v.map(i=>e.jsx(V,{gap:i,onOpenBrief:h,onDismiss:u,onReopen:m,busy:c==null?void 0:c.has(i.id)},i.id))})})]}),w.length>0&&e.jsxs(R,{children:[e.jsx(B,{children:e.jsxs(P,{className:"text-base",children:["Prompts you've won (",w.length,")"]})}),e.jsx(T,{children:e.jsx("ul",{className:"space-y-3",children:w.map(i=>e.jsx(V,{gap:i,onOpenBrief:h,onDismiss:u,onReopen:m},i.id))})})]}),o.length>0&&e.jsxs("div",{children:[e.jsxs(k,{variant:"ghost",size:"sm",onClick:()=>p(i=>!i),children:[a?"Hide":"Show"," dismissed (",o.length,")"]}),a&&e.jsx("ul",{className:"space-y-3 mt-3",children:o.map(i=>e.jsx(V,{gap:i,onOpenBrief:h,onDismiss:u,onReopen:m,busy:c==null?void 0:c.has(i.id)},i.id))})]})]})},At=({gap:t,open:s,onOpenChange:n,onGenerating:r,onBriefUpdated:h})=>{const{toast:u}=ye(),[m,c]=b.useState(null),[a,p]=b.useState(""),[v,w]=b.useState(!1),o=b.useRef(null),[i,d]=b.useState(()=>new Set),[N,_]=b.useState(null);b.useEffect(()=>{o.current=s?(t==null?void 0:t.id)??null:null},[s,t]),b.useEffect(()=>{if(!s||!t){w(!1);return}if(_(null),t.brief){c(t.brief),p(t.brief.title),w(!1);return}c(null),w(!0);let l=!1;return ge(t.id).then(x=>{h==null||h(x,t.id),!l&&(c(x),p(x.title))}).catch(x=>{l||_(x instanceof Error?x.message:"Could not build the brief. Try again.")}).finally(()=>{l||w(!1)}),()=>{l=!0}},[s,t]);const C=async()=>{if(!t)return;const l=t.id,x=()=>o.current===l;w(!0),_(null);try{const y=await ge(l,!0);if(h==null||h(y,l),!x())return;c(y),p(y.title)}catch(y){if(!x())return;_(y instanceof Error?y.message:"Could not rebuild the brief.")}finally{x()&&w(!1)}},E=async()=>{if(!t||!m)return;const l=t.id,x=()=>o.current===l;d(y=>new Set(y).add(l));try{await Et({...t,brief:m},a),u({title:"Generating the page",description:"You'll find it in Articles when it's done."}),r(),x()&&n(!1)}catch(y){y instanceof $e?u({variant:"destructive",title:"Out of credits",description:"Upgrade your plan to generate this page."}):u({variant:"destructive",title:"Could not start generation",description:y instanceof Error?y.message:"Please try again."})}finally{d(y=>{if(!y.has(l))return y;const I=new Set(y);return I.delete(l),I})}},g=!!t&&i.has(t.id),f=!!m&&a.trim().length>0&&!v&&!g;return e.jsx(Pe,{open:s,onOpenChange:n,children:e.jsxs(De,{className:"max-w-2xl max-h-[85vh] overflow-y-auto",children:[e.jsxs(Oe,{children:[e.jsx(Ue,{children:"Win this answer"}),e.jsx(We,{children:t?e.jsxs(e.Fragment,{children:["The page to publish for â",t.query,"â."]}):null})]}),v&&e.jsxs("div",{className:"space-y-3 py-2",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Reading the page the engines cited and reverse-engineering a briefâ¦"}),e.jsx(G,{className:"h-8 w-2/3"}),e.jsx(G,{className:"h-24 w-full"}),e.jsx(G,{className:"h-24 w-full"})]}),!v&&N&&e.jsxs("div",{className:"space-y-3 py-2",children:[e.jsx("p",{className:"text-sm text-destructive",children:N}),e.jsxs(k,{variant:"outline",size:"sm",onClick:()=>void C(),children:[e.jsx(U,{className:"h-4 w-4 mr-2"})," Try again"]})]}),!v&&!N&&m&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(W,{variant:"secondary",children:mt(m.page_type)}),(t==null?void 0:t.winners[0])&&e.jsxs("span",{className:"text-xs text-muted-foreground",children:["beating ",t.winners[0].name]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(Be,{htmlFor:"gap-brief-title",children:"Title"}),e.jsx(Ge,{id:"gap-brief-title",value:a,onChange:l=>p(l.target.value),maxLength:300})]}),m.angle&&e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium",children:"Angle"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:m.angle})]}),m.answer_block&&e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium",children:"Opening answer block"}),e.jsx("p",{className:"text-sm text-muted-foreground border-l-2 pl-3",children:m.answer_block})]}),m.h2s.length>0&&e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium",children:"Questions it answers"}),e.jsx("ul",{className:"text-sm text-muted-foreground list-disc pl-5 space-y-0.5",children:m.h2s.map((l,x)=>e.jsx("li",{children:l},`${x}-${l}`))})]}),m.outline.length>0&&e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium",children:"Outline"}),e.jsx("ol",{className:"text-sm text-muted-foreground list-decimal pl-5 space-y-0.5",children:m.outline.map((l,x)=>e.jsx("li",{children:l},`${x}-${l}`))})]}),m.entities.length>0&&e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium",children:"Must mention"}),e.jsx("div",{className:"flex flex-wrap gap-1",children:m.entities.map((l,x)=>e.jsx(W,{variant:"outline",className:"font-normal",children:l},`${x}-${l}`))})]})]}),e.jsxs(Fe,{className:"gap-2 sm:gap-2",children:[m&&!v&&e.jsxs(k,{variant:"ghost",size:"sm",onClick:()=>void C(),disabled:g,children:[e.jsx(U,{className:"h-4 w-4 mr-2"})," Rebuild brief"]}),e.jsx(k,{onClick:()=>void E(),disabled:!f,children:g?e.jsxs(e.Fragment,{children:[e.jsx(se,{className:"h-4 w-4 mr-2 animate-spin"})," Startingâ¦"]}):e.jsxs(e.Fragment,{children:[e.jsx(be,{className:"h-4 w-4 mr-2"})," Generate this page"]})})]})]})})},Rt=({runs:t})=>e.jsx("div",{className:"space-y-3",children:t.map(s=>{const n=s.prompts_total>0?Math.round(s.prompts_checked/s.prompts_total*100):0;return e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between text-sm mb-1",children:[e.jsx("span",{className:"font-medium",children:F(s.engine)}),e.jsx("span",{className:"text-muted-foreground",children:s.status==="failed"?"failed":`${s.prompts_checked}/${s.prompts_total}`})]}),e.jsx(z,{value:s.status==="completed"?100:n})]},s.engine)})}
26),Tt=({soa:t,brandName:s,runs:n,onRescan:r,isRescanning:h})=>{const u=t.competitors[0],m=n.filter(c=>c.status!=="completed");return e.jsxs("div",{className:"space-y-6",children:[m.length>0&&e.jsx(R,{className:"border-amber-400/60",children:e.jsxs(T,{className:"pt-4 pb-4 text-sm text-muted-foreground",children:["Partial scan: ",m.map(c=>F(c.engine)).join(", ")," ","didn't finish, so these numbers may undercount."]})}),e.jsx(R,{children:e.jsxs(T,{className:"pt-6 text-center space-y-2",children:[e.jsxs("div",{className:"text-5xl font-bold",children:[t.promptsWon,e.jsxs("span",{className:"text-2xl text-muted-foreground font-normal",children:[" ","of ",t.promptsTotal]})]}),e.jsxs("p",{className:"text-muted-foreground",children:["buying-intent prompts where at least one AI answer mentions"," ",e.jsx("span",{className:"font-medium",children:s}),u&&u.mentioned>t.promptsWon&&e.jsxs(e.Fragment,{children:[" â ",e.jsxs("span",{className:"text-destructive font-medium",children:[u.name," appears in ",u.mentioned]})]})]}),e.jsx("div",{className:"pt-2",children:e.jsxs(k,{variant:"outline",size:"sm",onClick:r,disabled:h,children:[e.jsx(U,{className:"h-4 w-4 mr-2"})," Scan again"]})})]})}),e.jsxs("div",{className:"grid md:grid-cols-2 gap-6",children:[e.jsxs(R,{children:[e.jsx(B,{children:e.jsx(P,{className:"text-base",children:"By engine"})}),e.jsx(T,{className:"space-y-3",children:t.perEngine.map(c=>e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between text-sm mb-1",children:[e.jsx("span",{children:F(c.engine)}),e.jsxs("span",{className:"text-muted-foreground",children:[c.cited,"/",c.total]})]}),e.jsx(z,{value:c.pct})]},c.engine))})]}),e.jsxs(R,{children:[e.jsx(B,{children:e.jsx(P,{className:"text-base",children:"Share of answer"})}),e.jsxs(T,{className:"space-y-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between text-sm mb-1",children:[e.jsxs("span",{className:"font-medium",children:[s," (you)"]}),e.jsxs("span",{className:"text-muted-foreground",children:[t.sharePct,"%"]})]}),e.jsx(z,{value:t.sharePct})]}),t.competitors.slice(0,5).map(c=>e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between text-sm mb-1",children:[e.jsx("span",{children:c.name}),e.jsxs("span",{className:"text-muted-foreground",children:[c.pct,"%"]})]}),e.jsx(z,{value:c.pct,className:"[&>div]:bg-destructive/60"})]},c.name)),t.competitors.length===0&&e.jsx("p",{className:"text-sm text-muted-foreground",children:"No competitor appeared in these answers."})]})]})]})]})},Wt=()=>{var ie,ce,le;const t=Se(),s=Ce(),{toast:n}=ye(),r=ot(),h=b.useRef(!1),[u,m]=b.useState(null),[c,a]=b.useState(!1),p=ke(),v=J({queryKey:["radar-panels"],queryFn:Te}),w=b.useMemo(()=>v.data??[],[v.data]),o=u??((ie=w[0])==null?void 0:ie.id)??null,i=w.find(j=>j.id===o);b.useEffect(()=>{var O;if(h.current)return;h.current=!0;const j=(O=t.state)==null?void 0:O.startPanelId;if(j){m(j),s(t.pathname,{replace:!0,state:null}),r.start(j);return}de().then(A=>{A&&(m(A.panelId),r.adopt(A.panelId,A.scanBatchId))}).catch(()=>{})},[]);const d=(r.isScanning||r.isComplete)&&r.panelId!==null&&r.panelId===o,N=J({queryKey:["radar-latest",i==null?void 0:i.id],enabled:!!i&&!d,queryFn:async()=>{const j=await Re(i.id);return j?{batchId:j,...await je(j)}:null}}),_=b.useMemo(()=>d&&r.isComplete?xe(r.checks,r.mentions):!d&&N.data?xe(N.data.checks,N.data.mentions):null,[d,r.isComplete,r.checks,r.mentions,N.data]),C=d?r.runs:((ce=N.data)==null?void 0:ce.runs)??[],E=(i==null?void 0:i.brand_name)||(i==null?void 0:i.domain)||"your brand",g=async()=>{if(!(!o||c||r.isScanning)){a(!0);try{const j=await de().catch(()=>null);if(j){j.panelId===o?r.adopt(j.panelId,j.scanBatchId):n({title:"A scan is already running",description:"Wait for it to finish before starting a new one."});return}r.start(o)}finally{a(!1)}}},f=d&&r.isComplete?r.batchId:((le=N.data)==null?void 0:le.batchId)??null,l=J({queryKey:["radar-gaps",o],enabled:!!o,queryFn:async()=>St(await Nt(o))}),[x,y]=b.useState(null),[I,S]=b.useState(()=>new Set),M=b.useRef(new Set);b.useEffect(()=>{!f||M.current.has(f)||(M.current.add(f),wt(f).then(()=>l.refetch()).catch(()=>{M.current.delete(f),n({variant:"destructive",title:"Could not refresh your citation gaps",description:"Showing the last known result. Rescan to try again."})}))},[f]);const ae=async(j,O)=>{S(A=>
26new Set(A).add(j.id));try{await O(),await l.refetch()}catch{n({variant:"destructive",title:"Could not update that prompt",description:"Please try again."})}finally{S(A=>{if(!A.has(j.id))return A;const $=new Set(A);return $.delete(j.id),$})}};return v.isLoading?e.jsxs("div",{className:"max-w-4xl mx-auto space-y-4",children:[e.jsx(G,{className:"h-10 w-64"}),e.jsx(G,{className:"h-40 w-full"}),e.jsx(G,{className:"h-64 w-full"})]}):v.isError&&!r.isScanning&&!r.isComplete?e.jsxs("div",{className:"max-w-2xl mx-auto text-center space-y-4 pt-16",children:[e.jsx("p",{className:"text-muted-foreground",children:"Could not load your visibility panels. Check your connection and try again."}),e.jsxs(k,{variant:"outline",onClick:()=>void v.refetch(),children:[e.jsx(U,{className:"h-4 w-4 mr-2"})," Try again"]})]}):w.length===0&&!r.isScanning&&!r.isComplete?e.jsxs("div",{className:"max-w-2xl mx-auto text-center space-y-6 pt-16",children:[e.jsx(oe,{className:"h-16 w-16 mx-auto text-muted-foreground"}),e.jsx("h1",{className:"text-3xl font-bold",children:"Are you visible to AI?"}),e.jsx("p",{className:"text-muted-foreground",children:"When buyers ask ChatGPT or Perplexity for recommendations in your category, do you show up â or do your competitors? Run a scan to find out."}),e.jsx(k,{asChild:!0,size:"lg",children:e.jsx(Q,{to:"/radar/new",children:"Run your first scan"})})]}):e.jsxs("div",{className:"max-w-4xl mx-auto space-y-6 pb-16",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-3xl font-bold flex items-center gap-2",children:[e.jsx(oe,{className:"h-7 w-7"})," AI Visibility"]}),i&&e.jsx("p",{className:"text-muted-foreground text-sm mt-1",children:i.domain})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[w.length>1&&e.jsx("select",{className:"border rounded-md px-2 py-1.5 text-sm bg-background",value:(i==null?void 0:i.id)??"",onChange:j=>m(j.target.value),disabled:r.isScanning,children:w.map(j=>e.jsx("option",{value:j.id,children:j.domain},j.id))}),r.isScanning?e.jsx(k,{variant:"outline",disabled:!0,children:"New scan"}):e.jsx(k,{variant:"outline",asChild:!0,children:e.jsx(Q,{to:"/radar/new",children:"New scan"})})]})]}),r.error&&e.jsx(R,{className:"border-destructive/50",children:e.jsxs(T,{className:"pt-6 flex items-center justify-between gap-4",children:[e.jsx("span",{className:"text-sm text-destructive",children:r.error}),r.panelId&&r.batchId&&e.jsxs(k,{variant:"outline",size:"sm",onClick:()=>void r.adopt(r.panelId,r.batchId),children:[e.jsx(U,{className:"h-4 w-4 mr-2"})," Resume scan"]})]})}),d&&r.isScanning&&e.jsxs(e.Fragment,{children:[e.jsxs(R,{children:[e.jsx(B,{children:e.jsxs(P,{className:"text-base flex items-center gap-2",children:[e.jsx(se,{className:"h-4 w-4 animate-spin"}),"Asking ",r.runs.length," engines your buyers' questionsâ¦"]})}),e.jsx(T,{children:e.jsx(Rt,{runs:r.runs})})]}),e.jsxs(R,{children:[e.jsx(B,{children:e.jsxs(P,{className:"text-base",children:["Live answers (",r.checks.length,")"]})}),e.jsx(T,{children:e.jsxs("ul",{className:"space-y-2 max-h-80 overflow-y-auto pr-2",children:[[...r.checks].reverse().map(j=>e.jsxs("li",{className:"flex items-center justify-between gap-3 text-sm border rounded-md px-3 py-2",children:[e.jsxs("span",{className:"truncate",children:["â",j.query,"â"]}),e.jsxs("span",{className:"flex items-center gap-2 shrink-0",children:[e.jsx(W,{variant:"outline",children:F(j.engine)}),j.brand_cited?e.jsx(we,{className:"h-4 w-4 text-green-600"}):e.jsx(ze,{className:"h-4 w-4 text-destructive"})]})]},j.id)),r.checks.length===0&&e.jsx("li",{className:"text-sm text-muted-foreground animate-pulse",children:"Waiting for the first answersâ¦"})]})})]})]}),!r.isScanning&&_&&e.jsx(Tt,{soa:_,brandName:E,runs:C,onRescan:()=>void g(),isRescanning:r.isScanning||c}),!r.isScanning&&_&&e.jsx(It,{gaps:l.data??[],isLoading:l.isLoading,isError:l.isError,onRetry:()=>void l.refetch(),onOpenBrief:y,onDismiss:j=>void ae(j,()=>vt(j.id)),onReopen:j=>void ae(j,()=>_t(j.id)),busyGapIds:I}),e.jsx(At,{gap:x,open:!!x,onOpenChange:j=>{j||y(null)},onGenerating:()=>void l.refetch(),onBriefUpdated:(j,O)=>{p.setQueryData(["radar-gaps",o],A=>A==null?void 0:A.map($=>
26$.id===O?{...$,brief:j,status:$.status==="open"?"brief_ready":$.status}:$)),l.refetch()}}),!r.isScanning&&!_&&i&&N.isError&&e.jsx(R,{className:"border-destructive/50",children:e.jsxs(T,{className:"pt-6 text-center space-y-4",children:[e.jsxs("p",{className:"text-sm text-destructive",children:["Could not load the latest scan results for ",i.domain,"."]}),e.jsxs(k,{variant:"outline",onClick:()=>void N.refetch(),children:[e.jsx(U,{className:"h-4 w-4 mr-2"})," Try again"]})]})}),!r.isScanning&&!_&&i&&!N.isLoading&&!N.isError&&e.jsx(R,{children:e.jsxs(T,{className:"pt-6 text-center space-y-4",children:[e.jsxs("p",{className:"text-muted-foreground",children:["No scan results yet for ",i.domain,"."]}),e.jsx(k,{onClick:()=>void g(),disabled:c,children:"Run a scan now"})]})})]})};export{Wt 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.