microtecflix/src/AdminApp.tsx

194 lines
7.5 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import {
Play, Shield, LogOut, ArrowRight, Lock, Mail, RefreshCw,
Layers, ShieldAlert, Users, GraduationCap, DollarSign, Database
} from 'lucide-react';
import AdminDashboard from './components/AdminDashboard';
import AdminContentManager from './components/AdminContentManager';
export default function AdminApp() {
const [token, setToken] = useState<string | null>(localStorage.getItem('devflix_admin_token'));
const [adminUser, setAdminUser] = useState<{
name: string;
email: string;
role: 'admin';
} | null>(null);
// App routing inside admin panel
const [activeView, setView] = useState<'dashboard' | 'courses'>('dashboard');
// Authentication forms
const [loginEmail, setLoginEmail] = useState('');
const [loginPassword, setLoginPassword] = useState('');
const [authError, setAuthError] = useState<string | null>(null);
const [authLoading, setAuthLoading] = useState(false);
useEffect(() => {
if (token) {
fetchAdminProfile();
}
}, [token]);
const fetchAdminProfile = async () => {
try {
const res = await fetch('/api/auth/me', {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (res.ok) {
const data = await res.json();
if (data.role === 'admin') {
setAdminUser(data);
} else {
// If a student tries to use the admin token
setAuthError('Token inválido para acesso administrativo.');
handleLogout();
}
} else {
handleLogout();
}
} catch (err) {
console.error('Failed to load profile:', err);
handleLogout();
}
};
const handleLogin = async (e: React.FormEvent) => {
e.preventDefault();
setAuthError(null);
setAuthLoading(true);
try {
const res = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: loginEmail, password: loginPassword })
});
const data = await res.json();
if (!res.ok) {
throw new Error(data.error || 'Erro ao efetuar login');
}
if (data.user.role !== 'admin') {
throw new Error('Acesso recusado. Apenas administradores podem acessar esta área.');
}
localStorage.setItem('devflix_admin_token', data.token);
setToken(data.token);
setAdminUser(data.user);
setLoginEmail('');
setLoginPassword('');
} catch (err: any) {
setAuthError(err.message);
} finally {
setAuthLoading(false);
}
};
const handleLogout = () => {
localStorage.removeItem('devflix_admin_token');
setToken(null);
setAdminUser(null);
};
const quickFillAdmin = () => {
setLoginEmail('sidney.gomes1989@gmail.com');
setLoginPassword('admin123');
setAuthError(null);
};
return (
<div className="min-h-screen bg-[#0b0c10] text-zinc-100 flex flex-col selection:bg-[#E50914] selection:text-white font-sans">
{token && adminUser ? (
<AdminDashboard token={token} adminUser={adminUser} onLogout={handleLogout} />
) : (
/* --- UNAUTHENTICATED ADMIN ACCESS SCREEN --- */
<div className="flex-grow flex items-center justify-center p-4 md:p-8 relative" style={{ backgroundImage: `linear-gradient(rgba(11,12,16,0.9), rgba(11,12,16,0.9)), url('https://images.unsplash.com/photo-1558494949-ef010cbdcc31?q=80&w=1200&auto=format&fit=crop')`, backgroundSize: 'cover', backgroundPosition: 'center' }}>
<div className="absolute inset-0 bg-black/40 z-0" />
{/* Glass login panel */}
<div className="relative z-10 w-full max-w-md glass-card rounded-2xl p-6 md:p-10 space-y-6 shadow-2xl border border-white/10">
{/* Admin Header Accent */}
<div className="flex flex-col items-center space-y-3 text-center">
<div className="bg-[#E50914] text-white p-3 rounded-xl flex items-center justify-center shadow-lg animate-pulse">
<Shield className="w-7 h-7" />
</div>
<div className="space-y-1">
<h1 className="font-display font-black text-2xl tracking-tighter text-white">
MICROTEC<span className="text-[#E50914]">FLIX</span> <span className="text-zinc-500 font-medium text-lg">ADMIN</span>
</h1>
<p className="text-[11px] text-zinc-400 font-medium">Autenticação obrigatória para gestores, administradores e moderadores.</p>
</div>
</div>
{/* Error notifications */}
{authError && (
<div className="bg-red-950/40 border border-red-900/50 text-red-400 p-3.5 rounded-xl text-xs leading-relaxed text-center flex items-center justify-center space-x-2">
<ShieldAlert className="w-4 h-4 flex-shrink-0 text-red-500" />
<span>{authError}</span>
</div>
)}
{/* Form */}
<form onSubmit={handleLogin} className="space-y-4">
<div className="space-y-1">
<label className="text-[10px] text-zinc-400 font-bold uppercase tracking-wider">E-mail Administrativo</label>
<div className="relative">
<Mail className="absolute left-3.5 top-3.5 w-4 h-4 text-zinc-500" />
<input
type="email"
required
value={loginEmail}
onChange={(e) => setLoginEmail(e.target.value)}
placeholder="email.admin@devflix.com"
className="w-full glass-input rounded-xl p-3.5 pl-11 text-xs text-white focus:outline-none"
/>
</div>
</div>
<div className="space-y-1">
<label className="text-[10px] text-zinc-400 font-bold uppercase tracking-wider">Senha de Segurança</label>
<div className="relative">
<Lock className="absolute left-3.5 top-3.5 w-4 h-4 text-zinc-500" />
<input
type="password"
required
value={loginPassword}
onChange={(e) => setLoginPassword(e.target.value)}
placeholder="Sua senha privada"
className="w-full glass-input rounded-xl p-3.5 pl-11 text-xs text-white focus:outline-none"
/>
</div>
</div>
<button
type="submit"
disabled={authLoading}
className="w-full glass-btn-primary text-white text-xs font-bold py-3.5 px-4 rounded-xl flex items-center justify-center space-x-2 cursor-pointer disabled:opacity-50"
>
<span>{authLoading ? 'Autenticando...' : 'Acessar Painel de Controle'}</span>
<ArrowRight className="w-4 h-4" />
</button>
{/* SANDBOX ACCESS PRESET */}
<div className="border-t border-white/5 pt-4">
<button
type="button"
onClick={quickFillAdmin}
className="w-full bg-white/5 hover:bg-white/10 text-zinc-300 font-bold p-2.5 rounded-lg text-xs transition-colors flex items-center justify-center space-x-1"
>
<Users className="w-4 h-4 text-[#E50914]" />
<span>Entrar com Credencial Admin Demonstrativa</span>
</button>
</div>
</form>
</div>
</div>
)}
</div>
);
}