feat(frontend): improve login error handling and user avatar

- Implemented more specific error messages for the login page, distinguishing between invalid credentials and server errors.
- Updated i18n files with new translations for login error messages.
- Improved the avatar fallback to use the user's email initials if their name is not available.
- Removed frontend-source.tar.gz from tracking.
- Chore: Added debug logs to the seeder-api location loader.
This commit is contained in:
Yamamoto 2026-01-03 18:28:12 -03:00
parent e59e15dd35
commit 08efbe4f2b
8 changed files with 32 additions and 12 deletions

Binary file not shown.

View file

@ -83,7 +83,15 @@ export default function LoginPage() {
} catch (err: any) { } catch (err: any) {
console.error('🔥 [LOGIN FRONT] Erro no login:', err); console.error('🔥 [LOGIN FRONT] Erro no login:', err);
console.error('🔥 [LOGIN FRONT] Detalhes:', err.response?.data || err.message); console.error('🔥 [LOGIN FRONT] Detalhes:', err.response?.data || err.message);
setError(err.message || t("auth.login.errors.generic"));
const errorMessage = err.message;
if (errorMessage === "AUTH_INVALID_CREDENTIALS") {
setError(t("auth.login.errors.invalidCredentials"));
} else if (errorMessage === "AUTH_SERVER_ERROR") {
setError(t("auth.login.errors.serverError"));
} else {
setError(t("auth.login.errors.generic"));
}
} finally { } finally {
setLoading(false); setLoading(false);
} }

View file

@ -69,7 +69,11 @@ export function DashboardHeader() {
alt={user?.name} alt={user?.name}
/> />
<AvatarFallback className="bg-primary/10 text-primary"> <AvatarFallback className="bg-primary/10 text-primary">
{user?.name ? getInitials(user.name) : "U"} {user?.name
? getInitials(user.name)
: user?.email
? getInitials(user.email.split('@')[0])
: "U"}
</AvatarFallback> </AvatarFallback>
</Avatar> </Avatar>
</Button> </Button>

View file

@ -256,7 +256,8 @@
"password": "Password must be at least 3 characters" "password": "Password must be at least 3 characters"
}, },
"errors": { "errors": {
"invalidCredentials": "Invalid username or password.", "invalidCredentials": "Incorrect email or password. Please try again.",
"serverError": "Server error. Please try again later.",
"generic": "Error signing in. Please try again." "generic": "Error signing in. Please try again."
} }
}, },

View file

@ -256,7 +256,8 @@
"password": "La contraseña debe tener al menos 3 caracteres" "password": "La contraseña debe tener al menos 3 caracteres"
}, },
"errors": { "errors": {
"invalidCredentials": "Usuario o contraseña inválidos.", "invalidCredentials": "Correo electrónico o contraseña incorrectos. Por favor inténtalo de nuevo.",
"serverError": "Error del servidor. Por favor inténtalo más tarde.",
"generic": "Error al iniciar sesión. Inténtalo de nuevo." "generic": "Error al iniciar sesión. Inténtalo de nuevo."
} }
}, },

View file

@ -256,7 +256,8 @@
"password": "Senha deve ter pelo menos 3 caracteres" "password": "Senha deve ter pelo menos 3 caracteres"
}, },
"errors": { "errors": {
"invalidCredentials": "Usuário ou senha inválidos.", "invalidCredentials": "E-mail ou senha incorretos. Por favor, tente novamente.",
"serverError": "Erro no servidor. Por favor, tente mais tarde.",
"generic": "Erro ao fazer login. Tente novamente." "generic": "Erro ao fazer login. Tente novamente."
} }
}, },

View file

@ -36,9 +36,9 @@ export async function login(
if (!res.ok) { if (!res.ok) {
if (res.status === 401) { if (res.status === 401) {
throw new Error("Credenciais inválidas"); throw new Error("AUTH_INVALID_CREDENTIALS");
} }
throw new Error("Erro no servidor"); throw new Error("AUTH_SERVER_ERROR");
} }
const data: LoginResponse = await res.json(); const data: LoginResponse = await res.json();
@ -199,7 +199,7 @@ export async function registerCandidate(data: RegisterCandidateData): Promise<vo
if (!res.ok) { if (!res.ok) {
const errorData = await res.json().catch(() => ({})); const errorData = await res.json().catch(() => ({}));
console.error('[registerCandidate] Error response:', res.status, errorData); console.error('[registerCandidate] Error response:', res.status, errorData);
throw new Error(errorData.message || `Erro no registro: ${res.status}`); throw new Error(errorData.message || `Registration failed: ${res.status}`);
} }
const responseData = await res.json().catch(() => ({})); const responseData = await res.json().catch(() => ({}));
@ -246,7 +246,7 @@ export async function registerCompany(data: RegisterCompanyData): Promise<void>
if (!res.ok) { if (!res.ok) {
const errorData = await res.json().catch(() => ({})); const errorData = await res.json().catch(() => ({}));
console.error('[registerCompany] Error response:', res.status, errorData); console.error('[registerCompany] Error response:', res.status, errorData);
throw new Error(errorData.message || `Erro no registro: ${res.status}`); throw new Error(errorData.message || `Registration failed: ${res.status}`);
} }
const responseData = await res.json().catch(() => ({})); const responseData = await res.json().catch(() => ({}));

View file

@ -73,8 +73,9 @@ function transformSubregionsInsert(stmt) {
// To: [id, name, continent_id, translations, created, updated, flag, wiki_data_id] // To: [id, name, continent_id, translations, created, updated, flag, wiki_data_id]
if (values.length >= 8) { if (values.length >= 8) {
const [id, name, translations, region_id, created, updated, flag, wikiDataId] = values; const [id, name, translations, region_id, created, updated, flag, wikiDataId] = values;
console.log(`DEBUG: Subregions reorder: id=${id}, region=${region_id}`);
const reordered = [id, name, region_id, translations, created, updated, flag, wikiDataId]; const reordered = [id, name, region_id, translations, created, updated, flag, wikiDataId];
return `INSERT INTO subregions (id, name, continent_id, translations, created_at, updated_at, flag, wiki_data_id) VALUES (${reordered.join(', ')});`; return `INSERT INTO public.subregions (id, name, continent_id, translations, created_at, updated_at, flag, wiki_data_id) VALUES (${reordered.join(', ')});`;
} }
return stmt; return stmt;
@ -92,7 +93,10 @@ function transformSubregionsInsert(stmt) {
*/ */
function transformCountriesInsert(stmt) { function transformCountriesInsert(stmt) {
const valuesMatch = stmt.match(/VALUES\s*\((.+)\);?$/is); const valuesMatch = stmt.match(/VALUES\s*\((.+)\);?$/is);
if (!valuesMatch) return stmt; if (!valuesMatch) {
console.log('DEBUG: Regex failed for subregions!');
return stmt;
}
const valuesStr = valuesMatch[1]; const valuesStr = valuesMatch[1];
const values = parseValues(valuesStr); const values = parseValues(valuesStr);
@ -313,7 +317,8 @@ async function executeSqlFile(filename, tableName) {
} }
// Apply special transformations for subregions (column reordering) // Apply special transformations for subregions (column reordering)
if (pgStmt.includes('INSERT INTO subregions')) { if (pgStmt.includes('INSERT INTO subregions') || pgStmt.includes('INSERT INTO public.subregions')) {
console.log('DEBUG: Transforming subregions insert...');
pgStmt = transformSubregionsInsert(pgStmt); pgStmt = transformSubregionsInsert(pgStmt);
} }