Repository navigation
Expand file tree
/
Copy pathadmin-analytics.html
More file actions
108 lines (104 loc) · 7.57 KB
/
Copy pathadmin-analytics.html
File metadata and controls
108 lines (104 loc) · 7.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
<!DOCTYPE html>
<html lang="en">
<head>
<style id="auth-gate">html{visibility:hidden}</style>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smitten — Analytics</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&family=Caveat:wght@600;700&family=Quicksand:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/admin.css">
<script src="assets/js/supabase-config.js"></script>
<script src="assets/js/vendor/supabase.js"></script>
<script src="assets/js/supabase-client.js"></script>
<script src="assets/js/auth.js"></script>
<script src="assets/js/ui-helpers.js"></script>
<script src="assets/js/api.js"></script>
<script src="assets/js/admin-shell.js"></script>
</head>
<body>
<script>AUTH.requireAdmin();</script>
<svg style="position:absolute;width:0;height:0;"><defs>
<symbol id="d-heart" viewBox="0 0 100 92"><path d="M50 88 C15 62 4 40 12 24 C19 10 40 8 50 24 C60 8 81 10 88 24 C96 40 85 62 50 88 Z"/></symbol>
</defs></svg>
<aside>
<div class="brand"><svg viewBox="0 0 100 92" style="width:18px;height:18px;stroke:var(--pink);stroke-width:8;fill:none;"><use href="#d-heart"/></svg>Smitten Admin</div>
<div class="god-badge">✦ Super Admin · Full Access</div>
<div class="nav-group">
<div class="nav-label">Overview</div>
<a class="nav-item" href="admin.html"><svg viewBox="0 0 24 24" fill="none"><rect x="3" y="3" width="8" height="8" rx="2" stroke="#3A2B39" stroke-width="2"/><rect x="13" y="3" width="8" height="8" rx="2" stroke="#3A2B39" stroke-width="2"/><rect x="3" y="13" width="8" height="8" rx="2" stroke="#3A2B39" stroke-width="2"/><rect x="13" y="13" width="8" height="8" rx="2" stroke="#3A2B39" stroke-width="2"/></svg> Dashboard</a>
</div>
<div class="nav-group">
<div class="nav-label">Manage</div>
<a class="nav-item" href="admin-users.html"><svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="8" r="4" stroke="#7A6B78" stroke-width="2"/><path d="M4 21c0-4.4 3.6-7 8-7s8 2.6 8 7" stroke="#7A6B78" stroke-width="2"/></svg> Users</a>
<a class="nav-item" href="admin-invitations.html"><svg viewBox="0 0 24 24" fill="none"><rect x="3" y="5" width="18" height="16" rx="3" stroke="#7A6B78" stroke-width="2"/><path d="M3 10h18" stroke="#7A6B78" stroke-width="2"/></svg> Notes / Invitations</a>
<a class="nav-item" href="admin-templates.html"><svg viewBox="0 0 24 24" fill="none"><path d="M4 19l1-9 7-7 7 7-1 9a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2z" stroke="#7A6B78" stroke-width="2"/></svg> Templates</a>
<a class="nav-item" href="admin-sections.html"><svg viewBox="0 0 24 24" fill="none"><rect x="4" y="4" width="7" height="7" rx="2" stroke="#7A6B78" stroke-width="2"/><rect x="13" y="4" width="7" height="7" rx="2" stroke="#7A6B78" stroke-width="2"/><rect x="4" y="13" width="7" height="7" rx="2" stroke="#7A6B78" stroke-width="2"/><rect x="13" y="13" width="7" height="7" rx="2" stroke="#7A6B78" stroke-width="2"/></svg> Sections</a>
</div>
<div class="nav-group">
<div class="nav-label">Trust & Safety</div>
<a class="nav-item" href="admin-reports.html"><svg viewBox="0 0 24 24" fill="none"><path d="M12 3l8 3.5v5c0 5-3.4 8.7-8 9.5-4.6-.8-8-4.5-8-9.5v-5L12 3z" stroke="#7A6B78" stroke-width="2"/></svg> Reports</a>
<a class="nav-item" href="admin-audit.html"><svg viewBox="0 0 24 24" fill="none"><path d="M4 6h16M4 12h16M4 18h10" stroke="#7A6B78" stroke-width="2" stroke-linecap="round"/></svg> Audit Log</a>
</div>
<div class="nav-group">
<div class="nav-label">Commerce</div>
<a class="nav-item" href="admin-orders.html"><svg viewBox="0 0 24 24" fill="none"><circle cx="9" cy="20" r="1.4" fill="#7A6B78"/><circle cx="18" cy="20" r="1.4" fill="#7A6B78"/><path d="M2 3h3l2.4 12.2a2 2 0 0 0 2 1.8h8.6a2 2 0 0 0 2-1.6L22 8H6" stroke="#7A6B78" stroke-width="2" stroke-linecap="round"/></svg> Orders</a>
<a class="nav-item" href="admin-payments.html"><svg viewBox="0 0 24 24" fill="none"><rect x="2" y="6" width="20" height="13" rx="3" stroke="#7A6B78" stroke-width="2"/><path d="M2 10h20" stroke="#7A6B78" stroke-width="2"/></svg> Payments</a>
<a class="nav-item active" href="admin-analytics.html"><svg viewBox="0 0 24 24" fill="none"><path d="M4 19V9M10 19V5M16 19v-7M22 19V3" stroke="#7A6B78" stroke-width="2" stroke-linecap="round"/></svg> Analytics</a>
</div>
<div class="nav-group">
<div class="nav-label">System</div>
<a class="nav-item" href="admin-settings.html"><svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="3" stroke="#7A6B78" stroke-width="2"/><path d="M19 12a7 7 0 0 0-.2-1.6l2-1.5-2-3.4-2.3.9a7 7 0 0 0-2.8-1.6L13.3 2h-2.6l-.4 2.8a7 7 0 0 0-2.8 1.6l-2.3-.9-2 3.4 2 1.5A7 7 0 0 0 5 12c0 .5.1 1.1.2 1.6l-2 1.5 2 3.4 2.3-.9c.8.7 1.8 1.3 2.8 1.6l.4 2.8h2.6l.4-2.8a7 7 0 0 0 2.8-1.6l2.3.9 2-3.4-2-1.5c.1-.5.2-1.1.2-1.6z" stroke="#7A6B78" stroke-width="1.6"/></svg> Settings</a>
</div>
<div style="margin-top:auto;padding:14px 6px 4px;">
<a href="dashboard.html" class="nav-item" style="color:var(--ink-soft);">← Back to app</a>
</div>
</aside>
<main>
<header class="top">
<h1>📈 Analytics</h1>
<div class="topright"><div class="avatar"></div></div>
</header>
<div class="stats c5" id="an-stats">
<div class="stat a1"><div class="num">…</div><div class="lbl">Users</div></div>
<div class="stat a2"><div class="num">…</div><div class="lbl">Notes sent</div></div>
<div class="stat a3"><div class="num">…</div><div class="lbl">Open → response</div></div>
<div class="stat a4"><div class="num">…</div><div class="lbl">Acceptance rate</div></div>
<div class="stat"><div class="num">—</div><div class="lbl">Avg. time to respond</div></div>
</div>
<div class="panel">
<div class="panel-head"><h3>Funnel — all time</h3></div>
<div style="padding:20px 22px 26px;display:flex;flex-direction:column;gap:14px;" id="funnel"></div>
</div>
</main>
<script>
(async function () {
const statsEl = document.getElementById("an-stats");
const funnelEl = document.getElementById("funnel");
try {
const s = await API.admin.stats();
const openResponse = s.opened ? Math.round((100 * s.responded) / s.opened) : 0;
statsEl.innerHTML = `
<div class="stat a1"><div class="num">${s.users.toLocaleString()}</div><div class="lbl">Users</div></div>
<div class="stat a2"><div class="num">${s.notes_sent.toLocaleString()}</div><div class="lbl">Notes sent</div></div>
<div class="stat a3"><div class="num">${openResponse}%</div><div class="lbl">Open → response</div></div>
<div class="stat a4"><div class="num">${s.acceptance_rate}%</div><div class="lbl">Acceptance rate</div></div>
<div class="stat"><div class="num">—</div><div class="lbl">Avg. time to respond</div></div>`;
const max = s.notes_sent || 1;
const bars = [
["Sent", s.notes_sent, "var(--pink)"],
["Opened", s.opened, "var(--lavender)"],
["Responded", s.responded, "var(--yellow)"],
["Accepted", s.accepted, "var(--mint)"],
];
funnelEl.innerHTML = bars.map(([label, val, color]) => `
<div><div style="display:flex;justify-content:space-between;font-size:12.5px;font-weight:700;margin-bottom:6px;"><span>${label}</span><span>${val.toLocaleString()}</span></div>
<div style="height:14px;border-radius:8px;border:2px solid var(--ink);background:${color};width:${Math.max(2, Math.round((100 * val) / max))}%;"></div></div>`).join("");
} catch (err) {
statsEl.innerHTML = UI.errorBlock(UI.friendlyError(err));
}
})();
</script>
</body>
</html>