1import{r as m,e as V,cg as Z,j as e,U as J,cn as W,f as X,aT as k,bm as w,a$ as Y,a_ as ee,aZ as te}from"./vendor-DZ4Bm0V6.js";import{A as se}from"./admin-layout-CQv2OQHM.js";import{a as P}from"./admin-auth-Brb0uAzS.js";import{u as ae,C as L,f as R,B as p,I as re,d as ie,e as ne,k as E,p as F,q as U,r as j,s as S,t as B,v as o,y as oe}from"./ec2-main-entry-l5BaOXr2.js";import{A as ce,b as le,c as de,d as ue,e as he,f as me,g as pe,h as xe}from"./alert-dialog-CvJBjAuh.js";function K(r){if(!r)return"â";const a=new Date(r);return isNaN(a.getTime())?"â":a.toLocaleDateString("en-GB",{day:"2-digit",month:"short",year:"numeric"})}function ge(r){if(!r)return"â";const a=new Date(r);return isNaN(a.getTime())?"â":a.toLocaleString("en-GB",{day:"2-digit",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"})}function je(r){const a=(r||"").toUpperCase().replace(/\s+/g,"");return a.length>3?`${a.slice(0,a.length-3)} ${a.slice(a.length-3)}`:a||"â"}function z(r){if(r.shape){const a=r.postcode.includes(":")?r.postcode.split(":")[1]:r.postcode;return`${r.shape.charAt(0).toUpperCase()+r.shape.slice(1)} #${a}`}return je(r.postcode)}function fe(r){if(r.shape)return"Area report";const a=parseFloat(r.miles);return a?`${a} mile${a===1?"":"s"}`:"â"}function _(r,a,f){const n=r[a];return f==="number"?parseFloat(n)||0:f==="date"?n&&new Date(n).getTime()||0:(n??"").toString().toLowerCase()}function Ce(){const{toast:r}=ae(),[a,f]=m.useState("customers"),[n,y]=m.useState(1),[$,H]=m.useState(""),[D,I]=m.useState(""),[x,q]=m.useState(!1),[d,A]=m.useState({key:null,type:"string",dir:"asc"}),[l,b]=m.useState(null),{data:i,isLoading:M}=V({queryKey:["/api/admin/report-purchases",a,n,$,x],queryFn:async()=>{const t=new URLSearchParams({view:a});x?t.set("all","1"):t.set("page",String(n)),$&&t.set("search",$);const s=await P(`/api/admin/report-purchases?${t}`);if(!s.ok)throw new Error("Failed to fetch report purchases");return s.json()}}),C=Z({mutationFn:async t=>{const s=t.type==="purchase"?`/api/admin/report-purchases/purchase/${t.rid}`:`/api/admin/report-purchases/customer?email=${encodeURIComponent(t.email)}`,c=await P(s,{method:"DELETE"});if(!c.ok){let g=`Delete failed (${c.status})`;try{const h=await c.json();h?.error&&(g=h.error)}catch{}throw new Error(g)}return c.json()},onSuccess:(t,s)=>{r({title:s.type==="purchase"?"Purchase deleted":"Customer deleted",description:s.type==="purchase"?"Removed 1 purchase record.":`Removed ${t.deleted} purchase${t.deleted===1?"":"s"} for ${s.email}.`}),oe.invalidateQueries({queryKey:["/api/admin/report-purchases"]}),b(null)},onError:t=>{r({title:"Delete failed",description:t?.message||"Unknown error",variant:"destructive"})}}),v=m.useMemo(()=>{const t=[...i?.rows??[]];if(!d.key)return t;const s=d.key;return t.sort((c,g)=>{const h=_(c,s,d.type),N=_(g,s,d.type);return h<N?d.dir==="asc"?-1:1:h>N?d.dir==="asc"?1:-1:0}),t},[i,d]);function G(t,s){A(c=>c.key===t?{key:t,type:s,dir:c.dir==="asc"?"desc":"asc"}:{key:t,type:s,dir:"asc"})}function O(t){t.preventDefault(),y(1),H(D)}function T(t){t!==a&&(f(t),y(1),A({key:null,type:"string",dir:"asc"}))}function u({label:t,sortKey:s,type:c,className:g}){const h=d.key===s,N=h?d.dir==="asc"?ee:te:Y;return e.jsx(S,{className:g,children:e.jsxs("button",{type:"button",className:`inline-flex items-center gap-1 hover:text-foreground ${h?"text-foreground font-semibold":""}`,onClick:()=>G(s,c),"data-testid":`sort-${s}`,children:[t," ",e.jsx(N,{className:"w-3.5 h-3.5 opacity-70"})]})})}const Q=a==="customers"?i?`${i.total} customers`:"Customers":i?`${i.total} purchases`:"Purchases";return e.jsxs(se,{children:[e.jsxs("div",{"data-testid":"admin-report-purchases-page",children:[e.jsx("h1",{className:"text-2xl font-bold mb-2","data-testid":"text-page-title",children:"Report Purchases"}),e.jsxs("p",{className:"text-sm text-muted-foreground mb-4",children:["History of customers who bought postcode and area reports. Credit codes are managed on the"," ",e.jsx("a",{href:"/admin/codes",className:"underline","data-testid":"link-codes",children:"Codes"})," page."]}),e.jsx(L,{className:"mb-4",children:e.jsxs(R,{className:"pt-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",children:[e.jsxs("div",{className:"flex flex-wrap gap-2","data-testid":"view-toggle",children:[e.jsxs(p,{variant:a==="customers"?"default":"outline",size:"sm",onClick:()=>T("customers"),"data-testid":"button-view-customers",children:[e.jsx(J,{className:"w-4 h-4 mr-1"})," By Customer"]}),e.jsxs(p,{variant:a==="purchases"?"default":"outline",size:"sm",onClick:()=>T("purchases"),"data-testid":"button-view-purchases",children:[e.jsx(W,{className:"w-4 h-4 mr-1"})," All Purchases"]}),e.jsx(p,{variant:x?"secondary":"outline",size:"sm",onClick:()=>{q(t=>!t),y(1)},"data-testid":"button-toggle-show-all",children:x?"Showing all on one page":"Show all on one page"})]}),e.jsxs("form",{onSubmit:O,className:"flex items-center gap-2 sm:w-96","data-testid":"form-search",children:[e.jsx(re,{placeholder:a==="customers"?"Search by email...":"Search by email or postcode...",value:D,onChange:t=>I(t.target.value),"data-testid":"input-search"}),e.jsxs(p,{type:"submit","data-testid":"button-search",children:[e.jsx(X,{className:"w-4 h-4 mr-1"})," Search"]})]})]})}),e.jsxs(L,{children:[e.jsxs(ie,{className:"flex flex-row items-center justify-between gap-2 space-y-0 pb-2",children:[e.jsx(ne,{"data-testid":"text-total-count",children:Q}),i&&!x&&i.pages>1&&e.jsxs(E,{variant:"secondary","data-testid":"badge-page-info",children:["Page ",i.page," of ",i.pages]}),x&&i&&e.jsx(E,{variant:"secondary","data-testid":"badge-show-all",children:"Single page"})]}),e.jsxs(R,{children:[M?e.jsx("div",{className:"flex justify-center py-8","data-testid":"loading-spinner",children:e.jsx(k,{className:"w-6 h-6 animate-spin text-muted-foreground"})}):a==="customers"?e.jsxs(F,{"data-testid":"table-customers",children:[e.jsx(U,{children:e.jsxs(j,{children:[e.jsx(u,{label:"Customer Email",sortKey:"email",type:"string"}),e.jsx(u,{label:"Reports Bought",sortKey:"reports",type:"number",className:"text-right"}),e.jsx(u,{label:"First Purchase",sortKey:"first_purchase",type:"date"}),e.jsx(u,{label:"Last Purchase",sortKey:"last_purchase",type:"date"}),e.jsx(S,{className:"text-right",children:"Actions"})]})}),e.jsxs(B,{children:[v.map((t,s)=>e.jsxs(j,{"data-testid":`row-customer-${s}`,children:[e.jsx(o,{"data-testid":`text-email-${s}`,children:t.email}),e.jsx(o,{className:"text-right font-medium","data-testid":`text-reports-${s}`,children:t.reports}),e.jsx(o,{"data-testid":`text-first-${s}`,children:K(t.first_purchase)}),e.jsx(o,{"data-testid":`text-last-${s}`,children:K(t.last_purchase)}),e.jsx(o,{className:"text-right",children:e.jsx(p,{variant:"ghost",size:"icon",className:"text-destructive hover:text-destructive",onClick:()=>b({type:"customer",email:t.email,reports:t.reports}),"data-testid":`button-delete-customer-${s}`,title:"Delete this customer and all their purchases",children:e.jsx(w,{className:"w-4 h-4"})})})]},`${t.email}-${s}`)),v.length===0&&e.jsx(j,{children:e.jsx(o,{colSpan:5,className:"text-center text-muted-foreground py-8",children:"No customers found."})})]})]}):e.jsxs(F,{"data-testid":"table-purchases",children:[e.jsx(U,{children:e.jsxs(j,{children:[e.jsx(u,{label:"Customer Email",sortKey:"email",type:"string"}),e.jsx(u,{label:"Postcode / Area",sortKey:"postcode",type:"string"}),e.jsx(u,{label:"Radius",sortKey:"miles",type:"number"}),e.jsx(u,{label:"Purchased",sortKey:"purchase_date",type:"date"}),e.jsx(S,{className:"text-right",children:"Actions"})]})}),e.jsxs(B,{children:[v.map((t,s)=>e.jsxs(j,{"data-testid":`row-purchase-${s}`,children:[e.jsx(o,{"data-testid":`text-email-${s}`,children:t.email||e.jsx("span",{className:"text-muted-foreground",children:"â"})}),e.jsx(o,{className:"font-mono text-sm","data-testid":`text-area-${s}`,children:z(t)}),e.jsx(o,{"data-testid":`text-radius-${s}`,children:fe(t)}),e.jsx(o,{"data-testid":`text-date-${s}`,children:ge(t.purchase_date)}),e.jsx(o,{className:"text-right",children:e.jsx(p,{variant:"ghost",size:"icon",className:"text-destructive hover:text-destructive",onClick:()=>b({type:"purchase",rid:t.rid,label:`${z(t)} â ${t.email||"no email"}`}),"data-testid":`button-delete-purchase-${s}`,title:"Delete this purchase",children:e.jsx(w,{className:"w-4 h-4"})})})]},`${t.rid}-${s}`)),v.length===0&&e.jsx(j,{children:e.jsx(o,{colSpan:5,className:"text-center text-muted-foreground py-8",children:"No purchases found."})})]})]}),i&&!x&&i.pages>1&&e.jsxs("div",{className:"flex items-center justify-center gap-2 mt-4","data-testid":"pagination",children:[e.jsx(p,{variant:"outline",size:"sm",disabled:n<=1,onClick:()=>y(n-1),"data-testid":"button-prev-page",children:"Previous"}),e.jsxs("span",{className:"text-sm text-muted-foreground","data-testid":"text-page-indicator",children:[n," / ",i.pages]}),e.jsx(p,{variant:"outline",size:"sm",disabled:n>=i.pages,onClick:()=>y(n+1),"data-testid":"button-next-page",children:"Next"})]})]})]})]}),e.jsx(ce,{open:!!l,onOpenChange:t=>{t||b(null)},children:e.jsxs(le,{"data-testid":"dialog-delete-confirm",children:[e.jsxs(de,{children:[e.jsx(ue,{children:l?.type==="customer"?"Delete customer?":"Delete purchase?"}),e.jsx(he,{children:l?.type==="customer"?e.jsxs(e.Fragment,{children:["This permanently deletes ",e.jsx("strong",{children:l.email})," and all"," ",e.jsx("strong",{children:l.reports})," of their report purchase record",l.reports===1?"":"s",". This cannot be undone."]}):l?e.jsxs(e.Fragment,{children:["This permanently deletes the purchase record for"," ",e.jsx("strong",{children:l.label}),". This cannot be undone."]}):null})]}),e.jsxs(me,{children:[e.jsx(pe,{"data-testid":"button-cancel-delete",children:"Cancel"}),e.jsxs(xe,{className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",disabled:C.isPending,onClick:t=>{t.preventDefault(),l&&C.mutate(l)},"data-testid":"button-confirm-delete",children:[C.isPending?e.jsx(k,{className:"w-4 h-4 mr-1 animate-spin"}):e.jsx(w,{className:"w-4 h-4 mr-1"}),"Delete"]})]})]})})]})}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.