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

+92
View File
@@ -0,0 +1,92 @@
"use client";
import { useState, useEffect, useCallback } from "react";
export interface Server {
serverId: number;
serverName: string;
serverType: "pvp" | "no-pvp" | "retro-pvp" | "hardcore-pvp" | null;
location: "NA" | "SA" | "EU" | "OC" | "BR" | null;
isActive: boolean;
stats: {
totalListings: number;
totalUsers: number;
totalSubscribers: number;
totalTransactions: number;
totalVolume: number;
averageListingPrice: number;
lastActivityAt: Date | null;
};
}
interface UseServersReturn {
servers: Server[];
isLoading: boolean;
error: string | null;
refetch: () => Promise<void>;
}
/**
* Hook para buscar e gerenciar servidores disponíveis
*/
export function useServers(): UseServersReturn {
const [servers, setServers] = useState<Server[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchServers = useCallback(async () => {
// Só buscar no cliente
if (typeof window === "undefined") {
setIsLoading(false);
return;
}
setIsLoading(true);
setError(null);
try {
const response = await fetch("/api/servers", {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
// Verificar se a resposta é JSON
const contentType = response.headers.get("content-type");
if (!contentType || !contentType.includes("application/json")) {
const text = await response.text();
console.error("Resposta não é JSON:", text.substring(0, 200));
setError("Erro: resposta inválida do servidor");
setIsLoading(false);
return;
}
const data = await response.json();
if (data.success) {
setServers(data.servers || []);
} else {
setError(data.error || "Erro ao buscar servidores");
}
} catch (err) {
const errorMessage = err instanceof Error ? err.message : "Erro desconhecido";
setError("Erro ao conectar com o servidor");
console.error("Erro ao buscar servidores:", errorMessage, err);
} finally {
setIsLoading(false);
}
}, []);
useEffect(() => {
fetchServers();
}, [fetchServers]);
return {
servers,
isLoading,
error,
refetch: fetchServers,
};
}
+105
View File
@@ -0,0 +1,105 @@
"use client";
import { useState, useEffect, useCallback } from "react";
export interface SessionUser {
userId: number;
username: string;
email: string;
}
interface SessionState {
user: SessionUser | null;
isLoading: boolean;
isAuthenticated: boolean;
}
/**
* Hook para gerenciar sessão do usuário
*/
export function useSession() {
const [session, setSession] = useState<SessionState>({
user: null,
isLoading: true,
isAuthenticated: false,
});
/**
* Verifica a sessão atual
*/
const checkSession = useCallback(async () => {
try {
const response = await fetch("/api/auth/session", {
method: "GET",
credentials: "include",
});
const data = await response.json();
if (data.success && data.authenticated) {
setSession({
user: data.user,
isLoading: false,
isAuthenticated: true,
});
} else {
setSession({
user: null,
isLoading: false,
isAuthenticated: false,
});
}
} catch (error) {
console.error("Erro ao verificar sessão:", error);
setSession({
user: null,
isLoading: false,
isAuthenticated: false,
});
}
}, []);
/**
* Encerra a sessão
*/
const logout = useCallback(async () => {
try {
await fetch("/api/auth/session", {
method: "DELETE",
credentials: "include",
});
setSession({
user: null,
isLoading: false,
isAuthenticated: false,
});
// Recarregar página para limpar estado
window.location.href = "/";
} catch (error) {
console.error("Erro ao fazer logout:", error);
}
}, []);
/**
* Atualiza a sessão após login
*/
const refreshSession = useCallback(async () => {
await checkSession();
}, [checkSession]);
// Verificar sessão ao montar componente
useEffect(() => {
checkSession();
}, [checkSession]);
return {
user: session.user,
isLoading: session.isLoading,
isAuthenticated: session.isAuthenticated,
logout,
refreshSession,
};
}