@greatapps/common 1.1.675 → 1.1.677

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/dist/components/account/ConfigurationsMyAccountModal.mjs +8 -6
  2. package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -1
  3. package/dist/components/account/ConfirmDeleteAccountModal.mjs +20 -19
  4. package/dist/components/account/ConfirmDeleteAccountModal.mjs.map +1 -1
  5. package/dist/components/account/ConfirmGlobalPreferencesModal.mjs +10 -11
  6. package/dist/components/account/ConfirmGlobalPreferencesModal.mjs.map +1 -1
  7. package/dist/components/account/DeleteAccountModal.mjs +34 -28
  8. package/dist/components/account/DeleteAccountModal.mjs.map +1 -1
  9. package/dist/components/account/DisableTwoFactorAuthModal.mjs +7 -5
  10. package/dist/components/account/DisableTwoFactorAuthModal.mjs.map +1 -1
  11. package/dist/components/account/IsntPossibleDeleteAccountModal.mjs +8 -9
  12. package/dist/components/account/IsntPossibleDeleteAccountModal.mjs.map +1 -1
  13. package/dist/components/account/TwoFactorAuthModal.mjs +22 -23
  14. package/dist/components/account/TwoFactorAuthModal.mjs.map +1 -1
  15. package/dist/components/account/constants.mjs +4 -4
  16. package/dist/components/account/constants.mjs.map +1 -1
  17. package/dist/components/account/hooks/useChangeEmailForm.mjs +5 -3
  18. package/dist/components/account/hooks/useChangeEmailForm.mjs.map +1 -1
  19. package/dist/components/account/hooks/useChangePasswordForm.mjs +26 -3
  20. package/dist/components/account/hooks/useChangePasswordForm.mjs.map +1 -1
  21. package/dist/components/account/hooks/useChangePhoneForm.mjs +18 -9
  22. package/dist/components/account/hooks/useChangePhoneForm.mjs.map +1 -1
  23. package/dist/components/account/hooks/useDisableTwoFactorAuthForm.mjs +26 -3
  24. package/dist/components/account/hooks/useDisableTwoFactorAuthForm.mjs.map +1 -1
  25. package/dist/components/account/hooks/useOtpVerification.mjs +19 -3
  26. package/dist/components/account/hooks/useOtpVerification.mjs.map +1 -1
  27. package/dist/components/account/hooks/useTwoFactorAuthForm.mjs +27 -4
  28. package/dist/components/account/hooks/useTwoFactorAuthForm.mjs.map +1 -1
  29. package/dist/components/account/sections/ChangeEmailModal.mjs +25 -28
  30. package/dist/components/account/sections/ChangeEmailModal.mjs.map +1 -1
  31. package/dist/components/account/sections/ChangePasswordSection.mjs +8 -6
  32. package/dist/components/account/sections/ChangePasswordSection.mjs.map +1 -1
  33. package/dist/components/account/sections/ChangePhoneModal.mjs +24 -27
  34. package/dist/components/account/sections/ChangePhoneModal.mjs.map +1 -1
  35. package/dist/components/account/sections/MyProfileSection.mjs +37 -22
  36. package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
  37. package/dist/components/account/sections/PreferencesSection.mjs +48 -24
  38. package/dist/components/account/sections/PreferencesSection.mjs.map +1 -1
  39. package/dist/components/account/sections/SecuritySection.mjs +11 -9
  40. package/dist/components/account/sections/SecuritySection.mjs.map +1 -1
  41. package/dist/components/account/sections/TokenSection.mjs +24 -8
  42. package/dist/components/account/sections/TokenSection.mjs.map +1 -1
  43. package/dist/components/layouts/AppMobileNavBar.mjs +2 -148
  44. package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
  45. package/dist/components/layouts/NavBar.mjs +5 -3
  46. package/dist/components/layouts/NavBar.mjs.map +1 -1
  47. package/dist/components/layouts/NotificationsPopover.mjs +5 -3
  48. package/dist/components/layouts/NotificationsPopover.mjs.map +1 -1
  49. package/dist/components/layouts/ProfilePopover.mjs +6 -4
  50. package/dist/components/layouts/ProfilePopover.mjs.map +1 -1
  51. package/dist/components/layouts/UsersSelectorPopover.mjs +9 -7
  52. package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
  53. package/dist/components/modals/BuyCreditsModal.mjs +17 -18
  54. package/dist/components/modals/BuyCreditsModal.mjs.map +1 -1
  55. package/dist/components/modals/CreditsDisabledModal.mjs +6 -4
  56. package/dist/components/modals/CreditsDisabledModal.mjs.map +1 -1
  57. package/dist/components/modals/PaidPlanRequiredModal.mjs +5 -3
  58. package/dist/components/modals/PaidPlanRequiredModal.mjs.map +1 -1
  59. package/dist/components/modals/cards/AddCardModal.mjs +64 -46
  60. package/dist/components/modals/cards/AddCardModal.mjs.map +1 -1
  61. package/dist/components/modals/cards/CannotDeleteCardModal.mjs +9 -7
  62. package/dist/components/modals/cards/CannotDeleteCardModal.mjs.map +1 -1
  63. package/dist/components/modals/cards/CardFormFields.mjs +65 -51
  64. package/dist/components/modals/cards/CardFormFields.mjs.map +1 -1
  65. package/dist/components/modals/cards/DeleteCardModal.mjs +10 -8
  66. package/dist/components/modals/cards/DeleteCardModal.mjs.map +1 -1
  67. package/dist/components/navigation/CancelledSubscriptionBanner.mjs +4 -2
  68. package/dist/components/navigation/CancelledSubscriptionBanner.mjs.map +1 -1
  69. package/dist/components/navigation/OverdueInvoiceBanner.mjs +4 -2
  70. package/dist/components/navigation/OverdueInvoiceBanner.mjs.map +1 -1
  71. package/dist/components/navigation/PendingCancellationBanner.mjs +4 -6
  72. package/dist/components/navigation/PendingCancellationBanner.mjs.map +1 -1
  73. package/dist/components/navigation/ProjectSelectorPopover.mjs +8 -6
  74. package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
  75. package/dist/components/navigation/UpcomingInvoiceBanner.mjs +4 -6
  76. package/dist/components/navigation/UpcomingInvoiceBanner.mjs.map +1 -1
  77. package/dist/components/navigation/subcomponents/BottomLinks.mjs +5 -3
  78. package/dist/components/navigation/subcomponents/BottomLinks.mjs.map +1 -1
  79. package/dist/components/navigation/subcomponents/CreditsCard.mjs +3 -1
  80. package/dist/components/navigation/subcomponents/CreditsCard.mjs.map +1 -1
  81. package/dist/components/navigation/subcomponents/PlanCard.mjs +3 -1
  82. package/dist/components/navigation/subcomponents/PlanCard.mjs.map +1 -1
  83. package/dist/components/navigation/subcomponents/ProjectSelector.mjs +5 -3
  84. package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
  85. package/dist/components/pages/NotFoundPage.mjs +5 -3
  86. package/dist/components/pages/NotFoundPage.mjs.map +1 -1
  87. package/dist/components/pages/notifications/Notifications.mjs +13 -10
  88. package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
  89. package/dist/components/ui/buttons/CopyButton.mjs +9 -5
  90. package/dist/components/ui/buttons/CopyButton.mjs.map +1 -1
  91. package/dist/components/ui/data-display/CardItem.mjs +7 -5
  92. package/dist/components/ui/data-display/CardItem.mjs.map +1 -1
  93. package/dist/components/ui/data-display/PaymentInfoCard.mjs +10 -8
  94. package/dist/components/ui/data-display/PaymentInfoCard.mjs.map +1 -1
  95. package/dist/components/ui/feedback/CircularProgress.mjs.map +1 -1
  96. package/dist/components/ui/feedback/DefaultCircularProgress.mjs +3 -1
  97. package/dist/components/ui/feedback/DefaultCircularProgress.mjs.map +1 -1
  98. package/dist/components/ui/form/ComboboxField.mjs +11 -6
  99. package/dist/components/ui/form/ComboboxField.mjs.map +1 -1
  100. package/dist/components/ui/form/DatePicker.mjs +5 -2
  101. package/dist/components/ui/form/DatePicker.mjs.map +1 -1
  102. package/dist/components/ui/form/DateRangePicker.mjs +5 -2
  103. package/dist/components/ui/form/DateRangePicker.mjs.map +1 -1
  104. package/dist/components/ui/form/PhoneInput.mjs +5 -3
  105. package/dist/components/ui/form/PhoneInput.mjs.map +1 -1
  106. package/dist/components/ui/form/SelectField.mjs +6 -3
  107. package/dist/components/ui/form/SelectField.mjs.map +1 -1
  108. package/dist/components/widgets/ImageUpload/ImageCropModal.mjs +11 -18
  109. package/dist/components/widgets/ImageUpload/ImageCropModal.mjs.map +1 -1
  110. package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs +6 -15
  111. package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs.map +1 -1
  112. package/dist/i18n/config.mjs +13 -0
  113. package/dist/i18n/config.mjs.map +1 -0
  114. package/dist/i18n/country-language.mjs +74 -0
  115. package/dist/i18n/country-language.mjs.map +1 -0
  116. package/dist/i18n/messages/en-us.mjs +494 -0
  117. package/dist/i18n/messages/en-us.mjs.map +1 -0
  118. package/dist/i18n/messages/es-es.mjs +494 -0
  119. package/dist/i18n/messages/es-es.mjs.map +1 -0
  120. package/dist/i18n/messages/index.mjs +16 -0
  121. package/dist/i18n/messages/index.mjs.map +1 -0
  122. package/dist/i18n/messages/pt-br.mjs +507 -0
  123. package/dist/i18n/messages/pt-br.mjs.map +1 -0
  124. package/dist/i18n/normalize.mjs +12 -0
  125. package/dist/i18n/normalize.mjs.map +1 -0
  126. package/dist/i18n/resolve-locale.mjs +42 -0
  127. package/dist/i18n/resolve-locale.mjs.map +1 -0
  128. package/dist/i18n.mjs +14 -0
  129. package/dist/i18n.mjs.map +1 -0
  130. package/dist/index.mjs +19 -3
  131. package/dist/index.mjs.map +1 -1
  132. package/dist/modules/accounts/hooks/use-currency-formatter.hook.mjs +20 -0
  133. package/dist/modules/accounts/hooks/use-currency-formatter.hook.mjs.map +1 -0
  134. package/dist/modules/cards/hooks/handle-delete-card.hook.mjs +2 -1
  135. package/dist/modules/cards/hooks/handle-delete-card.hook.mjs.map +1 -1
  136. package/dist/modules/images/utils/validate-image.mjs +8 -8
  137. package/dist/modules/images/utils/validate-image.mjs.map +1 -1
  138. package/dist/modules/plans/hooks/list-plans.hook.mjs +2 -2
  139. package/dist/modules/plans/hooks/list-plans.hook.mjs.map +1 -1
  140. package/dist/modules/plans/types/plan.type.mjs +5 -1
  141. package/dist/modules/plans/types/plan.type.mjs.map +1 -1
  142. package/dist/modules/plans/utils/map-api-plan-to-ui.mjs +61 -35
  143. package/dist/modules/plans/utils/map-api-plan-to-ui.mjs.map +1 -1
  144. package/dist/modules/projects/services/projects.service.mjs +9 -0
  145. package/dist/modules/projects/services/projects.service.mjs.map +1 -1
  146. package/dist/modules/subscriptions/utils/periodicity.mjs +20 -14
  147. package/dist/modules/subscriptions/utils/periodicity.mjs.map +1 -1
  148. package/dist/providers/auth.provider.mjs +9 -1
  149. package/dist/providers/auth.provider.mjs.map +1 -1
  150. package/dist/server.mjs +2 -0
  151. package/dist/server.mjs.map +1 -1
  152. package/dist/utils/format/currency.mjs +32 -4
  153. package/dist/utils/format/currency.mjs.map +1 -1
  154. package/dist/utils/intl/cookie-domain.mjs +17 -0
  155. package/dist/utils/intl/cookie-domain.mjs.map +1 -0
  156. package/dist/utils/intl/locale-cookie.mjs +13 -0
  157. package/dist/utils/intl/locale-cookie.mjs.map +1 -0
  158. package/dist/utils/intl/locales.mjs +3 -2
  159. package/dist/utils/intl/locales.mjs.map +1 -1
  160. package/package.json +7 -1
  161. package/src/components/account/ConfigurationsMyAccountModal.tsx +10 -6
  162. package/src/components/account/ConfirmDeleteAccountModal.tsx +22 -13
  163. package/src/components/account/ConfirmGlobalPreferencesModal.tsx +12 -10
  164. package/src/components/account/DeleteAccountModal.tsx +34 -24
  165. package/src/components/account/DisableTwoFactorAuthModal.tsx +11 -6
  166. package/src/components/account/IsntPossibleDeleteAccountModal.tsx +8 -6
  167. package/src/components/account/TwoFactorAuthModal.tsx +33 -29
  168. package/src/components/account/constants.ts +8 -5
  169. package/src/components/account/hooks/useChangeEmailForm.tsx +5 -3
  170. package/src/components/account/hooks/useChangePasswordForm.tsx +20 -6
  171. package/src/components/account/hooks/useChangePhoneForm.tsx +16 -10
  172. package/src/components/account/hooks/useDisableTwoFactorAuthForm.tsx +20 -6
  173. package/src/components/account/hooks/useOtpVerification.tsx +16 -4
  174. package/src/components/account/hooks/useTwoFactorAuthForm.tsx +21 -7
  175. package/src/components/account/sections/ChangeEmailModal.tsx +35 -21
  176. package/src/components/account/sections/ChangePasswordSection.tsx +10 -6
  177. package/src/components/account/sections/ChangePhoneModal.tsx +50 -22
  178. package/src/components/account/sections/MyProfileSection.tsx +37 -23
  179. package/src/components/account/sections/PreferencesSection.tsx +52 -25
  180. package/src/components/account/sections/SecuritySection.tsx +19 -10
  181. package/src/components/account/sections/TokenSection.tsx +22 -10
  182. package/src/components/layouts/AppMobileNavBar.tsx +1 -154
  183. package/src/components/layouts/NavBar.tsx +5 -3
  184. package/src/components/layouts/NotificationsPopover.tsx +5 -3
  185. package/src/components/layouts/ProfilePopover.tsx +6 -4
  186. package/src/components/layouts/UsersSelectorPopover.tsx +9 -7
  187. package/src/components/modals/BuyCreditsModal.tsx +18 -16
  188. package/src/components/modals/CreditsDisabledModal.tsx +6 -6
  189. package/src/components/modals/PaidPlanRequiredModal.tsx +5 -3
  190. package/src/components/modals/cards/AddCardModal.tsx +89 -62
  191. package/src/components/modals/cards/CannotDeleteCardModal.tsx +9 -8
  192. package/src/components/modals/cards/CardFormFields.tsx +93 -75
  193. package/src/components/modals/cards/DeleteCardModal.tsx +10 -8
  194. package/src/components/navigation/CancelledSubscriptionBanner.tsx +4 -2
  195. package/src/components/navigation/OverdueInvoiceBanner.tsx +4 -2
  196. package/src/components/navigation/PendingCancellationBanner.tsx +4 -2
  197. package/src/components/navigation/ProjectSelectorPopover.tsx +8 -6
  198. package/src/components/navigation/UpcomingInvoiceBanner.tsx +4 -2
  199. package/src/components/navigation/subcomponents/BottomLinks.tsx +5 -3
  200. package/src/components/navigation/subcomponents/CreditsCard.tsx +3 -1
  201. package/src/components/navigation/subcomponents/PlanCard.tsx +3 -1
  202. package/src/components/navigation/subcomponents/ProjectSelector.tsx +5 -3
  203. package/src/components/pages/NotFoundPage.tsx +5 -3
  204. package/src/components/pages/notifications/Notifications.tsx +13 -10
  205. package/src/components/ui/buttons/CopyButton.tsx +10 -5
  206. package/src/components/ui/data-display/CardItem.tsx +7 -5
  207. package/src/components/ui/data-display/PaymentInfoCard.tsx +10 -8
  208. package/src/components/ui/feedback/CircularProgress.tsx +4 -0
  209. package/src/components/ui/feedback/DefaultCircularProgress.tsx +3 -1
  210. package/src/components/ui/form/ComboboxField.tsx +11 -6
  211. package/src/components/ui/form/DatePicker.tsx +5 -2
  212. package/src/components/ui/form/DateRangePicker.tsx +5 -2
  213. package/src/components/ui/form/PhoneInput.tsx +5 -3
  214. package/src/components/ui/form/SelectField.tsx +6 -3
  215. package/src/components/widgets/ImageUpload/ImageCropModal.tsx +19 -11
  216. package/src/components/widgets/ImageUpload/ImageTooSmallModal.tsx +6 -5
  217. package/src/i18n/config.ts +17 -0
  218. package/src/i18n/country-language.ts +60 -0
  219. package/src/i18n/messages/en-us.ts +514 -0
  220. package/src/i18n/messages/es-es.ts +515 -0
  221. package/src/i18n/messages/index.ts +24 -0
  222. package/src/i18n/messages/pt-br.ts +538 -0
  223. package/src/i18n/normalize.ts +15 -0
  224. package/src/i18n/resolve-locale.ts +77 -0
  225. package/src/i18n.ts +10 -0
  226. package/src/index.ts +13 -2
  227. package/src/modules/accounts/hooks/use-currency-formatter.hook.tsx +32 -0
  228. package/src/modules/cards/hooks/handle-delete-card.hook.ts +8 -3
  229. package/src/modules/images/utils/validate-image.ts +23 -8
  230. package/src/modules/plans/hooks/list-plans.hook.ts +2 -2
  231. package/src/modules/plans/types/plan.type.ts +4 -0
  232. package/src/modules/plans/utils/map-api-plan-to-ui.ts +109 -47
  233. package/src/modules/projects/services/projects.service.ts +12 -0
  234. package/src/modules/subscriptions/utils/periodicity.ts +29 -12
  235. package/src/providers/auth.provider.tsx +13 -1
  236. package/src/server.ts +2 -0
  237. package/src/utils/format/currency.ts +62 -7
  238. package/src/utils/intl/cookie-domain.ts +29 -0
  239. package/src/utils/intl/locale-cookie.ts +18 -0
  240. package/src/utils/intl/locales.ts +3 -2
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useState, useCallback } from 'react';
4
+ import { useTranslations } from 'next-intl';
4
5
  import { toast } from 'sonner';
