PageSourceSearch

https://otify.ai/assets/analytics-BJi5J53G.js

js otify.ai collected 2026-10-05 13:09:34 UTC 11,597 bytes, 1 lines download raw bytes

1import{a as n,j as e}from"./vendor-query-DpmjRaff.js";import{u as W,d as I,e as Y}from"./api-C_3je0sM.js";import{A as H}from"./AppLayout-C5uxni6X.js";import{C as c,a as m,b as h,c as p,d as u}from"./card-0UxxyZVB.js";import{B as _}from"./button-DFpU9D0S.js";import{u as J,f as A,c as Q}from"./index-CpQEu0WC.js";import{U as R,X as Z}from"./vendor-lucide-7RWYeRgH.js";import{R as v,L as ee,C as T,X as $,Y as D,T as N,a as w,b as C,B as te,d as z,P as se,e as ae,f as re}from"./vendor-charts-BLhBHYFa.js";import"./vendor-router-C2uiXmW_.js";import"./vendor-motion-BmrqGbJq.js";import"./vendor-radix-oX6yOSYI.js";import"./vendor-react-CGVP4TbQ.js";const S="https://otify.ai/api";function je(){const{admin:L,token:o}=J(),s=L?.role==="superadmin",[d,V]=n.useState("7d"),[x,K]=n.useState([]),[r,f]=n.useState(null),[j,P]=n.useState(null),[B,k]=n.useState(!1),i={whatsapp:"hsl(142, 71%, 45%)",sms:"hsl(262, 83%, 58%)",email:"hsl(221, 83%, 53%)",rcs:"hsl(199, 89%, 48%)",truecaller:"hsl(38, 92%, 50%)",success:"hsl(142, 71%, 45%)",failed:"hsl(346, 87%, 60%)",sent:"hsl(217, 91%, 60%)"},F=t=>{const a=new Date(t);return d==="24h"?a.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}):a.toLocaleDateString([],{month:"short",day:"numeric"})},E=({active:t,payload:a,label:b})=>t&&a&&a.length?e.jsxs("div",{className:"bg-card/90 backdrop-blur-md border border-white/10 p-4 rounded-xl shadow-xl",children:[e.jsx("p",{className:"text-white mb-2 font-medium",children:new Date(b).toLocaleString()}),a.map((y,U)=>e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx("div",{className:"w-2 h-2 rounded-full",style:{backgroundColor:y.color}}),e.jsxs("span",{className:"text-muted-foreground capitalize",children:[y.name,":"]}),e.jsx("span",{className:"text-white font-mono font-medium",children:y.value})]},U))]}):null;n.useEffect(()=>{!s||!o||fetch(`${S}/reporting/clients`,{headers:{Authorization:`Bearer ${o}`}}).then(t=>t.json()).then(t=>K(t.clients??[])).catch(()=>{})},[s,o]),n.useEffect(()=>{if(!s||!o)return;const t=r?`${S}/reporting/client-analytics?clientId=${r.id}&period=${d}`:`${S}/reporting/client-analytics?period=${d}`;k(!0),fetch(t,{headers:{Authorization:`Bearer ${o}`}}).then(a=>a.json()).then(a=>P(a)).catch(()=>{}).finally(()=>k(!1))},[s,o,r,d]);const{data:G}=W({query:{enabled:!s}}),{data:M}=I({query:{enabled:!s}}),{data:O}=Y({period:d},{query:{enabled:!s}}),l=s?j?.summary:G,g=s?j?.channelStats:M?.stats,X=s?j?.timeseries?.map(t=>({timestamp:t.ts,...t}))??[]:O?.data??[],q=s?"ts":"timestamp";return e.jsx(H,{children:e.jsxs("div",{className:"space-y-6 pb-12",children:[e.jsxs("div",{className:"flex flex-col md:flex-row justify-between items-start md:items-end gap-4",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl font-display font-bold text-white mb-2",children:s?"Platform Analytics":"Analytics"}),e.jsx("p",{className:"text-muted-foreground",children:s?"Combined platform view across all clients, with per-client drill-down.":"Deep dive into dispatch volumes, conversion rates, and channel performance."})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[s&&x.length>0&&e.jsxs("select",{className:"h-9 rounded-xl border border-white/10 bg-black/40 px-3 text-sm text-white focus:outline-none focus:ring-2 focus:ring-primary/50 appearance-none min-w-[180px]",value:r?.id??"",onChange:t=>{const a=x.find(b=>b.id===t.target.value)??null;f(a)},children:[e.jsx("option",{value:"",children:"All Clients (Combined)"}),x.map(t=>e.jsx("option",{value:t.id,children:t.name},t.id))]}),e.jsx("div",{className:"flex bg-black/40 p-1 rounded-xl border border-white/10",children:["24h","7d","30d"].map(t=>e.jsx(_,{variant:"ghost",size:"sm",className:`rounded-lg ${d===t?"bg-white/10 text-white shadow-sm":"text-muted-foreground"}`,onClick:()=>V(t),children:t.toUpperCase()},t))})]})]}),s&&r&&e.jsx("div",{className:"flex items-center gap-2",children:e.jsxs("div",{className:"flex items-center gap-2 px-3 py-1.5 rounded-lg bg-primary/10 border border-primary/20 text-xs text-primary",children:[e.jsx(R,{className:"w-3.5 h-3.5"}),e.jsxs("span",{children:["Viewing: ",e.jsx("span",{className:"font-semibold",children:r.name})]}),e.jsxs("span",{className:"text-primary/60",children:["(",r.email,")"]}),e.jsx("button",{onClick:()=>f(null),className:"ml-1 hover:text-white transition-colors",children:e.jsx(Z,{className:"w-3 h-3"})})]})}),s&&B&&e.jsx("div",{className:"flex items-center justify-center h-20",children:e.jsx("div",{className:"w-8 h-8 border-2 border-primary/30 border-t-primary rounded-full animate-spin"})}),e.jsx("div",{className:"grid grid-cols-2 lg:grid-cols-4 gap-4",children:[{label:"Total Sent",value:l?.totalSent,color:"text-white"},{label:"Total Verified",value:l?.totalVerified,color:"text-emerald-400"},{label:"Total Failed",value:l?.totalFailed,color:"text-rose-400"},{label:"Avg Delivery Rate",value:`${Math.round(l?.deliveryRate||0)}%`,color:"text-blue-400"}
1].map((t,a)=>e.jsx(c,{className:"border-white/5 bg-gradient-to-br from-white/[0.02] to-transparent",children:e.jsxs(m,{className:"p-4",children:[e.jsx("p",{className:"text-xs text-muted-foreground uppercase tracking-wider mb-1",children:t.label}),e.jsx("p",{className:`text-2xl font-display font-bold ${t.color}`,children:t.value!==void 0?typeof t.value=="number"?A(t.value):t.value:"…"})]})},a))}),s&&e.jsx("div",{className:"grid grid-cols-2 lg:grid-cols-4 gap-4",children:[{label:"Verification Rate",value:`${Math.round(l?.verificationRate||0)}%`,color:"text-emerald-400"},{label:"Fallback Rate",value:`${Math.round(l?.fallbackRate||0)}%`,color:"text-amber-400"},{label:"Avg Verify Time",value:`${l?.avgVerifyTimeSeconds??0}s`,color:"text-violet-400"},{label:"Total Expired",value:l?.totalExpired,color:"text-zinc-400"}].map((t,a)=>e.jsx(c,{className:"border-white/5 bg-gradient-to-br from-white/[0.02] to-transparent",children:e.jsxs(m,{className:"p-4",children:[e.jsx("p",{className:"text-xs text-muted-foreground uppercase tracking-wider mb-1",children:t.label}),e.jsx("p",{className:`text-2xl font-display font-bold ${t.color}`,children:t.value!==void 0?typeof t.value=="number"?A(t.value):t.value:"…"})]})},a))}),e.jsxs(c,{className:"border-white/10 shadow-2xl",children:[e.jsxs(h,{children:[e.jsx(p,{children:"Dispatch & Verification Volume"}),e.jsx(u,{children:r?`Activity for ${r.name} over the selected period.`:"Chronological breakdown over selected period."})]}),e.jsx(m,{children:e.jsx("div",{className:"h-[350px] w-full mt-4",children:e.jsx(v,{width:"100%",height:"100%",children:e.jsxs(ee,{data:X,margin:{top:5,right:5,left:-20,bottom:0},children:[e.jsx(T,{strokeDasharray:"3 3",stroke:"rgba(255,255,255,0.05)",vertical:!1}),e.jsx($,{dataKey:q,stroke:"rgba(255,255,255,0.3)",fontSize:12,tickFormatter:F,tickMargin:10}),e.jsx(D,{stroke:"rgba(255,255,255,0.3)",fontSize:12,tickFormatter:t=>t>=1e3?`${t/1e3}k`:t}),e.jsx(N,{content:e.jsx(E,{})}),e.jsx(w,{wrapperStyle:{paddingTop:"20px"}}),e.jsx(C,{type:"monotone",dataKey:"sent",name:"Sent",stroke:i.sent,strokeWidth:3,dot:!1,activeDot:{r:6,fill:i.sent}}),e.jsx(C,{type:"monotone",dataKey:"verified",name:"Verified",stroke:i.success,strokeWidth:3,dot:!1,activeDot:{r:6,fill:i.success}}),e.jsx(C,{type:"monotone",dataKey:"failed",name:"Failed",stroke:i.failed,strokeWidth:2,strokeDasharray:"5 5",dot:!1})]})})})})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs(c,{className:"border-white/10",children:[e.jsxs(h,{children:[e.jsx(p,{children:"Channel Performance"}),e.jsx(u,{children:"Delivery vs Verification rates per channel."})]}),e.jsx(m,{children:e.jsx("div",{className:"h-[300px] w-full mt-4",children:e.jsx(v,{width:"100%",height:"100%",children:e.jsxs(te,{data:g??[],layout:"vertical",margin:{top:5,right:30,left:20,bottom:5},children:[e.jsx(T,{strokeDasharray:"3 3",stroke:"rgba(255,255,255,0.05)",horizontal:!1}),e.jsx($,{type:"number",stroke:"rgba(255,255,255,0.3)",fontSize:12,unit:"%"}),e.jsx(D,{dataKey:"channel",type:"category",stroke:"rgba(255,255,255,0.7)",fontSize:12,width:80,style:{textTransform:"capitalize"}}),e.jsx(N,{cursor:{fill:"rgba(255,255,255,0.05)"},contentStyle:{backgroundColor:"rgba(24,24,27,0.9)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"8px"}}),e.jsx(w,{}),e.jsx(z,{dataKey:"deliveryRate",name:"Delivery Rate %",fill:i.sent,radius:[0,4,4,0],barSize:20}),e.jsx(z,{dataKey:"verificationRate",name:"Verify Rate %",fill:i.success,radius:[0,4,4,0],barSize:20})]})})})})]}),e.jsxs(c,{className:"border-white/10",children:[e.jsxs(h,{children:[e.jsx(p,{children:"Channel Distribution"}),e.jsx(u,{children:"Total OTPs sent by channel."})]}),e.jsx(m,{className:"flex items-center justify-center",children:e.jsx("div",{className:"h-[300px] w-full",children:e.jsx(v,{width:"100%",height:"100%",children:e.jsxs(se,{children:[e.jsx(ae,{data:g??[],cx:"50%",cy:"50%",innerRadius:80,outerRadius:110,paddingAngle:5,dataKey:"sent",nameKey:"channel",stroke:"none",children:(g??[]).map((t,a)=>e.jsx(re,{fill:i[t.channel]||"#8884d8"},`cell-${a}`))}),e.jsx(N,{contentStyle:{backgroundColor:"rgba(24,24,27,0.9)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"8px"},itemStyle:{color:"#fff"}}),e.jsx(w,{verticalAlign:"bottom",height:36,iconType:"circle",formatter:t=>e.jsx("span",{className:"capitalize text-white/80",children:t})})]})})})})]})]}),s&&!r&&x.length>0&&e.jsxs(c,{className:"border-white/10",children:[e.jsxs(h,{children:[e.jsxs(p,{className:"flex items-center gap-2",children:[e.jsx(R,{className:"w-5 h-5 text-primary"}),"Client Comparison"]}),e.jsx(u,{children:"All-time OTP volumes per client. Click a client to drill in."})]}),e.jsx(m,{className:"p-0",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-white/5 text-xs text-muted-foreground uppercase tracking-wider",children:[e.jsx("th",{className:"text-left px-6 py-3 font-medium",children:"Client"}),e.jsx("th",{className:"text-right px-6 py-3 font-medium",children:"Total Sent"}),e.jsx("th",{className:"text-right px-6 py-3 font-medium",children:"Verified"}),e.jsx("th",{className:"text-right px-6 py-3 font-medium",children:"Failed"}),e.jsx("th",{className:"text-right px-6 py-3 font-medium",children:"Verify Rate"}),e.jsx("th",{className:"px-6 py-3"})]})}),e.jsx("tbody",{className:"divide-y divide-white/5",children:x.map(t=>e.jsxs("tr",{className:"hover:bg-white/[0.02] transition-colors",children:[e.jsx("td",{className:"px-6 py-3",children:e.jsxs("div",{children:[e.jsx("p",{className:"text-white font-medium text-sm",children:t.name}),e.jsx("p",{className:"text-muted-foreground text-xs",children:t.email})]})}),e.jsx("td",{className:"px-6 py-3 text-right text-white font-mono text-sm",children:(t.totalSent??0).toLocaleStr
1ing()}),e.jsx("td",{className:"px-6 py-3 text-right text-emerald-400 font-mono text-sm",children:(t.totalVerified??0).toLocaleString()}),e.jsx("td",{className:"px-6 py-3 text-right text-rose-400 font-mono text-sm",children:(t.totalFailed??0).toLocaleString()}),e.jsx("td",{className:"px-6 py-3 text-right",children:e.jsxs("span",{className:Q("text-sm font-medium",(t.verificationRate??0)>=70?"text-emerald-400":(t.verificationRate??0)>=40?"text-amber-400":"text-rose-400"),children:[t.verificationRate??0,"%"]})}),e.jsx("td",{className:"px-6 py-3 text-right",children:e.jsx("button",{onClick:()=>f(t),className:"text-xs px-3 py-1 rounded-lg bg-primary/10 border border-primary/20 text-primary hover:bg-primary/20 transition-all",children:"Drill in →"})})]},t.id))})]})})})]})]})})}export{je 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.