@greatapps/common 1.1.234 → 1.1.237

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 (227) hide show
  1. package/dist/components/account/ConfigurationsMyAccountModal.mjs +1 -1
  2. package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -1
  3. package/dist/components/account/ConfirmDeleteAccountModal.mjs.map +1 -1
  4. package/dist/components/account/ConfirmGlobalPreferencesModal.mjs.map +1 -1
  5. package/dist/components/account/DeleteAccountModal.mjs.map +1 -1
  6. package/dist/components/account/DisableTwoFactorAuthModal.mjs.map +1 -1
  7. package/dist/components/account/IsntPossibleDeleteAccountModal.mjs.map +1 -1
  8. package/dist/components/account/TwoFactorAuthModal.mjs.map +1 -1
  9. package/dist/components/account/hooks/useChangePhoneForm.mjs.map +1 -1
  10. package/dist/components/account/hooks/useTwoFactorAuthForm.mjs.map +1 -1
  11. package/dist/components/account/sections/ChangeEmailModal.mjs.map +1 -1
  12. package/dist/components/account/sections/ChangePasswordSection.mjs.map +1 -1
  13. package/dist/components/account/sections/ChangePhoneModal.mjs.map +1 -1
  14. package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
  15. package/dist/components/account/sections/PreferencesSection.mjs.map +1 -1
  16. package/dist/components/account/sections/SecuritySection.mjs.map +1 -1
  17. package/dist/components/embeds/CrispEmbed.mjs.map +1 -1
  18. package/dist/components/embeds/FrillEmbed.mjs.map +1 -1
  19. package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
  20. package/dist/components/layouts/AppNavBar.mjs.map +1 -1
  21. package/dist/components/layouts/MdSideBarNavigation.mjs.map +1 -1
  22. package/dist/components/layouts/NavBar.mjs +3 -3
  23. package/dist/components/layouts/NavBar.mjs.map +1 -1
  24. package/dist/components/layouts/NotificationsPopover.mjs.map +1 -1
  25. package/dist/components/layouts/ProfilePopover.mjs.map +1 -1
  26. package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
  27. package/dist/components/navigation/CancelledSubscriptionBanner.mjs.map +1 -1
  28. package/dist/components/navigation/NavItemsContext.mjs.map +1 -1
  29. package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
  30. package/dist/components/navigation/shells/TabsMobileShell.mjs.map +1 -1
  31. package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
  32. package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
  33. package/dist/components/ui/buttons/Button.mjs.map +1 -1
  34. package/dist/components/ui/buttons/CancelButton.mjs.map +1 -1
  35. package/dist/components/ui/buttons/CopyButton.mjs.map +1 -1
  36. package/dist/components/ui/data-display/Accordion.mjs.map +1 -1
  37. package/dist/components/ui/data-display/Badge.mjs.map +1 -1
  38. package/dist/components/ui/data-display/Card.mjs.map +1 -1
  39. package/dist/components/ui/data-display/Pagination.mjs.map +1 -1
  40. package/dist/components/ui/data-display/ScrollArea.mjs.map +1 -1
  41. package/dist/components/ui/data-display/Separator.mjs.map +1 -1
  42. package/dist/components/ui/data-display/Table.mjs.map +1 -1
  43. package/dist/components/ui/data-display/Tabs.mjs.map +1 -1
  44. package/dist/components/ui/feedback/CircularProgress.mjs.map +1 -1
  45. package/dist/components/ui/feedback/DefaultCircularProgress.mjs.map +1 -1
  46. package/dist/components/ui/feedback/LoadingOverlay.mjs.map +1 -1
  47. package/dist/components/ui/feedback/Progress.mjs.map +1 -1
  48. package/dist/components/ui/feedback/Toast.mjs.map +1 -1
  49. package/dist/components/ui/form/Calendar.mjs.map +1 -1
  50. package/dist/components/ui/form/Checkbox.mjs.map +1 -1
  51. package/dist/components/ui/form/ComboboxField.mjs.map +1 -1
  52. package/dist/components/ui/form/DatePicker.mjs.map +1 -1
  53. package/dist/components/ui/form/DateRangePicker.mjs.map +1 -1
  54. package/dist/components/ui/form/FormField.mjs.map +1 -1
  55. package/dist/components/ui/form/Input.mjs.map +1 -1
  56. package/dist/components/ui/form/InputOtp.mjs.map +1 -1
  57. package/dist/components/ui/form/PhoneInput.mjs.map +1 -1
  58. package/dist/components/ui/form/RadioGroup.mjs.map +1 -1
  59. package/dist/components/ui/form/Select.mjs +1 -1
  60. package/dist/components/ui/form/Select.mjs.map +1 -1
  61. package/dist/components/ui/form/Switch.mjs.map +1 -1
  62. package/dist/components/ui/form/Textarea.mjs.map +1 -1
  63. package/dist/components/ui/overlay/Command.mjs.map +1 -1
  64. package/dist/components/ui/overlay/Dialog.mjs.map +1 -1
  65. package/dist/components/ui/overlay/Popover.mjs.map +1 -1
  66. package/dist/components/ui/overlay/Sheet.mjs.map +1 -1
  67. package/dist/components/ui/overlay/Tooltip.mjs.map +1 -1
  68. package/dist/hooks/copy-to-clipboard.hook.mjs.map +1 -1
  69. package/dist/index.mjs.map +1 -1
  70. package/dist/middleware.mjs.map +1 -1
  71. package/dist/modules/accounts/actions/account-management.action.mjs +1 -0
  72. package/dist/modules/accounts/actions/account-management.action.mjs.map +1 -1
  73. package/dist/modules/accounts/actions/find-current-account.action.mjs.map +1 -1
  74. package/dist/modules/accounts/actions/list-currencies.action.mjs.map +1 -1
  75. package/dist/modules/accounts/actions/list-timezones.action.mjs.map +1 -1
  76. package/dist/modules/accounts/hooks/current-account.hook.mjs.map +1 -1
  77. package/dist/modules/accounts/hooks/useAccountManagement.mjs.map +1 -1
  78. package/dist/modules/accounts/hooks/useCurrencies.mjs.map +1 -1
  79. package/dist/modules/accounts/hooks/useTimezones.mjs.map +1 -1
  80. package/dist/modules/accounts/services/account.service.mjs.map +1 -1
  81. package/dist/modules/auth/hooks/login.hook.mjs.map +1 -1
  82. package/dist/modules/auth/hooks/logout.hook.mjs.map +1 -1
  83. package/dist/modules/auth/hooks/register.hook.mjs.map +1 -1
  84. package/dist/modules/ia-credits/actions/list-ia-credits.action.mjs.map +1 -1
  85. package/dist/modules/projects/actions/add-project-user.action.mjs.map +1 -1
  86. package/dist/modules/projects/actions/list-all-account-users.action.mjs.map +1 -1
  87. package/dist/modules/projects/actions/list-available-users.action.mjs.map +1 -1
  88. package/dist/modules/projects/actions/list-project-users.action.mjs.map +1 -1
  89. package/dist/modules/projects/actions/remove-project-user.action.mjs.map +1 -1
  90. package/dist/modules/projects/hooks/add-project-user.hook.mjs.map +1 -1
  91. package/dist/modules/projects/hooks/list-all-account-users.hook.mjs.map +1 -1
  92. package/dist/modules/projects/hooks/list-available-users.hook.mjs.map +1 -1
  93. package/dist/modules/projects/hooks/list-project-users.hook.mjs.map +1 -1
  94. package/dist/modules/projects/hooks/remove-project-user.hook.mjs.map +1 -1
  95. package/dist/modules/subscriptions/actions/find-plan-by-id.action.mjs.map +1 -1
  96. package/dist/modules/subscriptions/actions/list-subscriptions.action.mjs.map +1 -1
  97. package/dist/modules/subscriptions/hooks/find-active-subscription.hook.mjs.map +1 -1
  98. package/dist/modules/subscriptions/hooks/list-subscriptions.hook.mjs.map +1 -1
  99. package/dist/modules/subscriptions/hooks/use-has-plan-addon.hook.mjs.map +1 -1
  100. package/dist/modules/subscriptions/hooks/use-plan-by-id.hook.mjs.map +1 -1
  101. package/dist/modules/subscriptions/services/plans.service.mjs.map +1 -1
  102. package/dist/modules/subscriptions/types/plan.type.mjs.map +1 -1
  103. package/dist/modules/users/action/find-user-by-id.action.mjs.map +1 -1
  104. package/dist/modules/users/action/list-messages.action.mjs.map +1 -1
  105. package/dist/modules/users/action/mark-all-messages-as-read.action.mjs.map +1 -1
  106. package/dist/modules/users/action/mark-message-as-read.action.mjs.map +1 -1
  107. package/dist/modules/users/hooks/messages.hook.mjs.map +1 -1
  108. package/dist/modules/whitelabel/actions/find-whitelabel-styles.action.mjs.map +1 -1
  109. package/dist/modules/whitelabel/actions/find-whitelabel.action.mjs.map +1 -1
  110. package/dist/modules/whitelabel/services/whitelabel-styles.service.mjs.map +1 -1
  111. package/dist/providers/whitelabel.provider.mjs.map +1 -1
  112. package/dist/utils/countries.mjs.map +1 -1
  113. package/dist/utils/safeServerAction.mjs.map +1 -1
  114. package/dist/utils/withAction.mjs.map +1 -1
  115. package/package.json +89 -89
  116. package/src/components/account/ConfigurationsMyAccountModal.tsx +150 -150
  117. package/src/components/account/ConfirmDeleteAccountModal.tsx +55 -55
  118. package/src/components/account/ConfirmGlobalPreferencesModal.tsx +66 -66
  119. package/src/components/account/DeleteAccountModal.tsx +130 -130
  120. package/src/components/account/DisableTwoFactorAuthModal.tsx +86 -86
  121. package/src/components/account/IsntPossibleDeleteAccountModal.tsx +49 -49
  122. package/src/components/account/TwoFactorAuthModal.tsx +223 -223
  123. package/src/components/account/hooks/useChangePhoneForm.tsx +81 -81
  124. package/src/components/account/hooks/useTwoFactorAuthForm.tsx +101 -101
  125. package/src/components/account/sections/ChangeEmailModal.tsx +225 -225
  126. package/src/components/account/sections/ChangePasswordSection.tsx +64 -64
  127. package/src/components/account/sections/ChangePhoneModal.tsx +231 -231
  128. package/src/components/account/sections/MyProfileSection.tsx +327 -327
  129. package/src/components/account/sections/PreferencesSection.tsx +273 -273
  130. package/src/components/account/sections/SecuritySection.tsx +160 -160
  131. package/src/components/embeds/CrispEmbed.tsx +101 -101
  132. package/src/components/embeds/FrillEmbed.tsx +119 -119
  133. package/src/components/layouts/AppMobileNavBar.tsx +110 -110
  134. package/src/components/layouts/AppNavBar.tsx +57 -57
  135. package/src/components/layouts/MdSideBarNavigation.tsx +56 -56
  136. package/src/components/layouts/NavBar.tsx +120 -120
  137. package/src/components/layouts/NotificationsPopover.tsx +115 -115
  138. package/src/components/layouts/ProfilePopover.tsx +167 -167
  139. package/src/components/layouts/UsersSelectorPopover.tsx +238 -238
  140. package/src/components/navigation/CancelledSubscriptionBanner.tsx +69 -69
  141. package/src/components/navigation/NavItemsContext.ts +20 -20
  142. package/src/components/navigation/ProjectSelectorPopover.tsx +157 -157
  143. package/src/components/navigation/shells/TabsMobileShell.tsx +72 -72
  144. package/src/components/navigation/subcomponents/ProjectSelector.tsx +154 -154
  145. package/src/components/pages/notifications/Notifications.tsx +160 -160
  146. package/src/components/ui/buttons/Button.tsx +57 -57
  147. package/src/components/ui/buttons/CancelButton.tsx +14 -14
  148. package/src/components/ui/buttons/CopyButton.tsx +54 -54
  149. package/src/components/ui/data-display/Accordion.tsx +81 -81
  150. package/src/components/ui/data-display/Badge.tsx +47 -47
  151. package/src/components/ui/data-display/Card.tsx +93 -93
  152. package/src/components/ui/data-display/Pagination.tsx +126 -126
  153. package/src/components/ui/data-display/ScrollArea.tsx +59 -59
  154. package/src/components/ui/data-display/Separator.tsx +29 -29
  155. package/src/components/ui/data-display/Table.tsx +117 -117
  156. package/src/components/ui/data-display/Tabs.tsx +67 -67
  157. package/src/components/ui/feedback/CircularProgress.tsx +75 -75
  158. package/src/components/ui/feedback/DefaultCircularProgress.tsx +61 -61
  159. package/src/components/ui/feedback/LoadingOverlay.tsx +31 -31
  160. package/src/components/ui/feedback/Progress.tsx +40 -40
  161. package/src/components/ui/feedback/Toast.tsx +101 -101
  162. package/src/components/ui/form/Calendar.tsx +228 -228
  163. package/src/components/ui/form/Checkbox.tsx +31 -31
  164. package/src/components/ui/form/ComboboxField.tsx +154 -154
  165. package/src/components/ui/form/DatePicker.tsx +97 -97
  166. package/src/components/ui/form/DateRangePicker.tsx +108 -108
  167. package/src/components/ui/form/FormField.tsx +131 -131
  168. package/src/components/ui/form/Input.tsx +20 -20
  169. package/src/components/ui/form/InputOtp.tsx +80 -80
  170. package/src/components/ui/form/PhoneInput.tsx +205 -205
  171. package/src/components/ui/form/RadioGroup.tsx +45 -45
  172. package/src/components/ui/form/Select.tsx +200 -200
  173. package/src/components/ui/form/Switch.tsx +32 -32
  174. package/src/components/ui/form/Textarea.tsx +19 -19
  175. package/src/components/ui/overlay/Command.tsx +185 -185
  176. package/src/components/ui/overlay/Dialog.tsx +151 -151
  177. package/src/components/ui/overlay/Popover.tsx +49 -49
  178. package/src/components/ui/overlay/Sheet.tsx +166 -166
  179. package/src/components/ui/overlay/Tooltip.tsx +62 -62
  180. package/src/hooks/copy-to-clipboard.hook.tsx +67 -67
  181. package/src/index.ts +359 -359
  182. package/src/middleware.ts +4 -4
  183. package/src/modules/accounts/actions/account-management.action.ts +91 -90
  184. package/src/modules/accounts/actions/find-current-account.action.ts +9 -9
  185. package/src/modules/accounts/actions/list-currencies.action.ts +8 -8
  186. package/src/modules/accounts/actions/list-timezones.action.ts +8 -8
  187. package/src/modules/accounts/hooks/current-account.hook.tsx +22 -22
  188. package/src/modules/accounts/hooks/useAccountManagement.ts +85 -85
  189. package/src/modules/accounts/hooks/useCurrencies.ts +15 -15
  190. package/src/modules/accounts/hooks/useTimezones.ts +15 -15
  191. package/src/modules/accounts/services/account.service.ts +236 -236
  192. package/src/modules/accounts/types.ts +214 -214
  193. package/src/modules/auth/hooks/login.hook.tsx +13 -13
  194. package/src/modules/auth/hooks/logout.hook.tsx +11 -11
  195. package/src/modules/auth/hooks/register.hook.tsx +11 -11
  196. package/src/modules/ia-credits/actions/list-ia-credits.action.ts +8 -8
  197. package/src/modules/projects/actions/add-project-user.action.ts +9 -9
  198. package/src/modules/projects/actions/list-all-account-users.action.ts +9 -9
  199. package/src/modules/projects/actions/list-available-users.action.ts +9 -9
  200. package/src/modules/projects/actions/list-project-users.action.ts +9 -9
  201. package/src/modules/projects/actions/remove-project-user.action.ts +9 -9
  202. package/src/modules/projects/hooks/add-project-user.hook.ts +69 -69
  203. package/src/modules/projects/hooks/list-all-account-users.hook.ts +34 -34
  204. package/src/modules/projects/hooks/list-available-users.hook.ts +33 -33
  205. package/src/modules/projects/hooks/list-project-users.hook.ts +33 -33
  206. package/src/modules/projects/hooks/remove-project-user.hook.ts +69 -69
  207. package/src/modules/subscriptions/actions/find-plan-by-id.action.ts +8 -8
  208. package/src/modules/subscriptions/actions/list-subscriptions.action.ts +9 -9
  209. package/src/modules/subscriptions/hooks/find-active-subscription.hook.ts +19 -19
  210. package/src/modules/subscriptions/hooks/list-subscriptions.hook.ts +17 -17
  211. package/src/modules/subscriptions/hooks/use-has-plan-addon.hook.ts +17 -17
  212. package/src/modules/subscriptions/hooks/use-plan-by-id.hook.ts +13 -13
  213. package/src/modules/subscriptions/services/plans.service.ts +36 -36
  214. package/src/modules/subscriptions/types/plan.type.ts +21 -21
  215. package/src/modules/users/action/find-user-by-id.action.ts +8 -8
  216. package/src/modules/users/action/list-messages.action.ts +12 -12
  217. package/src/modules/users/action/mark-all-messages-as-read.action.ts +8 -8
  218. package/src/modules/users/action/mark-message-as-read.action.ts +8 -8
  219. package/src/modules/users/hooks/messages.hook.ts +60 -60
  220. package/src/modules/whitelabel/actions/find-whitelabel-styles.action.ts +14 -14
  221. package/src/modules/whitelabel/actions/find-whitelabel.action.ts +23 -23
  222. package/src/modules/whitelabel/services/whitelabel-styles.service.ts +98 -98
  223. package/src/modules/whitelabel/styles-schema.ts +37 -37
  224. package/src/providers/whitelabel.provider.tsx +46 -46
  225. package/src/utils/countries.ts +224 -224
  226. package/src/utils/safeServerAction.ts +21 -21
  227. package/src/utils/withAction.ts +13 -13
