PageSourceSearch

https://tosot.ai/assets/sn-reference-rules-CIwpczAX.js

js tosot.ai collected 2026-10-05 13:09:12 UTC 10,534 bytes, 1 lines download raw bytes

1import{k as C,j as t,r as i,g as v}from"./index-CLsq8RhH.js";import{f as A}from"./formatters-98ayU2_q.js";function I({value:e,onChange:a,endpoint:l,placeholder:c,allLabel:m}){const[b,f]=i.useState([]);return i.useEffect(()=>{let d=!0;return v.get(l).then(h=>{d&&f((h.data??[]).map(x=>{if(typeof x=="string")return{value:x,label:x};const u=x;return{value:String(u.value??u.id??""),label:String(u.label??u.title??u.value??u.id??"")}}))}),()=>{d=!1}},[l]),t.jsxs("select",{className:"w-full rounded border px-3 py-2 text-sm",value:String(e??""),onChange:d=>a(d.target.value),children:[t.jsx("option",{value:"",children:m??c}),b.map(d=>t.jsx("option",{value:d.value,children:d.label},d.value))]})}function L({value:e,onChange:a,brandName:l,currentRuleId:c}){const m=i.useMemo(()=>new Set(Array.isArray(e)?e.map(String):typeof e=="string"&&e?[e]:[]),[e]),[b,f]=i.useState([]),[d,h]=i.useState(""),[x,u]=i.useState("AVAILABLE"),[j,p]=i.useState(null);i.useEffect(()=>{let r=!0;const o=new URLSearchParams;return o.set("brandName",l),c&&o.set("currentRuleId",c),p(null),v.get(`/api/admin/r/sn-reference-rules/category-options?${o.toString()}`).then(g=>{r&&f(g.data??[])}).catch(g=>{r&&p(g instanceof Error?g.message:"Failed to load categories.")}),()=>{r=!1}},[l,c]);const y=b.filter(r=>{const o=d.trim().toLowerCase(),N=m.has(r.value)?"SELECTED":r.status;return x!=="ALL"&&N!==x?!1:o?`${r.label} ${r.ruleLabel??""}`.toLowerCase().includes(o):!0});function s(r){a(Array.from(r).sort((o,g)=>o.localeCompare(g)))}const n=y.filter(r=>r.status!=="USED_BY_OTHER"||m.has(r.value));return t.jsxs("div",{className:"space-y-3 rounded border bg-white p-3",children:[t.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[t.jsxs("div",{className:"text-xs text-gray-600",children:["Selected: ",t.jsx("span",{className:"font-semibold text-gray-900",children:m.size})," categor",m.size===1?"y":"ies"]}),t.jsxs("div",{className:"flex flex-wrap gap-2",children:[t.jsx("button",{type:"button",className:"rounded border px-2.5 py-1.5 text-xs font-medium text-gray-700 hover:bg-gray-50",onClick:()=>{const r=new Set(m);for(const o of n)o.status!=="USED_BY_OTHER"&&r.add(o.value);s(r)},children:"Select visible"}),t.jsx("button",{type:"button",className:"rounded border px-2.5 py-1.5 text-xs font-medium text-gray-700 hover:bg-gray-50",onClick:()=>s(new Set),children:"Clear"})]})]}),t.jsxs("div",{className:"grid gap-2 sm:grid-cols-[1fr_auto]",children:[t.jsx("input",{className:"w-full rounded border px-3 py-2 text-sm",value:d,onChange:r=>h(r.target.value),placeholder:"Search categories or the rule currently using them"}),t.jsxs("select",{className:"rounded border px-2 py-2 text-sm",value:x,onChange:r=>u(r.target.value),children:[t.jsx("option",{value:"AVAILABLE",children:"Available"}),t.jsx("option",{value:"SELECTED",children:"Selected"}),t.jsx("option",{value:"USED_BY_OTHER",children:"Used by others"}),t.jsx("option",{value:"ALL",children:"All"})]})]}),j?t.jsx("div",{className:"rounded border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-700",children:j}):null,t.jsxs("div",{className:"max-h-72 space-y-1 overflow-y-auto rounded border border-gray-100 p-2",children:[y.map(r=>{const o=m.has(r.value),g=r.status==="USED_BY_OTHER"&&!o;return t.jsxs("label",{className:`flex items-start gap-2 rounded px-2 py-2 text-sm ${g?"bg-gray-50 text-gray-400":"hover:bg-blue-50"}`,children:[t.jsx("input",{type:"checkbox",className:"mt-0.5",checked:o,disabled:g,onChange:N=>{const S=new Set(m);N.target.checked?S.add(r.value):S.delete(r.value),s(S)}}),t.jsxs("span",{className:"min-w-0 flex-1",children:[t.jsx("span",{className:"block font-medium text-gray-800",children:r.label}),g?t.jsxs("span",{className:"block text-xs text-gray-500",children:["Used by: ",r.ruleLabel??`Rule #${r.ruleId}`]}):null]})]},r.value)}),y.length===0?t.jsx("div",{className:"px-3 py-6 text-center text-sm text-gray-500",children:"No categories match this view."}):null]})]})}function T({value:e,onChange:a}){const[l,c]=i.useState([]),[m,b]=i.useState(!1),[f,d]=i.useState(!1),[h,x]=i.useState(null),u=i.useRef(null),j=i.useCallback(async()=>{const s=await v.get("/api/admin/r/sn-reference-images/options");c(s.data??[])},[]);i.useEffect(()=>{let s=!0;return v.get("/api/admin/r/sn-reference-images/options").then(n=>{s&&c(n.data??[])}),()=>{s=!1}},[]);const p=l.find(s=>
1s.id===String(e??""));async function y(s){d(!0),x(null);try{const n=new FormData;n.set("file",s),n.set("title",s.name.replace(/\.[^.]+$/,""));const r=await v.postFormData("/api/admin/r/sn-reference-images/upload",n);await j(),a(r.data.id),b(!1)}catch(n){x(n instanceof Error?n.message:"Upload failed.")}finally{d(!1),u.current&&(u.current.value="")}}return t.jsxs("div",{className:"space-y-3",children:[t.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[p?t.jsx("img",{src:p.imageUrl,alt:p.title,className:"h-20 w-28 rounded border object-cover"}):t.jsx("div",{className:"flex h-20 w-28 items-center justify-center rounded border border-dashed text-xs text-gray-500",children:"No image"}),t.jsxs("div",{className:"min-w-0 flex-1",children:[t.jsx("div",{className:"truncate text-sm font-medium text-gray-800",children:(p==null?void 0:p.title)??"No reference image selected"}),t.jsx("button",{type:"button",className:"mt-2 rounded border border-blue-300 px-3 py-2 text-sm font-medium text-blue-700 hover:bg-blue-50",onClick:()=>b(!0),children:"Choose from library"})]})]}),m?t.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",children:t.jsxs("div",{className:"max-h-[86vh] w-full max-w-4xl overflow-hidden rounded-lg bg-white shadow-xl",children:[t.jsxs("div",{className:"flex items-center justify-between border-b px-4 py-3",children:[t.jsxs("div",{children:[t.jsx("div",{className:"text-base font-semibold text-gray-900",children:"Choose Reference Image"}),t.jsx("div",{className:"text-xs text-gray-500",children:"Select an existing preview image or upload a new one."})]}),t.jsx("button",{type:"button",className:"rounded border px-3 py-1.5 text-sm",onClick:()=>b(!1),children:"Close"})]}),t.jsxs("div",{className:"space-y-4 overflow-y-auto p-4",children:[t.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[t.jsx("button",{type:"button",className:"rounded bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700 disabled:opacity-60",disabled:f,onClick:()=>{var s;return(s=u.current)==null?void 0:s.click()},children:f?"Uploading...":"Upload image"}),t.jsx("input",{ref:u,type:"file",accept:"image/*",className:"hidden",onChange:s=>{var r;const n=(r=s.target.files)==null?void 0:r[0];n&&y(n)}}),h?t.jsx("span",{className:"text-sm text-red-600",children:h}):null]}),t.jsx("div",{className:"grid gap-3 sm:grid-cols-2 lg:grid-cols-3",children:l.map(s=>{const n=s.id===String(e??"");return t.jsxs("button",{type:"button",className:`rounded border p-2 text-left hover:border-blue-400 ${n?"border-blue-500 bg-blue-50":"border-gray-200"}`,onClick:()=>{a(s.id),b(!1)},children:[t.jsx("img",{src:s.imageUrl,alt:s.title,className:"aspect-[4/3] w-full rounded object-cover"}),t.jsx("div",{className:"mt-2 truncate text-sm font-medium text-gray-800",children:s.title})]},s.id)})}),l.length===0?t.jsx("div",{className:"rounded border border-dashed p-6 text-center text-sm text-gray-500",children:"No images yet. Upload one to use it."}):null]})]})}):null]})}function w(e,a){return e||a}function k(e){var l;const a=((l=e.categories)==null?void 0:l.map(c=>c.productCategory).filter(Boolean))??[];return a.length?a:e.productCategory?[e.productCategory]:[]}function E(e){var l;const a=(l=e.productCategories)!=null&&l.length?e.productCategories:k(e);return a.length?a.length<=2?a.join(", "):`${a.slice(0,2).join(", ")} +${a.length-2}`:"No categories"}const B={name:"sn-reference-rules",endpoint:"/api/admin/r/sn-reference-rules",idKey:"id",title:"SN Position",description:"Map brand and category combinations to the correct serial number label location image.",titleOf:e=>`${w(e.brandName,"All brands")} / ${E(e)}`,routes:{list:"/admin/sn-reference-rules",detail:"/admin/sn-reference-rules/:id",create:"/admin/sn-reference-rules/new"},list:{dateGroup:!0,groupQueryEndpoint:"/api/admin/r/sn-reference-rules/groups/query",defaultSort:{key:"brandName",dir:"asc"},search:{placeholder:"Search...",defaultField:"brand",fields:[{value:"brand",label:"Brand"},{value:"category",label:"Category"},{value:"image",label:"Image"},{value:"instruction",label:"Instruction"}],toQuery:(e,a)=>e.trim()?{search:e.trim(),searchField:a||"brand"}:null},columns:[{key:"brandName",label:"Brand",render:e=>w(e.brandName,"All brands")},{key:"productCategories",label:"Categories",render:e=>E(e)},{key:"imageId",label:"Image",render:e=>{var a;return((a=e.image)==null?void 0:a.title)??e.imageId}},{key:"instructionText",label:"Hint",render:e=>t.jsx("span",{className:"text-gray-600",children:e.instructionText||"-"})},{key:"updatedAt",label:"Updated",render:e=>t.jsx("span",{className:"text-xs text-gray-500",children:A(e.updatedAt)})}]},form:{initialDraft:{brandName:"",productCategories:[],imageId:"",instructionText:""},createTitle:"Create SN position entry",onLoad:e=>({...e,productCategories:k(e)}
1),validate:e=>e.imageId?null:"Reference image is required.",beforeSubmit:e=>{var a,l;return{brandName:((a=e.brandName)==null?void 0:a.trim())||"",productCategories:Array.isArray(e.productCategories)?e.productCategories:[],imageId:e.imageId,instructionText:((l=e.instructionText)==null?void 0:l.trim())||null}},fields:[{key:"brandName",label:"Brand",type:"select",helpText:"Leave blank to use this rule for all brands.",renderValue:(e,a)=>t.jsx(I,{value:e.brandName,onChange:a,endpoint:"/api/admin/r/sn-reference-rules/brand-options",placeholder:"Select brand",allLabel:"All brands"})},{key:"productCategories",label:"Categories",type:"select",gridSpan:2,helpText:"Each category can only be selected by one rule for the selected brand. Used categories must be released from their current rule first.",renderValue:(e,a,l)=>{var c;return t.jsx(L,{value:e.productCategories,onChange:a,brandName:String(e.brandName??""),currentRuleId:((c=l.row)==null?void 0:c.id)??null})}},{key:"imageId",label:"Reference Image",type:"select",required:!0,gridSpan:2,renderValue:(e,a)=>t.jsx(T,{value:e.imageId,onChange:a})},{key:"instructionText",label:"Position Hint",type:"textarea",gridSpan:2}]},permissions:{canCreate:e=>C(e),canEdit:e=>C(e),requiredListAction:"list",requiredEditAction:"edit"}};export{B as snReferenceRulesDescriptor};

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.