- New /admin/activity page: live login events, failed attempts, active
sessions from audit_log + sessions tables; auto-refresh toggle
- New /api/admin/activity route: queries audit_log + sessions for
stats (active sessions, logins/failures 24h, signups 7d) and events
- Fix /api/admin/stats: real growth charts (families/users by day),
real children-by-age, real conversion rate, active sessions count,
and login/failure counts — was all hardcoded empty arrays before
- Fix /api/admin/analytics: avg logs per family now divides by actual
family count instead of hardcoded 1
- Dashboard: 6-card grid adding Active Sessions + Failed Logins 24h
with links to Activity Monitor; bar charts now show hover counts
- Families: inline tier upgrade/downgrade button (Pro ↑ / Free ↓)
wired to existing PATCH API; member panel polished
- Support: admin reply thread using support_responses table; Cmd+Enter
to send; conversation view with original message + admin replies;
auto-moves ticket to in_progress on first reply
- Settings: honest read-only display for env-var-controlled settings
(pricing, AI config); editable free-tier limits that write to DB
- New /api/admin/families/limits route for bulk free-tier limit update
- Sidebar: added Activity Monitor nav item
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root causes:
- tia_admin_session is httpOnly so document.cookie could never read it → all
client-side cookie checks always failed and redirected before any data fetched
- Sub-pages used localStorage.getItem("admin_token") which was never stored,
and passed Authorization: Bearer null headers the server ignores
Fixes:
- FamilyProvider: use usePathname() hook instead of window.location.pathname
- admin/layout.tsx: rewrite as server component using verifyAdminSession()
(new lib/admin-auth.ts helper that uses next/headers cookies()) → server-side
redirect to /admin-login if session invalid; extract sidebar to AdminSidebar.tsx
- admin/page.tsx: remove broken document.cookie guard (layout handles auth now)
- admin-login/page.tsx: replace document.cookie check with GET /api/admin/auth call
- All 7 admin sub-pages: remove localStorage guard, remove Authorization: Bearer
headers, add credentials: include to every fetch call
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>