frontend: let translateError take unknown and drop the any catches
Pedro Lucas Porcellis porcellis@eletrotupi.com · 12 days ago
13a51f682d4b5fcaa5c7daa8c766d0d8738d29da Browse filesParents
bee79a3Changed files
9
Additions
+24
Deletions
-22
frontend/app/auth/activate.tsx
1 1
import React, { useEffect, useRef, useState } from 'react';
2 2
import {
3 3
View,
4 4
StyleSheet,
5 5
ScrollView,
50 50
setLoading(true);
51 51
try {
52 52
await activate(value);
53 53
showToast('Conta ativada com sucesso!', 'success');
54 54
router.replace('/');
55 -
} catch (error: any) {
55 +
} catch (error) {
56 56
setCode('');
57 57
setCodeError(
58 -
translateError(error.message) ||
58 +
translateError(error) ||
59 59
'Código incorreto. Verifique o código e tente novamente.',
60 60
);
61 61
codeInputRef.current?.focus();
62 62
} finally {
63 63
setLoading(false);
180 180
footerText: {
181 181
textAlign: 'center',
182 182
marginBottom: 10,
183 183
},
184 184
});
frontend/app/auth/forgot-password.tsx
1 1
import React, { useState } from 'react';
2 2
import {
3 3
View,
4 4
StyleSheet,
5 5
ScrollView,
49 49
setEmailSent(true);
50 50
// In development, show the reset token
51 51
if (data.token) {
52 52
setResetToken(data.token);
53 53
}
54 -
} catch (error: any) {
55 -
showToast(translateError(error.message) || 'Falha ao enviar link de recuperação', 'error');
54 +
} catch (error) {
55 +
showToast(translateError(error) || 'Falha ao enviar link de recuperação', 'error');
56 56
} finally {
57 57
setLoading(false);
58 58
}
59 59
};
60 60
248 248
},
249 249
footerText: {
250 250
fontSize: 14,
251 251
},
252 252
});
frontend/app/auth/login.tsx
1 1
import React, { useState, useEffect, useRef } from "react";
2 2
import {
3 3
View,
4 4
StyleSheet,
5 5
ScrollView,
96 96
}
97 97
}
98 98
}
99 99
100 100
router.replace("/");
101 -
} catch (error: any) {
101 +
} catch (error) {
102 102
console.log("LOGIN error: ", error);
103 103
if (error instanceof ApiError && error.fields) {
104 104
setErrors(translateFields(error.fields));
105 105
} else {
106 -
showToast(translateError(error.message) || 'Falha ao fazer login', 'error');
106 +
showToast(translateError(error) || 'Falha ao fazer login', 'error');
107 107
}
108 108
} finally {
109 109
setLoading(false);
110 110
}
111 111
};
261 261
},
262 262
footerText: {
263 263
fontSize: 14,
264 264
},
265 265
});
frontend/app/auth/reset-password.tsx
1 1
import React, { useState } from 'react';
2 2
import {
3 3
View,
4 4
StyleSheet,
5 5
ScrollView,
60 60
setLoading(true);
61 61
try {
62 62
await resetPassword(token, password);
63 63
showToast('Senha recuperada com sucesso!', 'success');
64 64
router.replace('/auth/login');
65 -
} catch (error: any) {
66 -
showToast(translateError(error.message) || 'Falha em recuperar a conta', 'error');
65 +
} catch (error) {
66 +
showToast(translateError(error) || 'Falha em recuperar a conta', 'error');
67 67
} finally {
68 68
setLoading(false);
69 69
}
70 70
};
71 71
177 177
},
178 178
footerText: {
179 179
fontSize: 14,
180 180
},
181 181
});
frontend/app/auth/signup.tsx
1 1
import React, { useState } from 'react';
2 2
import {
3 3
View,
4 4
StyleSheet,
5 5
ScrollView,
69 69
70 70
setLoading(true);
71 71
try {
72 72
await signup({ firstName, lastName, email, password });
73 73
router.replace('/');
74 -
} catch (error: any) {
74 +
} catch (error) {
75 75
if (error instanceof ApiError && error.fields) {
76 76
setErrors(translateFields(error.fields));
77 77
} else {
78 -
showToast(translateError(error.message) || 'Falha no cadastro. Tente novamente.', 'error');
78 +
showToast(translateError(error) || 'Falha no cadastro. Tente novamente.', 'error');
79 79
}
80 80
} finally {
81 81
setLoading(false);
82 82
}
83 83
};
215 215
},
216 216
footerText: {
217 217
fontSize: 14,
218 218
},
219 219
});
frontend/app/profile.tsx
1 1
import { useState, useEffect } from 'react';
2 2
import {
3 3
View,
4 4
StyleSheet,
5 5
ScrollView,
81 81
const response = await apiClient.updateUser({
82 82
id,
83 83
firstName,
84 84
lastName,
85 85
email,
86 -
password
86 +
...(password ? { password } : {}),
87 87
});
88 88
89 89
updateAuthUser(response.user);
90 90
91 91
router.replace('/(tabs)/insights');
92 -
} catch (error: any) {
92 +
} catch (error) {
93 93
console.error("[PROFILE]", error)
94 94
if (error instanceof ApiError && error.fields) {
95 95
setErrors(translateFields(error.fields));
96 96
} else {
97 -
showToast(translateError(error.message) || 'Falha ao atualizar o perfil', 'error');
97 +
showToast(translateError(error) || 'Falha ao atualizar o perfil', 'error');
98 98
}
99 99
}
100 100
}
101 101
102 102
const onChangeAvatar = (user: User) => {
249 249
cardBlockHint: {
250 250
...Typography.cardHint,
251 251
color: Colors.light.textSecondary
252 252
}
253 253
});
frontend/app/sleep/new.tsx
1 1
import {
2 2
View,
3 3
StyleSheet,
4 4
KeyboardAvoidingView,
5 5
ScrollView,
34 34
const save = async () => {
35 35
try {
36 36
const data = { date, annotations, average };
37 37
await createSleepRecord.mutateAsync(data);
38 38
router.replace("/");
39 -
} catch (error: any) {
39 +
} catch (error) {
40 40
showToast(
41 -
error instanceof ApiError ? translateError(error.message) : 'Falha ao salvar o registro de sono',
41 +
error instanceof ApiError ? translateError(error) : 'Falha ao salvar o registro de sono',
42 42
'error',
43 43
);
44 44
}
45 45
};
46 46
147 147
},
148 148
keyboardView: {
149 149
flex: 1,
150 150
},
151 151
});
frontend/app/triggers/new.tsx
1 1
import {
2 2
View,
3 3
StyleSheet,
4 4
KeyboardAvoidingView,
5 5
ScrollView,
64 64
});
65 65
router.back();
66 66
} else {
67 67
router.replace("/(tabs)/actions");
68 68
}
69 -
} catch (error: any) {
69 +
} catch (error) {
70 70
showToast(
71 -
error instanceof ApiError ? translateError(error.message) : 'Falha ao salvar o gatilho',
71 +
error instanceof ApiError ? translateError(error) : 'Falha ao salvar o gatilho',
72 72
'error',
73 73
);
74 74
}
75 75
};
76 76
186 186
alignItems: "center",
187 187
justifyContent: "center",
188 188
marginTop: 1,
189 189
},
190 190
});
frontend/lib/errors/translations.ts
1 1
const MESSAGE_MAP: Record<string, string> = {
2 2
'Required': 'Campo obrigatório',
3 3
'Invalid email': 'Email inválido',
4 4
'Invalid email address': 'Email inválido',
5 5
'Invalid credentials': 'Credenciais inválidas',
21 21
[/Invalid enum value/, () => 'Opção inválida'],
22 22
[/Validation error:/, () => 'Erro de validação'],
23 23
[/^HTTP \d+$/, () => 'Algo deu errado. Tente novamente.'],
24 24
];
25 25
26 -
export function translateError(message: string): string {
27 -
if (MESSAGE_MAP[message]) return MESSAGE_MAP[message];
26 +
export function translateError(message: unknown): string {
27 +
const text = message instanceof Error ? message.message : String(message);
28 28
29 -
console.log("Erro foi: ", message)
29 +
if (MESSAGE_MAP[text]) return MESSAGE_MAP[text];
30 +
31 +
console.log("Erro foi: ", text)
30 32
31 33
for (const [pattern, replacement] of PATTERN_MAP) {
32 -
const match = message.match(pattern);
34 +
const match = text.match(pattern);
33 35
if (match) {
34 36
return typeof replacement === 'function' ? replacement(match) : replacement;
35 37
}
36 38
}
37 39
38 -
return message;
40 +
return text;
39 41
}
40 42
41 43
export function translateFields(
42 44
fields: Record<string, string>,
43 45
): Record<string, string> {
44 46
return Object.fromEntries(
45 47
Object.entries(fields).map(([k, v]) => [k, translateError(v)]),
46 48
);
47 49
}