PageSourceSearch

https://popify.world/assets/AdminDiscovery-Ddcb70FQ.js

js popify.world collected 2026-09-24 15:15:22 UTC 28,384 bytes, 3 lines download raw bytes

1import{j as e,q as V,a3 as Y,s as _,B as k,ag as je,ai as ve,aj as re,ak as ie,a4 as C,u as ye,a0 as Ne}from"./index-B8sBaXQd.js";import{r as d}from"./vendor-recharts-PDzeV0Q9.js";import{A as J}from"./AdminShell-Daupe0PS.js";import{S as ee}from"./SEO-Eo8PLAwa.js";import{B as H}from"./badge-CIMDk1D_.js";import{C as F,b as $,c as z,a as B}from"./card-Cw1kiO5Q.js";import{L as q}from"./label-dG8NhYMg.js";import{R as Ce,a as _e}from"./radio-group-Ckij2C-2.js";import{T as Se,a as ke,b as se,c as E,d as Re,e as T}from"./table-BlDHuMyk.js";import{T as we,a as De,b as Ee}from"./tabs-DU0jjdov.js";import{C as te}from"./clock-C0bEwGpw.js";import{B as Te}from"./ban-CVPB6iRr.js";import{C as Le}from"./circle-x-BP95mhhd.js";import{C as qe}from"./circle-check-D5PqN2mn.js";import{L as A}from"./loader-circle-DttseWp6.js";import{u as K}from"./useMutation-DNbLMEyj.js";import{I as ne}from"./input-CdVRlp_C.js";import{S as Ae,a as Ie,b as Me,c as Pe,d as Ue}from"./select-f6afgOXu.js";import{f as oe}from"./validations-BzFPckrD.js";import{G as Oe}from"./shield-BYC-J9mv.js";import{A as Fe,h as $e,a as ze,b as Be,c as Ge,d as Qe,e as Ve,f as Ye,g as He}from"./alert-dialog-CTQqVVAf.js";import{C as Ke,a as We,b as Xe}from"./collapsible-BGf7BMbl.js";import{S as G}from"./separator-v-28rTKx.js";import{a as le}from"./useQuery-9bnKLnUE.js";import{E as Ze}from"./external-link-8Hd60Wl8.js";import{R as Je}from"./rotate-ccw-DU5G_hRk.js";import{C as es}from"./chevron-down-B1LDaoge.js";import{C as ce}from"./chevron-right-BbRMN46B.js";import{f as L}from"./formatDistanceToNow-3UBXKcFR.js";import{C as ss}from"./chevron-left-DB0tVaYU.js";import{T as ts}from"./telescope-CHzSYNhV.js";import"./Layout-DAWUt-Eh.js";import"./Footer-DeVgdLil.js";import"./Header-BUQn9Pzh.js";import"./search-ptOco6OC.js";import"./map-pin-BTYmtfJU.js";import"./store-CnfieG8L.js";import"./building-x2E7TkaF.js";import"./popify-logo-j04LgRya.js";import"./list-CtVT9Y2l.js";import"./calendar-DmfXVeb3.js";import"./users-DHPuX-8_.js";import"./user-BT4chubZ.js";import"./building-2-cBWZmyXA.js";import"./file-text-SdZWtsDM.js";import"./chart-column-DgCCpDjK.js";import"./trending-up-CxKrPUSf.js";import"./circle-alert-CgZ3UpaC.js";import"./upload-horg_POA.js";import"./trophy-C6J7-1he.js";import"./mail-Cik6hlfX.js";import"./index-BgQ1TD9Y.js";import"./index-DfEW_cST.js";import"./index-vzZ7al4T.js";import"./circle-6Cn-O5vr.js";import"./check-CDWAMMC0.js";import"./chevron-up-uIN8WUTz.js";import"./leave-review-schemas-D-qo09bh.js";import"./types-lSNCvkhu.js";import"./index-Dz42c7uB.js";import"./en-US-wfBU2YNu.js";function ns(s){switch(s){case"queued":return{label:"Queued",icon:te,variant:"secondary",className:"bg-slate-100 text-slate-700 border-slate-200"};case"processing":return{label:"Processing",icon:A,variant:"secondary",className:"bg-blue-100 text-blue-800 border-blue-200",spin:!0};case"done":return{label:"Done",icon:qe,variant:"secondary",className:"bg-green-100 text-green-800 border-green-200"};case"failed":return{label:"Failed",icon:Le,variant:"destructive"};case"cancelled":return{label:"Cancelled",icon:Te,variant:"outline",className:"text-muted-foreground border-muted"};default:return{label:s??"Unknown",icon:te,variant:"outline"}}}function de({status:s,className:t}){const n=ns(s),a=n.icon,i=["inline-flex items-center gap-1",n.className,t].filter(Boolean).join(" ");return e.jsxs(H,{variant:n.variant,className:i,children:[e.jsx(a,{className:n.spin?"h-3 w-3 animate-spin":"h-3 w-3","aria-hidden":"true"}),e.jsx("span",{children:n.label})]})}const Q=["city","region","province"],as=1,ae=200,W="ca";function rs(s){return s.normalize("NFD").replace(/[̀-ͯ]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function ue(s){const t=rs(s.name);if(t==="")return null;const n=(s.country??W).trim().toLowerCase();return`region://${s.granularity}/${t}/${n}`}function me(s){var o;if(!Q.includes(s.granularity))return{ok:!1,error:`Granularity must be one of: ${Q.join(", ")}`};const t=s.name.trim();if(t.length<as)return{ok:!1,error:"Region name is required"};if(t.length>ae)return{ok:!1,error:`Region name must be ${ae} characters or fewer`};const a=(s.country??W).trim().toLowerCase();if(!/^[a-z]{2}$/.test(a))return{ok:!1,error:"Country must be a 2-letter ISO code (e.g., 'ca', 'us')"};const i=ue({granularity:s.granularity,name:t,country:a});if(i===null)return{ok:!1,error:"Region name must contain at least one letter or digit"};const l=oe.safeParse({url:i,entity_type:"region"});return l.success?{ok:!0,url:i}:{ok:!1,error:((o=l.error.issues[0])==null?void 0:o.message)??"Region URL failed validation"}}function is(s,t){const n=me(s);if(!n.ok||!n.url)throw new Error(n.error??"Region submission validation failed");return{url:n.url,entity_type:"region",status:"queued",source:"operator",submitted_by:t}}function os({currentUserId:s}
1){const[t,n]=d.useState("city"),[a,i]=d.useState(""),[l,o]=d.useState(W),{toast:u}=V(),y=Y(),g=a.trim(),x=me({granularity:t,name:g,country:l}),b=ue({granularity:t,name:g,country:l}),f=K({mutationFn:async()=>{const c=is({granularity:t,name:g,country:l},s),{error:m}=await _.from("discovery_submissions").insert(c);if(m)throw m},onSuccess:()=>{u({title:"Region submitted",description:`Engine will scan ${g} on the next discovery drain.`}),i(""),y.invalidateQueries({queryKey:["discoverySubmissions"]})},onError:c=>{const m=c instanceof Error?c.message:"Submission failed";u({title:"Couldn't submit region",description:m,variant:"destructive"})}}),I=c=>{if(c.preventDefault(),!x.ok){u({title:"Check the form",description:x.error??"Region input is invalid",variant:"destructive"});return}f.mutate()},h=a.length>0&&!x.ok;return e.jsxs(F,{children:[e.jsxs($,{children:[e.jsxs(z,{className:"flex items-center gap-2",children:[e.jsx(Oe,{className:"w-5 h-5 text-muted-foreground"}),"Submit a region"]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Engine scans the region with Brave + classifies hits → operator reviews the candidates → promote keepers into the discovery queue. C-5 / POPIFY-44."})]}),e.jsx(B,{children:e.jsxs("form",{onSubmit:I,className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-[180px_1fr_120px] gap-3",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(q,{htmlFor:"region-granularity",children:"Granularity"}),e.jsxs(Ae,{value:t,onValueChange:c=>n(c),disabled:f.isPending,children:[e.jsx(Ie,{id:"region-granularity",children:e.jsx(Me,{placeholder:"Select"})}),e.jsx(Pe,{children:Q.map(c=>e.jsx(Ue,{value:c,className:"capitalize",children:c},c))})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(q,{htmlFor:"region-name",children:"Name"}),e.jsx(ne,{id:"region-name",value:a,onChange:c=>i(c.target.value),placeholder:t==="city"?"Newmarket":t==="region"?"York Region":"Ontario",disabled:f.isPending,"aria-invalid":h})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(q,{htmlFor:"region-country",children:"Country"}),e.jsx(ne,{id:"region-country",value:l,onChange:c=>o(c.target.value),placeholder:"ca",maxLength:2,className:"uppercase",disabled:f.isPending})]})]}),h?e.jsx("p",{className:"text-sm text-destructive",children:x.error}):b?e.jsxs("p",{className:"text-sm text-muted-foreground",children:["Will submit as"," ",e.jsx("code",{className:"text-xs",children:b})]}):null,e.jsx("div",{className:"flex items-center gap-3",children:e.jsxs(k,{type:"submit",disabled:!x.ok||f.isPending,title:x.ok?void 0:x.error,children:[f.isPending&&e.jsx(A,{className:"mr-2 h-4 w-4 animate-spin"}),f.isPending?"Submitting…":"Submit region"]})})]})})]})}const P=20;function ls(s){const t=new Set,n=[],a=s.split(/\r?\n/);for(let i=0;i<a.length;i++){const l=a[i].trim();l!==""&&(t.has(l)||(t.add(l),n.push({line:i+1,url:l})))}return n}function cs(s,t){var i;const n=[],a=[];for(const{line:l,url:o}of s){const u=oe.safeParse({url:o,entity_type:t});u.success?n.push({line:l,url:u.data.url,ok:!0}):a.push({line:l,url:o,ok:!1,error:((i=u.error.issues[0])==null?void 0:i.message)??"invalid"})}return{valid:n,invalid:a}}function ds(s,t,n){return s.map(({url:a})=>({url:a,entity_type:t,status:"queued",source:"operator",submitted_by:n}))}function us(s,t){return s.status!=="done"&&s.status!=="failed"&&s.status!=="cancelled"?null:{url:s.url,entity_type:s.entity_type,status:"queued",source:"operator",submitted_by:t}}function ms(s){switch(s){case"done":case"failed":case"cancelled":return{kind:"shown-enabled"};default:return{kind:"absent"}}}function hs(s){return s.filteredRowCount>0?{kind:"non-empty"}:s.totalAllRowCount===0?{kind:"first-time",heading:"No discovery seeds yet",body:"Paste a market, vendor, or organizer URL above to send the engine its first lead."}:{kind:"filter-empty",heading:`No ${{all:"in the queue",queued:"queued",processing:"in progress",done:"completed",failed:"failed"}[s.statusFilter]} seeds right now`,body:"Switch tabs or submit a new URL above."}}function fs(s){let t="";if(typeof s=="string")t=s;else if(s&&typeof s=="object"&&"message"in s){const a=s.message;
1typeof a=="string"&&(t=a)}const n=t.trim();return{message:n.length>0?n:"Couldn't load discovery submissions. The queue is fine — your view just lost the connection.",retryLabel:"Retry"}}function xs(s){switch(s){case"queued":return{kind:"shown-enabled"};case"processing":return{kind:"shown-disabled",reason:"Can't cancel — discovery is already running"};case"done":case"failed":case"cancelled":return{kind:"absent"};default:return{kind:"absent"}}}const ps=2*60*60*1e3;function gs(s,t=new Date,n=ps){if(s.status!=="processing"||!s.started_at)return!1;const a=Date.parse(s.started_at);return Number.isFinite(a)?t.getTime()-a>n:!1}function bs(s,t){switch(s){case"market":return`/markets?market=${encodeURIComponent(t)}`;case"vendor":return`/vendor/${encodeURIComponent(t)}`;case"organizer":return`/organizer/${encodeURIComponent(t)}`}}function js(s){const t={markets:Math.max(0,Math.floor((s==null?void 0:s.markets_discovered)??0)||0),vendors:Math.max(0,Math.floor((s==null?void 0:s.vendors_discovered)??0)||0),organizers:Math.max(0,Math.floor((s==null?void 0:s.organizers_discovered)??0)||0)},n={markets:[],vendors:[],organizers:[]},a=(s==null?void 0:s.entity_refs)??[];for(const o of a)o==null||typeof o!="object"||o.entity_type!=="market"&&o.entity_type!=="vendor"&&o.entity_type!=="organizer"||n[`${o.entity_type}s`].push({...o,href:bs(o.entity_type,o.entity_id)});const i=t.markets+t.vendors+t.organizers,l=i===0&&a.length===0;return{counts:t,groups:n,totalDiscovered:i,emptyButDone:l}}function vs(s){const t=(s??"").trim();return t.length>0?t:"Discovery run failed; the engine did not provide an error message."}function ys(s){const t={all:s.length,queued:0,processing:0,done:0,failed:0};for(const n of s)switch(n.status){case"queued":t.queued+=1;break;case"processing":t.processing+=1;break;case"done":t.done+=1;break;case"failed":t.failed+=1;break}return t}const Ns=25;function Cs(s,t,n=Ns){const a=s.length,i=Math.max(1,Math.ceil(a/n)),l=Number.isFinite(t)?Math.floor(t):1,o=Math.min(Math.max(l,1),i),u=(o-1)*n;return{page:s.slice(u,u+n),pageNumber:o,pageCount:i,total:a,label:`Page ${o} of ${i} (${a} total)`}}function _s(s){return s.submitting?{enabled:!1,reason:"Submitting…"}:s.totalCount===0?{enabled:!1,reason:"Add at least one URL"}:s.totalCount>P?{enabled:!1,reason:`Max ${P} URLs per batch — remove ${s.totalCount-P} to submit`}:s.invalidCount>0?{enabled:!1,reason:"Fix the highlighted lines"}:s.validCount===0?{enabled:!1,reason:"Add at least one URL"}:{enabled:!0}}const X="discovery-submissions",Ss="discovery-submission",ks=15e3,Rs="id, url, entity_type, status, created_at, started_at, completed_at, attempt_count, source, submitted_by, error, last_scanned_at";function ws(s){return[X,s]}function he(s){return[Ss,s]}function Ds(s){return{queryKey:ws(s),queryFn:async()=>{let t=_.from("discovery_submissions").select(Rs).order("created_at",{ascending:!1});s!=="all"&&(t=t.eq("status",s));const{data:n,error:a}=await t;if(a)throw a;return n??[]},refetchInterval:ks,refetchIntervalInBackground:!1}}function Es(s){return{queryKey:he(s),queryFn:async()=>{if(!s)return null;const{data:t,error:n}=await _.from("discovery_submissions").select("*").eq("id",s).maybeSingle();if(n)throw n;return t??null},enabled:s!==null}}function Ts(s){return le(Ds(s))}function Ls(s){return le(Es(s))}async function qs(s,t=_){if(s.length===0)return{submitted:0,failed:0,failedLines:[]};const n=await Promise.allSettled(s.map(async l=>{const{error:o}=await t.from("discovery_submissions").insert(l);if(o)throw new Error(o.message);return l}));let a=0;const i=[];return n.forEach((l,o)=>{if(l.status==="fulfilled")a+=1;else{const u=l.reason,y=u instanceof Error?u.message:typeof u=="string"?u:"insert failed";i.push({payload:s[o],error:y})}}),{submitted:a,failed:i.length,failedLines:i}}function fe(){const s=Y();return K({mutationFn:t=>qs(t),onSuccess:()=>{s.invalidateQueries({queryKey:[X]})}})}async function As(s,t=_){const{data:n,error:a}=await t.from("discovery_submissions").update({status:"cancelled"}).eq("id",s).eq("status","queued").select("id");if(a)throw new Error(a.message);return(Array.isArray(n)?n.length:0)>0?{kind:"cancelled",id:s}:{kind:"no_op",id:s}}function Is(){const s=Y();return K({mutationFn:t=>As(t),onSuccess:(t,n)=>{s.invalidateQueries({queryKey:[X]}),s.invalidateQueries({queryKey:he(n)})}})}function Ms({submissionId:s,onOpenChange:t}){const n=Ls(s);return e.jsx(je,{open:s!==null,onOpenChange:t,children:e.jsx(ve,{className:"w-[520px] sm:max-w-[520px] overflow-y-auto",children:n.isLoading||!n.data?e.jsx(Gs,{}):e.jsx(Ps,{row:n.data})})})}function Ps({row:s}){return e.jsxs(e.Fragment,{children:[e.jsxs(re,{className:"space-y-3 pb-3",children:[e.jsx(ie,{className:"break-all text-base font-medium",children:e.jsxs("a",{href:s.url,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-start gap-1 hover:underline",children:[e.jsx("span",{children:s.url}),e.jsx(Ze,{className:"h-4 w-4 mt-1 shrink-0","aria-hidden":"true"})]})}),e.jsx(de,{status:s.status})]}),e.jsx(Os,{row:s}),e.jsx(G,{className:"my-4"}),e.jsx(Fs,{row:s}),e.jsx(G,{className:"my-4"}),e.jsx(Us,{row:s})]})}function Us({row:s}){const t=xs(s.status),n=ms(s.status),{toast:a}=V(),i=Is(),l=fe(),[o,u]=d.useState(!1),[y,g]=d.useState(null);if(d.useEffect(()=>{let h=!1;return _.auth.getSession().then(({data:{session:c}})=>{var m;h||g(((m=c==null?void 0:c.user)==null?void 0:m.id)??null)}),()=>{h=!0}},[]),t.kind==="absent"&&n.kind==="absent")return null;const x=t.kind==="shown-disabled"||i.isPending,b=t.kind==="shown-disabled"?t.reason:void 0,f=async()=>{try{const h=await i.mutateAsync(s.id);u(!1),h.kind==="cancelled"?a({title:"Submission cancelled",description:"The URL stays in the queue marked Cancelled."}):a({title:"Already running",description:"The engine claimed this seed before the cancel landed. Let it finish; you can ignore the result if you don't want it."})}catch(h){const c=h instanceof Error?h.message:"Cancel failed.";a({title:"Couldn't cancel",description:c,variant:"destructive"})}},I=async()=>{var c;const h=us(s,y);if(!h){a({title:"Can't re-run",description:"This seed is still queued or processing.",variant:"destructive"});return}try{const m=await l.mutateAsync([h]);if(m.submitted===1)a({title:"Re-queued",description:`${s.url} is back in the queue.`});else{const j=((c=m.failedLines[0])==null?void 0:c.error)??"insert failed";a({title:"Re-queue failed",description:j,variant:"destructive"})}}catch(m){const j=m instanceof Error?m.message:"Re-queue failed.";a({title:"Re-queue failed",description:j,variant:"destructive"})}};return e.jsxs("section",{children:[e.jsx("h3",{className:"text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-2",children:"Actions"}),e.jsxs("div",{className:"flex items-center gap-3 flex-wrap",children:[t.kind!=="absent"&&e.jsxs(Fe,{open:o,onOpenChange:u,children:[e.jsx($e,{asChild:!0,children:e.jsxs(k,{variant:"outline",size:"sm",disabled:x,title:b,children:[i.isPending&&e.jsx(A,{className:"mr-2 h-4 w-4 animate-spin"}),"Cancel"]})}),e.jsxs(ze,{children:[e.jsxs(Be,{children:[e.jsx(Ge,{children:"Cancel this discovery seed?"}),e.jsxs(Qe,{children:["The URL stays in the queue marked ",e.jsx("strong",{children:"Cancelled"}),". The engine won't pick it up. If the engine has already started processing this row, the cancel is best-effort."]})]}),e.jsxs(Ve,{children:[e.jsx(Ye,{children:"Keep queued"}),e.jsx(He,{onClick:f,className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",children:"Cancel seed"})]})]})]}),n.kind==="shown-enabled"&&e.jsxs(k,{variant:"outline",size:"sm",disabled:l.isPending,onClick:I,title:"Re-queue the same URL as a fresh discovery seed",children:[l.isPending?e.jsx(A,{className:"mr-2 h-4 w-4 animate-spin"}):e.jsx(Je,{className:"mr-2 h-4 w-4","aria-hidden":"true"}),"Re-run"]}),b&&e.jsx("span",{className:"text-sm text-muted-foreground",children:b})]})]})}function Os({row:s}){return e.jsxs("section",{children:[e.jsx("h3",{className:"text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-2",children:"Submission"}),e.jsxs("dl",{className:"grid grid-cols-[120px_1fr] gap-y-2 text-sm",children:[e.jsx(v,{label:"Entity type",value:e.jsx("span",{className:"capitalize",children:s.entity_type})}),e.jsx(v,{label:"Submitted",value:L(new Date(s.created_at),{addSuffix:!0})}),s.started_at&&e.jsx(v,{label:"Started",value:L(new Date(s.started_at),{addSuffix:!0})}),s.completed_at&&e.jsx(v,{label:"Completed",value:L(new Date(s.completed_at),{addSuffix:!0})}),s.last_scanned_at&&e.jsx(v,{label:"Last scanned",value:e.jsx("span",{title:s.last_scanned_at,children:L(new Date(s.last_scanned_at),{addSuffix:!0})})}),s.source_content_hash&&e.jsx(v,{label:"Source hash",value:e.jsxs("code",{className:"text-xs",title:s.source_content_hash,children:[s.source_content_hash.slice(0,8),"…"]})}),e.jsx(v,{label:"Attempts",value:e.jsxs(e.Fragment,{children:[s.attempt_count,gs(s)&&e.jsx(H,{variant:"outline",className:"ml-2 border-amber-200 text-amber-700",children:"Running long"})]})}),s.engine_run_id&&e.jsx(v,{label:"Engine run",value:e.jsx("code",{className:"text-xs",children:s.engine_run_id})}),e.jsx(v,{label:"Source",value:e.jsx("span",{className:"capitalize",children:s.source})}),s.submitted_by&&e.jsx(v,{label:"Submitted by",value:e.jsxs("code",{className:"text-xs",children:[s.submitted_by.slice(0,8),"…"]})})]})]})}function v({label:s,value:t}){return e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-muted-foreground",children:s}),e.jsx("dd",{className:"text-foreground",children:t})]})}function Fs({row:s}){switch(s.status){case"done":return e.jsx($s,{resultSummary:s.result_summary});case"failed":return e.jsx(zs,{error:s.error});case"queued":case"processing":return e.jsx(Bs,{});case"cancelled":default:return e.jsx(e.Fragment,{})}}function $s({resultSummary:s}){const t=js(s),n=(s==null?void 0:s.skipped_unchanged)===!0;return e.jsxs("section",{children:[e.jsx("h3",{className:"text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-2",children:"Discovered entities"}),n&&e.jsx("p",{className:"text-sm text-muted-foreground italic mb-3",children:"Source unchanged since last scan — no re-extract performed."}),e.jsxs("div",{className:"grid grid-cols-3 gap-2 mb-3",children:[e.jsx(U,{label:"Markets",count:t.counts.markets}),e.jsx(U,{label:"Vendors",count:t.counts.vendors}),e.jsx(U,{label:"Organizers",count:t.counts.organizers})]}),t.emptyButDone&&!n?e.jsx("p",{className:"text-sm text-muted-foreground",children:"The run completed but discovered no new entities. The page may have already been ingested, or there was nothing new to find."}):e.jsxs("div",{className:"space-y-1",children:[e.jsx(O,{label:"Markets",entries:t.groups.markets}),e.jsx(O,{label:"Vendors",entries:t.groups.vendors}),e.jsx(O,{label:"Organizers",entries:t.groups.organizers})]})]})}function U({label:s,count:t}){return e.jsxs("div",{className:"rounded-md border bg-card p-3 text-center",children:[e.jsx("div",{className:"text-2xl font-semibold tabular-nums",children:t}),e.jsx("div",{className:"text-xs text-muted-foreground mt-0.5",children:s})]})}function O({label:s,entries:t}){const[n,a]=d.useState(!0);return t.length===0?null:e.jsxs(Ke,{open:n,onOpenChange:a,children:[e.jsxs(We,{className:"flex items-center gap-1 text-sm font-medium py-1",children:[n?e.jsx(es,{className:"h-3 w-3"}):e.jsx(ce,{className:"h-3 w-3"}),s," ",e.jsxs("span",{className:"text-muted-foreground",children:["(",t.length,")"]})]}),e.jsx(Xe,{className:"pl-4 space-y-1",children:t.map(i=>e.jsx("a",{href:i.href,className:"block text-sm text-primary hover:underline",children:i.name},i.entity_id))})]})}function zs({error:s}){const t=vs(s);return e.jsxs("section",{children:[e.jsx("h3",{className:"text-xs font-semibold uppercase tracking-wider text-destructive mb-2",children:"Run failed"}),e.jsx("div",{className:"rounded-md border border-red-200 bg-red-50 p-4 text-sm text-red-900 whitespace-pre-wrap break-words",children:t})]})}function Bs(){return e.jsxs("section",{className:"text-sm text-muted-foreground flex items-start gap-2",children:[e.jsx(A,{className:"h-4 w-4 mt-0.5 animate-spin shrink-0","aria-hidden":"true"}),e.jsx("p",{children:"Discovered entities will appear here when the run completes."})]})}function Gs(){return e.jsxs(e.Fragment,{children:[e.jsxs(re,{className:"space-y-3 pb-3",children:[e.jsx(ie,{children:e.jsx(C,{className:"h-5 w-3/4"})}),e.jsx(C,{className:"h-5 w-24"})]}),e.jsx(G,{className:"my-4"}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(C,{className:"h-4 w-full"}),e.jsx(C,{className:"h-4 w-2/3"}),e.jsx(C,{className:"h-4 w-1/2"}),e.jsx(C,{className:"h-20 w-full mt-4"})]})]})}function sn(){const s=ye(),{toast:t}=V(),[n,a]=d.useState(null),[i,l]=d.useState(null),[o,u]=d.useState("all"),[y,g]=d.useState(1),[x,b]=d.useState(""),[f,I]=d.useState("market"),[h,c]=d.use
1State(null),m=Ts(o),j=fe();d.useEffect(()=>{let r=!1;return(async()=>{const{data:{session:p}}=await _.auth.getSession();if(r)return;if(!p){s("/auth");return}l(p.user.id);const{data:M}=await _.from("user_roles").select("role").eq("user_id",p.user.id).eq("role","admin").maybeSingle();if(!r){if(!M){t({title:"Access Denied",description:"You don't have admin privileges.",variant:"destructive"}),s("/");return}a(!0)}})(),()=>{r=!0}},[s,t]);const R=d.useMemo(()=>ls(x),[x]),N=d.useMemo(()=>cs(R,f),[R,f]),w=d.useMemo(()=>_s({validCount:N.valid.length,invalidCount:N.invalid.length,totalCount:R.length,submitting:j.isPending}),[N,R.length,j.isPending]),S=d.useMemo(()=>m.data??[],[m.data]),xe=d.useMemo(()=>ys(S),[S]),D=d.useMemo(()=>Cs(S,y),[S,y]),Z=d.useMemo(()=>hs({filteredRowCount:S.length,totalAllRowCount:o==="all"?S.length:1,statusFilter:o}),[S.length,o]),pe=async()=>{var M;if(!w.enabled)return;const r=ds(N.valid,f,i),p=await j.mutateAsync(r);if(p.failed===0)t({title:`${p.submitted} seed${p.submitted===1?"":"s"} queued`,description:"The engine will pick them up on the next drain."}),b("");else{const ge=p.failedLines.map(be=>be.payload.url).join(`
2`);b(ge),t({title:`${p.submitted} of ${p.submitted+p.failed} queued · ${p.failed} failed`,description:(M=p.failedLines[0])==null?void 0:M.error,variant:"destructive"})}};return n===null?e.jsxs(J,{title:"Discovery Console",children:[e.jsx(ee,{title:"Discovery Console",noindex:!0}),e.jsx(C,{className:"h-8 w-64"})]}):n?e.jsxs(J,{title:"Discovery Console",description:"Submit market, vendor, or organizer URLs to the Vendor Discovery Engine. Watch them flow through queued → processing → done.",children:[e.jsx(ee,{title:"Discovery Console",noindex:!0}),e.jsxs("div",{className:"space-y-6",children:[e.jsxs(F,{children:[e.jsx($,{children:e.jsx(z,{children:"Submit URLs"})}),e.jsxs(B,{className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(q,{htmlFor:"discovery-urls",children:"URLs (one per line, up to 20)"}),e.jsx(Ne,{id:"discovery-urls",value:x,onChange:r=>b(r.target.value),placeholder:`https://vividvendors.ca/spring-2026/
3https://acraftvendor.ca`,rows:6,disabled:j.isPending}),e.jsxs("div",{className:"text-sm text-muted-foreground",children:[R.length," URL",R.length===1?"":"s",N.invalid.length>0&&e.jsxs(e.Fragment,{children:[" · ",e.jsxs("span",{className:"text-destructive",children:[N.invalid.length," invalid"]})]})]}),N.invalid.length>0&&e.jsx("ul",{className:"text-sm text-destructive list-disc pl-5",children:N.invalid.map(r=>e.jsxs("li",{children:["Line ",r.line,": ",r.error," — ",e.jsx("code",{children:r.url})]},r.line))})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(q,{children:"Entity type"}),e.jsx(Ce,{value:f,onValueChange:r=>I(r),className:"flex gap-6",children:["market","vendor","organizer"].map(r=>e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(_e,{value:r,id:`et-${r}`}),e.jsx(q,{htmlFor:`et-${r}`,className:"capitalize cursor-pointer",children:r})]},r))})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs(k,{onClick:pe,disabled:!w.enabled,title:w.reason,children:[j.isPending&&e.jsx(A,{className:"mr-2 h-4 w-4 animate-spin"}),j.isPending?"Submitting…":"Submit"]}),!w.enabled&&w.reason&&e.jsx("span",{className:"text-sm text-muted-foreground",children:w.reason})]})]})]}),e.jsx(os,{currentUserId:i}),e.jsxs(F,{children:[e.jsx($,{children:e.jsx(z,{children:"Submissions"})}),e.jsxs(B,{className:"space-y-4",children:[e.jsx(we,{value:o,onValueChange:r=>{u(r),g(1)},children:e.jsx(De,{children:["all","queued","processing","done","failed"].map(r=>e.jsxs(Ee,{value:r,className:"capitalize",children:[r,e.jsx(H,{variant:"secondary",className:"ml-2",children:xe[r]})]},r))})}),m.isLoading?e.jsx(Qs,{}):m.isError?e.jsx(Vs,{error:m.error,onRetry:()=>m.refetch()}):Z.kind!=="non-empty"?e.jsx(Ys,{vm:Z}):e.jsxs(e.Fragment,{children:[e.jsxs(Se,{children:[e.jsx(ke,{children:e.jsxs(se,{children:[e.jsx(E,{children:"URL"}),e.jsx(E,{children:"Type"}),e.jsx(E,{children:"Status"}),e.jsx(E,{children:"Attempts"}),e.jsx(E,{children:"Submitted"}),e.jsx(E,{children:"Last scanned"})]})}),e.jsx(Re,{children:D.page.map(r=>e.jsxs(se,{className:"cursor-pointer hover:bg-muted/50",onClick:()=>c(r.id),children:[e.jsx(T,{className:"max-w-md truncate",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"truncate",children:r.url}),r.source&&r.source!=="operator"&&e.jsx("span",{className:"px-1.5 py-0.5 text-[10px] font-mono uppercase tracking-wider rounded bg-slate-100 text-slate-600 shrink-0",title:`Submission source: ${r.source}`,children:r.source==="engine_post_back"?"engine":r.source})]})}),e.jsx(T,{className:"capitalize",children:r.entity_type}),e.jsx(T,{children:e.jsx(de,{status:r.status})}),e.jsx(T,{children:r.attempt_count}),e.jsx(T,{className:"text-muted-foreground",children:L(new Date(r.created_at),{addSuffix:!0})}),e.jsx(T,{className:"text-muted-foreground",children:r.last_scanned_at?e.jsx("span",{title:r.last_scanned_at,children:L(new Date(r.last_scanned_at),{addSuffix:!0})}):"—"})]},r.id))})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm text-muted-foreground",children:D.label}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(k,{variant:"outline",size:"sm",onClick:()=>g(r=>Math.max(1,r-1)),disabled:D.pageNumber<=1,children:[e.jsx(ss,{className:"h-4 w-4"})," Prev"]}),e.jsxs(k,{variant:"outline",size:"sm",onClick:()=>g(r=>Math.min(D.pageCount,r+1)),disabled:D.pageNumber>=D.pageCount,children:["Next ",e.jsx(ce,{className:"h-4 w-4"})]})]})]})]})]})]}),e.jsx(Ms,{submissionId:h,onOpenChange:r=>{r||c(null)}})]})]}):null}function Qs(){return e.jsx("div",{className:"space-y-2",children:Array.from({length:5}).map((s,t)=>e.jsx(C,{className:"h-10 w-full"},t))})}function Vs({error:s,onRetry:t}){const n=fs(s);return e.jsxs("div",{className:"border border-destructive/30 bg-destructive/5 rounded-md p-6 text-center space-y-3",children:[e.jsx("p",{className:"text-sm text-destructive",children:n.message}),e.jsx(k,{variant:"outline",size:"sm",onClick:t,children:n.retryLabel})]})}function Ys({vm:s}){return e.jsxs("div",{className:"border border-dashed rounded-md p-10 text-center space-y-3",children:[e.jsx(ts,{className:"mx-auto h-10 w-10 text-muted-foreground","aria-hidden":"true"}),e.jsx("h3",{className:"text-lg font-semibold",children:s.heading}),e.jsx("p",{className:"text-sm text-muted-foreground",children:s.body})]})}export{sn 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.