1import{r as d,j as e}from"./vendor-router-CFmQt7zv.js";import{u as H,a as G,b as Z}from"./vendor-query-BSKXI886.js";import{al as S,B as b,P as ee,I as L,L as D,a5 as se,S as te,n as ae,Y as re,o as le,p as ne,w as F,H as ie,C as q}from"./index-B1j2AiI_.js";import{T as I,a as R,b as p,c as j,d as E,e as m}from"./table-D-J_Egb6.js";import{u as oe}from"./use-debounce-Cwqkhos5.js";import{C as ce}from"./clock-Dtb363qw.js";import{P as de}from"./play-DjJcfs3Q.js";import{f as me}from"./formatDistanceToNow-DBb-slA0.js";import"./vendor-react-qkC6yhPU.js";import"./vendor-shiki-BYpP0sHd.js";import"./vendor-radix-BXY4_wtq.js";import"./en-US-B8tgjrRv.js";import"./endOfMonth-Bq1jtKGm.js";const z={list:async t=>{const a=new URLSearchParams;return t?.search&&a.append("search",t.search),t?.limit&&a.append("limit",t.limit.toString()),t?.offset&&a.append("offset",t.offset.toString()),(await S.get(`/admin/job-titles?${a.toString()}`)).data},unnormalizedCount:async()=>(await S.get("/admin/job-titles/unnormalized-count")).data,normalize:async(t,a)=>{const l=await fetch(`${S.defaults.baseURL}/admin/job-titles/normalize`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({limit:t})});if(!l.ok)throw new Error(`HTTP error! status: ${l.status}`);const N=l.body?.getReader();if(!N)throw new Error("No response body");const o=new TextDecoder;let i="";for(;;){const{done:x,value:y}=await N.read();if(x)break;i+=o.decode(y,{stream:!0});const r=i.split(` 2 3`);i=r.pop()||"";for(const u of r)if(u.startsWith("data: "))try{const n=JSON.parse(u.slice(6));a?.(n)}catch(n){console.error("Failed to parse SSE data:",n)}}}},g={all:["admin-job-titles"],lists:t=>[...g.all,"list",t],detail:t=>[...g.all,"detail",t]};function xe(t){return H({queryKey:g.lists(t),queryFn:()=>z.list(t)})}function ue(){return H({queryKey:[...g.all,"unnormalized-count"],queryFn:()=>z.unnormalizedCount()})}function he(){const t=G();return Z({mutationFn:async({limit:a,onProgress:l})=>z.normalize(a,l),onSuccess:()=>{t.invalidateQueries({queryKey:g.all})}})}function Pe(){const[t,a]=d.useState(1),[l,N]=d.useState(""),[o,i]=d.useState(!1),[x,y]=d.useState(""),[r,u]=d.useState([]),[n,C]=d.useState(!1),M=oe(l,400),v=20,$=(t-1)*v,{data:T,isLoading:K,refetch:O}=xe({limit:v,offset:$,search:M||void 0}),{data:U}=ue(),P=U?.count??0,{mutateAsync:_}=he(),k=T?.data??[],J=T?.total??0,A=Math.ceil(J/v),Q=t<A,V=async s=>{s.preventDefault(),i(!0),u([]),C(!0);const h=x?parseInt(x,10):void 0;try{await _({limit:h,onProgress:f=>{if(f.type==="complete"){const c=f;i(!1),F.success(`Normalization complete, linked ${c.summary.linked}/${c.summary.total} experiences`),O()}else{const c=f;u(Y=>[...Y,c])}}})}catch{i(!1),F.error("Normalization failed. Check server logs for details.")}},B=s=>{switch(s){case"processing":case"checking":case"normalizing":case"linking":return o?e.jsx(D,{className:"h-4 w-4 animate-spin"}):e.jsx(q,{className:"h-4 w-4 text-green-600"});case"completed":case"batch_complete":return e.jsx(q,{className:"h-4 w-4 text-green-600"});case"failed":return e.jsx(ie,{className:"h-4 w-4 text-red-600"})}},w=r.length>0?r[r.length-1]:null,W=r.filter(s=>s.status==="batch_complete").length,X=r.filter(s=>s.status==="failed").length;return e.jsxs("div",{className:"flex flex-col gap-6 p-6",children:[e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold",children:"Job Titles"}),e.jsxs("p",{className:"text-muted-foreground text-sm",children:["Manage normalized job titles, ",J.toLocaleString()," total",P>0&&e.jsxs("span",{className:"ml-2 text-orange-500 font-medium",children:["· ",P.toLocaleString()," experiences not yet normalized"]})]})]}),e.jsxs(b,{onClick:()=>C(!n),children:[n?e.jsx(ce,{className:"mr-2 h-4 w-4"}):e.jsx(ee,{className:"mr-2 h-4 w-4"}),n?"Hide Normalize Panel":"Normalize Job Titles"]})]}),n&&e.jsxs("div",{className:"rounded-lg border p-6 space-y-4 bg-muted/50",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h2",{className:"text-lg font-semibold",children:"Normalize Job Titles"}),w&&e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[B(w.status),e.jsx("span",{children:w.message})]})]}),e.jsx("form",{onSubmit:V,className:"flex flex-col gap-4",children:e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs("div",{className:"flex-1 max-w-xs",children:[e.jsx("label",{className:"text-xs font-semibold text-gray-700 mb-1.5 block",children:"Limit (number of experiences to process)"}),e.jsx(L,{type:"number",min:1,value:x,onChange:s=>y(s.target.value),placeholder:"Leave blank for all",disabled:o}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Processes experiences without a linked job title. Normalizes via OpenAI in batches of 100."})]}),e.jsx(b,{type:"submit",disabled:o,className:"mt-6",children:o?e.jsxs(e.Fragment,{children:[e.jsx(D,{className:"mr-2 h-4 w-4 animate-spin"}),"Normalizingâ¦"]}):e.jsxs(e.Fragment,{children:[e.jsx(de,{className:"mr-2 h-4 w-4"}),"Start Normalize"]})})]})}),r.length>0&&e.jsxs("div",{className:"grid grid-cols-3 gap-3",children:[e.jsxs("div",{className:"rounded-lg border p-3 space-y-1",children:[e.jsx("p",{className:"text-xs text-muted-foreground font-medium",children:"Total Updates"}),e.jsx("p",{className:"text-xl font-bold",children:r.length})]}),e.jsxs("div",{className:"rounded-lg border p-3 space-y-1",children:[e.jsx("p",{className:"text-xs text-muted-foreground font-medium",children:"Batches Completed"}),e.jsx("p",{className:"text-xl font-bold text-green-600",children:W})]}),e.jsxs("div",{className:"rounded-lg border p-3 space-y-1",children:[e.jsx("p",{className:"text-xs text-muted-foreground font-medium",children:"Batches Failed"}),e.jsx("p",{className:"text-xl font-bold text-red-600",children:X})]})]}),r.length>0&&e.jsx("div",{className:"rounded-lg border bg-background",children:e.jsx("div",{className:"max-h-64 overflow-y-auto",children:e.jsxs(I,{children:[e.jsx(R,{children:e.jsxs(p,{children:[e.jsx(j,{className:"w-10",children:"Status"}),e.jsx(j,{children:"Batch"}),e.jsx(j,{children:"Message"})]})}),e.jsx(E,{children:r.slice().reverse().map((s,h)=>e.jsxs(p,{children:[e.jsx(m,{children:B(s.status)}),e.jsx(m,{className:"font-medium",children:s.batchNumber&&s.totalBatches?e.jsxs(se,{variant:"outline",children:[s.batchNumber,"/",s.totalBatches]}):e.jsx("span",{className:"text-muted-foreground",children:"-"})}),e.jsx(m,{className:"text-sm text-muted-foreground",children:s.message})]},h))})]})})})]}),e.jsxs("div",{className:"relative w-72",children:[e.jsx(te,{className:"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"}),e.jsx(L,{className:"pl-9",placeholder:"Search job titles...",value:l,onCh
3ange:s=>{N(s.target.value),a(1)}})]}),e.jsx("div",{className:"rounded-md border",children:e.jsxs(I,{children:[e.jsx(R,{children:e.jsxs(p,{children:[e.jsx(j,{children:"Job Title"}),e.jsx(j,{children:"Added"})]})}),e.jsx(E,{children:K?Array.from({length:5}).map((s,h)=>e.jsx(p,{children:Array.from({length:2}).map((f,c)=>e.jsx(m,{children:e.jsx(ae,{className:"h-4 w-full"})},c))},h)):k.map(s=>e.jsxs(p,{children:[e.jsx(m,{children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(re,{className:"h-4 w-4 text-muted-foreground"}),e.jsx("span",{className:"font-medium",children:s.name})]})}),e.jsx(m,{className:"text-sm text-muted-foreground",children:me(new Date(s.createdAt),{addSuffix:!0})})]},s.id))})]})}),k.length>0&&e.jsxs("div",{className:"flex items-center justify-end gap-2",children:[e.jsx(b,{variant:"outline",size:"sm",disabled:t<=1,onClick:()=>a(s=>s-1),children:e.jsx(le,{className:"h-4 w-4"})}),e.jsxs("span",{className:"text-sm text-muted-foreground",children:["Page ",t," of ",A]}),e.jsx(b,{variant:"outline",size:"sm",disabled:!Q,onClick:()=>a(s=>s+1),children:e.jsx(ne,{className:"h-4 w-4"})})]})]})}export{Pe 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.