@greatapps/common 1.1.676 → 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 (243) 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/services/plans.service.mjs +1 -1
  141. package/dist/modules/plans/services/plans.service.mjs.map +1 -1
  142. package/dist/modules/plans/types/plan.type.mjs +5 -1
  143. package/dist/modules/plans/types/plan.type.mjs.map +1 -1
  144. package/dist/modules/plans/utils/map-api-plan-to-ui.mjs +61 -35
  145. package/dist/modules/plans/utils/map-api-plan-to-ui.mjs.map +1 -1
  146. package/dist/modules/projects/services/projects.service.mjs +9 -0
  147. package/dist/modules/projects/services/projects.service.mjs.map +1 -1
  148. package/dist/modules/subscriptions/utils/periodicity.mjs +20 -14
  149. package/dist/modules/subscriptions/utils/periodicity.mjs.map +1 -1
  150. package/dist/providers/auth.provider.mjs +9 -1
  151. package/dist/providers/auth.provider.mjs.map +1 -1
  152. package/dist/server.mjs +2 -0
  153. package/dist/server.mjs.map +1 -1
  154. package/dist/utils/format/currency.mjs +32 -4
  155. package/dist/utils/format/currency.mjs.map +1 -1
  156. package/dist/utils/intl/cookie-domain.mjs +17 -0
  157. package/dist/utils/intl/cookie-domain.mjs.map +1 -0
  158. package/dist/utils/intl/locale-cookie.mjs +13 -0
  159. package/dist/utils/intl/locale-cookie.mjs.map +1 -0
  160. package/dist/utils/intl/locales.mjs +3 -2
  161. package/dist/utils/intl/locales.mjs.map +1 -1
  162. package/package.json +7 -1
  163. package/src/components/account/ConfigurationsMyAccountModal.tsx +10 -6
  164. package/src/components/account/ConfirmDeleteAccountModal.tsx +22 -13
  165. package/src/components/account/ConfirmGlobalPreferencesModal.tsx +12 -10
  166. package/src/components/account/DeleteAccountModal.tsx +34 -24
  167. package/src/components/account/DisableTwoFactorAuthModal.tsx +11 -6
  168. package/src/components/account/IsntPossibleDeleteAccountModal.tsx +8 -6
  169. package/src/components/account/TwoFactorAuthModal.tsx +33 -29
  170. package/src/components/account/constants.ts +8 -5
  171. package/src/components/account/hooks/useChangeEmailForm.tsx +5 -3
  172. package/src/components/account/hooks/useChangePasswordForm.tsx +20 -6
  173. package/src/components/account/hooks/useChangePhoneForm.tsx +16 -10
  174. package/src/components/account/hooks/useDisableTwoFactorAuthForm.tsx +20 -6
  175. package/src/components/account/hooks/useOtpVerification.tsx +16 -4
  176. package/src/components/account/hooks/useTwoFactorAuthForm.tsx +21 -7
  177. package/src/components/account/sections/ChangeEmailModal.tsx +35 -21
  178. package/src/components/account/sections/ChangePasswordSection.tsx +10 -6
  179. package/src/components/account/sections/ChangePhoneModal.tsx +50 -22
  180. package/src/components/account/sections/MyProfileSection.tsx +37 -23
  181. package/src/components/account/sections/PreferencesSection.tsx +52 -25
  182. package/src/components/account/sections/SecuritySection.tsx +19 -10
  183. package/src/components/account/sections/TokenSection.tsx +22 -10
  184. package/src/components/layouts/AppMobileNavBar.tsx +1 -154
  185. package/src/components/layouts/NavBar.tsx +5 -3
  186. package/src/components/layouts/NotificationsPopover.tsx +5 -3
  187. package/src/components/layouts/ProfilePopover.tsx +6 -4
  188. package/src/components/layouts/UsersSelectorPopover.tsx +9 -7
  189. package/src/components/modals/BuyCreditsModal.tsx +18 -16
  190. package/src/components/modals/CreditsDisabledModal.tsx +6 -6
  191. package/src/components/modals/PaidPlanRequiredModal.tsx +5 -3
  192. package/src/components/modals/cards/AddCardModal.tsx +89 -62
  193. package/src/components/modals/cards/CannotDeleteCardModal.tsx +9 -8
  194. package/src/components/modals/cards/CardFormFields.tsx +93 -75
  195. package/src/components/modals/cards/DeleteCardModal.tsx +10 -8
  196. package/src/components/navigation/CancelledSubscriptionBanner.tsx +4 -2
  197. package/src/components/navigation/OverdueInvoiceBanner.tsx +4 -2
  198. package/src/components/navigation/PendingCancellationBanner.tsx +4 -2
  199. package/src/components/navigation/ProjectSelectorPopover.tsx +8 -6
  200. package/src/components/navigation/UpcomingInvoiceBanner.tsx +4 -2
  201. package/src/components/navigation/subcomponents/BottomLinks.tsx +5 -3
  202. package/src/components/navigation/subcomponents/CreditsCard.tsx +3 -1
  203. package/src/components/navigation/subcomponents/PlanCard.tsx +3 -1
  204. package/src/components/navigation/subcomponents/ProjectSelector.tsx +5 -3
  205. package/src/components/pages/NotFoundPage.tsx +5 -3
  206. package/src/components/pages/notifications/Notifications.tsx +13 -10
  207. package/src/components/ui/buttons/CopyButton.tsx +10 -5
  208. package/src/components/ui/data-display/CardItem.tsx +7 -5
  209. package/src/components/ui/data-display/PaymentInfoCard.tsx +10 -8
  210. package/src/components/ui/feedback/CircularProgress.tsx +4 -0
  211. package/src/components/ui/feedback/DefaultCircularProgress.tsx +3 -1
  212. package/src/components/ui/form/ComboboxField.tsx +11 -6
  213. package/src/components/ui/form/DatePicker.tsx +5 -2
  214. package/src/components/ui/form/DateRangePicker.tsx +5 -2
  215. package/src/components/ui/form/PhoneInput.tsx +5 -3
  216. package/src/components/ui/form/SelectField.tsx +6 -3
  217. package/src/components/widgets/ImageUpload/ImageCropModal.tsx +19 -11
  218. package/src/components/widgets/ImageUpload/ImageTooSmallModal.tsx +6 -5
  219. package/src/i18n/config.ts +17 -0
  220. package/src/i18n/country-language.ts +60 -0
  221. package/src/i18n/messages/en-us.ts +514 -0
  222. package/src/i18n/messages/es-es.ts +515 -0
  223. package/src/i18n/messages/index.ts +24 -0
  224. package/src/i18n/messages/pt-br.ts +538 -0
  225. package/src/i18n/normalize.ts +15 -0
  226. package/src/i18n/resolve-locale.ts +77 -0
  227. package/src/i18n.ts +10 -0
  228. package/src/index.ts +13 -2
  229. package/src/modules/accounts/hooks/use-currency-formatter.hook.tsx +32 -0
  230. package/src/modules/cards/hooks/handle-delete-card.hook.ts +8 -3
  231. package/src/modules/images/utils/validate-image.ts +23 -8
  232. package/src/modules/plans/hooks/list-plans.hook.ts +2 -2
  233. package/src/modules/plans/services/plans.service.ts +1 -1
  234. package/src/modules/plans/types/plan.type.ts +4 -0
  235. package/src/modules/plans/utils/map-api-plan-to-ui.ts +109 -47
  236. package/src/modules/projects/services/projects.service.ts +12 -0
  237. package/src/modules/subscriptions/utils/periodicity.ts +29 -12
  238. package/src/providers/auth.provider.tsx +13 -1
  239. package/src/server.ts +2 -0
  240. package/src/utils/format/currency.ts +62 -7
  241. package/src/utils/intl/cookie-domain.ts +29 -0
  242. package/src/utils/intl/locale-cookie.ts +18 -0
  243. package/src/utils/intl/locales.ts +3 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/common",
