1import{c as ae,r as l,l as f,h as v,j as t,x,ax as b,ac as ne,X as re,J as oe,L as O,n as ie,aT as le,aU as de,bf as ce,b8 as ue,bg as me,a as he,C as pe,bh as _e,M as fe,ad as xe}from"./index-f--GfbGy.js";import{P as ge}from"./PageHeader-mOtZbH7v.js";import{T as je,a as we,b as Q}from"./tabs-CmG3F9Ix.js";import{R as ye}from"./refresh-cw-DmIXRYyu.js";import{E as ve}from"./external-link-7pLn2YZK.js";import{L as Ne}from"./link-2-D1YoXTN_.js";const k={new:"New",under_review:"Under review",matched:"Matched",closed:"Closed"};function H(s){return s==="new"?"default":s==="under_review"?"secondary":"outline"}function V(s){const r=(Date.now()-new Date(s).getTime())/1e3;return r<60?`${Math.max(1,Math.round(r))}s`:r<3600?`${Math.round(r/60)}m`:r<86400?`${Math.round(r/3600)}h`:`${Math.round(r/86400)}d`}function X(s){return s&&s.trim().split(/\s+/)[0]||"Anonymous"}function be(s,r){const i=s.metadata_json??{},u=Array.isArray(s.photos_json)?s.photos_json:[],g=u[0]?.url??u[0]??null,c=i.title||i.name||(s.description?s.description.slice(0,80):null)||(s.category?`Lost ${s.category}`:"Lost item");return{id:s.id,kind:"lost",title:c,reporter:{name:X(s.reporter_name??i.reporter_first_name),city:i.city??null},category:s.category,location:s.last_seen_location,created_at:s.created_at,photo_url:typeof g=="string"?g:null,raw:s,status:r?.status??"new",close_reason:r?.close_reason??null,matched_object_id:r?.matched_object_id??null,matched_lost_report_id:r?.matched_lost_report_id??null}}function ke(s,r){const i=s.parsed??{},u=s.vision_attributes??{},g=i.title||i.name||u.short_label||u.label||(s.raw_input?s.raw_input.slice(0,80):null)||"Found item",c=i.city||i.location_city||(s.resolved_venue_name??null);return{id:s.id,kind:"found",title:g,reporter:{name:X(i.reporter_first_name??i.first_name??s.email?.split("@")[0]),city:typeof c=="string"?c:null},category:i.category??null,location:s.resolved_venue_name??i.location??null,created_at:s.created_at,photo_url:s.photo_url??s.handoff_photo_url??null,raw:s,status:r?.status??"new",close_reason:r?.close_reason??null,matched_object_id:r?.matched_object_id??null,matched_lost_report_id:r?.matched_lost_report_id??null}}function Te(){const[s,r]=ae(),i=s.get("tab")==="found"?"found":"lost",[u,g]=l.useState(s.get("q")??""),[c,J]=l.useState(s.get("status")??"all"),[L,q]=l.useState([]),[R,E]=l.useState([]),[$,P]=l.useState(!0),[n,M]=l.useState(null),[A,T]=l.useState([]),[D,z]=l.useState(!1);l.useEffect(()=>{const e=new URLSearchParams(s);e.set("tab",i),c!=="all"?e.set("status",c):e.delete("status"),r(e,{replace:!0})},[i,c]),l.useEffect(()=>{const e=window.setTimeout(()=>{const a=new URLSearchParams(s);u?a.set("q",u):a.delete("q"),r(a,{replace:!0})},300);return()=>window.clearTimeout(e)},[u]);const N=l.useCallback(async()=>{P(!0);try{const[e,a]=await Promise.all([f.from("lost_reports").select("id, description, category, last_seen_location, last_seen_lat, last_seen_lng, lost_at, reporter_name, reporter_user_id, status, metadata_json, photos_json, created_at").is("deleted_at",null).order("created_at",{ascending:!1}).limit(200),f.from("smart_intake_session").select("id, intent, parsed, raw_input, vision_attributes, resolved_venue_name, photo_url, handoff_photo_url, created_at, finalized_at, custody").eq("intent","found").order("created_at",{ascending:!1}).limit(200)]),m=(e.data??[]).map(d=>d.id),w=(a.data??[]).map(d=>d.id),p=[...m,...w];let _={};if(p.length){const{data:d}=await f.from("report_admin_state").select("kind, report_id, status, close_reason, matched_object_id, matched_lost_report_id").in("report_id",p);for(const h of d??[])_[`${h.kind}:${h.report_id}`]=h}q((e.data??[]).map(d=>be(d,_[`lost:${d.id}`]))),E((a.data??[]).map(d=>ke(d,_[`found:${d.id}`])))}catch(e){v.error(e?.message??"Failed to load reports")}finally{P(!1)}},[]);l.useEffect(()=>{N()},[N]);const j=l.useRef(null);l.useEffect(()=>{const e=()=>{j.current||(j.current=window.setTimeout(()=>{j.current=null,N()},1500))},a=f.channel("admin-reports").on("postgres_changes",{event:"INSERT",schema:"public",table:"lost_reports"},e).on("postgres_changes",{event:"INSERT",schema:"public",table:"smart_intake_session",filter:"intent=eq.found"},e).subscribe();return()=>{j.current&&(clearTimeout(j.current),j.current=null),f.removeChannel(a)}},[N]);const I=i==="lost"?L:R,U=l.useMemo(()=>I.filter(e=>{if(c!=="all"&&e.status!==c)return!1;if(u){const a=u.toLowerCase();if(!`${e.title} ${e.reporter.name} ${e.reporter.city??""} ${e.category??""} ${e.location??""}`.toLowerCase().includes(a))return!1}return!0}),[I,u,c]),C=l.useMemo(()=>({lost:L.filter(e=>e.status==="new").length,found:R.filter(e=>e.status==="new").length}),[L,R]),W=l.useCallback(async e=>{if(e.kind!=="lost"){T([]);return}z(!0);try{const a=(e.raw?.metadata_json?.city??e.location??"").toString().split(",")[0]?.trim(),m=e.category,w=new Date(Date.now()-1e3*60*60*24*30).toISOString();let p=f.from("feed_items").select("id, title, city, reported_at, primary_image_url, status_kind, moderation_status").eq("moderation_status","approved").eq("status_kind","foun
1d").gte("reported_at",w).order("reported_at",{ascending:!1}).limit(40);a&&(p=p.ilike("city",`%${a}%`)),m&&(p=p.eq("category",m));let _=f.from("lost_reports").select("id, description, last_seen_location, lost_at, created_at, metadata_json").neq("id",e.id).is("deleted_at",null).gte("created_at",w).order("created_at",{ascending:!1}).limit(40);m&&(_=_.eq("category",m));const[d,h]=await Promise.all([p,_]),y=(e.title||"").toLowerCase().split(/\W+/).filter(o=>o.length>3),B=o=>y.reduce((S,se)=>S+(o.toLowerCase().includes(se)?1:0),0),Z=(d.data??[]).map(o=>({kind:"feed_item",id:o.id,title:o.title,city:o.city,date:o.reported_at,primary_image_url:o.primary_image_url,_s:B(o.title??"")})),ee=(h.data??[]).map(o=>({kind:"lost_report",id:o.id,title:o.metadata_json?.title||(o.description??"").slice(0,80)||"Lost item",city:o.metadata_json?.city??null,date:o.created_at,_s:B(o.metadata_json?.title||o.description||"")})),te=[...Z,...ee].sort((o,S)=>S._s-o._s||+new Date(S.date)-+new Date(o.date)).slice(0,3);T(te)}finally{z(!1)}},[]);function G(e){M(e),T([]),e.kind==="lost"&&W(e)}async function F(e,a,m={}){const{data:{user:w}}=await f.auth.getUser(),p={kind:e.kind,report_id:e.id,status:a,reviewer_user_id:w?.id??null,...m},{error:_}=await f.from("report_admin_state").upsert(p,{onConflict:"kind,report_id"});if(_)return v.error(_.message);v.success(`Marked ${k[a].toLowerCase()}`);const d=h=>h.map(y=>y.id===e.id&&y.kind===e.kind?{...y,status:a,...m}:y);e.kind==="lost"?q(d):E(d),M(h=>h&&h.id===e.id?{...h,status:a,...m}:h)}async function K(e,a){const m=a.kind==="feed_item"?{matched_object_id:a.id,matched_lost_report_id:null}:{matched_lost_report_id:a.id,matched_object_id:null};await F(e,"matched",m),e.kind==="lost"&&await f.from("lost_reports").update({status:"matched"}).eq("id",e.id),v.success("Match confirmed â both sides notified")}async function Y(e){const a=window.prompt("Reason for closing?","Resolved");a&&await F(e,"closed",{close_reason:a})}return t.jsxs("div",{className:"space-y-4",children:[t.jsx(ge,{title:"Reports",description:"User-submitted lost and found reports from lo.st",actions:t.jsxs(x,{variant:"outline",size:"sm",onClick:()=>N(),children:[t.jsx(ye,{className:"me-2 h-3.5 w-3.5"})," Refresh"]})}),t.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[t.jsx(je,{value:i,onValueChange:e=>r(a=>(a.set("tab",e),a),{replace:!0}),children:t.jsxs(we,{children:[t.jsxs(Q,{value:"lost",children:["Lost reports ",C.lost>0&&t.jsx(b,{variant:"secondary",className:"ms-2",children:C.lost})]}),t.jsxs(Q,{value:"found",children:["Found reports ",C.found>0&&t.jsx(b,{variant:"secondary",className:"ms-2",children:C.found})]})]})}),t.jsxs("div",{className:"relative ms-auto min-w-[260px] flex-1 max-w-md",children:[t.jsx(ne,{className:"pointer-events-none absolute start-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"}),t.jsx(re,{className:"ps-9",placeholder:"Search reporter, title, cityâ¦",value:u,onChange:e=>g(e.target.value)})]}),t.jsx("div",{className:"flex items-center gap-1 rounded-lg bg-surface-sunken p-1",children:["all","new","under_review","matched","closed"].map(e=>t.jsx("button",{onClick:()=>J(e),className:`rounded-md px-2.5 py-1 text-xs font-medium transition ${c===e?"bg-background shadow-card text-foreground":"text-muted-foreground hover:text-foreground"}`,children:e==="all"?"All":k[e]},e))})]}),t.jsxs(oe,{className:"divide-y overflow-hidden",children:[$&&t.jsxs("div",{className:"flex items-center justify-center p-12 text-sm text-muted-foreground",children:[t.jsx(O,{className:"me-2 h-4 w-4 animate-spin"})," Loading reportsâ¦"]}),!$&&U.length===0&&t.jsxs("div",{className:"p-12 text-center text-sm text-muted-foreground",children:["No ",i," reports",c!=="all"?` with status "${k[c]}"`:"","."]}),!$&&U.map(e=>t.jsxs("button",{onClick:()=>G(e),className:"flex w-full items-start gap-3 p-3 text-start transition hover:bg-surface-sunken/40",children:[e.photo_url?t.jsx("img",{src:e.photo_url,alt:"",className:"h-14 w-14 shrink-0 rounded object-cover bg-muted"}):t.jsx("div",{className:"h-14 w-14 shrink-0 rounded bg-surface-sunken"}),t.jsxs("div",{className:"min-w-0 flex-1",children:[t.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[t.jsx("span",{className:"truncate font-medium",children:e.title}),e.category&&t.jsx(b,{variant:"outline",className:"text-xs",children:e.category}),t.jsx(b,{variant:H(e.status),className:"text-xs",children:k[e.status]})]}),t.jsxs("div",{className:"mt-0.5 truncate text-xs text-muted-foreground",children:[e.reporter.name,e.reporter.city?` · ${e.reporter.city}`:"",e.location?t.jsxs(t.Fragment,{children:[" · ",t.jsx(ie,{className:"inline h-3 w-3"})," ",e.location]}):null]})]}),t.jsx("div",{className:"shrink-0 text-end",children:t.jsx("div",{className:"font-mono text-xs text-muted-foreground",children:V(e.created_at)})})]},`${e.kind}:${e.id}`))]}),t.jsx(le,{open:!!n,onOpenChange:e=>!e&&M(null),children:t.jsx(de,{className:"w-full sm:max-w-xl overflow-y-auto",children:n&&t.jsxs(t.Fragment,{children:[t.jsxs(ce,{children:[t.jsxs(ue,{className:"flex items-center gap-2",children:[n.title,t.jsx(b,{variant:H(n.status),children:k[n.status]})]}),t.jsxs(me,{children:["Reported by ",n.reporter.name,n.reporter.city?` from ${n.reporter.city}
1`:""," ·"," ",new Date(n.created_at).toLocaleString()]})]}),t.jsxs("div",{className:"mt-5 space-y-5 text-sm",children:[n.photo_url&&t.jsx("img",{src:n.photo_url,alt:"",className:"w-full rounded-lg bg-muted object-cover"}),t.jsxs("dl",{className:"grid grid-cols-3 gap-x-3 gap-y-2",children:[n.category&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-xs text-muted-foreground",children:"Category"}),t.jsx("dd",{className:"col-span-2",children:n.category})]}),n.location&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-xs text-muted-foreground",children:"Location"}),t.jsx("dd",{className:"col-span-2",children:n.location})]}),n.kind==="lost"&&n.raw.description&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-xs text-muted-foreground",children:"Description"}),t.jsx("dd",{className:"col-span-2 whitespace-pre-wrap",children:n.raw.description})]}),n.kind==="found"&&n.raw.raw_input&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{className:"text-xs text-muted-foreground",children:"Description"}),t.jsx("dd",{className:"col-span-2 whitespace-pre-wrap",children:n.raw.raw_input})]})]}),n.kind==="lost"&&t.jsxs("div",{children:[t.jsxs("div",{className:"mb-2 flex items-center justify-between",children:[t.jsx("h3",{className:"text-sm font-semibold",children:"Likely matches"}),D&&t.jsx(O,{className:"h-3.5 w-3.5 animate-spin text-muted-foreground"})]}),A.length===0&&!D&&t.jsx("p",{className:"text-xs text-muted-foreground",children:"No candidate matches in the last 30 days."}),t.jsx("div",{className:"space-y-2",children:A.map(e=>t.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-border-subtle bg-surface p-2",children:[e.primary_image_url?t.jsx("img",{src:e.primary_image_url,alt:"",className:"h-10 w-10 rounded object-cover bg-muted"}):t.jsx("div",{className:"h-10 w-10 rounded bg-surface-sunken"}),t.jsxs("div",{className:"min-w-0 flex-1",children:[t.jsx("div",{className:"truncate text-sm font-medium",children:e.title}),t.jsxs("div",{className:"text-xs text-muted-foreground",children:[e.kind==="feed_item"?"Feed item":"Other lost report",e.city?` · ${e.city}`:""," · ",V(e.date)," ago"]})]}),t.jsx(x,{size:"sm",variant:"outline",asChild:!0,children:t.jsx(he,{to:e.kind==="feed_item"?`/feed/i/${e.id}`:"/admin/reports?tab=lost",target:"_blank",children:t.jsx(ve,{className:"h-3.5 w-3.5"})})}),t.jsxs(x,{size:"sm",onClick:()=>K(n,e),children:[t.jsx(pe,{className:"me-1 h-3.5 w-3.5"})," Confirm"]})]},`${e.kind}:${e.id}`))})]})]}),t.jsxs(_e,{className:"mt-6 flex-col gap-2 sm:flex-row sm:justify-end",children:[t.jsx(x,{variant:"outline",size:"sm",onClick:()=>F(n,"under_review"),children:"Mark under review"}),t.jsxs(x,{variant:"outline",size:"sm",onClick:()=>v.info("Reply UI coming soon"),children:[t.jsx(fe,{className:"me-1.5 h-3.5 w-3.5"})," Reply"]}),t.jsxs(x,{variant:"outline",size:"sm",onClick:()=>v.info("Publish-to-feed coming soon"),children:[t.jsx(Ne,{className:"me-1.5 h-3.5 w-3.5"})," Publish to feed"]}),t.jsxs(x,{variant:"destructive",size:"sm",onClick:()=>Y(n),children:[t.jsx(xe,{className:"me-1.5 h-3.5 w-3.5"})," Close"]})]})]})})})]})}export{Te 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.