1import{r as x,b as v,a7 as A,j as e,a8 as N,v as I,E as m,l as p,K as E,a9 as T}from"./index-CUacjr6u.js";import{M}from"./Modal-3u2-SC5e.js";import"./useModalLock-BCou8JEy.js";const b=50,S={unhealthy_status:"Unhealthy",subscription_refunded:"Refund",credit_topup_refunded:"Top-up refund",dispute_opened:"Dispute"},k={unhealthy_status:"bg-amber-100 text-amber-900 border-amber-200",subscription_refunded:"bg-rose-100 text-rose-900 border-rose-200",credit_topup_refunded:"bg-rose-100 text-rose-900 border-rose-200",dispute_opened:"bg-violet-100 text-violet-900 border-violet-200"},L={active:"bg-emerald-100 text-emerald-900 border-emerald-200",past_due:"bg-amber-100 text-amber-900 border-amber-200",payment_failed:"bg-rose-100 text-rose-900 border-rose-200",canceled:"bg-neutral-100 text-neutral-700 border-neutral-200",trialing:"bg-sky-100 text-sky-900 border-sky-200"};function _(t){return L[t.toLowerCase()]??"bg-neutral-100 text-neutral-700 border-neutral-200"}function D(t){if(!t)return"â";const r=new Date(t).getTime();if(Number.isNaN(r))return t;const s=r-Date.now(),o=Math.abs(s),i=s>0,d=Math.round(o/1e3);if(d<60)return i?`in ${d} sec`:`${d} sec ago`;const c=Math.round(d/60);if(c<60)return i?`in ${c} min`:`${c} min ago`;const n=Math.round(c/60);if(n<24)return i?`in ${n} hr`:`${n} hr ago`;const l=Math.round(n/24);return i?`in ${l}d`:`${l}d ago`}function $(t,r){const[s,o]=x.useState(t);return x.useEffect(()=>{const i=setTimeout(()=>o(t),r);return()=>clearTimeout(i)},[t,r]),s}const F={searchInput:"",plan:"",cycle:"",provider:"",status:"",attentionOnly:!1,endingSoon:!1};
1function G(){const[t,r]=x.useState(F),[s,o]=x.useState(0),[i,d]=x.useState(null),c=$(t.searchInput,300),n=x.useCallback((a,w)=>{r(C=>({...C,[a]:w}))},[]);x.useEffect(()=>{o(0)},[c,t.plan,t.cycle,t.provider,t.status,t.attentionOnly,t.endingSoon]);const l={query:c.trim(),plan:t.plan||void 0,cycle:t.cycle||void 0,provider:t.provider||void 0,status:t.status||void 0,attention:t.attentionOnly||void 0,endingSoon:t.endingSoon||void 0,offset:s},{data:h,isLoading:g,isError:P,error:f}=v({queryKey:["admin-subscriptions",l],queryFn:()=>A({query:l.query||void 0,plan:l.plan,cycle:l.cycle,provider:l.provider,status:l.status,attention:l.attention,endingSoon:l.endingSoon,limit:b,offset:s}),refetchInterval:6e4}),y=h?.subscriptions??[],j=h?.pagination.hasMore??!1;return e.jsxs("div",{className:"px-4 sm:px-6 lg:px-8 py-6 max-w-[1280px] mx-auto",children:[e.jsx("div",{className:"flex items-start justify-between mb-6",children:e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-semibold text-label flex items-center gap-2",children:[e.jsx(N,{className:"w-6 h-6 text-tint"})," Subscriptions"]}),e.jsx("p",{className:"text-secondary-label text-sm mt-1",children:"Read-only inspector for user subscription state and recent billing events. Lifecycle actions (cancel / refund / extend) are handled in PayPal / Stripe â this page surfaces them after the fact via webhook events."})]})}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 mb-4 p-3 border border-border rounded-lg bg-background-secondary",children:[e.jsxs("div",{className:"relative",children:[e.jsx(I,{className:"w-4 h-4 absolute left-2.5 top-1/2 -translate-y-1/2 text-secondary-label"}),e.jsx("input",{type:"text",placeholder:"Search email or user idâ¦",value:t.searchInput,onChange:a=>n("searchInput",a.target.value),className:"text-sm pl-8 pr-3 py-1.5 border border-border rounded-md bg-background w-64 max-w-full","aria-label":"Search subscriptions"})]}),e.jsxs("select",{"aria-label":"Filter by plan",className:"text-sm border border-border rounded-md px-2 py-1.5 bg-background",value:t.plan,onChange:a=>n("plan",a.target.value),children:[e.jsx("option",{value:"",children:"All plans"}),e.jsx("option",{value:"free",children:"Free"}),e.jsx("option",{value:"hobby",children:"Hobby"}),e.jsx("option",{value:"pro",children:"Pro"})]}),e.jsxs("select",{"aria-label":"Filter by cycle",className:"text-sm border border-border rounded-md px-2 py-1.5 bg-background",value:t.cycle,onChange:a=>n("cycle",a.target.value),children:[e.jsx("option",{value:"",children:"All cycles"}),e.jsx("option",{value:"monthly",children:"Monthly"}),e.jsx("option",{value:"yearly",children:"Annual"})]}),e.jsxs("select",{"aria-label":"Filter by provider",className:"text-sm border border-border rounded-md px-2 py-1.5 bg-background",value:t.provider,onChange:a=>n("provider",a.target.value),children:[e.jsx("option",{value:"",children:"All providers"}),e.jsx("option",{value:"stripe",children:"Stripe"}),e.jsx("option",{value:"paypal",children:"PayPal"})]}),e.jsxs("select",{"aria-label":"Filter by status",className:"text-sm border border-border rounded-md px-2 py-1.5 bg-background",value:t.status,onChange:a=>n("status",a.target.value),children:[e.jsx("option",{value:"",children:"All statuses"}),e.jsx("option",{value:"active",children:"Active"}),e.jsx("option",{value:"past_due",children:"Past due"}),e.jsx("option",{value:"payment_failed",children:"Payment failed"}),e.jsx("option",{value:"canceled",children:"Canceled"}),e.jsx("option",{value:"trialing",children:"Trialing"}),e.jsx("option",{value:"incomplete",children:"Incomplete"})]}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs px-2 py-1.5 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:t.attentionOnly,onChange:a=>n("attentionOnly",a.target.checked),"aria-label":"Attention only"}),"Attention only"]}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs px-2 py-1.5 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:t.endingSoon,onChange:a=>n("endingSoon",a.target.checked),"aria-label":"Ending in 7 days"}),"Ending in 7 days"]})]}),P?e.jsxs("div",{className:"border border-red-200 bg-red-50 rounded-lg p-4 text-sm text-red-900",children:["Failed to load subscriptions:"," ",f instanceof Error?f.message:"unknown error"]}):g?e.jsx(q,{}):y.length===0?e.jsx(z,{}):e.jsxs("div",{className:"border border-border rounded-lg overflow-hidden","data-testid":"subscriptions-list",children:[e.jsxs("div",{className:"grid grid-cols-[1.5fr_0.8fr_0.8fr_0.8fr_1fr_140px] gap-3 items-center px-4 py-2 bg-background-secondary border-b border-border text-[10px] font-semibold uppercase tracking-wide text-tertiary-label",children:[e.jsx("span",{children:"User"}),e.jsx("span",{children:"Plan"}),e.jsx("span",{children:"Provider"}),e.jsx("span",{children:"Status"}),e.jsx("span",{children:"Attention"}),e.jsx("span",{children:"Period end"})]}),y.map(a=>e.jsx(U,{row:a,onClick:()=>d(a.userId)},a.userId))]}),!g&&(s>0||j)?e.jsxs("div",{className:"flex items-center justify-center gap-3 mt-4 text-sm",children:[e.jsx("button",{type:"button",onClick:()=>o(Math.max(0,s-b)),disabled:s===0,className:"px-3 py-1.5 border border-border rounded-md disabled:opacity-50",children:"â Prev"}),e.jsxs("span",{className:"text-secondary-label",children:["Page ",Math.floor(s/b)+1]}),e.jsx("button",{type:"button",onClick:()=>o(s+b),disabled:!j,className:"px-3 py-1.5 border border-border rounded-md disabled:opacity-50",children:"Next â¶"})]}):null,e.jsx(K,{userId:i,onClose:()=>d(null)})]})}function U({row:t,onClick:r}){return e.jsxs("div",{className:"grid grid-cols-[1.5fr_0.8fr_0.8fr_0.8fr_1fr_140px] gap-3 items-start p-3 cursor-pointer focus-visible:outline focus-visible:outline-2 focus-visible:outline-tint focus-visible:-outline-offset-2 hover:bg-background-secondary/50 border-b border-border last:border-b-0 bg-background",onClick:r,onKeyDown:s=>{(s.key==="Enter"||s.key===" ")&&(s.preventDefault(),r())},role:"button",tabIndex:0,"data-testid":`subscription-row-${t.userId}`,"aria-label":`Open detail for ${t.email??t.userId}`,children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-sm font-medium text-label truncate",title:t.email??"",children:t.email||t.displayName||t.userId}),e.jsx("div",{className:"text-[10px] text-tertiary-label font-mono truncate",children:t.userId})]}),e.jsxs("div",{className:"text-xs text-label",children:[e.jsx("div",{className:"font-medium capitalize",children:t.planKey}),e.jsx("div",{className:"text-tertiary-label",children:t.billingCycle}),t.pendingPlanKey?e.jsxs("div",{className:"text-[10px] text-amber-700 mt-0.5",title:t.pendingChangeAt?`Changes ${new Date(t.pen
1dingChangeAt).toLocaleString()}`:"Change scheduled",children:["â ",t.pendingPlanKey," ",t.pendingBillingCycle??""]}):null]}),e.jsx("div",{className:"text-xs",children:t.providerSubscriptionUrl&&t.providerSubscriptionId?e.jsxs("a",{href:t.providerSubscriptionUrl,target:"_blank",rel:"noopener noreferrer",onClick:s=>s.stopPropagation(),className:"inline-flex items-center gap-1 text-tint hover:underline","data-testid":`provider-link-${t.userId}`,title:`Open in ${t.billingProvider} dashboard`,children:[e.jsx("span",{className:"capitalize",children:t.billingProvider}),e.jsx(m,{className:"w-3 h-3"})]}):e.jsx("span",{className:"text-tertiary-label",children:t.billingProvider??"â"})}),e.jsxs("div",{children:[e.jsx("span",{className:p("inline-flex items-center text-[10px] px-1.5 py-0.5 rounded border w-fit capitalize",_(t.status)),children:t.status.replace(/_/g," ")}),t.cancelAtPeriodEnd?e.jsx("div",{className:"text-[10px] text-amber-700 mt-0.5",children:"Canceling at period end"}):null]}),e.jsx("div",{className:"flex flex-wrap gap-1",children:t.attentionReasons.map(s=>e.jsxs("span",{className:p("inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded border",k[s]),"data-testid":`attention-badge-${s}`,children:[e.jsx(E,{className:"w-2.5 h-2.5"}),S[s]]},s))}),e.jsx("div",{className:"text-xs text-secondary-label",children:D(t.currentPeriodEnd)})]})}function K({userId:t,onClose:r}){const{data:s,isLoading:o,isError:i,error:d}=v({queryKey:["admin-subscription-detail",t],queryFn:()=>{if(!t)throw new Error("no userId");return T(t)},enabled:!!t});return t?e.jsx(M,{open:!0,onClose:r,title:"Subscription detail",size:"xl",children:e.jsx("div",{className:"px-6 py-4 overflow-y-auto",style:{maxHeight:"75vh"},"data-testid":"subscription-detail-modal",children:o?e.jsx("output",{"aria-live":"polite",className:"block text-secondary-label text-sm",children:"Loadingâ¦"}):i?e.jsxs("div",{className:"border border-red-200 bg-red-50 rounded-lg p-4 text-sm text-red-900",children:["Failed to load detail:"," ",d instanceof Error?d.message:"unknown error"]}):s?e.jsx(O,{data:s}):e.jsx("div",{className:"text-secondary-label text-sm",children:"No data"})})}):null}function O({data:t}){const r=t.subscription;return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("section",{children:[e.jsx("h2",{className:"text-xs uppercase tracking-wide text-tertiary-label mb-2",children:"Subscription"}),r?e.jsxs("div",{className:"grid grid-cols-2 gap-3 text-xs",children:[e.jsxs(u,{label:"User",children:[e.jsx("div",{children:r.email??"â"}),e.jsx("div",{className:"font-mono text-[10px] text-tertiary-label",children:r.userId})]}),e.jsxs(u,{label:"Plan",children:[r.planKey," (",r.billingCycle,")",r.pendingPlanKey?e.jsxs("div",{className:"text-amber-700 mt-0.5",children:["Switching to ",r.pendingPlanKey," ",r.pendingBillingCycle??"",r.pendingChangeAt?` on ${new Date(r.pendingChangeAt).toLocaleString()}`:""]}):null]}),e.jsx(u,{label:"Status",children:e.jsx("span",{className:p("inline-flex items-center text-[10px] px-1.5 py-0.5 rounded border w-fit capitalize",_(r.status)),children:r.status.replace(/_/g," ")})}),e.jsx(u,{label:"Provider",children:r.providerSubscriptionUrl?e.jsxs("a",{href:r.providerSubscriptionUrl,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 text-tint hover:underline",children:[e.jsx("span",{className:"capitalize",children:r.billingProvider})," ",e.jsx(m,{className:"w-3 h-3"})]}):r.billingProvider??"â"}),e.jsxs(u,{label:"Period",children:[new Date(r.currentPeriodStart).toLocaleString()," â"," ",new Date(r.currentPeriodEnd).toLocaleString(),r.cancelAtPeriodEnd?e.jsx("div",{className:"text-amber-700 mt-0.5",children:"Canceling at period end"}):null]}),e.jsx(u,{label:"Attention",children:r.attentionReasons.length===0?e.jsx("span",{className:"text-tertiary-label",children:"healthy"}):e.jsx("div",{className:"flex flex-wrap gap-1",children:r.attentionReasons.map(s=>e.jsx("span",{className:p("inline-flex items-center text-[10px] px-1.5 py-0.5 rounded border",k[s]),children:S[s]},s))})})]}):e.jsx("div",{className:"text-sm text-secondary-label italic",children:"No subscription row for this user."})]}),e.jsxs("section",{children:[e.jsxs("h2",{className:"text-xs uppercase tracking-wide text-tertiary-label mb-2",children:["Recent billing events (",t.events.length,")"]}),t.events.length===0?e.jsx("div",{className:"text-sm text-secondary-label italic",children:"No billing events yet."}):e.jsx("div",{className:"border border-border rounded overflow-hidden",children:t.events.map(s=>e.jsx(R,{event:s},s.id))})]})]})}function R({event:t}){const r=t.fulfillmentStatus==="failed"||t.errorMessage!==null;return e.jsxs("div",{className:p("px-3 py-2 text-xs border-b border-border last:border-b-0",r?"bg-rose-50/40":"bg-background"),children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx("span",{className:"font-mono text-[11px] text-label",children:t.eventType}),e.jsx("span",{className:p("text-[10px] px-1.5 py-0.5 rounded border",t.fulfillmentStatus==="processed"?"bg-emerald-100 text-emerald-900 border-emerald-200":t.fulfillmentStatus==="failed"?"bg-rose-100 text-rose-900 border-rose-200":"bg-amber-100 text-amber-900 border-amber-200"),children:t.fulfillmentStatus})]}),e.jsxs("div",{className:"flex items-center gap-2 text-[11px] text-tertiary-label",children:[e.jsx("span",{children:new Date(t.createdAt).toLocaleStr
1ing()}),t.externalPaymentUrl?e.jsxs("a",{href:t.externalPaymentUrl,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-0.5 text-tint hover:underline",title:"Open payment in provider dashboard",children:["payment ",e.jsx(m,{className:"w-3 h-3"})]}):null]})]}),t.errorMessage?e.jsx("div",{className:"mt-1 text-rose-900 text-[11px] font-mono","data-testid":"event-error",children:t.errorMessage}):null,e.jsx("div",{className:"mt-1 text-[10px] text-tertiary-label font-mono truncate",children:t.externalEventId})]})}function u({label:t,children:r}){return e.jsxs("div",{children:[e.jsx("div",{className:"text-tertiary-label uppercase tracking-wide text-[10px] mb-1",children:t}),e.jsx("div",{className:"text-sm text-label",children:r})]})}function q(){return e.jsx("div",{className:"border border-border rounded-lg overflow-hidden",children:Array.from({length:5}).map((t,r)=>e.jsxs("div",{className:"grid grid-cols-[1.5fr_0.8fr_0.8fr_0.8fr_1fr_140px] gap-3 items-start p-3 border-b border-border last:border-b-0",children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("div",{className:"h-3 w-1/2 bg-background-tertiary rounded animate-pulse"}),e.jsx("div",{className:"h-2.5 w-3/4 bg-background-tertiary rounded animate-pulse"})]}),e.jsx("div",{className:"h-3 w-16 bg-background-tertiary rounded animate-pulse"}),e.jsx("div",{className:"h-3 w-16 bg-background-tertiary rounded animate-pulse"}),e.jsx("div",{className:"h-3 w-16 bg-background-tertiary rounded animate-pulse"}),e.jsx("div",{className:"h-3 w-20 bg-background-tertiary rounded animate-pulse"}),e.jsx("div",{className:"h-3 w-16 bg-background-tertiary rounded animate-pulse"})]},r))})}function z(){return e.jsxs("div",{className:"border border-border rounded-lg p-12 text-center bg-background-secondary/30","data-testid":"subscriptions-empty",children:[e.jsx(N,{className:"w-10 h-10 mx-auto text-secondary-label mb-3"}),e.jsx("div",{className:"font-semibold text-label",children:"No subscriptions match the current filters"}),e.jsx("p",{className:"text-sm text-secondary-label mt-1",children:"Try clearing filters or widening the search."})]})}export{G as AdminSubscriptions};
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.