PageSourceSearch

https://knuckl.com/assets/JobOversight-zyQBlwc5.js

js knuckl.com collected 2026-10-02 01:36:39 UTC 39,070 bytes, 6 lines download raw bytes

1import{u as oe,a as v,e as A,k as U,j as e}from"./vendor-query-CRhh6spR.js";import{c as Ie,h as y,s as m,S as ge,q as be,r as ve,v as je,w as _e,L as Je,A as M,B as T,I as Oe,T as Ve,P as R}from"./index-BkVb42KZ.js";import{B as q}from"./badge-DfIFDYyU.js";import{S as se,a as ae,b as ie,c as re,d as S}from"./select-B5KGv1Do.js";import{D as Qe,a as Ue,b as ze,c as me,d as Be}from"./dropdown-menu-CR6TaDw3.js";import{A as ye,a as we,b as Ne,c as ke,d as Ce,e as Se,f as qe,g as Ae}from"./alert-dialog-whTlFcP7.js";import{A as We}from"./AdminSearchInput-CS_ud0Ue.js";import{t as He}from"./image-url-_sEuZELz.js";import{E as ne}from"./external-link-ibDNud24.js";import{T as De}from"./trash-2-eLOCP2Wl.js";import{T as Ge,a as Xe,b as O,c as V}from"./tabs-CWfW2Hlf.js";import{C as B,a as W}from"./card-CScRmu7W.js";import{C as Le}from"./copy-BEFhSt3P.js";import{C as le}from"./clipboard-list-DxTA222t.js";import{A as Te}from"./activity-5c8vuK-9.js";import{U as ce}from"./users-CLblnKO6.js";import{M as $e}from"./message-square-BwPXUwfW.js";import{C as Ze}from"./chart-column-UiAhC4rs.js";import{L as Q}from"./vendor-react-BAmwgVqg.js";import{E as ue}from"./eye-D9PTLHAC.js";import{S as Ye}from"./search-BNuSVdRk.js";import{B as Pe}from"./bell-CGtP-THa.js";import{S as pe}from"./shield-alert-DxK97mGJ.js";import{C as F}from"./circle-x-D3XjrB4n.js";import{C as xe}from"./circle-check-big-Cjr7FrMh.js";import{U as et}from"./user-plus-C-YQzt8j.js";import{A as tt}from"./AdminPage-BhQW-9r_.js";import{A as st}from"./AdminCard-FaakhOlA.js";import{A as at,a as it}from"./AdminLoading-CBBcaphO.js";import{B as rt}from"./briefcase-D-vMkZXu.js";import{L as nt}from"./lock-BhoZ9g-C.js";import{R as lt}from"./rotate-ccw-H-Njgz4G.js";import{E as ot}from"./ellipsis-vertical-4BGDn3no.js";import{P as ct}from"./play-CiL78hr7.js";import{P as dt}from"./pencil-Bd8KNKwZ.js";import"./vendor-charts-BVeOEGzI.js";import"./vendor-stripe-2y4Jo9_W.js";import"./vendor-supabase-Csx7YFID.js";import"./index-D17hSi50.js";import"./index-Bmtd1gWP.js";import"./index-fVqgy0Om.js";import"./chevron-down-CXoJibNt.js";import"./check-BtcgJ1Z4.js";import"./chevron-up-DcqJwcAx.js";import"./index-D5IzgxZK.js";import"./chevron-right-DSioQ7mT.js";import"./circle-Sm8JI_tc.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 mt=Ie("MailPlus",[["path",{d:"M22 13V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h8",key:"12jkf8"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7",key:"1ocrg3"}],["path",{d:"M19 16v6",key:"tddt3s"}],["path",{d:"M16 19h6",key:"xwg31i"}]]),ut=["accepted","rejected","withdrawn","removed","no_show","completed","paid"],pt=a=>{switch(a){case"accepted":return"bg-emerald-500/15 text-emerald-600 dark:text-emerald-400";
6case"pending":return"bg-yellow-500/15 text-yellow-700 dark:text-yellow-400";case"rejected":case"removed":case"no_show":return"bg-destructive/15 text-destructive";case"completed":case"paid":return"bg-blue-500/15 text-blue-600 dark:text-blue-400";default:return"bg-muted text-muted-foreground"}};function xt({jobId:a,jobTitle:t,onOpenChange:h}){const l=oe(),[r,d]=v.useState(null),{data:f,isLoading:n}=A({queryKey:["admin-job-applicants",a],enabled:!!a,queryFn:async()=>{const{data:s,error:c}=await m.from("applications").select("id, worker_id, status, message, created_at, status_changed_at, status_reason").eq("job_id",a).order("created_at",{ascending:!1});if(c)throw c;const j=[...new Set((s??[]).map(x=>x.worker_id))];if(j.length===0)return[];const{data:C}=await m.from("profiles").select("user_id, full_name, avatar_url").in("user_id",j),N=new Map((C??[]).map(x=>[x.user_id,x]));return(s??[]).map(x=>({...x,profile:N.get(x.worker_id)??null}))}}),b=U({mutationFn:async({id:s,status:c})=>{const{error:j}=await m.from("applications").update({status:c,status_changed_at:new Date().toISOString(),status_reason:"admin override"}).eq("id",s);if(j)throw j},onSuccess:()=>{l.invalidateQueries({queryKey:["admin-job-applicants",a]}),l.invalidateQueries({queryKey:["admin-jobs"]}),y.success("Application updated")},onError:s=>y.error(s.message||"Update failed")}),o=U({mutationFn:async s=>{const{error:c}=await m.from("applications").delete().eq("id",s);if(c)throw c},onSuccess:()=>{l.invalidateQueries({queryKey:["admin-job-applicants",a]}),l.invalidateQueries({queryKey:["admin-jobs"]}),y.success("Application deleted"),d(null)},onError:s=>y.error(s.message||"Delete failed")});return e.jsx(ge,{open:!!a,onOpenChange:h,children:e.jsxs(be,{side:"right",className:"w-full sm:max-w-xl overflow-y-auto",children:[e.jsxs(ve,{children:[e.jsx(je,{className:"text-base",children:"Applicants"}),e.jsx(_e,{className:"truncate",children:t})]}),e.jsx("div",{className:"mt-4 space-y-2",children:n?e.jsx("div",{className:"flex justify-center py-8",children:e.jsx(Je,{className:"w-5 h-5 animate-spin text-muted-foreground"})}):!f||f.length===0?e.jsx("p",{className:"text-center text-sm text-muted-foreground py-8",children:"No applicants for this job."}):f.map(s=>{var C,N;const c=((C=s.profile)==null?void 0:C.full_name)||"Worker",j=c.split(" ").map(x=>x[0]).slice(0,2).join("").toUpperCase()||"W";return e.jsxs("div",{className:"rounded-lg border border-border/60 bg-card p-3",children:[e.jsxs("div",{className:"flex items-start gap-3",children:[(N=s.profile)!=null&&N.avatar_url?e.jsx("img",{src:He(s.profile.avatar_url,96),alt:c,className:"w-10 h-10 rounded-full object-cover",loading:"lazy"}):e.jsx("div",{className:"w-10 h-10 rounded-full bg-primary/15 text-primary flex items-center justify-center text-sm font-semibold",children:j}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("p",{className:"text-sm font-semibold truncate",children:c}),e.jsx(q,{variant:"outline",className:`text-micro ${pt(s.status)}`,children:s.status})]}),e.jsxs("p",{className:"text-caption text-muted-foreground mt-0.5",children:["Applied ",M(s.created_at),s.status_changed_at&&s.status_changed_at!==s.created_at&&e.jsxs(e.Fragment,{children:[" · changed ",M(s.status_changed_at)]})]}),s.message&&e.jsx("p",{className:"text-xs text-muted-foreground mt-1 whitespace-pre-wrap break-words",children:s.message}),s.status_reason&&e.jsxs("p",{className:"text-caption text-muted-foreground italic mt-1",children:["Reason: ",s.status_reason]})]})]}),e.jsxs("div",{className:"mt-3 flex items-center gap-2",children:[e.jsxs(se,{value:s.status,onValueChange:x=>b.mutate({id:s.id,status:x}),disabled:b.isPending,children:[e.jsx(ae,{className:"h-8 text-xs flex-1",children:e.jsx(ie,{})}),e.jsx(re,{children:ut.map(x=>e.jsx(S,{value:x,className:"text-xs",children:x},x))})]}),e.jsx(T,{asChild:!0,variant:"outline",size:"sm",className:"h-8 text-xs",children:e.jsx("a",{href:`/profile/${s.worker_id}`,target:"_blank",rel:"noreferrer",children:e.jsx(ne,{className:"w-3.5 h-3.5"})})}),e.jsx(T,{variant:"ghost",size:"sm",className:"h-8 w-8 p-0 text-destructive hover:text-destructive",onClick:()=>
6d(s.id),children:e.jsx(De,{className:"w-3.5 h-3.5"})})]})]},s.id)})}),e.jsx(ye,{open:!!r,onOpenChange:s=>!s&&d(null),children:e.jsxs(we,{children:[e.jsxs(Ne,{children:[e.jsx(ke,{children:"Delete application?"}),e.jsx(Ce,{children:"This permanently removes the application record. The worker can re-apply unless the job is closed."})]}),e.jsxs(Se,{children:[e.jsx(qe,{children:"Cancel"}),e.jsx(Ae,{className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",onClick:()=>r&&o.mutate(r),children:"Delete"})]})]})})]})})}const ht={job_created:{label:"Job created",Icon:le},job_closed:{label:"Job closed",Icon:F,tone:"text-muted-foreground"},job_deleted:{label:"Job deleted",Icon:F,tone:"text-destructive"},invitation_sent:{label:"Invitation sent",Icon:mt},invitation_accepted:{label:"Invitation accepted",Icon:xe,tone:"text-emerald-600"},invitation_declined:{label:"Invitation declined",Icon:F,tone:"text-muted-foreground"},invitation_expired:{label:"Invitation expired",Icon:F,tone:"text-muted-foreground"},application_submitted:{label:"Application",Icon:et,tone:"text-primary"},application_accepted:{label:"Application accepted",Icon:xe,tone:"text-emerald-600"},application_rejected:{label:"Application rejected",Icon:F,tone:"text-destructive"},application_withdrawn:{label:"Application withdrawn",Icon:F,tone:"text-muted-foreground"},application_pending:{label:"Application change",Icon:le},group_message:{label:"Group chat",Icon:ce},direct_message:{label:"1:1 message",Icon:$e},call_initiated:{label:"Call initiated",Icon:R},call_ringing:{label:"Call ringing",Icon:R},call_in_progress:{label:"Call connected",Icon:R,tone:"text-emerald-600"},call_completed:{label:"Call completed",Icon:R,tone:"text-emerald-600"},call_failed:{label:"Call failed",Icon:R,tone:"text-destructive"},call_no_answer:{label:"Call no answer",Icon:R,tone:"text-muted-foreground"},notification:{label:"Notification",Icon:Pe},dispute_opened:{label:"Dispute opened",Icon:Ve,tone:"text-amber-600"},dispute_resolved:{label:"Dispute resolved",Icon:pe,tone:"text-emerald-600"},admin_action:{label:"Admin action",Icon:pe,tone:"text-primary"}};function ft(a){return ht[a]??{label:a,Icon:Te}}function E(a){return a?a.slice(0,8):"—"}function Me(a){var t;(t=navigator.clipboard)==null||t.writeText(a).then(()=>y.success("Copied"))}function gt({jobId:a,onOpenChange:t}){const[h,l]=v.useState("overview"),r=!!a;return e.jsx(ge,{open:r,onOpenChange:t,children:e.jsx(be,{side:"right",className:"w-full sm:max-w-2xl p-0 flex flex-col",children:a&&e.jsxs(e.Fragment,{children:[e.jsxs(ve,{className:"px-4 pt-4 pb-2 border-b border-border",children:[e.jsx(je,{className:"text-base font-semibold",children:"Job inspector"}),e.jsxs(_e,{className:"text-xs font-mono text-muted-foreground flex items-center gap-2",children:[e.jsx("span",{className:"truncate",children:a}),e.jsx("button",{onClick:()=>Me(a),className:"hover:text-foreground",children:e.jsx(Le,{className:"w-3 h-3"})})]})]}),e.jsxs(Ge,{value:h,onValueChange:l,className:"flex-1 flex flex-col min-h-0",children:[e.jsx("div",{className:"px-3 pt-2 border-b border-border",children:e.jsxs(Xe,{className:"w-full grid grid-cols-5 h-auto bg-transparent gap-1",children:[e.jsxs(O,{value:"overview",className:"flex-col gap-0.5 py-1.5 text-micro",children:[e.jsx(le,{className:"w-3.5 h-3.5"}),"Overview"]}),e.jsxs(O,{value:"timeline",className:"flex-col gap-0.5 py-1.5 text-micro",children:[e.jsx(Te,{className:"w-3.5 h-3.5"}),"Timeline"]}),e.jsxs(O,{value:"people",className:"flex-col gap-0.5 py-1.5 text-micro",children:[e.jsx(ce,{className:"w-3.5 h-3.5"}),"People"]}),e.jsxs(O,{value:"comms",className:"flex-col gap-0.5 py-1.5 text-micro",children:[e.jsx($e,{className:"w-3.5 h-3.5"}),"Comms"]}),e.jsxs(O,{value:"stats",className:"flex-col gap-0.5 py-1.5 text-micro",children:[e.jsx(Ze,{className:"w-3.5 h-3.5"}),"Stats"]})]})}),e.jsxs("div",{className:"flex-1 overflow-y-auto px-4 py-3",children:[e.jsx(V,{value:"overview",className:"mt-0",children:e.jsx(vt,{jobId:a})}),e.jsx(V,{value:"timeline",className:"mt-0",children:e.jsx(jt,{jobId:a})}),e.jsx(V,{value:"people",className:"mt-0",children:e.jsx(_t,{jobId:a})}),e.jsx(V,{value:"comms",className:"mt-0",children:e.jsx(yt,{jobId:a})}),e.jsx(V,{value:"stats",className:"mt-0",children:e.jsx(wt,{jobId:a})})]})]})]})})})}function bt({jobId:a,notified:t,status:h}){const l=oe(),[r,d]=v.useState(!1),[f,n]=v.useState(!1),b=async()=>{d(!0);try{const{data:o,error:s}=await m.rpc("admin_refanout_job",{_job_id:a});if(s)throw s;const c=Number(o??0);c>0?y.success(`Alerted ${c} new worker${c===1?"":"s"}`):y.info("No new workers to alert — everyone in range was already notified"),l.invali
6dateQueries({queryKey:["admin-job-overview",a]})}catch(o){y.error((o==null?void 0:o.message)??"Re-notify failed")}finally{d(!1),n(!1)}};return e.jsx(B,{children:e.jsxs(W,{className:"p-3 space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-micro uppercase tracking-wider text-muted-foreground",children:"Worker reach"}),e.jsxs("div",{className:"text-sm font-medium",children:[t," notified"]})]}),f?e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(T,{size:"sm",onClick:b,disabled:r,className:"text-xs",children:r?"Sending…":"Confirm"}),e.jsx(T,{size:"sm",variant:"ghost",onClick:()=>n(!1),disabled:r,className:"text-xs",children:"Cancel"})]}):e.jsxs(T,{size:"sm",variant:"outline",disabled:h!=="active",onClick:()=>n(!0),className:"text-xs gap-1.5",children:[e.jsx(Pe,{className:"w-3.5 h-3.5"})," Re-notify workers"]})]}),e.jsxs("p",{className:"text-caption text-muted-foreground",children:["Alerts the nearest matching workers who have not already been notified about this job (up to 50 per run).",h!=="active"&&" Only active jobs can be re-notified."]})]})})}function vt({jobId:a}){const{data:t,isLoading:h}=A({queryKey:["admin-job-overview",a],queryFn:async()=>{const{data:d,error:f}=await m.from("jobs").select("*").eq("id",a).maybeSingle();if(f)throw f;return d}}),{data:l}=A({queryKey:["admin-job-contractor",t==null?void 0:t.contractor_id],enabled:!!(t!=null&&t.contractor_id),queryFn:async()=>{const{data:d}=await m.from("profiles").select("user_id, full_name").eq("user_id",t.contractor_id).maybeSingle();return d}});if(h)return e.jsx("div",{className:"text-sm text-muted-foreground py-6 text-center",children:"Loading…"});if(!t)return e.jsx("div",{className:"text-sm text-muted-foreground py-6 text-center",children:"Job not found."});const r=[{label:"Title",value:t.title},{label:"Status",value:t.status},{label:"Visibility",value:t.visibility??"—"},{label:"Urgency",value:t.urgency??"—"},{label:"Pay",value:`$${Number(t.pay).toFixed(0)}/${t.pay_type}`},{label:"Slots",value:`${t.filled_slots}/${t.slots}`},{label:"Location",value:t.location??"—"},{label:"Trade",value:t.trade??"—"},{label:"Schedule",value:t.schedule_mode??t.schedule_type??"—"},{label:"Start date",value:t.start_date??"—"},{label:"End date",value:t.end_date??"—"},{label:"Posted",value:new Date(t.created_at).toLocaleString()},{label:"Closed",value:t.closed_at?new Date(t.closed_at).toLocaleString():"—"},{label:"Deleted",value:t.deleted_at?new Date(t.deleted_at).toLocaleString():"—"}];return e.jsxs("div",{className:"space-y-4",children:[e.jsx(bt,{jobId:a,notified:t.notified_worker_count??0,status:t.status}),e.jsx(B,{children:e.jsxs(W,{className:"p-3 space-y-2",children:[e.jsx("div",{className:"text-micro uppercase tracking-wider text-muted-foreground",children:"Contractor"}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-sm font-medium truncate",children:(l==null?void 0:l.full_name)??"Unknown"}),e.jsx("div",{className:"text-caption text-muted-foreground font-mono",children:E(t.contractor_id)})]}),e.jsxs(Q,{to:`/admin/users?role=contractor&id=${t.contractor_id}`,className:"text-xs text-primary inline-flex items-center gap-1 hover:underline",children:["Profile ",e.jsx(ne,{className:"w-3 h-3"})]})]})]})}),e.jsx(B,{children:e.jsx(W,{className:"p-0",children:e.jsx("dl",{className:"divide-y divide-border text-sm",children:r.map(d=>e.jsxs("div",{className:"flex items-start justify-between gap-3 px-3 py-2",children:[e.jsx("dt",{className:"text-xs text-muted-foreground shrink-0 w-24",children:d.label}),e.jsx("dd",{className:"text-right text-sm break-words min-w-0",children:String(d.value??"—")})]},d.label))})})}),t.description&&e.jsx(B,{children:e.jsxs(W,{className:"p-3",children:[e.jsx("div",{className:"text-micro uppercase tracking-wider text-muted-foreground mb-1.5",children:"Description"}),e.jsx("p",{className:"text-sm whitespace-pre-wrap break-words",children:t.description})]})}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(Q,{to:`/jobs/${a}`,target:"_blank",className:"text-xs rounded-full border border-border bg-card px-3 py-2 hover:bg-muted inline-flex items-center gap-1.5",children:[e.jsx(ue,{className:"w-3 h-3"})," View as worker"]}),e.jsxs(Q,{to:`/contractor/jobs/${a}`,target:"_blank",className:"text-xs rounded-full border border-border bg-card px-3 py-2 hover:bg-muted inline-flex items-center gap-1.5",children:[e.jsx(ue,{className:"w-3 h-3"})," View as contractor"]}),e.jsxs(Q,{to:`/jobs/share/${a}`,target:"_blank",className:"text-xs rounded-full border border-border bg-card px-3 py-2 hover:bg-muted inline-flex items-center gap-1.5",children:[e.jsx(ne,{className:"w-3 h-3"})," Public share"]}),e.jsxs("button",{onClick:()=>Me(`${window.location.origin}/jobs/share/${a}`),className:"text-xs rounded-full border border-border bg-card px-3 py-2 hover:bg-muted inline-flex items-center gap-1.5",children:[e.jsx(Le,{className:"w-3 h-3"})," Copy share link"]})]})]})}function jt({jobId:a}){const[t,h]=v.useState("all"),{data:l,isLoading:r}=A({queryKey:["admin-job-timeline",a],queryFn:async()=>{const{data:n,error:b}=await m.rpc("admin_job_timeline",{p_job_id:a});if(b)throw b;return n??[]}}),d=v.useMemo(()=>l?t==="all"?l:t==="messages"?l.filter(n=>n.kind==="direct_message"||n.kind==="group_message"):t==="applications"?l.filter(n=>n.kind.startsWith("application_")):t==="invitations"?l.filter(n=>n.kind.startsWith("invitation_")):t==="calls"?l.filter(n=>n.kind.startsWith("call_")):t==="admin"?l.filter(n=>n.kind==="admin_action"||n.kind.startsWith("job_")||n.kind.startsWith("dispute_")):l:[],[l,t]),f=[{v:"all",label:"All"},{v:"messages",label:"Messages"},{v:"applications",label:"Apps"},{v:"invitations",label:"Invites"},{v:"calls",label:"Calls"},{v:"admin",label:"Admin"}];return e.jsxs("div",{className:"space-y-3",children:[e.jsx("div",{className:"flex flex-wrap gap-1.5",children:f.map(n=>e.jsx("button",{onClick:()=>h(n.v),className:`text-caption rounded-full px-2.5 py-1 border transition ${t===n.v?"bg-primary text-primary-foreground border-primary":"bg-card border-border hover:bg-muted"}`,children:n.label},n.v))}),r?e.jsx("div",{className:"text-sm text-muted-foreground py-6 text-center",children:"Loading timeline…"}):d.length===0?e.jsx("div",{className:"text-sm text-muted-foreground py-6 text-center",children:"No events."}):e.jsx("ol",{className:"relative border-l border-border ml-2 space-y-3",children:d.map((n,b)=>{var c;const o=ft(n.kind),s=o.Icon;return e.jsxs("li",{className:"ml-4 pl-1",children:[e.jsx("span",{className:`absolute -left-[7px] mt-1 w-3.5 h-3.5 rounded-full border-2 border-background bg-card flex items-center justify-center ${o.tone??""}`,children:e.jsx(s,{className:"w-2 h-2"})}),e.jsxs("div",{className:"flex items-center justify-between gap-2 text-caption text-muted-foreground",children:[e.jsx("span",{className:`font-semibold ${o.tone??"text-foreground"}`,children:o.label}
6),e.jsx("span",{title:new Date(n.at).toLocaleString(),children:M(n.at)})]}),(n.actor_name||n.summary)&&e.jsxs("div",{className:"text-xs mt-0.5",children:[n.actor_name&&e.jsxs("span",{className:"font-medium",children:[n.actor_name," "]}),n.summary&&e.jsx("span",{className:"text-muted-foreground",children:n.summary})]}),((c=n.payload)==null?void 0:c.content)&&e.jsx("div",{className:"mt-1 text-xs bg-muted/50 rounded px-2 py-1 break-words whitespace-pre-wrap",children:n.payload.content}),n.payload&&Object.keys(n.payload).length>0&&!n.payload.content&&e.jsxs("details",{className:"mt-0.5",children:[e.jsx("summary",{className:"text-micro text-muted-foreground cursor-pointer",children:"payload"}),e.jsx("pre",{className:"text-micro bg-muted/50 rounded p-1.5 mt-0.5 overflow-x-auto",children:JSON.stringify(n.payload,null,2)})]})]},`${n.kind}-${n.at}-${b}`)})})]})}function _t({jobId:a}){const{data:t,isLoading:h}=A({queryKey:["admin-job-people",a],queryFn:async()=>{const[r,d]=await Promise.all([m.from("job_invitations").select("id, worker_id, status, invited_at, responded_at, invite_method").eq("job_id",a).order("invited_at",{ascending:!1}),m.from("applications").select("id, worker_id, status, apply_source, created_at, status_changed_at").eq("job_id",a).order("created_at",{ascending:!1})]),f=new Set;(r.data??[]).forEach(o=>f.add(o.worker_id)),(d.data??[]).forEach(o=>f.add(o.worker_id));const n=f.size>0?await m.from("profiles").select("user_id, full_name").in("user_id",Array.from(f)):{data:[]},b=new Map((n.data??[]).map(o=>[o.user_id,o.full_name]));return{invitations:(r.data??[]).map(o=>({...o,name:b.get(o.worker_id)})),applications:(d.data??[]).map(o=>({...o,name:b.get(o.worker_id)}))}}});if(h)return e.jsx("div",{className:"text-sm text-muted-foreground py-6 text-center",children:"Loading…"});const l=((t==null?void 0:t.applications)??[]).filter(r=>r.status==="accepted");return e.jsxs("div",{className:"space-y-4",children:[e.jsx(I,{title:"Hired",count:l.length,children:l.length===0?e.jsx(L,{label:"No one hired yet."}):l.map(r=>e.jsx(te,{workerId:r.worker_id,name:r.name,right:e.jsx(q,{variant:"default",className:"text-micro",children:"accepted"})},r.id))}),e.jsx(I,{title:"Applicants",count:(t==null?void 0:t.applications.length)??0,children:((t==null?void 0:t.applications)??[]).length===0?e.jsx(L,{label:"No applications."}):((t==null?void 0:t.applications)??[]).map(r=>e.jsx(te,{workerId:r.worker_id,name:r.name,meta:`${M(r.created_at)}${r.apply_source?` · via ${r.apply_source}`:""}`,right:e.jsx(q,{variant:he(r.status),className:"text-micro",children:r.status})},r.id))}),e.jsx(I,{title:"Invitations",count:(t==null?void 0:t.invitations.length)??0,children:((t==null?void 0:t.invitations)??[]).length===0?e.jsx(L,{label:"No invitations sent."}):((t==null?void 0:t.invitations)??[]).map(r=>e.jsx(te,{workerId:r.worker_id,name:r.name,meta:`${M(r.invited_at)}${r.invite_method?` · ${r.invite_method}`:""}`,right:e.jsx(q,{variant:he(r.status),className:"text-micro",children:r.status})},r.id))})]})}function he(a){return a==="accepted"?"default":a==="rejected"||a==="declined"||a==="expired"?"destructive":a==="withdrawn"?"outline":"secondary"}function I({title:a,count:t,children:h}){return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-baseline justify-between mb-1.5",children:[e.jsx("h3",{className:"text-xs font-semibold uppercase tracking-wider text-muted-foreground",children:a}),e.jsx("span",{className:"text-xs text-muted-foreground",children:t})]}),e.jsx("div",{className:"rounded-lg border border-border divide-y divide-border bg-card",children:h})]})}function L({label:a}){return e.jsx("div",{className:"p-3 text-xs text-muted-foreground text-center",children:a})}function te({workerId:a,name:t,meta:h,right:l}){return e.jsxs("div",{className:"px-3 py-2 flex items-center justify-between gap-2",children:[e.jsxs(Q,{to:`/admin/users?role=worker&id=${a}`,className:"min-w-0 flex-1 group",children:[e.jsx("div",{className:"text-sm font-medium truncate group-hover:underline",children:t??E(a)}),h&&e.jsx("div",{className:"text-caption text-muted-foreground truncate",children:h})]}),e.jsx("div",{className:"shrink-0",children:l})]})}function yt({jobId:a}){const[t,h]=v.useState(""),{data:l,isLoading:r}=A({queryKey:["admin-job-dms",a],queryFn:async()=>{const{data:s,error:c}=await m.rpc("admin_job_messages",{p_job_id:a});if(c)throw c;return s??[]}}),{data:d,isLoading:f}=A({queryKey:["admin-job-group",a],queryFn:async()=>{const{data:s,error:c}=await m.from("job_group_messages").select("id, sender_id, content, created_at").eq("job_id",a).order("created_at",{ascending:!1}).limit(500);if(c)throw c;const j=Array.from(new Set((s??[]).map(x=>x.sender_id))),C=j.length?await m.from("profiles").select("user_id, full_name").in("user_id",j):{data:[]},N=new Map((C.data??[]).map(x=>[x.user_id,x.full_name]));return(s??[]).map(x=>({...x,sender_name:N.get(x.sender_id)}))}}),{data:n,isLoading:b}=A({queryKey:["admin-job-calls",a],queryFn:async()=>{const{data:s,error:c}=await m.from("call_logs").select("id, contractor_id, worker_id, status, duration_seconds, initiated_at, twilio_session_sid").eq("job_id",a).order("initiated_at",{ascending:!1});if(c)throw c;return s??[]}}),o=s=>!t||s.toLowerCase().includes(t.toLowerCase());return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"relative",children:[e.jsx(Ye,{className:"w-3.5 h-3.5 absolute left-2.5 top-2.5 text-muted-foreground"}),e.jsx(Oe,{placeholder:"Search messages…",value:t,onChange:s=>h(s.target.value),className:"pl-8 h-9"})]}),e.jsx(I,{title:"Group chat",count:(d==null?void 0:d.length)??0,children:f?e.jsx(L,{label:"Loading…"}):(d??[]).filter(s=>o(s.content)).length===0?e.jsx(L,{label:"No group messages."}):(d??[]).filter(s=>o(s.content)).map(s=>e.jsxs("div",{className:"px-3 py-2 space-y-0.5",children:[e.jsxs("div",{className:"flex items-center justify-between text-caption text-muted-foreground",children:[e.jsx("span",{className:"font-medium text-foreground",children:s.sender_name??E(s.sender_id)}),e.jsx("span",{children:M(s.created_at)})]}),e.jsx("p",{className:"text-sm whitespace-pre-wrap break-words",children:s.content})]},s.id))}),e.jsx(I,{title:"1:1 messages",count:(l==null?void 0:l.length)??0,children:r?e.jsx(L,{label:"Loading…"}):(l??[]).filter(s=>o(s.content)).length===0?e.jsx(L,{label:"No 1:1 messages tagged to this job."}):(l??[]).filter(s=>o(s.content)).map(s=>e.jsxs("div",{className:"px-3 py-2 space-y-1",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 text-caption text-muted-foreground",children:[e.jsxs("div",{className:"flex items-center gap-1 min-w-0",children:[e.jsx("span",{className:"font-medium text-foreground truncate",children:s.sender_name??E(s.sender_id)}),e.jsx(q,{variant:"outline",className:"text-micro uppercase",children:s.sender_role}),e.jsx("span",{children:"→"}),e.jsx("span",{className:"font-medium text-foreground truncate",children:s.receiver_name??E(s.receiver_id)}),e.jsx(q,{variant:"outline",className:"text-micro uppercase",children:s.receiver_role})]}),e.jsx("span",{className:"shrink-0",children:M(s.created_at)})]}),e.jsx("p",{className:"text-sm whitespace-pre-wrap break-words",children:s.content}),s.is_cold&&e.jsx(q,{variant:"secondary",className:"text-micro",children:"cold"})]},s.id))}),e.jsx(I,{title:"Calls",count:(n==null?void 0:n.length)??0,children:b?e.jsx(L,{label:"Loading…"}):(n??[]).length===0?e.jsx(L,{label:"No calls."}):(n??[]).map(s=>{var c;return e.jsxs("div",{className:"px-3 py-2 flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"text-xs text-muted-foreground font-mono",children:[E(s.contractor_id)," → ",E(s.worker_id)]}),e.jsxs("div",{className:"text-caption text-muted-foreground",children:[s.duration_seconds?`${s.duration_seconds}s`:"—"," · ",((c=s.twilio_session_sid)==null?void 0:c.slice(0,12))??""]})]}),e.jsxs("div",{className:"flex flex-col items-end gap-0.5",children:[e.jsx(q,{variant:s.status==="completed"?"default":["failed","no_answer"].includes(s.status)?"destructive":"secondary",className:"text-micro",children:s.status}),e.jsx("span",{className:"text-micro text-muted-foreground",children:M(s.initiated_at)})]})]},s.id)})})]})}function wt({jobId:a}){const{data:t,isLoading:h}=A({queryKey:["admin-job-stats",a],queryFn:async()=>{const r=(u,G)=>{let J=m.from(u).select("*",{count:"exact",head:!0});return J=G(J),J.then(X=>X.count??0)},[d,f,n,b,o,s,c,j,C,N,x,H]=await Promise.all([r("job_views",u=>u.eq("job_id",a)),r("applications",u=>u.eq("job_id",a)),r("applications",u=>u.eq("job_id",a).eq("status","accepted")),r("applications",u=>u.eq("job_id",a).eq("status","rejected")),r("job_invitations",u=>
6u.eq("job_id",a).eq("status","pending")),r("job_invitations",u=>u.eq("job_id",a).eq("status","accepted")),r("call_logs",u=>u.eq("job_id",a)),r("call_logs",u=>u.eq("job_id",a).eq("status","completed")),r("messages",u=>u.eq("job_id",a)),r("job_group_messages",u=>u.eq("job_id",a)),r("notifications",u=>u.eq("job_id",a)),r("disputes",u=>u.eq("job_id",a))]),K=d>0?Math.round(f/d*100):0;return{views:d,apps:f,accepted:n,rejected:b,invitesPending:o,invitesAccepted:s,calls:c,callsOk:j,dms:C,group:N,notifs:x,disputes:H,conversionRate:K}}});if(h||!t)return e.jsx("div",{className:"text-sm text-muted-foreground py-6 text-center",children:"Loading…"});const l=[{label:"Views",value:t.views},{label:"Applications",value:t.apps},{label:"View → Apply",value:`${t.conversionRate}%`},{label:"Accepted",value:t.accepted,tone:"text-emerald-600"},{label:"Rejected",value:t.rejected,tone:"text-destructive"},{label:"Invites pending",value:t.invitesPending},{label:"Invites accepted",value:t.invitesAccepted,tone:"text-emerald-600"},{label:"Calls",value:t.calls},{label:"Calls connected",value:t.callsOk,tone:"text-emerald-600"},{label:"1:1 messages",value:t.dms},{label:"Group messages",value:t.group},{label:"Notifications",value:t.notifs},{label:"Disputes",value:t.disputes,tone:t.disputes>0?"text-amber-600":""}];return e.jsx("div",{className:"grid grid-cols-2 gap-2",children:l.map(r=>e.jsxs("div",{className:"rounded-xl border border-border bg-card p-3",children:[e.jsx("div",{className:"text-micro uppercase tracking-wider text-muted-foreground",children:r.label}),e.jsx("div",{className:`text-xl font-semibold ${r.tone??""}`,children:r.value})]},r.label))})}const fe=50;function gs(){const a=oe(),[t,h]=v.useState("all"),[l,r]=v.useState("all"),[d,f]=v.useState(""),[n,b]=v.useState(null),[o,s]=v.useState(null),[c,j]=v.useState(null),[C,N]=v.useState(null),[x,H]=v.useState(fe),K=t==="deleted",{data:u,isLoading:G}=A({queryKey:["admin-jobs",t,l,x],queryFn:async()=>{let i=m.from("jobs").select("id, title, status, pay, pay_type, slots, filled_slots, created_at, contractor_id, location, urgency, deleted_at, visibility").order("created_at",{ascending:!1}).limit(x);K?i=i.not("deleted_at","is",null):(i=i.is("deleted_at",null),t!=="all"&&(i=i.eq("status",t))),l!=="all"&&(i=i.eq("visibility",l));const{data:p,error:_}=await i;if(_)throw _;if(p&&p.length>0){const w=[...new Set(p.map(g=>g.contractor_id))],k=p.map(g=>g.id),[z,P,Ke]=await Promise.all([m.from("profiles").select("user_id, full_name").in("user_id",w),m.from("job_invitations").select("job_id, status").in("job_id",k),m.from("applications").select("job_id, status").in("job_id",k)]),Z=z.data,Y=new Map;(P.data??[]).forEach(g=>{const D=Y.get(g.job_id)??{pending:0,accepted:0,declined:0,expired:0};g.status==="pending"?D.pending++:g.status==="accepted"?D.accepted++:g.status==="declined"?D.declined++:g.status==="expired"&&D.expired++,Y.set(g.job_id,D)});const ee=new Map;(Ke.data??[]).forEach(g=>{const D=ee.get(g.job_id)??{total:0,pending:0};D.total++,g.status==="pending"&&D.pending++,ee.set(g.job_id,D)});const Re=new Map((Z==null?void 0:Z.map(g=>[g.user_id,g.full_name]))??[]);return p.map(g=>({...g,contractor_name:Re.get(g.contractor_id)||"Unknown",invitation_counts:Y.get(g.id)??{pending:0,accepted:0,declined:0,expired:0},application_counts:ee.get(g.id)??{total:0,pending:0}}))}return(p==null?void 0:p.map(w=>({...w,contractor_name:"Unknown",invitation_counts:{pending:0,accepted:0,declined:0,expired:0},application_counts:{total:0,pending:0}})))??[]}});v.useEffect(()=>{const i=m.channel(`admin-jobs-rt-${Math.random().toString(36).slice(2,8)}`).on("postgres_changes",{event:"*",schema:"public",table:"jobs"},()=>{a.invalidateQueries({queryKey:["admin-jobs"]})}).subscribe();return()=>{m.removeChannel(i)}},[a]);const J=U({mutationFn:async({id:i,status:p})=>{const _={status:p};p==="closed"?_.closed_at=new Date().toISOString():_.closed_at=null;const{error:w}=await m.from("jobs").update(_).eq("id",i);if(w)throw w;try{const{data:{user:k}}=await m.auth.getUser();k&&await m.from("admin_activity_log").insert({admin_id:k.id,action:"job.
6status_change",details:{job_id:i,new_status:p}})}catch{}},onSuccess:()=>{a.invalidateQueries({queryKey:["admin-jobs"]}),a.invalidateQueries({queryKey:["admin-stats"]}),y.success("Job status updated"),b(null)},onError:i=>y.error(i.message)}),X=U({mutationFn:async i=>{const{data:p}=await m.from("applications").select("id").eq("job_id",i).eq("status","accepted").limit(1),_=(p??[]).length>0,{error:w}=await m.from("jobs").update({deleted_at:new Date().toISOString(),..._?{needs_closeout:!0}:{}}).eq("id",i);if(w)throw w;try{const{data:{user:k}}=await m.auth.getUser();k&&await m.from("admin_activity_log").insert({admin_id:k.id,action:"job.soft_delete",details:{job_id:i,status_untouched:!0,flagged_needs_closeout:_}})}catch{}},onSuccess:()=>{a.invalidateQueries({queryKey:["admin-jobs"]}),a.invalidateQueries({queryKey:["admin-stats"]}),y.success("Job hidden — status and completion data left intact"),s(null)},onError:i=>y.error(i.message)}),de=U({mutationFn:async i=>{const{error:p}=await m.from("jobs").update({deleted_at:null}).eq("id",i);if(p)throw p;try{const{data:{user:_}}=await m.auth.getUser();_&&await m.from("admin_activity_log").insert({admin_id:_.id,action:"job.restore",details:{job_id:i}})}catch{}},onSuccess:()=>{a.invalidateQueries({queryKey:["admin-jobs"]}),a.invalidateQueries({queryKey:["admin-stats"]}),y.success("Job restored")},onError:i=>y.error(i.message)}),Fe=i=>{switch(i){case"active":return"bg-emerald-500/15 text-emerald-600 dark:text-emerald-400";case"filled":return"bg-blue-500/15 text-blue-600 dark:text-blue-400";case"closed":return"bg-muted text-muted-foreground";case"draft":return"bg-yellow-500/15 text-yellow-700 dark:text-yellow-400";default:return""}},$=v.useMemo(()=>{if(!u||!d.trim())return u;const i=d.toLowerCase();return u.filter(p=>p.title.toLowerCase().includes(i)||p.contractor_name.toLowerCase().includes(i)||(p.location||"").toLowerCase().includes(i)||p.id.toLowerCase().includes(i))},[u,d]),Ee=i=>{const p=[];return i!=="active"&&p.push({label:"Set Active",value:"active",icon:e.jsx(ct,{className:"w-3.5 h-3.5"})}),i!=="closed"&&p.push({label:"Close Job",value:"closed",icon:e.jsx(F,{className:"w-3.5 h-3.5"})}),i!=="draft"&&p.push({label:"Revert to Draft",value:"draft",icon:e.jsx(dt,{className:"w-3.5 h-3.5"})}),p};return e.jsxs(tt,{title:"Jobs",subtitle:"Tap a row to open the inspector.",actions:e.jsxs(e.Fragment,{children:[e.jsxs(se,{value:t,onValueChange:h,children:[e.jsx(ae,{className:"w-36 h-9",children:e.jsx(ie,{placeholder:"Filter status"})}),e.jsxs(re,{children:[e.jsx(S,{value:"all",children:"All Statuses"}),e.jsx(S,{value:"active",children:"Active"}),e.jsx(S,{value:"closed",children:"Closed"}),e.jsx(S,{value:"draft",children:"Draft"}),e.jsx(S,{value:"deleted",children:"Deleted"})]})]}),e.jsxs(se,{value:l,onValueChange:r,children:[e.jsx(ae,{className:"w-36 h-9",children:e.jsx(ie,{placeholder:"Visibility"})}),e.jsxs(re,{children:[e.jsx(S,{value:"all",children:"All Visibility"}),e.jsx(S,{value:"public",children:"Public"}),e.jsx(S,{value:"private",children:"Private"}),e.jsx(S,{value:"invite_only",children:"Invite only"})]})]})]}),children:[e.jsx(We,{value:d,onChange:f,placeholder:"Search title, contractor, location, or job id…"}),G?e.jsx(at,{rows:6}):($==null?void 0:$.length)===0?e.jsx(it,{Icon:rt,title:"No jobs found",description:"Try clearing the status/visibility filters or searching a different term."}):e.jsxs("div",{className:"space-y-2",children:[$==null?void 0:$.map(i=>{var p,_,w,k,z;return e.jsx(st,{className:`cursor-pointer transition hover:bg-muted/30 ${K?"opacity-60":""}`,onClick:()=>N(i.id),children:e.jsx("div",{className:"p-4",children:e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"text-sm font-medium text-foreground truncate",children:i.title}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-0.5",children:["by ",i.contractor_name," · ",i.location||"No location"]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["$",Number(i.pay).toFixed(0),"/",i.pay_type," · ",i.filled_slots,"/",i.slots," filled"]}),i.visibility==="private"&&e.jsxs("p",{className:"text-caption text-muted-foreground mt-0.5",children:[((p=i.inv
6itation_counts)==null?void 0:p.pending)??0," pending · ",((_=i.invitation_counts)==null?void 0:_.accepted)??0," accepted"]})]}),e.jsxs("div",{className:"flex items-center gap-2 shrink-0",onClick:P=>P.stopPropagation(),children:[e.jsxs(T,{variant:"outline",size:"sm",className:"h-7 text-xs gap-1",onClick:()=>j({id:i.id,title:i.title}),children:[e.jsx(ce,{className:"w-3.5 h-3.5"}),((w=i.application_counts)==null?void 0:w.total)??0,(((k=i.application_counts)==null?void 0:k.pending)??0)>0&&e.jsxs("span",{className:"ml-0.5 text-micro font-semibold text-yellow-600 dark:text-yellow-400",children:["·",(z=i.application_counts)==null?void 0:z.pending," pend"]})]}),i.visibility==="private"&&e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-primary/10 border border-primary/20 text-primary text-caption font-semibold",children:[e.jsx(nt,{size:10}),"Private"]}),i.visibility==="invite_only"&&e.jsx("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-muted border border-border text-muted-foreground text-caption font-semibold",children:"Invite only"}),K?e.jsx(q,{variant:"outline",className:"text-micro border-destructive/30 text-destructive",children:"Deleted"}):e.jsx("span",{className:`text-micro px-2 py-0.5 rounded-full font-medium uppercase ${Fe(i.status)}`,children:i.status}),i.urgency!=="normal"&&e.jsx(q,{variant:"destructive",className:"text-micro",children:i.urgency}),K?e.jsxs(T,{variant:"outline",size:"sm",className:"h-7 text-xs gap-1",onClick:()=>de.mutate(i.id),disabled:de.isPending,children:[e.jsx(lt,{className:"w-3.5 h-3.5"}),"Restore"]}):e.jsxs(Qe,{children:[e.jsx(Ue,{asChild:!0,children:e.jsx(T,{variant:"ghost",size:"sm",className:"h-7 w-7 p-0",children:e.jsx(ot,{className:"w-4 h-4"})})}),e.jsxs(ze,{align:"end",className:"w-44",children:[Ee(i.status).map(P=>e.jsxs(me,{onClick:()=>J.mutate({id:i.id,status:P.value}),className:"gap-2 text-xs",children:[P.icon,P.label]},P.value)),e.jsx(Be,{}),e.jsxs(me,{onClick:()=>s({id:i.id,title:i.title}),className:"gap-2 text-xs text-destructive focus:text-destructive",children:[e.jsx(De,{className:"w-3.5 h-3.5"}),"Remove Job"]})]})]})]})]})})},i.id)}),$&&$.length>=x&&e.jsx("div",{className:"pt-2 flex justify-center",children:e.jsx(T,{variant:"outline",size:"sm",onClick:()=>H(i=>i+fe),children:"Load more"})})]}),e.jsx(ye,{open:!!o,onOpenChange:i=>!i&&s(null),children:e.jsxs(we,{children:[e.jsxs(Ne,{children:[e.jsx(ke,{children:"Remove this job?"}),e.jsxs(Ce,{children:['"',o==null?void 0:o.title,'" will be hidden from all users. Its status and completion records are left untouched — if workers were hired, the job is flagged for closeout so the contractor still captures outcomes. Reversible from the Deleted filter.']})]}),e.jsxs(Se,{children:[e.jsx(qe,{children:"Cancel"}),e.jsx(Ae,{onClick:()=>o&&X.mutate(o.id),className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",children:"Remove"})]})]})}),e.jsx(xt,{jobId:(c==null?void 0:c.id)??null,jobTitle:(c==null?void 0:c.title)??"",onOpenChange:i=>!i&&j(null)}),e.jsx(gt,{jobId:C,onOpenChange:i=>!i&&N(null)})]})}export{gs 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.