PageSourceSearch

https://jasno.ai/assets/RedditCitations-DUf82x5E.js

js jasno.ai collected 2026-10-05 12:32:26 UTC 19,155 bytes, 1 lines download raw bytes

1import{r as d,ab as R,j as e,h as U,U as E,y as B,aj as G,S as K}from"./index-BccoXoiL.js";import{a as Y,u as W}from"./useInView-CX0gQOW-.js";import{C as A}from"./CompetitorAvatar-DChqc7m1.js";import{N as X}from"./NoProjectEmptyState-BzMQ4b1x.js";import{y as q}from"./chartAxis-Tr1qmLAx.js";import{b as V,G as J}from"./chartBuckets-CGMgKx6_.js";import{M as S}from"./message-square-jYPr0qyy.js";import{R as I}from"./refresh-cw-pzCQewnq.js";import{C as P}from"./circle-check-big-x6zsLcw3.js";import{R as H,X as Q,Y as Z,T as ee}from"./generateCategoricalChart-VDSrz2_-.js";import{L as te,a as _}from"./LineChart-Cb8ZvRr-.js";import{E as se}from"./external-link-C5CI4Mn_.js";import{C as re}from"./chevron-up-BI80mSco.js";import{A as ae}from"./arrow-up-BTcrWkAI.js";import{C as ne}from"./circle-x-B54KUTz9.js";import{f as de}from"./format-3gWReUe6.js";import"./card-BT2jnzK3.js";import"./plus-DN7iXqTE.js";import"./en-US-DPHc_Go0.js";const oe={SerpAPI:"Google AI Overview"},L=a=>oe[a]??a,ie={Perplexity:"bg-teal-100 text-teal-800 dark:bg-teal-950 dark:text-teal-300",ChatGPT:"bg-green-100 text-green-800 dark:bg-green-950 dark:text-green-300","Google AI Overview":"bg-blue-100 text-blue-800 dark:bg-blue-950 dark:text-blue-300",Gemini:"bg-blue-100 text-blue-800 dark:bg-blue-950 dark:text-blue-300"};function le({model:a}){const x=L(a),c=ie[x]??"bg-muted text-muted-foreground";return e.jsx("span",{className:`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${c}`,children:x})}function ce({c:a,excludedSet:x}){const[c,u]=d.useState(!1),h=a.prompt_texts??[],n=(a.competitor_mentions??[]).filter(s=>!x?.has((s.name||"").toLowerCase())),o=h.length>0||n.length>0;return e.jsxs(e.Fragment,{children:[e.jsxs("tr",{className:"hover:bg-muted transition-colors cursor-pointer",onClick:()=>o&&u(s=>!s),children:[e.jsx("td",{className:"px-4 py-3",children:e.jsxs("div",{className:"flex items-start gap-2 min-w-0",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("a",{href:a.thread_url,target:"_blank",rel:"noopener noreferrer",onClick:s=>s.stopPropagation(),className:"font-medium text-foreground hover:text-brand-orange flex items-center gap-1 group",children:[e.jsx("span",{className:"line-clamp-2 leading-snug",children:a.thread_title||a.thread_url}),e.jsx(se,{size:11,className:"flex-shrink-0 text-muted-foreground group-hover:text-brand-orange"})]}),e.jsxs("div",{className:"flex items-center gap-2 mt-1 flex-wrap",children:[e.jsxs("span",{className:"text-xs text-brand-orange font-medium bg-brand-orange/10 border border-brand-orange/20 px-1.5 py-0.5 rounded",children:["r/",a.subreddit]}),e.jsx("div",{className:"flex gap-1 flex-wrap",children:(a.ai_models??[]).map(s=>e.jsx(le,{model:s},s))})]})]}),o&&e.jsx("button",{onClick:s=>{s.stopPropagation(),u(i=>!i)},className:"flex-shrink-0 text-muted-foreground hover:text-foreground mt-0.5",title:"Show prompts & competitors for this thread",children:c?e.jsx(re,{size:14}):e.jsx(G,{size:14})})]})}),e.jsx("td",{className:"px-4 py-3 text-right whitespace-nowrap",children:e.jsxs("div",{className:"inline-flex items-center gap-1 text-foreground",children:[e.jsx(ae,{size:12,className:"text-brand-orange"}),e.jsx("span",{className:"font-semibold text-sm tabular-nums",children:(a.upvotes??0).toLocaleString()})]})}),e.jsx("td",{className:"px-4 py-3",children:a.brand_mentioned?e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(P,{size:15,className:"text-green-600 flex-shrink-0"}),e.jsxs("span",{className:"text-xs font-semibold text-green-700 dark:text-green-400 bg-green-100 dark:bg-green-950 px-1.5 py-0.5 rounded",children:[a.brand_mention_count,"× mentioned"]})]}):e.jsxs("div",{className:"flex items-center gap-1 text-muted-foreground",children:[e.jsx(ne,{size:14}),e.jsx("span",{className:"text-xs",children:"absent"})]})}),e.jsx("td",{className:"px-4 py-3",children:n.length>0?e.jsxs("div",{className:"flex flex-wrap gap-1",children:[n.slice(0,3).map(s=>e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 bg-red-50 dark:bg-red-950/40 text-red-700 dark:text-red-400 border border-red-100 dark:border-red-900 rounded text-xs font-medium",children:[e.jsx(A,{name:s.name,size:14}),s.name," ",e.jsxs("span",{className:"opacity-60",children:["×",s.count]})]},s.name)),n.length>3&&e.jsxs("span",{className:"text-xs text-muted-foreground",children:["+",n.length-3," more"]})]}):e.jsx("span",{className:"text-xs text-muted-foreground",children:"—"})})]}),c&&(h.length>0||n.length>0)&&e.jsx("tr",{className:"bg-muted border-t border-border",children:e.jsxs("td",{colSpan:4,className:"px-4 py-3 space-y-3",children:[h.length>0&&e.jsxs("div",{children:[e.jsxs("p",{className:"text-xs font-semibold text-foreground mb-2 flex items-center gap-1.5",children:[e.jsx(K,{size:11,className:"text-brand-orange"}),"AI prompts that cited this thread"]}),e.jsx("div",{className:"flex flex-wrap gap-1.5",children:h.map((s,i)=>e.jsx("span",{className:"text-xs bg-background border border-border text-foreground px-2.5 py-1 rounded-full leading-snug",children:s},i))})]}),n.length>0&&e.jsxs("div",{children:[e.jsxs("p",{className:"text-xs font-semibold text-foreground mb-2 flex items-center gap-1.5",children:[e.jsx(E,{size:11,className:"text-muted-foreground"}),"Competitors mentioned in this thread"]}),e.jsx("div",{className:"flex flex-wrap gap-1.5",children:n.map(s=>e.jsxs("span",{className:"inline-flex items-center gap-1 text-xs bg-background border border-border text-foreground px-2.5 py-1 rounded-full leading-snug",children:[e.jsx(A,{name:s.name,size:14}),s.name," ",e.jsxs("span",{className:"text-muted-foreground",children:["×",s.count]})]},s.name))})]})]})})]})}function me({snapshots:a}){const[x,c]=W(),[u,h]=d.useState("day"),n=d.useMemo(()=>a.map(s=>{const i=s.snapshot_date||s.created_date;if(!i)return null;const f=new Date(i);return Number.isNaN(f.getTime())?null:{ts:f.getTime(),date:de(f,"MMM d, h:mmaaa"),threads:s.cited_thread_count??0,brandThreads:s.brand_thread_count??0,competitorMentions:s.competitor_mention_total??0}}
1).filter(Boolean).sort((s,i)=>s.ts-i.ts),[a]),o=d.useMemo(()=>V({points:n,timestampKey:"ts",dateKey:"date",numericKeys:["threads","brandThreads","competitorMentions"],granularity:u,mode:"sum"}),[n,u]);return n.length===0?null:e.jsxs("div",{className:"py-6 border-b border-border",children:[e.jsxs("div",{className:"flex items-center justify-between mb-0.5",children:[e.jsxs("h3",{className:"text-sm font-semibold text-foreground flex items-center gap-2",children:[e.jsx(B,{size:14,className:"text-brand-orange"}),"Reddit Exposure Over Time"]}),e.jsx(J,{value:u,onChange:h})]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5 mb-5",children:"Cited Reddit threads, threads mentioning your brand, and competitor mentions, recorded each scan."}),n.length<2?e.jsxs("div",{className:"h-44 flex flex-col items-center justify-center text-center gap-2",children:[e.jsx("div",{className:"text-sm font-medium text-foreground",children:"Just one data point so far"}),e.jsx("p",{className:"text-xs text-muted-foreground max-w-xs",children:"This timeline builds up as you run more scans — run another scan to see how your Reddit exposure changes over time."})]}):e.jsxs("div",{ref:x,className:"dot-grid rounded-lg",children:[e.jsx(H,{width:"100%",height:220,children:e.jsxs(te,{data:o,margin:{top:5,right:20,left:10,bottom:5},style:{background:"transparent"},children:[e.jsx(Q,{dataKey:"date",tick:{fontSize:11,fill:"hsl(var(--muted-foreground))"}}),e.jsx(Z,{tick:{fontSize:11,fill:"hsl(var(--muted-foreground))"},allowDecimals:!1,width:56,label:q("Count")}),e.jsx(ee,{contentStyle:{backgroundColor:"hsl(var(--card))",border:"1px solid hsl(var(--border))",borderRadius:"10px",fontSize:"12px",color:"hsl(var(--foreground))"}}),e.jsx(_,{type:"monotone",dataKey:"threads",name:"Cited threads",stroke:"#FF4D00",strokeWidth:2.5,dot:{r:3},activeDot:{r:5}}),e.jsx(_,{type:"monotone",dataKey:"brandThreads",name:"Brand appearances",stroke:"#10b981",strokeWidth:2,dot:{r:3},activeDot:{r:4}}),e.jsx(_,{type:"monotone",dataKey:"competitorMentions",name:"Competitor mentions",stroke:"#ef4444",strokeWidth:2,dot:{r:3},activeDot:{r:4},strokeDasharray:"5 5"})]},c)}),e.jsxs("div",{className:"flex items-center gap-4 mt-3 text-xs text-muted-foreground flex-wrap",children:[e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"w-2 h-2 rounded-full bg-brand-orange"})," Cited threads"]}),e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"w-2 h-2 rounded-full bg-green-500"})," Brand appearances"]}),e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"w-2 h-2 rounded-full bg-red-500"})," Competitor mentions"]})]})]})]})}function ze(){const[a,x]=d.useState([]),[c,u]=d.useState([]),[h,n]=d.useState(!0),[o,s]=d.useState(!1),[i,f]=d.useState(!1),[m,O]=d.useState(null),g=d.useRef(null);d.useEffect(()=>{const t=localStorage.getItem("activeProjectId");O(t),t||n(!1)},[]);const y=d.useCallback(async t=>{if(t)try{const r=await R(`/projects/${t}/reddit-snapshots`);if(!r.ok)throw new Error(await r.text());u(await r.json())}catch(r){console.error("[RedditCitations] snapshots load error:",r)}},[]),v=d.useCallback(async t=>{if(!t)return null;try{const r=await R(`/projects/${t}/reddit-citations`);if(!r.ok)throw new Error(await r.text());const l=await r.json();return x(l),l}catch(r){return console.error("[RedditCitations] load error:",r),null}finally{n(!1)}},[]);d.useEffect(()=>{m&&(f(!1),v(m),y(m))},[m,v,y]),d.useEffect(()=>()=>{g.current&&clearInterval(g.current)},[]);function D(t,r){let l=0;g.current=setInterval(async()=>{l++;const N=await v(t);(N!==null&&N.length>r||l>=12)&&(clearInterval(g.current),g.current=null,s(!1),f(!0),y(t))},5e3)}async function T(){if(!(!m||o)){s(!0);try{const t=await R(`/projects/${m}/reddit-citations/refresh`,{method:"POST"});if(!t.ok)throw new Error(await t.text());D(m,a.length)}catch(t){console.error("[RedditCitations] refresh error:",t),s(!1)}}}const p=a.length,M=[...new Set(a.flatMap(t=>t.ai_models??[]))],b=a.filter(t=>t.brand_mentioned).length,$=p?Math.round(b/p*100):0,{excludedSet:w}=Y(m),z=a.reduce((t,r)=>t+(r.competitor_mentions??[]).filter(l=>!w.has((l.name||"").toLowerCase())).reduce((l,N)=>l+N.count,0),0),F=a.reduce((t,r)=>(r.subreddit&&(t[r.subreddit]=(t[r.subreddit]??0)+1),t),{}),k=Object.entries(F).sort((t,r)=>r[1]-t[1]),C={};a.forEach(t=>
1{(t.competitor_mentions??[]).forEach(({name:r,count:l})=>{w.has((r||"").toLowerCase())||(C[r]=(C[r]??0)+l)})});const j=Object.entries(C).sort((t,r)=>r[1]-t[1]);return h?e.jsx("div",{className:"flex items-center justify-center py-20",children:e.jsx("div",{className:"w-5 h-5 border-2 border-border border-t-foreground rounded-full animate-spin"})}):m?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"border-b border-border px-6 py-3 flex items-center justify-between gap-4 flex-wrap",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx(S,{className:"w-4 h-4 text-muted-foreground flex-shrink-0"}),e.jsx("span",{className:"text-sm font-medium text-foreground",children:"Reddit Citations"}),e.jsx("span",{className:"hidden sm:inline text-xs text-muted-foreground truncate",children:"· Reddit threads cited by AI when answering your tracked prompts"})]}),e.jsxs("button",{onClick:T,disabled:o,className:"inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium bg-foreground text-background rounded hover:opacity-80 disabled:opacity-40 transition-opacity flex-shrink-0",children:[e.jsx(I,{size:12,className:o?"animate-spin":""}),o?"Scanning…":"Refresh"]})]}),e.jsxs("div",{className:"px-4 md:px-6",children:[o&&e.jsxs("div",{className:"mt-4 flex items-center gap-3 px-4 py-3 rounded-lg border border-border bg-muted text-sm",children:[e.jsx(U,{className:"w-4 h-4 animate-spin text-muted-foreground flex-shrink-0"}),e.jsx("span",{className:"text-foreground font-medium",children:"Scanning Reddit citations…"}),e.jsx("span",{className:"text-muted-foreground hidden sm:inline",children:"Results will appear here automatically."})]}),e.jsxs("div",{className:"-mx-4 md:-mx-6 grid grid-cols-2 md:grid-cols-4 border-b border-border bg-muted",children:[e.jsxs("div",{className:"px-5 py-4 border-r border-border",children:[e.jsx("div",{className:"text-xs text-muted-foreground mb-1",children:"Cited Threads"}),e.jsx("div",{className:"text-2xl font-semibold tabular-nums text-foreground",children:p}),e.jsx("div",{className:"text-xs text-muted-foreground mt-0.5",children:"from AI analysis runs"})]}),e.jsxs("div",{className:"px-5 py-4 border-r border-border",children:[e.jsx("div",{className:"text-xs text-muted-foreground mb-1",children:"Your Brand Appears"}),e.jsx("div",{className:`text-2xl font-semibold tabular-nums ${b>0?"text-green-600 dark:text-green-400":"text-muted-foreground"}`,children:b>0?`${$}%`:"0%"}),e.jsxs("div",{className:"text-xs text-muted-foreground mt-0.5",children:[b," of ",p," threads"]})]}),e.jsxs("div",{className:"px-5 py-4 border-r border-border",children:[e.jsx("div",{className:"text-xs text-muted-foreground mb-1",children:"AI Models"}),e.jsx("div",{className:"text-2xl font-semibold tabular-nums text-foreground",children:M.length||"—"}),e.jsx("div",{className:"text-xs text-muted-foreground mt-0.5 truncate",children:M.map(L).join(", ")||"run an analysis first"})]}),e.jsxs("div",{className:"px-5 py-4",children:[e.jsx("div",{className:"text-xs text-muted-foreground mb-1",children:"Competitor Mentions"}),e.jsx("div",{className:`text-2xl font-semibold tabular-nums ${z>0?"text-red-500":"text-muted-foreground"}`,children:z||"—"}),e.jsx("div",{className:"text-xs text-muted-foreground mt-0.5",children:"across all threads"})]})]}),c.length>0&&e.jsx(me,{snapshots:c}),a.length===0?e.jsxs("div",{className:"py-16 flex flex-col items-center justify-center text-center",children:[e.jsx(S,{size:36,className:"text-muted-foreground mb-4"}),i?e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-base font-semibold text-foreground",children:"No Reddit citations found yet"}),e.jsx("p",{className:"text-sm text-muted-foreground mt-2 max-w-md",children:"We checked your latest AI analysis and didn't find any cited Reddit threads. If you just started a scan it may still be finishing — give it a moment and hit Scan Again. Otherwise this simply means the AI models didn't reference Reddit when answering your tracked prompts. Make sure your analyses run with Perplexity enabled to surface Reddit citations."})]}):e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-base font-semibold text-foreground",children:"No Reddit citations yet"}),e.jsx("p",{className:"text-sm text-muted-foreground mt-2 max-w-sm",children:"Run an analysis with Perplexity enabled, then click Refresh to check for Reddit threads cited in AI responses."})]}),e.jsxs("button",{onClick:T,disabled:o,className:"mt-5 inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-foreground text-background rounded hover:opacity-80 disabled:opacity-40 transition-opacity",children:[e.jsx(I,{size:13,className:o?"animate-spin":""}),i?"Scan Again":"Scan Now"]})]}):e.jsxs(e.Fragment,{children:[(k.length>0||j.length>0)&&e.jsxs("div",{className:"py-6 border-b border-border grid grid-cols-1 md:grid-cols-2 gap-8",children:[k.length>0&&e.jsxs("div",{children:[e.jsxs("h3",{className:"text-sm font-semibold text-foreground mb-3 flex items-center gap-2",children:[e.jsx(S,{size:13,className:"text-brand-orange"}),"Top Subreddits"]}),e.jsx("div",{className:"space-y-2 max-h-72 overflow-y-auto pr-1",children:k.map(([t,r])=>e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("a",{href:`https://www.reddit.com/r/${t}`,target:"_blank",rel:"noopener noreferrer",className:"text-xs font-medium text-brand-orange bg-brand-orange/10 border border-brand-orange/20 hover:bg-brand-orange/15 hover:underline px-2 py-0.5 rounded w-36 truncate flex-shrink-0",title:`Open r/${t} on reddit.com`,children:["r/",t]}),e.jsx("div",{className:"flex-1 bg-muted rounded-full h-1.5 overflow-hidden",children:e.jsx("div",{className:"bg-brand-orange h-1.5 rounded-full transition-all",style:{width:`${Math.round(r/p*100)}%`}})}),e.jsx("span",{className:"text-xs text-muted-foreground w-5 text-right flex-shrink-0 tabular-nums",children:r})]},t))})]}),j.length>0?e.jsxs("div",{children:[e.jsxs("h3",{className:"text-sm font-semibold text-foreground mb-3 flex items-center gap-2",children:[e.jsx(E,{size:13,className:"text-muted-foreground"}),"Competitor Exposure in Citations"]}),e.jsx("div",{className:"space-y-2 max-h-72 overflow-y-auto pr-1",children:j.map(([t,r])=>e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-xs font-medium text-foreground px-2 py-0.5 border border-border rounded w-36 flex-shrink-0 truncate",children:[e.jsx(A,{name:t,size:14}),e.jsx("span",{className:"truncate",children:t})]}),e.jsx("div",{className:"flex-1 bg-muted rounded-full h-1.5 overflow-hidden",children:e.jsx("div",{className:"bg-zinc-500 h-1.5 rounded-full transition-all",style:{width:`${Math.round(r/(j[0]?.[1]??1)*100)}%`}})}),e.jsx("span",{className:"text-xs text-muted-foreground w-5 text-right flex-shrink-0 tabular-nums",children:r})]},t))})]}):e.jsx("div",{className:"flex items-center justify-center py-8",children:e.jsxs("div",{className:"text-center",children:[e.jsx(P,{size:24,className:"mx-auto text-green-500 mb-2"}),e.jsx("p",{className:"text-sm font-medium text-foreground",children:"No competitor mentions"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:"Competitors don't appear in these Reddit threads"})]})})]}),e.jsxs("div",{className:"py-6",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsxs("h3",{className:"text-sm font-semibold text-foreground",children:["All Cited Threads",e.jsx("span",{className:"ml-2 text-xs font-normal text-muted-foreground",children:"· click a row to see which prompts triggered it"})]}),e.jsxs("span",{className:"text-xs text-muted-foreground tabular-nums",children:[p," thread",p!==1?"s":""]})]}),e.jsx("div",{className:"overflow-x-auto rounded-lg border border-border",children:e.jsxs("table",{className:"w-full min-w-[640px] text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-border bg-muted text-left",children:[e.jsx("th",{className:"px-4 py-2.5 text-xs font-medium text-muted-foreground",children:"Thread"}),e.jsx("th",{className:"px-4 py-2.5 text-xs font-medium text-muted-foreground text-right",children:"Upvotes"}),e.jsx("th",{className:"px-4 py-2.5 text-xs font-medium text-muted-foreground",children:"Your Brand"}),e.jsx("th",{className:"px-4 py-2.5 text-xs font-medium text-muted-foreground",children:"Competitors"})]})}),e.jsx("tbody",{className:"divide-y divide-border",children:a.map(t=>e.jsx(ce,{c:t,excludedSet:w},t.id))})]})}),e.jsx("p",{className:"text-xs text-muted-foreground mt-3 text-center",children:"Threads extracted from AI citation URLs in your analysis runs · Click Refresh to re-scan the latest run"})]})]})]})]}):e.jsx(X,{})}export{ze 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.