PageSourceSearch

https://harbor-os.com/assets/AdminCategoryReview-E5T_cjye.js

js harbor-os.com collected 2026-10-02 01:32:39 UTC 7,671 bytes, 1 lines download raw bytes

1import{by as z,r as l,g as D,i as I,j as e,bA as y,cm as E,$ as C,K as b,c2 as q}from"./vendor-B3bqREfz.js";import{u as P,T as $,o as K,p as x,r as M,C as B,d as O,g as i,B as c,D as _,h as L,j as Q,k as U,m as V,f as G}from"./index-BHZdkTHk.js";import{T as H}from"./textarea-BFtGXtJd.js";import{S as W,a as X,b as Y,c as J,d as Z}from"./select-CdK0CD7c.js";import{S as ee}from"./skeleton-BoAKzVms.js";const se=["boat galley","marine grade","marine rated","vessel","yacht","boat kitchen","offshore","marine stainless","saltwater","bilge","anchor","port side","starboard","hull","keel","mast","dock","mooring","marina","haul out","boat lift","davit","teak deck"],ae=["boats","parts","engines","electronics","safety_gear","trailers","fishing_gear","watersports","general","clothing","tools","food"];function S(o,g){const r=`${o} ${g}`.toLowerCase();return se.some(m=>r.includes(m))}function ce(){const{toast:o}=P(),g=z(),[r,m]=l.useState("pending"),[a,d]=l.useState(null),[u,h]=l.useState(""),[N,p]=l.useState(""),[t,f]=l.useState(null),{data:w=[],isLoading:k}=D({queryKey:["/api/admin/category-review",r],queryFn:async()=>{const s=await fetch(`/api/admin/category-review?status=${r}`);if(!s.ok)throw new Error("Failed to fetch");return s.json()}}),v=I({mutationFn:async({id:s,action:n,finalCategory:R,adminNotes:F})=>G("POST",`/api/admin/category-review/${s}/action`,{action:n,finalCategory:R,adminNotes:F}),onSuccess:()=>{o({title:"Action recorded",description:"Review queue updated."}),g.invalidateQueries({queryKey:["/api/admin/category-review"]}),d(null),f(null),h(""),p("")},onError:s=>{o({title:"Error",description:s.message,variant:"destructive"})}});function j(s,n){d(s),f(n),h(s.review.suggestedCategory||s.productCategory||""),p("")}function A(){!a||!t||v.mutate({id:a.review.id,action:t,finalCategory:u,adminNotes:N})}a!=null&&a.review.aiConfidenceScore&&parseFloat(a.review.aiConfidenceScore);const T=a?S(a.productName||"",a.productCategory||""):!1;return e.jsxs("div",{className:"container mx-auto px-4 py-8",children:[e.jsxs("div",{className:"mb-6",children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900",children:"Category Review Queue"}),e.jsx("p",{className:"text-sm text-gray-500 mt-1",children:"Review and approve product category assignments. Items with marine keywords are auto-classified."})]}),e.jsxs($,{value:r,onValueChange:m,children:[e.jsxs(K,{className:"mb-6",children:[e.jsx(x,{value:"pending",children:"Pending"}),e.jsx(x,{value:"approved",children:"Approved"}),e.jsx(x,{value:"recategorized",children:"Recategorized"}),e.jsx(x,{value:"rejected",children:"Rejected"})]}),e.jsx(M,{value:r,children:k?e.jsx("div",{className:"grid gap-4",children:Array.from({length:5}).map((s,n)=>e.jsx(ee,{className:"h-24 w-full"},n))}):w.length===0?e.jsxs("div",{className:"text-center py-12 text-gray-400",children:[e.jsx(y,{className:"h-10 w-10 mx-auto mb-3 opacity-30"}),e.jsxs("p",{children:["No items in ",r," queue."]})]}):e.jsx("div",{className:"space-y-4",children:w.map(s=>{const n=S(s.productName||"",s.productCategory||"");return e.jsx(B,{className:"hover:shadow-sm transition-shadow",children:e.jsx(O,{className:"p-4",children:e.jsxs("div",{className:"flex items-start gap-4",children:[e.jsx("div",{className:"w-16 h-16 flex-shrink-0 rounded bg-gray-100 overflow-hidden",children:s.productImageUrl?e.jsx("img",{src:s.productImageUrl,alt:"",className:"w-full h-full object-cover"}):e.jsx("div",{className:"w-full h-full flex items-center justify-center",children:e.jsx(E,{className:"h-6 w-6 text-gray-300"})})}),e.jsx("div",{className:"flex-1 min-w-0",children:e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsxs("div",{children:[e.jsx("p",{className:"font-medium text-gray-900 text-sm truncate",children:s.productName||`Product #${s.review.productId}`}),e.jsxs("div",{className:"flex items-center gap-2 mt-1 flex-wrap",children:[e.jsxs(i,{variant:"outline",className:"text-xs",children:["Current: ",s.productCategory||"none"]}),s.review.suggestedCategory&&e.jsxs(i,{variant:"secondary",className:"text-xs",children:["Suggested: ",s.review.suggestedCategory]}),s.review.aiConfidenceScore&&e.jsxs(i,{className:`text-xs ${parseFloat(s.review.aiConfidenceScore)>=.8?"bg-green-100 text-green-700":parseFloat(s.review.aiConfidenceScore)>=.5?"bg-yellow-100 text-yellow-700":"bg-red-100 text-red-700"}`,variant:"outline",children:["AI: ",(parseFloat(s.review.aiConfidenceScore)*100).toFixed(0),"%"]}),n&&e.jsx(i,{className:"text-xs bg-blue-100 text-blue-700",variant:"outline",children:"Marine keyword match"})]}),s.review.aiReasoning&&e.jsx("p",{className:"text-xs text-gray-500 mt-1 line-clamp-1",children:s.review.aiReasoning}),e.jsxs("p",{className:"text-xs text-gray-400 mt-0.5",children:["Submitted by ",s.submitterUsername||"system"," · ",new Date(s.review.createdAt).toLocaleDateString()]})]}),r==="pending"&&e.jsxs("div",{className:"flex gap-2 flex-shrink-0",children:[e.jsxs(c,{size:"sm",variant:"outline",className:"h-8 text-xs text-green-600 border-green-200 hover:bg-green-50",onClick:()=>j(s,"approve"),children:[e.jsx(y,{className:"h-3.5 w-3.5 mr-1"})," Approve"]}),e.jsxs(c,{size:"sm",variant:"outline",className:"h-8 text-xs text-blue-600 border-blue-200 hover:bg-blue-50",onClick:()=>j(s,"recategorize"),children:[e.jsx(C,{className:"h-3.5 w-3.5 mr-1"})," Recategorize"]}),e.jsxs(c,{size:"sm",variant:"outline",className:"h-8 text-xs text-red-600 border-red-200 hover:bg-red-50",onClick:()=>j(s,"reject"),children:[e.jsx(b,{className:"h-3.5 w-3.5 mr-1"})," Reject"]})]})]})})]})})},s.review.id)})})})]}),e.jsx(_,{open:!!a,onOpenChange:s=>!s&&d(null),children:e.jsxs(L,{className:"max-w-md",children:[e.jsx(Q,{children:e.jsxs(U,{className:"flex items-center gap-2",children:[t==="approve"&&e.jsxs(e.Fragment,{children:[e.jsx(y,{className:"h-5 w-5 text-green-500"})," Approve Category"]}),t==="reject"&&e.jsxs(e.Fragment,{children:[e.jsx(b,{className:"h-5 w-5 text-red-500"})," Reject Category"]}),t==="recategorize"&&e.jsxs(e.Fragment,{children:[e.jsx(C,{className:"h-5 w-5 text-blue-500"})," Recategorize Product"]})]})}),a&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"p-3 bg-gray-50 rounded-lg",children:[e.jsx("p",{className:"font-medium text-sm",children:a.productName}),e.jsxs("div",{className:"flex gap-2 mt-1 flex-wrap",children:[e.jsxs(i,{variant:"outline",className:"text-xs",children:["Current: ",a.productCategory||"none"]}),a.review.suggestedCategory&&e.jsxs(i,{variant:"secondary",className:"text-xs",children:["Suggested: ",a.review.suggestedCategory]})]}),T&&e.jsxs("div",{className:"flex items-center gap-1 mt-2 text-xs text-blue-600",children:[e.jsx(q,{className:"h-3.5 w-3.5"}),"Marine keyword detected — auto-classifiable"]})]}),t==="recategorize"&&e.jsxs("div",{className:"space-y-2",children:[e.jsx("label",{className:"text-sm font-medium",children:"Final Category"}),e.jsxs(W,{value:u,onValueChange:h,children:[e.jsx(X,{children:e.jsx(Y,{placeholder:"Select category..."})}),e.jsx(J,{children:ae.map(s=>e.jsx(Z,{value:s,children:s},s))})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("label",{className:"text-sm font-medium",children:["Admin Notes ",t!=="recategorize"&&"(optional)"]}),e.jsx(H,{value:N,onChange:s=>p(s.target.value),placeholder:"Internal notes for this decision...",rows:3})]})]}),e.jsxs(V,{children:[e.jsx(c,{variant:"outline",onClick:()=>d(null),children:"Cancel"}),e.jsx(c,{onClick:A,disabled:v.isPending||t==="recategorize"&&!u,className:t==="approve"?"bg-green-600 hover:bg-green-700":t==="reject"?"bg-red-600 hover:bg-red-700":"",children:v.isPending?"Saving...":"Confirm"})]})]})})]})}export{ce 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.