PageSourceSearch

https://myworshipfm.com/assets/AdminAnalytics-DUjeueni.js

js myworshipfm.com collected 2026-10-02 01:14:30 UTC 6,451 bytes, 1 lines download raw bytes

1import{r as o,j as e}from"./react-vendor-DJyVv-9k.js";import{ax as B,O as I,s as K,bw as f,W as F,X,Y,Z as G,_ as j,C as b,g as y,h as N,j as w}from"./index-SEobiKDJ.js";import{N as O}from"./router-CKKuDg_f.js";import{U as H,aP as J,bZ as W,b_ as Z,b$ as q}from"./icons-BX4ctka3.js";import{R as Q,b as ee,C as se,X as te,Y as ae,T as ie,d as ne}from"./charts-CPklpUXh.js";import"./capacitor-DHBo0MhY.js";import"./radix-BgH8Shby.js";import"./supabase-D3lgsHDr.js";import"./react-query-Dh77tccY.js";const S=u=>u==="24h"?24:u==="7d"?24*7:24*30,re={US:"United States",CN:"China mainland",CA:"Canada",JM:"Jamaica",AU:"Australia",DM:"Dominica",FR:"France",DE:"Germany",DK:"Denmark",GB:"United Kingdom",BR:"Brazil",MX:"Mexico",IN:"India"},ge=()=>{const{isAdmin:u,loading:M}=B(),{user:C,loading:D}=I(),[d,A]=o.useState("24h"),[r,_]=o.useState([]),[L,v]=o.useState(!0);o.useEffect(()=>{if(!u)return;let s=!1;return(async()=>{v(!0);const t=new Date(Date.now()-S(d)*36e5).toISOString(),{data:a}=await K.from("site_pageviews").select("session_id, path, source, device, country, created_at").gte("created_at",t).order("created_at",{ascending:!0}).limit(1e4);s||(_(a||[]),v(!1))})(),()=>{s=!0}},[u,d]);const m=o.useMemo(()=>{const s=new Map;for(const l of r)s.has(l.session_id)||s.set(l.session_id,[]),s.get(l.session_id).push(l);const t=s.size,a=r.length,n=t?a/t:0;let i=0,c=0;s.forEach(l=>{l.length===1&&(c+=1);const P=new Date(l[0].created_at).getTime(),$=new Date(l[l.length-1].created_at).getTime();i+=Math.max(0,($-P)/1e3)});const g=t?i/t:0,E=t?Math.round(c/t*100):0;return{visitors:t,pageviews:a,perVisit:n,avgDurSecs:g,bounceRate:E}},[r]),T=o.useMemo(()=>{const s=d==="24h"?36e5:864e5,t=new Map;for(const i of r){const c=Math.floor(new Date(i.created_at).getTime()/s)*s;t.has(c)||t.set(c,new Set),t.get(c).add(i.session_id)}const a=[],n=Date.now()-S(d)*36e5;for(let i=Math.floor(n/s)*s;i<=Date.now();i+=s){const c=new Date(i),g=d==="24h"?c.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}):c.toLocaleDateString([],{month:"short",day:"numeric"});a.push({label:g,value:t.get(i)?.size||0})}return a},[r,d]),h=s=>{const t=new Map;for(const a of r){const n=s(a)||"Unknown";t.has(n)||t.set(n,new Set),t.get(n).add(a.session_id)}return[...t.entries()].map(([a,n])=>({label:a,value:n.size})).sort((a,n)=>n.value-a.value).slice(0,10)},R=o.useMemo(()=>h(s=>s.path),[r]),k=o.useMemo(()=>h(s=>s.source),[r]),V=o.useMemo(()=>h(s=>s.device),[r]),U=o.useMemo(()=>h(s=>s.country),[r]),z=s=>{if(s<60)return`${Math.round(s)}s`;const t=Math.floor(s/60),a=Math.round(s%60);return`${t}m ${a}s`};if(M||D)return e.jsx(f,{children:e.jsx("div",{className:"container mx-auto px-4 py-8",children:"Loading…"})});if(!C)return e.jsx(O,{to:"/admin/login",replace:!0});if(!u)return e.jsx(f,{children:e.jsxs("div",{className:"container mx-auto px-4 py-16 text-center",children:[e.jsx("h2",{className:"text-2xl font-bold",children:"Access denied"}),e.jsx("p",{className:"text-muted-foreground",children:"Administrator privileges required."})]})});const x=({icon:s,label:t,value:a})=>e.jsxs("div",{className:"p-4 rounded-lg border bg-white",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm text-muted-foreground",children:t}),e.jsx(s,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsx("div",{className:"text-2xl font-bold",children:a})]}),p=({title:s,data:t,formatLabel:a})=>{const n=Math.max(1,...t.map(i=>i.value));return e.jsxs(b,{children:[e.jsxs(y,{className:"flex-row items-center justify-between pb-2",children:[e.jsx(N,{className:"text-base",children:s}),e.jsx("span",{className:"text-xs text-muted-foreground",children:"Visitors"})]}),e.jsxs(w,{className:"space-y-2",children:[t.length===0&&e.jsx("p",{className:"text-sm text-muted-foreground",children:"No data yet."}),t.map(i=>e.jsxs("div",{className:"relative",children:[e.jsxs("div",{className:"flex items-center justify-between text-sm py-1 px-2 rounded relative z-10",children:[e.jsx("span",{className:"truncate max-w-[75%]",title:i.label,children:a?a(i.label):i.label}),e.jsx("span",{className:"font-semibold",children:i.value})]}),e.jsx("div",{className:"absolute inset-y-0 left-0 rounded bg-primary/10",style:{width:`${i.value/n*100}%`},"aria-hidden":!0})]},i.label))]})]})};return e.jsx(f,{children:e.jsxs("div",{className:"container mx-auto px-4 py-8 space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-3",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl font-bold",children:"Site Analytics"}),e.jsx("p",{className:"text-muted-foreground",children:"Visitors, top pages, sources, devices and countries for myworshipfm.com."})]}),e.jsxs(F,{value:d,onValueChange:s=>A(s),children:[e.jsx(X,{className:"w-40",children:e.jsx(Y,{})}),e.jsxs(G,{children:[e.jsx(j,{value:"24h",children:"Last 24 hours"}),e.jsx(j,{value:"7d",children:"Last 7 days"}),e.jsx(j,{value:"30d",children:"Last 30 days"})]})]})]}
1),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-5 gap-3",children:[e.jsx(x,{icon:H,label:"Visitors",value:m.visitors}),e.jsx(x,{icon:J,label:"Page views",value:m.pageviews}),e.jsx(x,{icon:W,label:"Views per visit",value:m.perVisit.toFixed(2)}),e.jsx(x,{icon:Z,label:"Visit duration",value:z(m.avgDurSecs)}),e.jsx(x,{icon:q,label:"Bounce rate",value:`${m.bounceRate}%`})]}),e.jsxs(b,{children:[e.jsx(y,{children:e.jsx(N,{className:"text-base",children:"Visitors over time"})}),e.jsx(w,{style:{height:280},children:L?e.jsx("div",{className:"h-full flex items-center justify-center text-muted-foreground",children:"Loading…"}):e.jsx(Q,{width:"100%",height:"100%",children:e.jsxs(ee,{data:T,children:[e.jsx(se,{strokeDasharray:"3 3",opacity:.3}),e.jsx(te,{dataKey:"label",fontSize:11,tickMargin:6}),e.jsx(ae,{allowDecimals:!1,fontSize:11,width:30}),e.jsx(ie,{}),e.jsx(ne,{type:"monotone",dataKey:"value",stroke:"hsl(var(--primary))",strokeWidth:2,dot:!1})]})})})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4",children:[e.jsx(p,{title:"Top pages",data:R}),e.jsx(p,{title:"Sources",data:k}),e.jsx(p,{title:"Devices",data:V,formatLabel:s=>s.charAt(0).toUpperCase()+s.slice(1)}),e.jsx(p,{title:"Countries",data:U,formatLabel:s=>re[s]||s})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Data is captured in-app from public site visits (admin pages excluded). Country is derived from IP geolocation on first visit."})]})})};export{ge 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.