PageSourceSearch

https://pixelbunny.ai/assets/AdminChargebackBulk-Dh2r6CMb.js

js pixelbunny.ai collected 2026-10-05 12:24:52 UTC 9,338 bytes, 4 lines download raw bytes

1import{r as g,j as e,C as w,f as k,U as P,B as z,y as B,M as F,L as R,aO as J,k as Z,V as m,s as D}from"./index-6Cb8ZntX.js";import{T as A,a as L,b as E,c as S,d as U,e as v}from"./table-YD_FdNbp.js";import{A as M}from"./AdminPageHeader-DXPFizzh.js";import{F as H}from"./file-archive-ISjAf3ua.js";const X=["fraudulent","product_not_received","product_unacceptable","subscription_canceled","duplicate","credit_not_processed","general"];function G(l){const t=[];let i=[],n="",x=!1;for(let d=0;d<l.length;d++){const o=l[d];x?o==='"'?l[d+1]==='"'?(n+='"',d++):x=!1:n+=o:o==='"'?x=!0:o===","?(i.push(n),n=""):o===`
2`?(i.push(n),t.push(i),i=[],n=""):o==="\r"||(n+=o)}if((n.length||i.length)&&(i.push(n),t.push(i)),t.length===0)return[];const f=t[0].map(d=>d.trim().toLowerCase());return t.slice(1).filter(d=>d.some(o=>o.trim())).map(d=>{const o={};return f.forEach((N,I)=>{o[N]=(d[I]??"").trim()}),o})}function Y(l){return l.map(t=>{const i=t.payment_intent||t.charge||t.id||t["payment intent id"]||t["charge id"]||t["dispute id"]||"",n=t.id||t["dispute id"]||(i.startsWith("dp_")?i:""),x=t.reason||"",f=t.evidence_due_by||t.due_by||t["evidence due by"]||t["due by"]||"";return{stripe_id:i,dispute_id:n&&n.startsWith("dp_")?n:void 0,dispute_reason:x||void 0,respond_by:f||void 0}}).filter(t=>t.stripe_id)}function Q(l){return l.split(/\r?\n/).map(t=>t.trim()).filter(Boolean).map(t=>{const i=t.split(",").map(n=>n.trim());return{stripe_id:i[0],dispute_id:i[1]||void 0,dispute_reason:i[2]||void 0,respond_by:i[3]||void 0}})}function se(){const[l,t]=g.useState(""),[i,n]=g.useState([]),[x,f]=g.useState(null),[d,o]=g.useState(!1),[N,I]=g.useState(!1),p=g.useMemo(()=>{const s=Q(l),r=new Map;for(const a of i)r.set(a.stripe_id,a);for(const a of s)r.has(a.stripe_id)||r.set(a.stripe_id,a);return[...r.values()]},[l,i]),O=async s=>{try{const r=await s.text(),a=G(r),h=Y(a);n(h),f(s.name),m.success(`Parsed ${h.length} row${h.length===1?"":"s"} from ${s.name}`)}catch(r){m.error((r==null?void 0:r.message)||"Failed to parse CSV")}},T=async()=>{if(p.length===0){m.error("Add at least one dispute id or upload a Stripe CSV.");return}if(p.length>100){m.error("Max 100 disputes per batch. Split the list and try again.");return}o(!0);try{const{data:s}=await D.auth.getSession();if(!s.session)throw new Error("Not signed in");const a=await fetch("https://esndhpasoxrwzxpzjlfg.supabase.co/functions/v1/admin-chargeback-evidence-bulk",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s.session.access_token}`,apikey:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImVzbmRocGFzb3hyd3p4cHpqbGZnIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzIzNDgxNjgsImV4cCI6MjA4NzkyNDE2OH0.cStXgyUmRDoaIctjoH4aNL2DUjjcnZLn_7VFNyEbdzE"},body:JSON.stringify({items:p})});if(!a.ok){const V=await a.json().catch(()=>({error:`HTTP ${a.status}`}));throw new Error(V.error||"Bulk build failed")}const h=await a.blob(),j=(a.headers.get("content-disposition")||"").match(/filename="([^"]+)"/),C=(j==null?void 0:j[1])||`pixelbunny-chargeback-batch-${Date.now()}.zip`,y=a.headers.get("x-ok"),b=a.headers.get("x-failed"),c=URL.createObjectURL(h),_=document.createElement("a");_.href=c,_.download=C,document.body.appendChild(_),_.click(),_.remove(),URL.revokeObjectURL(c),m.success(`Master ZIP ready — ${y} ok, ${b} failed (${(h.size/1024).toFixed(0)} KB)`)}catch(s){m.error((s==null?void 0:s.message)||"Bulk build failed")}finally{o(!1)}},$=async()=>{if(p.length===0){m.error("Add at least one dispute id first.");return}I(!0);let s=0,r=0,a=0,h=0;try{const u=new Set;for(const y of p){const{data:b}=await D.rpc("admin_lookup_by_stripe_id",{p_id:y.stripe_id});for(const c of b||[])c.user_id&&u.add(c.user_id)}if(u.size===0){m.error("Could not resolve any batch id to a user account.");return}const{data:j}=await D.auth.getSession();if(!j.session)throw new Error("Not signed in");const C="esndhpasoxrwzxpzjlfg";for(const y of u)try{const b=await fetch(`https://${C}.supabase.co/functions/v1/admin-fetch-stripe-snapshot`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${j.session.access_token}`,apikey:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImVzbmRocGFzb3hyd3p4cHpqbGZnIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzIzNDgxNjgsImV4cCI6MjA4NzkyNDE2OH0.cStXgyUmRDoaIctjoH4aNL2DUjjcnZLn_7VFNyEbdzE"},body:JSON.stringify({user_id:y,force:!1})}),c=await b.json();b.ok&&(c!=null&&c.summary)?(s+=c.summary.fetched??0,r+=c.summary.skipped_existing??0,a+=c.summary.no_charge_found??0,h+=c.summary.error??0):h+=1}catch{h+=1}m.success(`Snapshots (${u.size} user${u.size===1?"":"s"}): ${s} fetched, ${r} cached, ${a} unresolved, ${h} errored.`)}catch(u){m.error((u==null?void 0:u.message)||"Snapshot backfill failed")}finally{I(!1)}};return e.jsxs("div",{className:"p-4 md:p-6 space-y-4 max-w-6xl mx-auto",children:[e.jsx(M,{title:"Bulk Chargeback Evidence",subtitle:"Upload the Stripe Disputes CSV export (or paste ids) and build one master ZIP containing a full evidence packet for every disputed invoice."}),e.jsxs("div",{className:"grid md:grid-cols-2 gap-4",children:[e.jsx(w,{children:e.jsxs(k,{className:"p-4 space-y-3",children:[e.jsx("div",{className:"text-sm font-semibold",children:"1. Stripe Disputes CSV"}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["In Stripe Dashboard → Payments → Disputes, click ",e.jsx("b",{children:"Export"})," and drop the CSV here. We read ",e.jsx("code",{children:"payment_intent"}),", ",e.jsx("code",{children:"charge"}),", ",e.jsx("code",{children:"id"}),",",e.jsx("code",{children:"reason"}),", and ",e.jsx("code",{children:"evidence_due_by"}),"."]}),e.jsxs("label",{className:"flex flex-col items-center justify-center h-32 border border-dashed border-border rounded-md cursor-pointer hover:bg-accent/40 transition",onDragOver:s=>s.preventDefault(),onDrop:s=>{var a;s.preventDefault();const r=(a=s.dataTransfer.files)==null?void 0:a[0];r&&O(r)},children:[e.jsx(P,{className:"h-5 w-5 mb-2 text-muted-foreground"}),e.jsx("span",{className:"text-xs text-muted-foreground",children:x?`${x} — ${i.length} rows`:"Drop CSV or click to choose"}),e.jsx("input",{type:"file",accept:".csv,text/csv",className:"hidden",onChange:s=>{var a;const r=(a=s.target.files)==null?void 0:a[0];r&&O(r)}})]}),i.length>0&&e.jsxs(z,{variant:"ghost",size:"sm",onClick:()=>{n([]),f(null)},children:[e.jsx(B,{className:"h-4 w-4 mr-2"})," Clear CSV"]})]})}),e.jsx(w,{children:e.jsxs(k,{className:"p-4 space-y-3",children:[e.jsx("div",{className:"text-sm font-semibold",children:"2. Or paste ids (one per line)"}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Accepts ",e.jsx("code",{children:"pi_…"}),", ",e.jsx("code",{children:"ch_…"}),", ",e.jsx("code",{children:"cs_…"}),", ",e.jsx("code",{children:"evt_…"}),", or payment order ids. Optional extras on the same line, comma-separated:",e.jsx("code",{children:"stripe_id,dispute_id,reason,respond_by"}),"."]}),e.jsx(F,{rows:8,className:"font-mono text-xs",placeholder:`pi_3PabcXYZ...
3ch_1PdefRST...,dp_1P...
4pi_3Pghi...,,fraudulent,2026-07-20`,value:l,onChange:s=>t(s.target.value)})]})})]}),e.jsx(w,{children:e.jsxs(k,{className:"p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"text-sm font-semibold",children:["Resolved batch — ",p.length," dispute",p.length===1?"":"s"]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(z,{variant:"outline",onClick:$,disabled:N||p.length===0,title:"Fetch Stripe AVS/CVC/3DS/Radar data for every user in the batch and cache it. Powers 02b_payment_authentication.pdf in every packet.",children:[N?e.jsx(R,{className:"h-4 w-4 mr-2 animate-spin"}):e.jsx(J,{className:"h-4 w-4 mr-2"}),"Fetch Stripe snapshots"]}),e.jsxs(z,{onClick:T,disabled:d||p.length===0,children:[d?e.jsx(R,{className:"h-4 w-4 mr-2 animate-spin"}):e.jsx(H,{className:"h-4 w-4 mr-2"}),"Build master ZIP"]})]})]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs(A,{children:[e.jsx(L,{children:e.jsxs(E,{children:[e.jsx(S,{children:"Stripe id"}),e.jsx(S,{children:"Dispute id"}),e.jsx(S,{children:"Reason"}),e.jsx(S,{children:"Respond by"})]})}),e.jsxs(U,{children:[p.length===0&&e.jsx(E,{children:e.jsx(v,{colSpan:4,className:"text-center text-muted-foreground py-8 text-xs",children:"Add disputes above to build a packet."})}),p.map(s=>e.jsxs(E,{children:[e.jsx(v,{className:"font-mono text-xs",children:s.stripe_id}),e.jsx(v,{className:"font-mono text-xs",children:s.dispute_id||"—"}),e.jsx(v,{className:"text-xs",children:s.dispute_reason?e.jsx(Z,{variant:X.includes(s.dispute_reason)?"secondary":"outline",children:s.dispute_reason}):e.jsx("span",{className:"text-muted-foreground",children:"general"})}),e.jsx(v,{className:"text-xs",children:s.respond_by||"—"})]},s.stripe_id))]})]})}),e.jsxs("p",{className:"text-[11px] text-muted-foreground leading-5",children:["Each packet is built in series to stay under the edge-function memory budget. The master ZIP contains ",e.jsx("code",{children:"INDEX.csv"}),", ",e.jsx("code",{children:"unresolved.csv"}),", ",e.jsx("code",{children:"README.txt"}),"and ",e.jsx("code",{children:"packets/*.zip"})," — one full evidence ZIP per dispute, ready to unzip and upload into Stripe's dispute form."]})]})})]})}export{se 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.