Files
aletheia/frontend/src/app/login/page.tsx
bigtux 20a26affaa 📚 Documentação inicial do ALETHEIA
- MANUAL-PRODUTO.md: Manual do usuário final
- MANUAL-VENDAS.md: Estratégia comercial e vendas
- MANUAL-TECNICO.md: Infraestrutura e deploy
- README.md: Visão geral do projeto
2026-02-10 15:08:15 -03:00

86 lines
3.7 KiB
TypeScript

'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import Link from 'next/link';
import { useAuthStore } from '@/stores/authStore';
export default function LoginPage() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const router = useRouter();
const { setAuth } = useAuthStore();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
setError('');
try {
const API = process.env.NEXT_PUBLIC_API_URL || '';
const res = await fetch(`${API}/api/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.detail || 'Credenciais inválidas');
setAuth(data.access_token, data.user);
router.push('/scan');
} catch (err: any) {
setError(err.message || 'Credenciais inválidas');
} finally {
setLoading(false);
}
};
return (
<div className="min-h-screen bg-dark flex items-center justify-center px-4 relative overflow-hidden">
{/* Orbs */}
<div className="orb orb-primary w-[400px] h-[400px] -top-[150px] -right-[100px]" />
<div className="orb orb-accent w-[300px] h-[300px] bottom-[10%] -left-[100px]" />
<div className="relative z-10 w-full max-w-md animate-fade-up">
{/* Logo */}
<div className="text-center mb-10">
<div className="w-16 h-16 rounded-2xl bg-gradient-to-br from-primary to-accent flex items-center justify-center mx-auto mb-4">
<svg width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="2.5" strokeLinecap="round">
<circle cx="12" cy="12" r="10" /><circle cx="12" cy="12" r="4" />
</svg>
</div>
<h1 className="text-3xl font-black gradient-text">ALETHEIA</h1>
<p className="text-gray-500 text-sm mt-1">A verdade sobre o que você come</p>
</div>
<form onSubmit={handleSubmit} className="glass rounded-3xl p-10 space-y-5">
<h2 className="text-xl font-bold">Entrar</h2>
<div>
<label className="block text-sm text-gray-400 mb-2">Email</label>
<input type="email" value={email} onChange={e => setEmail(e.target.value)} required
className="w-full px-4 py-3.5 rounded-xl bg-dark border border-dark-border text-white placeholder-gray-600 focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/30 transition"
placeholder="seu@email.com" />
</div>
<div>
<label className="block text-sm text-gray-400 mb-2">Senha</label>
<input type="password" value={password} onChange={e => setPassword(e.target.value)} required
className="w-full px-4 py-3.5 rounded-xl bg-dark border border-dark-border text-white placeholder-gray-600 focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/30 transition"
placeholder="••••••••" />
</div>
{error && <p className="text-danger text-sm">{error}</p>}
<button type="submit" disabled={loading} className="btn-glow w-full !text-center disabled:opacity-50">
{loading ? 'Entrando...' : 'Entrar →'}
</button>
<p className="text-center text-gray-500 text-sm">
Não tem conta? <Link href="/register" className="text-primary hover:underline">Criar conta grátis</Link>
</p>
</form>
</div>
</div>
);
}