PageSourceSearch

https://www.echomtg.com/_nuxt/DsovT2nQ.js

js echomtg.com collected 2026-09-29 06:14:00 UTC 8,614 bytes, 2 lines download raw bytes

1const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./Z1-TM1L3.js","./fVOeVomg.js"])))=>i.map(i=>d[i]);
2import{_ as W}from"#entry";import{u as J,b as K,r as X,z as O,q as Z}from"./BGlOPmvk.js";import{y as U,B as f,P as $,G as ee}from"./BYw8qiE9.js";import{k as te,o as ae,c as v,U as Y,O as T,S as l,V as a,r as b,P as n,R as m,W as g,j as _,m as S,Q as V,a2 as le}from"./fVOeVomg.js";import"./C91MxAc7.js";const se={key:0},ne={class:"grid grid-cols-1 md:grid-cols-3 gap-3 mx-3 my-3 items-end"},re={class:"flex gap-2 flex-wrap"},oe={class:"grid grid-cols-2 md:grid-cols-4 gap-4 text-center mx-3"},ue={class:"grid grid-cols-2 md:grid-cols-4 gap-4 text-center mx-3 mt-4"},ie={class:"grid grid-cols-2 md:grid-cols-4 gap-4 text-center mx-3 mt-4"},de={class:"text-xs text-gray-400 text-center mt-3 mx-3"},ve={class:"grid grid-cols-1 md:grid-cols-2 gap-4 mx-3"},be={class:"mx-3"},me={class:"mx-3 mb-8"},ce={key:0,class:"mx-3 mb-6 text-xs text-amber-700 bg-amber-50 border border-amber-200 rounded p-2"},we=te({__name:"saas-metrics",setup(pe){const R=le(async()=>(await W(async()=>{const{default:t}=await import("./Z1-TM1L3.js");return{default:t}},__vite__mapDeps([0,1]),import.meta.url)).default),{$echomtg:q}=J(),D=K(),C=v(()=>D.isAuthenticated),N=v(()=>(D.user?.user_level??0)>=8);X({title:"Admin: SaaS Metrics"});const o=t=>t==null?"—":Number(t).toLocaleString(void 0,{maximumFractionDigits:2});function M(t){return t.toISOString().slice(0,10)}const A=M(new Date),B=M(new Date(Date.now()-2160*60*60*1e3)),c=b(B),p=b(A),y=b(!1),P=b(""),L=b(!1),r=b({mrr:0,arr:0,arpu:0,active_subscribers:0,unknown_priced_subs:0,plan_breakdown:[],ltv_estimate:null}),i=b({new_subs:0,churned_subs:0,net_new_subs:0,new_mrr:0,churned_mrr:0,net_new_mrr:0,logo_churn_pct:0,flow_by_day:[]}),x=b({signups:0,converted:0,conv_pct:0}),w=b({}),I=v(()=>{const t=new Date(c.value).getTime(),e=new Date(p.value).getTime();return isNaN(t)||isNaN(e)?0:Math.max(0,Math.round((e-t)/864e5))}),u=t=>{const e=t.highlight==="warn"?"text-amber-600":t.highlight==="good"?"text-emerald-600":"";return S("div",[S("p",{class:"text-xs md:text-sm text-gray-500"},t.label),S("p",{class:`text-base md:text-lg font-semibold ${e}`},String(t.value)),t.sub?S("p",{class:"text-xs text-gray-400"},t.sub):null])},z=v(()=>({chart:{type:"bar",toolbar:{show:!1}},plotOptions:{bar:{horizontal:!0,distributed:!0}},xaxis:{categories:r.value.plan_breakdown.map(t=>t.plan)},tooltip:{y:{formatter:t=>`$${t.toLocaleString()}`}},dataLabels:{enabled:!0,formatter:t=>`$${t.toLocaleString()}`},legend:{show:!1}})),E=v(()=>[{name:"MRR",data:r.value.plan_breakdown.map(t=>t.mrr_contrib)}]),F=v(()=>({chart:{type:"donut"},labels:r.value.plan_breakdown.map(t=>t.plan),legend:{position:"bottom"}})),G=v(()=>r.value.plan_breakdown.map(t=>t.subscribers)),H=v(()=>({chart:{type:"bar",stacked:!1,toolbar:{show:!1}},xaxis:{categories:i.value.flow_by_day.map(t=>t.date)},colors:["#10b981","#ef4444"],dataLabels:{enabled:!1},legend:{position:"top"}})),j=v(()=>[{name:"New",data:i.value.flow_by_day.map(t=>t.new)},{name:"Churned",data:i.value.flow_by_day.map(t=>-t.lost)}]),Q=[{title:"Plan",key:"plan"},{title:"Subscribers",key:"subscribers",render:t=>t.subscribers.toLocaleString()},{title:"Monthly each",key:"monthly_each",render:t=>`$${t.monthly_each}`},{title:"MRR contrib",key:"mrr_contrib",render:t=>`$${Number(t.mrr_contrib).toLocaleString()}`},{title:"Annual?",key:"is_annual",render:t=>t.is_annual?"yes":"no"}];async function h(t=!1){y.value=!0;try{const e=new URLSearchParams;c.value&&e.set("start",c.value),p.value&&e.set("end",p.value),t&&e.set("refresh","1");const s=await q.getReq(`admin/saas_metrics/?${e.toString()}`);if(s?.status!=="success"){O({statusCode:500,statusMessage:s?.message||"Failed to load metrics"});return}r.value={mrr:s.mrr,arr:s.arr,arpu:s.arpu,active_subscribers:s.active_subscribers,unknown_priced_subs:s.unknown_priced_subs,plan_breakdown:s.plan_breakdown,ltv_estimate:s.ltv_estimate},i.value=s.period_flow,x.value=s.conversion,w.value=s.notes,P.value=s.generated_at,L.value=!!s.cached}finally{y.value=!1}}function k(t){c.value=M(new Date(Date.now()-t*864e5)),p.value=A,h(!1)}return ae(async()=>
2{if(!C.value||!N.value)return O({statusCode:404,statusMessage:"Page Not Found"});await h(!1)}),(t,e)=>{const s=Z;return C.value&&N.value?(V(),Y("div",se,[e[23]||(e[23]=l("h1",{class:"title is-size-4 ml-3"},"SaaS Metrics",-1)),l("div",ne,[l("div",null,[e[8]||(e[8]=l("p",{class:"text-xs text-gray-500 mb-1"},"Period start",-1)),a(n(U),{value:c.value,"onUpdate:value":e[0]||(e[0]=d=>c.value=d),placeholder:"YYYY-MM-DD"},null,8,["value"])]),l("div",null,[e[9]||(e[9]=l("p",{class:"text-xs text-gray-500 mb-1"},"Period end",-1)),a(n(U),{value:p.value,"onUpdate:value":e[1]||(e[1]=d=>p.value=d),placeholder:"YYYY-MM-DD"},null,8,["value"])]),l("div",re,[a(n(f),{type:"primary",loading:y.value,onClick:e[2]||(e[2]=d=>h(!1))},{default:m(()=>[...e[10]||(e[10]=[_("Apply",-1)])]),_:1},8,["loading"]),a(n(f),{loading:y.value,onClick:e[3]||(e[3]=d=>h(!0))},{default:m(()=>[...e[11]||(e[11]=[_("Refresh cache",-1)])]),_:1},8,["loading"]),a(n(f),{quaternary:"",onClick:e[4]||(e[4]=d=>k(30))},{default:m(()=>[...e[12]||(e[12]=[_("30d",-1)])]),_:1}),a(n(f),{quaternary:"",onClick:e[5]||(e[5]=d=>k(90))},{default:m(()=>[...e[13]||(e[13]=[_("90d",-1)])]),_:1}),a(n(f),{quaternary:"",onClick:e[6]||(e[6]=d=>k(180))},{default:m(()=>[...e[14]||(e[14]=[_("180d",-1)])]),_:1}),a(n(f),{quaternary:"",onClick:e[7]||(e[7]=d=>k(365))},{default:m(()=>[...e[15]||(e[15]=[_("1y",-1)])]),_:1})])]),a(n($)),l("div",oe,[a(u,{label:"MRR",value:`$${o(r.value.mrr)}`,sub:"monthly recurring"},null,8,["value"]),a(u,{label:"ARR",value:`$${o(r.value.arr)}`,sub:"annual run rate"},null,8,["value"]),a(u,{label:"ARPU",value:`$${o(r.value.arpu)}`,sub:"avg / sub / mo"},null,8,["value"]),a(u,{label:"Active Subs",value:o(r.value.active_subscribers)},null,8,["value"])]),l("div",ue,[a(u,{label:"New subs (period)",value:o(i.value.new_subs),sub:`+$${o(i.value.new_mrr)} MRR`,highlight:"good"},null,8,["value","sub"]),a(u,{label:"Churned subs",value:o(i.value.churned_subs),sub:`-$${o(i.value.churned_mrr)} MRR`,highlight:"warn"},null,8,["value","sub"]),a(u,{label:"Logo Churn Rate",value:`${i.value.logo_churn_pct}%`,sub:"period-bound"},null,8,["value"]),a(u,{label:"Net New MRR",value:`$${o(i.value.net_new_mrr)}`,highlight:i.value.net_new_mrr>=0?"good":"warn"},null,8,["value","highlight"])]),l("div",ie,[a(u,{label:"Signups (period)",value:o(x.value.signups)},null,8,["value"]),a(u,{label:"Converted to paid",value:o(x.value.converted),sub:`${x.value.conv_pct}%`},null,8,["value","sub"]),a(u,{label:"LTV estimate",value:r.value.ltv_estimate===null?"—":`$${o(r.value.ltv_estimate)}`,sub:"ARPU / churn"},null,8,["value"]),a(u,{label:"Unknown-priced subs",value:o(r.value.unknown_priced_subs),sub:"not in plans table",highlight:r.value.unknown_priced_subs>0?"warn":""},null,8,["value","highlight"])]),l("div",de," Generated "+g(P.value)+" · Cache: "+g(L.value?"HIT":"MISS")+" · Period: "+g(c.value)+" → "+g(p.value)+" ("+g(I.value)+" days) · event log: "+g(w.value.has_event_log?"enabled":"missing"),1),a(n($)),l("div",ve,[l("div",null,[e[16]||(e[16]=l("h4",{class:"text-lg font-semibold mb-2"},"MRR contribution by plan tier",-1)),a(s,null,{default:m(()=>[a(n(R),{type:"bar",height:"360",options:z.value,series:E.value},null,8,["options","series"])]),_:1}),e[17]||(e[17]=l("p",{class:"text-xs text-gray-500 mt-1"}," Mythic typically contributes far more MRR than its share of subscriber count — protect that tier in any pricing change. ",-1))]),l("div",null,[e[18]||(e[18]=l("h4",{class:"text-lg font-semibold mb-2"},"Subscribers per plan",-1)),a(s,null,{default:m(()=>[a(n(R),{type:"donut",height:"360",options:F.value,series:G.value},null,8,["options","series"])]),_:1})])]),a(n($)),l("div",be,[e[19]||(e[19]=l("h4",{class:"text-lg font-semibold mb-2"},"Daily new vs churned subs (event-log)",-1)),a(s,null,{default:m(()=>[a(n(R),{type:"bar",height:"320",options:H.value,series:j.value},null,8,["options","series"])]),_:1}),e[20]||(e[20]=l("p",{class:"text-xs text-gray-500 mt-1"}," Sourced from `stripe_events` (Phase 2 webhook receiver). Sparse before late April 2026 because the table started recording then. ",-1))]),a(n($)),l("div",me,[e[21]||(e[21]=l("h4",{class:"text-lg font-semibold mb-2"},"Plan breakdown table",-1)),a(n(ee),{columns:Q,data:r.value.plan_breakdown,size:"small",pagination:!1},null,8,["data"])]),w.value.churn_mrr_caveat?(V(),Y("div",ce,[e[22]||(e[22]=l("strong",null,"Note:",-1)),_(" "+g(w.value.churn_mrr_caveat),1)])):T("",!0)])):T("",!0)}}});
2export{we 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.