@greatapps/common 1.1.380 → 1.1.381

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 (345) hide show
  1. package/dist/components/account/AccountModals.mjs.map +1 -1
  2. package/dist/components/account/ConfigurationsMyAccountModal.mjs +1 -1
  3. package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -1
  4. package/dist/components/account/ConfirmDeleteAccountModal.mjs.map +1 -1
  5. package/dist/components/account/ConfirmGlobalPreferencesModal.mjs.map +1 -1
  6. package/dist/components/account/DeleteAccountModal.mjs.map +1 -1
  7. package/dist/components/account/DisableTwoFactorAuthModal.mjs.map +1 -1
  8. package/dist/components/account/IsntPossibleDeleteAccountModal.mjs.map +1 -1
  9. package/dist/components/account/TwoFactorAuthModal.mjs.map +1 -1
  10. package/dist/components/account/hooks/useChangePhoneForm.mjs.map +1 -1
  11. package/dist/components/account/hooks/useTwoFactorAuthForm.mjs.map +1 -1
  12. package/dist/components/account/sections/ChangeEmailModal.mjs.map +1 -1
  13. package/dist/components/account/sections/ChangePasswordSection.mjs.map +1 -1
  14. package/dist/components/account/sections/ChangePhoneModal.mjs.map +1 -1
  15. package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
  16. package/dist/components/account/sections/PreferencesSection.mjs.map +1 -1
  17. package/dist/components/account/sections/SecuritySection.mjs.map +1 -1
  18. package/dist/components/embeds/CrispEmbed.mjs.map +1 -1
  19. package/dist/components/embeds/FrillEmbed.mjs.map +1 -1
  20. package/dist/components/handlers/SearchParamsHandler.mjs.map +1 -1
  21. package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
  22. package/dist/components/layouts/AppNavBar.mjs.map +1 -1
  23. package/dist/components/layouts/CollapsibleSidebar.mjs.map +1 -1
  24. package/dist/components/layouts/MdSideBarNavigation.mjs.map +1 -1
  25. package/dist/components/layouts/NavBar.mjs.map +1 -1
  26. package/dist/components/layouts/NotificationsPopover.mjs.map +1 -1
  27. package/dist/components/layouts/ProfilePopover.mjs.map +1 -1
  28. package/dist/components/layouts/SideBarNavigation.mjs.map +1 -1
  29. package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
  30. package/dist/components/layouts/WhitelabelCodes.mjs.map +1 -1
  31. package/dist/components/modals/BuyCreditsModal.mjs.map +1 -1
  32. package/dist/components/modals/ModalManager.mjs.map +1 -1
  33. package/dist/components/modals/Modals.mjs.map +1 -1
  34. package/dist/components/modals/cards/AddCardModal.mjs.map +1 -1
  35. package/dist/components/modals/cards/CardFormFields.mjs.map +1 -1
  36. package/dist/components/navigation/CancelledSubscriptionBanner.mjs.map +1 -1
  37. package/dist/components/navigation/NavItemsContext.mjs.map +1 -1
  38. package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
  39. package/dist/components/navigation/shells/TabsMobileShell.mjs.map +1 -1
  40. package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
  41. package/dist/components/pages/NotFoundPage.mjs.map +1 -1
  42. package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
  43. package/dist/components/ui/buttons/Button.mjs.map +1 -1
  44. package/dist/components/ui/buttons/CancelButton.mjs.map +1 -1
  45. package/dist/components/ui/buttons/CopyButton.mjs.map +1 -1
  46. package/dist/components/ui/data-display/Accordion.mjs.map +1 -1
  47. package/dist/components/ui/data-display/Badge.mjs.map +1 -1
  48. package/dist/components/ui/data-display/Card.mjs.map +1 -1
  49. package/dist/components/ui/data-display/CardBrandIcons.mjs.map +1 -1
  50. package/dist/components/ui/data-display/CardItem.mjs.map +1 -1
  51. package/dist/components/ui/data-display/Pagination.mjs.map +1 -1
  52. package/dist/components/ui/data-display/PaymentInfoCard.mjs.map +1 -1
  53. package/dist/components/ui/data-display/ScrollArea.mjs.map +1 -1
  54. package/dist/components/ui/data-display/Separator.mjs.map +1 -1
  55. package/dist/components/ui/data-display/Table.mjs.map +1 -1
  56. package/dist/components/ui/data-display/Tabs.mjs.map +1 -1
  57. package/dist/components/ui/feedback/CircularProgress.mjs.map +1 -1
  58. package/dist/components/ui/feedback/DefaultCircularProgress.mjs.map +1 -1
  59. package/dist/components/ui/feedback/LoadingOverlay.mjs.map +1 -1
  60. package/dist/components/ui/feedback/Progress.mjs.map +1 -1
  61. package/dist/components/ui/feedback/Skeleton.mjs.map +1 -1
  62. package/dist/components/ui/feedback/Toast.mjs.map +1 -1
  63. package/dist/components/ui/form/Calendar.mjs.map +1 -1
  64. package/dist/components/ui/form/Checkbox.mjs.map +1 -1
  65. package/dist/components/ui/form/ComboboxField.mjs.map +1 -1
  66. package/dist/components/ui/form/DatePicker.mjs.map +1 -1
  67. package/dist/components/ui/form/DateRangePicker.mjs.map +1 -1
  68. package/dist/components/ui/form/FormField.mjs.map +1 -1
  69. package/dist/components/ui/form/Input.mjs.map +1 -1
  70. package/dist/components/ui/form/InputOtp.mjs.map +1 -1
  71. package/dist/components/ui/form/PhoneInput.mjs.map +1 -1
  72. package/dist/components/ui/form/RadioGroup.mjs.map +1 -1
  73. package/dist/components/ui/form/Select.mjs +1 -1
  74. package/dist/components/ui/form/Select.mjs.map +1 -1
  75. package/dist/components/ui/form/Switch.mjs.map +1 -1
  76. package/dist/components/ui/form/Textarea.mjs.map +1 -1
  77. package/dist/components/ui/overlay/Command.mjs.map +1 -1
  78. package/dist/components/ui/overlay/Dialog.mjs.map +1 -1
  79. package/dist/components/ui/overlay/Popover.mjs.map +1 -1
  80. package/dist/components/ui/overlay/Sheet.mjs.map +1 -1
  81. package/dist/components/ui/overlay/Tooltip.mjs.map +1 -1
  82. package/dist/components/widgets/notifications/NotificationCard.mjs.map +1 -1
  83. package/dist/hooks/copy-to-clipboard.hook.mjs.map +1 -1
  84. package/dist/hooks/useDebounce.mjs.map +1 -1
  85. package/dist/hooks/useDebounceState.mjs.map +1 -1
  86. package/dist/hooks/useDebouncedEffect.mjs.map +1 -1
  87. package/dist/index.mjs.map +1 -1
  88. package/dist/infra/utils/clsx.mjs.map +1 -1
  89. package/dist/infra/utils/date.mjs.map +1 -1
  90. package/dist/infra/utils/parser.mjs.map +1 -1
  91. package/dist/infra/utils/percentage.mjs.map +1 -1
  92. package/dist/middleware.mjs.map +1 -1
  93. package/dist/modules/accounts/actions/account-management.action.mjs.map +1 -1
  94. package/dist/modules/accounts/actions/find-current-account.action.mjs.map +1 -1
  95. package/dist/modules/accounts/actions/list-currencies.action.mjs.map +1 -1
  96. package/dist/modules/accounts/actions/list-timezones.action.mjs.map +1 -1
  97. package/dist/modules/accounts/hooks/current-account.hook.mjs.map +1 -1
  98. package/dist/modules/accounts/hooks/useAccountManagement.mjs.map +1 -1
  99. package/dist/modules/accounts/hooks/useCurrencies.mjs.map +1 -1
  100. package/dist/modules/accounts/hooks/useTimezones.mjs.map +1 -1
  101. package/dist/modules/accounts/hooks/useViaCep.mjs.map +1 -1
  102. package/dist/modules/accounts/services/account.service.mjs.map +1 -1
  103. package/dist/modules/accounts/services/two-factor.service.mjs +3 -2
  104. package/dist/modules/accounts/services/two-factor.service.mjs.map +1 -1
  105. package/dist/modules/auth/actions/validate-session.action.mjs.map +1 -1
  106. package/dist/modules/auth/actions/verify-two-factor.action.mjs +2 -2
  107. package/dist/modules/auth/actions/verify-two-factor.action.mjs.map +1 -1
  108. package/dist/modules/auth/hooks/login.hook.mjs.map +1 -1
  109. package/dist/modules/auth/hooks/logout.hook.mjs.map +1 -1
  110. package/dist/modules/auth/hooks/register.hook.mjs.map +1 -1
  111. package/dist/modules/auth/hooks/useManagementPermissions.mjs.map +1 -1
  112. package/dist/modules/auth/hooks/useUserQuery.mjs +2 -2
  113. package/dist/modules/auth/hooks/useUserQuery.mjs.map +1 -1
  114. package/dist/modules/auth/services/auth.service.mjs +3 -2
  115. package/dist/modules/auth/services/auth.service.mjs.map +1 -1
  116. package/dist/modules/auth/utils/assert-management-permission.mjs.map +1 -1
  117. package/dist/modules/auth/utils/assert-management-subscription.mjs.map +1 -1
  118. package/dist/modules/auth/utils/build-wl-override.mjs.map +1 -1
  119. package/dist/modules/cards/actions/create-card.action.mjs.map +1 -1
  120. package/dist/modules/cards/actions/list-cards.action.mjs.map +1 -1
  121. package/dist/modules/cards/hooks/cards.hook.mjs.map +1 -1
  122. package/dist/modules/cards/hooks/create-card.hook.mjs.map +1 -1
  123. package/dist/modules/cards/services/cards.service.mjs.map +1 -1
  124. package/dist/modules/cards/types.mjs.map +1 -1
  125. package/dist/modules/ia-credits/actions/list-ia-credits.action.mjs.map +1 -1
  126. package/dist/modules/plans/actions/find-plan-by-id.action.mjs.map +1 -1
  127. package/dist/modules/plans/hooks/use-has-plan-addon.hook.mjs.map +1 -1
  128. package/dist/modules/plans/hooks/use-plan-by-id.hook.mjs.map +1 -1
  129. package/dist/modules/plans/services/plans.service.mjs.map +1 -1
  130. package/dist/modules/plans/types/plan.type.mjs.map +1 -1
  131. package/dist/modules/projects/actions/add-project-user.action.mjs.map +1 -1
  132. package/dist/modules/projects/actions/list-all-account-users.action.mjs.map +1 -1
  133. package/dist/modules/projects/actions/list-available-users.action.mjs.map +1 -1
  134. package/dist/modules/projects/actions/list-project-users.action.mjs.map +1 -1
  135. package/dist/modules/projects/actions/remove-project-user.action.mjs.map +1 -1
  136. package/dist/modules/projects/hooks/add-project-user.hook.mjs.map +1 -1
  137. package/dist/modules/projects/hooks/list-all-account-users.hook.mjs.map +1 -1
  138. package/dist/modules/projects/hooks/list-available-users.hook.mjs.map +1 -1
  139. package/dist/modules/projects/hooks/list-project-users.hook.mjs.map +1 -1
  140. package/dist/modules/projects/hooks/remove-project-user.hook.mjs.map +1 -1
  141. package/dist/modules/subscriptions/actions/calculate-subscription.action.mjs.map +1 -1
  142. package/dist/modules/subscriptions/actions/list-subscriptions.action.mjs.map +1 -1
  143. package/dist/modules/subscriptions/actions/update-subscription-plan.action.mjs.map +1 -1
  144. package/dist/modules/subscriptions/constants/query-keys.constants.mjs.map +1 -1
  145. package/dist/modules/subscriptions/hooks/calculate-subscription.hook.mjs.map +1 -1
  146. package/dist/modules/subscriptions/hooks/find-active-subscription.hook.mjs.map +1 -1
  147. package/dist/modules/subscriptions/hooks/list-subscriptions.hook.mjs.map +1 -1
  148. package/dist/modules/subscriptions/hooks/update-subscription-plan.hook.mjs.map +1 -1
  149. package/dist/modules/subscriptions/hooks/use-cancelled-subscription-guard.mjs.map +1 -1
  150. package/dist/modules/subscriptions/types/calculate-subscription.type.mjs.map +1 -1
  151. package/dist/modules/subscriptions/utils/build-plan-extras.mjs.map +1 -1
  152. package/dist/modules/subscriptions/utils/has-subscription-expired.mjs.map +1 -1
  153. package/dist/modules/subscriptions/utils/periodicity.mjs.map +1 -1
  154. package/dist/modules/subscriptions/utils/resolve-plan-extras-prices.mjs.map +1 -1
  155. package/dist/modules/users/action/find-user-by-id.action.mjs.map +1 -1
  156. package/dist/modules/users/action/list-messages.action.mjs.map +1 -1
  157. package/dist/modules/users/action/mark-all-messages-as-read.action.mjs.map +1 -1
  158. package/dist/modules/users/action/mark-message-as-read.action.mjs.map +1 -1
  159. package/dist/modules/users/hooks/messages.hook.mjs.map +1 -1
  160. package/dist/modules/users/services/messages.service.mjs.map +1 -1
  161. package/dist/modules/whitelabel/actions/find-whitelabel.action.mjs.map +1 -1
  162. package/dist/modules/whitelabel/actions/revalidate-whitelabel.action.mjs.map +1 -1
  163. package/dist/modules/whitelabel/utils/normalize-hostname.mjs.map +1 -1
  164. package/dist/providers/whitelabel.provider.mjs.map +1 -1
  165. package/dist/store/useAccountModals.mjs.map +1 -1
  166. package/dist/store/useBuyCreditsModal.mjs.map +1 -1
  167. package/dist/store/useDesktopSidebarStore.mjs.map +1 -1
  168. package/dist/store/useMdSidebarStore.mjs.map +1 -1
  169. package/dist/store/useModalManager.mjs.map +1 -1
  170. package/dist/utils/constants/br-states.mjs.map +1 -1
  171. package/dist/utils/countries.mjs.map +1 -1
  172. package/dist/utils/safeServerAction.mjs.map +1 -1
  173. package/dist/utils/withAction.mjs.map +1 -1
  174. package/package.json +89 -89
  175. package/src/components/account/AccountModals.tsx +17 -17
  176. package/src/components/account/ConfigurationsMyAccountModal.tsx +146 -146
  177. package/src/components/account/ConfirmDeleteAccountModal.tsx +55 -55
  178. package/src/components/account/ConfirmGlobalPreferencesModal.tsx +66 -66
  179. package/src/components/account/DeleteAccountModal.tsx +130 -130
  180. package/src/components/account/DisableTwoFactorAuthModal.tsx +86 -86
  181. package/src/components/account/IsntPossibleDeleteAccountModal.tsx +49 -49
  182. package/src/components/account/TwoFactorAuthModal.tsx +215 -215
  183. package/src/components/account/hooks/useChangePhoneForm.tsx +107 -107
  184. package/src/components/account/hooks/useTwoFactorAuthForm.tsx +101 -101
  185. package/src/components/account/sections/ChangeEmailModal.tsx +225 -225
  186. package/src/components/account/sections/ChangePasswordSection.tsx +64 -64
  187. package/src/components/account/sections/ChangePhoneModal.tsx +245 -245
  188. package/src/components/account/sections/MyProfileSection.tsx +327 -327
  189. package/src/components/account/sections/PreferencesSection.tsx +248 -248
  190. package/src/components/account/sections/SecuritySection.tsx +46 -46
  191. package/src/components/embeds/CrispEmbed.tsx +101 -101
  192. package/src/components/embeds/FrillEmbed.tsx +119 -119
  193. package/src/components/handlers/SearchParamsHandler.tsx +61 -61
  194. package/src/components/layouts/AppMobileNavBar.tsx +118 -118
  195. package/src/components/layouts/AppNavBar.tsx +46 -46
  196. package/src/components/layouts/CollapsibleSidebar.tsx +67 -67
  197. package/src/components/layouts/MdSideBarNavigation.tsx +56 -56
  198. package/src/components/layouts/NavBar.tsx +172 -172
  199. package/src/components/layouts/NotificationsPopover.tsx +115 -115
  200. package/src/components/layouts/ProfilePopover.tsx +174 -174
  201. package/src/components/layouts/SideBarNavigation.tsx +62 -62
  202. package/src/components/layouts/UsersSelectorPopover.tsx +234 -234
  203. package/src/components/layouts/WhitelabelCodes.tsx +59 -59
  204. package/src/components/modals/BuyCreditsModal.tsx +314 -314
  205. package/src/components/modals/ModalManager.tsx +29 -29
  206. package/src/components/modals/Modals.tsx +26 -26
  207. package/src/components/modals/cards/AddCardModal.tsx +260 -260
  208. package/src/components/modals/cards/CardFormFields.tsx +294 -294
  209. package/src/components/navigation/CancelledSubscriptionBanner.tsx +60 -60
  210. package/src/components/navigation/NavItemsContext.ts +20 -20
  211. package/src/components/navigation/ProjectSelectorPopover.tsx +194 -194
  212. package/src/components/navigation/shells/TabsMobileShell.tsx +72 -72
  213. package/src/components/navigation/subcomponents/ProjectSelector.tsx +190 -190
  214. package/src/components/pages/NotFoundPage.tsx +67 -67
  215. package/src/components/pages/notifications/Notifications.tsx +160 -160
  216. package/src/components/ui/buttons/Button.tsx +57 -57
  217. package/src/components/ui/buttons/CancelButton.tsx +14 -14
  218. package/src/components/ui/buttons/CopyButton.tsx +54 -54
  219. package/src/components/ui/data-display/Accordion.tsx +81 -81
  220. package/src/components/ui/data-display/Badge.tsx +47 -47
  221. package/src/components/ui/data-display/Card.tsx +93 -93
  222. package/src/components/ui/data-display/CardBrandIcons.tsx +336 -336
  223. package/src/components/ui/data-display/CardItem.tsx +75 -75
  224. package/src/components/ui/data-display/Pagination.tsx +126 -126
  225. package/src/components/ui/data-display/PaymentInfoCard.tsx +186 -186
  226. package/src/components/ui/data-display/ScrollArea.tsx +59 -59
  227. package/src/components/ui/data-display/Separator.tsx +29 -29
  228. package/src/components/ui/data-display/Table.tsx +117 -117
  229. package/src/components/ui/data-display/Tabs.tsx +67 -67
  230. package/src/components/ui/feedback/CircularProgress.tsx +75 -75
  231. package/src/components/ui/feedback/DefaultCircularProgress.tsx +61 -61
  232. package/src/components/ui/feedback/LoadingOverlay.tsx +31 -31
  233. package/src/components/ui/feedback/Progress.tsx +40 -40
  234. package/src/components/ui/feedback/Skeleton.tsx +5 -5
  235. package/src/components/ui/feedback/Toast.tsx +101 -101
  236. package/src/components/ui/form/Calendar.tsx +228 -228
  237. package/src/components/ui/form/Checkbox.tsx +31 -31
  238. package/src/components/ui/form/ComboboxField.tsx +154 -154
  239. package/src/components/ui/form/DatePicker.tsx +97 -97
  240. package/src/components/ui/form/DateRangePicker.tsx +108 -108
  241. package/src/components/ui/form/FormField.tsx +131 -131
  242. package/src/components/ui/form/Input.tsx +20 -20
  243. package/src/components/ui/form/InputOtp.tsx +80 -80
  244. package/src/components/ui/form/PhoneInput.tsx +208 -208
  245. package/src/components/ui/form/RadioGroup.tsx +45 -45
  246. package/src/components/ui/form/Select.tsx +200 -200
  247. package/src/components/ui/form/Switch.tsx +32 -32
  248. package/src/components/ui/form/Textarea.tsx +19 -19
  249. package/src/components/ui/overlay/Command.tsx +185 -185
  250. package/src/components/ui/overlay/Dialog.tsx +151 -151
  251. package/src/components/ui/overlay/Popover.tsx +49 -49
  252. package/src/components/ui/overlay/Sheet.tsx +166 -166
  253. package/src/components/ui/overlay/Tooltip.tsx +62 -62
  254. package/src/components/widgets/notifications/NotificationCard.tsx +68 -68
  255. package/src/hooks/copy-to-clipboard.hook.tsx +67 -67
  256. package/src/hooks/useDebounce.ts +26 -26
  257. package/src/hooks/useDebounceState.ts +11 -11
  258. package/src/hooks/useDebouncedEffect.ts +69 -69
  259. package/src/index.ts +391 -391
  260. package/src/infra/utils/clsx.ts +6 -6
  261. package/src/infra/utils/date.ts +7 -7
  262. package/src/infra/utils/parser.ts +52 -52
  263. package/src/infra/utils/percentage.ts +42 -42
  264. package/src/middleware.ts +4 -4
  265. package/src/modules/accounts/actions/account-management.action.ts +107 -107
  266. package/src/modules/accounts/actions/find-current-account.action.ts +9 -9
  267. package/src/modules/accounts/actions/list-currencies.action.ts +8 -8
  268. package/src/modules/accounts/actions/list-timezones.action.ts +8 -8
  269. package/src/modules/accounts/hooks/current-account.hook.tsx +22 -22
  270. package/src/modules/accounts/hooks/useAccountManagement.ts +85 -85
  271. package/src/modules/accounts/hooks/useCurrencies.ts +15 -15
  272. package/src/modules/accounts/hooks/useTimezones.ts +15 -15
  273. package/src/modules/accounts/hooks/useViaCep.ts +25 -25
  274. package/src/modules/accounts/services/account.service.ts +239 -239
  275. package/src/modules/accounts/services/two-factor.service.ts +3 -2
  276. package/src/modules/accounts/types.ts +225 -225
  277. package/src/modules/auth/actions/validate-session.action.ts +56 -56
  278. package/src/modules/auth/actions/verify-two-factor.action.ts +2 -2
  279. package/src/modules/auth/hooks/login.hook.tsx +13 -13
  280. package/src/modules/auth/hooks/logout.hook.tsx +11 -11
  281. package/src/modules/auth/hooks/register.hook.tsx +11 -11
  282. package/src/modules/auth/hooks/useManagementPermissions.ts +45 -45
  283. package/src/modules/auth/hooks/useUserQuery.ts +2 -2
  284. package/src/modules/auth/services/auth.service.ts +3 -1
  285. package/src/modules/auth/types/management-permission.type.ts +7 -7
  286. package/src/modules/auth/utils/assert-management-permission.ts +46 -46
  287. package/src/modules/auth/utils/assert-management-subscription.ts +27 -27
  288. package/src/modules/auth/utils/build-wl-override.ts +43 -43
  289. package/src/modules/cards/actions/create-card.action.ts +9 -9
  290. package/src/modules/cards/actions/list-cards.action.ts +8 -8
  291. package/src/modules/cards/hooks/cards.hook.ts +14 -14
  292. package/src/modules/cards/hooks/create-card.hook.ts +18 -18
  293. package/src/modules/cards/services/cards.service.ts +51 -51
  294. package/src/modules/cards/types.ts +32 -32
  295. package/src/modules/ia-credits/actions/list-ia-credits.action.ts +8 -8
  296. package/src/modules/plans/actions/find-plan-by-id.action.ts +8 -8
  297. package/src/modules/plans/hooks/use-has-plan-addon.hook.ts +17 -17
  298. package/src/modules/plans/hooks/use-plan-by-id.hook.ts +13 -13
  299. package/src/modules/plans/services/plans.service.ts +36 -36
  300. package/src/modules/plans/types/plan.type.ts +21 -21
  301. package/src/modules/projects/actions/add-project-user.action.ts +9 -9
  302. package/src/modules/projects/actions/list-all-account-users.action.ts +9 -9
  303. package/src/modules/projects/actions/list-available-users.action.ts +9 -9
  304. package/src/modules/projects/actions/list-project-users.action.ts +9 -9
  305. package/src/modules/projects/actions/remove-project-user.action.ts +9 -9
  306. package/src/modules/projects/hooks/add-project-user.hook.ts +69 -69
  307. package/src/modules/projects/hooks/list-all-account-users.hook.ts +34 -34
  308. package/src/modules/projects/hooks/list-available-users.hook.ts +33 -33
  309. package/src/modules/projects/hooks/list-project-users.hook.ts +33 -33
  310. package/src/modules/projects/hooks/remove-project-user.hook.ts +69 -69
  311. package/src/modules/subscriptions/actions/calculate-subscription.action.ts +9 -9
  312. package/src/modules/subscriptions/actions/list-subscriptions.action.ts +9 -9
  313. package/src/modules/subscriptions/actions/update-subscription-plan.action.ts +14 -14
  314. package/src/modules/subscriptions/constants/query-keys.constants.ts +1 -1
  315. package/src/modules/subscriptions/hooks/calculate-subscription.hook.ts +13 -13
  316. package/src/modules/subscriptions/hooks/find-active-subscription.hook.ts +19 -19
  317. package/src/modules/subscriptions/hooks/list-subscriptions.hook.ts +16 -16
  318. package/src/modules/subscriptions/hooks/update-subscription-plan.hook.ts +25 -25
  319. package/src/modules/subscriptions/hooks/use-cancelled-subscription-guard.ts +39 -39
  320. package/src/modules/subscriptions/types/billing-period.type.ts +1 -1
  321. package/src/modules/subscriptions/types/calculate-subscription.type.ts +75 -75
  322. package/src/modules/subscriptions/utils/build-plan-extras.ts +56 -56
  323. package/src/modules/subscriptions/utils/has-subscription-expired.ts +8 -8
  324. package/src/modules/subscriptions/utils/periodicity.ts +52 -52
  325. package/src/modules/subscriptions/utils/resolve-plan-extras-prices.ts +23 -23
  326. package/src/modules/users/action/find-user-by-id.action.ts +8 -8
  327. package/src/modules/users/action/list-messages.action.ts +12 -12
  328. package/src/modules/users/action/mark-all-messages-as-read.action.ts +8 -8
  329. package/src/modules/users/action/mark-message-as-read.action.ts +8 -8
  330. package/src/modules/users/hooks/messages.hook.ts +60 -60
  331. package/src/modules/users/services/messages.service.ts +48 -48
  332. package/src/modules/whitelabel/actions/find-whitelabel.action.ts +23 -23
  333. package/src/modules/whitelabel/actions/revalidate-whitelabel.action.ts +19 -19
  334. package/src/modules/whitelabel/schema.ts +84 -84
  335. package/src/modules/whitelabel/utils/normalize-hostname.ts +26 -26
  336. package/src/providers/whitelabel.provider.tsx +54 -54
  337. package/src/store/useAccountModals.ts +55 -55
  338. package/src/store/useBuyCreditsModal.ts +21 -21
  339. package/src/store/useDesktopSidebarStore.ts +47 -47
  340. package/src/store/useMdSidebarStore.ts +34 -34
  341. package/src/store/useModalManager.ts +104 -104
  342. package/src/utils/constants/br-states.ts +29 -29
  343. package/src/utils/countries.ts +224 -224
  344. package/src/utils/safeServerAction.ts +21 -21
  345. package/src/utils/withAction.ts +13 -13
