modo-claro

modified:   src/hooks/useAgenda.js
modified:   src/index.css
modified:   src/main.jsx
modified:   src/mappers/reportMapper.js
modified:   src/pages/AgendaPage.jsx
modified:   src/pages/AuthPages.jsx
modified:   src/pages/MedicalRecordsPage.jsx
modified:   src/pages/PatientsPage.jsx
modified:   src/pages/ReportsPage.jsx
modified:   src/pages/SettingsPage.jsx
modified:   src/repositories/analyticsRepository.js
modified:   src/repositories/authRepository.js
modified:   src/repositories/patientRepository.js
modified:   src/repositories/reportRepository.js
modified:   src/repositories/repositoryUtils.js
new file:   src/utils/theme.js
new file:   vercel.json
This commit is contained in:
2026-05-07 05:51:07 -03:00
parent 64d9527318
commit db7a2fe8f5
17 changed files with 669 additions and 121 deletions

View File

@@ -23,7 +23,7 @@ export async function fetchJsonWithFallback(requests, fallbackMessage) {
}
if (lastError && !lastResponse) {
throw new Error(lastError.message || fallbackMessage)
throw new Error(translateErrorMessage(lastError.message || fallbackMessage))
}
throw new Error(await getResponseError(lastResponse, fallbackMessage))
@@ -54,7 +54,7 @@ export async function getResponseError(response, fallbackMessage) {
const text = await response.text().catch(() => '')
const error = parseErrorBody(text)
const message =
const message = translateErrorMessage(
error.error_description ||
error.msg ||
error.message ||
@@ -62,11 +62,50 @@ export async function getResponseError(response, fallbackMessage) {
error.details ||
error.hint ||
text ||
fallbackMessage
fallbackMessage,
)
return response.status ? `${fallbackMessage} (${response.status}): ${message}` : message
}
export function translateErrorMessage(message) {
const rawMessage = String(message || '').trim()
const normalized = rawMessage.toLowerCase()
if (!rawMessage) return 'Erro inesperado.'
if (isPortugueseMessage(rawMessage)) return rawMessage
const translations = [
[/failed to fetch|networkerror|load failed|network request failed/, 'Não foi possível conectar ao servidor. Verifique sua conexão e tente novamente.'],
[/invalid login credentials|invalid credentials/, 'E-mail ou senha inválidos.'],
[/email not confirmed/, 'E-mail ainda não confirmado. Verifique sua caixa de entrada.'],
[/user already registered|already registered/, 'Este e-mail já está cadastrado.'],
[/user not found/, 'Usuário não encontrado.'],
[/jwt expired|invalid jwt|jwt malformed|invalid token|token is expired/, 'Sessão expirada. Faça login novamente.'],
[/missing required parameters?/, 'Parâmetros obrigatórios não foram enviados.'],
[/duplicate key value violates unique constraint/, 'Já existe um registro com essas informações.'],
[/new row violates row-level security policy|row-level security policy|permission denied/, 'Você não tem permissão para realizar esta ação.'],
[/violates foreign key constraint/, 'Não foi possível salvar porque há um vínculo obrigatório ausente ou inválido.'],
[/null value in column "([^"]+)".*violates not-null constraint/, 'Campo obrigatório não preenchido.'],
[/invalid input value for enum ([^:]+): "([^"]+)"/, 'Valor inválido para uma opção do sistema.'],
[/invalid input syntax for type uuid/, 'Identificador inválido enviado para a API.'],
[/relation .* does not exist/, 'Recurso da API não encontrado.'],
[/function .* does not exist/, 'Endpoint da API não encontrado.'],
[/cors|preflight/, 'A API bloqueou a requisição por configuração de CORS.'],
]
for (const [pattern, translation] of translations) {
if (pattern.test(normalized)) return translation
}
return rawMessage
}
function isPortugueseMessage(message) {
return /[ãõáéíóúâêôç]/i.test(message) ||
/\b(erro|falha|não|nao|usuário|usuario|senha|campo|obrigatório|obrigatorio|sessão|sessao)\b/i.test(message)
}
function shouldFallback(response) {
return [404, 405].includes(response.status)
}