eletrotupi / tcc/ commit / 13a51f6

frontend: let translateError take unknown and drop the any catches

Pedro Lucas Porcellis porcellis@eletrotupi.com · 12 days ago 13a51f682d4b5fcaa5c7daa8c766d0d8738d29da Browse files
Parents bee79a3
Changed 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
}