@@ -1,215 +1,215 @@
1
- 'use client';
2
-
3
- import { IconX, IconCopy, IconRefresh } from '@tabler/icons-react';
4
- import { Button } from '../ui/buttons/Button';
5
- import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';
6
- import { Separator } from '../ui/data-display/Separator';
7
- import { InputOTP, InputOTPGroup, InputOTPSlot } from '../ui/form/InputOtp';
8
- import useTwoFactorAuthForm from './hooks/useTwoFactorAuthForm';
9
-
10
- interface TwoFactorAuthModalProps {
11
- open: boolean;
12
- onClose: () => void;
13
- onSuccess?: () => void;
14
- }
15
-
16
- export default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFactorAuthModalProps) {
17
- const {
18
- code,
19
- setCode,
20
- isCodeComplete,
21
- isGenerating,
22
- isConfirming,
23
- generateFailed,
24
- retryGenerate,
25
- qrcode,
26
- backupCodes,
27
- step,
28
- handleSubmit,
29
- handleFinalize,
30
- handleCopyCodes,
31
- resetForm,
32
- } = useTwoFactorAuthForm({ onSuccess, open });
33
-
34
- const handleClose = () => {
35
- resetForm();
36
- onClose();
37
- };
38
-
39
- if (step === 'recovery') {
40
- return (
41
- <Dialog open={open} onOpenChange={handleClose}>
42
- <DialogContent
43
- showCloseButton={false}
44
- overlayClassName="z-[1010]"
45
- 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%]"
46
- >
47
- <DialogHeader className="sr-only">
48
- <DialogTitle>Códigos de segurança</DialogTitle>
49
- </DialogHeader>
50
- <div className="flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0">
51
- <span className="paragraph-medium-semibold text-gray-950 text-center">
52
- Códigos de segurança
53
- </span>
54
- <Button
55
- type="button"
56
- variant="ghost"
57
- className="size-8! p-0 absolute right-4"
58
- onClick={handleClose}
59
- >
60
- <IconX size={18} />
61
- </Button>
62
- </div>
63
-
64
- <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">
65
- <div className="flex flex-col gap-2">
66
- <h3 className="paragraph-medium-semibold text-gray-950 max-w-[269px]">
67
- Salve estes códigos de recuperação de emergência
68
- </h3>
69
- <div className="paragraph-small-regular text-gray-600">
70
- <p>
71
- Se você perder acesso ao seu telefone, não será possível fazer login em sua conta
72
- sem um código de dois fatores.
73
- </p>
74
- <br />
75
- <p>Imprima, copie ou escreva em um local seguro os códigos abaixo.</p>
76
- </div>
77
- </div>
78
-
79
- <div className="bg-gray-50 rounded-lg p-4 flex flex-col gap-4">
80
- <div className="paragraph-small-medium text-gray-950 whitespace-nowrap">
81
- {backupCodes.map((backupCode, i) => (
82
- <p key={i}>{backupCode}</p>
83
- ))}
84
- </div>
85
- <Button
86
- type="button"
87
- variant="secondary"
88
- className="h-8! w-fit"
89
- onClick={handleCopyCodes}
90
- >
91
- <IconCopy size={16} />
92
- Copiar códigos
93
- </Button>
94
- </div>
95
- </div>
96
-
97
- <div className="flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between mt-auto lg:mt-0">
98
- <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
99
- Cancelar
100
- </Button>
101
- <Button className="h-10!" type="button" onClick={handleFinalize}>
102
- Finalizar
103
- </Button>
104
- </div>
105
- </DialogContent>
106
- </Dialog>
107
- );
108
- }
109
-
110
- return (
111
- <Dialog open={open} onOpenChange={handleClose}>
112
- <DialogContent
113
- showCloseButton={false}
114
- overlayClassName="z-[1010]"
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%]"
116
- >
117
- <DialogHeader className="sr-only">
118
- <DialogTitle>Autenticação de dois fatores</DialogTitle>
119
- </DialogHeader>
120
- <div className="shrink-0 flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0">
121
- <span className="paragraph-medium-semibold text-gray-950 text-center">
122
- Autenticação de dois fatores
123
- </span>
124
- <Button
125
- type="button"
126
- variant="ghost"
127
- className="size-8! p-0 absolute right-4"
128
- onClick={handleClose}
129
- >
130
- <IconX size={18} />
131
- </Button>
132
- </div>
133
-
134
- <form
135
- className="flex-1 min-h-0 flex flex-col"
136
- onSubmit={(e) => {
137
- e.preventDefault();
138
- if (isCodeComplete) handleSubmit();
139
- }}
140
- >
141
- <div className="flex-1 min-h-0 overflow-y-auto overscroll-contain lg:overflow-visible">
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">
143
- <p className="paragraph-small-regular text-gray-950 text-center max-w-full lg:max-w-[412px]">
144
- Instale um aplicativo autenticador no seu celular (ex.:{' '}
145
- <a
146
- href="https://support.google.com/accounts/answer/1066447"
147
- target="_blank"
148
- rel="noopener noreferrer"
149
- className="paragraph-small-medium underline"
150
- >
151
- Google Authenticator
152
- </a>
153
- ), escaneie o QR Code ao lado ou copie a chave no aplicativo e, em seguida, digite o
154
- código de 6 dígitos gerado para continuar.
155
- </p>
156
-
157
- <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]">
158
- {generateFailed ? (
159
- <button
160
- type="button"
161
- onClick={() => retryGenerate()}
162
- className="flex flex-col items-center gap-1.5 text-center"
163
- >
164
- <IconRefresh size={20} className="text-gray-400" />
165
- <span className="paragraph-xsmall-medium text-gray-500">Tentar novamente</span>
166
- </button>
167
- ) : isGenerating || !qrcode ? (
168
- <div className="skeleton w-full h-full rounded" />
169
- ) : (
170
- // eslint-disable-next-line @next/next/no-img-element
171
- <img
172
- src={qrcode}
173
- alt="QR Code para autenticação de dois fatores"
174
- className="w-full h-full"
175
- />
176
- )}
177
- </div>
178
-
179
- <div className="flex items-center gap-3 w-full">
180
- <Separator className="flex-1" />
181
- <span className="paragraph-xsmall-medium text-gray-500 opacity-80 whitespace-nowrap">
182
- Cole os 6 dígitos abaixo
183
- </span>
184
- <Separator className="flex-1" />
185
- </div>
186
-
187
- <div className="scroll-mt-20">
188
- <InputOTP maxLength={6} value={code} onChange={setCode}>
189
- <InputOTPGroup className="gap-2">
190
- {Array.from({ length: 6 }).map((_, i) => (
191
- <InputOTPSlot
192
- key={i}
193
- index={i}
194
- className="w-11! lg:w-12! h-13! lg:h-14! rounded-lg! text-lg border-gray-200"
195
- />
196
- ))}
197
- </InputOTPGroup>
198
- </InputOTP>
199
- </div>
200
- </div>
201
- </div>
202
-
203
- <div className="shrink-0 flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between gap-2 bg-white">
204
- <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
205
- Cancelar
206
- </Button>
207
- <Button type="submit" className="h-10!" disabled={!isCodeComplete || isConfirming}>
208
- {isConfirming ? 'Ativando...' : 'Ativar autenticação'}
209
- </Button>
210
- </div>
211
- </form>
212
- </DialogContent>
213
- </Dialog>
214
- );
215
- }
1
+ 'use client';
2
+
3
+ import { IconX, IconCopy, IconRefresh } from '@tabler/icons-react';
4
+ import { Button } from '../ui/buttons/Button';
5
+ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';
6
+ import { Separator } from '../ui/data-display/Separator';
7
+ import { InputOTP, InputOTPGroup, InputOTPSlot } from '../ui/form/InputOtp';
8
+ import useTwoFactorAuthForm from './hooks/useTwoFactorAuthForm';
9
+
10
+ interface TwoFactorAuthModalProps {
11
+ open: boolean;
12
+ onClose: () => void;
13
+ onSuccess?: () => void;
14
+ }
15
+
16
+ export default function TwoFactorAuthModal({ open, onClose, onSuccess }: TwoFactorAuthModalProps) {
17
+ const {
18
+ code,
19
+ setCode,
20
+ isCodeComplete,
21
+ isGenerating,
22
+ isConfirming,
23
+ generateFailed,
24
+ retryGenerate,
25
+ qrcode,
26
+ backupCodes,
27
+ step,
28
+ handleSubmit,
29
+ handleFinalize,
30
+ handleCopyCodes,
31
+ resetForm,
32
+ } = useTwoFactorAuthForm({ onSuccess, open });
33
+
34
+ const handleClose = () => {
35
+ resetForm();
36
+ onClose();
37
+ };
38
+
39
+ if (step === 'recovery') {
40
+ return (
41
+ <Dialog open={open} onOpenChange={handleClose}>
42
+ <DialogContent
43
+ showCloseButton={false}
44
+ overlayClassName="z-[1010]"
45
+ 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%]"
46
+ >
47
+ <DialogHeader className="sr-only">
48
+ <DialogTitle>Códigos de segurança</DialogTitle>
49
+ </DialogHeader>
50
+ <div className="flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0">
51
+ <span className="paragraph-medium-semibold text-gray-950 text-center">
52
+ Códigos de segurança
53
+ </span>
54
+ <Button
55
+ type="button"
56
+ variant="ghost"
57
+ className="size-8! p-0 absolute right-4"
58
+ onClick={handleClose}
59
+ >
60
+ <IconX size={18} />
61
+ </Button>
62
+ </div>
63
+
64
+ <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">
65
+ <div className="flex flex-col gap-2">
66
+ <h3 className="paragraph-medium-semibold text-gray-950 max-w-[269px]">
67
+ Salve estes códigos de recuperação de emergência
68
+ </h3>
69
+ <div className="paragraph-small-regular text-gray-600">
70
+ <p>
71
+ Se você perder acesso ao seu telefone, não será possível fazer login em sua conta
72
+ sem um código de dois fatores.
73
+ </p>
74
+ <br />
75
+ <p>Imprima, copie ou escreva em um local seguro os códigos abaixo.</p>
76
+ </div>
77
+ </div>
78
+
79
+ <div className="bg-gray-50 rounded-lg p-4 flex flex-col gap-4">
80
+ <div className="paragraph-small-medium text-gray-950 whitespace-nowrap">
81
+ {backupCodes.map((backupCode, i) => (
82
+ <p key={i}>{backupCode}</p>
83
+ ))}
84
+ </div>
85
+ <Button
86
+ type="button"
87
+ variant="secondary"
88
+ className="h-8! w-fit"
89
+ onClick={handleCopyCodes}
90
+ >
91
+ <IconCopy size={16} />
92
+ Copiar códigos
93
+ </Button>
94
+ </div>
95
+ </div>
96
+
97
+ <div className="flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between mt-auto lg:mt-0">
98
+ <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
99
+ Cancelar
100
+ </Button>
101
+ <Button className="h-10!" type="button" onClick={handleFinalize}>
102
+ Finalizar
103
+ </Button>
104
+ </div>
105
+ </DialogContent>
106
+ </Dialog>
107
+ );
108
+ }
109
+
110
+ return (
111
+ <Dialog open={open} onOpenChange={handleClose}>
112
+ <DialogContent
113
+ showCloseButton={false}
114
+ overlayClassName="z-[1010]"
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%]"
116
+ >
117
+ <DialogHeader className="sr-only">
118
+ <DialogTitle>Autenticação de dois fatores</DialogTitle>
119
+ </DialogHeader>
120
+ <div className="shrink-0 flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0">
121
+ <span className="paragraph-medium-semibold text-gray-950 text-center">
122
+ Autenticação de dois fatores
123
+ </span>
124
+ <Button
125
+ type="button"
126
+ variant="ghost"
127
+ className="size-8! p-0 absolute right-4"
128
+ onClick={handleClose}
129
+ >
130
+ <IconX size={18} />
131
+ </Button>
132
+ </div>
133
+
134
+ <form
135
+ className="flex-1 min-h-0 flex flex-col"
136
+ onSubmit={(e) => {
137
+ e.preventDefault();
138
+ if (isCodeComplete) handleSubmit();
139
+ }}
140
+ >
141
+ <div className="flex-1 min-h-0 overflow-y-auto overscroll-contain lg:overflow-visible">
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">
143
+ <p className="paragraph-small-regular text-gray-950 text-center max-w-full lg:max-w-[412px]">
144
+ Instale um aplicativo autenticador no seu celular (ex.:{' '}
145
+ <a
146
+ href="https://support.google.com/accounts/answer/1066447"
147
+ target="_blank"
148
+ rel="noopener noreferrer"
149
+ className="paragraph-small-medium underline"
150
+ >
151
+ Google Authenticator
152
+ </a>
153
+ ), escaneie o QR Code ao lado ou copie a chave no aplicativo e, em seguida, digite o
154
+ código de 6 dígitos gerado para continuar.
155
+ </p>
156
+
157
+ <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]">
158
+ {generateFailed ? (
159
+ <button
160
+ type="button"
161
+ onClick={() => retryGenerate()}
162
+ className="flex flex-col items-center gap-1.5 text-center"
163
+ >
164
+ <IconRefresh size={20} className="text-gray-400" />
165
+ <span className="paragraph-xsmall-medium text-gray-500">Tentar novamente</span>
166
+ </button>
167
+ ) : isGenerating || !qrcode ? (
168
+ <div className="skeleton w-full h-full rounded" />
169
+ ) : (
170
+ // eslint-disable-next-line @next/next/no-img-element
171
+ <img
172
+ src={qrcode}
173
+ alt="QR Code para autenticação de dois fatores"
174
+ className="w-full h-full"
175
+ />
176
+ )}
177
+ </div>
178
+
179
+ <div className="flex items-center gap-3 w-full">
180
+ <Separator className="flex-1" />
181
+ <span className="paragraph-xsmall-medium text-gray-500 opacity-80 whitespace-nowrap">
182
+ Cole os 6 dígitos abaixo
183
+ </span>
184
+ <Separator className="flex-1" />
185
+ </div>
186
+
187
+ <div className="scroll-mt-20">
188
+ <InputOTP maxLength={6} value={code} onChange={setCode}>
189
+ <InputOTPGroup className="gap-2">
190
+ {Array.from({ length: 6 }).map((_, i) => (
191
+ <InputOTPSlot
192
+ key={i}
193
+ index={i}
194
+ className="w-11! lg:w-12! h-13! lg:h-14! rounded-lg! text-lg border-gray-200"
195
+ />
196
+ ))}
197
+ </InputOTPGroup>
198
+ </InputOTP>
199
+ </div>
200
+ </div>
201
+ </div>
202
+
203
+ <div className="shrink-0 flex items-center p-4 lg:p-5 border-t border-gray-200 justify-between gap-2 bg-white">
204
+ <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
205
+ Cancelar
206
+ </Button>
207
+ <Button type="submit" className="h-10!" disabled={!isCodeComplete || isConfirming}>
208
+ {isConfirming ? 'Ativando...' : 'Ativar autenticação'}
209
+ </Button>
210
+ </div>
211
+ </form>
212
+ </DialogContent>
213
+ </Dialog>
214
+ );
215
+ }
@@ -1,107 +1,107 @@
1
- 'use client';
2
-
3
- import { useState, useCallback } from 'react';
4
- import { toast } from 'sonner';
5
- import { Toast } from '../../ui/feedback/Toast';
6
- import { requestPhoneChangeAction, updateUserAction } from '../../../modules/accounts/actions/account-management.action';
7
-
8
- function splitPhoneValue(fullValue: string): { ddi: string; local: string } {
9
- const trimmed = fullValue.trim();
10
- const spaceIdx = trimmed.indexOf(' ');
11
- if (spaceIdx === -1) return { ddi: '+55', local: trimmed };
12
- return { ddi: trimmed.slice(0, spaceIdx), local: trimmed.slice(spaceIdx + 1) };
13
- }
14
-
15
- interface UseChangePhoneFormOptions {
16
- hasExistingPhone: boolean;
17
- onDirectUpdateSuccess?: () => void;
18
- }
19
-
20
- export default function useChangePhoneForm({ hasExistingPhone, onDirectUpdateSuccess }: UseChangePhoneFormOptions) {
21
- const [showVerification, setShowVerification] = useState(false);
22
- const [phoneValue, setPhoneValue] = useState('');
23
- const [phoneError, setPhoneError] = useState('');
24
- const [isSubmitting, setIsSubmitting] = useState(false);
25
- const [submittedPhone, setSubmittedPhone] = useState({ ddi: '+55', local: '' });
26
-
27
- const handlePhoneChange = useCallback((value: string) => {
28
- setPhoneValue(value);
29
- if (phoneError) setPhoneError('');
30
- }, [phoneError]);
31
-
32
- const handleContinue = useCallback(async (e: React.FormEvent) => {
33
- e.preventDefault();
34
-
35
- const { ddi, local } = splitPhoneValue(phoneValue);
36
-
37
- if (!local || local.replace(/\D/g, '').length < 8) {
38
- setPhoneError('Número de telefone inválido');
39
- return;
40
- }
41
-
42
- setIsSubmitting(true);
43
- try {
44
- if (!hasExistingPhone) {
45
- const result = await updateUserAction({ phone: local, ddi });
46
-
47
- if (!result.success) {
48
- toast.custom((t) => (
49
- <Toast
50
- variant="error"
51
- message={result.error ?? 'Ocorreu um erro ao salvar o telefone. Tente novamente mais tarde.'}
52
- toastId={t}
53
- />
54
- ));
55
- return;
56
- }
57
-
58
- toast.custom((t) => (
59
- <Toast variant="success" message="Telefone adicionado" toastId={t} />
60
- ));
61
- onDirectUpdateSuccess?.();
62
- return;
63
- }
64
-
65
- const result = await requestPhoneChangeAction(local, ddi);
66
-
67
- if (!result.success) {
68
- toast.custom((t) => (
69
- <Toast
70
- variant="error"
71
- message={result.error ?? 'Número já existente ou ocorreu um erro. Tente novamente mais tarde.'}
72
- toastId={t}
73
- />
74
- ));
75
- return;
76
- }
77
-
78
- setSubmittedPhone({ ddi, local });
79
- setShowVerification(true);
80
- } finally {
81
- setIsSubmitting(false);
82
- }
83
- }, [phoneValue, hasExistingPhone, onDirectUpdateSuccess]);
84
-
85
- const handleBack = useCallback(() => {
86
- setShowVerification(false);
87
- }, []);
88
-
89
- const resetForm = useCallback(() => {
90
- setPhoneValue('');
91
- setPhoneError('');
92
- setSubmittedPhone({ ddi: '+55', local: '' });
93
- setShowVerification(false);
94
- }, []);
95
-
96
- return {
97
- showVerification,
98
- phoneValue,
99
- phoneError,
100
- isSubmitting,
101
- submittedPhone,
102
- handlePhoneChange,
103
- handleContinue,
104
- handleBack,
105
- resetForm,
106
- };
107
- }
1
+ 'use client';
2
+
3
+ import { useState, useCallback } from 'react';
4
+ import { toast } from 'sonner';
5
+ import { Toast } from '../../ui/feedback/Toast';
6
+ import { requestPhoneChangeAction, updateUserAction } from '../../../modules/accounts/actions/account-management.action';
7
+
8
+ function splitPhoneValue(fullValue: string): { ddi: string; local: string } {
9
+ const trimmed = fullValue.trim();
10
+ const spaceIdx = trimmed.indexOf(' ');
11
+ if (spaceIdx === -1) return { ddi: '+55', local: trimmed };
12
+ return { ddi: trimmed.slice(0, spaceIdx), local: trimmed.slice(spaceIdx + 1) };
13
+ }
14
+
15
+ interface UseChangePhoneFormOptions {
16
+ hasExistingPhone: boolean;
17
+ onDirectUpdateSuccess?: () => void;
18
+ }
19
+
20
+ export default function useChangePhoneForm({ hasExistingPhone, onDirectUpdateSuccess }: UseChangePhoneFormOptions) {
21
+ const [showVerification, setShowVerification] = useState(false);
22
+ const [phoneValue, setPhoneValue] = useState('');
23
+ const [phoneError, setPhoneError] = useState('');
24
+ const [isSubmitting, setIsSubmitting] = useState(false);
25
+ const [submittedPhone, setSubmittedPhone] = useState({ ddi: '+55', local: '' });
26
+
27
+ const handlePhoneChange = useCallback((value: string) => {
28
+ setPhoneValue(value);
29
+ if (phoneError) setPhoneError('');
30
+ }, [phoneError]);
31
+
32
+ const handleContinue = useCallback(async (e: React.FormEvent) => {
33
+ e.preventDefault();
34
+
35
+ const { ddi, local } = splitPhoneValue(phoneValue);
36
+
37
+ if (!local || local.replace(/\D/g, '').length < 8) {
38
+ setPhoneError('Número de telefone inválido');
39
+ return;
40
+ }
41
+
42
+ setIsSubmitting(true);
43
+ try {
44
+ if (!hasExistingPhone) {
45
+ const result = await updateUserAction({ phone: local, ddi });
46
+
47
+ if (!result.success) {
48
+ toast.custom((t) => (
49
+ <Toast
50
+ variant="error"
51
+ message={result.error ?? 'Ocorreu um erro ao salvar o telefone. Tente novamente mais tarde.'}
52
+ toastId={t}
53
+ />
54
+ ));
55
+ return;
56
+ }
57
+
58
+ toast.custom((t) => (
59
+ <Toast variant="success" message="Telefone adicionado" toastId={t} />
60
+ ));
61
+ onDirectUpdateSuccess?.();
62
+ return;
63
+ }
64
+
65
+ const result = await requestPhoneChangeAction(local, ddi);
66
+
67
+ if (!result.success) {
68
+ toast.custom((t) => (
69
+ <Toast
70
+ variant="error"
71
+ message={result.error ?? 'Número já existente ou ocorreu um erro. Tente novamente mais tarde.'}
72
+ toastId={t}
73
+ />
74
+ ));
75
+ return;
76
+ }
77
+
78
+ setSubmittedPhone({ ddi, local });
79
+ setShowVerification(true);
80
+ } finally {
81
+ setIsSubmitting(false);
82
+ }
83
+ }, [phoneValue, hasExistingPhone, onDirectUpdateSuccess]);
84
+
85
+ const handleBack = useCallback(() => {
86
+ setShowVerification(false);
87
+ }, []);
88
+
89
+ const resetForm = useCallback(() => {
90
+ setPhoneValue('');
91
+ setPhoneError('');
92
+ setSubmittedPhone({ ddi: '+55', local: '' });
93
+ setShowVerification(false);
94
+ }, []);
95
+
96
+ return {
97
+ showVerification,
98
+ phoneValue,
99
+ phoneError,
100
+ isSubmitting,
101
+ submittedPhone,
102
+ handlePhoneChange,
103
+ handleContinue,
104
+ handleBack,
105
+ resetForm,
106
+ };
107
+ }