@greatapps/common 1.1.675 → 1.1.677
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/account/ConfigurationsMyAccountModal.mjs +8 -6
- package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -1
- package/dist/components/account/ConfirmDeleteAccountModal.mjs +20 -19
- package/dist/components/account/ConfirmDeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/ConfirmGlobalPreferencesModal.mjs +10 -11
- package/dist/components/account/ConfirmGlobalPreferencesModal.mjs.map +1 -1
- package/dist/components/account/DeleteAccountModal.mjs +34 -28
- package/dist/components/account/DeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/DisableTwoFactorAuthModal.mjs +7 -5
- package/dist/components/account/DisableTwoFactorAuthModal.mjs.map +1 -1
- package/dist/components/account/IsntPossibleDeleteAccountModal.mjs +8 -9
- package/dist/components/account/IsntPossibleDeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/TwoFactorAuthModal.mjs +22 -23
- package/dist/components/account/TwoFactorAuthModal.mjs.map +1 -1
- package/dist/components/account/constants.mjs +4 -4
- package/dist/components/account/constants.mjs.map +1 -1
- package/dist/components/account/hooks/useChangeEmailForm.mjs +5 -3
- package/dist/components/account/hooks/useChangeEmailForm.mjs.map +1 -1
- package/dist/components/account/hooks/useChangePasswordForm.mjs +26 -3
- package/dist/components/account/hooks/useChangePasswordForm.mjs.map +1 -1
- package/dist/components/account/hooks/useChangePhoneForm.mjs +18 -9
- package/dist/components/account/hooks/useChangePhoneForm.mjs.map +1 -1
- package/dist/components/account/hooks/useDisableTwoFactorAuthForm.mjs +26 -3
- package/dist/components/account/hooks/useDisableTwoFactorAuthForm.mjs.map +1 -1
- package/dist/components/account/hooks/useOtpVerification.mjs +19 -3
- package/dist/components/account/hooks/useOtpVerification.mjs.map +1 -1
- package/dist/components/account/hooks/useTwoFactorAuthForm.mjs +27 -4
- package/dist/components/account/hooks/useTwoFactorAuthForm.mjs.map +1 -1
- package/dist/components/account/sections/ChangeEmailModal.mjs +25 -28
- package/dist/components/account/sections/ChangeEmailModal.mjs.map +1 -1
- package/dist/components/account/sections/ChangePasswordSection.mjs +8 -6
- package/dist/components/account/sections/ChangePasswordSection.mjs.map +1 -1
- package/dist/components/account/sections/ChangePhoneModal.mjs +24 -27
- package/dist/components/account/sections/ChangePhoneModal.mjs.map +1 -1
- package/dist/components/account/sections/MyProfileSection.mjs +37 -22
- package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
- package/dist/components/account/sections/PreferencesSection.mjs +48 -24
- package/dist/components/account/sections/PreferencesSection.mjs.map +1 -1
- package/dist/components/account/sections/SecuritySection.mjs +11 -9
- package/dist/components/account/sections/SecuritySection.mjs.map +1 -1
- package/dist/components/account/sections/TokenSection.mjs +24 -8
- package/dist/components/account/sections/TokenSection.mjs.map +1 -1
- package/dist/components/layouts/AppMobileNavBar.mjs +2 -148
- package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
- package/dist/components/layouts/NavBar.mjs +5 -3
- package/dist/components/layouts/NavBar.mjs.map +1 -1
- package/dist/components/layouts/NotificationsPopover.mjs +5 -3
- package/dist/components/layouts/NotificationsPopover.mjs.map +1 -1
- package/dist/components/layouts/ProfilePopover.mjs +6 -4
- package/dist/components/layouts/ProfilePopover.mjs.map +1 -1
- package/dist/components/layouts/UsersSelectorPopover.mjs +9 -7
- package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
- package/dist/components/modals/BuyCreditsModal.mjs +17 -18
- package/dist/components/modals/BuyCreditsModal.mjs.map +1 -1
- package/dist/components/modals/CreditsDisabledModal.mjs +6 -4
- package/dist/components/modals/CreditsDisabledModal.mjs.map +1 -1
- package/dist/components/modals/PaidPlanRequiredModal.mjs +5 -3
- package/dist/components/modals/PaidPlanRequiredModal.mjs.map +1 -1
- package/dist/components/modals/cards/AddCardModal.mjs +64 -46
- package/dist/components/modals/cards/AddCardModal.mjs.map +1 -1
- package/dist/components/modals/cards/CannotDeleteCardModal.mjs +9 -7
- package/dist/components/modals/cards/CannotDeleteCardModal.mjs.map +1 -1
- package/dist/components/modals/cards/CardFormFields.mjs +65 -51
- package/dist/components/modals/cards/CardFormFields.mjs.map +1 -1
- package/dist/components/modals/cards/DeleteCardModal.mjs +10 -8
- package/dist/components/modals/cards/DeleteCardModal.mjs.map +1 -1
- package/dist/components/navigation/CancelledSubscriptionBanner.mjs +4 -2
- package/dist/components/navigation/CancelledSubscriptionBanner.mjs.map +1 -1
- package/dist/components/navigation/OverdueInvoiceBanner.mjs +4 -2
- package/dist/components/navigation/OverdueInvoiceBanner.mjs.map +1 -1
- package/dist/components/navigation/PendingCancellationBanner.mjs +4 -6
- package/dist/components/navigation/PendingCancellationBanner.mjs.map +1 -1
- package/dist/components/navigation/ProjectSelectorPopover.mjs +8 -6
- package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
- package/dist/components/navigation/UpcomingInvoiceBanner.mjs +4 -6
- package/dist/components/navigation/UpcomingInvoiceBanner.mjs.map +1 -1
- package/dist/components/navigation/subcomponents/BottomLinks.mjs +5 -3
- package/dist/components/navigation/subcomponents/BottomLinks.mjs.map +1 -1
- package/dist/components/navigation/subcomponents/CreditsCard.mjs +3 -1
- package/dist/components/navigation/subcomponents/CreditsCard.mjs.map +1 -1
- package/dist/components/navigation/subcomponents/PlanCard.mjs +3 -1
- package/dist/components/navigation/subcomponents/PlanCard.mjs.map +1 -1
- package/dist/components/navigation/subcomponents/ProjectSelector.mjs +5 -3
- package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
- package/dist/components/pages/NotFoundPage.mjs +5 -3
- package/dist/components/pages/NotFoundPage.mjs.map +1 -1
- package/dist/components/pages/notifications/Notifications.mjs +13 -10
- package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
- package/dist/components/ui/buttons/CopyButton.mjs +9 -5
- package/dist/components/ui/buttons/CopyButton.mjs.map +1 -1
- package/dist/components/ui/data-display/CardItem.mjs +7 -5
- package/dist/components/ui/data-display/CardItem.mjs.map +1 -1
- package/dist/components/ui/data-display/PaymentInfoCard.mjs +10 -8
- package/dist/components/ui/data-display/PaymentInfoCard.mjs.map +1 -1
- package/dist/components/ui/feedback/CircularProgress.mjs.map +1 -1
- package/dist/components/ui/feedback/DefaultCircularProgress.mjs +3 -1
- package/dist/components/ui/feedback/DefaultCircularProgress.mjs.map +1 -1
- package/dist/components/ui/form/ComboboxField.mjs +11 -6
- package/dist/components/ui/form/ComboboxField.mjs.map +1 -1
- package/dist/components/ui/form/DatePicker.mjs +5 -2
- package/dist/components/ui/form/DatePicker.mjs.map +1 -1
- package/dist/components/ui/form/DateRangePicker.mjs +5 -2
- package/dist/components/ui/form/DateRangePicker.mjs.map +1 -1
- package/dist/components/ui/form/PhoneInput.mjs +5 -3
- package/dist/components/ui/form/PhoneInput.mjs.map +1 -1
- package/dist/components/ui/form/SelectField.mjs +6 -3
- package/dist/components/ui/form/SelectField.mjs.map +1 -1
- package/dist/components/widgets/ImageUpload/ImageCropModal.mjs +11 -18
- package/dist/components/widgets/ImageUpload/ImageCropModal.mjs.map +1 -1
- package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs +6 -15
- package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs.map +1 -1
- package/dist/i18n/config.mjs +13 -0
- package/dist/i18n/config.mjs.map +1 -0
- package/dist/i18n/country-language.mjs +74 -0
- package/dist/i18n/country-language.mjs.map +1 -0
- package/dist/i18n/messages/en-us.mjs +494 -0
- package/dist/i18n/messages/en-us.mjs.map +1 -0
- package/dist/i18n/messages/es-es.mjs +494 -0
- package/dist/i18n/messages/es-es.mjs.map +1 -0
- package/dist/i18n/messages/index.mjs +16 -0
- package/dist/i18n/messages/index.mjs.map +1 -0
- package/dist/i18n/messages/pt-br.mjs +507 -0
- package/dist/i18n/messages/pt-br.mjs.map +1 -0
- package/dist/i18n/normalize.mjs +12 -0
- package/dist/i18n/normalize.mjs.map +1 -0
- package/dist/i18n/resolve-locale.mjs +42 -0
- package/dist/i18n/resolve-locale.mjs.map +1 -0
- package/dist/i18n.mjs +14 -0
- package/dist/i18n.mjs.map +1 -0
- package/dist/index.mjs +19 -3
- package/dist/index.mjs.map +1 -1
- package/dist/modules/accounts/hooks/use-currency-formatter.hook.mjs +20 -0
- package/dist/modules/accounts/hooks/use-currency-formatter.hook.mjs.map +1 -0
- package/dist/modules/cards/hooks/handle-delete-card.hook.mjs +2 -1
- package/dist/modules/cards/hooks/handle-delete-card.hook.mjs.map +1 -1
- package/dist/modules/images/utils/validate-image.mjs +8 -8
- package/dist/modules/images/utils/validate-image.mjs.map +1 -1
- package/dist/modules/plans/hooks/list-plans.hook.mjs +2 -2
- package/dist/modules/plans/hooks/list-plans.hook.mjs.map +1 -1
- package/dist/modules/plans/types/plan.type.mjs +5 -1
- package/dist/modules/plans/types/plan.type.mjs.map +1 -1
- package/dist/modules/plans/utils/map-api-plan-to-ui.mjs +61 -35
- package/dist/modules/plans/utils/map-api-plan-to-ui.mjs.map +1 -1
- package/dist/modules/projects/services/projects.service.mjs +9 -0
- package/dist/modules/projects/services/projects.service.mjs.map +1 -1
- package/dist/modules/subscriptions/utils/periodicity.mjs +20 -14
- package/dist/modules/subscriptions/utils/periodicity.mjs.map +1 -1
- package/dist/providers/auth.provider.mjs +9 -1
- package/dist/providers/auth.provider.mjs.map +1 -1
- package/dist/server.mjs +2 -0
- package/dist/server.mjs.map +1 -1
- package/dist/utils/format/currency.mjs +32 -4
- package/dist/utils/format/currency.mjs.map +1 -1
- package/dist/utils/intl/cookie-domain.mjs +17 -0
- package/dist/utils/intl/cookie-domain.mjs.map +1 -0
- package/dist/utils/intl/locale-cookie.mjs +13 -0
- package/dist/utils/intl/locale-cookie.mjs.map +1 -0
- package/dist/utils/intl/locales.mjs +3 -2
- package/dist/utils/intl/locales.mjs.map +1 -1
- package/package.json +7 -1
- package/src/components/account/ConfigurationsMyAccountModal.tsx +10 -6
- package/src/components/account/ConfirmDeleteAccountModal.tsx +22 -13
- package/src/components/account/ConfirmGlobalPreferencesModal.tsx +12 -10
- package/src/components/account/DeleteAccountModal.tsx +34 -24
- package/src/components/account/DisableTwoFactorAuthModal.tsx +11 -6
- package/src/components/account/IsntPossibleDeleteAccountModal.tsx +8 -6
- package/src/components/account/TwoFactorAuthModal.tsx +33 -29
- package/src/components/account/constants.ts +8 -5
- package/src/components/account/hooks/useChangeEmailForm.tsx +5 -3
- package/src/components/account/hooks/useChangePasswordForm.tsx +20 -6
- package/src/components/account/hooks/useChangePhoneForm.tsx +16 -10
- package/src/components/account/hooks/useDisableTwoFactorAuthForm.tsx +20 -6
- package/src/components/account/hooks/useOtpVerification.tsx +16 -4
- package/src/components/account/hooks/useTwoFactorAuthForm.tsx +21 -7
- package/src/components/account/sections/ChangeEmailModal.tsx +35 -21
- package/src/components/account/sections/ChangePasswordSection.tsx +10 -6
- package/src/components/account/sections/ChangePhoneModal.tsx +50 -22
- package/src/components/account/sections/MyProfileSection.tsx +37 -23
- package/src/components/account/sections/PreferencesSection.tsx +52 -25
- package/src/components/account/sections/SecuritySection.tsx +19 -10
- package/src/components/account/sections/TokenSection.tsx +22 -10
- package/src/components/layouts/AppMobileNavBar.tsx +1 -154
- package/src/components/layouts/NavBar.tsx +5 -3
- package/src/components/layouts/NotificationsPopover.tsx +5 -3
- package/src/components/layouts/ProfilePopover.tsx +6 -4
- package/src/components/layouts/UsersSelectorPopover.tsx +9 -7
- package/src/components/modals/BuyCreditsModal.tsx +18 -16
- package/src/components/modals/CreditsDisabledModal.tsx +6 -6
- package/src/components/modals/PaidPlanRequiredModal.tsx +5 -3
- package/src/components/modals/cards/AddCardModal.tsx +89 -62
- package/src/components/modals/cards/CannotDeleteCardModal.tsx +9 -8
- package/src/components/modals/cards/CardFormFields.tsx +93 -75
- package/src/components/modals/cards/DeleteCardModal.tsx +10 -8
- package/src/components/navigation/CancelledSubscriptionBanner.tsx +4 -2
- package/src/components/navigation/OverdueInvoiceBanner.tsx +4 -2
- package/src/components/navigation/PendingCancellationBanner.tsx +4 -2
- package/src/components/navigation/ProjectSelectorPopover.tsx +8 -6
- package/src/components/navigation/UpcomingInvoiceBanner.tsx +4 -2
- package/src/components/navigation/subcomponents/BottomLinks.tsx +5 -3
- package/src/components/navigation/subcomponents/CreditsCard.tsx +3 -1
- package/src/components/navigation/subcomponents/PlanCard.tsx +3 -1
- package/src/components/navigation/subcomponents/ProjectSelector.tsx +5 -3
- package/src/components/pages/NotFoundPage.tsx +5 -3
- package/src/components/pages/notifications/Notifications.tsx +13 -10
- package/src/components/ui/buttons/CopyButton.tsx +10 -5
- package/src/components/ui/data-display/CardItem.tsx +7 -5
- package/src/components/ui/data-display/PaymentInfoCard.tsx +10 -8
- package/src/components/ui/feedback/CircularProgress.tsx +4 -0
- package/src/components/ui/feedback/DefaultCircularProgress.tsx +3 -1
- package/src/components/ui/form/ComboboxField.tsx +11 -6
- package/src/components/ui/form/DatePicker.tsx +5 -2
- package/src/components/ui/form/DateRangePicker.tsx +5 -2
- package/src/components/ui/form/PhoneInput.tsx +5 -3
- package/src/components/ui/form/SelectField.tsx +6 -3
- package/src/components/widgets/ImageUpload/ImageCropModal.tsx +19 -11
- package/src/components/widgets/ImageUpload/ImageTooSmallModal.tsx +6 -5
- package/src/i18n/config.ts +17 -0
- package/src/i18n/country-language.ts +60 -0
- package/src/i18n/messages/en-us.ts +514 -0
- package/src/i18n/messages/es-es.ts +515 -0
- package/src/i18n/messages/index.ts +24 -0
- package/src/i18n/messages/pt-br.ts +538 -0
- package/src/i18n/normalize.ts +15 -0
- package/src/i18n/resolve-locale.ts +77 -0
- package/src/i18n.ts +10 -0
- package/src/index.ts +13 -2
- package/src/modules/accounts/hooks/use-currency-formatter.hook.tsx +32 -0
- package/src/modules/cards/hooks/handle-delete-card.hook.ts +8 -3
- package/src/modules/images/utils/validate-image.ts +23 -8
- package/src/modules/plans/hooks/list-plans.hook.ts +2 -2
- package/src/modules/plans/types/plan.type.ts +4 -0
- package/src/modules/plans/utils/map-api-plan-to-ui.ts +109 -47
- package/src/modules/projects/services/projects.service.ts +12 -0
- package/src/modules/subscriptions/utils/periodicity.ts +29 -12
- package/src/providers/auth.provider.tsx +13 -1
- package/src/server.ts +2 -0
- package/src/utils/format/currency.ts +62 -7
- package/src/utils/intl/cookie-domain.ts +29 -0
- package/src/utils/intl/locale-cookie.ts +18 -0
- package/src/utils/intl/locales.ts +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/account/hooks/useDisableTwoFactorAuthForm.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useState, useCallback } from 'react';\r\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\r\nimport { toast } from 'sonner';\r\nimport { Toast } from '../../ui/feedback/Toast';\r\nimport { USER_QUERY_KEY } from '../../../modules/auth/hooks/useUserQuery';\r\nimport { disableTwoFactorAction } from '../../../modules/accounts/actions/account-management.action';\r\nimport { useWlQueryKey } from '../../../hooks/useAuthQueryKey';\r\n\r\ninterface UseDisableTwoFactorAuthFormProps {\r\n onClose: () => void;\r\n onSuccess?: () => void;\r\n}\r\n\r\nexport default function useDisableTwoFactorAuthForm({\r\n onClose,\r\n onSuccess,\r\n}: UseDisableTwoFactorAuthFormProps) {\r\n const [code, setCode] = useState('');\r\n const queryClient = useQueryClient();\r\n const userKey = useWlQueryKey([...USER_QUERY_KEY]);\r\n\r\n const isValid = code.length === 6;\r\n\r\n const mutation = useMutation({\r\n mutationFn: (otpCode: string) => disableTwoFactorAction(otpCode),\r\n onSuccess: (result) => {\r\n if (!result.success) {\r\n setCode('');\r\n toast.custom((
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/account/hooks/useDisableTwoFactorAuthForm.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useState, useCallback } from 'react';\r\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\r\nimport { useTranslations } from 'next-intl';\r\nimport { toast } from 'sonner';\r\nimport { Toast } from '../../ui/feedback/Toast';\r\nimport { USER_QUERY_KEY } from '../../../modules/auth/hooks/useUserQuery';\r\nimport { disableTwoFactorAction } from '../../../modules/accounts/actions/account-management.action';\r\nimport { useWlQueryKey } from '../../../hooks/useAuthQueryKey';\r\n\r\ninterface UseDisableTwoFactorAuthFormProps {\r\n onClose: () => void;\r\n onSuccess?: () => void;\r\n}\r\n\r\nexport default function useDisableTwoFactorAuthForm({\r\n onClose,\r\n onSuccess,\r\n}: UseDisableTwoFactorAuthFormProps) {\r\n const translate = useTranslations();\r\n const [code, setCode] = useState('');\r\n const queryClient = useQueryClient();\r\n const userKey = useWlQueryKey([...USER_QUERY_KEY]);\r\n\r\n const isValid = code.length === 6;\r\n\r\n const mutation = useMutation({\r\n mutationFn: (otpCode: string) => disableTwoFactorAction(otpCode),\r\n onSuccess: (result) => {\r\n if (!result.success) {\r\n setCode('');\r\n toast.custom((toastId) => (\r\n <Toast\r\n variant=\"error\"\r\n message={result.error ?? translate('common.account.twoFactor.invalidCode')}\r\n toastId={toastId}\r\n />\r\n ));\r\n return;\r\n }\r\n\r\n queryClient.invalidateQueries({ queryKey: userKey });\r\n toast.custom((toastId) => (\r\n <Toast\r\n variant=\"success\"\r\n message={translate('common.account.twoFactor.disabledSuccess')}\r\n toastId={toastId}\r\n />\r\n ));\r\n setCode('');\r\n onSuccess?.();\r\n },\r\n onError: () => {\r\n setCode('');\r\n toast.custom((toastId) => (\r\n <Toast\r\n variant=\"error\"\r\n message={translate('common.account.twoFactor.disableError')}\r\n toastId={toastId}\r\n />\r\n ));\r\n },\r\n });\r\n\r\n const { mutate, reset } = mutation;\r\n\r\n const handleClose = useCallback(() => {\r\n setCode('');\r\n reset();\r\n onClose();\r\n }, [onClose, reset]);\r\n\r\n const handleSubmit = useCallback(() => {\r\n if (!isValid) return;\r\n mutate(code);\r\n }, [code, isValid, mutate]);\r\n\r\n return {\r\n code,\r\n setCode,\r\n isValid,\r\n isLoading: mutation.isPending,\r\n handleClose,\r\n handleSubmit,\r\n };\r\n}\r\n"],"mappings":";AAiCU;AA/BV,SAAS,UAAU,mBAAmB;AACtC,SAAS,aAAa,sBAAsB;AAC5C,SAAS,uBAAuB;AAChC,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,sBAAsB;AAC/B,SAAS,8BAA8B;AACvC,SAAS,qBAAqB;AAOf,SAAR,4BAA6C;AAAA,EAClD;AAAA,EACA;AACF,GAAqC;AACnC,QAAM,YAAY,gBAAgB;AAClC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE;AACnC,QAAM,cAAc,eAAe;AACnC,QAAM,UAAU,cAAc,CAAC,GAAG,cAAc,CAAC;AAEjD,QAAM,UAAU,KAAK,WAAW;AAEhC,QAAM,WAAW,YAAY;AAAA,IAC3B,YAAY,CAAC,YAAoB,uBAAuB,OAAO;AAAA,IAC/D,WAAW,CAAC,WAAW;AACrB,UAAI,CAAC,OAAO,SAAS;AACnB,gBAAQ,EAAE;AACV,cAAM,OAAO,CAAC,YACZ;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,SAAS,OAAO,SAAS,UAAU,sCAAsC;AAAA,YACzE;AAAA;AAAA,QACF,CACD;AACD;AAAA,MACF;AAEA,kBAAY,kBAAkB,EAAE,UAAU,QAAQ,CAAC;AACnD,YAAM,OAAO,CAAC,YACZ;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS,UAAU,0CAA0C;AAAA,UAC7D;AAAA;AAAA,MACF,CACD;AACD,cAAQ,EAAE;AACV,kBAAY;AAAA,IACd;AAAA,IACA,SAAS,MAAM;AACb,cAAQ,EAAE;AACV,YAAM,OAAO,CAAC,YACZ;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS,UAAU,uCAAuC;AAAA,UAC1D;AAAA;AAAA,MACF,CACD;AAAA,IACH;AAAA,EACF,CAAC;AAED,QAAM,EAAE,QAAQ,MAAM,IAAI;AAE1B,QAAM,cAAc,YAAY,MAAM;AACpC,YAAQ,EAAE;AACV,UAAM;AACN,YAAQ;AAAA,EACV,GAAG,CAAC,SAAS,KAAK,CAAC;AAEnB,QAAM,eAAe,YAAY,MAAM;AACrC,QAAI,CAAC,QAAS;AACd,WAAO,IAAI;AAAA,EACb,GAAG,CAAC,MAAM,SAAS,MAAM,CAAC;AAE1B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,SAAS;AAAA,IACpB;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useCallback } from "react";
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
4
5
|
import { toast } from "sonner";
|
|
5
6
|
import { Toast } from "../../ui/feedback/Toast";
|
|
6
7
|
import useCountdownTimer from "../../../hooks/useCountdownTimer";
|
|
@@ -12,6 +13,7 @@ function useOtpVerification({
|
|
|
12
13
|
validateFn,
|
|
13
14
|
resendFn
|
|
14
15
|
}) {
|
|
16
|
+
const translate = useTranslations();
|
|
15
17
|
const [code, setCode] = useState("");
|
|
16
18
|
const [isLoading, setIsLoading] = useState(false);
|
|
17
19
|
const [hasError, setHasError] = useState(false);
|
|
@@ -64,12 +66,26 @@ function useOtpVerification({
|
|
|
64
66
|
if (resendFn) {
|
|
65
67
|
await resendFn();
|
|
66
68
|
}
|
|
67
|
-
toast.custom((
|
|
69
|
+
toast.custom((toastId) => /* @__PURE__ */ jsx(
|
|
70
|
+
Toast,
|
|
71
|
+
{
|
|
72
|
+
variant: "success",
|
|
73
|
+
message: translate("common.account.twoFactor.codeResent"),
|
|
74
|
+
toastId
|
|
75
|
+
}
|
|
76
|
+
));
|
|
68
77
|
} catch (error) {
|
|
69
78
|
console.error("Erro ao reenviar c\xF3digo:", error);
|
|
70
|
-
toast.custom((
|
|
79
|
+
toast.custom((toastId) => /* @__PURE__ */ jsx(
|
|
80
|
+
Toast,
|
|
81
|
+
{
|
|
82
|
+
variant: "error",
|
|
83
|
+
message: translate("common.account.twoFactor.resendError"),
|
|
84
|
+
toastId
|
|
85
|
+
}
|
|
86
|
+
));
|
|
71
87
|
}
|
|
72
|
-
}, [canResend, resetTimer, resendFn]);
|
|
88
|
+
}, [canResend, resetTimer, resendFn, translate]);
|
|
73
89
|
const reset = useCallback(() => {
|
|
74
90
|
setCode("");
|
|
75
91
|
setHasError(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/account/hooks/useOtpVerification.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useState, useCallback } from 'react';\r\nimport { toast } from 'sonner';\r\nimport { Toast } from '../../ui/feedback/Toast';\r\nimport useCountdownTimer from '../../../hooks/useCountdownTimer';\r\nimport { OTP_CODE_LENGTH, VALID_OTP_CODE } from '../../../utils/validators/account';\r\nimport { hasExactLength } from '../../../utils/validators/common';\r\n\r\ninterface UseOtpVerificationOptions {\r\n onSuccess: () => void;\r\n successMessage: string;\r\n validateFn?: (code: string) => Promise<boolean>;\r\n resendFn?: () => Promise<void>;\r\n}\r\n\r\nexport default function useOtpVerification({\r\n onSuccess,\r\n successMessage,\r\n validateFn,\r\n resendFn,\r\n}: UseOtpVerificationOptions) {\r\n const [code, setCode] = useState('');\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [hasError, setHasError] = useState(false);\r\n\r\n const {\r\n seconds: timer,\r\n isExpired: canResend,\r\n reset: resetTimer,\r\n } = useCountdownTimer({ initialSeconds: 59 });\r\n\r\n const handleCodeChange = useCallback(\r\n (value: string) => {\r\n setCode(value.toUpperCase());\r\n if (hasError) {\r\n setHasError(false);\r\n }\r\n },\r\n [hasError]\r\n );\r\n\r\n const handleValidate = useCallback(async () => {\r\n if (!hasExactLength(code, OTP_CODE_LENGTH)) return;\r\n\r\n setIsLoading(true);\r\n setHasError(false);\r\n\r\n try {\r\n let isValid: boolean;\r\n\r\n if (validateFn) {\r\n isValid = await validateFn(code);\r\n } else {\r\n await new Promise((resolve) => setTimeout(resolve, 500));\r\n isValid = code === VALID_OTP_CODE;\r\n }\r\n\r\n if (!isValid) {\r\n setHasError(true);\r\n return;\r\n }\r\n\r\n toast.custom((t) => <Toast variant=\"success\" message={successMessage} toastId={t} />);\r\n\r\n setCode('');\r\n onSuccess();\r\n } catch (error) {\r\n console.error('Erro ao validar código:', error);\r\n setHasError(true);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [code, onSuccess, successMessage, validateFn]);\r\n\r\n const handleResend = useCallback(async () => {\r\n if (!canResend) return;\r\n\r\n try {\r\n resetTimer();\r\n setHasError(false);\r\n setCode('');\r\n\r\n if (resendFn) {\r\n await resendFn();\r\n }\r\n\r\n toast.custom((
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/account/hooks/useOtpVerification.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useState, useCallback } from 'react';\r\nimport { useTranslations } from 'next-intl';\r\nimport { toast } from 'sonner';\r\nimport { Toast } from '../../ui/feedback/Toast';\r\nimport useCountdownTimer from '../../../hooks/useCountdownTimer';\r\nimport { OTP_CODE_LENGTH, VALID_OTP_CODE } from '../../../utils/validators/account';\r\nimport { hasExactLength } from '../../../utils/validators/common';\r\n\r\ninterface UseOtpVerificationOptions {\r\n onSuccess: () => void;\r\n successMessage: string;\r\n validateFn?: (code: string) => Promise<boolean>;\r\n resendFn?: () => Promise<void>;\r\n}\r\n\r\nexport default function useOtpVerification({\r\n onSuccess,\r\n successMessage,\r\n validateFn,\r\n resendFn,\r\n}: UseOtpVerificationOptions) {\r\n const translate = useTranslations();\r\n const [code, setCode] = useState('');\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [hasError, setHasError] = useState(false);\r\n\r\n const {\r\n seconds: timer,\r\n isExpired: canResend,\r\n reset: resetTimer,\r\n } = useCountdownTimer({ initialSeconds: 59 });\r\n\r\n const handleCodeChange = useCallback(\r\n (value: string) => {\r\n setCode(value.toUpperCase());\r\n if (hasError) {\r\n setHasError(false);\r\n }\r\n },\r\n [hasError]\r\n );\r\n\r\n const handleValidate = useCallback(async () => {\r\n if (!hasExactLength(code, OTP_CODE_LENGTH)) return;\r\n\r\n setIsLoading(true);\r\n setHasError(false);\r\n\r\n try {\r\n let isValid: boolean;\r\n\r\n if (validateFn) {\r\n isValid = await validateFn(code);\r\n } else {\r\n await new Promise((resolve) => setTimeout(resolve, 500));\r\n isValid = code === VALID_OTP_CODE;\r\n }\r\n\r\n if (!isValid) {\r\n setHasError(true);\r\n return;\r\n }\r\n\r\n toast.custom((t) => <Toast variant=\"success\" message={successMessage} toastId={t} />);\r\n\r\n setCode('');\r\n onSuccess();\r\n } catch (error) {\r\n console.error('Erro ao validar código:', error);\r\n setHasError(true);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [code, onSuccess, successMessage, validateFn]);\r\n\r\n const handleResend = useCallback(async () => {\r\n if (!canResend) return;\r\n\r\n try {\r\n resetTimer();\r\n setHasError(false);\r\n setCode('');\r\n\r\n if (resendFn) {\r\n await resendFn();\r\n }\r\n\r\n toast.custom((toastId) => (\r\n <Toast\r\n variant=\"success\"\r\n message={translate('common.account.twoFactor.codeResent')}\r\n toastId={toastId}\r\n />\r\n ));\r\n } catch (error) {\r\n console.error('Erro ao reenviar código:', error);\r\n toast.custom((toastId) => (\r\n <Toast\r\n variant=\"error\"\r\n message={translate('common.account.twoFactor.resendError')}\r\n toastId={toastId}\r\n />\r\n ));\r\n }\r\n }, [canResend, resetTimer, resendFn, translate]);\r\n\r\n const reset = useCallback(() => {\r\n setCode('');\r\n setHasError(false);\r\n }, []);\r\n\r\n const isValidLength = hasExactLength(code, OTP_CODE_LENGTH);\r\n\r\n return {\r\n code,\r\n isLoading,\r\n hasError,\r\n timer,\r\n canResend,\r\n isValidLength,\r\n handleCodeChange,\r\n handleValidate,\r\n handleResend,\r\n reset,\r\n };\r\n}\r\n"],"mappings":";AAiE0B;AA/D1B,SAAS,UAAU,mBAAmB;AACtC,SAAS,uBAAuB;AAChC,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,OAAO,uBAAuB;AAC9B,SAAS,iBAAiB,sBAAsB;AAChD,SAAS,sBAAsB;AAShB,SAAR,mBAAoC;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA8B;AAC5B,QAAM,YAAY,gBAAgB;AAClC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE;AACnC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAE9C,QAAM;AAAA,IACJ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,OAAO;AAAA,EACT,IAAI,kBAAkB,EAAE,gBAAgB,GAAG,CAAC;AAE5C,QAAM,mBAAmB;AAAA,IACvB,CAAC,UAAkB;AACjB,cAAQ,MAAM,YAAY,CAAC;AAC3B,UAAI,UAAU;AACZ,oBAAY,KAAK;AAAA,MACnB;AAAA,IACF;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,iBAAiB,YAAY,YAAY;AAC7C,QAAI,CAAC,eAAe,MAAM,eAAe,EAAG;AAE5C,iBAAa,IAAI;AACjB,gBAAY,KAAK;AAEjB,QAAI;AACF,UAAI;AAEJ,UAAI,YAAY;AACd,kBAAU,MAAM,WAAW,IAAI;AAAA,MACjC,OAAO;AACL,cAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAG,CAAC;AACvD,kBAAU,SAAS;AAAA,MACrB;AAEA,UAAI,CAAC,SAAS;AACZ,oBAAY,IAAI;AAChB;AAAA,MACF;AAEA,YAAM,OAAO,CAAC,MAAM,oBAAC,SAAM,SAAQ,WAAU,SAAS,gBAAgB,SAAS,GAAG,CAAE;AAEpF,cAAQ,EAAE;AACV,gBAAU;AAAA,IACZ,SAAS,OAAO;AACd,cAAQ,MAAM,8BAA2B,KAAK;AAC9C,kBAAY,IAAI;AAAA,IAClB,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,MAAM,WAAW,gBAAgB,UAAU,CAAC;AAEhD,QAAM,eAAe,YAAY,YAAY;AAC3C,QAAI,CAAC,UAAW;AAEhB,QAAI;AACF,iBAAW;AACX,kBAAY,KAAK;AACjB,cAAQ,EAAE;AAEV,UAAI,UAAU;AACZ,cAAM,SAAS;AAAA,MACjB;AAEA,YAAM,OAAO,CAAC,YACZ;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS,UAAU,qCAAqC;AAAA,UACxD;AAAA;AAAA,MACF,CACD;AAAA,IACH,SAAS,OAAO;AACd,cAAQ,MAAM,+BAA4B,KAAK;AAC/C,YAAM,OAAO,CAAC,YACZ;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS,UAAU,sCAAsC;AAAA,UACzD;AAAA;AAAA,MACF,CACD;AAAA,IACH;AAAA,EACF,GAAG,CAAC,WAAW,YAAY,UAAU,SAAS,CAAC;AAE/C,QAAM,QAAQ,YAAY,MAAM;AAC9B,YAAQ,EAAE;AACV,gBAAY,KAAK;AAAA,EACnB,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgB,eAAe,MAAM,eAAe;AAE1D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useCallback, useEffect } from "react";
|
|
4
4
|
import { useMutation } from "@tanstack/react-query";
|
|
5
|
+
import { useTranslations } from "next-intl";
|
|
5
6
|
import { toast } from "sonner";
|
|
6
7
|
import { Toast } from "../../ui/feedback/Toast";
|
|
7
8
|
import { copyToClipboard } from "../../../utils/browser/clipboard";
|
|
@@ -11,12 +12,20 @@ import {
|
|
|
11
12
|
} from "../../../modules/accounts/actions/account-management.action";
|
|
12
13
|
import { withAction } from "../../../utils/withAction";
|
|
13
14
|
function useTwoFactorAuthForm({ onSuccess, open } = {}) {
|
|
15
|
+
const translate = useTranslations();
|
|
14
16
|
const [code, setCode] = useState("");
|
|
15
17
|
const [step, setStep] = useState("code");
|
|
16
18
|
const generateMutation = useMutation({
|
|
17
19
|
mutationFn: withAction(generateTwoFactorAction),
|
|
18
20
|
onError: () => {
|
|
19
|
-
toast.custom((
|
|
21
|
+
toast.custom((toastId) => /* @__PURE__ */ jsx(
|
|
22
|
+
Toast,
|
|
23
|
+
{
|
|
24
|
+
variant: "error",
|
|
25
|
+
message: translate("common.account.twoFactor.generateError"),
|
|
26
|
+
toastId
|
|
27
|
+
}
|
|
28
|
+
));
|
|
20
29
|
}
|
|
21
30
|
});
|
|
22
31
|
const confirmMutation = useMutation({
|
|
@@ -26,7 +35,14 @@ function useTwoFactorAuthForm({ onSuccess, open } = {}) {
|
|
|
26
35
|
},
|
|
27
36
|
onError: () => {
|
|
28
37
|
setCode("");
|
|
29
|
-
toast.custom((
|
|
38
|
+
toast.custom((toastId) => /* @__PURE__ */ jsx(
|
|
39
|
+
Toast,
|
|
40
|
+
{
|
|
41
|
+
variant: "error",
|
|
42
|
+
message: translate("common.account.twoFactor.confirmError"),
|
|
43
|
+
toastId
|
|
44
|
+
}
|
|
45
|
+
));
|
|
30
46
|
}
|
|
31
47
|
});
|
|
32
48
|
const { mutate: triggerGenerate } = generateMutation;
|
|
@@ -49,9 +65,16 @@ function useTwoFactorAuthForm({ onSuccess, open } = {}) {
|
|
|
49
65
|
const codes = generateMutation.data?.backupCodes ?? [];
|
|
50
66
|
const success = await copyToClipboard(codes.join("\n"));
|
|
51
67
|
if (success) {
|
|
52
|
-
toast.custom((
|
|
68
|
+
toast.custom((toastId) => /* @__PURE__ */ jsx(
|
|
69
|
+
Toast,
|
|
70
|
+
{
|
|
71
|
+
variant: "success",
|
|
72
|
+
message: translate("common.account.twoFactor.codesCopied"),
|
|
73
|
+
toastId
|
|
74
|
+
}
|
|
75
|
+
));
|
|
53
76
|
}
|
|
54
|
-
}, [generateMutation.data]);
|
|
77
|
+
}, [generateMutation.data, translate]);
|
|
55
78
|
const resetForm = () => {
|
|
56
79
|
setCode("");
|
|
57
80
|
setStep("code");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/account/hooks/useTwoFactorAuthForm.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useCallback, useEffect } from 'react';\nimport { useMutation } from '@tanstack/react-query';\nimport { toast } from 'sonner';\nimport { Toast } from '../../ui/feedback/Toast';\nimport { copyToClipboard } from '../../../utils/browser/clipboard';\nimport {\n generateTwoFactorAction,\n confirmTwoFactorAction,\n} from '../../../modules/accounts/actions/account-management.action';\nimport { withAction } from '../../../utils/withAction';\n\ntype Step = 'code' | 'recovery';\n\ninterface UseTwoFactorAuthFormProps {\n onSuccess?: () => void;\n open?: boolean;\n}\n\nexport default function useTwoFactorAuthForm({ onSuccess, open }: UseTwoFactorAuthFormProps = {}) {\n const [code, setCode] = useState('');\n const [step, setStep] = useState<Step>('code');\n\n const generateMutation = useMutation({\n mutationFn: withAction(generateTwoFactorAction),\n onError: () => {\n toast.custom((
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/account/hooks/useTwoFactorAuthForm.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useCallback, useEffect } from 'react';\nimport { useMutation } from '@tanstack/react-query';\nimport { useTranslations } from 'next-intl';\nimport { toast } from 'sonner';\nimport { Toast } from '../../ui/feedback/Toast';\nimport { copyToClipboard } from '../../../utils/browser/clipboard';\nimport {\n generateTwoFactorAction,\n confirmTwoFactorAction,\n} from '../../../modules/accounts/actions/account-management.action';\nimport { withAction } from '../../../utils/withAction';\n\ntype Step = 'code' | 'recovery';\n\ninterface UseTwoFactorAuthFormProps {\n onSuccess?: () => void;\n open?: boolean;\n}\n\nexport default function useTwoFactorAuthForm({ onSuccess, open }: UseTwoFactorAuthFormProps = {}) {\n const translate = useTranslations();\n const [code, setCode] = useState('');\n const [step, setStep] = useState<Step>('code');\n\n const generateMutation = useMutation({\n mutationFn: withAction(generateTwoFactorAction),\n onError: () => {\n toast.custom((toastId) => (\n <Toast\n variant=\"error\"\n message={translate('common.account.twoFactor.generateError')}\n toastId={toastId}\n />\n ));\n },\n });\n\n const confirmMutation = useMutation({\n mutationFn: withAction(confirmTwoFactorAction),\n onSuccess: () => {\n setStep('recovery');\n },\n onError: () => {\n setCode('');\n toast.custom((toastId) => (\n <Toast\n variant=\"error\"\n message={translate('common.account.twoFactor.confirmError')}\n toastId={toastId}\n />\n ));\n },\n });\n\n const { mutate: triggerGenerate } = generateMutation;\n\n useEffect(() => {\n if (open) {\n triggerGenerate();\n }\n }, [open, triggerGenerate]);\n\n const generateFailed = generateMutation.isError;\n\n const isCodeComplete = code.length === 6;\n\n const handleSubmit = () => {\n if (!isCodeComplete) return;\n confirmMutation.mutate(code);\n };\n\n const handleFinalize = () => {\n onSuccess?.();\n setTimeout(resetForm, 300);\n };\n\n const handleCopyCodes = useCallback(async () => {\n const codes = generateMutation.data?.backupCodes ?? [];\n const success = await copyToClipboard(codes.join('\\n'));\n if (success) {\n toast.custom((toastId) => (\n <Toast\n variant=\"success\"\n message={translate('common.account.twoFactor.codesCopied')}\n toastId={toastId}\n />\n ));\n }\n }, [generateMutation.data, translate]);\n\n const resetForm = () => {\n setCode('');\n setStep('code');\n generateMutation.reset();\n confirmMutation.reset();\n };\n\n return {\n code,\n setCode,\n isCodeComplete,\n isGenerating: generateMutation.isPending,\n isConfirming: confirmMutation.isPending,\n generateFailed,\n retryGenerate: triggerGenerate,\n qrcode: generateMutation.data?.qrcode,\n backupCodes: generateMutation.data?.backupCodes ?? [],\n step,\n handleSubmit,\n handleFinalize,\n handleCopyCodes,\n resetForm,\n };\n}\n"],"mappings":";AA8BQ;AA5BR,SAAS,UAAU,aAAa,iBAAiB;AACjD,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAChC,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AASZ,SAAR,qBAAsC,EAAE,WAAW,KAAK,IAA+B,CAAC,GAAG;AAChG,QAAM,YAAY,gBAAgB;AAClC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE;AACnC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAe,MAAM;AAE7C,QAAM,mBAAmB,YAAY;AAAA,IACnC,YAAY,WAAW,uBAAuB;AAAA,IAC9C,SAAS,MAAM;AACb,YAAM,OAAO,CAAC,YACZ;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS,UAAU,wCAAwC;AAAA,UAC3D;AAAA;AAAA,MACF,CACD;AAAA,IACH;AAAA,EACF,CAAC;AAED,QAAM,kBAAkB,YAAY;AAAA,IAClC,YAAY,WAAW,sBAAsB;AAAA,IAC7C,WAAW,MAAM;AACf,cAAQ,UAAU;AAAA,IACpB;AAAA,IACA,SAAS,MAAM;AACb,cAAQ,EAAE;AACV,YAAM,OAAO,CAAC,YACZ;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS,UAAU,uCAAuC;AAAA,UAC1D;AAAA;AAAA,MACF,CACD;AAAA,IACH;AAAA,EACF,CAAC;AAED,QAAM,EAAE,QAAQ,gBAAgB,IAAI;AAEpC,YAAU,MAAM;AACd,QAAI,MAAM;AACR,sBAAgB;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,MAAM,eAAe,CAAC;AAE1B,QAAM,iBAAiB,iBAAiB;AAExC,QAAM,iBAAiB,KAAK,WAAW;AAEvC,QAAM,eAAe,MAAM;AACzB,QAAI,CAAC,eAAgB;AACrB,oBAAgB,OAAO,IAAI;AAAA,EAC7B;AAEA,QAAM,iBAAiB,MAAM;AAC3B,gBAAY;AACZ,eAAW,WAAW,GAAG;AAAA,EAC3B;AAEA,QAAM,kBAAkB,YAAY,YAAY;AAC9C,UAAM,QAAQ,iBAAiB,MAAM,eAAe,CAAC;AACrD,UAAM,UAAU,MAAM,gBAAgB,MAAM,KAAK,IAAI,CAAC;AACtD,QAAI,SAAS;AACX,YAAM,OAAO,CAAC,YACZ;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS,UAAU,sCAAsC;AAAA,UACzD;AAAA;AAAA,MACF,CACD;AAAA,IACH;AAAA,EACF,GAAG,CAAC,iBAAiB,MAAM,SAAS,CAAC;AAErC,QAAM,YAAY,MAAM;AACtB,YAAQ,EAAE;AACV,YAAQ,MAAM;AACd,qBAAiB,MAAM;AACvB,oBAAgB,MAAM;AAAA,EACxB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,iBAAiB;AAAA,IAC/B,cAAc,gBAAgB;AAAA,IAC9B;AAAA,IACA,eAAe;AAAA,IACf,QAAQ,iBAAiB,MAAM;AAAA,IAC/B,aAAa,iBAAiB,MAAM,eAAe,CAAC;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useTranslations } from "next-intl";
|
|
3
4
|
import { IconChevronLeft, IconX, IconMail } from "@tabler/icons-react";
|
|
4
5
|
import { Button } from "../../ui/buttons/Button";
|
|
5
6
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../../ui/overlay/Dialog";
|
|
@@ -14,6 +15,7 @@ import { confirmEmailChangeAction } from "../../../modules/accounts/actions/acco
|
|
|
14
15
|
import useChangeEmailForm from "../hooks/useChangeEmailForm";
|
|
15
16
|
import useOtpVerification from "../hooks/useOtpVerification";
|
|
16
17
|
function ChangeEmailModal({ open, onClose }) {
|
|
18
|
+
const translate = useTranslations();
|
|
17
19
|
const { user } = useAuth();
|
|
18
20
|
const invalidateUser = useInvalidateUser();
|
|
19
21
|
const {
|
|
@@ -44,7 +46,7 @@ function ChangeEmailModal({ open, onClose }) {
|
|
|
44
46
|
reset: resetOtp
|
|
45
47
|
} = useOtpVerification({
|
|
46
48
|
onSuccess: handleSuccess,
|
|
47
|
-
successMessage: "
|
|
49
|
+
successMessage: translate("common.account.changeEmail.emailChanged"),
|
|
48
50
|
validateFn: async (token) => {
|
|
49
51
|
const result = await confirmEmailChangeAction(token, emailToVerify);
|
|
50
52
|
return result.success;
|
|
@@ -75,12 +77,12 @@ function ChangeEmailModal({ open, onClose }) {
|
|
|
75
77
|
children: [
|
|
76
78
|
showVerification ? /* @__PURE__ */ jsxs(DialogHeader, { className: "flex flex-row items-center justify-between px-4 py-3 border-b border-gray-200 lg:border-b-0", children: [
|
|
77
79
|
/* @__PURE__ */ jsx(Button, { variant: "ghost", className: "size-8! p-0", onClick: handleBackFromVerification, children: /* @__PURE__ */ jsx(IconChevronLeft, { size: 20, className: "text-gray-950" }) }),
|
|
78
|
-
/* @__PURE__ */ jsx(DialogTitle, { className: "paragraph-medium-semibold text-gray-950 text-center flex-1", children: "
|
|
80
|
+
/* @__PURE__ */ jsx(DialogTitle, { className: "paragraph-medium-semibold text-gray-950 text-center flex-1", children: translate("common.account.changeEmail.title") }),
|
|
79
81
|
/* @__PURE__ */ jsx(Button, { variant: "ghost", className: "size-8! p-0", onClick: handleClose, children: /* @__PURE__ */ jsx(IconX, { size: 18, className: "text-gray-500" }) })
|
|
80
82
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
81
|
-
/* @__PURE__ */ jsx(DialogHeader, { className: "sr-only", children: /* @__PURE__ */ jsx(DialogTitle, { children: "
|
|
83
|
+
/* @__PURE__ */ jsx(DialogHeader, { className: "sr-only", children: /* @__PURE__ */ jsx(DialogTitle, { children: translate("common.account.changeEmail.title") }) }),
|
|
82
84
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0", children: [
|
|
83
|
-
/* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950 text-center", children: "
|
|
85
|
+
/* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950 text-center", children: translate("common.account.changeEmail.title") }),
|
|
84
86
|
/* @__PURE__ */ jsx(
|
|
85
87
|
Button,
|
|
86
88
|
{
|
|
@@ -105,15 +107,11 @@ function ChangeEmailModal({ open, onClose }) {
|
|
|
105
107
|
/* @__PURE__ */ jsxs("div", { className: "px-4 lg:px-5 py-5 lg:py-6 flex flex-col gap-4 flex-1 lg:flex-none", children: [
|
|
106
108
|
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center size-12 bg-white rounded-lg shadow-xs border border-gray-200", children: /* @__PURE__ */ jsx(IconMail, { size: 20, className: "text-gray-950" }) }),
|
|
107
109
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
108
|
-
/* @__PURE__ */ jsx("h3", { className: "paragraph-medium-semibold text-gray-950", children: "
|
|
109
|
-
/* @__PURE__ */
|
|
110
|
-
|
|
111
|
-
" ",
|
|
112
|
-
|
|
113
|
-
user?.email,
|
|
114
|
-
"."
|
|
115
|
-
] })
|
|
116
|
-
] })
|
|
110
|
+
/* @__PURE__ */ jsx("h3", { className: "paragraph-medium-semibold text-gray-950", children: translate("common.account.otp.validationCode") }),
|
|
111
|
+
/* @__PURE__ */ jsx("p", { className: "paragraph-small-regular text-gray-600", children: translate.rich("common.account.changeEmail.sentCodeTo", {
|
|
112
|
+
email: user?.email ?? "",
|
|
113
|
+
b: (chunks) => /* @__PURE__ */ jsx("span", { className: "font-semibold text-gray-950 break-all", children: chunks })
|
|
114
|
+
}) })
|
|
117
115
|
] }),
|
|
118
116
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
119
117
|
/* @__PURE__ */ jsx(InputOTP, { maxLength: OTP_CODE_LENGTH, pattern: OTP_ALPHANUMERIC_PATTERN, value: code, onChange: handleCodeChange, children: /* @__PURE__ */ jsx(InputOTPGroup, { className: "flex flex-row gap-2", children: [...Array(OTP_CODE_LENGTH)].map((_, i) => /* @__PURE__ */ jsx(
|
|
@@ -124,7 +122,7 @@ function ChangeEmailModal({ open, onClose }) {
|
|
|
124
122
|
},
|
|
125
123
|
i
|
|
126
124
|
)) }) }),
|
|
127
|
-
hasError && /* @__PURE__ */ jsx("p", { className: "paragraph-small-regular text-red-500", children: "
|
|
125
|
+
hasError && /* @__PURE__ */ jsx("p", { className: "paragraph-small-regular text-red-500", children: translate("common.account.otp.incorrectCode") })
|
|
128
126
|
] }),
|
|
129
127
|
canResend ? /* @__PURE__ */ jsx(
|
|
130
128
|
"button",
|
|
@@ -132,32 +130,31 @@ function ChangeEmailModal({ open, onClose }) {
|
|
|
132
130
|
type: "button",
|
|
133
131
|
onClick: handleResend,
|
|
134
132
|
className: "paragraph-small-medium text-gray-950 underline cursor-pointer hover:text-gray-700 w-fit",
|
|
135
|
-
children: "
|
|
133
|
+
children: translate("common.account.otp.resend")
|
|
136
134
|
}
|
|
137
|
-
) : /* @__PURE__ */
|
|
138
|
-
|
|
139
|
-
" ",
|
|
140
|
-
|
|
141
|
-
] })
|
|
135
|
+
) : /* @__PURE__ */ jsx("p", { className: "paragraph-small-regular text-gray-500", children: translate.rich("common.account.otp.resendIn", {
|
|
136
|
+
time: formatTimer(timer),
|
|
137
|
+
b: (chunks) => /* @__PURE__ */ jsx("span", { className: "paragraph-small-semibold text-gray-950", children: chunks })
|
|
138
|
+
}) })
|
|
142
139
|
] }),
|
|
143
140
|
/* @__PURE__ */ jsx(Separator, {}),
|
|
144
141
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 lg:px-5 py-4 lg:py-5 mt-auto lg:mt-0", children: [
|
|
145
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", className: "h-10!", type: "button", onClick: handleClose, children: "
|
|
146
|
-
/* @__PURE__ */ jsx(Button, { className: "h-10!", type: "submit", disabled: !isValidLength || isLoading, children: isLoading ? "
|
|
142
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", className: "h-10!", type: "button", onClick: handleClose, children: translate("common.actions.cancel") }),
|
|
143
|
+
/* @__PURE__ */ jsx(Button, { className: "h-10!", type: "submit", disabled: !isValidLength || isLoading, children: isLoading ? translate("common.account.otp.validating") : translate("common.account.changeEmail.confirm") })
|
|
147
144
|
] })
|
|
148
145
|
]
|
|
149
146
|
}
|
|
150
147
|
) : /* @__PURE__ */ jsxs("form", { onSubmit: handleContinue, className: "flex flex-col flex-1 lg:flex-none", children: [
|
|
151
148
|
/* @__PURE__ */ jsxs("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", children: [
|
|
152
149
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
153
|
-
/* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950", children: "
|
|
154
|
-
/* @__PURE__ */ jsx("span", { className: "paragraph-small-regular text-gray-600", children: "
|
|
150
|
+
/* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950", children: translate("common.account.changeEmail.updateTitle") }),
|
|
151
|
+
/* @__PURE__ */ jsx("span", { className: "paragraph-small-regular text-gray-600", children: translate("common.account.changeEmail.updateDescription") })
|
|
155
152
|
] }),
|
|
156
153
|
/* @__PURE__ */ jsx(
|
|
157
154
|
FormField,
|
|
158
155
|
{
|
|
159
|
-
label: "
|
|
160
|
-
placeholder: "
|
|
156
|
+
label: translate("common.account.changeEmail.newEmail"),
|
|
157
|
+
placeholder: translate("common.account.changeEmail.newEmailPlaceholder"),
|
|
161
158
|
type: "email",
|
|
162
159
|
...register("email"),
|
|
163
160
|
error: !!errors.email,
|
|
@@ -167,8 +164,8 @@ function ChangeEmailModal({ open, onClose }) {
|
|
|
167
164
|
)
|
|
168
165
|
] }),
|
|
169
166
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0", children: [
|
|
170
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", className: "h-10!", type: "button", onClick: handleClose, children: "
|
|
171
|
-
/* @__PURE__ */ jsx(Button, { className: "h-10!", type: "submit", disabled: isSubmitting, children: isSubmitting ? "
|
|
167
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", className: "h-10!", type: "button", onClick: handleClose, children: translate("common.actions.cancel") }),
|
|
168
|
+
/* @__PURE__ */ jsx(Button, { className: "h-10!", type: "submit", disabled: isSubmitting, children: isSubmitting ? translate("common.actions.sending") : translate("common.actions.continue") })
|
|
172
169
|
] })
|
|
173
170
|
] })
|
|
174
171
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/account/sections/ChangeEmailModal.tsx"],"sourcesContent":["'use client';\n\nimport { IconChevronLeft, IconX, IconMail } from '@tabler/icons-react';\nimport { Button } from '../../ui/buttons/Button';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\nimport { Separator } from '../../ui/data-display/Separator';\nimport { InputOTP, InputOTPGroup, InputOTPSlot } from '../../ui/form/InputOtp';\nimport { FormField } from '../../ui/form/FormField';\nimport { formatTimer } from '../../../utils/format/masks';\nimport { OTP_CODE_LENGTH, OTP_ALPHANUMERIC_PATTERN } from '../../../utils/validators/account';\nimport { useAuth } from '../../../providers/auth.provider';\nimport { useInvalidateUser } from '../../../modules/auth/hooks/useUserQuery';\nimport { confirmEmailChangeAction } from '../../../modules/accounts/actions/account-management.action';\nimport useChangeEmailForm from '../hooks/useChangeEmailForm';\nimport useOtpVerification from '../hooks/useOtpVerification';\n\ninterface ChangeEmailModalProps {\n open: boolean;\n onClose: () => void;\n}\n\nexport function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {\n const { user } = useAuth();\n const invalidateUser = useInvalidateUser();\n\n const {\n showVerification,\n emailToVerify,\n isSubmitting,\n errors,\n register,\n handleContinue,\n handleBack,\n resetForm,\n } = useChangeEmailForm();\n\n const handleSuccess = () => {\n invalidateUser();\n resetForm();\n onClose();\n };\n\n const {\n code,\n isLoading,\n hasError,\n timer,\n canResend,\n isValidLength,\n handleCodeChange,\n handleValidate,\n handleResend,\n reset: resetOtp,\n } = useOtpVerification({\n onSuccess: handleSuccess,\n successMessage: 'E-mail alterado com sucesso',\n validateFn: async (token) => {\n const result = await confirmEmailChangeAction(token, emailToVerify);\n return result.success;\n },\n resendFn: async () => {\n const { requestEmailChangeAction } = await import('../../../modules/accounts/actions/account-management.action');\n const result = await requestEmailChangeAction(emailToVerify);\n if (!result.success) {\n throw new Error(result.error);\n }\n },\n });\n\n const handleClose = () => {\n resetForm();\n resetOtp();\n onClose();\n };\n\n const handleBackFromVerification = () => {\n resetOtp();\n handleBack();\n };\n\n return (\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n overlayClassName=\"z-[1002]\"\n className=\"flex flex-col p-0 gap-0 max-w-full sm: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]\"\n >\n {showVerification ? (\n <DialogHeader className=\"flex flex-row items-center justify-between px-4 py-3 border-b border-gray-200 lg:border-b-0\">\n <Button variant=\"ghost\" className=\"size-8! p-0\" onClick={handleBackFromVerification}>\n <IconChevronLeft size={20} className=\"text-gray-950\" />\n </Button>\n <DialogTitle className=\"paragraph-medium-semibold text-gray-950 text-center flex-1\">\n Alterar e-mail\n </DialogTitle>\n <Button variant=\"ghost\" className=\"size-8! p-0\" onClick={handleClose}>\n <IconX size={18} className=\"text-gray-500\" />\n </Button>\n </DialogHeader>\n ) : (\n <>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>Alterar e-mail</DialogTitle>\n </DialogHeader>\n <div className=\"flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0\">\n <span className=\"paragraph-medium-semibold text-gray-950 text-center\">\n Alterar e-mail\n </span>\n <Button\n variant=\"ghost\"\n className=\"absolute right-2 size-8! p-0\"\n onClick={handleClose}\n >\n <IconX size={18} className=\"text-gray-500\" />\n </Button>\n </div>\n </>\n )}\n\n <div className={`${showVerification ? 'w-full' : 'w-1/2'} h-0.75 bg-primary`} />\n\n {showVerification ? (\n <form\n onSubmit={(e) => {\n e.preventDefault();\n handleValidate();\n }}\n className=\"flex flex-col flex-1 lg:flex-none\"\n >\n <div className=\"px-4 lg:px-5 py-5 lg:py-6 flex flex-col gap-4 flex-1 lg:flex-none\">\n <div className=\"flex items-center justify-center size-12 bg-white rounded-lg shadow-xs border border-gray-200\">\n <IconMail size={20} className=\"text-gray-950\" />\n </div>\n\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"paragraph-medium-semibold text-gray-950\">Código de validação</h3>\n <p className=\"paragraph-small-regular text-gray-600\">\n Enviamos um código de validação para o E-mail{' '}\n <span className=\"font-semibold text-gray-950 break-all\">{user?.email}.</span>\n </p>\n </div>\n\n <div className=\"flex flex-col gap-2\">\n <InputOTP maxLength={OTP_CODE_LENGTH} pattern={OTP_ALPHANUMERIC_PATTERN} value={code} onChange={handleCodeChange}>\n <InputOTPGroup className=\"flex flex-row gap-2\">\n {[...Array(OTP_CODE_LENGTH)].map((_, i) => (\n <InputOTPSlot\n key={i}\n index={i}\n 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'}`}\n />\n ))}\n </InputOTPGroup>\n </InputOTP>\n {hasError && (\n <p className=\"paragraph-small-regular text-red-500\">Código incorreto</p>\n )}\n </div>\n\n {canResend ? (\n <button\n type=\"button\"\n onClick={handleResend}\n className=\"paragraph-small-medium text-gray-950 underline cursor-pointer hover:text-gray-700 w-fit\"\n >\n Reenviar código\n </button>\n ) : (\n <p className=\"paragraph-small-regular text-gray-500\">\n Reenviar em{' '}\n <span className=\"paragraph-small-semibold text-gray-950\">\n {formatTimer(timer)}\n </span>\n </p>\n )}\n </div>\n\n <Separator />\n\n <div className=\"flex items-center justify-between px-4 lg:px-5 py-4 lg:py-5 mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n Cancelar\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={!isValidLength || isLoading}>\n {isLoading ? 'Validando...' : 'Alterar e-mail'}\n </Button>\n </div>\n </form>\n ) : (\n <form onSubmit={handleContinue} className=\"flex flex-col flex-1 lg:flex-none\">\n <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\">\n <div className=\"flex flex-col gap-1\">\n <span className=\"paragraph-medium-semibold text-gray-950\">\n Atualizar E-mail de contato\n </span>\n <span className=\"paragraph-small-regular text-gray-600\">\n Informe o seu novo E-mail para manter seu contato atualizado.\n </span>\n </div>\n\n <FormField\n label=\"Novo e-mail\"\n placeholder=\"Digite seu novo e-mail\"\n type=\"email\"\n {...register('email')}\n error={!!errors.email}\n errorMessage={errors.email?.message}\n leftIcon={IconMail}\n />\n </div>\n\n <div className=\"flex items-center justify-between p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n Cancelar\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={isSubmitting}>\n {isSubmitting ? 'Enviando...' : 'Continuar'}\n </Button>\n </div>\n </form>\n )}\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/account/sections/ChangeEmailModal.tsx"],"sourcesContent":["'use client';\n\nimport { useTranslations } from 'next-intl';\nimport { IconChevronLeft, IconX, IconMail } from '@tabler/icons-react';\nimport { Button } from '../../ui/buttons/Button';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\nimport { Separator } from '../../ui/data-display/Separator';\nimport { InputOTP, InputOTPGroup, InputOTPSlot } from '../../ui/form/InputOtp';\nimport { FormField } from '../../ui/form/FormField';\nimport { formatTimer } from '../../../utils/format/masks';\nimport { OTP_CODE_LENGTH, OTP_ALPHANUMERIC_PATTERN } from '../../../utils/validators/account';\nimport { useAuth } from '../../../providers/auth.provider';\nimport { useInvalidateUser } from '../../../modules/auth/hooks/useUserQuery';\nimport { confirmEmailChangeAction } from '../../../modules/accounts/actions/account-management.action';\nimport useChangeEmailForm from '../hooks/useChangeEmailForm';\nimport useOtpVerification from '../hooks/useOtpVerification';\n\ninterface ChangeEmailModalProps {\n open: boolean;\n onClose: () => void;\n}\n\nexport function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {\n const translate = useTranslations();\n const { user } = useAuth();\n const invalidateUser = useInvalidateUser();\n\n const {\n showVerification,\n emailToVerify,\n isSubmitting,\n errors,\n register,\n handleContinue,\n handleBack,\n resetForm,\n } = useChangeEmailForm();\n\n const handleSuccess = () => {\n invalidateUser();\n resetForm();\n onClose();\n };\n\n const {\n code,\n isLoading,\n hasError,\n timer,\n canResend,\n isValidLength,\n handleCodeChange,\n handleValidate,\n handleResend,\n reset: resetOtp,\n } = useOtpVerification({\n onSuccess: handleSuccess,\n successMessage: translate('common.account.changeEmail.emailChanged'),\n validateFn: async (token) => {\n const result = await confirmEmailChangeAction(token, emailToVerify);\n return result.success;\n },\n resendFn: async () => {\n const { requestEmailChangeAction } = await import('../../../modules/accounts/actions/account-management.action');\n const result = await requestEmailChangeAction(emailToVerify);\n if (!result.success) {\n throw new Error(result.error);\n }\n },\n });\n\n const handleClose = () => {\n resetForm();\n resetOtp();\n onClose();\n };\n\n const handleBackFromVerification = () => {\n resetOtp();\n handleBack();\n };\n\n return (\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n overlayClassName=\"z-[1002]\"\n className=\"flex flex-col p-0 gap-0 max-w-full sm: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]\"\n >\n {showVerification ? (\n <DialogHeader className=\"flex flex-row items-center justify-between px-4 py-3 border-b border-gray-200 lg:border-b-0\">\n <Button variant=\"ghost\" className=\"size-8! p-0\" onClick={handleBackFromVerification}>\n <IconChevronLeft size={20} className=\"text-gray-950\" />\n </Button>\n <DialogTitle className=\"paragraph-medium-semibold text-gray-950 text-center flex-1\">\n {translate('common.account.changeEmail.title')}\n </DialogTitle>\n <Button variant=\"ghost\" className=\"size-8! p-0\" onClick={handleClose}>\n <IconX size={18} className=\"text-gray-500\" />\n </Button>\n </DialogHeader>\n ) : (\n <>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{translate('common.account.changeEmail.title')}</DialogTitle>\n </DialogHeader>\n <div className=\"flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0\">\n <span className=\"paragraph-medium-semibold text-gray-950 text-center\">\n {translate('common.account.changeEmail.title')}\n </span>\n <Button\n variant=\"ghost\"\n className=\"absolute right-2 size-8! p-0\"\n onClick={handleClose}\n >\n <IconX size={18} className=\"text-gray-500\" />\n </Button>\n </div>\n </>\n )}\n\n <div className={`${showVerification ? 'w-full' : 'w-1/2'} h-0.75 bg-primary`} />\n\n {showVerification ? (\n <form\n onSubmit={(e) => {\n e.preventDefault();\n handleValidate();\n }}\n className=\"flex flex-col flex-1 lg:flex-none\"\n >\n <div className=\"px-4 lg:px-5 py-5 lg:py-6 flex flex-col gap-4 flex-1 lg:flex-none\">\n <div className=\"flex items-center justify-center size-12 bg-white rounded-lg shadow-xs border border-gray-200\">\n <IconMail size={20} className=\"text-gray-950\" />\n </div>\n\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"paragraph-medium-semibold text-gray-950\">\n {translate('common.account.otp.validationCode')}\n </h3>\n <p className=\"paragraph-small-regular text-gray-600\">\n {translate.rich('common.account.changeEmail.sentCodeTo', {\n email: user?.email ?? '',\n b: (chunks) => (\n <span className=\"font-semibold text-gray-950 break-all\">{chunks}</span>\n ),\n })}\n </p>\n </div>\n\n <div className=\"flex flex-col gap-2\">\n <InputOTP maxLength={OTP_CODE_LENGTH} pattern={OTP_ALPHANUMERIC_PATTERN} value={code} onChange={handleCodeChange}>\n <InputOTPGroup className=\"flex flex-row gap-2\">\n {[...Array(OTP_CODE_LENGTH)].map((_, i) => (\n <InputOTPSlot\n key={i}\n index={i}\n 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'}`}\n />\n ))}\n </InputOTPGroup>\n </InputOTP>\n {hasError && (\n <p className=\"paragraph-small-regular text-red-500\">\n {translate('common.account.otp.incorrectCode')}\n </p>\n )}\n </div>\n\n {canResend ? (\n <button\n type=\"button\"\n onClick={handleResend}\n className=\"paragraph-small-medium text-gray-950 underline cursor-pointer hover:text-gray-700 w-fit\"\n >\n {translate('common.account.otp.resend')}\n </button>\n ) : (\n <p className=\"paragraph-small-regular text-gray-500\">\n {translate.rich('common.account.otp.resendIn', {\n time: formatTimer(timer),\n b: (chunks) => (\n <span className=\"paragraph-small-semibold text-gray-950\">{chunks}</span>\n ),\n })}\n </p>\n )}\n </div>\n\n <Separator />\n\n <div className=\"flex items-center justify-between px-4 lg:px-5 py-4 lg:py-5 mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n {translate('common.actions.cancel')}\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={!isValidLength || isLoading}>\n {isLoading\n ? translate('common.account.otp.validating')\n : translate('common.account.changeEmail.confirm')}\n </Button>\n </div>\n </form>\n ) : (\n <form onSubmit={handleContinue} className=\"flex flex-col flex-1 lg:flex-none\">\n <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\">\n <div className=\"flex flex-col gap-1\">\n <span className=\"paragraph-medium-semibold text-gray-950\">\n {translate('common.account.changeEmail.updateTitle')}\n </span>\n <span className=\"paragraph-small-regular text-gray-600\">\n {translate('common.account.changeEmail.updateDescription')}\n </span>\n </div>\n\n <FormField\n label={translate('common.account.changeEmail.newEmail')}\n placeholder={translate('common.account.changeEmail.newEmailPlaceholder')}\n type=\"email\"\n {...register('email')}\n error={!!errors.email}\n errorMessage={errors.email?.message}\n leftIcon={IconMail}\n />\n </div>\n\n <div className=\"flex items-center justify-between p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n {translate('common.actions.cancel')}\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={isSubmitting}>\n {isSubmitting ? translate('common.actions.sending') : translate('common.actions.continue')}\n </Button>\n </div>\n </form>\n )}\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { IconLock, IconX } from "@tabler/icons-react";
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
4
5
|
import { Button } from "../../ui/buttons/Button";
|
|
5
6
|
import { FormField } from "../../ui/form/FormField";
|
|
6
7
|
import useChangePasswordForm from "../hooks/useChangePasswordForm";
|
|
7
8
|
import usePasswordVisibility from "../../../hooks/usePasswordVisibility";
|
|
8
9
|
function ChangePasswordSection({ onBack }) {
|
|
10
|
+
const translate = useTranslations();
|
|
9
11
|
const { register, handleSubmit, errors } = useChangePasswordForm({
|
|
10
12
|
onSuccess: onBack
|
|
11
13
|
});
|
|
@@ -18,16 +20,16 @@ function ChangePasswordSection({ onBack }) {
|
|
|
18
20
|
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",
|
|
19
21
|
children: [
|
|
20
22
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
21
|
-
/* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950", children: "
|
|
23
|
+
/* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950", children: translate("common.account.changePassword.title") }),
|
|
22
24
|
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", className: "size-8! p-0", onClick: onBack, children: /* @__PURE__ */ jsx(IconX, { size: 18 }) })
|
|
23
25
|
] }),
|
|
24
26
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
25
27
|
/* @__PURE__ */ jsx(
|
|
26
28
|
FormField,
|
|
27
29
|
{
|
|
28
|
-
label: "
|
|
30
|
+
label: translate("common.account.changePassword.currentPassword"),
|
|
29
31
|
type: "password",
|
|
30
|
-
placeholder: "
|
|
32
|
+
placeholder: translate("common.account.changePassword.currentPasswordPlaceholder"),
|
|
31
33
|
leftIcon: IconLock,
|
|
32
34
|
error: !!errors.currentPassword,
|
|
33
35
|
errorMessage: errors.currentPassword?.message,
|
|
@@ -40,9 +42,9 @@ function ChangePasswordSection({ onBack }) {
|
|
|
40
42
|
/* @__PURE__ */ jsx(
|
|
41
43
|
FormField,
|
|
42
44
|
{
|
|
43
|
-
label: "
|
|
45
|
+
label: translate("common.account.changePassword.newPassword"),
|
|
44
46
|
type: "password",
|
|
45
|
-
placeholder: "
|
|
47
|
+
placeholder: translate("common.account.changePassword.newPasswordPlaceholder"),
|
|
46
48
|
leftIcon: IconLock,
|
|
47
49
|
error: !!errors.newPassword,
|
|
48
50
|
errorMessage: errors.newPassword?.message,
|
|
@@ -53,7 +55,7 @@ function ChangePasswordSection({ onBack }) {
|
|
|
53
55
|
}
|
|
54
56
|
)
|
|
55
57
|
] }),
|
|
56
|
-
/* @__PURE__ */ jsx(Button, { type: "submit", className: "w-fit h-10!", children: "
|
|
58
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", className: "w-fit h-10!", children: translate("common.account.changePassword.submit") })
|
|
57
59
|
]
|
|
58
60
|
}
|
|
59
61
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/account/sections/ChangePasswordSection.tsx"],"sourcesContent":["'use client';\n\nimport { IconLock, IconX } from '@tabler/icons-react';\nimport { Button } from '../../ui/buttons/Button';\nimport { FormField } from '../../ui/form/FormField';\nimport useChangePasswordForm from '../hooks/useChangePasswordForm';\nimport usePasswordVisibility from '../../../hooks/usePasswordVisibility';\n\ninterface ChangePasswordSectionProps {\n onBack: () => void;\n}\n\nexport function ChangePasswordSection({ onBack }: ChangePasswordSectionProps) {\n const { register, handleSubmit, errors } = useChangePasswordForm({\n onSuccess: onBack,\n });\n const { showPassword: showCurrentPw, togglePassword: toggleCurrentPw } = usePasswordVisibility();\n const { showPassword: showNewPw, togglePassword: toggleNewPw } = usePasswordVisibility();\n\n return (\n <form\n onSubmit={handleSubmit}\n 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\"\n >\n <div className=\"flex items-center justify-between\">\n <span className=\"paragraph-medium-semibold text-gray-950\"
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/account/sections/ChangePasswordSection.tsx"],"sourcesContent":["'use client';\n\nimport { IconLock, IconX } from '@tabler/icons-react';\nimport { useTranslations } from 'next-intl';\nimport { Button } from '../../ui/buttons/Button';\nimport { FormField } from '../../ui/form/FormField';\nimport useChangePasswordForm from '../hooks/useChangePasswordForm';\nimport usePasswordVisibility from '../../../hooks/usePasswordVisibility';\n\ninterface ChangePasswordSectionProps {\n onBack: () => void;\n}\n\nexport function ChangePasswordSection({ onBack }: ChangePasswordSectionProps) {\n const translate = useTranslations();\n const { register, handleSubmit, errors } = useChangePasswordForm({\n onSuccess: onBack,\n });\n const { showPassword: showCurrentPw, togglePassword: toggleCurrentPw } = usePasswordVisibility();\n const { showPassword: showNewPw, togglePassword: toggleNewPw } = usePasswordVisibility();\n\n return (\n <form\n onSubmit={handleSubmit}\n 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\"\n >\n <div className=\"flex items-center justify-between\">\n <span className=\"paragraph-medium-semibold text-gray-950\">\n {translate('common.account.changePassword.title')}\n </span>\n <Button type=\"button\" variant=\"ghost\" className=\"size-8! p-0\" onClick={onBack}>\n <IconX size={18} />\n </Button>\n </div>\n\n <div className=\"flex flex-col gap-4\">\n <FormField\n label={translate('common.account.changePassword.currentPassword')}\n type=\"password\"\n placeholder={translate('common.account.changePassword.currentPasswordPlaceholder')}\n leftIcon={IconLock}\n error={!!errors.currentPassword}\n errorMessage={errors.currentPassword?.message}\n classnameContainer=\"h-10!\"\n showPassword={showCurrentPw}\n onTogglePassword={toggleCurrentPw}\n {...register('currentPassword')}\n />\n <FormField\n label={translate('common.account.changePassword.newPassword')}\n type=\"password\"\n placeholder={translate('common.account.changePassword.newPasswordPlaceholder')}\n leftIcon={IconLock}\n error={!!errors.newPassword}\n errorMessage={errors.newPassword?.message}\n classnameContainer=\"h-10!\"\n showPassword={showNewPw}\n onTogglePassword={toggleNewPw}\n {...register('newPassword')}\n />\n </div>\n\n <Button type=\"submit\" className=\"w-fit h-10!\">\n {translate('common.account.changePassword.submit')}\n </Button>\n </form>\n );\n}\n"],"mappings":";AA0BM,SACE,KADF;AAxBN,SAAS,UAAU,aAAa;AAChC,SAAS,uBAAuB;AAChC,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAC1B,OAAO,2BAA2B;AAClC,OAAO,2BAA2B;AAM3B,SAAS,sBAAsB,EAAE,OAAO,GAA+B;AAC5E,QAAM,YAAY,gBAAgB;AAClC,QAAM,EAAE,UAAU,cAAc,OAAO,IAAI,sBAAsB;AAAA,IAC/D,WAAW;AAAA,EACb,CAAC;AACD,QAAM,EAAE,cAAc,eAAe,gBAAgB,gBAAgB,IAAI,sBAAsB;AAC/F,QAAM,EAAE,cAAc,WAAW,gBAAgB,YAAY,IAAI,sBAAsB;AAEvF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV,WAAU;AAAA,MAEV;AAAA,6BAAC,SAAI,WAAU,qCACb;AAAA,8BAAC,UAAK,WAAU,2CACb,oBAAU,qCAAqC,GAClD;AAAA,UACA,oBAAC,UAAO,MAAK,UAAS,SAAQ,SAAQ,WAAU,eAAc,SAAS,QACrE,8BAAC,SAAM,MAAM,IAAI,GACnB;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,WAAU,uBACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO,UAAU,+CAA+C;AAAA,cAChE,MAAK;AAAA,cACL,aAAa,UAAU,0DAA0D;AAAA,cACjF,UAAU;AAAA,cACV,OAAO,CAAC,CAAC,OAAO;AAAA,cAChB,cAAc,OAAO,iBAAiB;AAAA,cACtC,oBAAmB;AAAA,cACnB,cAAc;AAAA,cACd,kBAAkB;AAAA,cACjB,GAAG,SAAS,iBAAiB;AAAA;AAAA,UAChC;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO,UAAU,2CAA2C;AAAA,cAC5D,MAAK;AAAA,cACL,aAAa,UAAU,sDAAsD;AAAA,cAC7E,UAAU;AAAA,cACV,OAAO,CAAC,CAAC,OAAO;AAAA,cAChB,cAAc,OAAO,aAAa;AAAA,cAClC,oBAAmB;AAAA,cACnB,cAAc;AAAA,cACd,kBAAkB;AAAA,cACjB,GAAG,SAAS,aAAa;AAAA;AAAA,UAC5B;AAAA,WACF;AAAA,QAEA,oBAAC,UAAO,MAAK,UAAS,WAAU,eAC7B,oBAAU,sCAAsC,GACnD;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useTranslations } from "next-intl";
|
|
3
4
|
import { IconChevronLeft, IconX, IconMessage } from "@tabler/icons-react";
|
|
4
5
|
import { Button } from "../../ui/buttons/Button";
|
|
5
6
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../../ui/overlay/Dialog";
|
|
@@ -14,6 +15,7 @@ import { confirmPhoneChangeAction } from "../../../modules/accounts/actions/acco
|
|
|
14
15
|
import useChangePhoneForm from "../hooks/useChangePhoneForm";
|
|
15
16
|
import useOtpVerification from "../hooks/useOtpVerification";
|
|
16
17
|
function ChangePhoneModal({ open, onClose }) {
|
|
18
|
+
const translate = useTranslations();
|
|
17
19
|
const { user } = useAuth();
|
|
18
20
|
const invalidateUser = useInvalidateUser();
|
|
19
21
|
const hasExistingPhone = !!user?.phone;
|
|
@@ -56,7 +58,7 @@ function ChangePhoneModal({ open, onClose }) {
|
|
|
56
58
|
reset: resetOtp
|
|
57
59
|
} = useOtpVerification({
|
|
58
60
|
onSuccess: handleSuccess,
|
|
59
|
-
successMessage: "
|
|
61
|
+
successMessage: translate("common.account.changePhone.phoneChanged"),
|
|
60
62
|
validateFn: async (token) => {
|
|
61
63
|
const result = await confirmPhoneChangeAction(token, submittedPhone.local, submittedPhone.ddi);
|
|
62
64
|
return result.success;
|
|
@@ -87,12 +89,12 @@ function ChangePhoneModal({ open, onClose }) {
|
|
|
87
89
|
children: [
|
|
88
90
|
showVerification ? /* @__PURE__ */ jsxs(DialogHeader, { className: "flex flex-row items-center justify-between px-4 py-3 border-b border-gray-200 lg:border-b-0", children: [
|
|
89
91
|
/* @__PURE__ */ jsx(Button, { variant: "ghost", className: "size-8! p-0", onClick: handleBackFromVerification, children: /* @__PURE__ */ jsx(IconChevronLeft, { size: 20, className: "text-gray-950" }) }),
|
|
90
|
-
/* @__PURE__ */ jsx(DialogTitle, { className: "paragraph-medium-semibold text-gray-950 text-center flex-1", children: "
|
|
92
|
+
/* @__PURE__ */ jsx(DialogTitle, { className: "paragraph-medium-semibold text-gray-950 text-center flex-1", children: translate("common.account.changePhone.titleEdit") }),
|
|
91
93
|
/* @__PURE__ */ jsx(Button, { variant: "ghost", className: "size-8! p-0", onClick: handleClose, children: /* @__PURE__ */ jsx(IconX, { size: 18, className: "text-gray-500" }) })
|
|
92
94
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
93
|
-
/* @__PURE__ */ jsx(DialogHeader, { className: "sr-only", children: /* @__PURE__ */ jsx(DialogTitle, { children: hasExistingPhone ? "
|
|
95
|
+
/* @__PURE__ */ jsx(DialogHeader, { className: "sr-only", children: /* @__PURE__ */ jsx(DialogTitle, { children: hasExistingPhone ? translate("common.account.changePhone.titleEdit") : translate("common.account.changePhone.titleAdd") }) }),
|
|
94
96
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0", children: [
|
|
95
|
-
/* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950 text-center", children: hasExistingPhone ? "
|
|
97
|
+
/* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950 text-center", children: hasExistingPhone ? translate("common.account.changePhone.titleEdit") : translate("common.account.changePhone.titleAdd") }),
|
|
96
98
|
/* @__PURE__ */ jsx(
|
|
97
99
|
Button,
|
|
98
100
|
{
|
|
@@ -117,15 +119,11 @@ function ChangePhoneModal({ open, onClose }) {
|
|
|
117
119
|
/* @__PURE__ */ jsxs("div", { className: "px-4 lg:px-5 py-5 lg:py-6 flex flex-col gap-4 flex-1 lg:flex-none", children: [
|
|
118
120
|
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center size-12 bg-white rounded-lg shadow-xs border border-gray-200", children: /* @__PURE__ */ jsx(IconMessage, { size: 20, className: "text-gray-950" }) }),
|
|
119
121
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
120
|
-
/* @__PURE__ */ jsx("h3", { className: "paragraph-medium-semibold text-gray-950", children: "
|
|
121
|
-
/* @__PURE__ */
|
|
122
|
-
|
|
123
|
-
" ",
|
|
124
|
-
|
|
125
|
-
currentPhoneDisplay,
|
|
126
|
-
"."
|
|
127
|
-
] })
|
|
128
|
-
] })
|
|
122
|
+
/* @__PURE__ */ jsx("h3", { className: "paragraph-medium-semibold text-gray-950", children: translate("common.account.otp.validationCode") }),
|
|
123
|
+
/* @__PURE__ */ jsx("p", { className: "paragraph-small-regular text-gray-600", children: translate.rich("common.account.changePhone.sentCodeTo", {
|
|
124
|
+
phone: currentPhoneDisplay,
|
|
125
|
+
b: (chunks) => /* @__PURE__ */ jsx("span", { className: "font-semibold text-gray-950", children: chunks })
|
|
126
|
+
}) })
|
|
129
127
|
] }),
|
|
130
128
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
131
129
|
/* @__PURE__ */ jsx(InputOTP, { maxLength: OTP_CODE_LENGTH, pattern: OTP_ALPHANUMERIC_PATTERN, value: code, onChange: handleCodeChange, children: /* @__PURE__ */ jsx(InputOTPGroup, { className: "flex flex-row gap-2", children: [...Array(OTP_CODE_LENGTH)].map((_, i) => /* @__PURE__ */ jsx(
|
|
@@ -136,7 +134,7 @@ function ChangePhoneModal({ open, onClose }) {
|
|
|
136
134
|
},
|
|
137
135
|
i
|
|
138
136
|
)) }) }),
|
|
139
|
-
hasError && /* @__PURE__ */ jsx("p", { className: "paragraph-small-regular text-red-500", children: "
|
|
137
|
+
hasError && /* @__PURE__ */ jsx("p", { className: "paragraph-small-regular text-red-500", children: translate("common.account.otp.incorrectCode") })
|
|
140
138
|
] }),
|
|
141
139
|
canResend ? /* @__PURE__ */ jsx(
|
|
142
140
|
"button",
|
|
@@ -144,31 +142,30 @@ function ChangePhoneModal({ open, onClose }) {
|
|
|
144
142
|
type: "button",
|
|
145
143
|
onClick: handleResend,
|
|
146
144
|
className: "paragraph-small-medium text-gray-950 underline cursor-pointer hover:text-gray-700 w-fit",
|
|
147
|
-
children: "
|
|
145
|
+
children: translate("common.account.otp.resend")
|
|
148
146
|
}
|
|
149
|
-
) : /* @__PURE__ */
|
|
150
|
-
|
|
151
|
-
" ",
|
|
152
|
-
|
|
153
|
-
] })
|
|
147
|
+
) : /* @__PURE__ */ jsx("p", { className: "paragraph-small-regular text-gray-500", children: translate.rich("common.account.otp.resendIn", {
|
|
148
|
+
time: formatTimer(timer),
|
|
149
|
+
b: (chunks) => /* @__PURE__ */ jsx("span", { className: "paragraph-small-semibold text-gray-950", children: chunks })
|
|
150
|
+
}) })
|
|
154
151
|
] }),
|
|
155
152
|
/* @__PURE__ */ jsx(Separator, {}),
|
|
156
153
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 lg:px-5 py-4 lg:py-5 mt-auto lg:mt-0", children: [
|
|
157
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", className: "h-10!", type: "button", onClick: handleClose, children: "
|
|
158
|
-
/* @__PURE__ */ jsx(Button, { className: "h-10!", type: "submit", disabled: !isValidLength || isLoading, children: isLoading ? "
|
|
154
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", className: "h-10!", type: "button", onClick: handleClose, children: translate("common.actions.cancel") }),
|
|
155
|
+
/* @__PURE__ */ jsx(Button, { className: "h-10!", type: "submit", disabled: !isValidLength || isLoading, children: isLoading ? translate("common.account.otp.validating") : translate("common.account.changePhone.confirm") })
|
|
159
156
|
] })
|
|
160
157
|
]
|
|
161
158
|
}
|
|
162
159
|
) : /* @__PURE__ */ jsxs("form", { onSubmit: handleContinue, className: "flex flex-col flex-1 lg:flex-none", children: [
|
|
163
160
|
/* @__PURE__ */ jsxs("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", children: [
|
|
164
161
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
165
|
-
/* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950", children: hasExistingPhone ? "
|
|
166
|
-
/* @__PURE__ */ jsx("span", { className: "paragraph-small-regular text-gray-600", children: hasExistingPhone ? "
|
|
162
|
+
/* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950", children: hasExistingPhone ? translate("common.account.changePhone.updateTitle") : translate("common.account.changePhone.addTitle") }),
|
|
163
|
+
/* @__PURE__ */ jsx("span", { className: "paragraph-small-regular text-gray-600", children: hasExistingPhone ? translate("common.account.changePhone.updateDescription") : translate("common.account.changePhone.addDescription") })
|
|
167
164
|
] }),
|
|
168
165
|
/* @__PURE__ */ jsx(
|
|
169
166
|
PhoneInput,
|
|
170
167
|
{
|
|
171
|
-
label: hasExistingPhone ? "
|
|
168
|
+
label: hasExistingPhone ? translate("common.account.changePhone.newNumber") : translate("common.account.changePhone.numberLabel"),
|
|
172
169
|
placeholder: "(00) 0 0000-0000",
|
|
173
170
|
value: phoneValue,
|
|
174
171
|
onChange: handlePhoneChange,
|
|
@@ -178,8 +175,8 @@ function ChangePhoneModal({ open, onClose }) {
|
|
|
178
175
|
)
|
|
179
176
|
] }),
|
|
180
177
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0", children: [
|
|
181
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", className: "h-10!", type: "button", onClick: handleClose, children: "
|
|
182
|
-
/* @__PURE__ */ jsx(Button, { className: "h-10!", type: "submit", disabled: isSubmitting, children: isSubmitting ? hasExistingPhone ? "
|
|
178
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", className: "h-10!", type: "button", onClick: handleClose, children: translate("common.actions.cancel") }),
|
|
179
|
+
/* @__PURE__ */ jsx(Button, { className: "h-10!", type: "submit", disabled: isSubmitting, children: isSubmitting ? hasExistingPhone ? translate("common.actions.sending") : translate("common.actions.saving") : hasExistingPhone ? translate("common.actions.continue") : translate("common.actions.save") })
|
|
183
180
|
] })
|
|
184
181
|
] })
|
|
185
182
|
]
|