PageSourceSearch

https://atomikhub.com/assets/client-detail-BJG9XTG9.js

js atomikhub.com collected 2026-10-03 21:16:38 UTC 55,781 bytes, 5 lines download raw bytes

1import{u as $,gq as De,t as Re,r as l,gu as Te,j as e,s as z,b0 as _e,az as Se,b1 as fe,B as P,v as Ce,w as Z,aF as se,aG as re,aA as Ae,bZ as X,x as K,a$ as k,aO as J,aN as je,U as Ie,ab as V,e as Me,gv as B,iR as $e,bk as Fe,aW as le,aX as ne,aY as de,aZ as ce,iS as Oe,aP as Ve,b5 as oe}from"./index-DCYDlreI-ms8gbr5h.js";import{C as Be}from"./ChartHint-ClkSXLqS.js";import{S as ke}from"./save-DHAtDh6P.js";import{C as ve}from"./circle-pause-cElZcjJR.js";import{C as Ne}from"./circle-play-8lk7dyp7.js";import{C as Le}from"./calendar-DwfrZ1o5.js";import{P as Ue}from"./plus-Cg7ahvLS.js";import{B as ye}from"./ban-DcfYaGy_.js";const qe=["free_trial","free","starter","pro","business","enterprise","adm"];function dt(){const{t:i,i18n:d}=$("admin"),o=d.language,S=De(),r=Number(S.clientId),[,t]=Re(),[s,b]=l.useState(null),[h,p]=l.useState(!0),[w,x]=l.useState(null),[a,g]=l.useState(!1),[A,m]=l.useState(null);Te(s?i("client_detail.shell_title",`Cliente ${s.companyName||s.clientId}`,{name:s.companyName||s.clientId}):i("client_detail.shell_loading","Cliente"));const[_,R]=l.useState(""),[c,E]=l.useState(""),[f,v]=l.useState(""),[D,L]=l.useState(null),[pe,T]=l.useState(!1),[Q,C]=l.useState(null),[me,G]=l.useState(!1),[F,q]=l.useState(!1),[W,I]=l.useState(!1);async function U(){p(!0),x(null);try{const u=await B(`/api/admin/clients/${r}`);if(u.status===401||u.status===403){t("/admin-atomik-hub/login");return}const y=await u.json();y?.ok&&y.client?(b(y.client),R(y.client.tier),E(y.client.subscription_status??""),v(y.client.notes??"")):x(y?.error||i("client_detail.errors.not_found","Client not found"))}catch(u){x(u instanceof Error?u.message:String(u))}finally{p(!1)}}async function Y(){try{const y=await(await B(`/api/admin/clients/${r}/billing`)).json();y?.ok&&y.billing&&L(y.billing)}catch{}}l.useEffect(()=>{U(),Y()},[r]);function H(u){const y=D?.manualPayments.find(n=>n.id===u)??null;y&&C(y)}async function ue(u,y,n){g(!0),x(null),m(null);try{const j=await B(`/api/admin/clients/${r}${y}`,{method:u,headers:{"Content-Type":"application/json"},body:n?JSON.stringify(n):void 0}),O=await j.json();return j.ok&&O.ok?!0:(x(O?.error||i("client_detail.errors.save_failed",`Falha (${j.status})`,{status:j.status})),!1)}catch(j){return x(j instanceof Error?j.message:String(j)),!1}finally{g(!1)}}async function xe(){await ue("PATCH","",{tier:_!==s?.tier?_:void 0,subscription_status:c!==(s?.subscription_status??"")?c:void 0,notes:f!==(s?.notes??"")?f:void 0})&&(m(i("client_detail.messages.saved","Changes saved.")),U())}function ee(){G(!0)}function be(){q(!0)}function ge(){I(!0)}return h?e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-background",children:e.jsx(z,{className:"w-8 h-8 text-amber-500 animate-spin"})}):w&&!s?e.jsxs("div",{className:"max-w-3xl mx-auto p-6",children:[e.jsxs(_e,{className:"bg-destructive/10 border-destructive/50",children:[e.jsx(Se,{className:"h-4 w-4 text-destructive"}),e.jsx(fe,{children:w})]}),e.jsxs(P,{variant:"outline",onClick:()=>t("/admin-atomik-hub/clients"),className:"mt-4",children:[e.jsx(Ce,{className:"w-4 h-4 mr-2"}),i("client_detail.back","Back")]})]}):s?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"max-w-6xl mx-auto p-6",children:[e.jsxs(P,{variant:"ghost",size:"sm",onClick:()=>t("/admin-atomik-hub/clients"),className:"mb-4 text-muted-foreground",children:[e.jsx(Ce,{className:"w-4 h-4 mr-2"}),i("client_detail.back_to_list","Back to list")]}),e.jsxs("div",{className:"mb-6",children:[e.jsxs("h1",{className:"text-2xl font-bold flex items-center gap-2",children:[s.companyName||s.tenant||i("client_detail.fallback_title",`Client #${s.clientId}`,{id:s.clientId}),e.jsx(Be,{size:"md",text:i("client_detail.page_hint","Detalhe completo de um cliente: usuários, assinatura, billing, scans, recursos descobertos, suporte aberto. Operações comuns: impersonate, mudar plano, suspender, exportar dados.")})]}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-1 font-mono",children:["clientId=",s.clientId," · type=",s.type," · tenant=",s.tenant??"—"]})]}),A&&e.jsx(_e,{className:"mb-4 bg-emerald-500/10 border-emerald-500/40",children:e.jsx(fe,{className:"text-emerald-500",children:A})}),w&&e.jsxs(_e,{className:"mb-4 bg-destructive/10 border-destructive/50",children:[e.jsx(Se,{className:"h-4 w-4 text-destructive"}),e.jsx(fe,{children:w})]}),e.jsxs("div",{className:"grid sm:grid-cols-2 lg:grid-cols-4 gap-3 mb-6",children:[e.jsx(he,{label:i("client_detail.info.current_tier","Current tier"),value:s.tier,variant:"amber"}),e.jsx(he,{label:i("client_detail.info.status","Status"),value:s.subscription_status??i("client_detail.info.empty_value","—"),variant:s.subscription_status==="suspended"?"rose":"cyan"}),e.jsx(he,{label:i("client_detail.info.members","Members"),value:String(s.members_count),variant:"violet"}),e.jsx(he,{label:i("client_detail.info.cloud_accounts","Cloud accounts"),value:String(s.cloud_providers.length),variant:"emerald"})]}),e.jsxs(Z,{className:"bg-card border-border mb-6",children:[e.jsxs(se,{children:[e.jsxs(re,{className:"text-sm flex items-center gap-2",children:[e.jsx(Ae,{className:"w-4 h-4 text-amber-500"}),i("client_detail.edit.title","Edit")]}),e.jsx(X,{children:i("client_detail.edit.description","Changes update the tier middleware cache in real time.")})]}),e.jsxs(K,{className:"space-y-3",children:[e.jsxs("div",{className:"grid sm:grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:i("client_detail.edit.tier","Tier")}
1),e.jsx("select",{value:_,onChange:u=>R(u.target.value),className:"w-full h-9 px-3 rounded-md bg-background border border-border text-sm",disabled:a,children:qe.map(u=>e.jsx("option",{value:u,children:u},u))})]}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:i("client_detail.edit.subscription_status","Subscription status")}),e.jsx(J,{value:c,onChange:u=>E(u.target.value),placeholder:i("client_detail.edit.subscription_placeholder","active | suspended | …"),disabled:a,className:"h-9"})]})]}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:i("client_detail.edit.notes","Notes (admin)")}),e.jsx("textarea",{value:f,onChange:u=>v(u.target.value),rows:3,disabled:a,className:"w-full px-3 py-2 rounded-md bg-background border border-border text-sm",placeholder:i("client_detail.edit.notes_placeholder","Internal notes — not visible to the client")})]}),e.jsxs("div",{className:"flex gap-2 pt-2",children:[e.jsxs(P,{onClick:xe,disabled:a,className:"bg-amber-500 hover:bg-amber-400 text-black",children:[a&&e.jsx(z,{className:"w-4 h-4 mr-2 animate-spin"}),e.jsx(ke,{className:"w-4 h-4 mr-2"}),i("client_detail.edit.save","Save")]}),s.subscription_status!=="suspended"?e.jsxs(P,{onClick:ee,disabled:a,variant:"outline",className:"border-amber-500/50 text-amber-500",children:[e.jsx(ve,{className:"w-4 h-4 mr-2"}),i("client_detail.edit.suspend","Suspend")]}):e.jsxs(P,{onClick:be,disabled:a,variant:"outline",className:"border-emerald-500/50 text-emerald-500",children:[e.jsx(Ne,{className:"w-4 h-4 mr-2"}),i("client_detail.edit.reactivate","Reactivate")]}),e.jsxs(P,{onClick:ge,disabled:a,variant:"outline",className:"border-destructive/50 text-destructive ml-auto",children:[e.jsx(je,{className:"w-4 h-4 mr-2"}),i("client_detail.edit.soft_delete","Soft-delete")]})]})]})]}),D&&e.jsx(Je,{billing:D,locale:o}),D&&e.jsx(ze,{billing:D,clientId:s.clientId,locale:o,onRegister:()=>T(!0),onVoid:H}),e.jsxs(Z,{className:"bg-card border-border mb-6",children:[e.jsx(se,{children:e.jsxs(re,{className:"text-sm flex items-center gap-2",children:[e.jsx(Ie,{className:"w-4 h-4 text-cyan-500"}),i("client_detail.members.title",`Members (${s.members_count})`,{count:s.members_count})]})}),e.jsx(K,{children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-border text-left text-xs text-muted-foreground",children:[e.jsx("th",{className:"py-2 pr-3",children:i("client_detail.members.name_email","Nome / E-mail")}),e.jsx("th",{className:"py-2 pr-3",children:i("client_detail.members.role","Role")}),e.jsx("th",{className:"py-2 pr-3",children:i("client_detail.members.permissions","Permissions")}),e.jsx("th",{className:"py-2 pr-3",children:i("client_detail.members.status","Status")}),e.jsx("th",{className:"py-2 pr-3",children:i("client_detail.members.last_login","Last login")})]})}),e.jsx("tbody",{children:s.members.map(u=>e.jsxs("tr",{className:"border-b border-border/50",children:[e.jsxs("td",{className:"py-2 pr-3",children:[e.jsx("div",{className:"font-medium text-sm",children:u.name}),e.jsx("code",{className:"text-xs text-muted-foreground",children:u.email})]}),e.jsx("td",{className:"py-2 pr-3",children:e.jsx(V,{variant:"outline",className:"text-xs",children:u.role})}),e.jsx("td",{className:"py-2 pr-3 text-xs",children:u.permissions.length}),e.jsx("td",{className:"py-2 pr-3",children:e.jsx(V,{variant:"outline",className:u.status==="active"?"text-xs border-emerald-500/50 text-emerald-500":"text-xs",children:u.status})}),e.jsx("td",{className:"py-2 pr-3 text-xs text-muted-foreground",children:u.last_login_at?new Date(u.last_login_at).toLocaleString(o):i("client_detail.members.empty","—")})]},u.auth0Sub))})]})})})]}),s.cloud_providers.length>0&&e.jsxs(Z,{className:"bg-card border-border",children:[e.jsx(se,{children:e.jsxs(re,{className:"text-sm flex items-center gap-2",children:[e.jsx(Me,{className:"w-4 h-4 text-cyan-500"}),i("client_detail.cloud.title",`Cloud accounts (${s.cloud_providers.length})`,{count:s.cloud_providers.length})]})}),e.jsx(K,{children:e.jsx("div",{className:"space-y-2",children:Object.entries(s.credentials_summary).map(([u,y])=>e.jsxs("div",{className:"flex items-center justify-between p-3 rounded-md border border-border",children:[e.jsxs("div",{children:[e.jsx(V,{variant:"outline",className:"text-xs border-cyan-500/40 text-cyan-500 mb-1",children:u.toUpperCase()}),e.jsx("div",{className:"text-xs text-muted-foreground",children:i("client_detail.cloud.configured_at","Configurado em {{date}}
1",{date:y.configured_at?new Date(y.configured_at).toLocaleString(o):i("client_detail.cloud.empty","—")})})]}),e.jsx(V,{variant:"outline",className:y.status==="success"?"border-emerald-500/50 text-emerald-500":y.status==="failed"?"border-destructive/50 text-destructive":"text-muted-foreground",children:y.status??i("client_detail.cloud.status_unknown","unknown")})]},u))})})]})]}),pe&&D&&e.jsx(Ye,{clientId:r,billing:D,onClose:()=>T(!1),onSaved:async()=>{T(!1),m(i("client_detail.billing.registered","Pagamento manual registrado.")),await Promise.all([U(),Y()])}}),Q&&e.jsx(He,{clientId:r,payment:Q,locale:o,onClose:()=>C(null),onVoided:async()=>{C(null),m(i("client_detail.billing.voided","Pagamento estornado.")),await Promise.all([U(),Y()])}}),me&&s&&e.jsx(Ze,{clientId:r,clientName:s.companyName||s.tenant||`#${s.clientId}`,tier:s.tier,onClose:()=>G(!1),onSuspended:async()=>{G(!1),m(i("client_detail.messages.suspended","Cliente suspenso.")),await U()}}),F&&s&&e.jsx(Ke,{clientId:r,clientName:s.companyName||s.tenant||`#${s.clientId}`,tier:s.tier,suspendedAt:s.suspended_at,suspendedBy:s.suspended_by,suspendedReason:s.suspended_reason,onClose:()=>q(!1),onReactivated:async()=>{q(!1),m(i("client_detail.messages.reactivated","Cliente reativado.")),await U()}}),W&&s&&e.jsx(Qe,{clientId:r,clientName:s.companyName||s.tenant||`#${s.clientId}`,tier:s.tier,onClose:()=>I(!1),onDeleted:async()=>{I(!1),m(i("client_detail.messages.soft_deleted","Client marked for deletion (purge in 30d).")),await U()}})]}):null}function he({label:i,value:d,variant:o}){const S={amber:"text-amber-500",cyan:"text-cyan-500",violet:"text-violet-500",emerald:"text-emerald-500",rose:"text-rose-500"};return e.jsx(Z,{className:"bg-card border-border",children:e.jsxs(K,{className:"pt-4",children:[e.jsx("div",{className:"text-xs text-muted-foreground",children:i}),e.jsx("div",{className:`text-2xl font-bold mt-1 ${S[o]}`,children:d})]})})}function Je({billing:i,locale:d}){const{t:o}=$("admin"),S=x=>x?new Date(x).toLocaleDateString(d):"—",r=i.stripe?.currentPeriodEnd??null,t=i.paidUntilDate??null,s=i.trialEndDate??null;let b=null,h="none";const p=[{src:"stripe",iso:r},{src:"manual",iso:t},{src:"trial",iso:s}];for(const x of p)x.iso&&(!b||new Date(x.iso)>new Date(b))&&(b=x.iso,h=x.src);const w={stripe:"border-violet-500/50 text-violet-500",manual:"border-emerald-500/50 text-emerald-500",trial:"border-amber-500/50 text-amber-500",none:"border-border text-muted-foreground"};return e.jsxs(Z,{className:"bg-card border-border mb-6",children:[e.jsxs(se,{children:[e.jsxs(re,{className:"text-sm flex items-center gap-2",children:[e.jsx(Le,{className:"w-4 h-4 text-emerald-500"}),o("client_detail.billing.cycle_title","Ciclo de pagamento")]}),e.jsx(X,{children:o("client_detail.billing.cycle_description","Next due date — current Stripe sub, last manual payment, or trial end (whichever comes later).")})]}),e.jsxs(K,{children:[e.jsxs("div",{className:"grid sm:grid-cols-3 gap-4",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground",children:o("client_detail.billing.tier","Plano")}),e.jsx("div",{className:"text-lg font-semibold mt-1",children:i.tier})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground",children:o("client_detail.billing.next_due","Next due")}),e.jsx("div",{className:"text-lg font-semibold mt-1",children:S(b)})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground",children:o("client_detail.billing.source","Origem")}),e.jsx("div",{className:"mt-1",children:e.jsxs(V,{variant:"outline",className:`${w[h]} text-xs`,children:[h==="stripe"&&o("client_detail.billing.source_stripe","Stripe automatic"),h==="manual"&&o("client_detail.billing.source_manual","Manual"),h==="trial"&&o("client_detail.billing.source_trial","Trial"),h==="none"&&o("client_detail.billing.source_none","None")]})})]})]}),i.stripe&&e.jsxs("div",{className:"mt-4 grid sm:grid-cols-3 gap-4 pt-4 border-t border-border/50",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground",children:o("client_detail.billing.stripe_status","Stripe status")}
1),e.jsx("div",{className:"text-sm font-medium mt-1",children:i.stripe.status??"—"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground",children:o("client_detail.billing.stripe_interval","Ciclo Stripe")}),e.jsxs("div",{className:"text-sm font-medium mt-1",children:[i.stripe.interval==="month"&&o("client_detail.billing.interval_month","Mensal"),i.stripe.interval==="year"&&o("client_detail.billing.interval_year","Anual"),i.stripe.interval===null&&"—"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground",children:o("client_detail.billing.stripe_cancel_at_end","Cancels at period end")}),e.jsx("div",{className:"text-sm font-medium mt-1",children:i.stripe.cancelAtPeriodEnd?o("client_detail.billing.yes","Yes"):o("client_detail.billing.no","No")})]})]})]})]})}const Ee={pix:"PIX",bank_transfer:"Transferência",cash:"Dinheiro",other:"Outro"};function ze({billing:i,clientId:d,locale:o,onRegister:S,onVoid:r}){const{t}=$("admin"),s=a=>new Date(a).toLocaleDateString(o),b=a=>new Date(a).toLocaleString(o,{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}),h=(a,g)=>new Intl.NumberFormat(o,{style:"currency",currency:g}).format(a),p=i.manualPayments.filter(a=>a.status==="active"),w=p.reduce((a,g)=>a+g.amount,0),x=p[0]?.currency||"USD";return e.jsxs(Z,{className:"bg-card border-border mb-6",children:[e.jsx(se,{children:e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs(re,{className:"text-sm flex items-center gap-2",children:[e.jsx($e,{className:"w-4 h-4 text-violet-500"}),t("client_detail.billing.manual_title","Manual payments")]}),e.jsx(X,{children:t("client_detail.billing.manual_description","PIX, transferências e outros pagamentos fora da Stripe. Registrar um manual também agenda o cancelamento da Stripe sub no fim do período atual.")})]}),e.jsxs(P,{onClick:S,size:"sm",className:"bg-emerald-500 hover:bg-emerald-400 text-black",children:[e.jsx(Ue,{className:"w-4 h-4 mr-1.5"}),t("client_detail.billing.register_button","Registrar pagamento")]})]})}),e.jsx(K,{children:i.manualPayments.length===0?e.jsx("p",{className:"text-sm text-muted-foreground",children:t("client_detail.billing.manual_empty","No manual payment recorded.")}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-border text-left text-xs text-muted-foreground",children:[e.jsx("th",{className:"py-2 pr-3",children:t("client_detail.billing.col_paid_at","Data")}),e.jsx("th",{className:"py-2 pr-3",children:t("client_detail.billing.col_amount","Valor")}),e.jsx("th",{className:"py-2 pr-3",children:t("client_detail.billing.col_method","Method")}),e.jsx("th",{className:"py-2 pr-3",children:t("client_detail.billing.col_reference","Reference")}),e.jsx("th",{className:"py-2 pr-3",children:t("client_detail.billing.col_period","Period covered")}),e.jsx("th",{className:"py-2 pr-3",children:t("client_detail.billing.col_receipt","Comprovante")}),e.jsx("th",{className:"py-2 pr-3",children:t("client_detail.billing.col_registered_by","Registrado por")}),e.jsx("th",{className:"py-2 pr-3",children:t("client_detail.billing.col_status","Status")}),e.jsx("th",{className:"py-2 pr-3"})]})}),e.jsx("tbody",{children:i.manualPayments.map(a=>e.jsxs("tr",{className:`border-b border-border/50 ${a.status==="voided"?"opacity-50":""}`,children:[e.jsx("td",{className:"py-2 pr-3 text-xs whitespace-nowrap",title:t("client_detail.billing.col_paid_at_tooltip","Registrado em: {{registered}}",{registered:b(a.registeredAt)}),children:b(a.paidAt)}),e.jsxs("td",{className:"py-2 pr-3 font-medium",children:[e.jsx("div",{children:h(a.amount,a.currency)}),a.targetTier&&e.jsx("div",{className:"text-[10px] text-muted-foreground font-normal",children:a.previousTier?t("client_detail.billing.row_tier_change","{{from}} → {{to}}",{from:a.previousTier,to:a.targetTier}):a.targetTier})]}),e.jsx("td",{className:"py-2 pr-3 text-xs",children:e.jsx(V,{variant:"outline",className:"text-xs",children:Ee[a.method]||a.method})}),e.jsx("td",{className:"py-2 pr-3 text-xs font-mono text-muted-foreground",children:a.reference||"—"}),e.jsxs("td",{className:"py-2 pr-3 text-xs text-muted-foreground",children:[s(a.periodStart)," → ",s(a.periodEnd)]}),e.jsx("td",{className:"py-2 pr-3 text-xs",children:a.hasReceipt?e.jsxs("a",{href:`/api/admin/clients/${d}/manual-payments/${a.id}/receipt`,target:"_blank",rel:"noopener noreferrer",className:"text-cyan-500 hover:text-cyan-400 inline-flex items-center gap-1",children:[e.jsx(Fe,{className:"w-3 h-3"}),a.receiptName||t("client_detail.billing.view_receipt","Ver")]}):e.jsx("span",{className:"text-muted-foreground",children:"—"})}),e.jsxs("td",{className:"py-2 pr-3 text-xs",children:[e.jsx("div",{className:"text-muted-foreground",title:[a.registeredByName?`${a.registeredByName}`:null,`adminId=${a.registeredBy}
1`].filter(Boolean).join(`
2`),children:a.registeredByEmail||a.registeredBy}),a.status==="voided"&&a.voidedByEmail&&e.jsxs("div",{className:"text-[10px] text-rose-500 mt-0.5",title:a.voidedAt?`${t("client_detail.billing.row_voided_at","Estornado em")}: ${new Date(a.voidedAt).toLocaleString(o)}
3${t("client_detail.billing.row_voided_reason","Motivo")}: ${a.voidedReason||""}`:void 0,children:[t("client_detail.billing.row_voided_by_label","Estornado por:")," ",a.voidedByEmail]})]}),e.jsx("td",{className:"py-2 pr-3",children:e.jsxs("div",{className:"flex flex-wrap gap-1",children:[e.jsx(V,{variant:"outline",className:a.status==="active"?"text-xs border-emerald-500/50 text-emerald-500":"text-xs border-rose-500/50 text-rose-500",children:a.status==="active"?t("client_detail.billing.status_active","Active"):t("client_detail.billing.status_voided","Estornado")}),a.acceptedPriceMismatch&&e.jsx(V,{variant:"outline",className:"text-[10px] border-amber-500/50 text-amber-500 cursor-help",title:[t("client_detail.billing.row_price_override_title","Valor diverge do plano — admin justificou nas notas"),a.expectedAmountUsd!=null?`${t("client_detail.billing.row_expected_label","Esperado")}: $${a.expectedAmountUsd.toFixed(2)} USD`:null,a.priceVariancePercent!=null?`${t("client_detail.billing.row_variance_label","Variance")}: ${(a.priceVariancePercent*100).toFixed(1)}%`:null,a.notes?`${t("client_detail.billing.row_justification_label","Justificativa")}: ${a.notes}`:null].filter(Boolean).join(`
4`),children:t("client_detail.billing.row_price_override","price-override")}),a.receiptValidation?.accepted&&e.jsx(V,{variant:"outline",className:"text-[10px] border-amber-500/50 text-amber-500 cursor-help",title:[t("client_detail.billing.row_receipt_override_title","Comprovante divergente aceito manualmente"),a.receiptValidation.extractedAmount!=null?`${t("client_detail.billing.row_ocr_extracted_label","OCR extraiu")}: ${a.receiptValidation.extractedAmount.toFixed(2)} ${a.receiptValidation.extractedCurrency||""}`:null,a.receiptValidation.deltaPercent!=null?`${t("client_detail.billing.row_ocr_delta_label","Delta")}: ${(a.receiptValidation.deltaPercent*100).toFixed(1)}%`:null,a.notes?`${t("client_detail.billing.row_justification_label","Justificativa")}: ${a.notes}`:null].filter(Boolean).join(`
5`),children:t("client_detail.billing.row_receipt_override","comprovante-override")}),a.receiptValidation&&a.receiptValidation.ocrStatus==="low_confidence"&&!a.receiptValidation.accepted&&e.jsx(V,{variant:"outline",className:"text-[10px] border-amber-500/50 text-amber-500",children:t("client_detail.billing.row_low_confidence","OCR baixa")}),a.receiptValidation&&a.receiptValidation.ocrStatus==="ok"&&a.receiptValidation.deltaPercent!==null&&Math.abs(a.receiptValidation.deltaPercent)<=.01&&e.jsx(V,{variant:"outline",className:"text-[10px] border-emerald-500/50 text-emerald-500",title:t("client_detail.billing.row_ocr_match_title","Valor do comprovante bate com o informado"),children:t("client_detail.billing.row_ocr_match","OCR ✓")})]})}),e.jsx("td",{className:"py-2 pr-3",children:a.status==="active"&&e.jsx("button",{onClick:()=>r(a.id),className:"text-xs text-rose-500 hover:text-rose-400 inline-flex items-center gap-1",title:t("client_detail.billing.void_button","Estornar"),children:e.jsx(ye,{className:"w-3 h-3"})})})]},a.id))}),e.jsx("tfoot",{children:e.jsxs("tr",{className:"text-xs",children:[e.jsx("td",{className:"pt-3 pr-3 text-muted-foreground",colSpan:1,children:t("client_detail.billing.total_active","Active total")}),e.jsx("td",{className:"pt-3 pr-3 font-semibold",children:h(w,x)}),e.jsx("td",{colSpan:7})]})})]})})})]})}const Xe=["application/pdf","image/png","image/jpeg","image/webp"],Ge=5*1024*1024,We={month:"monthly",quarter:"quarterly",semester:"semestral",year:"annual"};function Ye({clientId:i,billing:d,onClose:o,onSaved:S}){const{t:r}=$("admin"),{t}=$("common"),s=l.useRef(null),[b,h]=l.useState(null),[p,w]=l.useState(d.tier!=="free"&&d.tier!=="free_trial"?d.tier:"pro"),[x,a]=l.useState(d.stripe?.interval==="year"?"year":"month"),[g,A]=l.useState(""),[m,_]=l.useState("USD"),[R,c]=l.useState("pix"),[E,f]=l.useState(""),[v,D]=l.useState(new Date().toISOString().slice(0,10)),[L,pe]=l.useState(""),[T,Q]=l.useState(null),[C,me]=l.useState(!1),[G,F]=l.useState(null),[q,W]=l.useState(null),[I,U]=l.useState(null),[Y,H]=l.useState(!1),[ue,xe]=l.useState(!1);l.useEffect(()=>{(async()=>{try{const j=await(await B("/api/admin/plans")).json();j?.ok&&Array.isArray(j.plans)&&h(j.plans)}catch{}})()},[]);const ee=(()=>
5{if(!b)return null;const n=b.find(O=>O.tierId===p);if(!n)return null;const j=n.pricing?.[We[x]];return typeof j=="number"&&Number.isFinite(j)&&j>0?j:null})(),be=d.tier!==p;function ge(n){return new Promise((j,O)=>{const N=new FileReader;N.onload=()=>{const M=N.result;if(typeof M!="string")return O(new Error("read failed"));const we=M.indexOf(",");j(we>=0?M.slice(we+1):M)},N.onerror=()=>O(N.error||new Error("read failed")),N.readAsDataURL(n)})}async function u(){F(null);const n=Number(g);if(!Number.isFinite(n)||n<=0){F(r("client_detail.billing.errors.invalid_amount","Invalid amount"));return}if(T){if(T.size>Ge){F(r("client_detail.billing.errors.receipt_too_large","Comprovante excede 5MB"));return}if(!Xe.includes(T.type)){F(r("client_detail.billing.errors.receipt_unsupported","File type not supported (PDF, PNG, JPG, WEBP)"));return}}me(!0);try{const j={amount:n,currency:m.toUpperCase(),method:R,paidAt:new Date(v+"T12:00:00Z").toISOString(),targetTier:p,targetCycle:x};if(E.trim()&&(j.reference=E.trim()),L.trim()&&(j.notes=L.trim()),Y&&(j.acceptPriceMismatch=!0),ue&&(j.acceptReceiptMismatch=!0),T){const M=await ge(T);j.receipt={name:T.name,mimeType:T.type,base64:M}}const O=await B(`/api/admin/clients/${i}/manual-payments`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(j)}),N=await O.json().catch(()=>({}));if(!O.ok||!N?.ok){const M=String(N?.error??"");if(M==="price_mismatch"&&N?.details){W({expected:Number(N.details.expectedAmountUsd??0),actual:Number(N.details.actualAmount??n),variancePercent:Number(N.details.variancePercent??0)}),F(null);return}if(M==="price_mismatch_needs_justification"){F(r("client_detail.billing.errors.price_needs_notes",'Justifique o desconto/ajuste no campo "Notas" (mín. 5 caracteres) para liberar o registro.'));return}if(M==="receipt_mismatch"&&N?.details){U({ocrStatus:String(N.details.ocrStatus??"error"),extractedAmount:N.details.extractedAmount===null||N.details.extractedAmount===void 0?null:Number(N.details.extractedAmount),extractedCurrency:N.details.extractedCurrency?String(N.details.extractedCurrency):null,confidence:N.details.confidence===null||N.details.confidence===void 0?null:Number(N.details.confidence),deltaPercent:N.details.deltaPercent===null||N.details.deltaPercent===void 0?null:Number(N.details.deltaPercent)}),F(null);return}if(M==="plan_not_found"||M==="plan_inactive"){F(r("client_detail.billing.errors.plan_invalid","Target plan invalid or inactive"));return}F(N?.message||M||r("client_detail.billing.errors.save_failed","Failed to record ({{status}})",{status:O.status}));return}await S()}catch(j){F(j instanceof Error?j.message:String(j))}finally{me(!1)}}const y=d.stripe?.status==="active"||d.stripe?.status==="trialing";return e.jsx(le,{open:!0,onOpenChange:n=>{n||o()},children:e.jsxs(ne,{className:"max-w-xl",children:[e.jsx(de,{children:e.jsx(ce,{children:r("client_detail.billing.register_title","Registrar pagamento manual")})}),e.jsxs("div",{className:"space-y-3 py-2 max-h-[70vh] overflow-y-auto pr-1",children:[G&&e.jsx("div",{className:"bg-destructive/10 border border-destructive/50 text-destructive text-sm p-3 rounded",children:G}),y&&e.jsx("div",{className:"bg-amber-500/10 border border-amber-500/40 text-amber-500 text-xs p-2.5 rounded",children:r("client_detail.billing.stripe_warning","Active Stripe sub: recording a manual payment cancels auto-renewal at the end of the current period.")}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:r("client_detail.billing.field_target_tier","Plano alvo")}),e.jsx("select",{value:p,onChange:n=>{w(n.target.value),W(null),H(!1)},disabled:C||!b,className:"w-full h-9 px-3 rounded-md bg-background border border-border text-sm",children:(b??[]).filter(n=>n.isActive&&n.tierId!=="free"&&n.tierId!=="free_trial"&&n.tierId!=="adm").map(n=>e.jsxs("option",{value:n.tierId,children:[n.tierId,n.tierId===d.tier?` (${r("client_detail.billing.tier_current","atual")})`:""]},n.tierId))}),be&&e.jsx("div",{className:"text-[11px] text-amber-500 mt-1",children:r("client_detail.billing.tier_change_warning","Vai mudar tier de {{from}} → {{to}}",{from:d.tier,to:p})})]}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:r("client_detail.billing.field_target_cycle","Ciclo")}),e.jsxs("select",{value:x,onChange:n=>{a(n.target.value),W(null),H(!1)},disabled:C,className:"w-full h-9 px-3 rounded-md bg-background border border-border text-sm",children:[e.jsx("option",{value:"month",children:r("client_detail.billing.cycle_month","Mensal")}),e.jsx("option",{value:"quarter",children:r("client_detail.billing.cycle_quarter","Trimestral")}),e.jsx("option",{value:"semester",children:r("client_detail.billing.cycle_semester","Semestral")}),e.jsx("option",{value:"year",children:r("client_detail.billing.cycle_year","Anual")})]})]})]}),ee!==null&&e.jsxs("div",{className:"bg-cyan-500/10 border border-cyan-500/40 text-cyan-400 text-xs p-2.5 rounded flex items-center justify-between gap-2",children:[e.jsx("span",{children:r("client_detail.billing.expected_price_label","Expected price:")}),e.jsxs("span",{className:"font-semibold",children:["$",ee.toLocaleStr
5ing("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})," USD"]})]}),b&&ee===null&&e.jsx("div",{className:"bg-amber-500/10 border border-amber-500/40 text-amber-500 text-xs p-2.5 rounded",children:r("client_detail.billing.no_price_for_cycle","Plan has no price configured for this cycle. The backend will accept any amount without comparing.")}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:r("client_detail.billing.field_amount","Valor")}),e.jsx(J,{type:"number",step:"0.01",value:g,onChange:n=>{A(n.target.value),W(null),U(null),H(!1),xe(!1)},placeholder:"0.00",disabled:C})]}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:r("client_detail.billing.field_currency","Moeda")}),e.jsxs("select",{value:m,onChange:n=>_(n.target.value),disabled:C,className:"w-full h-9 px-3 rounded-md bg-background border border-border text-sm",children:[e.jsx("option",{value:"USD",children:"USD"}),e.jsx("option",{value:"BRL",children:"BRL"}),e.jsx("option",{value:"EUR",children:"EUR"})]})]})]}),q&&e.jsxs("div",{className:"bg-rose-500/10 border border-rose-500/50 text-rose-400 text-xs p-3 rounded space-y-2",children:[e.jsx("div",{className:"font-semibold",children:r("client_detail.billing.price_mismatch_title","Amount differs from plan price")}),e.jsx("div",{children:r("client_detail.billing.price_mismatch_detail","Expected: ${{expected}} USD · Entered: {{actual}} {{currency}} · Difference: {{variance}}%",{expected:q.expected.toFixed(2),actual:q.actual.toFixed(2),currency:m,variance:(q.variancePercent*100).toFixed(1)})}),e.jsxs("label",{className:"flex items-start gap-2 cursor-pointer pt-1",children:[e.jsx("input",{type:"checkbox",checked:Y,onChange:n=>H(n.target.checked),disabled:C,className:"mt-0.5"}),e.jsx("span",{children:r("client_detail.billing.accept_price_mismatch",'Valor com desconto/ajuste justificado — preencher o motivo em "Notas" (mín. 5 caracteres)')})]})]}),I&&e.jsxs("div",{className:"bg-rose-500/10 border border-rose-500/50 text-rose-400 text-xs p-3 rounded space-y-2",children:[e.jsx("div",{className:"font-semibold",children:I.ocrStatus==="no_amount_found"?r("client_detail.billing.receipt_no_amount_title","Could not read the amount on the receipt"):I.ocrStatus==="low_confidence"?r("client_detail.billing.receipt_low_confidence_title","Comprovante com baixa legibilidade"):r("client_detail.billing.receipt_mismatch_title","Valor do comprovante diverge do informado")}),I.extractedAmount!==null&&e.jsx("div",{children:r("client_detail.billing.receipt_mismatch_detail","Receipt: {{extracted}} {{ec}} · Entered: {{actual}} {{currency}} · Difference: {{delta}}%",{extracted:I.extractedAmount.toFixed(2),ec:I.extractedCurrency||"?",actual:Number(g).toFixed(2),currency:m,delta:((I.deltaPercent??0)*100).toFixed(1)})}),I.confidence!==null&&e.jsx("div",{className:"text-[11px] opacity-80",children:r("client_detail.billing.receipt_confidence","OCR confidence: {{c}}",{c:I.confidence.toFixed(2)})}),e.jsxs("label",{className:"flex items-start gap-2 cursor-pointer pt-1",children:[e.jsx("input",{type:"checkbox",checked:ue,onChange:n=>xe(n.target.checked),disabled:C,className:"mt-0.5"}),e.jsx("span",{children:r("client_detail.billing.accept_receipt_mismatch","I visually checked the receipt and the amount is correct — record anyway")})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:r("client_detail.billing.field_method","Method")}),e.jsxs("select",{value:R,onChange:n=>c(n.target.value),disabled:C,className:"w-full h-9 px-3 rounded-md bg-background border border-border text-sm",children:[e.jsx("option",{value:"pix",children:"PIX"}),e.jsx("option",{value:"bank_transfer",children:r("client_detail.billing.method_bank","Bank transfer")}),e.jsx("option",{value:"cash",children:r("client_detail.billing.method_cash","Dinheiro")}),e.jsx("option",{value:"other",children:r("client_detail.billing.method_other","Outro")})]})]}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:r("client_detail.billing.field_paid_at","Data do pagamento")}
5),e.jsx(J,{type:"date",value:v,onChange:n=>D(n.target.value),disabled:C})]})]}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:r("client_detail.billing.field_reference","Reference (end-to-end ID, etc.)")}),e.jsx(J,{value:E,onChange:n=>f(n.target.value),placeholder:r("client_detail.billing.field_reference_placeholder","opcional"),disabled:C})]}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:r("client_detail.billing.field_notes","Notes")}),e.jsx("textarea",{value:L,onChange:n=>pe(n.target.value),rows:2,disabled:C,className:"w-full px-3 py-2 rounded-md bg-background border border-border text-sm",placeholder:r("client_detail.billing.field_notes_placeholder","opcional")})]}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:r("client_detail.billing.field_receipt","Comprovante (PDF, PNG, JPG, WEBP — max 5MB)")}),e.jsxs("div",{className:"flex items-center gap-2 mt-1",children:[e.jsx("input",{ref:s,type:"file",accept:".pdf,.png,.jpg,.jpeg,.webp,application/pdf,image/png,image/jpeg,image/webp",onChange:n=>Q(n.target.files?.[0]??null),disabled:C,className:"hidden"}),e.jsxs(P,{type:"button",variant:"outline",size:"sm",onClick:()=>s.current?.click(),disabled:C,children:[e.jsx(Oe,{className:"w-4 h-4 mr-1.5"}),r("client_detail.billing.field_receipt_select","Selecionar arquivo")]}),T&&e.jsxs("div",{className:"flex items-center gap-1.5 text-xs",children:[e.jsx("span",{children:T.name}),e.jsxs("span",{className:"text-muted-foreground",children:["(",Math.round(T.size/1024)," KB)"]}),e.jsx("button",{type:"button",onClick:()=>{Q(null),s.current&&(s.current.value="")},className:"text-rose-500 hover:text-rose-400",children:e.jsx(Ve,{className:"w-3.5 h-3.5"})})]})]})]})]}),e.jsxs(oe,{children:[e.jsx(P,{variant:"outline",onClick:o,disabled:C,children:t("cancel","Cancelar")}
5),e.jsxs(P,{onClick:()=>{u()},disabled:C,className:"bg-emerald-500 hover:bg-emerald-400 text-black",children:[C&&e.jsx(z,{className:"w-4 h-4 mr-1.5 animate-spin"}),!C&&e.jsx(ke,{className:"w-4 h-4 mr-1.5"}),C?t("saving","Saving..."):t("save","Registrar")]})]})]})})}const te=10;function He({clientId:i,payment:d,locale:o,onClose:S,onVoided:r}){const{t}=$("admin"),{t:s}=$("common"),b=(f,v)=>new Intl.NumberFormat(o,{style:"currency",currency:v}).format(f),h=f=>new Date(f).toLocaleString(o,{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}),[p,w]=l.useState(""),[x,a]=l.useState(""),[g,A]=l.useState(!1),[m,_]=l.useState(!1),[R,c]=l.useState(null);async function E(){if(c(null),p.trim().length<te){c(t("client_detail.billing.void_modal.errors.reason_too_short","Justificativa precisa ter pelo menos {{min}} caracteres",{min:te}));return}if(!x){c(t("client_detail.billing.void_modal.errors.password_required","Digite sua senha de admin para confirmar."));return}if(!g){c(t("client_detail.billing.void_modal.errors.confirm_required",'Marque "Confirmo que entendo o impacto" para prosseguir.'));return}_(!0);try{const f=await B("/api/admin/auth/verify-password",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:x})});if(f.status===401){c(t("client_detail.billing.void_modal.errors.wrong_password","Senha de admin incorreta."));return}if(!f.ok){const L=await f.json().catch(()=>({}));c(L?.error||t("client_detail.billing.void_modal.errors.verify_failed","Failed to verify password ({{status}})",{status:f.status}));return}const v=await B(`/api/admin/clients/${i}/manual-payments/${d.id}`,{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({reason:p.trim()})}),D=await v.json().catch(()=>({}));if(!v.ok||!D?.ok){if(D?.error==="sudo_required"){c(t("client_detail.billing.void_modal.errors.sudo_required","Approval step expired. Try again."));return}c(D?.error||t("client_detail.billing.void_modal.errors.void_failed","Failed to void ({{status}})",{status:v.status}));return}await r()}catch(f){c(f instanceof Error?f.message:String(f))}finally{_(!1)}}return e.jsx(le,{open:!0,onOpenChange:f=>{f||S()},children:e.jsxs(ne,{className:"max-w-lg",children:[e.jsxs(de,{children:[e.jsxs(ce,{className:"flex items-center gap-2 text-rose-500",children:[e.jsx(ye,{className:"w-5 h-5"}),t("client_detail.billing.void_modal.title","Estornar pagamento manual")]}),e.jsx(X,{children:t("client_detail.billing.void_modal.description","Destructive action — requires justification and re-authentication. Audited with your admin id and timestamp.")})]}),e.jsxs("div",{className:"space-y-4 py-2 max-h-[70vh] overflow-y-auto pr-1",children:[R&&e.jsx("div",{className:"bg-destructive/10 border border-destructive/50 text-destructive text-sm p-3 rounded",children:R}),e.jsxs("div",{className:"bg-muted/30 border border-border rounded-md p-3 space-y-1.5 text-sm",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:t("client_detail.billing.void_modal.summary_amount","Valor:")}),e.jsx("span",{className:"font-semibold",children:b(d.amount,d.currency)})]}),e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsx("span",{className:"text-muted-foreground",children:t("client_detail.billing.void_modal.summary_paid_at","Pago em:")}),e.jsx("span",{className:"font-mono",children:h(d.paidAt)})]}),e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsx("span",{className:"text-muted-foreground",children:t("client_detail.billing.void_modal.summary_method","Method:")}),e.jsx("span",{children:(Ee[d.method]||d.method).toUpperCase()})]}),d.reference&&e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsx("span",{className:"text-muted-foreground",children:t("client_detail.billing.void_modal.summary_reference","Reference:")}),e.jsx("span",{className:"font-mono text-[11px]",children:d.reference})]}),e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsx("span",{className:"text-muted-foreground",children:t("client_detail.billing.void_modal.summary_registered_by","Registrado por:")}),e.jsx("span",{children:d.registeredByEmail||d.registeredBy})]}),d.targetTier&&e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsx("span",{className:"text-muted-foreground",children:t("client_detail.billing.void_modal.summary_tier","Plano alvo:")}),e.jsxs("span",{children:[e.jsx("code",{children:d.targetTier}),d.previousTier?` (de ${d.previousTier})`:""]})]})]}),e.jsx("div",{className:"bg-amber-500/10 border border-amber-500/40 text-amber-500 text-xs p-2.5 rounded",children:t("client_detail.billing.void_modal.impact_warning","When voiding: paidUntilDate is recalculated from the last remaining active payment, and the Stripe sub is not re-activated automatically. The attached receipt is kept in storage for audit.")}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:t("client_detail.billing.void_modal.field_reason","Void justification (min. {{min}} characters)",{min:te})}),e.jsx("textarea",{value:p,onChange:f=>{w(f.target.value),c(null)},rows:3,disabled:m,className:"w-full px-3 py-2 rounded-md bg-background border border-border text-sm",placeholder:t("client_detail.billing.void_modal.field_reason_placeholder","Ex.: Cliente solicitou cancelamento por X — ticket #1234.")}),e.jsxs("div",{className:"text-[10px] text-muted-foreground mt-0.5",children:[p.trim().length,"/",te]})]}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:t("client_detail.billing.void_modal.field_password","Your admin password (re-authentication)")}),e.jsx(J,{type:"password",value:x,onChange:f=>{a(f.target.value),c(null)},disabled:m,autoComplete:"current-password",placeholder:t("client_detail.billing.void_modal.field_password_placeholder","••••••••")})]}),e.jsxs("label",{className:"flex items-start gap-2 cursor-pointer pt-1 text-sm",children:[e.jsx("input",{type:"checkbox",checked:g,onChange:f=>A(f.target.checked),disabled:m,className:"mt-1"}),e.jsx("span",{children:t("client_detail.billing.void_modal.confirm_label","I confirm I understand the impact of this void and the action will be recorded in the audit log with my admin id.")})]})]}),e.jsxs(oe,{children:[e.jsx(P,{variant:"outline",onClick:S,disabled:m,children:s("cancel","Cancelar")}
5),e.jsxs(P,{onClick:()=>{E()},disabled:m||p.trim().length<te||!x||!g,className:"bg-rose-500 hover:bg-rose-400 text-white",children:[m&&e.jsx(z,{className:"w-4 h-4 mr-1.5 animate-spin"}),!m&&e.jsx(ye,{className:"w-4 h-4 mr-1.5"}),m?s("saving","Saving..."):t("client_detail.billing.void_modal.submit","Confirm void")]})]})]})})}const ae=10;async function Pe(i){try{const d=await B("/api/admin/auth/verify-password",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:i})});return d.status===401?{ok:!1,error:"wrong_password"}:d.ok?{ok:!0}:{ok:!1,error:(await d.json().catch(()=>({})))?.error||`verify_failed_${d.status}`}}catch(d){return{ok:!1,error:d instanceof Error?d.message:String(d)}}}function Ze({clientId:i,clientName:d,tier:o,onClose:S,onSuspended:r}){const{t}=$("admin"),{t:s}=$("common"),[b,h]=l.useState(""),[p,w]=l.useState(""),[x,a]=l.useState(!1),[g,A]=l.useState(!1),[m,_]=l.useState(null);async function R(){if(_(null),b.trim().length<ae){_(t("client_detail.suspend_modal.errors.reason_too_short","Justificativa precisa ter pelo menos {{min}} caracteres",{min:ae}));return}if(!p){_(t("client_detail.suspend_modal.errors.password_required","Digite sua senha de admin para confirmar."));return}if(!x){_(t("client_detail.suspend_modal.errors.confirm_required",'Marque "Confirmo o impacto" para prosseguir.'));return}A(!0);try{const c=await Pe(p);if(!c.ok){_(c.error==="wrong_password"?t("client_detail.suspend_modal.errors.wrong_password","Senha de admin incorreta."):t("client_detail.suspend_modal.errors.verify_failed","Failed to verify password"));return}const E=await B(`/api/admin/clients/${i}/suspend`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({reason:b.trim()})}),f=await E.json().catch(()=>({}));if(!E.ok||!f?.ok){_(f?.error||t("client_detail.suspend_modal.errors.suspend_failed","Failed to suspend ({{status}})",{status:E.status}));return}await r()}catch(c){_(c instanceof Error?c.message:String(c))}finally{A(!1)}}return e.jsx(le,{open:!0,onOpenChange:c=>{c||S()},children:e.jsxs(ne,{className:"max-w-lg",children:[e.jsxs(de,{children:[e.jsxs(ce,{className:"flex items-center gap-2 text-amber-500",children:[e.jsx(ve,{className:"w-5 h-5"}),t("client_detail.suspend_modal.title","Suspend client")]}),e.jsx(X,{children:t("client_detail.suspend_modal.description","Destructive action — blocks the client access. Requires justification and re-authentication. Audited with your admin id.")})]}),e.jsxs("div",{className:"space-y-4 py-2",children:[m&&e.jsx("div",{className:"bg-destructive/10 border border-destructive/50 text-destructive text-sm p-3 rounded",children:m}),e.jsxs("div",{className:"bg-muted/30 border border-border rounded-md p-3 space-y-1.5 text-sm",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:t("client_detail.suspend_modal.summary_client","Cliente:")}),e.jsx("span",{className:"font-semibold",children:d})]}),e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsx("span",{className:"text-muted-foreground",children:t("client_detail.suspend_modal.summary_tier","Plano:")}),e.jsx("span",{children:e.jsx("code",{children:o})})]}),e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsx("span",{className:"text-muted-foreground",children:"clientId:"}),e.jsx("span",{className:"font-mono",children:i})]})]}),e.jsx("div",{className:"bg-amber-500/10 border border-amber-500/40 text-amber-500 text-xs p-2.5 rounded",children:t("client_detail.suspend_modal.impact_warning","The client will be blocked from accessing the app. When they try to interact they will see a real-time notice with the reason. You can reactivate at any time.")}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:t("client_detail.suspend_modal.field_reason","Reason (min. {{min}} characters)",{min:ae})}),e.jsx("textarea",{value:b,onChange:c=>{h(c.target.value),_(null)},rows:3,disabled:g,className:"w-full px-3 py-2 rounded-md bg-background border border-border text-sm",placeholder:t("client_detail.suspend_modal.field_reason_placeholder","E.g.: Client overdue for 60 days — billing policy §4.2.")}),e.jsxs("div",{className:"text-[10px] text-muted-foreground mt-0.5",children:[b.trim().length,"/",ae]})]}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:t("client_detail.suspend_modal.field_password","Sua senha de admin")}),e.jsx(J,{type:"password",value:p,onChange:c=>{w(c.target.value),_(null)},disabled:g,autoComplete:"current-password",placeholder:"••••••••"})]}),e.jsxs("label",{className:"flex items-start gap-2 cursor-pointer pt-1 text-sm",children:[e.jsx("input",{type:"checkbox",checked:x,onChange:c=>a(c.target.checked),disabled:g,className:"mt-1"}),e.jsx("span",{children:t("client_detail.suspend_modal.confirm_label","I confirm I understand this client will be blocked and the action will be audited with my admin id.")})]})]}),e.jsxs(oe,{children:[e.jsx(P,{variant:"outline",onClick:S,disabled:g,children:s("cancel","Cancelar")}
5),e.jsxs(P,{onClick:()=>{R()},disabled:g||b.trim().length<ae||!p||!x,className:"bg-amber-500 hover:bg-amber-400 text-black",children:[g&&e.jsx(z,{className:"w-4 h-4 mr-1.5 animate-spin"}),!g&&e.jsx(ve,{className:"w-4 h-4 mr-1.5"}),g?s("saving","Saving..."):t("client_detail.suspend_modal.submit","Suspend client")]})]})]})})}function Ke({clientId:i,clientName:d,tier:o,suspendedAt:S,suspendedBy:r,suspendedReason:t,onClose:s,onReactivated:b}){const{t:h}=$("admin"),{t:p}=$("common"),[w,x]=l.useState(!1),[a,g]=l.useState(null);async function A(){g(null),x(!0);try{const _=await B(`/api/admin/clients/${i}/reactivate`,{method:"POST",headers:{"Content-Type":"application/json"}}),R=await _.json().catch(()=>({}));if(!_.ok||!R?.ok){g(R?.error||h("client_detail.reactivate_modal.errors.reactivate_failed","Failed to reactivate ({{status}})",{status:_.status}));return}await b()}catch(_){g(_ instanceof Error?_.message:String(_))}finally{x(!1)}}const m=S?new Date(S).toLocaleString():null;return e.jsx(le,{open:!0,onOpenChange:_=>{!_&&!w&&s()},children:e.jsxs(ne,{className:"max-w-lg",children:[e.jsxs(de,{children:[e.jsxs(ce,{className:"flex items-center gap-2 text-emerald-500",children:[e.jsx(Ne,{className:"w-5 h-5"}),h("client_detail.reactivate_modal.title","Reactivate client")]}),e.jsx(X,{children:h("client_detail.reactivate_modal.description","Restores the client access. The real-time block disappears within 5s. Action audited with your admin id.")})]}),e.jsxs("div",{className:"space-y-4 py-2",children:[a&&e.jsx("div",{className:"bg-destructive/10 border border-destructive/50 text-destructive text-sm p-3 rounded",children:a}),e.jsxs("div",{className:"bg-muted/30 border border-border rounded-md p-3 space-y-1.5 text-sm",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:h("client_detail.reactivate_modal.summary_client","Cliente:")}),e.jsx("span",{className:"font-semibold",children:d})]}),e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsx("span",{className:"text-muted-foreground",children:h("client_detail.reactivate_modal.summary_tier","Plano:")}),e.jsx("span",{children:e.jsx("code",{children:o})})]}),e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsx("span",{className:"text-muted-foreground",children:"clientId:"}),e.jsx("span",{className:"font-mono",children:i})]})]}),e.jsxs("div",{className:"bg-amber-500/10 border border-amber-500/40 rounded-md p-3 space-y-1.5 text-xs",children:[e.jsx("div",{className:"font-semibold text-amber-500",children:h("client_detail.reactivate_modal.current_suspension","Current suspension")}),m&&e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:h("client_detail.reactivate_modal.suspended_at","Suspended at:")}),e.jsx("span",{children:m})]}),r&&e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:h("client_detail.reactivate_modal.suspended_by","Suspended by:")}),e.jsx("span",{className:"font-mono",children:r})]}),t&&e.jsxs("div",{children:[e.jsx("div",{className:"text-muted-foreground mb-0.5",children:h("client_detail.reactivate_modal.suspended_reason","Motivo:")}),e.jsx("div",{className:"bg-background/60 border border-border rounded p-2",children:t})]}),!m&&!r&&!t&&e.jsx("div",{className:"text-muted-foreground",children:h("client_detail.reactivate_modal.no_suspension_context","No suspension context recorded.")})]}),e.jsx("div",{className:"bg-emerald-500/10 border border-emerald-500/40 text-emerald-500 text-xs p-2.5 rounded",children:h("client_detail.reactivate_modal.impact_info","On confirm, the client regains immediate access and the block notice is removed within 5 seconds.")})]}),e.jsxs(oe,{children:[e.jsx(P,{variant:"outline",onClick:s,disabled:w,children:p("cancel","Cancelar")}
5),e.jsxs(P,{onClick:()=>{A()},disabled:w,className:"bg-emerald-500 hover:bg-emerald-400 text-black",children:[w&&e.jsx(z,{className:"w-4 h-4 mr-1.5 animate-spin"}),!w&&e.jsx(Ne,{className:"w-4 h-4 mr-1.5"}),w?p("saving","Saving..."):h("client_detail.reactivate_modal.submit","Confirm reactivation")]})]})]})})}const ie=15;function Qe({clientId:i,clientName:d,tier:o,onClose:S,onDeleted:r}){const{t}=$("admin"),{t:s}=$("common"),[b,h]=l.useState(""),[p,w]=l.useState(""),[x,a]=l.useState(!1),[g,A]=l.useState(""),[m,_]=l.useState(!1),[R,c]=l.useState(null),E=`delete client ${i}`;async function f(){if(c(null),b.trim().length<ie){c(t("client_detail.delete_modal.errors.reason_too_short","Motivo precisa ter pelo menos {{min}} caracteres",{min:ie}));return}if(!p){c(t("client_detail.delete_modal.errors.password_required","Digite sua senha de admin."));return}if(!x){c(t("client_detail.delete_modal.errors.confirm_required","Check the impact confirmation."));return}if(g.trim().toLowerCase()!==E){c(t("client_detail.delete_modal.errors.confirmation_phrase",'Digite exatamente "{{phrase}}" para confirmar.',{phrase:E}));return}_(!0);try{const v=await Pe(p);if(!v.ok){c(v.error==="wrong_password"?t("client_detail.delete_modal.errors.wrong_password","Senha de admin incorreta."):t("client_detail.delete_modal.errors.verify_failed","Falha ao verificar senha"));return}const D=await B(`/api/admin/clients/${i}/soft-delete`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({reason:b.trim()})}),L=await D.json().catch(()=>({}));if(!D.ok||!L?.ok){c(L?.error||t("client_detail.delete_modal.errors.delete_failed","Failed to delete ({{status}})",{status:D.status}));return}await r()}catch(v){c(v instanceof Error?v.message:String(v))}finally{_(!1)}}return e.jsx(le,{open:!0,onOpenChange:v=>{v||S()},children:e.jsxs(ne,{className:"max-w-lg",children:[e.jsxs(de,{children:[e.jsxs(ce,{className:"flex items-center gap-2 text-rose-500",children:[e.jsx(je,{className:"w-5 h-5"}),t("client_detail.delete_modal.title","Soft-delete cliente")]}),e.jsx(X,{children:t("client_detail.delete_modal.description","Marks the client for purge in 30d. Reactivatable during that window. Audited.")})]}),e.jsxs("div",{className:"space-y-4 py-2",children:[R&&e.jsx("div",{className:"bg-destructive/10 border border-destructive/50 text-destructive text-sm p-3 rounded",children:R}),e.jsxs("div",{className:"bg-muted/30 border border-border rounded-md p-3 space-y-1.5 text-sm",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:t("client_detail.delete_modal.summary_client","Cliente:")}),e.jsx("span",{className:"font-semibold",children:d})]}),e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsx("span",{className:"text-muted-foreground",children:t("client_detail.delete_modal.summary_tier","Plano:")}),e.jsx("span",{children:e.jsx("code",{children:o})})]}),e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsx("span",{className:"text-muted-foreground",children:"clientId:"}),e.jsx("span",{className:"font-mono",children:i})]})]}),e.jsx("div",{className:"bg-rose-500/10 border border-rose-500/50 text-rose-400 text-xs p-2.5 rounded",children:t("client_detail.delete_modal.impact_warning","The client loses immediate access and the data will be purged in 30 days. It can be reactivated within that window. After 30d the purge is irreversible.")}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:t("client_detail.delete_modal.field_reason","Reason (min. {{min}} characters)",{min:ie})}),e.jsx("textarea",{value:b,onChange:v=>{h(v.target.value),c(null)},rows:3,disabled:m,className:"w-full px-3 py-2 rounded-md bg-background border border-border text-sm",placeholder:t("client_detail.delete_modal.field_reason_placeholder","E.g.: Fraudulent account — ticket reference #SEC-1234.")}),e.jsxs("div",{className:"text-[10px] text-muted-foreground mt-0.5",children:[b.trim().length,"/",ie]})]}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs",children:t("client_detail.delete_modal.field_password","Sua senha de admin")}),e.jsx(J,{type:"password",value:p,onChange:v=>{w(v.target.value),c(null)},disabled:m,autoComplete:"current-password",placeholder:"••••••••"})]}),e.jsxs("div",{children:[e.jsx(k,{className:"text-xs text-rose-400",children:t("client_detail.delete_modal.field_confirm_p
5hrase",'Digite "{{phrase}}" para confirmar:',{phrase:E})}),e.jsx(J,{value:g,onChange:v=>{A(v.target.value),c(null)},disabled:m,placeholder:E})]}),e.jsxs("label",{className:"flex items-start gap-2 cursor-pointer pt-1 text-sm",children:[e.jsx("input",{type:"checkbox",checked:x,onChange:v=>a(v.target.checked),disabled:m,className:"mt-1"}),e.jsx("span",{children:t("client_detail.delete_modal.confirm_label","I confirm I understand this client will be marked for purge in 30d and the action will be audited.")})]})]}),e.jsxs(oe,{children:[e.jsx(P,{variant:"outline",onClick:S,disabled:m,children:s("cancel","Cancelar")}),e.jsxs(P,{onClick:()=>{f()},disabled:m||b.trim().length<ie||!p||!x||g.trim().toLowerCase()!==E,className:"bg-rose-500 hover:bg-rose-400 text-white",children:[m&&e.jsx(z,{className:"w-4 h-4 mr-1.5 animate-spin"}),!m&&e.jsx(je,{className:"w-4 h-4 mr-1.5"}),m?s("saving","Saving..."):t("client_detail.delete_modal.submit","Confirm deletion")]})]})]})})}export{dt 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.