1import{j as e}from"./query-vendor-DBbghNzL.js";import{r as h}from"./react-vendor-B4iqnpmg.js";import{i as H,B as b,u as B,C as c,s as F}from"./index-Dddl32Ja.js";import{A as U}from"./AdminLayout-C0zioWlX.js";import{K as t,P as D,a as I,B as f}from"./KpiCard-wbKRu4y0.js";import{d as J,a as z}from"./exportUtils-7uPBqgeX.js";import{R as j,o as Q,T as p,p as O,X as v,Y as N,B as x}from"./generateCategoricalChart-PCk3LlXs.js";import"./icons-vendor-DfIUqQcN.js";import"./supabase-vendor-DRR_Es6B.js";function G({rows:r,max:d}){const i=d??Math.max(1,...r.map(l=>(l.male||0)+(l.female||0)+(l.other||0)+(l.unspec||0)));return e.jsxs("div",{className:"space-y-2",children:[r.map(l=>{const n=(l.male||0)+(l.female||0)+(l.other||0)+(l.unspec||0),o=a=>`${a/i*100}%`;return e.jsxs("div",{className:"text-xs",children:[e.jsxs("div",{className:"flex justify-between mb-1",children:[e.jsx("span",{className:"font-medium",children:l.label}),e.jsx("span",{className:"text-muted-foreground",children:n})]}),e.jsxs("div",{className:"flex h-3 rounded-full overflow-hidden bg-muted",children:[l.male?e.jsx("div",{className:"bg-primary",style:{width:o(l.male)},title:`Male ${l.male}`}):null,l.female?e.jsx("div",{className:"bg-secondary-foreground/70",style:{width:o(l.female),backgroundColor:"hsl(var(--accent))"},title:`Female ${l.female}`}):null,l.other?e.jsx("div",{style:{width:o(l.other),backgroundColor:"hsl(var(--muted-foreground))"},title:`Other ${l.other}`}):null,l.unspec?e.jsx("div",{style:{width:o(l.unspec),backgroundColor:"hsl(var(--border))"},title:`Unspecified ${l.unspec}`}):null]})]},l.label)}),e.jsxs("div",{className:"flex gap-3 text-[10px] text-muted-foreground pt-1",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"w-2 h-2 rounded-full bg-primary"}),"Male"]}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"w-2 h-2 rounded-full",style:{background:"hsl(var(--accent))"}}),"Female"]}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"w-2 h-2 rounded-full",style:{background:"hsl(var(--muted-foreground))"}}),"Other"]}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"w-2 h-2 rounded-full",style:{background:"hsl(var(--border))"}}),"Unspecified"]})]})]})}function Z({label:r,overall:d,male:i,female:l,other:n}){const o=({pct:a,color:_,lbl:g})=>e.jsxs("div",{className:"flex items-center gap-1 text-[10px]",title:`${g}: ${a??0}%`,children:[e.jsx("span",{className:"w-6 text-muted-foreground",children:g}),e.jsx("div",{className:"flex-1 h-1.5 bg-muted rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full",style:{width:`${Math.min(100,a??0)}%`,background:_}})}),e.jsxs("span",{className:"w-8 text-right tabular-nums",children:[a??0,"%"]})]});return e.jsxs("div",{className:"border-b py-3",children:[e.jsxs("div",{className:"flex justify-between items-baseline mb-2",children:[e.jsx("span",{className:"font-medium text-sm",children:r}),e.jsxs("span",{className:"text-xl font-bold tabular-nums",children:[d??0,"%"]})]}),e.jsxs("div",{className:"grid sm:grid-cols-3 gap-2",children:[e.jsx(o,{pct:i,color:"hsl(var(--primary))",lbl:"M"}),e.jsx(o,{pct:l,color:"hsl(var(--accent))",lbl:"F"}),e.jsx(o,{pct:n,color:"hsl(var(--muted-foreground))",lbl:"O"})]})]})}const ee=r=>{if(r==null)return{background:"hsl(var(--muted))"};const d=Math.min(1,r/100);return{background:`hsl(var(--primary) / ${.15+d*.7})`,color:d>.5?"hsl(var(--primary-foreground))":"hsl(var(--foreground))"}};function se({rows:r}){if(!(r!=null&&r.length))return e.jsx("p",{className:"text-sm text-muted-foreground",children:"Not enough data yet."});const d=["w1","w2","w4","w8","w12"];return e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"text-xs w-full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-left text-muted-foreground",children:[e.jsx("th",{className:"p-1.5",children:"Cohort"}),e.jsx("th",{className:"p-1.5",children:"Size"}),d.map(i=>e.jsx("th",{className:"p-1.5 text-center uppercase",children:i},i))]})}),e.jsx("tbody",{children:r.map(i=>e.jsxs("tr",{className:"border-t",children:[e.jsx("td",{className:"p-1.5 font-mono",children:i.cohort}),e.jsx("td",{className:"p-1.5 tabular-nums",children:i.size}),d.map(l=>e.jsxs("td",{className:"p-1.5 text-center tabular-nums rounded",style:ee(i[l]),children:[i[l]??0,"%"]},l))]},i.cohort))})]})})}const y={Male:"hsl(var(--primary))",Female:"hsl(var(--accent))",Other:"hsl(var(--muted-foreground))",Unspecified:"hsl(var(--border))"};function me(){const{user:r,isAdmin:d,loading:i,rolesLoading:l}=H(),[n,o]=h.useState(null),[a,_]=h.useState(null),[g,T]=h.useState(null),[q,K]=h.useState(!1),C=h.useRef(null),w=h.useRef(0),E=async()=>{const s=++w.current;T(null),K(!0),F.rpc("report_kpis_cached").then(({data:L,error:$})=>{s===w.current&&($?F.rpc("report_kpis").then(({data:Y,error:S})=>{s===w.current&&(S?(T(S.message),B.error(S.message)):o(Y),K(!1))}):(o(L),K(!1)))}),F.rpc("report_engagement").then(({data:L,error:$})=>{s===w.current&&($?(console.warn("engagement load failed",$),_({totals:{},engagement_pct:[]})):_(L))})};if(h.useEffect(()=>{i||l||!r||!d||E()},[i,l,r==null?void 0:r.id,d]),g)return e.jsx(U,{children:e.jsxs("div",{className:"space-y-3",children:[e.jsx("h1",{className:"text-2xl font-bold",children:"Dashboard couldn't load"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:g}),e.jsx(b,{onClick:E,children:"Retry"})]})});if(!n)return e.jsx(U,{children:e.jsx("p",{className:"text-muted-foreground",children:q?"Loading dashboardâ¦":"Preparing dashboardâ¦"})});const R=!!a,k=(a==null?void 0:a.totals)??{male:0,female:0,other:0,unspec:0},m=(a==null?void 0:a.investor)??{},u=(a==null?void 0:a.community)??{},A=(a==null?void 0:a.activation)??{},M=(a==null?void 0:a.activity)??{},P=[{name:"Male",value:k.male},{name:"Female",value:k.female},{name:"Other",value:k.other},{name:"Unspecified",value:k.unspec}].filter(s=>(s.value??0)>0),W=((a==null?void 0:a.age_brackets)||[]).map(s=>({label:s.bracket,male:s.male,female:s.female,other:s.other,unspec:s.unspec})),V=((a==null?void 0:a.top_cities)||[]).map(s=>({label:s.city,male:s.male,female:s.female,other:s.other,unspec:s.unspec})),X=((a==null?void 0:a.top_countries)||[]).map(s=>({label:s.country,male:s.male,female:s.female,other:s.other,unspec:s.unspec}));return e.jsxs(U,{children:[e.jsxs("div",{className:"flex flex-wrap justify-between items-center mb-4 gap-2",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl font-bold",children:"Engagement dashboard"}),e.jsx("p",{className:"text-muted-foreground text-sm",children:"Live snapshot â every behavioural metric segmented by gender."})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(b,{size:"sm",variant:"outline",onClick:()=>C.current&&J(C.current,"engagement-dashboard.pdf"),children:"Download PDF"}),e.jsx(b,{size:"sm",variant:"outline",disabled:!R,onClick:()=>z("engagement-funnel.csv",(a==null?void 0:a.engagement_pct)??[]),children:"Funnel CSV"}),e.jsx(b,{size:"sm",variant:"outline",onClick:()=>{navigator.clipboard.writeText(`${window.location.origin}/stats`),B.success("Public stats link copied")},children:"Copy public link"})]})]}),e.jsxs("div",{ref:C,className:"space-y-6 bg-background",children:[e.jsxs("section",{className:"grid grid-cols-2 md:grid-cols-4 gap-3",children:[e.jsx(t,{label:"Total members",value:n.total_members,accent:!0}),e.jsx(t,{label:"Signups 7d",value:n.signups_7d,hint:`${n.signups_30d} in 30d · ${n.signups_90d} in 90d`}),e.jsx(t,{label:"Active 30d",value:n.active_30d,hint:`${n.active_90d} in 90d`}),e.jsx(t,{label:"Total runs",value:n.total_runs}),e.jsx(t,{label:"Total km",value:Number(n.total_km).toLocaleStr
1ing(),hint:`${Number(n.total_miles).toLocaleString()} mi`}),e.jsx(t,{label:"MRR",value:`£${(n.mrr_pence/100).toLocaleString()}`,hint:`${n.active_memberships} paying`}),e.jsx(t,{label:"Countries",value:n.countries,hint:`${n.cities} cities`}),e.jsx(t,{label:"Dogs",value:n.dogs,hint:`${n.runs_with_dog} pawsteps runs`})]}),!R&&e.jsx("p",{className:"text-xs text-muted-foreground",children:"Loading engagement metricsâ¦"}),R&&e.jsxs(e.Fragment,{children:[e.jsxs("section",{children:[e.jsx("h2",{className:"font-bold text-lg mb-2",children:"Investor KPIs"}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3",children:[e.jsx(t,{label:"Stickiness (WAU/MAU)",value:`${m.stickiness??0}%`,hint:`${m.wau??0} WAU · ${m.mau??0} MAU`,accent:!0}),e.jsx(t,{label:"Paid conversion",value:`${m.paid_conversion_pct??0}%`}),e.jsx(t,{label:"Gender balance index",value:`${m.gender_balance_index??0}`,hint:"100 = perfect 50/50"}),e.jsx(t,{label:"International reach",value:`${m.intl_pct??0}%`,hint:"Members outside UK"}),e.jsx(t,{label:"Day-1 activation",value:`${A.d1??0}%`,hint:`D7 ${A.d7??0}% · D30 ${A.d30??0}%`}),e.jsx(t,{label:"Avg pts / active member",value:m.avg_points_per_active??0}),e.jsx(t,{label:"Total social interactions",value:Number(m.total_interactions??0).toLocaleString(),hint:"Kudos + msgs + responses + buddies"}),e.jsx(t,{label:"At-risk members",value:u.at_risk??0,hint:"Active before, silent 30d+"})]})]}),e.jsxs("section",{className:"grid lg:grid-cols-2 gap-4",children:[e.jsxs(c,{className:"p-4 rounded-2xl",children:[e.jsx("h3",{className:"font-semibold mb-3",children:"Gender mix"}),e.jsx("div",{style:{width:"100%",height:240},children:e.jsx(j,{children:e.jsxs(D,{children:[e.jsx(I,{data:P,dataKey:"value",nameKey:"name",outerRadius:90,innerRadius:50,label:!0,children:P.map(s=>e.jsx(Q,{fill:y[s.name]},s.name))}),e.jsx(p,{}),e.jsx(O,{})]})})})]}),e.jsxs(c,{className:"p-4 rounded-2xl",children:[e.jsx("h3",{className:"font-semibold mb-3",children:"Age brackets (by gender)"}),e.jsx("div",{style:{width:"100%",height:240},children:e.jsx(j,{children:e.jsxs(f,{data:W.map(s=>({bracket:s.label,Male:s.male,Female:s.female,Other:s.other,Unspecified:s.unspec})),children:[e.jsx(v,{dataKey:"bracket"}),e.jsx(N,{}),e.jsx(p,{}),e.jsx(O,{}),e.jsx(x,{dataKey:"Male",stackId:"a",fill:y.Male}),e.jsx(x,{dataKey:"Female",stackId:"a",fill:y.Female}),e.jsx(x,{dataKey:"Other",stackId:"a",fill:y.Other}),e.jsx(x,{dataKey:"Unspecified",stackId:"a",fill:y.Unspecified})]})})})]}),e.jsxs(c,{className:"p-4 rounded-2xl",children:[e.jsx("h3",{className:"font-semibold mb-3",children:"Top cities"}),e.jsx(G,{rows:V})]}),e.jsxs(c,{className:"p-4 rounded-2xl",children:[e.jsx("h3",{className:"font-semibold mb-3",children:"Top countries"}),e.jsx(G,{rows:X})]}),e.jsxs(c,{className:"p-4 rounded-2xl lg:col-span-2",children:[e.jsx("h3",{className:"font-semibold mb-3",children:"Top languages spoken"}),e.jsx("div",{style:{width:"100%",height:220},children:e.jsx(j,{children:e.jsxs(f,{data:(a.languages||[]).map(s=>({code:s.code,count:s.count})),children:[e.jsx(v,{dataKey:"code"}),e.jsx(N,{}),e.jsx(p,{}),e.jsx(x,{dataKey:"count",fill:"hsl(var(--primary))"})]})})})]})]}),e.jsxs("section",{children:[e.jsxs("div",{className:"flex justify-between items-center mb-2",children:[e.jsx("h2",{className:"font-bold text-lg",children:"Engagement funnel"}),e.jsx(b,{size:"sm",variant:"ghost",onClick:()=>z("engagement-funnel.csv",a.engagement_pct),children:"CSV"})]}),e.jsxs(c,{className:"p-4 rounded-2xl",children:[e.jsx("p",{className:"text-xs text-muted-foreground mb-2",children:"Each row: % of total members who have done this, broken down by gender."}),(a.engagement_pct||[]).map(s=>e.jsx(Z,{label:s.label,overall:s.overall,male:s.male,female:s.female,other:s.other},s.key))]})]}),e.jsxs("section",{className:"grid lg:grid-cols-2 gap-4",children:[e.jsxs(c,{className:"p-4 rounded-2xl",children:[e.jsx("h3",{className:"font-semibold mb-3",children:"Runs per member"}),e.jsx("div",{style:{width:"100%",height:220},children:e.jsx(j,{children:e.jsxs(f,{data:a.runs_distribution,children:[e.jsx(v,{dataKey:"bucket"}),e.jsx(N,{}),e.jsx(p,{}),e.jsx(x,{dataKey:"count",fill:"hsl(var(--primary))"})]})})})]}),e.jsxs(c,{className:"p-4 rounded-2xl",children:[e.jsx("h3",{className:"font-semibold mb-3",children:"Kilometres per member"}),e.jsx("div",{style:{width:"100%",height:220},children:e.jsx(j,{children:e.jsxs(f,{data:a.km_distribution,children:[e.jsx(v,{dataKey:"bucket"}),e.jsx(N,{}),e.jsx(p,{}),e.jsx(x,{dataKey:"count",fill:"hsl(var(--accent))"})]})})})]}),e.jsxs(c,{className:"p-4 rounded-2xl lg:col-span-2 grid grid-cols-2 md:grid-cols-4 gap-3",children:[e.jsx(t,{label:"Avg km / run",value:M.avg_km_per_run??0}),e.jsx(t,{label:"Longest run",value:`${M.longest_run_km??0} km`}),e.jsx(t,{label:"Median runs / active (30d)",value:M.median_runs_per_active??0}),e.jsx(t,{label:"Avg runs per member",value:n.avg_runs_per_member??0})]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"font-bold text-lg mb-2",children:"Weekly cohort retention"}),e.jsxs(c,{className:"p-4 rounded-2xl",children:[e.jsx("p",{className:"text-xs text-muted-foreground mb-3",children:"% of each weekly signup cohort that logged a run in week N."}),e.jsx(se,{rows:a.retention_cohorts||[]})]})]}),e.jsxs("section",{className:"grid grid-cols-2 md:grid-cols-4 gap-3",children:[e.jsx(t,{label:"Avg buddies / member",value:u.avg_buddies??0}),e.jsx(t,{label:"Network density",value:u.network_density??0}),e.jsx(t,{label:"Avg msgs / pair",value:u.avg_msgs_per_pair??0}),e.jsx(t,{label:"Group-run fill",value:`${u.group_run_fill??0}%`}),e.jsx(t,{label:"Run-call 'in' rate",value:`${u.run_call_in_rate??0}%`}),e.jsx(t,{label:"Buddy connections",value:n.buddy_connections}),e.jsx(t,{label:"Messages exchanged",value:n.messages}),e.jsx(t,{label:"Kudos given",value:n.kudos})]}),e.jsxs("section",{className:"grid lg:grid-cols-2 gap-4",children:[e.jsxs(c,{className:"p-4 rounded-2xl",children:[e.jsx("h3",{className:"font-semibold mb-3",children:"Loyalty tiers"}),e.jsx("div",{style:{width:"100%",height:220},children:e.jsx(j,{children:e.jsxs(D,{children:[e.jsx(I,{data:u.loyalty_tiers??[],dataKey:"count",nameKey:"tier",outerRadius:80,label:!0}),e.jsx(p,{}),e.jsx(O,{})]})})})]}),e.jsxs(c,{className:"p-4 rounded-2xl",children:[e.jsx("h3",{className:"font-semibold mb-3",children:"Top dog breeds"}),e.jsx("div",{style:{width:"100%",height:220},children:e.jsx(j,{children:e.jsxs(f,{data:u.top_breeds??[],layout:"vertical",children:[e.jsx(v,{type:"number"}),e.jsx(N,{type:"category",dataKey:"breed",width:120}),e.jsx(p,{}),e.jsx(x,{dataKey:"count",fill:"hsl(var(--primary))"})]})})})]})]})]})]})]})}export{me 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.