3
- "version": "1.1.676",
3
+ "version": "1.1.677",
4
4
  "description": "Shared library for GreatApps frontend applications",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./src/index.ts",
@@ -28,6 +28,10 @@
28
28
  "./handlers": {
29
29
  "import": "./dist/handlers.mjs",
30
30
  "types": "./src/handlers.ts"
31
+ },
32
+ "./i18n": {
33
+ "import": "./dist/i18n.mjs",
34
+ "types": "./src/i18n.ts"
31
35
  }
32
36
  },
33
37
  "files": [
@@ -86,6 +90,7 @@
86
90
  "@types/react-dom": "^19.2.3",
87
91
  "glob": "^13.0.6",
88
92
  "next": "16.2.1",
93
+ "next-intl": "^4.12.0",
89
94
  "react": "19.1.4",
90
95
  "react-dom": "19.1.4",
91
96
  "react-hook-form": "^7.72.0",
@@ -97,6 +102,7 @@
97
102
  "@hookform/resolvers": ">=3.0.0",
98
103
  "@tanstack/react-query": ">=5.0.0",
99
104
  "next": ">=16.0.0",
105
+ "next-intl": ">=4.0.0",
100
106
  "react": ">=19.0.0",
101
107
  "react-dom": ">=19.0.0",
102
108
  "react-hook-form": ">=7.0.0",
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { IconKey, IconLock, IconSettings2, IconX } from '@tabler/icons-react';
4
+ import { useTranslations } from 'next-intl';
4
5
  import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';
5
6
  import { Tabs, TabsList, TabsTrigger, TabsContent } from '../ui/data-display/Tabs';
6
7
  import { cn } from '../../infra/utils/clsx';
@@ -19,6 +20,7 @@ import { hasSubscriptionExpired } from '../../modules/subscriptions/utils/has-su
19
20
  import { useWhitelabel } from '../../providers/whitelabel.provider';
20
21
 
21
22
  export default function ConfigurationsMyAccountModal() {
23
+ const translate = useTranslations();
22
24
  const {
23
25
  activeModal,
24
26
  openDeleteAccount,
@@ -85,10 +87,12 @@ export default function ConfigurationsMyAccountModal() {
85
87
  lg:top-[50%] lg:bottom-auto lg:left-[50%] lg:right-auto lg:translate-x-[-50%] lg:translate-y-[-50%]"
86
88
  >
87
89
  <DialogHeader className="sr-only">
88
- <DialogTitle>Configurações</DialogTitle>
90
+ <DialogTitle>{translate('common.account.configurations.title')}</DialogTitle>
89
91
  </DialogHeader>
90
92
  <div className="md:hidden flex items-center justify-between px-5 py-3 border-b border-gray-200">
91
- <span className="text-gray-950 paragraph-medium-semibold">Configurações</span>
93
+ <span className="text-gray-950 paragraph-medium-semibold">
94
+ {translate('common.account.configurations.title')}
95
+ </span>
92
96
  <button
93
97
  type="button"
94
98
  className="size-8 flex items-center justify-center text-gray-500 cursor-pointer"
@@ -116,26 +120,26 @@ export default function ConfigurationsMyAccountModal() {
116
120
  )}
117
121
  >
118
122
  <span className="hidden lg:block paragraph-medium-semibold text-gray-950 mb-0">
119
- Configurações
123
+ {translate('common.account.configurations.title')}
120
124
  </span>
121
125
 
122
126
  <div className="lg:flex lg:flex-col flex flex-row lg:gap-0 gap-0 lg:w-full">
123
127
  <TabsTrigger value={AccountSectionType.PREFERENCES} className={tabTriggerClasses}>
124
128
  <IconSettings2 size={20} className="shrink-0" />
125
- <span className="paragraph-small-medium">Preferências</span>
129
+ <span className="paragraph-small-medium">{translate('common.preferences.title')}</span>
126
130
  </TabsTrigger>
127
131
 
128
132
  {isOwner && whitelabel?.id === 1 && (
129
133
  <TabsTrigger value={AccountSectionType.TOKEN} className={tabTriggerClasses}>
130
134
  <IconKey size={20} className="shrink-0" />
131
- <span className="paragraph-small-medium">Token da conta</span>
135
+ <span className="paragraph-small-medium">{translate('common.account.token.title')}</span>
132
136
  </TabsTrigger>
133
137
  )}
134
138
 
135
139
  {isOwner && (
136
140
  <TabsTrigger value={AccountSectionType.SECURITY} className={tabTriggerClasses}>
137
141
  <IconLock size={20} className="shrink-0" />
138
- <span className="paragraph-small-medium">Segurança</span>
142
+ <span className="paragraph-small-medium">{translate('common.account.security.title')}</span>
139
143
  </TabsTrigger>
140
144
  )}
141
145
  </div>
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { useTranslations } from 'next-intl';
3
4
  import { IconAlertTriangle } from '@tabler/icons-react';
4
5
  import { toast } from 'sonner';
5
6
  import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';
@@ -15,6 +16,7 @@ import { useAuth } from '../../providers/auth.provider';
15
16
  import { UserProfile } from '../../modules/users/schema';
16
17
 
17
18
  export default function ConfirmDeleteAccountModal() {
19
+ const translate = useTranslations();
18
20
  const { activeModal, deleteAccountPayload, openDeleteAccount, close } = useAccountModals();
19
21
  const open = activeModal === 'confirmDelete';
20
22
 
@@ -33,7 +35,7 @@ export default function ConfirmDeleteAccountModal() {
33
35
  if (!deleteAccountPayload) {
34
36
  // Fluxo quebrado (usuário pulou o primeiro modal ou refresh) — manda
35
37
  // de volta pro modal inicial pra re-coletar a senha.
36
- openDeleteAccount('Sessão expirada. Preencha os campos novamente.');
38
+ openDeleteAccount(translate('common.account.confirmDelete.sessionExpired'));
37
39
  return;
38
40
  }
39
41
  await deleteAccount.mutateAsync({ password: deleteAccountPayload.password });
@@ -41,20 +43,25 @@ export default function ConfirmDeleteAccountModal() {
41
43
  await deleteAccountUser.mutateAsync(user!.id);
42
44
  }
43
45
  close();
44
- toast.custom((t) => (
45
- <Toast variant="success" message="Conta excluída com sucesso" toastId={t} />
46
+ toast.custom((toastId) => (
47
+ <Toast
48
+ variant="success"
49
+ message={translate('common.account.confirmDelete.success')}
50
+ toastId={toastId}
51
+ />
46
52
  ));
47
53
  await logout();
48
54
  } catch (error) {
49
- const message = error instanceof Error ? error.message : 'Erro ao excluir. Tente novamente.';
55
+ const message =
56
+ error instanceof Error ? error.message : translate('common.account.confirmDelete.error');
50
57
  if (isOwner) {
51
58
  // Falha no delete do owner (ex.: senha inválida) — volta pro primeiro
52
59
  // modal com a mensagem do backend pra o usuário corrigir e tentar de novo.
53
60
  openDeleteAccount(message);
54
61
  return;
55
62
  }
56
- toast.custom((t) => (
57
- <Toast variant="error" message={message} toastId={t} />
63
+ toast.custom((toastId) => (
64
+ <Toast variant="error" message={message} toastId={toastId} />
58
65
  ));
59
66
  }
60
67
  };
@@ -65,17 +72,17 @@ export default function ConfirmDeleteAccountModal() {
65
72
  <div className="flex flex-col gap-5 p-4 lg:p-5">
66
73
  <DialogHeader className="p-0">
67
74
  <DialogTitle className="paragraph-medium-semibold text-gray-950">
68
- Uma pena te ver ir!
75
+ {translate('common.account.confirmDelete.title')}
69
76
  </DialogTitle>
70
77
  </DialogHeader>
71
78
 
72
79
  <div className="bg-red-50 p-4 lg:p-5 rounded-lg flex items-center gap-4">
73
80
  <IconAlertTriangle size={20} className="text-red-500 shrink-0" strokeWidth={2} />
74
81
  <p className="paragraph-small-regular text-gray-600">
75
- Todas suas{' '}
76
- <span className="font-semibold text-gray-950">{pagesCount} páginas</span>{' '}
77
- serão deletadas permanentemente. Essa ação é{' '}
78
- <span className="font-semibold text-gray-950">irreversível!</span>
82
+ {translate.rich('common.account.confirmDelete.warning', {
83
+ count: String(pagesCount),
84
+ b: (chunks) => <span className="font-semibold text-gray-950">{chunks}</span>,
85
+ })}
79
86
  </p>
80
87
  </div>
81
88
  </div>
@@ -84,7 +91,7 @@ export default function ConfirmDeleteAccountModal() {
84
91
 
85
92
  <div className="flex items-center gap-2 p-4 lg:p-5">
86
93
  <Button className="h-10 flex-1" onClick={close} disabled={isDeleting}>
87
- Manter minha conta
94
+ {translate('common.account.confirmDelete.keepAccount')}
88
95
  </Button>
89
96
  <Button
90
97
  variant="secondary"
@@ -92,7 +99,9 @@ export default function ConfirmDeleteAccountModal() {
92
99
  onClick={handleConfirm}
93
100
  disabled={isDeleting}
94
101
  >
95
- {isDeleting ? 'Excluindo...' : 'Excluir mesmo assim'}
102
+ {isDeleting
103
+ ? translate('common.account.confirmDelete.deleting')
104
+ : translate('common.account.confirmDelete.deleteAnyway')}
96
105
  </Button>
97
106
  </div>
98
107
  </DialogContent>
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { useTranslations } from 'next-intl';
3
4
  import { IconAlertTriangle } from '@tabler/icons-react';
4
5
  import { Button } from '../ui/buttons/Button';
5
6
  import {
@@ -22,13 +23,14 @@ export default function ConfirmGlobalPreferencesModal({
22
23
  onConfirm,
23
24
  onCancel,
24
25
  }: ConfirmGlobalPreferencesModalProps) {
26
+ const translate = useTranslations();
25
27
  return (
26
28
  <Dialog open={open} onOpenChange={onCancel}>
27
29
  <DialogContent className="flex flex-col p-0 gap-0 md:w-[386px]! lg:w-[386px]! max-w-[386px]! max-[386px]:w-[calc(100%-32px)]">
28
30
  <DialogHeader className="sr-only">
29
- <DialogTitle>Alterar preferências globais</DialogTitle>
31
+ <DialogTitle>{translate('common.account.globalPreferences.title')}</DialogTitle>
30
32
  <DialogDescription>
31
- Confirmação de alteração de preferências globais da conta
33
+ {translate('common.account.globalPreferences.srDescription')}
32
34
  </DialogDescription>
33
35
  </DialogHeader>
34
36
 
@@ -38,14 +40,14 @@ export default function ConfirmGlobalPreferencesModal({
38
40
  </div>
39
41
  <div className="flex flex-col gap-2">
40
42
  <span className="paragraph-medium-semibold text-gray-950">
41
- Alterar preferências globais
43
+ {translate('common.account.globalPreferences.title')}
42
44
  </span>
43
45
  <span className="paragraph-small-regular text-gray-600">
44
- Você está alterando configurações que impactam{' '}
45
- <span className="paragraph-small-semibold text-gray-950">
46
- todos os usuários da conta
47
- </span>
48
- . Deseja confirmar?
46
+ {translate.rich('common.account.globalPreferences.warning', {
47
+ b: (chunks) => (
48
+ <span className="paragraph-small-semibold text-gray-950">{chunks}</span>
49
+ ),
50
+ })}
49
51
  </span>
50
52
  </div>
51
53
  </div>
@@ -54,10 +56,10 @@ export default function ConfirmGlobalPreferencesModal({
54
56
 
55
57
  <div className="flex items-center gap-2 p-5">
56
58
  <Button onClick={onConfirm} className="h-10!">
57
- Confirmar
59
+ {translate('common.actions.confirm')}
58
60
  </Button>
59
61
  <Button variant="secondary" onClick={onCancel} className="h-10!">
60
- Cancelar
62
+ {translate('common.actions.cancel')}
61
63
  </Button>
62
64
  </div>
63
65
  </DialogContent>
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useState, useCallback, useEffect } from 'react';
4
+ import { useTranslations } from 'next-intl';
4
5
  import { IconLock, IconAlertTriangle } from '@tabler/icons-react';
5
6
  import { toast } from 'sonner';
6
7
  import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';
@@ -13,16 +14,16 @@ import usePasswordVisibility from '../../hooks/usePasswordVisibility';
13
14
  import { useAccountModals } from '../../store/useAccountModals';
14
15
  import { AccountSectionType } from '../../enums/AccountSectionType';
15
16
 
16
- const REASON_OPTIONS = [
17
- { value: 'sem-funcao', label: 'A ferramenta não possui uma função que eu preciso' },
18
- { value: 'problemas', label: 'Encontrei problemas técnicos ou erros no sistema' },
19
- { value: 'suporte', label: 'Tive problemas com o suporte ou atendimento' },
20
- { value: 'demora', label: 'As atualizações demoram mais do que o esperado' },
21
- { value: 'temporario', label: 'O cancelamento é temporário' },
22
- { value: 'outro', label: 'Outro motivo' },
23
- ];
24
-
25
17
  export default function DeleteAccountModal() {
18
+ const translate = useTranslations();
19
+ const reasonOptions = [
20
+ { value: 'sem-funcao', label: translate('common.account.deleteAccount.reasons.noFeature') },
21
+ { value: 'problemas', label: translate('common.account.deleteAccount.reasons.technical') },
22
+ { value: 'suporte', label: translate('common.account.deleteAccount.reasons.support') },
23
+ { value: 'demora', label: translate('common.account.deleteAccount.reasons.updates') },
24
+ { value: 'temporario', label: translate('common.account.deleteAccount.reasons.temporary') },
25
+ { value: 'outro', label: translate('common.account.deleteAccount.reasons.other') },
26
+ ];
26
27
  const {
27
28
  activeModal,
28
29
  deleteAccountError,
@@ -61,8 +62,12 @@ export default function DeleteAccountModal() {
61
62
  const handleDelete = (e: React.FormEvent) => {
62
63
  e.preventDefault();
63
64
  if (!isFormValid) {
64
- toast.custom((t) => (
65
- <Toast variant="error" message="Preencha todos os campos obrigatórios" toastId={t} />
65
+ toast.custom((toastId) => (
66
+ <Toast
67
+ variant="error"
68
+ message={translate('common.account.deleteAccount.requiredFields')}
69
+ toastId={toastId}
70
+ />
66
71
  ));
67
72
  return;
68
73
  }
@@ -80,18 +85,21 @@ export default function DeleteAccountModal() {
80
85
  <div className="flex items-center justify-center w-fit bg-red-50 rounded-lg p-2.5 mb-5">
81
86
  <IconAlertTriangle size={20} className="text-red-500" />
82
87
  </div>
83
- <DialogTitle>Excluir conta</DialogTitle>
88
+ <DialogTitle>{translate('common.account.deleteAccount.title')}</DialogTitle>
84
89
  <DialogDescription className="paragraph-small-regular">
85
- Esta ação é <span className="font-semibold text-gray-950">irreversível</span>. Ao
86
- confirmar, sua conta e todos os seus dados serão excluídos.
90
+ {translate.rich('common.account.deleteAccount.description', {
91
+ b: (chunks) => (
92
+ <span className="font-semibold text-gray-950">{chunks}</span>
93
+ ),
94
+ })}
87
95
  </DialogDescription>
88
96
  </DialogHeader>
89
97
 
90
98
  <SelectField
91
- label="Motivo do cancelamento"
99
+ label={translate('common.account.deleteAccount.reasonLabel')}
92
100
  required
93
- placeholder="Selecione"
94
- options={REASON_OPTIONS}
101
+ placeholder={translate('common.account.deleteAccount.reasonPlaceholder')}
102
+ options={reasonOptions}
95
103
  value={reason}
96
104
  onChange={(value) => setReason(value as string)}
97
105
  className="h-10!"
@@ -99,24 +107,26 @@ export default function DeleteAccountModal() {
99
107
 
100
108
  <div>
101
109
  <TextAreaField
102
- label="Descreva o que levou a tomar essa decisão"
110
+ label={translate('common.account.deleteAccount.descriptionLabel')}
103
111
  required
104
- placeholder="Explique sua decisão..."
112
+ placeholder={translate('common.account.deleteAccount.descriptionPlaceholder')}
105
113
  value={description}
106
114
  onChange={(e) => setDescription(e.target.value)}
107
115
  rows={4}
108
116
  maxLength={400}
109
117
  />
110
118
  <span className="paragraph-xsmall-medium text-gray-600 text-left mt-1 block">
111
- {description.length}/400 caracteres
119
+ {translate('common.account.deleteAccount.charactersCount', {
120
+ count: String(description.length),
121
+ })}
112
122
  </span>
113
123
  </div>
114
124
 
115
125
  <FormField
116
126
  className="text-gray-600"
117
- label="Senha"
127
+ label={translate('common.account.deleteAccount.passwordLabel')}
118
128
  type="password"
119
- placeholder="Informe sua senha"
129
+ placeholder={translate('common.account.deleteAccount.passwordPlaceholder')}
120
130
  leftIcon={IconLock}
121
131
  value={password}
122
132
  onChange={(e) => {
@@ -137,10 +147,10 @@ export default function DeleteAccountModal() {
137
147
  className="h-10"
138
148
  type="submit"
139
149
  >
140
- Excluir conta
150
+ {translate('common.account.deleteAccount.submit')}
141
151
  </Button>
142
152
  <Button variant="secondary" className="h-10" type="button" onClick={handleClose}>
143
- Fechar
153
+ {translate('common.actions.close')}
144
154
  </Button>
145
155
  </div>
146
156
  </form>
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { useTranslations } from 'next-intl';
3
4
  import { IconShieldCheck } from '@tabler/icons-react';
4
5
  import { Button } from '../ui/buttons/Button';
5
6
  import {
@@ -24,6 +25,7 @@ export default function DisableTwoFactorAuthModal({
24
25
  onClose,
25
26
  onSuccess,
26
27
  }: DisableTwoFactorAuthModalProps) {
28
+ const translate = useTranslations();
27
29
  const { code, setCode, isValid, isLoading, handleClose, handleSubmit } =
28
30
  useDisableTwoFactorAuthForm({ onClose, onSuccess });
29
31
 
@@ -43,16 +45,17 @@ export default function DisableTwoFactorAuthModal({
43
45
  </div>
44
46
  <DialogHeader className="p-0 gap-2">
45
47
  <DialogTitle className="paragraph-medium-semibold text-gray-950">
46
- Desabilitar autenticação 2FA
48
+ {translate('common.account.twoFactor.disableTitle')}
47
49
  </DialogTitle>
48
50
  <DialogDescription className="paragraph-small-regular text-gray-600">
49
- Informe o código de 6 dígitos do seu aplicativo autenticador para confirmar a
50
- desativação.
51
+ {translate('common.account.twoFactor.disableDescription')}
51
52
  </DialogDescription>
52
53
  </DialogHeader>
53
54
 
54
55
  <div className="flex flex-col gap-2">
55
- <span className="paragraph-small-medium text-gray-700">Código do autenticador</span>
56
+ <span className="paragraph-small-medium text-gray-700">
57
+ {translate('common.account.twoFactor.authenticatorCode')}
58
+ </span>
56
59
  <InputOTP maxLength={6} pattern={REGEXP_ONLY_DIGITS} value={code} onChange={setCode}>
57
60
  <InputOTPGroup className="gap-2">
58
61
  {Array.from({ length: 6 }).map((_, i) => (
@@ -69,7 +72,9 @@ export default function DisableTwoFactorAuthModal({
69
72
 
70
73
  <div className="flex flex-row items-center gap-2 p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0">
71
74
  <Button className="h-10! flex-1" disabled={!isValid || isLoading} type="submit">
72
- {isLoading ? 'Desabilitando...' : 'Desabilitar 2FA'}
75
+ {isLoading
76
+ ? translate('common.account.twoFactor.disabling')
77
+ : translate('common.account.twoFactor.disable')}
73
78
  </Button>
74
79
  <Button
75
80
  variant="secondary"
@@ -77,7 +82,7 @@ export default function DisableTwoFactorAuthModal({
77
82
  type="button"
78
83
  onClick={handleClose}
79
84
  >
80
- Cancelar
85
+ {translate('common.actions.cancel')}
81
86
  </Button>
82
87
  </div>
83
88
  </form>
@@ -1,11 +1,13 @@
1
1
  'use client';
2
2
 
3
+ import { useTranslations } from 'next-intl';
3
4
  import { IconAlertTriangle } from '@tabler/icons-react';
4
5
  import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';
5
6
  import { Button } from '../ui/buttons/Button';
6
7
  import { useAccountModals } from '../../store/useAccountModals';
7
8
 
8
9
  export default function IsntPossibleDeleteAccountModal() {
10
+ const translate = useTranslations();
9
11
  const { activeModal, close, config } = useAccountModals();
10
12
  const { onGoToSubscription } = config;
11
13
  const open = activeModal === 'isntPossibleDelete';
@@ -19,12 +21,12 @@ export default function IsntPossibleDeleteAccountModal() {
19
21
  </div>
20
22
  <DialogHeader className="p-0 gap-2">
21
23
  <DialogTitle className="paragraph-medium-semibold text-gray-950">
22
- Não é possível excluir a conta
24
+ {translate('common.account.cantDelete.title')}
23
25
  </DialogTitle>
24
26
  <DialogDescription className="paragraph-small-regular text-gray-600">
25
- Você tem uma assinatura ativa. Para excluir sua conta,{' '}
26
- <span className="font-semibold text-gray-950">primeiro cancele a assinatura</span> na
27
- página Assinatura e depois tente novamente.
27
+ {translate.rich('common.account.cantDelete.description', {
28
+ b: (chunks) => <span className="font-semibold text-gray-950">{chunks}</span>,
29
+ })}
28
30
  </DialogDescription>
29
31
  </DialogHeader>
30
32
  </div>
@@ -33,14 +35,14 @@ export default function IsntPossibleDeleteAccountModal() {
33
35
 
34
36
  <div className="flex flex-row items-center gap-2">
35
37
  <Button className="h-10 flex-1" onClick={close}>
36
- Ok, entendi
38
+ {translate('common.account.cantDelete.confirm')}
37
39
  </Button>
38
40
  <Button
39
41
  variant="secondary"
40
42
  className="h-10 flex-1"
41
43
  onClick={onGoToSubscription ?? close}
42
44
  >
43
- Ir para assinatura
45
+ {translate('common.account.cantDelete.goToSubscription')}
44
46
  </Button>
45
47
  </div>
46
48
  </DialogContent>
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { useTranslations } from 'next-intl';
3
4
  import { IconX, IconCopy, IconRefresh } from '@tabler/icons-react';
4
5
  import { Button } from '../ui/buttons/Button';
5
6
  import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';
@@ -15,6 +16,7 @@ interface TwoFactorAuthModalProps {
15
16
  }
16
17
 
17
18
  export default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFactorAuthModalProps) {
19
+ const translate = useTranslations();
18
20
  const {
19
21
  code,
20
22
  setCode,
@@ -46,11 +48,11 @@ export default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFact
46
48
  className="z-[1011] flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-[100dvh] top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[470px] lg:h-auto lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]"
47
49
  >
48
50
  <DialogHeader className="sr-only">
49
- <DialogTitle>Códigos de segurança</DialogTitle>
51
+ <DialogTitle>{translate('common.account.twoFactor.recoveryTitle')}</DialogTitle>
50
52
  </DialogHeader>
51
53
  <div className="flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0">
52
54
  <span className="paragraph-medium-semibold text-gray-950 text-center">
53
- Códigos de segurança
55
+ {translate('common.account.twoFactor.recoveryTitle')}
54
56
  </span>
55
57
  <Button
56
58
  type="button"
@@ -65,15 +67,12 @@ export default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFact
65
67
  <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">
66
68
  <div className="flex flex-col gap-2">
67
69
  <h3 className="paragraph-medium-semibold text-gray-950 max-w-[269px]">
68
- Salve estes códigos de recuperação de emergência
70
+ {translate('common.account.twoFactor.recoveryHeading')}
69
71
  </h3>
70
72
  <div className="paragraph-small-regular text-gray-600">
71
- <p>
72
- Se você perder acesso ao seu telefone, não será possível fazer login em sua conta
73
- sem um código de dois fatores.
74
- </p>
73
+ <p>{translate('common.account.twoFactor.recoveryText1')}</p>
75
74
  <br />
76
- <p>Imprima, copie ou escreva em um local seguro os códigos abaixo.</p>
75
+ <p>{translate('common.account.twoFactor.recoveryText2')}</p>
77
76
  </div>
78
77
  </div>
79
78
 
@@ -90,17 +89,17 @@ export default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFact
90
89
  onClick={handleCopyCodes}
91
90
  >
92
91
  <IconCopy size={16} />
93
- Copiar códigos
92
+ {translate('common.account.twoFactor.copyCodes')}
94
93
  </Button>
95
94
  </div>
96
95
  </div>
97
96
 
98
97
  <div className="flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between mt-auto lg:mt-0">
99
98
  <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
100
- Cancelar
99
+ {translate('common.actions.cancel')}
101
100
  </Button>
102
101
  <Button className="h-10!" type="button" onClick={handleFinalize}>
103
- Finalizar
102
+ {translate('common.account.twoFactor.finish')}
104
103
  </Button>
105
104
  </div>
106
105
  </DialogContent>
@@ -116,11 +115,11 @@ export default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFact
116
115
  className="z-[1011] flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-[100dvh] top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[470px] lg:h-auto lg:max-h-[90vh] lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%]"
117
116
  >
118
117
  <DialogHeader className="sr-only">
119
- <DialogTitle>Autenticação de dois fatores</DialogTitle>
118
+ <DialogTitle>{translate('common.account.twoFactor.title')}</DialogTitle>
120
119
  </DialogHeader>
121
120
  <div className="shrink-0 flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0">
122
121
  <span className="paragraph-medium-semibold text-gray-950 text-center">
123
- Autenticação de dois fatores
122
+ {translate('common.account.twoFactor.title')}
124
123
  </span>
125
124
  <Button
126
125
  type="button"
@@ -142,17 +141,18 @@ export default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFact
142
141
  <div className="flex-1 min-h-0 overflow-y-auto overscroll-contain lg:overflow-visible">
143
142
  <div className="flex flex-col items-center gap-4 lg:gap-8 px-4 lg:px-5 py-4 lg:py-6 pb-60 lg:pb-6">
144
143
  <p className="paragraph-small-regular text-gray-950 text-center max-w-full lg:max-w-[412px]">
145
- Instale um aplicativo autenticador no seu celular (ex.:{' '}
146
- <a
147
- href="https://support.google.com/accounts/answer/1066447"
148
- target="_blank"
149
- rel="noopener noreferrer"
150
- className="paragraph-small-medium underline"
151
- >
152
- Google Authenticator
153
- </a>
154
- ), escaneie o QR Code ao lado ou copie a chave no aplicativo e, em seguida, digite o
155
- código de 6 dígitos gerado para continuar.
144
+ {translate.rich('common.account.twoFactor.instructions', {
145
+ link: (chunks) => (
146
+ <a
147
+ href="https://support.google.com/accounts/answer/1066447"
148
+ target="_blank"
149
+ rel="noopener noreferrer"
150
+ className="paragraph-small-medium underline"
151
+ >
152
+ {chunks}
153
+ </a>
154
+ ),
155
+ })}
156
156
  </p>
157
157
 
158
158
  <div className="border border-gray-200 rounded-lg overflow-hidden p-2 lg:p-3 flex items-center justify-center w-[136px] h-[136px] lg:w-[203px] lg:h-[203px]">
@@ -163,7 +163,9 @@ export default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFact
163
163
  className="flex flex-col items-center gap-1.5 text-center"
164
164
  >
165
165
  <IconRefresh size={20} className="text-gray-400" />
166
- <span className="paragraph-xsmall-medium text-gray-500">Tentar novamente</span>
166
+ <span className="paragraph-xsmall-medium text-gray-500">
167
+ {translate('common.account.twoFactor.retry')}
168
+ </span>
167
169
  </button>
168
170
  ) : isGenerating || !qrcode ? (
169
171
  <div className="skeleton w-full h-full rounded" />
@@ -171,7 +173,7 @@ export default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFact
171
173
  // eslint-disable-next-line @next/next/no-img-element
172
174
  <img
173
175
  src={qrcode}
174
- alt="QR Code para autenticação de dois fatores"
176
+ alt={translate('common.account.twoFactor.qrAlt')}
175
177
  className="w-full h-full"
176
178
  />
177
179
  )}
@@ -180,7 +182,7 @@ export default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFact
180
182
  <div className="flex items-center gap-3 w-full">
181
183
  <Separator className="flex-1" />
182
184
  <span className="paragraph-xsmall-medium text-gray-500 opacity-80 whitespace-nowrap">
183
- Cole os 6 dígitos abaixo
185
+ {translate('common.account.twoFactor.pasteDigits')}
184
186
  </span>
185
187
  <Separator className="flex-1" />
186
188
  </div>
@@ -203,10 +205,12 @@ export default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFact
203
205
 
204
206
  <div className="shrink-0 flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between gap-2 bg-white">
205
207
  <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
206
- Cancelar
208
+ {translate('common.actions.cancel')}
207
209
  </Button>
208
210
  <Button type="submit" className="h-10!" disabled={!isCodeComplete || isConfirming}>
209
- {isConfirming ? 'Ativando...' : 'Ativar autenticação'}
211
+ {isConfirming
212
+ ? translate('common.account.twoFactor.activating')
213
+ : translate('common.account.twoFactor.activate')}
210
214
  </Button>
211
215
  </div>
212
216
  </form>
@@ -18,9 +18,12 @@ export const TIME_FORMAT_OPTIONS = [
18
18
  { value: '12h', label: '12 horas (AM/PM)', displayValue: '12 horas (AM/PM)' },
19
19
  ];
20
20
 
21
+ // Catalog keys — consumers call translate(type) to get the localized label.
22
+ // pt-br values: 'Atualizações de projetos' | 'Alertas de segurança' |
23
+ // 'Mudanças no plano ou faturamento' | 'Manutenções programadas'
21
24
  export const NOTIFICATION_TYPES = [
22
- 'Atualizações de projetos',
23
- 'Alertas de segurança',
24
- 'Mudanças no plano ou faturamento',
25
- 'Manutenções programadas',
26
- ];
25
+ 'common.account.notificationTypes.projectUpdates',
26
+ 'common.account.notificationTypes.securityAlerts',
27
+ 'common.account.notificationTypes.planBilling',
28
+ 'common.account.notificationTypes.scheduledMaintenance',
29
+ ] as const;