5
6
  import { Toast } from '../../ui/feedback/Toast';
6
7
  import { requestPhoneChangeAction, updateUserAction } from '../../../modules/accounts/actions/account-management.action';
@@ -18,6 +19,7 @@ interface UseChangePhoneFormOptions {
18
19
  }
19
20
 
20
21
  export default function useChangePhoneForm({ hasExistingPhone, onDirectUpdateSuccess }: UseChangePhoneFormOptions) {
22
+ const translate = useTranslations();
21
23
  const [showVerification, setShowVerification] = useState(false);
22
24
  const [phoneValue, setPhoneValue] = useState('');
23
25
  const [phoneError, setPhoneError] = useState('');
@@ -35,7 +37,7 @@ export default function useChangePhoneForm({ hasExistingPhone, onDirectUpdateSuc
35
37
  const { ddi, local } = splitPhoneValue(phoneValue);
36
38
 
37
39
  if (!local || local.replace(/\D/g, '').length < 8) {
38
- setPhoneError('Número de telefone inválido');
40
+ setPhoneError(translate('common.account.changePhone.invalidNumber'));
39
41
  return;
40
42
  }
41
43
 
@@ -45,18 +47,22 @@ export default function useChangePhoneForm({ hasExistingPhone, onDirectUpdateSuc
45
47
  const result = await updateUserAction({ phone: local, ddi });
46
48
 
47
49
  if (!result.success) {
48
- toast.custom((t) => (
50
+ toast.custom((toastId) => (
49
51
  <Toast
50
52
  variant="error"
51
- message={result.error ?? 'Ocorreu um erro ao salvar o telefone. Tente novamente mais tarde.'}
52
- toastId={t}
53
+ message={result.error ?? translate('common.account.changePhone.saveError')}
54
+ toastId={toastId}
53
55
  />
54
56
  ));
55
57
  return;
56
58
  }
57
59
 
58
- toast.custom((t) => (
59
- <Toast variant="success" message="Telefone adicionado" toastId={t} />
60
+ toast.custom((toastId) => (
61
+ <Toast
62
+ variant="success"
63
+ message={translate('common.account.changePhone.phoneAdded')}
64
+ toastId={toastId}
65
+ />
60
66
  ));
61
67
  onDirectUpdateSuccess?.();
62
68
  return;
@@ -65,11 +71,11 @@ export default function useChangePhoneForm({ hasExistingPhone, onDirectUpdateSuc
65
71
  const result = await requestPhoneChangeAction(local, ddi);
66
72
 
67
73
  if (!result.success) {
68
- toast.custom((t) => (
74
+ toast.custom((toastId) => (
69
75
  <Toast
70
76
  variant="error"
71
- message={result.error ?? 'Número já existente ou ocorreu um erro. Tente novamente mais tarde.'}
72
- toastId={t}
77
+ message={result.error ?? translate('common.account.changePhone.numberExistsError')}
78
+ toastId={toastId}
73
79
  />
74
80
  ));
75
81
  return;
@@ -80,7 +86,7 @@ export default function useChangePhoneForm({ hasExistingPhone, onDirectUpdateSuc
80
86
  } finally {
81
87
  setIsSubmitting(false);
82
88
  }
83
- }, [phoneValue, hasExistingPhone, onDirectUpdateSuccess]);
89
+ }, [phoneValue, hasExistingPhone, onDirectUpdateSuccess, translate]);
84
90
 
85
91
  const handleBack = useCallback(() => {
86
92
  setShowVerification(false);
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { useState, useCallback } from 'react';
4
4
  import { useMutation, useQueryClient } from '@tanstack/react-query';
5
+ import { useTranslations } from 'next-intl';
5
6
  import { toast } from 'sonner';
6
7
  import { Toast } from '../../ui/feedback/Toast';
7
8
  import { USER_QUERY_KEY } from '../../../modules/auth/hooks/useUserQuery';
@@ -17,6 +18,7 @@ export default function useDisableTwoFactorAuthForm({
17
18
  onClose,
18
19
  onSuccess,
19
20
  }: UseDisableTwoFactorAuthFormProps) {
21
+ const translate = useTranslations();
20
22
  const [code, setCode] = useState('');
21
23
  const queryClient = useQueryClient();
22
24
  const userKey = useWlQueryKey([...USER_QUERY_KEY]);
@@ -28,23 +30,35 @@ export default function useDisableTwoFactorAuthForm({
28
30
  onSuccess: (result) => {
29
31
  if (!result.success) {
30
32
  setCode('');
31
- toast.custom((t) => (
32
- <Toast variant="error" message={result.error ?? 'Código inválido'} toastId={t} />
33
+ toast.custom((toastId) => (
34
+ <Toast
35
+ variant="error"
36
+ message={result.error ?? translate('common.account.twoFactor.invalidCode')}
37
+ toastId={toastId}
38
+ />
33
39
  ));
34
40
  return;
35
41
  }
36
42
 
37
43
  queryClient.invalidateQueries({ queryKey: userKey });
38
- toast.custom((t) => (
39
- <Toast variant="success" message="Autenticação de dois fatores desabilitada" toastId={t} />
44
+ toast.custom((toastId) => (
45
+ <Toast
46
+ variant="success"
47
+ message={translate('common.account.twoFactor.disabledSuccess')}
48
+ toastId={toastId}
49
+ />
40
50
  ));
41
51
  setCode('');
42
52
  onSuccess?.();
43
53
  },
44
54
  onError: () => {
45
55
  setCode('');
46
- toast.custom((t) => (
47
- <Toast variant="error" message="Erro ao desabilitar 2FA. Tente novamente." toastId={t} />
56
+ toast.custom((toastId) => (
57
+ <Toast
58
+ variant="error"
59
+ message={translate('common.account.twoFactor.disableError')}
60
+ toastId={toastId}
61
+ />
48
62
  ));
49
63
  },
50
64
  });
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useState, useCallback } from 'react';
4
+ import { useTranslations } from 'next-intl';
4
5
  import { toast } from 'sonner';
5
6
  import { Toast } from '../../ui/feedback/Toast';
6
7
  import useCountdownTimer from '../../../hooks/useCountdownTimer';
@@ -20,6 +21,7 @@ export default function useOtpVerification({
20
21
  validateFn,
21
22
  resendFn,
22
23
  }: UseOtpVerificationOptions) {
24
+ const translate = useTranslations();
23
25
  const [code, setCode] = useState('');
24
26
  const [isLoading, setIsLoading] = useState(false);
25
27
  const [hasError, setHasError] = useState(false);
@@ -85,14 +87,24 @@ export default function useOtpVerification({
85
87
  await resendFn();
86
88
  }
87
89
 
88
- toast.custom((t) => <Toast variant="success" message="Código reenviado" toastId={t} />);
90
+ toast.custom((toastId) => (
91
+ <Toast
92
+ variant="success"
93
+ message={translate('common.account.twoFactor.codeResent')}
94
+ toastId={toastId}
95
+ />
96
+ ));
89
97
  } catch (error) {
90
98
  console.error('Erro ao reenviar código:', error);
91
- toast.custom((t) => (
92
- <Toast variant="error" message="Erro ao reenviar código. Tente novamente." toastId={t} />
99
+ toast.custom((toastId) => (
100
+ <Toast
101
+ variant="error"
102
+ message={translate('common.account.twoFactor.resendError')}
103
+ toastId={toastId}
104
+ />
93
105
  ));
94
106
  }
95
- }, [canResend, resetTimer, resendFn]);
107
+ }, [canResend, resetTimer, resendFn, translate]);
96
108
 
97
109
  const reset = useCallback(() => {
98
110
  setCode('');
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { useState, useCallback, useEffect } from 'react';
4
4
  import { useMutation } from '@tanstack/react-query';
5
+ import { useTranslations } from 'next-intl';
5
6
  import { toast } from 'sonner';
6
7
  import { Toast } from '../../ui/feedback/Toast';
7
8
  import { copyToClipboard } from '../../../utils/browser/clipboard';
@@ -19,14 +20,19 @@ interface UseTwoFactorAuthFormProps {
19
20
  }
20
21
 
21
22
  export default function useTwoFactorAuthForm({ onSuccess, open }: UseTwoFactorAuthFormProps = {}) {
23
+ const translate = useTranslations();
22
24
  const [code, setCode] = useState('');
23
25
  const [step, setStep] = useState<Step>('code');
24
26
 
25
27
  const generateMutation = useMutation({
26
28
  mutationFn: withAction(generateTwoFactorAction),
27
29
  onError: () => {
28
- toast.custom((t) => (
29
- <Toast variant="error" message="Erro ao gerar QR Code. Tente novamente." toastId={t} />
30
+ toast.custom((toastId) => (
31
+ <Toast
32
+ variant="error"
33
+ message={translate('common.account.twoFactor.generateError')}
34
+ toastId={toastId}
35
+ />
30
36
  ));
31
37
  },
32
38
  });
@@ -38,8 +44,12 @@ export default function useTwoFactorAuthForm({ onSuccess, open }: UseTwoFactorAu
38
44
  },
39
45
  onError: () => {
40
46
  setCode('');
41
- toast.custom((t) => (
42
- <Toast variant="error" message="Erro ao confirmar código. Tente novamente." toastId={t} />
47
+ toast.custom((toastId) => (
48
+ <Toast
49
+ variant="error"
50
+ message={translate('common.account.twoFactor.confirmError')}
51
+ toastId={toastId}
52
+ />
43
53
  ));
44
54
  },
45
55
  });
@@ -70,11 +80,15 @@ export default function useTwoFactorAuthForm({ onSuccess, open }: UseTwoFactorAu
70
80
  const codes = generateMutation.data?.backupCodes ?? [];
71
81
  const success = await copyToClipboard(codes.join('\n'));
72
82
  if (success) {
73
- toast.custom((t) => (
74
- <Toast variant="success" message="Códigos copiados com sucesso" toastId={t} />
83
+ toast.custom((toastId) => (
84
+ <Toast
85
+ variant="success"
86
+ message={translate('common.account.twoFactor.codesCopied')}
87
+ toastId={toastId}
88
+ />
75
89
  ));
76
90
  }
77
- }, [generateMutation.data]);
91
+ }, [generateMutation.data, translate]);
78
92
 
79
93
  const resetForm = () => {
80
94
  setCode('');
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { useTranslations } from 'next-intl';
3
4
  import { IconChevronLeft, IconX, IconMail } from '@tabler/icons-react';
4
5
  import { Button } from '../../ui/buttons/Button';
5
6
  import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';
@@ -20,6 +21,7 @@ interface ChangeEmailModalProps {
20
21
  }
21
22
 
22
23
  export function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {
24
+ const translate = useTranslations();
23
25
  const { user } = useAuth();
24
26
  const invalidateUser = useInvalidateUser();
25
27
 
@@ -53,7 +55,7 @@ export function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {
53
55
  reset: resetOtp,
54
56
  } = useOtpVerification({
55
57
  onSuccess: handleSuccess,
56
- successMessage: 'E-mail alterado com sucesso',
58
+ successMessage: translate('common.account.changeEmail.emailChanged'),
57
59
  validateFn: async (token) => {
58
60
  const result = await confirmEmailChangeAction(token, emailToVerify);
59
61
  return result.success;
@@ -91,7 +93,7 @@ export function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {
91
93
  <IconChevronLeft size={20} className="text-gray-950" />
92
94
  </Button>
93
95
  <DialogTitle className="paragraph-medium-semibold text-gray-950 text-center flex-1">
94
- Alterar e-mail
96
+ {translate('common.account.changeEmail.title')}
95
97
  </DialogTitle>
96
98
  <Button variant="ghost" className="size-8! p-0" onClick={handleClose}>
97
99
  <IconX size={18} className="text-gray-500" />
@@ -100,11 +102,11 @@ export function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {
100
102
  ) : (
101
103
  <>
102
104
  <DialogHeader className="sr-only">
103
- <DialogTitle>Alterar e-mail</DialogTitle>
105
+ <DialogTitle>{translate('common.account.changeEmail.title')}</DialogTitle>
104
106
  </DialogHeader>
105
107
  <div className="flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0">
106
108
  <span className="paragraph-medium-semibold text-gray-950 text-center">
107
- Alterar e-mail
109
+ {translate('common.account.changeEmail.title')}
108
110
  </span>
109
111
  <Button
110
112
  variant="ghost"
@@ -133,10 +135,16 @@ export function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {
133
135
  </div>
134
136
 
135
137
  <div className="flex flex-col gap-1">
136
- <h3 className="paragraph-medium-semibold text-gray-950">Código de validação</h3>
138
+ <h3 className="paragraph-medium-semibold text-gray-950">
139
+ {translate('common.account.otp.validationCode')}
140
+ </h3>
137
141
  <p className="paragraph-small-regular text-gray-600">
138
- Enviamos um código de validação para o E-mail{' '}
139
- <span className="font-semibold text-gray-950 break-all">{user?.email}.</span>
142
+ {translate.rich('common.account.changeEmail.sentCodeTo', {
143
+ email: user?.email ?? '',
144
+ b: (chunks) => (
145
+ <span className="font-semibold text-gray-950 break-all">{chunks}</span>
146
+ ),
147
+ })}
140
148
  </p>
141
149
  </div>
142
150
 
@@ -153,7 +161,9 @@ export function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {
153
161
  </InputOTPGroup>
154
162
  </InputOTP>
155
163
  {hasError && (
156
- <p className="paragraph-small-regular text-red-500">Código incorreto</p>
164
+ <p className="paragraph-small-regular text-red-500">
165
+ {translate('common.account.otp.incorrectCode')}
166
+ </p>
157
167
  )}
158
168
  </div>
159
169
 
@@ -163,14 +173,16 @@ export function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {
163
173
  onClick={handleResend}
164
174
  className="paragraph-small-medium text-gray-950 underline cursor-pointer hover:text-gray-700 w-fit"
165
175
  >
166
- Reenviar código
176
+ {translate('common.account.otp.resend')}
167
177
  </button>
168
178
  ) : (
169
179
  <p className="paragraph-small-regular text-gray-500">
170
- Reenviar em{' '}
171
- <span className="paragraph-small-semibold text-gray-950">
172
- {formatTimer(timer)}
173
- </span>
180
+ {translate.rich('common.account.otp.resendIn', {
181
+ time: formatTimer(timer),
182
+ b: (chunks) => (
183
+ <span className="paragraph-small-semibold text-gray-950">{chunks}</span>
184
+ ),
185
+ })}
174
186
  </p>
175
187
  )}
176
188
  </div>
@@ -179,10 +191,12 @@ export function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {
179
191
 
180
192
  <div className="flex items-center justify-between px-4 lg:px-5 py-4 lg:py-5 mt-auto lg:mt-0">
181
193
  <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
182
- Cancelar
194
+ {translate('common.actions.cancel')}
183
195
  </Button>
184
196
  <Button className="h-10!" type="submit" disabled={!isValidLength || isLoading}>
185
- {isLoading ? 'Validando...' : 'Alterar e-mail'}
197
+ {isLoading
198
+ ? translate('common.account.otp.validating')
199
+ : translate('common.account.changeEmail.confirm')}
186
200
  </Button>
187
201
  </div>
188
202
  </form>
@@ -191,16 +205,16 @@ export function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {
191
205
  <div className="flex flex-col gap-5 lg:gap-6 px-4 lg:px-5 py-5 lg:py-6 flex-1 lg:flex-none">
192
206
  <div className="flex flex-col gap-1">
193
207
  <span className="paragraph-medium-semibold text-gray-950">
194
- Atualizar E-mail de contato
208
+ {translate('common.account.changeEmail.updateTitle')}
195
209
  </span>
196
210
  <span className="paragraph-small-regular text-gray-600">
197
- Informe o seu novo E-mail para manter seu contato atualizado.
211
+ {translate('common.account.changeEmail.updateDescription')}
198
212
  </span>
199
213
  </div>
200
214
 
201
215
  <FormField
202
- label="Novo e-mail"
203
- placeholder="Digite seu novo e-mail"
216
+ label={translate('common.account.changeEmail.newEmail')}
217
+ placeholder={translate('common.account.changeEmail.newEmailPlaceholder')}
204
218
  type="email"
205
219
  {...register('email')}
206
220
  error={!!errors.email}
@@ -211,10 +225,10 @@ export function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {
211
225
 
212
226
  <div className="flex items-center justify-between p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0">
213
227
  <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
214
- Cancelar
228
+ {translate('common.actions.cancel')}
215
229
  </Button>
216
230
  <Button className="h-10!" type="submit" disabled={isSubmitting}>
217
- {isSubmitting ? 'Enviando...' : 'Continuar'}
231
+ {isSubmitting ? translate('common.actions.sending') : translate('common.actions.continue')}
218
232
  </Button>
219
233
  </div>
220
234
  </form>
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { IconLock, IconX } from '@tabler/icons-react';
4
+ import { useTranslations } from 'next-intl';
4
5
  import { Button } from '../../ui/buttons/Button';
5
6
  import { FormField } from '../../ui/form/FormField';
6
7
  import useChangePasswordForm from '../hooks/useChangePasswordForm';
@@ -11,6 +12,7 @@ interface ChangePasswordSectionProps {
11
12
  }
12
13
 
13
14
  export function ChangePasswordSection({ onBack }: ChangePasswordSectionProps) {
15
+ const translate = useTranslations();
14
16
  const { register, handleSubmit, errors } = useChangePasswordForm({
15
17
  onSuccess: onBack,
16
18
  });
@@ -23,7 +25,9 @@ export function ChangePasswordSection({ onBack }: ChangePasswordSectionProps) {
23
25
  className="flex-1 overflow-y-auto px-4 pb-5 lg:p-5 flex flex-col h-full lg:h-full gap-5 lg:gap-6"
24
26
  >
25
27
  <div className="flex items-center justify-between">
26
- <span className="paragraph-medium-semibold text-gray-950">Alterar senha</span>
28
+ <span className="paragraph-medium-semibold text-gray-950">
29
+ {translate('common.account.changePassword.title')}
30
+ </span>
27
31
  <Button type="button" variant="ghost" className="size-8! p-0" onClick={onBack}>
28
32
  <IconX size={18} />
29
33
  </Button>
@@ -31,9 +35,9 @@ export function ChangePasswordSection({ onBack }: ChangePasswordSectionProps) {
31
35
 
32
36
  <div className="flex flex-col gap-4">
33
37
  <FormField
34
- label="Senha atual"
38
+ label={translate('common.account.changePassword.currentPassword')}
35
39
  type="password"
36
- placeholder="Digite sua senha atual"
40
+ placeholder={translate('common.account.changePassword.currentPasswordPlaceholder')}
37
41
  leftIcon={IconLock}
38
42
  error={!!errors.currentPassword}
39
43
  errorMessage={errors.currentPassword?.message}
@@ -43,9 +47,9 @@ export function ChangePasswordSection({ onBack }: ChangePasswordSectionProps) {
43
47
  {...register('currentPassword')}
44
48
  />
45
49
  <FormField
46
- label="Nova senha"
50
+ label={translate('common.account.changePassword.newPassword')}
47
51
  type="password"
48
- placeholder="Digite sua nova senha"
52
+ placeholder={translate('common.account.changePassword.newPasswordPlaceholder')}
49
53
  leftIcon={IconLock}
50
54
  error={!!errors.newPassword}
51
55
  errorMessage={errors.newPassword?.message}
@@ -57,7 +61,7 @@ export function ChangePasswordSection({ onBack }: ChangePasswordSectionProps) {
57
61
  </div>
58
62
 
59
63
  <Button type="submit" className="w-fit h-10!">
60
- Salvar nova senha
64
+ {translate('common.account.changePassword.submit')}
61
65
  </Button>
62
66
  </form>
63
67
  );
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { useTranslations } from 'next-intl';
3
4
  import { IconChevronLeft, IconX, IconMessage } from '@tabler/icons-react';
4
5
  import { Button } from '../../ui/buttons/Button';
5
6
  import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';
@@ -20,6 +21,7 @@ interface ChangePhoneModalProps {
20
21
  }
21
22
 
22
23
  export function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {
24
+ const translate = useTranslations();
23
25
  const { user } = useAuth();
24
26
  const invalidateUser = useInvalidateUser();
25
27
 
@@ -70,7 +72,7 @@ export function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {
70
72
  reset: resetOtp,
71
73
  } = useOtpVerification({
72
74
  onSuccess: handleSuccess,
73
- successMessage: 'Telefone alterado',
75
+ successMessage: translate('common.account.changePhone.phoneChanged'),
74
76
  validateFn: async (token) => {
75
77
  const result = await confirmPhoneChangeAction(token, submittedPhone.local, submittedPhone.ddi);
76
78
  return result.success;
@@ -108,7 +110,7 @@ export function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {
108
110
  <IconChevronLeft size={20} className="text-gray-950" />
109
111
  </Button>
110
112
  <DialogTitle className="paragraph-medium-semibold text-gray-950 text-center flex-1">
111
- Alterar telefone
113
+ {translate('common.account.changePhone.titleEdit')}
112
114
  </DialogTitle>
113
115
  <Button variant="ghost" className="size-8! p-0" onClick={handleClose}>
114
116
  <IconX size={18} className="text-gray-500" />
@@ -117,11 +119,17 @@ export function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {
117
119
  ) : (
118
120
  <>
119
121
  <DialogHeader className="sr-only">
120
- <DialogTitle>{hasExistingPhone ? 'Alterar telefone' : 'Adicionar telefone'}</DialogTitle>
122
+ <DialogTitle>
123
+ {hasExistingPhone
124
+ ? translate('common.account.changePhone.titleEdit')
125
+ : translate('common.account.changePhone.titleAdd')}
126
+ </DialogTitle>
121
127
  </DialogHeader>
122
128
  <div className="flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0">
123
129
  <span className="paragraph-medium-semibold text-gray-950 text-center">
124
- {hasExistingPhone ? 'Alterar telefone' : 'Adicionar telefone'}
130
+ {hasExistingPhone
131
+ ? translate('common.account.changePhone.titleEdit')
132
+ : translate('common.account.changePhone.titleAdd')}
125
133
  </span>
126
134
  <Button
127
135
  variant="ghost"
@@ -150,10 +158,14 @@ export function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {
150
158
  </div>
151
159
 
152
160
  <div className="flex flex-col gap-1">
153
- <h3 className="paragraph-medium-semibold text-gray-950">Código de validação</h3>
161
+ <h3 className="paragraph-medium-semibold text-gray-950">
162
+ {translate('common.account.otp.validationCode')}
163
+ </h3>
154
164
  <p className="paragraph-small-regular text-gray-600">
155
- Enviamos um código de validação para o número atual{' '}
156
- <span className="font-semibold text-gray-950">{currentPhoneDisplay}.</span>
165
+ {translate.rich('common.account.changePhone.sentCodeTo', {
166
+ phone: currentPhoneDisplay,
167
+ b: (chunks) => <span className="font-semibold text-gray-950">{chunks}</span>,
168
+ })}
157
169
  </p>
158
170
  </div>
159
171
 
@@ -170,7 +182,9 @@ export function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {
170
182
  </InputOTPGroup>
171
183
  </InputOTP>
172
184
  {hasError && (
173
- <p className="paragraph-small-regular text-red-500">Código incorreto</p>
185
+ <p className="paragraph-small-regular text-red-500">
186
+ {translate('common.account.otp.incorrectCode')}
187
+ </p>
174
188
  )}
175
189
  </div>
176
190
 
@@ -180,14 +194,16 @@ export function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {
180
194
  onClick={handleResend}
181
195
  className="paragraph-small-medium text-gray-950 underline cursor-pointer hover:text-gray-700 w-fit"
182
196
  >
183
- Reenviar código
197
+ {translate('common.account.otp.resend')}
184
198
  </button>
185
199
  ) : (
186
200
  <p className="paragraph-small-regular text-gray-500">
187
- Reenviar em{' '}
188
- <span className="paragraph-small-semibold text-gray-950">
189
- {formatTimer(timer)}
190
- </span>
201
+ {translate.rich('common.account.otp.resendIn', {
202
+ time: formatTimer(timer),
203
+ b: (chunks) => (
204
+ <span className="paragraph-small-semibold text-gray-950">{chunks}</span>
205
+ ),
206
+ })}
191
207
  </p>
192
208
  )}
193
209
  </div>
@@ -196,10 +212,12 @@ export function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {
196
212
 
197
213
  <div className="flex items-center justify-between px-4 lg:px-5 py-4 lg:py-5 mt-auto lg:mt-0">
198
214
  <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
199
- Cancelar
215
+ {translate('common.actions.cancel')}
200
216
  </Button>
201
217
  <Button className="h-10!" type="submit" disabled={!isValidLength || isLoading}>
202
- {isLoading ? 'Validando...' : 'Alterar telefone'}
218
+ {isLoading
219
+ ? translate('common.account.otp.validating')
220
+ : translate('common.account.changePhone.confirm')}
203
221
  </Button>
204
222
  </div>
205
223
  </form>
@@ -208,17 +226,23 @@ export function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {
208
226
  <div className="flex flex-col gap-5 lg:gap-6 px-4 lg:px-5 py-5 lg:py-6 flex-1 lg:flex-none">
209
227
  <div className="flex flex-col gap-1">
210
228
  <span className="paragraph-medium-semibold text-gray-950">
211
- {hasExistingPhone ? 'Atualizar telefone de contato' : 'Adicionar telefone de contato'}
229
+ {hasExistingPhone
230
+ ? translate('common.account.changePhone.updateTitle')
231
+ : translate('common.account.changePhone.addTitle')}
212
232
  </span>
213
233
  <span className="paragraph-small-regular text-gray-600">
214
234
  {hasExistingPhone
215
- ? 'Informe o novo número para manter seu contato atualizado.'
216
- : 'Informe seu número de telefone para contato.'}
235
+ ? translate('common.account.changePhone.updateDescription')
236
+ : translate('common.account.changePhone.addDescription')}
217
237
  </span>
218
238
  </div>
219
239
 
220
240
  <PhoneInput
221
- label={hasExistingPhone ? 'Novo número' : 'Número de telefone'}
241
+ label={
242
+ hasExistingPhone
243
+ ? translate('common.account.changePhone.newNumber')
244
+ : translate('common.account.changePhone.numberLabel')
245
+ }
222
246
  placeholder="(00) 0 0000-0000"
223
247
  value={phoneValue}
224
248
  onChange={handlePhoneChange}
@@ -229,12 +253,16 @@ export function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {
229
253
 
230
254
  <div className="flex items-center justify-between p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0">
231
255
  <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
232
- Cancelar
256
+ {translate('common.actions.cancel')}
233
257
  </Button>
234
258
  <Button className="h-10!" type="submit" disabled={isSubmitting}>
235
259
  {isSubmitting
236
- ? (hasExistingPhone ? 'Enviando...' : 'Salvando...')
237
- : (hasExistingPhone ? 'Continuar' : 'Salvar')}
260
+ ? hasExistingPhone
261
+ ? translate('common.actions.sending')
262
+ : translate('common.actions.saving')
263
+ : hasExistingPhone
264
+ ? translate('common.actions.continue')
265
+ : translate('common.actions.save')}
238
266
  </Button>
239
267
  </div>
240
268
  </form>