@@ -1,64 +1,64 @@
1
- 'use client';
2
-
3
- import { IconArrowLeft, IconLock } from '@tabler/icons-react';
4
- import { Button } from '../../ui/buttons/Button';
5
- import { FormField } from '../../ui/form/FormField';
6
- import useChangePasswordForm from '../hooks/useChangePasswordForm';
7
- import usePasswordVisibility from '../../../hooks/usePasswordVisibility';
8
-
9
- interface ChangePasswordSectionProps {
10
- onBack: () => void;
11
- }
12
-
13
- export function ChangePasswordSection({ onBack }: ChangePasswordSectionProps) {
14
- const { register, handleSubmit, errors } = useChangePasswordForm({
15
- onSuccess: onBack,
16
- });
17
- const { showPassword: showCurrentPw, togglePassword: toggleCurrentPw } = usePasswordVisibility();
18
- const { showPassword: showNewPw, togglePassword: toggleNewPw } = usePasswordVisibility();
19
-
20
- return (
21
- <form
22
- onSubmit={handleSubmit}
23
- className="flex-1 overflow-y-auto px-4 pb-5 lg:p-5 flex flex-col h-full lg:h-full gap-5 lg:gap-6"
24
- >
25
- <div className="flex items-center gap-3">
26
- <Button type="button" variant="ghost" className="size-8! p-0" onClick={onBack}>
27
- <IconArrowLeft size={20} />
28
- </Button>
29
- <span className="paragraph-medium-semibold text-gray-950">Alterar senha</span>
30
- </div>
31
-
32
- <div className="flex flex-col gap-4">
33
- <FormField
34
- label="Senha atual"
35
- type="password"
36
- placeholder="Digite sua senha atual"
37
- leftIcon={IconLock}
38
- error={!!errors.currentPassword}
39
- errorMessage={errors.currentPassword?.message}
40
- classnameContainer="h-10!"
41
- showPassword={showCurrentPw}
42
- onTogglePassword={toggleCurrentPw}
43
- {...register('currentPassword')}
44
- />
45
- <FormField
46
- label="Nova senha"
47
- type="password"
48
- placeholder="Digite sua nova senha"
49
- leftIcon={IconLock}
50
- error={!!errors.newPassword}
51
- errorMessage={errors.newPassword?.message}
52
- classnameContainer="h-10!"
53
- showPassword={showNewPw}
54
- onTogglePassword={toggleNewPw}
55
- {...register('newPassword')}
56
- />
57
- </div>
58
-
59
- <Button type="submit" className="w-fit h-10!">
60
- Salvar nova senha
61
- </Button>
62
- </form>
63
- );
64
- }
1
+ 'use client';
2
+
3
+ import { IconArrowLeft, IconLock } from '@tabler/icons-react';
4
+ import { Button } from '../../ui/buttons/Button';
5
+ import { FormField } from '../../ui/form/FormField';
6
+ import useChangePasswordForm from '../hooks/useChangePasswordForm';
7
+ import usePasswordVisibility from '../../../hooks/usePasswordVisibility';
8
+
9
+ interface ChangePasswordSectionProps {
10
+ onBack: () => void;
11
+ }
12
+
13
+ export function ChangePasswordSection({ onBack }: ChangePasswordSectionProps) {
14
+ const { register, handleSubmit, errors } = useChangePasswordForm({
15
+ onSuccess: onBack,
16
+ });
17
+ const { showPassword: showCurrentPw, togglePassword: toggleCurrentPw } = usePasswordVisibility();
18
+ const { showPassword: showNewPw, togglePassword: toggleNewPw } = usePasswordVisibility();
19
+
20
+ return (
21
+ <form
22
+ onSubmit={handleSubmit}
23
+ className="flex-1 overflow-y-auto px-4 pb-5 lg:p-5 flex flex-col h-full lg:h-full gap-5 lg:gap-6"
24
+ >
25
+ <div className="flex items-center gap-3">
26
+ <Button type="button" variant="ghost" className="size-8! p-0" onClick={onBack}>
27
+ <IconArrowLeft size={20} />
28
+ </Button>
29
+ <span className="paragraph-medium-semibold text-gray-950">Alterar senha</span>
30
+ </div>
31
+
32
+ <div className="flex flex-col gap-4">
33
+ <FormField
34
+ label="Senha atual"
35
+ type="password"
36
+ placeholder="Digite sua senha atual"
37
+ leftIcon={IconLock}
38
+ error={!!errors.currentPassword}
39
+ errorMessage={errors.currentPassword?.message}
40
+ classnameContainer="h-10!"
41
+ showPassword={showCurrentPw}
42
+ onTogglePassword={toggleCurrentPw}
43
+ {...register('currentPassword')}
44
+ />
45
+ <FormField
46
+ label="Nova senha"
47
+ type="password"
48
+ placeholder="Digite sua nova senha"
49
+ leftIcon={IconLock}
50
+ error={!!errors.newPassword}
51
+ errorMessage={errors.newPassword?.message}
52
+ classnameContainer="h-10!"
53
+ showPassword={showNewPw}
54
+ onTogglePassword={toggleNewPw}
55
+ {...register('newPassword')}
56
+ />
57
+ </div>
58
+
59
+ <Button type="submit" className="w-fit h-10!">
60
+ Salvar nova senha
61
+ </Button>
62
+ </form>
63
+ );
64
+ }
@@ -1,231 +1,231 @@
1
- 'use client';
2
-
3
- import { IconChevronLeft, IconX, IconMessage } 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 PhoneInput from '../../ui/form/PhoneInput';
9
- import { formatTimer, formatPhone } from '../../../utils/format/masks';
10
- import { OTP_CODE_LENGTH } from '../../../utils/validators/account';
11
- import { useAuth } from '../../../providers/auth.provider';
12
- import { useInvalidateUser } from '../../../modules/auth/hooks/useUserQuery';
13
- import { confirmPhoneChangeAction } from '../../../modules/accounts/actions/account-management.action';
14
- import useChangePhoneForm from '../hooks/useChangePhoneForm';
15
- import useOtpVerification from '../hooks/useOtpVerification';
16
-
17
- interface ChangePhoneModalProps {
18
- open: boolean;
19
- onClose: () => void;
20
- }
21
-
22
- export function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {
23
- const { user } = useAuth();
24
- const invalidateUser = useInvalidateUser();
25
-
26
- const currentPhoneDisplay = user?.phone
27
- ? formatPhone(
28
- user.ddi && user.phone.startsWith(user.ddi) ? user.phone.slice(user.ddi.length) : user.phone
29
- )
30
- : '';
31
-
32
- const {
33
- showVerification,
34
- phoneValue,
35
- phoneError,
36
- isSubmitting,
37
- submittedPhone,
38
- handlePhoneChange,
39
- handleContinue,
40
- handleBack,
41
- resetForm,
42
- } = useChangePhoneForm();
43
-
44
- const handleSuccess = () => {
45
- invalidateUser();
46
- resetForm();
47
- onClose();
48
- };
49
-
50
- const {
51
- code,
52
- isLoading,
53
- hasError,
54
- timer,
55
- canResend,
56
- isValidLength,
57
- handleCodeChange,
58
- handleValidate,
59
- handleResend,
60
- reset: resetOtp,
61
- } = useOtpVerification({
62
- onSuccess: handleSuccess,
63
- successMessage: 'Telefone alterado',
64
- validateFn: async (token) => {
65
- const result = await confirmPhoneChangeAction(token, submittedPhone.local, submittedPhone.ddi);
66
- return result.success;
67
- },
68
- resendFn: async () => {
69
- const { requestPhoneChangeAction } = await import('../../../modules/accounts/actions/account-management.action');
70
- const result = await requestPhoneChangeAction(submittedPhone.local, submittedPhone.ddi);
71
- if (!result.success) {
72
- throw new Error(result.error);
73
- }
74
- },
75
- });
76
-
77
- const handleClose = () => {
78
- resetForm();
79
- resetOtp();
80
- onClose();
81
- };
82
-
83
- const handleBackFromVerification = () => {
84
- resetOtp();
85
- handleBack();
86
- };
87
-
88
- return (
89
- <Dialog open={open} onOpenChange={handleClose}>
90
- <DialogContent
91
- showCloseButton={false}
92
- overlayClassName="z-[1002]"
93
- className="flex flex-col p-0 gap-0 max-w-full! border-0 rounded-t-2xl rounded-b-none h-dvh top-0! bottom-0! left-0! right-0! translate-x-0! translate-y-0! lg:max-w-125! 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%]! z-[1003]!"
94
- >
95
- {showVerification ? (
96
- <DialogHeader className="flex flex-row items-center justify-between px-4 py-3 border-b border-gray-200 lg:border-b-0">
97
- <Button variant="ghost" className="size-8! p-0" onClick={handleBackFromVerification}>
98
- <IconChevronLeft size={20} className="text-gray-950" />
99
- </Button>
100
- <DialogTitle className="paragraph-medium-semibold text-gray-950 text-center flex-1">
101
- Alterar telefone
102
- </DialogTitle>
103
- <Button variant="ghost" className="size-8! p-0" onClick={handleClose}>
104
- <IconX size={18} className="text-gray-500" />
105
- </Button>
106
- </DialogHeader>
107
- ) : (
108
- <>
109
- <DialogHeader className="sr-only">
110
- <DialogTitle>Alterar telefone</DialogTitle>
111
- </DialogHeader>
112
- <div className="flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0">
113
- <span className="paragraph-medium-semibold text-gray-950 text-center">
114
- Alterar telefone
115
- </span>
116
- <Button
117
- variant="ghost"
118
- className="absolute right-2 size-8! p-0"
119
- onClick={handleClose}
120
- >
121
- <IconX size={18} className="text-gray-500" />
122
- </Button>
123
- </div>
124
- </>
125
- )}
126
-
127
- <div className={`${showVerification ? 'w-full' : 'w-1/2'} h-0.75 bg-pages-300`} />
128
-
129
- {showVerification ? (
130
- <form
131
- onSubmit={(e) => {
132
- e.preventDefault();
133
- handleValidate();
134
- }}
135
- className="flex flex-col flex-1 lg:flex-none"
136
- >
137
- <div className="px-4 lg:px-5 py-5 lg:py-6 flex flex-col gap-4 flex-1 lg:flex-none">
138
- <div className="flex items-center justify-center size-12 bg-white rounded-lg shadow-xs border border-gray-200">
139
- <IconMessage size={20} className="text-gray-950" />
140
- </div>
141
-
142
- <div className="flex flex-col gap-1">
143
- <h3 className="paragraph-medium-semibold text-gray-950">Código de validação</h3>
144
- <p className="paragraph-small-regular text-gray-600">
145
- Enviamos um código de validação para o número atual{' '}
146
- <span className="font-semibold text-gray-950">{currentPhoneDisplay}.</span>
147
- </p>
148
- </div>
149
-
150
- <div className="flex flex-col gap-2">
151
- <InputOTP maxLength={OTP_CODE_LENGTH} value={code} onChange={handleCodeChange}>
152
- <InputOTPGroup className="flex flex-row gap-2">
153
- {[...Array(OTP_CODE_LENGTH)].map((_, i) => (
154
- <InputOTPSlot
155
- key={i}
156
- index={i}
157
- className={`uppercase text-2xl font-medium w-11 lg:w-12 h-13 lg:h-14 rounded-lg border bg-white shadow-none [&_div.animate-caret-blink]:bg-gray-950 ${hasError ? 'border-red-500' : 'border-gray-200'}`}
158
- />
159
- ))}
160
- </InputOTPGroup>
161
- </InputOTP>
162
- {hasError && (
163
- <p className="paragraph-small-regular text-red-500">Código incorreto</p>
164
- )}
165
- </div>
166
-
167
- {canResend ? (
168
- <button
169
- type="button"
170
- onClick={handleResend}
171
- className="paragraph-small-medium text-gray-950 underline cursor-pointer hover:text-gray-700 w-fit"
172
- >
173
- Reenviar código
174
- </button>
175
- ) : (
176
- <p className="paragraph-small-regular text-gray-500">
177
- Reenviar em{' '}
178
- <span className="paragraph-small-semibold text-gray-950">
179
- {formatTimer(timer)}
180
- </span>
181
- </p>
182
- )}
183
- </div>
184
-
185
- <Separator />
186
-
187
- <div className="flex items-center justify-between px-4 lg:px-5 py-4 lg:py-5 mt-auto lg:mt-0">
188
- <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
189
- Cancelar
190
- </Button>
191
- <Button className="h-10!" type="submit" disabled={!isValidLength || isLoading}>
192
- {isLoading ? 'Validando...' : 'Alterar telefone'}
193
- </Button>
194
- </div>
195
- </form>
196
- ) : (
197
- <form onSubmit={handleContinue} className="flex flex-col flex-1 lg:flex-none">
198
- <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">
199
- <div className="flex flex-col gap-1">
200
- <span className="paragraph-medium-semibold text-gray-950">
201
- Atualizar telefone de contato
202
- </span>
203
- <span className="paragraph-small-regular text-gray-600">
204
- Informe o novo número para manter seu contato atualizado.
205
- </span>
206
- </div>
207
-
208
- <PhoneInput
209
- label="Novo número"
210
- placeholder="(00) 0 0000-0000"
211
- value={phoneValue}
212
- onChange={handlePhoneChange}
213
- error={!!phoneError}
214
- errorMessage={phoneError}
215
- />
216
- </div>
217
-
218
- <div className="flex items-center justify-between p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0">
219
- <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
220
- Cancelar
221
- </Button>
222
- <Button className="h-10!" type="submit" disabled={isSubmitting}>
223
- {isSubmitting ? 'Enviando...' : 'Continuar'}
224
- </Button>
225
- </div>
226
- </form>
227
- )}
228
- </DialogContent>
229
- </Dialog>
230
- );
231
- }
1
+ 'use client';
2
+
3
+ import { IconChevronLeft, IconX, IconMessage } 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 PhoneInput from '../../ui/form/PhoneInput';
9
+ import { formatTimer, formatPhone } from '../../../utils/format/masks';
10
+ import { OTP_CODE_LENGTH } from '../../../utils/validators/account';
11
+ import { useAuth } from '../../../providers/auth.provider';
12
+ import { useInvalidateUser } from '../../../modules/auth/hooks/useUserQuery';
13
+ import { confirmPhoneChangeAction } from '../../../modules/accounts/actions/account-management.action';
14
+ import useChangePhoneForm from '../hooks/useChangePhoneForm';
15
+ import useOtpVerification from '../hooks/useOtpVerification';
16
+
17
+ interface ChangePhoneModalProps {
18
+ open: boolean;
19
+ onClose: () => void;
20
+ }
21
+
22
+ export function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {
23
+ const { user } = useAuth();
24
+ const invalidateUser = useInvalidateUser();
25
+
26
+ const currentPhoneDisplay = user?.phone
27
+ ? formatPhone(
28
+ user.ddi && user.phone.startsWith(user.ddi) ? user.phone.slice(user.ddi.length) : user.phone
29
+ )
30
+ : '';
31
+
32
+ const {
33
+ showVerification,
34
+ phoneValue,
35
+ phoneError,
36
+ isSubmitting,
37
+ submittedPhone,
38
+ handlePhoneChange,
39
+ handleContinue,
40
+ handleBack,
41
+ resetForm,
42
+ } = useChangePhoneForm();
43
+
44
+ const handleSuccess = () => {
45
+ invalidateUser();
46
+ resetForm();
47
+ onClose();
48
+ };
49
+
50
+ const {
51
+ code,
52
+ isLoading,
53
+ hasError,
54
+ timer,
55
+ canResend,
56
+ isValidLength,
57
+ handleCodeChange,
58
+ handleValidate,
59
+ handleResend,
60
+ reset: resetOtp,
61
+ } = useOtpVerification({
62
+ onSuccess: handleSuccess,
63
+ successMessage: 'Telefone alterado',
64
+ validateFn: async (token) => {
65
+ const result = await confirmPhoneChangeAction(token, submittedPhone.local, submittedPhone.ddi);
66
+ return result.success;
67
+ },
68
+ resendFn: async () => {
69
+ const { requestPhoneChangeAction } = await import('../../../modules/accounts/actions/account-management.action');
70
+ const result = await requestPhoneChangeAction(submittedPhone.local, submittedPhone.ddi);
71
+ if (!result.success) {
72
+ throw new Error(result.error);
73
+ }
74
+ },
75
+ });
76
+
77
+ const handleClose = () => {
78
+ resetForm();
79
+ resetOtp();
80
+ onClose();
81
+ };
82
+
83
+ const handleBackFromVerification = () => {
84
+ resetOtp();
85
+ handleBack();
86
+ };
87
+
88
+ return (
89
+ <Dialog open={open} onOpenChange={handleClose}>
90
+ <DialogContent
91
+ showCloseButton={false}
92
+ overlayClassName="z-[1002]"
93
+ className="flex flex-col p-0 gap-0 max-w-full! border-0 rounded-t-2xl rounded-b-none h-dvh top-0! bottom-0! left-0! right-0! translate-x-0! translate-y-0! lg:max-w-125! 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%]! z-[1003]!"
94
+ >
95
+ {showVerification ? (
96
+ <DialogHeader className="flex flex-row items-center justify-between px-4 py-3 border-b border-gray-200 lg:border-b-0">
97
+ <Button variant="ghost" className="size-8! p-0" onClick={handleBackFromVerification}>
98
+ <IconChevronLeft size={20} className="text-gray-950" />
99
+ </Button>
100
+ <DialogTitle className="paragraph-medium-semibold text-gray-950 text-center flex-1">
101
+ Alterar telefone
102
+ </DialogTitle>
103
+ <Button variant="ghost" className="size-8! p-0" onClick={handleClose}>
104
+ <IconX size={18} className="text-gray-500" />
105
+ </Button>
106
+ </DialogHeader>
107
+ ) : (
108
+ <>
109
+ <DialogHeader className="sr-only">
110
+ <DialogTitle>Alterar telefone</DialogTitle>
111
+ </DialogHeader>
112
+ <div className="flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0">
113
+ <span className="paragraph-medium-semibold text-gray-950 text-center">
114
+ Alterar telefone
115
+ </span>
116
+ <Button
117
+ variant="ghost"
118
+ className="absolute right-2 size-8! p-0"
119
+ onClick={handleClose}
120
+ >
121
+ <IconX size={18} className="text-gray-500" />
122
+ </Button>
123
+ </div>
124
+ </>
125
+ )}
126
+
127
+ <div className={`${showVerification ? 'w-full' : 'w-1/2'} h-0.75 bg-pages-300`} />
128
+
129
+ {showVerification ? (
130
+ <form
131
+ onSubmit={(e) => {
132
+ e.preventDefault();
133
+ handleValidate();
134
+ }}
135
+ className="flex flex-col flex-1 lg:flex-none"
136
+ >
137
+ <div className="px-4 lg:px-5 py-5 lg:py-6 flex flex-col gap-4 flex-1 lg:flex-none">
138
+ <div className="flex items-center justify-center size-12 bg-white rounded-lg shadow-xs border border-gray-200">
139
+ <IconMessage size={20} className="text-gray-950" />
140
+ </div>
141
+
142
+ <div className="flex flex-col gap-1">
143
+ <h3 className="paragraph-medium-semibold text-gray-950">Código de validação</h3>
144
+ <p className="paragraph-small-regular text-gray-600">
145
+ Enviamos um código de validação para o número atual{' '}
146
+ <span className="font-semibold text-gray-950">{currentPhoneDisplay}.</span>
147
+ </p>
148
+ </div>
149
+
150
+ <div className="flex flex-col gap-2">
151
+ <InputOTP maxLength={OTP_CODE_LENGTH} value={code} onChange={handleCodeChange}>
152
+ <InputOTPGroup className="flex flex-row gap-2">
153
+ {[...Array(OTP_CODE_LENGTH)].map((_, i) => (
154
+ <InputOTPSlot
155
+ key={i}
156
+ index={i}
157
+ className={`uppercase text-2xl font-medium w-11 lg:w-12 h-13 lg:h-14 rounded-lg border bg-white shadow-none [&_div.animate-caret-blink]:bg-gray-950 ${hasError ? 'border-red-500' : 'border-gray-200'}`}
158
+ />
159
+ ))}
160
+ </InputOTPGroup>
161
+ </InputOTP>
162
+ {hasError && (
163
+ <p className="paragraph-small-regular text-red-500">Código incorreto</p>
164
+ )}
165
+ </div>
166
+
167
+ {canResend ? (
168
+ <button
169
+ type="button"
170
+ onClick={handleResend}
171
+ className="paragraph-small-medium text-gray-950 underline cursor-pointer hover:text-gray-700 w-fit"
172
+ >
173
+ Reenviar código
174
+ </button>
175
+ ) : (
176
+ <p className="paragraph-small-regular text-gray-500">
177
+ Reenviar em{' '}
178
+ <span className="paragraph-small-semibold text-gray-950">
179
+ {formatTimer(timer)}
180
+ </span>
181
+ </p>
182
+ )}
183
+ </div>
184
+
185
+ <Separator />
186
+
187
+ <div className="flex items-center justify-between px-4 lg:px-5 py-4 lg:py-5 mt-auto lg:mt-0">
188
+ <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
189
+ Cancelar
190
+ </Button>
191
+ <Button className="h-10!" type="submit" disabled={!isValidLength || isLoading}>
192
+ {isLoading ? 'Validando...' : 'Alterar telefone'}
193
+ </Button>
194
+ </div>
195
+ </form>
196
+ ) : (
197
+ <form onSubmit={handleContinue} className="flex flex-col flex-1 lg:flex-none">
198
+ <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">
199
+ <div className="flex flex-col gap-1">
200
+ <span className="paragraph-medium-semibold text-gray-950">
201
+ Atualizar telefone de contato
202
+ </span>
203
+ <span className="paragraph-small-regular text-gray-600">
204
+ Informe o novo número para manter seu contato atualizado.
205
+ </span>
206
+ </div>
207
+
208
+ <PhoneInput
209
+ label="Novo número"
210
+ placeholder="(00) 0 0000-0000"
211
+ value={phoneValue}
212
+ onChange={handlePhoneChange}
213
+ error={!!phoneError}
214
+ errorMessage={phoneError}
215
+ />
216
+ </div>
217
+
218
+ <div className="flex items-center justify-between p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0">
219
+ <Button variant="secondary" className="h-10!" type="button" onClick={handleClose}>
220
+ Cancelar
221
+ </Button>
222
+ <Button className="h-10!" type="submit" disabled={isSubmitting}>
223
+ {isSubmitting ? 'Enviando...' : 'Continuar'}
224
+ </Button>
225
+ </div>
226
+ </form>
227
+ )}
228
+ </DialogContent>
229
+ </Dialog>
230
+ );
231
+ }