PageSourceSearch

https://opportuning.art/assets/AdminSourcesPage-CMKkU3Sf.js

js opportuning.art collected 2026-09-24 14:33:09 UTC 24,895 bytes, 18 lines download raw bytes

1import{c as le,r as d,j as e,C as je,a as Se,b as Ce,B as h,R as $e,L as U,d as _e,T as Re,e as Te,f as F,g as M,h as R,i as De,X as qe,s as x,k as c,E as ve,S as Ee,D as Le,U as Ve,l as de,m as Ie,n as ue,o as he,p as me,q as I,I as ee,t as se,v as te,w as re,x as ae,y as P,z as Ue,A as Ae,P as ze,F as He}from"./index-C-csw2iF.js";import{T as xe,a as pe,b as W,c as N,d as fe,e as v}from"./table-CdnNHBkk.js";import{H as Oe}from"./history-DTkTt5xG.js";import{U as Be}from"./undo-2-DViTDh2W.js";import{P as Fe}from"./plus-KtpaQJsP.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 Me=le("FileDown",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M12 18v-6",key:"17g6i2"}],["path",{d:"m9 15 3 3 3-3",key:"1npd3o"}]]);/**
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 ne=le("Stethoscope",[["path",{d:"M11 2v2",key:"1539x4"}],["path",{d:"M5 2v2",key:"1yf1q8"}],["path",{d:"M5 3H4a2 2 0 0 0-2 2v4a6 6 0 0 0 12 0V5a2 2 0 0 0-2-2h-1",key:"rb5t3r"}],["path",{d:"M8 15a6 6 0 0 0 12 0v-3",key:"x18d4x"}],["circle",{cx:"20",cy:"10",r:"2",key:"ts1r5v"}]]);/**
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 ie=le("Wrench",[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z",key:"cbrjhi"}]]),Pe={healthy:"default",repaired:"default",degraded:"outline",needs_review:"outline",broken:"destructive",disabled:"secondary",unknown:"secondary"};function We(){const[u,A]=d.useState([]),[E,J]=d.useState([]),[z,Y]=d.useState({}),[C,D]=d.useState(null),[m,$]=d.useState(!1),[y,L]=d.useState(!1),[H,G]=d.useState(!1),[O,B]=d.useState(!0),b=async()=>{B(!0);const[{data:s},{data:o}]=await Promise.all([x.from("opportunity_sources").select("id, name, url, health_status, verification_status, enabled, last_health_check_at, last_health_status_code, last_health_error, consecutive_errors, opportunities_found_7d, last_yield, replacement_candidate_url, replacement_confidence, replacement_reason, canonical_url").order("name"),x.from("source_repair_suggestions").select("*").eq("status","pending").order("detected_at",{ascending:!1})]);A(s||[]),J(o||[]),B(!1)};d.useEffect(()=>{b()},[]);const T=async(s,o,f)=>{D(o);try{const{data:p,error:Z}=await x.functions.invoke("source-doctor",{body:s});if(Z)throw Z;if(p!=null&&p.error)throw new Error(p.error);return c.success(f),await b(),p}catch(p){c.error(p instanceof Error?p.message:"Action failed")}finally{D(null)}},X=async s=>{const{data:o}=await x.from("source_url_history").select("*").eq("source_id",s).order("changed_at",{ascending:!1});Y(f=>({...f,[s]:o||[]}))},q=async()=>{$(!0);try{const{data:s,error:o}=await x.functions.invoke("source-doctor",{body:{action:"scan_broken",limit:10}});if(o)throw o;c.success(`Repair: ${(s==null?void 0:s.processed)??0} checked · ${(s==null?void 0:s.applied)??0} fixed · ${(s==null?void 0:s.suggested)??0} suggestions · ${(s==null?void 0:s.needs_review)??0} need review`),await b()}catch(s){c.error(s instanceof Error?s.message:"Scan failed")}finally{$(!1)}},K=async()=>{L(!0);try{const{data:s,error:o}=await x.functions.invoke("source-doctor",{body:{action:"sweep_health",limit:50,max_age_hours:24}});if(o)throw o;c.success(`Health sweep: ${(s==null?void 0:s.processed)??0} checked — ${(s==null?void 0:s.healthy)??0} healthy, ${(s==null?void 0:s.degraded)??0} degraded, ${(s==null?void 0:s.broken)??0} broken`),await b()}catch(s){c.error(s instanceof Error?s.message:"Sweep failed")}finally{L(!1)}},Q=async()=>{G(!0);try{const{data:s,error:o}=await x.functions.invoke("source-doctor",{body:{action:"scan_unproductive",limit:8}});if(o)throw o;c.success(`Yield scan: ${(s==null?void 0:s.processed)??0}
16 checked, ${(s==null?void 0:s.suggested)??0} new suggestions`),await b()}catch(s){c.error(s instanceof Error?s.message:"Yield scan failed")}finally{G(!1)}},k={healthy:u.filter(s=>s.health_status==="healthy"||s.health_status==="repaired").length,degraded:u.filter(s=>s.health_status==="degraded").length,broken:u.filter(s=>s.health_status==="broken").length,needs_review:u.filter(s=>s.health_status==="needs_review").length,unknown:u.filter(s=>s.health_status==="unknown").length},S=s=>u.filter(o=>Array.isArray(s)?s.includes(o.health_status):o.health_status===s),V=s=>{var o,f;return e.jsxs("div",{className:"border rounded-lg p-3 space-y-2",children:[e.jsx("div",{className:"flex items-start justify-between gap-3",children:e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"font-medium text-sm",children:s.name}),e.jsx(R,{variant:Pe[s.health_status]||"secondary",className:"text-xs capitalize",children:s.health_status.replace("_"," ")}),s.last_health_status_code&&e.jsxs(R,{variant:"outline",className:"text-xs",children:["HTTP ",s.last_health_status_code]}),s.consecutive_errors>0&&e.jsxs(R,{variant:"outline",className:"text-xs",children:[s.consecutive_errors," errors"]})]}),e.jsxs("a",{href:s.url,target:"_blank",rel:"noopener noreferrer",className:"text-xs text-muted-foreground hover:text-primary inline-flex items-center gap-1 mt-1 break-all",children:[s.url," ",e.jsx(ve,{className:"h-3 w-3 shrink-0"})]}),s.last_health_error&&e.jsx("p",{className:"text-xs text-destructive mt-1 truncate",title:s.last_health_error,children:s.last_health_error}),s.replacement_candidate_url&&e.jsxs("div",{className:"mt-2 text-xs bg-muted/40 rounded p-2",children:[e.jsxs("div",{className:"font-medium text-foreground mb-1",children:["Suggested replacement · ",Math.round((s.replacement_confidence||0)*100),"%"]}),e.jsx("a",{href:s.replacement_candidate_url,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline break-all",children:s.replacement_candidate_url}),s.replacement_reason&&e.jsx("p",{className:"text-muted-foreground mt-1",children:s.replacement_reason})]})]})}),e.jsxs("div",{className:"flex flex-wrap gap-1",children:[e.jsxs(h,{size:"sm",variant:"outline",disabled:C===`check-${s.id}`,onClick:()=>T({action:"check_source",source_id:s.id},`check-${s.id}`,"Health checked"),children:[C===`check-${s.id}`?e.jsx(U,{className:"h-3 w-3 mr-1 animate-spin"}):e.jsx(ne,{className:"h-3 w-3 mr-1"}),"Check"]}),e.jsxs(h,{size:"sm",variant:"outline",disabled:C===`repair-${s.id}`,onClick:()=>T({action:"repair_source",source_id:s.id},`repair-${s.id}`,"Repair attempted"),children:[C===`repair-${s.id}`?e.jsx(U,{className:"h-3 w-3 mr-1 animate-spin"}):e.jsx(ie,{className:"h-3 w-3 mr-1"}),"Auto-repair"]}),e.jsxs(h,{size:"sm",variant:"ghost",onClick:()=>X(s.id),children:[e.jsx(Oe,{className:"h-3 w-3 mr-1"})," History"]}),((o=z[s.id])==null?void 0:o.length)>0&&e.jsxs(h,{size:"sm",variant:"ghost",disabled:C===`rollback-${s.id}`,onClick:()=>T({action:"rollback_source_url",source_id:s.id},`rollback-${s.id}`,"Rolled back"),children:[e.jsx(Be,{className:"h-3 w-3 mr-1"})," Rollback"]})]}),((f=z[s.id])==null?void 0:f.length)>0&&e.jsx("div",{className:"text-xs text-muted-foreground border-t pt-2 mt-1 space-y-1",children:z[s.id].slice(0,5).map(p=>e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(R,{variant:"outline",className:"text-[10px]",children:p.change_type}),e.jsxs("span",{className:"truncate",children:[p.old_url," → ",p.new_url]}),e.jsx("span",{className:"ml-auto whitespace-nowrap",children:new Date(p.changed_at).toLocaleDateString()})]},p.id))})]},s.id)};return e.jsxs(je,{children:[e.jsxs(Se,{className:"flex flex-row items-center justify-between gap-2 space-y-0",children:[e.jsxs("div",{children:[e.jsxs(Ce,{className:"text-base flex items-center gap-2",children:[e.jsx(ne,{className:"h-4 w-4"})," Source Doctor"]}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-1",children:[k.healthy," healthy · ",k.degraded," degraded · ",k.broken," broken · ",k.needs_review," need review · ",E.length," pending suggestions"]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(h,{variant:"outline",size:"sm",onClick:b,disabled:O,children:[e.jsx($e,{className:`h-4 w-4 mr-2 ${O?"animate-spin":""}`})," Refresh"]}),e.jsxs(h,{variant:"outline",size:"sm",onClick:K,disabled:y,title:"Re-check the health of the 50 stalest sources",children:[y?e.jsx(U,{className:"h-4 w-4 mr-2 animate-spin"}):e.jsx(ne,{className:"h-4 w-4 mr-2"}),"Sweep health"]}),e.jsxs(h,{variant:"outline",size:"sm",onClick:Q,disabled:H,title:"Find better landing pages for healthy sources producing no opportunities",children:[H?e.jsx(U,{className:"h-4 w-4 mr-2 animate-spin"}):e.jsx(ie,{className:"h-4 w-4 mr-2"}),"Improve yield"]}),e.jsxs(h,{size:"sm",onClick:q,disabled:m,children:[m?e.jsx(U,{className:"h-4 w-4 mr-2 animate-spin"}):e.jsx(ie,{className:"h-4 w-4 mr-2"}),"Scan & repair broken"]})]})]}),e.jsx(_e,{children:e.jsxs(Re,{defaultValue:"suggestions",children:[e.jsxs(Te,{children:[e.jsxs(F,{value:"suggestions",children:["Suggestions (",E.length,")"]}),e.jsxs(F,{value:"broken",children:["Broken (",k.broken,")"]}),e.jsxs(F,{value:"needs_review",children:["Needs review (",k.needs_review,")"]}),e.jsxs(F,{value:"degraded",children:["Degraded (",k.degraded,")"]}),e.jsxs(F,{value:"healthy",children:["Healthy (",k.healthy,")"]})]}),e.jsxs(M,{value:"suggestions",className:"space-y-2 mt-4",children:[E.length===0&&e.jsx("p",{className:"text-sm text-muted-foreground p-4 text-center",children:"No pending suggestions."}),E.map(s=>{const o=u.find(f=>f.id===s.source_id);return e.jsxs("div",{className:"border rounded-lg p-3 space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"font-medium text-sm",children:(o==null?void 0:o.name)||"Unknown source"}),e.jsxs(R,{children:[Math.round(s.confidence*100),"% confidence"]})]}),e.jsxs("div",{className:"text-xs space-y-1",children:[e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"text-muted-foreground w-12",children:"Old:"}),e.jsx("a",{href:s.old_url,target:"_blank",rel:"noopener noreferrer",className:"truncate hover:text-primary",children:s.old_url})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"text-muted-foreground w-12",children:"New:"}),e.jsx("a",{href:s.candidate_url,target:"_blank",rel:"noopener noreferrer",className:"truncate text-primary hover:underline",children:s.candidate_url})]})]}),s.reason&&e.jsx("p",{className:"text-xs text-muted-foreground",children:s.reason}),e.jsxs("div",{className:"flex gap-1",children:[e.jsxs(h,{size:"sm",disabled:C===`apply-${s.id}`,onClick:()=>T({action:"apply_suggestion",suggestion_id:s.id},`apply-${s.id}`,"Replacement applied"),children:[e.jsx(De,{className:"h-3 w-3 mr-1"})," Apply"]}),e.jsxs(h,{size:"sm",variant:"outline",disabled:C===`reject-${s.id}`,onClick:()=>T({action:"reject_suggestion",suggestion_id:s.id},`reject-${s.id}`,"Suggestion rejected"),children:[e.jsx(qe,{className:"h-3 w-3 mr-1"})," Reject"]})]})]},s.id)})]}),e.jsxs(M,{value:"broken",className:"space-y-2 mt-4",children:[S("broken").length===0&&e.jsx("p",{className:"text-sm text-muted-foreground p-4 text-center",children:"None."}),S("broken").map(V)]}),e.jsxs(M,{value:"needs_review",className:"space-y-2 mt-4",children:[S("needs_review").length===0&&e.jsx("p",{className:"text-sm text-muted-foreground p-4 text-center",children:"None."}),S("needs_review").map(V)]}),e.jsxs(M,{value:"degraded",className:"space-y-2 mt-4",children:[S("degraded").length===0&&e.jsx("p",{className:"text-sm text-muted-foreground p-4 text-center",children:"None."}),S("degraded").map(V)]}),e.jsxs(M,{value:"healthy",className:"space-y-2 mt-4",children:[S(["healthy","repaired"]).length===0&&e.jsx("p",{className:"text-sm text-muted-foreground p-4 text-center",children:"No healthy sources yet — run a check."}),S(["healthy","repaired"]).slice(0,30).map(V)]})]})})]})}const Ye=["official funder","curated aggregator","institutional","event platform","festival/award","network/union","other"],Ge=["general_arts","dance_auditions","performance_open_calls","residencies","funding_grants","institutional_calls","festival_submissions","aggregator"],ge={active:{variant:"default",label:"Active"},error:{variant:"outline",label:"Error"},unknown:{variant:"secondary",label:"Unverified"}};function es(){const[u,A]=d.useState([]),[E,J]=d.useState(!0),[z,Y]=d.useState(!1),[C,D]=d.useState(!1),[m,$]=d.useState({name:"",url:"",country_region:"",source_type:"other",login_required:"false"}
16),[y,L]=d.useState([]),[H,G]=d.useState(!1),[O,B]=d.useState(!1),[b,T]=d.useState(!1),X=d.useRef(null),q=async()=>{const{data:t}=await x.from("opportunity_sources").select("*").order("name");A(t||[]),J(!1)};d.useEffect(()=>{q()},[]);const K=async()=>{if(!m.name||!m.url)return;const{error:t}=await x.from("opportunity_sources").insert({name:m.name,url:m.url.startsWith("http")?m.url:`https://${m.url}`,country_region:m.country_region||null,source_type:m.source_type,login_required:m.login_required});if(t){c.error(t.message);return}c.success("Source added"),$({name:"",url:"",country_region:"",source_type:"other",login_required:"false"}),Y(!1),q()},Q=async(t,r)=>{const a={enabled:r};r&&(a.consecutive_errors=0,a.disabled_reason=null),await x.from("opportunity_sources").update(a).eq("id",t),A(l=>l.map(n=>n.id===t?{...n,...a}:n))},k=async t=>{confirm("Delete this source?")&&(await x.from("opportunity_sources").delete().eq("id",t),c.success("Source deleted"),q())},S=async t=>{var r;try{const{data:a,error:l}=await x.functions.invoke("discover-opportunities",{body:{source_id:t}});if(l)throw l;c.success(`Scan started (run: ${(r=a.scan_run_id)==null?void 0:r.substring(0,8)}…)`)}catch(a){c.error(a.message||"Failed to start scan")}},V=async()=>{T(!0);const t=c.loading("Verifying sources…");try{let r=null,a=0;const l={verified:0,active:0,removed:0,errored:0};for(;a<100;){const{data:n,error:g}=await x.functions.invoke("verify-sources",{body:{after_id:r,batch_size:12}});if(g)throw g;if(l.verified+=(n==null?void 0:n.verified)??0,l.active+=(n==null?void 0:n.active)??0,l.removed+=(n==null?void 0:n.removed)??0,l.errored+=(n==null?void 0:n.errored)??0,c.loading(`Verifying sources… ${l.verified} checked`,{id:t}),!(n!=null&&n.has_more)||!(n!=null&&n.next_cursor))break;r=n.next_cursor,a+=1}if(a>=100)throw new Error("Verification stopped early to avoid an endless loop.");await q(),c.success(`Verified ${l.verified} sources: ${l.active} active, ${l.removed} removed (dead), ${l.errored} errors`,{id:t})}catch(r){c.error(r.message||"Verification failed",{id:t})}finally{T(!1)}},s=t=>{const r=t.split(`
17`).filter(l=>l.trim());if(r.length<2)return[];const a=r[0].split(",").map(l=>l.trim().toLowerCase());return r.slice(1).map(l=>{const n=l.split(",").map(j=>j.trim()),g={};return a.forEach((j,_)=>{g[j]=n[_]||""}),g})},o=t=>{var l;const r=(l=t.target.files)==null?void 0:l[0];if(!r)return;const a=new FileReader;a.onload=n=>{var _;const g=(_=n.target)==null?void 0:_.result,j=s(g);L(j),D(!0)},a.readAsText(r)},f=t=>{let r=t.trim();r.startsWith("http")||(r=`https://${r}`);try{const a=new URL(r);return a.origin+a.pathname.replace(/\/+$/,"")}catch{return r.replace(/\/+$/,"")}},p=async()=>{if(y.length===0)return;B(!0);let t=0,r=0,a=0,l=0;try{const n=new Set,g=y.filter(i=>{if(!i.url)return!0;const w=f(i.url);return n.has(w)?!1:(n.add(w),!0)});if(l=y.length-g.length,H){const i=new Set(g.map(w=>w.url?f(w.url):""));for(const w of u)i.has(f(w.url))||await x.from("opportunity_sources").update({enabled:!1}).eq("id",w.id)}const j=new Map;for(const i of u)j.set(f(i.url),i.id);for(const i of g){if(!i.name||!i.url){a++;continue}const w=i.url.startsWith("http")?i.url:`https://${i.url}`,oe=f(w),ce=j.get(oe);if(ce)await x.from("opportunity_sources").update({name:i.name,country_region:i.country_region||null,opportunity_types:i.opportunity_types||null,disciplines:i.disciplines||null,source_type:i.source_type||null,crawlability_notes:i.crawlability_notes||null,login_required:i.login_required||"false",enabled:!0}).eq("id",ce),r++;else{const{error:ke}=await x.from("opportunity_sources").insert({name:i.name,url:w,country_region:i.country_region||null,opportunity_types:i.opportunity_types||null,disciplines:i.disciplines||null,source_type:i.source_type||null,crawlability_notes:i.crawlability_notes||null,login_required:i.login_required||"false"});if(ke){a++;continue}j.set(oe,"new"),t++}}const _=[`${t} inserted`,`${r} updated`,`${a} skipped`];l>0&&_.push(`${l} duplicates removed`),c.success(`Import done: ${_.join(", ")}`),D(!1),L([]),q()}catch(n){c.error(n.message||"Import failed")}finally{B(!1)}},Z=async()=>{try{const r=await(await fetch("/seed-sources.csv")).text(),a=s(r);L(a),D(!0)}catch{c.error("Failed to load default sources")}},ye=()=>{if(u.length===0){c.error("No sources to export");return}const t=["name","url","country_region","opportunity_types","disciplines","source_type","crawlability_notes","login_required","enabled","verification_status","last_scanned_at","last_verified_at","consecutive_errors","disabled_reason"],r=_=>{if(_==null)return"";const i=String(_);return/[",\n]/.test(i)?`"${i.replace(/"/g,'""')}"`:i},a=u.map(_=>t.map(i=>r(_[i])).join(",")),l=[t.join(","),...a].join(`
18`),n=new Blob([l],{type:"text/csv;charset=utf-8;"}),g=URL.createObjectURL(n),j=document.createElement("a");j.href=g,j.download=`opportunity-sources-${new Date().toISOString().split("T")[0]}.csv`,j.click(),URL.revokeObjectURL(g),c.success(`Exported ${u.length} sources`)},we=u.filter(t=>t.verification_status==="active").length,Ne=u.filter(t=>t.verification_status==="unknown").length,be=u.filter(t=>t.verification_status==="error").length;
18return e.jsxs("div",{className:"p-6 max-w-6xl mx-auto space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:"Opportunity Sources"}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:[u.length," sources — ",we," active, ",be," errors, ",Ne," unverified"]})]}),e.jsxs("div",{className:"flex gap-2 flex-wrap",children:[e.jsxs(h,{variant:"outline",onClick:ye,children:[e.jsx(Me,{className:"h-4 w-4 mr-2"})," Export CSV"]}),e.jsxs(h,{variant:"outline",onClick:V,disabled:b,children:[b?e.jsx(U,{className:"h-4 w-4 mr-2 animate-spin"}):e.jsx(Ee,{className:"h-4 w-4 mr-2"}),b?"Verifying…":"Verify All"]}),e.jsxs(h,{variant:"outline",onClick:Z,children:[e.jsx(Le,{className:"h-4 w-4 mr-2"})," Import Defaults"]}),e.jsx("input",{ref:X,type:"file",accept:".csv",className:"hidden",onChange:o}),e.jsxs(h,{variant:"outline",onClick:()=>{var t;return(t=X.current)==null?void 0:t.click()},children:[e.jsx(Ve,{className:"h-4 w-4 mr-2"})," Import CSV"]}),e.jsxs(de,{open:z,onOpenChange:Y,children:[e.jsx(Ie,{asChild:!0,children:e.jsxs(h,{children:[e.jsx(Fe,{className:"h-4 w-4 mr-2"})," Add Source"]})}),e.jsxs(ue,{children:[e.jsx(he,{children:e.jsx(me,{children:"Add Source"})}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx(I,{children:"Name"}),e.jsx(ee,{value:m.name,onChange:t=>$(r=>({...r,name:t.target.value})),placeholder:"Creative Europe"})]}),e.jsxs("div",{children:[e.jsx(I,{children:"URL"}),e.jsx(ee,{value:m.url,onChange:t=>$(r=>({...r,url:t.target.value})),placeholder:"https://..."})]}),e.jsxs("div",{children:[e.jsx(I,{children:"Country / Region"}),e.jsx(ee,{value:m.country_region,onChange:t=>$(r=>({...r,country_region:t.target.value})),placeholder:"Germany"})]}),e.jsxs("div",{children:[e.jsx(I,{children:"Source Type"}),e.jsxs(se,{value:m.source_type,onValueChange:t=>$(r=>({...r,source_type:t})),children:[e.jsx(te,{children:e.jsx(re,{})}),e.jsx(ae,{children:Ye.map(t=>e.jsx(P,{value:t,children:t},t))})]})]}),e.jsxs("div",{children:[e.jsx(I,{children:"Login Required"}),e.jsxs(se,{value:m.login_required,onValueChange:t=>$(r=>({...r,login_required:t})),children:[e.jsx(te,{children:e.jsx(re,{})}),e.jsxs(ae,{children:[e.jsx(P,{value:"false",children:"No"}),e.jsx(P,{value:"partial",children:"Partial"}),e.jsx(P,{value:"true",children:"Yes"})]})]})]}),e.jsx(h,{onClick:K,className:"w-full",children:"Add Source"})]})]})]})]})]}),e.jsx(de,{open:C,onOpenChange:D,children:e.jsxs(ue,{className:"max-w-2xl max-h-[80vh] overflow-y-auto",children:[e.jsx(he,{children:e.jsxs(me,{children:["Import ",y.length," Sources"]})}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Ue,{checked:H,onCheckedChange:t=>G(!!t),id:"replace"}),e.jsx(I,{htmlFor:"replace",children:"Replace all: disable existing sources not in CSV"})]}),e.jsx("div",{className:"border rounded max-h-60 overflow-auto",children:e.jsxs(xe,{children:[e.jsx(pe,{children:e.jsxs(W,{children:[e.jsx(N,{children:"Name"}),e.jsx(N,{children:"URL"}),e.jsx(N,{children:"Region"})]})}),e.jsxs(fe,{children:[y.slice(0,20).map((t,r)=>e.jsxs(W,{children:[e.jsx(v,{className:"text-sm",children:t.name}),e.jsx(v,{className:"text-sm truncate max-w-[200px]",children:t.url}),e.jsx(v,{className:"text-sm",children:t.country_region})]},r)),y.length>20&&e.jsx(W,{children:e.jsxs(v,{colSpan:3,className:"text-center text-muted-foreground",children:["…and ",y.length-20," more"]})})]})]})}),e.jsx(h,{onClick:p,className:"w-full",disabled:O,children:O?"Importing…":`Import ${y.length} Sources`})]})]})}),e.jsx(je,{children:e.jsx(_e,{className:"p-0",children:E?e.jsx("div",{className:"p-8 text-center text-muted-foreground",children:"Loading..."}):u.length===0?e.jsx("div",{className:"p-8 text-center text-muted-foreground",children:"No sources configured yet. Import from CSV or add manually."}):e.jsxs(xe,{children:[e.jsx(pe,{children:e.jsxs(W,{children:[e.jsx(N,{children:"Name"}),e.jsx(N,{children:"Region"}),e.jsx(N,{children:"Type"}),e.jsx(N,{children:"Focus"}),e.jsx(N,{children:"Status"}),e.jsx(N,{children:"Last Scanned"}),e.jsx(N,{children:"Enabled"}),e.jsx(N,{className:"w-[120px]"})]})}),e.jsx(fe,{children:u.map(t=>{const r=ge[t.verification_status]||ge.unknown;return e.jsxs(W,{className:t.verification_status==="error"?"opacity-60":"",children:[e.jsxs(v,{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium",children:t.name}),e.jsx("a",{href:t.url,target:"_blank",rel:"noopener noreferrer",className:"text-muted-foreground hover:text-primary",children:e.jsx(ve,{className:"h-3 w-3"})}),t.login_required!=="false"&&e.jsxs(R,{variant:"outline",className:"text-xs",children:["🔒 ",t.login_required]}),t.disabled_reason&&e.jsx(R,{variant:"destructive",className:"text-xs",title:t.disabled_reason,children:"⚡ Circuit break"}),t.consecutive_errors>0&&!t.disabled_reason&&e.jsxs(R,{variant:"outline",className:"text-xs text-orange-500",children:["⚠ ",t.consecutive_errors," errors"]})]}),t.disabled_reason&&e.jsx("p",{className:"text-xs text-destructive mt-1 max-w-md truncate",title:t.disabled_reason,children:t.disabled_reason})]}),e.jsx(v,{className:"text-muted-foreground text-sm",children:t.country_region||"—"}),e.jsx(v,{className:"text-muted-foreground text-sm",children:t.source_type||"—"}),e.jsx(v,{children:e.jsxs(se,{value:t.source_focus||"general_arts",onValueChange:async a=>{await x.from("opportunity_sources").update({source_focus:a,discovery_prompt_profile:a==="dance_auditions"||a==="performance_open_calls"?"dance_performance":"default",candidate_confidence_threshold:a==="dance_auditions"||a==="performance_open_calls"?.2:.35}).eq("id",t.id),A(l=>l.map(n=>n.id===t.id?{...n,source_focus:a}:n))},children:[e.jsx(te,{className:"h-8 text-xs w-[160px]",children:e.jsx(re,{})}),e.jsx(ae,{children:Ge.map(a=>e.jsx(P,{value:a,className:"text-xs",children:a},a))})]})}),e.jsxs(v,{children:[e.jsx(R,{variant:r.variant,className:"text-xs",children:r.label}),t.last_verified_at&&e.jsx("span",{className:"block text-[10px] text-muted-foreground mt-0.5",children:new Date(t.last_verified_at).toLocaleDateString()})]}),e.jsx(v,{className:"text-muted-foreground text-sm",children:t.last_scanned_at?new Date(t.last_scanned_at).toLocaleDateString():"Never"}),e.jsx(v,{children:e.jsx(Ae,{checked:t.enabled,onCheckedChange:a=>Q(t.id,a)})}),e.jsx(v,{children:e.jsxs("div",{className:"flex gap-1",children:[e.jsx(h,{variant:"ghost",size:"icon",onClick:()=>S(t.id),title:"Scan",children:e.jsx(ze,{className:"h-4 w-4 text-primary"})}),e.jsx(h,{variant:"ghost",size:"icon",onClick:()=>k(t.id),children:e.jsx(He,{className:"h-4 w-4 text-destructive"})})]})})]},t.id)})})]})})}),e.jsx(We,{})]})}
18export{es 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.