WellNuo/admin/components/AdminLayout.js
Sergei ec63a2c1e2 Add admin panel, optimized API, OTP auth, migrations
Admin Panel (Next.js):
- Dashboard with stats
- Users list with relationships (watches/watched_by)
- User detail pages
- Deployments list and detail pages
- Devices, Orders, Subscriptions pages
- OTP-based admin authentication

Backend Optimizations:
- Fixed N+1 query problem in admin APIs
- Added pagination support
- Added .range() and count support to Supabase wrapper
- Optimized batch queries with lookup maps

Database:
- Added migrations for schema evolution
- New tables: push_tokens, notification_settings
- Updated access model

iOS Build Scripts:
- build-ios.sh, clear-apple-cache.sh
- EAS configuration updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-20 11:05:39 -08:00

51 lines
1.1 KiB
JavaScript

'use client';
import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import Sidebar from './Sidebar';
export default function AdminLayout({ children }) {
const router = useRouter();
const [loading, setLoading] = useState(true);
useEffect(() => {
const token = localStorage.getItem('adminToken');
console.log('[LAYOUT] Checking token:', token ? 'exists' : 'missing');
if (!token) {
console.log('[LAYOUT] No token, redirecting to login');
window.location.href = '/admin/login';
} else {
console.log('[LAYOUT] Token found, allowing access');
setLoading(false);
}
}, [router]);
if (loading) {
return (
<div style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
minHeight: '100vh',
color: 'var(--text-muted)'
}}>
Loading...
</div>
);
}
return (
<div style={{ display: 'flex' }}>
<Sidebar />
<main style={{
marginLeft: '240px',
flex: 1,
minHeight: '100vh',
padding: '32px',
}}>
{children}
</main>
</div>
);
}