feat: add user authentication UI to header component

Add login and register dialogs, user dropdown menu with profile link and logout option, and integrate with session management hook. Prevent hydration mismatches by conditionally rendering auth elements after mount. Update package-lock.json with new @esbuild dependencies for build tooling.
This commit is contained in:
Evandro Fonseca Junior committed 2025-11-04 02:33:29 -03:00
1 parent e641138887
commit 55eebde0ba
55 files changed
+7353 -7

No files matched your search

+119
View File
@@ -0,0 +1,119 @@
"use client";
import { useState } from "react";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useSession } from "@/lib/hooks/use-session";
interface LoginDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
}
export function LoginDialog({ open, onOpenChange }: LoginDialogProps) {
const [emailOrUsername, setEmailOrUsername] = useState("");
const [password, setPassword] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const { refreshSession } = useSession();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setIsLoading(true);
setError(null);
try {
const response = await fetch("/api/auth/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify({
emailOrUsername,
password,
}),
});
const data = await response.json();
if (data.success) {
// Atualizar sessão
await refreshSession();
// Fechar diálogo
onOpenChange(false);
// Limpar formulário
setEmailOrUsername("");
setPassword("");
// Recarregar página para atualizar estado
window.location.reload();
} else {
setError(data.error || "Erro ao fazer login");
}
} catch (err) {
setError("Erro ao conectar com o servidor");
} finally {
setIsLoading(false);
}
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Entrar</DialogTitle>
<DialogDescription>
Faça login para acessar sua conta
</DialogDescription>
</DialogHeader>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="emailOrUsername">Email ou Username</Label>
<Input
id="emailOrUsername"
type="text"
placeholder="[email protected] ou username"
value={emailOrUsername}
onChange={(e) => setEmailOrUsername(e.target.value)}
required
disabled={isLoading}
/>
</div>
<div className="space-y-2">
<Label htmlFor="password">Senha</Label>
<Input
id="password"
type="password"
placeholder="••••••••"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
disabled={isLoading}
/>
</div>
{error && (
<div className="text-sm text-destructive bg-destructive/10 p-3 rounded-md">
{error}
</div>
)}
<Button type="submit" className="w-full" disabled={isLoading}>
{isLoading ? "Entrando..." : "Entrar"}
</Button>
</form>
</DialogContent>
</Dialog>
);
}