PageSourceSearch

https://pragmaz.ai/assets/AdminRevenue-ox1yi-ZO.js

js pragmaz.ai collected 2026-10-02 00:43:18 UTC 10,943 bytes, 1 lines download raw bytes

1import{r as u,e as V,j as a,aS as k,a1 as ea,a2 as v,Y as _,aW as sa,aI as ra,aj as oa,di as J,a4 as ta}from"./app-CRAwfhea.js";import{u as na}from"./useIsLight-McDENofD.js";import{i,b as l,u as c,m as y,C as K,B as N,R as ia,p as la}from"./kit-BPe06PrA.js";import{N as S,C as m,V as x,K as R,L as G,T as ca,P as ua}from"./ui-CCrZkHuI.js";import"./LazyApexChart-BtPiBtiX.js";const da=[{l:"6 meses",m:6},{l:"12 meses",m:12},{l:"24 meses",m:24}],ma={paid:{l:"Paga",tom:"ok"},open:{l:"Em aberto",tom:""},void:{l:"Anulada",tom:""},uncollectible:{l:"Incobrável",tom:"ruim"}},Q=o=>{if(!o||o.length!==2)return"🌍";try{return String.fromCodePoint(...[...o.toUpperCase()].map(t=>127462+t.charCodeAt(0)-65))}catch{return"🌍"}};function fa(){var T,D,I,w,H,O;const o=na(),t=la(o),[C,W]=u.useState(12),[s,Y]=u.useState(null),[p,X]=u.useState(null),[A,U]=u.useState(!0),[F,B]=u.useState(null),z=u.useCallback(async()=>{var e,r,n;U(!0),B(null);try{const[f,aa]=await Promise.all([V.get("/admin/analytics/revenue"),V.get(`/admin/analytics/series?months=${C}`)]);Y(f.data),X(aa.data)}catch(f){B(((e=f.response)==null?void 0:e.status)===429?"limite":((n=(r=f.response)==null?void 0:r.data)==null?void 0:n.error)||f.message)}finally{U(!1)}},[C]);u.useEffect(()=>{z()},[z]);const g=u.useMemo(()=>{const e={brl:{assinaturas:0,cents:0},usd:{assinaturas:0,cents:0}};for(const r of(s==null?void 0:s.byCurrency)||[]){const n=String(r.currency).toLowerCase()==="usd"?"usd":"brl";e[n]={assinaturas:Number(r.assinaturas),cents:Number(r.cents)}}return e},[s]),h=((T=p==null?void 0:p.receita)==null?void 0:T.months)||[],L=(D=p==null?void 0:p.receita)==null?void 0:D.fronteiraMedicao,q=h.some(e=>e.fonte==="historico"),d=h[h.length-1],M=((s==null?void 0:s.faturas)||[]).filter(e=>e.status!=="paid"&&e.status!=="void"),P=M.reduce((e,r)=>e+Number(r.brl||0),0),Z=M.reduce((e,r)=>e+Number(r.usd||0),0),b=(s==null?void 0:s.risco)||{},E=((s==null?void 0:s.byPlan)||[]).filter(e=>String(e.currency).toLowerCase()!=="usd"),$=((s==null?void 0:s.byPlan)||[]).filter(e=>String(e.currency).toLowerCase()==="usd"),j=((s==null?void 0:s.porIntervalo)||[]).find(e=>e.intervalo==="year");return a.jsxs("div",{className:"rpt",children:[a.jsxs("header",{className:"rpt-head",children:[a.jsxs("div",{children:[a.jsxs("h1",{children:[a.jsx(k,{size:20})," Receita"]}),a.jsx("p",{children:"Recorrência contratada e caixa recebido — valores reais do Stripe, cada moeda no seu lugar."})]}),a.jsxs("div",{className:"rpt-head-acoes",children:[a.jsx("div",{className:"rpt-seg",children:da.map(e=>a.jsx("button",{className:C===e.m?"on ac":"",onClick:()=>W(e.m),children:e.l},e.m))}),a.jsxs("button",{className:"rpt-btn",onClick:z,disabled:A,children:[a.jsx(ea,{size:12,className:A?"animate-spin":""})," Atualizar"]}),(s==null?void 0:s.sync)&&a.jsxs("span",{className:`rpt-pill ${s.sync.obsoleto?"ruim":"ok"}`,title:`Sincronizado com o Stripe a cada ${s.sync.intervaloMin} min.`,children:["Stripe · ",s.sync.idadeMin===null?"nunca":`${s.sync.idadeMin} min`]})]})]}),((I=s==null?void 0:s.sync)==null?void 0:I.obsoleto)&&a.jsxs(S,{tom:"ruim",titulo:"Os valores podem estar velhos",icone:a.jsx(v,{size:14}),children:["A sincronia com o Stripe ",s.sync.nuncaRodou?a.jsx("b",{children:"nunca rodou"}):a.jsxs(a.Fragment,{children:["foi há ",a.jsxs("b",{children:[s.sync.idadeMin," min"]})]}),"."]}),F==="limite"?a.jsxs(S,{tom:"ruim",titulo:"Muitas consultas em pouco tempo",icone:a.jsx(v,{size:14}),children:["O painel aceita 60 consultas por minuto. Espere alguns segundos e clique em ",a.jsx("b",{children:"Atualizar"}),"."]}):F?a.jsx(S,{tom:"ruim",titulo:"Não foi possível carregar a receita",icone:a.jsx(v,{size:14}),children:a.jsx("code",{children:F})}):null,A&&!s?a.jsx(m,{children:a.jsx(x,{titulo:"Carregando…"})}):a.jsxs(a.Fragment,{children:[a.jsxs("div",{className:"rpt-grid rpt-g4",children:[a.jsx(R,{icone:a.jsx(k,{size:15}),label:"Recorrência BRL",valor:l(g.brl.cents),hint:`${i(g.brl.assinaturas)} assinaturas ativas em real`}),a.jsx(R,{icone:a.jsx(k,{size:15}),label:"Recorrência USD",valor:c(g.usd.cents),hint:`${i(g.usd.assinaturas)} assinaturas ativas em dólar`}),a.jsx(R,{icone:a.jsx(_,{size:15}),label:`Recebido em ${d?y(d.label):"—"}`,valor:d?l(d.mrrBrl):"—",hint:d?`${i(d.faturas)} faturas · + ${c(d.mrrUsd)}`:"—"}),a.jsx(R,{icone:a.jsx(v,{size:15}),label:"Faturado e não recebido",valor:l(P),tom:P>0?"ruim":"",hint:`+ ${c(Z)} em aberto ou incobrável`})]}),Number(b.assinaturas)>0&&a.jsxs(S,{tom:"ruim",titulo:"Recorrência que já pediu pra sair",icone:a.jsx(sa,{size:14}),children:[a.jsx("b",{children:i(b.assinaturas)})," assinaturas ativas têm cancelamento agendado —"," ",a.jsx("b",{children:l(b.brl)}),Number(b.usd)>0&&a.jsxs(a.Fragment,{children:[" e ",a.jsx("b",{children:c(b.usd)})]})," por mês que saem no fim do ciclo. Ainda estão pagando: é a única fatia do churn que ainda dá pra reverter. A lista com nome e data está em ",a.jsx("b",{children:"Assinaturas → Saindo"}),"."]}),a.jsx(m,{titulo:"Recebido por mês",icone:a.jsx(ra,{size:14}),meta:"duas moedas, dois gráficos",sub:q?a.jsxs(a.Fragment,{children:["Somar centavo de real com centavo de dólar produz um total que não é dinheiro nenhum. A cor separa as réguas: ",a.jsx("b",{children:"medido"})," (nossas faturas) a partir de ",L&&y(L),", e antes disso um ",a.jsx("b",{children:"retrato histórico"})," importado uma vez, que inclui a operação legada inteira — o degrau entre os dois é troca de fonte, não queda de receita."]}):"Faturas pagas por mês. O mês corrente fica de fora: está pela metade e desenharia uma queda que é só o calendário.",children:h.length?a.jsxs("div",{className:"rpt-grid rpt-g2",children:[a.jsxs("div",{children:[a.jsx(G,{itens:[{l:"Real (BRL)",cor:t.cat1}
1,...q?[{l:"Histórico",cor:t.neutro}]:[]]}),a.jsx(K,{isLight:o,porPonto:!0,altura:215,rotulo:"Recebido",fmt:e=>l(e*100),dados:h.map(e=>({nome:y(e.label),valor:Number(e.mrrBrl||0)/100,cor:e.fonte==="medido"?t.cat1:t.neutro,faturas:e.faturas,fonte:e.fonte})),tooltipExtra:e=>[{rotulo:"Faturas",valor:i(e.faturas)},{rotulo:"Fonte",valor:e.fonte==="medido"?"medido":"retrato histórico"}]})]}),a.jsxs("div",{children:[a.jsx(G,{itens:[{l:"Dólar (USD)",cor:t.cat2},...q?[{l:"Histórico",cor:t.neutro}]:[]]}),a.jsx(K,{isLight:o,porPonto:!0,altura:215,rotulo:"Recebido",fmt:e=>c(e*100),dados:h.map(e=>({nome:y(e.label),valor:Number(e.mrrUsd||0)/100,cor:e.fonte==="medido"?t.cat2:t.neutro,faturas:e.faturas,fonte:e.fonte})),tooltipExtra:e=>[{rotulo:"Fonte",valor:e.fonte==="medido"?"medido":"retrato histórico"}]})]})]}):a.jsx(x,{})}),a.jsx(m,{titulo:"Receita por país",icone:a.jsx(oa,{size:14}),meta:"valor real de cada assinatura",sub:a.jsxs(a.Fragment,{children:["Recorrência mensal dos assinantes de cada país, ",a.jsx("b",{children:"com o preço real do plano de cada um"})," e cada moeda no seu campo. Até 05/08/2026 esta conta multiplicava todo país pelo preço do plano Básico: o Brasil aparecia 29% menor que a realidade e os EUA ",a.jsx("b",{children:"702% maiores"}),", porque aplicava preço em reais a quem paga em dólar."]}),children:(w=s==null?void 0:s.byCountry)!=null&&w.length?a.jsxs("div",{className:"rpt-grid rpt-g2",children:[a.jsx(N,{isLight:o,rotulo:"Recorrência BRL",fmt:e=>l(e),dados:s.byCountry.filter(e=>Number(e.brl)>0).slice(0,8).map(e=>({nome:`${Q(e.country)} ${e.country}`,titulo:e.country,valor:Number(e.brl)})),tooltipExtra:e=>{const r=s.byCountry.find(n=>n.country===e.titulo);return r?[{rotulo:"Assinaturas",valor:i(r.assinaturas)}]:[]}}),a.jsx(N,{isLight:o,cor:t.cat2,rotulo:"Recorrência USD",fmt:e=>c(e),dados:s.byCountry.filter(e=>Number(e.usd)>0).slice(0,8).map(e=>({nome:`${Q(e.country)} ${e.country}`,titulo:e.country,valor:Number(e.usd)})),tooltipExtra:e=>{const r=s.byCountry.find(n=>n.country===e.titulo);return r?[{rotulo:"Assinaturas",valor:i(r.assinaturas)}]:[]}})]}):a.jsx(x,{})}),a.jsxs("div",{className:"rpt-grid rpt-g23",children:[a.jsx(m,{titulo:"Recorrência por produto — real",icone:a.jsx(J,{size:14}),sub:"Valor real de cada assinatura ativa, somado por produto. Nome vindo do Stripe: produto sem nome aparece com o ID, que é a verdade da fonte.",children:E.length?a.jsx(N,{isLight:o,rotulo:"Recorrência",fmt:e=>l(e),dados:E.slice(0,10).map(e=>({nome:String(e.produto).slice(0,34),titulo:e.produto,valor:Number(e.cents)})),tooltipExtra:e=>{const r=E.find(n=>n.produto===e.titulo);return r?[{rotulo:"Assinaturas",valor:i(r.assinaturas)},{rotulo:"Por assinatura",valor:l(Number(r.cents)/Math.max(1,r.assinaturas))}]:[]}}):a.jsx(x,{})}),a.jsx(m,{titulo:"Mensal × anual",icone:a.jsx(ta,{size:14}),sub:a.jsxs(a.Fragment,{children:["Quem paga adiantado tem risco de churn diferente e o caixa entra de uma vez. A recorrência do anual entra ",a.jsx("b",{children:"÷ 12"})," — somar o valor cheio infla aquela linha em 12×."]}),children:(H=s==null?void 0:s.porIntervalo)!=null&&H.length?a.jsxs(a.Fragment,{children:[a.jsx(ia,{isLight:o,rotuloCentro:"Assinaturas",dados:s.porIntervalo.map(e=>({nome:e.intervalo==="year"?"Anual":e.intervalo==="month"?"Mensal":String(e.intervalo),valor:Number(e.assinaturas)}))}),j&&a.jsxs("p",{className:"rpt-sub",style:{marginTop:8},children:["As ",a.jsx("b",{children:i(j.assinaturas)})," anuais somam ",a.jsx("b",{children:l(j.brl)})," de recorrência mensal equivalente",Number(j.usd)>0&&a.jsxs(a.Fragment,{children:[" e ",c(j.usd)]}),"."]})]}):a.jsx(x,{})})]}),$.length>0&&a.jsx(m,{titulo:"Recorrência por produto — dólar",icone:a.jsx(J,{size:14}),sub:"A base internacional em gráfico próprio: a escala e a moeda são outras, e somá-las não produziria dinheiro nenhum.",children:a.jsx(N,{isLight:o,cor:t.cat2,rotulo:"Recorrência",fmt:e=>c(e),dados:$.slice(0,8).map(e=>({nome:String(e.produto).slice(0,34),titulo:e.produto,valor:Number(e.cents)})),tooltipExtra:e=>{const r=$.find(n=>n.produto===e.titulo);return r?[{rotulo:"Assinaturas",valor:i(r.assinaturas)}]:[]}})}),a.jsx(m,{titulo:"Faturas por situação",icone:a.jsx(_,{size:14}),meta:"história completa",sub:a.jsxs(a.Fragment,{children:[a.jsx("b",{children:"Em aberto"})," ainda pode fechar; ",a.jsx("b",{children:"incobrável"})," é perda declarada pelo Stripe e ",a.jsx("b",{children:"anulada"})," é fatura cancelada. Juntar as três em “não pagou” apagaria a diferença entre esperar e perder."]}),children:(O=s==null?void 0:s.faturas)!=null&&O.length?a.jsx(ca,{inicial:{k:"n",dir:"desc"},dados:s.faturas.map(e=>({...e,__k:e.status})),cols:[{k:"status",l:"Situação",render:e=>{const r=ma[e.status]||{l:e.status,tom:""};return a.jsx(ua,{tom:r.tom,children:r.l})}},{k:"n",l:"Faturas",num:!0,render:e=>a.jsx("span",{className:"forte",children:i(e.n)})},{k:"brl",l:"BRL",num:!0,render:e=>Number(e.brl)?l(e.brl):a.jsx("span",{className:"fraco",children:"—"})},{k:"usd",l:"USD",num:!0,render:e=>Number(e.usd)?c(e.usd):a.jsx("span",{className:"fraco",children:"—"})}]}):a.jsx(x,{})})]})]})}export{fa 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.