PageSourceSearch

https://adpilot-489907.web.app/assets/Settings-DpLaLpTe.js

js adpilot-489907.web.app collected 2026-10-03 12:17:12 UTC 37,726 bytes, 22 lines download raw bytes

1import{r as a,j as e,a as b}from"./index-tNhE6V5Q.js";import{L as Y,C as w}from"./Dash-4uLE9yHf.js";const S="#181B24",h="#59616F",y="#8A93A2",E="#0E9F6E",k="#B45309",_="#DC2626",B="#4338CA",L="#2563EB";function O({on:t,onChange:n,disabled:c,color:x=E}){return e.jsxs("button",{type:"button",role:"switch","aria-checked":t,disabled:c,onClick:()=>n(!t),className:"inline-flex items-center flex-none disabled:opacity-50 cursor-pointer",children:[e.jsx("span",{className:"relative inline-block w-9 h-5 rounded-full transition-colors",style:{background:t?x:"#c9cdd6"},children:e.jsx("span",{className:`absolute top-[2px] w-4 h-4 bg-white rounded-full shadow-sm transition-all ${t?"left-[18px]":"left-[2px]"}`})}),e.jsx("span",{className:"ml-2 text-[11px] font-semibold tabular-nums",style:{color:h},children:t?"ON":"OFF"})]})}function A({on:t,color:n=E,pulse:c}){return e.jsx("span",{className:`inline-block w-2.5 h-2.5 rounded-full flex-none ${t&&c?"animate-pulse":""}`,style:{background:t?n:"#c9cdd6"}})}function M({msg:t}){const n=t.includes("✓");return e.jsx("div",{className:"mt-3 text-[12px]",style:{color:n?E:_},children:t})}function $({label:t,hint:n,children:c}){return e.jsxs("label",{className:"block",children:[e.jsx("div",{className:"text-[11px] font-medium mb-1",style:{color:S},children:t}),c,e.jsx("div",{className:"text-[10.5px] mt-1 leading-tight",style:{color:y},children:n})]})}const D="px-2 py-1.5 text-[12px] border border-[#E5E8ED] rounded-[6px] bg-white text-[#181B24] focus:outline-none focus:border-[#4338CA]",I="text-[12px] bg-[#4338CA] hover:bg-[#3730a3] disabled:opacity-50 text-white px-3 py-1.5 rounded-[6px]",P="text-[12px] text-[#8A93A2] hover:text-[#59616F] px-2 py-1",j="py-2 pr-3 font-medium text-left text-[11px] text-[#8A93A2]",v="py-2 pr-3 text-[12px] align-top",q=t=>{if(!t)return"—";try{return new Date(t).toLocaleString("en-IN",{dateStyle:"medium",timeStyle:"short"})}catch{return t}},U=t=>{const n=typeof t=="string"?parseFloat(t):t||0;return n?`₹${n.toLocaleString("en-IN")}`:"—"};function re(){const[t,n]=a.useState(null),[c,x]=a.useState(!0),[m,o]=a.useState(!1),[u,r]=a.useState(null),[d,g]=a.useState(""),i=async()=>{try{const s=await b.get(`/v1/agent/storefront-config?_=${Date.now()}`);n(s),r(null)}catch(s){r(s instanceof Error?s.message:"Failed to load")}finally{x(!1)}};a.useEffect(()=>{i()},[]);const p=async s=>{o(!0),r(null);try{await b.post("/v1/agent/admin/toggle",{enabled:s,reason:s?null:d.trim()||"Manual toggle"}),await i(),g("")}catch(N){r(N instanceof Error?N.message:"Toggle failed")}finally{o(!1)}},l=t?.enabled??!1;return e.jsxs("div",{className:"space-y-4",children:[c&&e.jsx(Y,{}),!c&&!t&&e.jsxs(w,{title:"Storefront widget",sources:["amicikart.com"],children:[e.jsx("div",{className:"text-[13px] font-semibold mb-1",style:{color:_},children:"Couldn't load agent settings"}),e.jsx("div",{className:"text-[12px] mb-3",style:{color:h},children:u||"API returned an unexpected response. The endpoint /api/v1/agent/storefront-config may not be deployed yet."}),e.jsx("button",{onClick:()=>{x(!0),i()},className:"text-[12px] bg-[#DC2626] hover:bg-[#b91c1c] text-white px-3 py-1.5 rounded-[6px]",children:"Retry"})]}),t&&e.jsxs(e.Fragment,{children:[e.jsxs(w,{title:"Storefront widget — kill switch",sources:["amicikart.com"],right:e.jsx(O,{on:l,onChange:p,disabled:m,color:E}),children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1.5",children:[e.jsx(A,{on:l,color:l?E:k,pulse:!0}),e.jsxs("span",{className:"text-[14px] font-semibold",style:{color:S},children:["Agent on amicikart.com is ",l?"LIVE":"OFF"]})]}),e.jsx("p",{className:"text-[12px] max-w-xl",style:{color:h},children:l?"Customers visiting amicikart.com see the chat widget and can interact with the agent. Toggle off to kill it instantly.":"The chat widget is currently hidden from your customers. Toggle on to deploy."}),t.kill_switch_reason&&e.jsxs("div",{className:"mt-2 text-[11px] rounded px-2 py-1 inline-block border",style:{color:k,background:"#FEF6EC",borderColor:"#F3DFC5"},children:["Disabled reason: ",t.kill_switch_reason]}
1),!l&&e.jsx("div",{className:"mt-3 pt-3 border-t border-[#EEF0F4]",children:e.jsxs("label",{className:"text-[11px]",style:{color:h},children:["Reason (optional, shown to no one but logged):",e.jsx("input",{type:"text",value:d,onChange:s=>g(s.target.value),placeholder:"e.g. testing fixes / brand-safety check",className:`mt-1 block w-full ${D}`})]})}),u&&e.jsx("div",{className:"mt-3 text-[12px] rounded px-2 py-1 border",style:{color:_,background:"#FEF2F2",borderColor:"#FADCDC"},children:u})]}),e.jsx(H,{}),e.jsx(K,{}),e.jsx(Z,{}),e.jsx(z,{}),e.jsx(J,{}),e.jsx(ee,{}),e.jsxs(w,{title:"Shopify theme integration",sources:["Shopify"],children:[e.jsxs("p",{className:"text-[12px] mb-3",style:{color:h},children:["The widget is loaded into amicikart.com via a Liquid snippet that injects an iframe pointing at",e.jsx("code",{className:"mx-1 px-1 bg-[#EEF0F4] rounded text-[10.5px]",children:"https://adpilot-489907.web.app/embed/agent"}),". When this toggle is OFF, the iframe still loads but the widget renders nothing — invisible to customers."]}),e.jsxs("div",{className:"text-[10.5px]",style:{color:y},children:["Snippet file: ",e.jsx("code",{className:"px-1 bg-[#EEF0F4] rounded",children:"snippets/adpilot-agent.liquid"})," · Auto-pushed to Shopify theme."]})]}),e.jsx(te,{}),e.jsx(se,{}),e.jsx(w,{title:"More controls (coming next)",children:e.jsxs("ul",{className:"space-y-1.5 text-[12px]",style:{color:h},children:[e.jsx("li",{children:"• Restrict which pages the widget shows on (e.g. only PDPs, only cart, etc.)"}),e.jsx("li",{children:"• Theme color override"}),e.jsx("li",{children:'• Business hours — auto-switch to "leave a message" outside hours'}),e.jsx("li",{children:"• Per-channel enable: web · WhatsApp · Instagram"}),e.jsx("li",{children:"• Rate limits per session / per IP"}),e.jsx("li",{children:"• Model choice: Sonnet 5 (current) · Opus 4.8 (smarter) · GLM 5.2 (cheapest)"})]})})]}),e.jsx(ne,{})]})}function H(){const[t,n]=a.useState(null),[c,x]=a.useState(!0),[m,o]=a.useState(!1),[u,r]=a.useState(null),d=()=>{x(!0),b.get(`/v1/agent/admin/agent/cancel-config?_=${Date.now()}`).then(l=>n(l.cancel)).catch(()=>n(null)).finally(()=>x(!1))};a.useEffect(d,[]);const g=async l=>{o(!0),r(null);try{const s=await b.post("/v1/agent/admin/agent/cancel-config",l);n(s.cancel),r("Saved ✓"),setTimeout(()=>r(null),2500)}catch(s){r(s instanceof Error?s.message:"Save failed"),d()}finally{o(!1)}},i=l=>{if(!t||l&&!window.confirm(`Enable AI order cancellation?
2
3The agent will be able to CANCEL website (Shopify) orders and REFUND prepaid orders to the original payment method — but ONLY after a strict match on order number + mobile/email on the order + a product in it, and only for orders that have not shipped.
4
5Continue?`))return;const s={...t,enabled:l};n(s),g(s)};if(c||!t)return e.jsx(w,{title:"Order cancellation & refunds",sources:["Shopify"],children:e.jsx("div",{className:"text-[12px]",style:{color:y},children:c?"Loading…":"Could not load — retry shortly."})});const p=t.enabled;return e.jsxs(w,{title:"Order cancellation & refunds",sources:["Shopify"],right:e.jsx(O,{on:p,onChange:i,disabled:m,color:_}),children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1.5",children:[e.jsx(A,{on:p,color:_,pulse:!0}),e.jsxs("span",{className:"text-[14px] font-semibold",style:{color:S},children:["AI order cancellation is ",p?"LIVE":"OFF"]})]}),e.jsxs("p",{className:"text-[12px] max-w-xl",style:{color:h},children:["When ON, the agent can ",e.jsx("strong",{children:"cancel a 
5website (Shopify) order and refund prepaid orders"})," to the original payment method — but ONLY after a strict ",e.jsx("strong",{children:"order number + mobile/email on the order + a product in it"})," all match, and only if the order hasn't shipped. Amazon/Flipkart, already-shipped, over-cap, or mismatched requests are never cancelled — they're logged for your team. This toggle is your instant kill switch."]}),e.jsx("div",{className:`mt-4 pt-4 border-t border-[#EEF0F4] ${p?"":"opacity-50 pointer-events-none"}`,children:e.jsx($,{label:"Auto-refund cap (₹)",hint:"Prepaid orders ABOVE this value are NOT auto-refunded — they're escalated to a human instead. Set 0 to allow any amount. Default 20,000.",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"number",min:0,value:t.max_refund_inr,onChange:l=>n({...t,max_refund_inr:Math.max(0,+l.target.value||0)}),className:`w-40 tabular-nums ${D}`}),e.jsx("button",{onClick:()=>g(t),disabled:m,className:I,children:m?"Saving…":"Save cap"})]})})}),u&&e.jsx(M,{msg:u})]})}function Z(){const[t,n]=a.useState(null),[c,x]=a.useState(!0),[m,o]=a.useState(!1),[u,r]=a.useState(null),d=()=>{x(!0),b.get(`/v1/agent/admin/agent/cancel-intransit-config?_=${Date.now()}`).then(l=>n(l.cancel_intransit)).catch(()=>n(null)).finally(()=>x(!1))};a.useEffect(d,[]);const g=async l=>{o(!0),r(null);try{const s=await b.post("/v1/agent/admin/agent/cancel-intransit-config",l);n(s.cancel_intransit),r("Saved ✓"),setTimeout(()=>r(null),2500)}catch(s){r(s instanceof Error?s.message:"Save failed"),d()}finally{o(!1)}},i=l=>{if(!t||l&&!window.confirm(`Turn on in-transit cancellation?
6
7After verifying the customer (the WhatsApp number on the order, or a WhatsApp OTP), Amico will:
8
9•  AUTO-cancel + refund orders AT or BELOW the refund cap — directly in chat, no human step
10•  QUEUE high-value orders (above the cap) below for your approval
11
12Lower the cap to shrink what Amico does on its own. Continue?`))return;const s={...t,enabled:l};n(s),g(s)};if(c||!t)return e.jsx(w,{title:"In-transit cancellation (booked / shipped)",sources:["Delhivery"],children:e.jsx("div",{className:"text-[12px]",style:{color:y},children:c?"Loading…":"Could not load — retry shortly."})});const p=t.enabled;return e.jsxs(w,{title:"In-transit cancellation (booked / shipped)",sources:["Delhivery"],right:e.jsx(O,{on:p,onChange:i,disabled:m,color:k}),children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1.5",children:[e.jsx(A,{on:p,color:k,pulse:!0}),e.jsxs("span",{className:"text-[14px] font-semibold",style:{color:S},children:["In-transit cancellation is ",p?"ON":"OFF"]})]}),e.jsxs("p",{className:"text-[12px] max-w-xl",style:{color:h},children:["For orders that are ",e.jsx("strong",{children:"already booked / shipped but not yet delivered"}),". When ON — and only after verifying the customer (the WhatsApp number on the order, or a WhatsApp OTP) — Amico can",e.jsx("strong",{children:" stop the courier shipment and refund"}),". ",e.jsx("strong",{children:"Orders at or below the refund cap are actioned automatically in chat"}),"; ",e.jsx("strong",{children:"high-value orders above the cap are queued below for a human to approve"}),". Out-for-delivery and delivered parcels are never stopped this way."]}),e.jsx("div",{className:`mt-4 pt-4 border-t border-[#EEF0F4] ${p?"":"opacity-50 pointer-events-none"}`,children:e.jsx($,{label:"Auto-cancel cap (₹)",hint:"The auto-approve threshold. Prepaid refunds AT or BELOW this are cancelled + refunded automatically in chat; ABOVE this they go to the approval queue for a human. COD (no refund) is always automatic. Set 0 to send EVERY prepaid order to the queue. Default 20,000.",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"number",min:0,value:t.max_refund_inr,onChange:l=>n({...t,max_refund_inr:Math.max(0,+l.target.value||0)}),className:`w-40 tabular-nums ${D}`}),e.jsx("button",{onClick:()=>g(t),disabled:m,className:I,children:m?"Saving…":"Save cap"})]})})}),u&&e.jsx(M,{msg:u})]})}
12function z(){const[t,n]=a.useState(null),[c,x]=a.useState(!0),[m,o]=a.useState(!1),[u,r]=a.useState(null),d=()=>{x(!0),b.get(`/v1/agent/admin/agent/address-edit-config?_=${Date.now()}`).then(p=>n(!!p.enabled)).catch(()=>n(null)).finally(()=>x(!1))};a.useEffect(d,[]);const g=async p=>{if(p&&!window.confirm(`Turn ON in-transit address editing?
13
14For an ALREADY-SHIPPED Delhivery parcel, after verifying the customer Amico will be able to request the courier to correct the delivery address — but ONLY within the SAME pincode and ONLY while it is still in transit (never once out for delivery, and it cannot change the city/PIN).
15
16It takes the customer through a double confirmation, tells them it is a best-effort courier request, and suggests they can also raise a Delhivery ticket. Continue?`))return;o(!0),r(null);const l=t;n(p);try{const s=await b.post("/v1/agent/admin/agent/address-edit-config",{enabled:p});n(!!s.intransit_address_edit_enabled),r("Saved ✓"),setTimeout(()=>r(null),2500)}catch(s){n(l),r(s instanceof Error?s.message:"Save failed")}finally{o(!1)}};if(c||t===null)return e.jsx(w,{title:"In-transit address edit (shipped parcels)",sources:["Delhivery"],children:e.jsx("div",{className:"text-[12px]",style:{color:y},children:c?"Loading…":"Could not load — retry shortly."})});const i=t;return e.jsxs(w,{title:"In-transit address edit (shipped parcels)",sources:["Delhivery"],right:e.jsx(O,{on:i,onChange:g,disabled:m,color:k}),children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1.5",children:[e.jsx(A,{on:i,color:k,pulse:!0}),e.jsxs("span",{className:"text-[14px] font-semibold",style:{color:S},children:["In-transit address edit is ",i?"ON":"OFF"]})]}),e.jsxs("p",{className:"text-[12px] max-w-xl",style:{color:h},children:["For an order that is ",e.jsx("strong",{children:"already shipped via Delhivery but not yet delivered"}),". When ON — and only after verifying the customer — Amico can ",e.jsx("strong",{children:"request the courier to correct the delivery address within the SAME pincode"}),". It explains plainly what it can and can’t do, takes a",e.jsx("strong",{children:" double confirmation"}),", notes it is a ",e.jsx("strong",{children:"best-effort"})," request and that the customer can also raise a Delhivery ticket, and only then applies. ",e.jsx("strong",{children:"It never changes the city/PIN and never edits a parcel that is out for delivery / delivered"})," — those are handed to the team. When OFF, Amico captures the corrected address and raises a ticket instead."]}),u&&e.jsx(M,{msg:u})]})}function K(){const[t,n]=a.useState(null),[c,x]=a.useState(!0),[m,o]=a.useState(!0),[u,r]=a.useState(!1),[d,g]=a.useState(null),i=()=>{o(!0),b.get(`/v1/agent/admin/agent/cancel-otp-config?_=${Date.now()}`).then(N=>{n(N.cancel_otp),x(!!N.wa_configured)}).catch(()=>n(null)).finally(()=>o(!1))};a.useEffect(i,[]);const p=async N=>{if(t){r(!0),g(null),n({enabled:N});try{const F=await b.post("/v1/agent/admin/agent/cancel-otp-config",{enabled:N});n(F.cancel_otp),g("Saved ✓"),setTimeout(()=>g(null),2500)}catch(F){g(F instanceof Error?F.message:"Save failed"),i()}finally{r(!1)}}};if(m||!t)return e.jsx(w,{title:"Identity verification (WhatsApp OTP)",sources:["WhatsApp Cloud"],children:e.jsx("div",{className:"text-[12px]",style:{color:y},children:m?"Loading…":"Could not load — retry shortly."})});const l=t.enabled,s=l&&c;return e.jsxs(w,{title:"Identity verification (WhatsApp OTP)",sources:["WhatsApp Cloud"],right:e.jsx(O,{on:l,onChange:p,disabled:u,color:B}),children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1.5",children:[e.jsx(A,{on:s,color:B,pulse:!0}),e.jsxs("span",{className:"text-[14px] font-semibold",style:{color:S},children:["WhatsApp identity check is ",s?"ACTIVE":l?"ON (waiting on WhatsApp)":"OFF"]})]}),e.jsxs("p",{className:"text-[12px] max-w-xl",style:{color:h},children:["Adds an ownership proof before ANY cancel/refund moves money. A customer messaging on",e.jsx("strong",{children:" WhatsApp from the number on the order"})," is trusted automatically. Everyone else (website, or a different WhatsApp number) gets a ",e.jsx("strong",{children:"6-digit code on WhatsApp"})," sent to the order's number, which they must enter — proving they control the order's phone, not just know its details. Applies to pre-dispatch cancels, RTO refunds, and in-transit cancellation requests."]}),l&&!c&&e.jsxs("div",{className:"mt-3 text-[11px] rounded px-3 py-2 border",style:{color:k,background:"#FEF6EC",borderColor:"#F3DFC5"},children:["The layer is enabled but the WhatsApp Cloud API isn't configured, so it's ",e.jsx("strong",{children:"inactive"})," — cancellations fall back to the order# + contact + product match (today's behaviour) until WhatsApp sending is live."]}),d&&e.jsx(M,{msg:d})]})}const Q={pending:{bg:"#FEF6EC",fg:k},executed:{bg:"#E7F7F0",fg:E},rejected:{bg:"#EEF0F4",fg:h},failed:{bg:"#FEF2F2",fg:_}
16,approved:{bg:"#EFF4FE",fg:L}};function J(){const[t,n]=a.useState(null),[c,x]=a.useState({}),[m,o]=a.useState(!0),[u,r]=a.useState(null),[d,g]=a.useState(null),i=()=>{o(!0),b.get(`/v1/agent/admin/agent/cancel-approvals?_=${Date.now()}`).then(s=>{n(s.approvals||[]),x(s.by_status||{})}).catch(()=>n([])).finally(()=>o(!1))};a.useEffect(i,[]);const p=async(s,N,F)=>{const R=N==="approve"?`APPROVE cancellation of ${F}?
17
18This will cancel the Delhivery shipment now, and (if prepaid) refund the order to the original payment method. This cannot be undone.`:`Reject the cancellation request for ${F}? No carrier or refund action is taken.`;if(window.confirm(R)){r(s),g(null);try{const C=await b.post(`/v1/agent/admin/agent/cancel-approvals/${s}/${N}`,{by:"admin"});C.ok||C.status==="executed"||C.status==="rejected"?g(N==="approve"?C.status==="executed"?`✓ ${F} cancelled + refunded`:`${F}: ${C.error||C.status}`:`✓ ${F} request rejected`):g(`${F}: ${C.error||C.status||"failed"}`),i()}catch(C){g(C instanceof Error?C.message:"Action failed")}finally{r(null)}}},l=c.pending||0;return e.jsxs(w,{title:"In-transit cancellation approvals",sources:["Delhivery","Shopify"],right:e.jsx("button",{onClick:i,className:P,children:"Refresh"}),children:[l>0&&e.jsxs("span",{className:"inline-block mb-2 px-2 py-0.5 rounded-full text-[10px] font-bold text-white tabular-nums",style:{background:k},children:[l," pending"]}),e.jsxs("p",{className:"text-[12px] mb-3",style:{color:h},children:[e.jsx("strong",{children:"High-value"})," in-transit cancellations (above your cap) that Amico filed for your sign-off — smaller ones are auto-actioned in chat. ",e.jsx("strong",{children:"Approve"})," cancels the Delhivery shipment and refunds (prepaid), verified live at approval time. ",e.jsx("strong",{children:"Reject"})," does nothing to the order."]}),d&&e.jsx("div",{className:"mb-3 text-[12px]",style:{color:d.startsWith("✓")?E:_},children:d}),m&&e.jsx("div",{className:"text-[12px] py-2",style:{color:y},children:"Loading…"}),!m&&t&&t.length===0&&e.jsx("div",{className:"text-[12px] py-3",style:{color:y},children:"No cancellation requests yet."}),!m&&t&&t.length>0&&e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-[12px]",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-[#EEF0F4]",children:[e.jsx("th",{className:`${j} whitespace-nowrap`,children:"When"}),e.jsx("th",{className:j,children:"Order"}),e.jsx("th",{className:j,children:"Customer"}),e.jsx("th",{className:j,children:"AWB / tracking"}),e.jsx("th",{className:j,children:"Refund"}),e.jsx("th",{className:j,children:"Status"}),e.jsx("th",{className:j,children:"Action"})]})}),e.jsx("tbody",{children:t.map(s=>{const N=Q[s.status]||{bg:"#EEF0F4",fg:h};return e.jsxs("tr",{className:"border-b border-[#EEF0F4]",children:[e.jsx("td",{className:`${v} whitespace-nowrap`,style:{color:h},children:q(s.created_at)}),e.jsxs("td",{className:`${v} font-medium whitespace-nowrap`,style:{color:S},children:[s.order_name,s.product_titles&&s.product_titles.length>0&&e.jsx("div",{className:"text-[10.5px] font-normal max-w-[180px] truncate",style:{color:y},title:s.product_titles.join(", "),children:s.product_titles.join(", ")})]}),e.jsxs("td",{className:v,style:{color:h},children:[s.customer_name&&e.jsx("div",{style:{color:S},children:s.customer_name}),s.customer_phone&&e.jsx("a",{href:`tel:${s.customer_phone}`,className:"hover:underline block",style:{color:L},children:s.customer_phone}),s.customer_email&&e.jsx("a",{href:`mailto:${s.customer_email}`,className:"hover:underline block",style:{color:L},children:s.customer_email}),s.auth_method&&e.jsx("span",{title:s.auth_method==="wa_native"?"Verified: messaged from the WhatsApp number on the order":s.auth_method==="otp"?"Verified: entered a WhatsApp OTP sent to the order number":"Identity layer was off — order# + contact + product match only",className:"inline-block mt-0.5 px-1.5 py-0.5 rounded text-[10px] font-medium",style:s.auth_method==="wa_native"?{background:"#E7F7F0",color:E}:s.auth_method==="otp"?{background:"#EEF0FB",color:B}:{background:"#EEF0F4",color:y},children:s.auth_method==="wa_native"?"WhatsApp ✓":s.auth_method==="otp"?"OTP ✓":"no OTP"})]}),e.jsxs("td",{className:v,style:{color:h},children:[e.jsx("div",{className:"font-mono text-[11px]",children:s.awb||"—"}),s.tracking_status&&e.jsx("div",{className:"text-[10.5px]",style:{color:y},children:s.tracking_status})]}),e.jsx("td",{className:`${v} whitespace-nowrap tabular-nums`,style:{color:h},children:s.prepaid?U(s.refund_amount):"COD"}),e.jsxs("td",{className:v,children:[e.jsx("span",{className:"px-1.5 py-0.5 rounded text-[10px] font-medium",style:{background:N.bg,color:N.fg},children:s.status}),s.error&&e.jsx("div",{className:"text-[10.5px] max-w-[160px] mt-0.5",style:{color:_},children:s.error})]}),e.jsx("td",{className:`${v} whitespace-nowrap`,children:s.status==="pending"?e.jsxs("div",{className:"flex gap-1.5",children:[e.jsx("button",{onClick:()=>p(s.id,"approve",s.order_name),disabled:u===s.id,className:"text-[11px] disabled:opacity-50 text-white px-2.5 py-1 rounded-[6px]",style:{background:E},children:u===s.id?"…":"Approve"}),e.jsx("button",{onClick:()=>p(s.id,"reject",s.order_name),disabled:u===s.id,className:"text-[11px] bg-[#EEF0F4] hover:bg-[#
18E5E8ED] disabled:opacity-50 px-2.5 py-1 rounded-[6px]",style:{color:h},children:"Reject"})]}):e.jsx("span",{className:"text-[10.5px]",style:{color:y},children:"—"})})]},s.id)})})]})})]})}function ee(){const[t,n]=a.useState(null),[c,x]=a.useState(!0),m=()=>{x(!0),b.get(`/v1/agent/admin/agent/cancellations?_=${Date.now()}`).then(o=>n(o.cancellations||[])).catch(()=>n([])).finally(()=>x(!1))};return a.useEffect(m,[]),e.jsxs(w,{title:"Recent cancellations & refunds",sources:["Shopify"],right:e.jsx("button",{onClick:m,className:P,children:"Refresh"}),children:[e.jsx("p",{className:"text-[12px] mb-3",style:{color:h},children:"Every order the agent cancelled — with the buyer's contact and reason, so your team can follow up (win-back / feedback)."}),c&&e.jsx("div",{className:"text-[12px] py-2",style:{color:y},children:"Loading…"}),!c&&t&&t.length===0&&e.jsx("div",{className:"text-[12px] py-3",style:{color:y},children:"No cancellations yet."}),!c&&t&&t.length>0&&e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-[12px]",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-[#EEF0F4]",children:[e.jsx("th",{className:`${j} whitespace-nowrap`,children:"When"}),e.jsx("th",{className:j,children:"Order"}),e.jsx("th",{className:j,children:"Customer contact"}),e.jsx("th",{className:j,children:"Refund"}),e.jsx("th",{className:j,children:"Reason"}),e.jsx("th",{className:j,children:"Status"})]})}),e.jsx("tbody",{children:t.map((o,u)=>e.jsxs("tr",{className:"border-b border-[#EEF0F4]",children:[e.jsx("td",{className:`${v} whitespace-nowrap`,style:{color:h},children:q(o.created_at)}),e.jsx("td",{className:`${v} font-medium whitespace-nowrap`,style:{color:S},children:o.order_name}),e.jsxs("td",{className:v,style:{color:h},children:[o.customer_phone&&e.jsx("a",{href:`tel:${o.customer_phone}`,className:"hover:underline block",style:{color:L},children:o.customer_phone}),o.customer_email&&e.jsx("a",{href:`mailto:${o.customer_email}`,className:"hover:underline block",style:{color:L},children:o.customer_email}),!o.customer_phone&&!o.customer_email&&e.jsx("span",{style:{color:y},children:"—"})]}),e.jsx("td",{className:`${v} whitespace-nowrap tabular-nums`,style:{color:h},children:o.prepaid?U(o.refund_amount):"COD"}),e.jsx("td",{className:`${v} max-w-[240px]`,style:{color:h},children:o.cancel_reason||e.jsx("span",{className:"italic",style:{color:y},children:"not given"})}),e.jsx("td",{className:v,children:e.jsx("span",{className:"px-1.5 py-0.5 rounded text-[10px] font-medium",style:o.result==="cancelled"?{background:"#E7F7F0",color:E}:{background:"#FEF2F2",color:_},children:o.result})})]},u))})]})})]})}function te(){const[t,n]=a.useState(null),[c,x]=a.useState(!0),[m,o]=a.useState(!1),[u,r]=a.useState(null);a.useEffect(()=>{b.get(`/v1/agent/admin/discount-settings?_=${Date.now()}`).then(n).finally(()=>x(!1))},[]);const d=(i,p)=>{t&&(n({...t,[i]:p}),r(null))},g=async()=>{if(t){o(!0),r(null);try{await b.post("/v1/agent/admin/discount-settings",t),r("Saved ✓"),setTimeout(()=>r(null),2500)}catch(i){r(i instanceof Error?i.message:"Save failed")}finally{o(!1)}}};return c||!t?e.jsx(w,{title:"Discount code generation",sources:["Shopify"],children:e.jsx("div",{className:"text-[12px]",style:{color:y},children:"Loading…"})}):e.jsxs(w,{title:"Discount code generation",sources:["Shopify"],right:e.jsx(O,{on:t.enabled,onChange:i=>d("enabled",i),color:E}),children:[e.jsx("p",{className:"text-[12px] max-w-xl mb-4",style:{color:h},children:"Let the agent issue real one-time Shopify discount codes when a customer asks for a deal. All caps below are enforced server-side — the AI cannot exceed them even if asked."}),e.jsxs("div",{className:`grid grid-cols-1 md:grid-cols-2 gap-3 ${t.enabled?"":"opacity-50 pointer-events-none"}`,children:[e.jsx($,{label:"Max discount %",hint:"Server clamps any LLM request to this ceiling. Max allowed: 50.",children:e.jsx("input",{type:"number",min:1,max:50,value:t.max_percent_off,onChange:i=>d("max_percent_off",Math.max(1,Math.min(50,+i.target.value||1))),className:`w-full tabular-nums ${D}`})}),e.jsx($,{label:"Min order value (₹)",hint:"Code only applies if cart subtotal ≥ this amount. 0 = no minimum.",children:e.jsx("input",{type:"number",min:0,value:t.min_order_value_inr,onChange:i=>d("min_order_value_inr",Math.max(0,+i.target.value||0)),className:`w-full tabular-nums ${D}`})}),e.jsx($,{label:"Expires in (days)",hint:"Code auto-expires N days after creation. Max 90.",children:e.jsx("input",{type:"number",min:1,max:90,value:t.expiry_days,onChange:i=>d("expiry_days",Math.max(1,Math.min(90,+i.target.value||7))),className:`w-full tabular-nums ${D}`})}),e.jsx($,{label:"Codes per chat session",hint:"Each visitor can receive at most this many codes in one conversation.",children:e.jsx("input",{type:"number",min:1,max:5,value:t.max_codes_per_session,onChange:i=>d("max_codes_per_session",Math.max(1,Math.min(5,+i.target.value||1))),className:`w-full tabular-nums ${D}`})}),e.jsx($,{label:"Codes per day (brand-wide)",hint:"Total codes the agent can issue across all customers per day. Hard limit on margin exposure.",children:e.jsx("input",{type:"number",min:1,max:500,value:t.max_codes_per_day,onChange:i=>d("max_codes_per_day",Math.max(1,Math.min(500,+i.target.value||50))),className:`w-full tabular-nums ${D}`})}),e.jsx($,{label:"Code prefix",hint:"Codes look like PREFIX-XXXXXX. e.g. CHAT-4F9K2X. Max 8 chars.",children:e.jsx("input",{type:"text",maxLength:8,value:t.code_prefix,onChange:i=>d("code_prefix",i.target.value.toUpperCase().replace(/[^A-Z0-9]/g,"").slice(0,8)),className:`w-full font-mono ${D}`})})]}),e.jsxs("div",{className:"mt-4 flex items-center gap-3",children:[e.jsx("button",{onClick:g,disabled:m,className:I,children:m?"Saving…":"Save discount settings"}),u&&e.jsx("span",{className:"text-[12px]",style:{color:u.includes("✓")?E:_},children:u})]}
18),e.jsxs("div",{className:"mt-4 pt-3 border-t border-[#EEF0F4] text-[10.5px]",style:{color:y},children:[e.jsx("strong",{children:"Worst-case daily exposure:"})," ","max_codes_per_day × max_percent_off × avg_order = ~",(t.max_codes_per_day*t.max_percent_off/100*Math.max(t.min_order_value_inr,1e3)).toLocaleString("en-IN"),"₹ in potential margin if every code is used today."]})]})}function se(){const[t,n]=a.useState(null),[c,x]=a.useState(!0),[m,o]=a.useState(!1),[u,r]=a.useState(null),[d,g]=a.useState(""),i=()=>{x(!0),b.get(`/v1/agent/admin/email/status?_=${Date.now()}`).then(n).catch(()=>n(null)).finally(()=>x(!1))};a.useEffect(i,[]);const p=async()=>{o(!0),r(null);try{const s=await b.post("/v1/agent/admin/email/test",{to:d.trim()||null});s.ok?r(`Sent ✓ — check ${d.trim()||t?.care_email}`):r(`Failed: ${s.reason||"unknown"}${s.detail?` — ${s.detail}`:""}`)}catch(s){r(s instanceof Error?s.message:"Test failed")}finally{o(!1)}},l=t?.configured??!1;return e.jsxs(w,{title:"Email notifications",sources:["Microsoft Graph"],children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1.5",children:[e.jsx(A,{on:l,color:l?E:k,pulse:!0}),e.jsxs("span",{className:"text-[14px] font-semibold",style:{color:S},children:["Email notifications — ",l?"connected":"not connected yet"]})]}),e.jsxs("p",{className:"text-[12px] mb-3 max-w-xl",style:{color:h},children:["When the agent escalates a chat to a human, it emails the full conversation summary to"," ",e.jsx("code",{className:"px-1 bg-[#EEF0F4] rounded text-[10.5px]",children:t?.care_email||"[email protected]"})," ","via Microsoft 365 (Graph) — with a deep link to the transcript and the customer's contact as Reply-To."]}),c&&e.jsx("div",{className:"text-[12px]",style:{color:y},children:"Loading…"}),!c&&t&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex flex-wrap gap-4 text-[11px] mb-3",style:{color:h},children:[e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx(A,{on:t.tenant_id_set})," Tenant ID"]}),e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx(A,{on:t.client_id_set})," Client ID"]}),e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx(A,{on:t.client_secret_set})," Client secret"]}),e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx(A,{on:!0})," Sends as ",t.sender]})]}),!l&&e.jsxs("div",{className:"text-[11px] rounded px-3 py-2 mb-3 leading-relaxed border",style:{color:k,background:"#FEF6EC",borderColor:"#F3DFC5"},children:[e.jsx("strong",{children:"To connect:"})," in Azure, add the ",e.jsx("code",{className:"px-1 bg-white/60 rounded",children:"Mail.Send"})," application permission to your Microsoft SSO app (grant admin consent) and create a client secret, then store the three values in GCP Secret Manager as ",e.jsx("code",{className:"px-1 bg-white/60 rounded",children:"ms-tenant-id"}),","," ",e.jsx("code",{className:"px-1 bg-white/60 rounded",children:"ms-client-id"}),","," ",e.jsx("code",{className:"px-1 bg-white/60 rounded",children:"ms-client-secret"}),". No redeploy needed — just hit Refresh here."]}),e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("input",{type:"email",value:d,onChange:s=>g(s.target.value),placeholder:t.care_email,disabled:!l,className:`w-60 disabled:bg-[#F6F7F9] ${D}`}),e.jsx("button",{onClick:p,disabled:!l||m,className:I,children:m?"Sending…":"Send test email"}),e.jsx("button",{onClick:i,className:P,children:"Refresh"}),u&&e.jsx("span",{className:"text-[12px]",style:{color:u.includes("✓")?E:_},children:u})]})]})]})}const ae=(t,n=90)=>{if(!t)return"—";const c=t.trim();return c.length>n?`${c.slice(0,n)}…`:c};function ne(){const[t,n]=a.useState(null),[c,x]=a.useState(!0),[m,o]=a.useState(!1),[u,r]=a.useState(null),[d,g]=a.useState(!1),[i,p]=a.useState(null),l=a.useRef(!0),s=async()=>{l.current?x(!0):o(!0);try{const f=await b.get(`/v1/agent/admin/desk-agent/overview?_=${Date.now()}`);n(f),r(null)}catch(f){r(f instanceof Error?f.message:"Failed to load")}finally{l.current=!1,x(!1),o(!1)}};a.useEffect(()=>{s();const f=setInterval(s,2e4);return()=>clearInterval(f)},[]);const N=async f=>{g(!0),r(null);try{await b.post("/v1/agent/admin/desk-agent/live",f),await s()}catch(W){r(W instanceof Error?W.message:"Failed to update live state")}finally{g(!1)}},F=()=>{t&&N({enabled:!t.live.enabled})},R=()=>{window.confirm(`Go live to ALL customers?
19
20Amico will start auto-replying to every customer who messages on WhatsApp — not just your test numbers. Make sure you have monitored the test conversations and trust the behavior.
21
22Continue?`)&&N({enabled:!0,test_phones:[]})},C=async f=>{p(f),r(null);try{await b.post("/v1/agent/admin/desk-agent/spam-revert",{session_id:f}),await s()}catch(W){r(W instanceof Error?W.message:"Failed to revert")}finally{p(null)}},T=t?.live.enabled??!1,V=t?.live.test_phones??[],X=V.length>0,G=(t?.items??[]).filter(f=>f.is_spam||f.status==="spam");return e.jsxs(w,{title:"WhatsApp desk agent",sources:["Zoho Desk","WhatsApp"],right:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("button",{onClick:s,disabled:m||c,className:`${P} disabled:opacity-50 flex items-center gap-1.5`,children:[m&&e.jsx("span",{className:"inline-block w-3 h-3 border-2 border-[#
22E5E8ED] border-t-[#4338CA] rounded-full animate-spin"}),"Refresh"]}),t&&e.jsx(O,{on:T,onChange:F,disabled:d,color:E})]}),children:[e.jsx("p",{className:"text-[12px] mb-3 max-w-xl",style:{color:h},children:"Amico — WhatsApp auto-reply on Zoho Desk. Full conversations live in CS → Conversations; these are the live-mode and spam-handling controls."}),c&&e.jsx("div",{className:"text-[12px]",style:{color:y},children:"Loading…"}),!c&&!t&&e.jsxs("div",{children:[e.jsx("div",{className:"text-[13px] font-semibold mb-1",style:{color:_},children:"Couldn't load Desk Agent"}),e.jsx("div",{className:"text-[12px] mb-3",style:{color:h},children:u||"The endpoint /api/v1/agent/admin/desk-agent/overview may not be reachable."}),e.jsx("button",{onClick:()=>{l.current=!0,s()},className:"text-[12px] bg-[#DC2626] hover:bg-[#b91c1c] text-white px-3 py-1.5 rounded-[6px]",children:"Retry"})]}),t&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1.5",children:[e.jsx(A,{on:!0,color:T?E:_,pulse:T}),e.jsxs("span",{className:"text-[14px] font-semibold",style:{color:S},children:["Amico on WhatsApp is ",T?"LIVE":"PAUSED"]})]}),e.jsx("p",{className:"text-[12px] max-w-xl",style:{color:h},children:T?"Amico is auto-replying to customers on the Zoho Desk WhatsApp channel. Toggle off to stop it instantly.":"Paused — Amico is not replying. Incoming WhatsApp messages are still ingested but get no auto-reply until you turn this on."}),e.jsx("div",{className:"mt-4 pt-4 border-t border-[#EEF0F4]",children:X?e.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",children:[e.jsxs("div",{className:"text-[11px] rounded px-3 py-2 leading-relaxed max-w-xl border",style:{color:k,background:"#FEF6EC",borderColor:"#F3DFC5"},children:[e.jsx("strong",{children:"Scoped to test number(s):"})," ",V.join(", "),".",e.jsx("br",{}),"Customers outside this list are ingested but ",e.jsx("strong",{children:"NOT"})," auto-replied."]}),e.jsx("button",{onClick:R,disabled:d,className:`${I} shrink-0 self-start`,children:d?"Saving…":"Go live to all customers"})]}):e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-[11px] font-medium rounded-full px-3 py-1 border",style:{color:E,background:"#E7F7F0",borderColor:"#BFE8D6"},children:[e.jsx("span",{className:"w-2 h-2 rounded-full",style:{background:E}}),"Live to all customers"]})}),u&&e.jsx("div",{className:"mt-3 text-[12px] rounded px-2 py-1 border",style:{color:_,background:"#FEF2F2",borderColor:"#FADCDC"},children:u}),e.jsxs("div",{className:"mt-4 pt-4 border-t border-[#EEF0F4]",children:[e.jsx("div",{className:"text-[10.5px] uppercase tracking-[0.06em] font-semibold mb-1",style:{color:y},children:"Flagged as spam"}),e.jsx("p",{className:"text-[12px] mb-3",style:{color:h},children:"Amico marked these as spam and did not engage. Revert any that are real customers."}),G.length===0?e.jsx("div",{className:"text-[12px] py-3",style:{color:y},children:"No messages flagged as spam. 🎉"}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-[12px]",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-[#EEF0F4]",children:[e.jsx("th",{className:j,children:"Customer"}),e.jsx("th",{className:j,children:"Phone"}),e.jsx("th",{className:j,children:"Last message"}),e.jsx("th",{className:j,children:"Why spam"}),e.jsx("th",{className:`${j} whitespace-nowrap`,children:"When"}),e.jsx("th",{className:`${j} text-right`,children:"Action"})]})}),e.jsx("tbody",{children:G.map(f=>e.jsxs("tr",{className:"border-b border-[#EEF0F4]",children:[e.jsx("td",{className:`${v} font-medium`,style:{color:S},children:f.name||"Unknown"}),e.jsx("td",{className:`${v} whitespace-nowrap`,children:f.phone?e.jsx("a",{href:`tel:${f.phone}`,className:"hover:underline",style:{color:L},children:f.phone}):e.jsx("span",{style:{color:y},children:"—"})}),e.jsx("td",{className:`${v} max-w-[260px]`,style:{color:h},children:ae(f.last_text)}),e.jsx("td",{className:`${v} max-w-[180px]`,style:{color:y},children:f.spam_reason||e.jsx("span",{className:"italic",children:"not given"})}),e.jsx("td",{className:`${v} whitespace-nowrap`,style:{color:h},children:q(f.created_at)}),e.jsx("td",{className:`${v} text-right`,children:e.jsx("button",{onClick:()=>C(f.session_id),disabled:i===f.session_id,className:"text-[11px] bg-white border border-[#
22E5E8ED] hover:border-[#4338CA] hover:text-[#4338CA] px-2.5 py-1 rounded-[6px] disabled:opacity-50 whitespace-nowrap",style:{color:h},children:i===f.session_id?"…":"Not spam / Revert"})})]},f.session_id))})]})})]})]})]})}export{re 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.