@greatapps/common 1.1.372 → 1.1.375
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/AccountModals.mjs.map +1 -1
- package/dist/components/account/ConfigurationsMyAccountModal.mjs +1 -1
- package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -1
- package/dist/components/account/ConfirmDeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/ConfirmGlobalPreferencesModal.mjs.map +1 -1
- package/dist/components/account/DeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/DisableTwoFactorAuthModal.mjs.map +1 -1
- package/dist/components/account/IsntPossibleDeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/TwoFactorAuthModal.mjs.map +1 -1
- package/dist/components/account/hooks/useChangePhoneForm.mjs.map +1 -1
- package/dist/components/account/hooks/useTwoFactorAuthForm.mjs.map +1 -1
- package/dist/components/account/sections/ChangeEmailModal.mjs.map +1 -1
- package/dist/components/account/sections/ChangePasswordSection.mjs.map +1 -1
- package/dist/components/account/sections/ChangePhoneModal.mjs.map +1 -1
- package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
- package/dist/components/account/sections/PreferencesSection.mjs.map +1 -1
- package/dist/components/account/sections/SecuritySection.mjs.map +1 -1
- package/dist/components/embeds/CrispEmbed.mjs.map +1 -1
- package/dist/components/embeds/FrillEmbed.mjs.map +1 -1
- package/dist/components/handlers/SearchParamsHandler.mjs.map +1 -1
- package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
- package/dist/components/layouts/AppNavBar.mjs.map +1 -1
- package/dist/components/layouts/CollapsibleSidebar.mjs.map +1 -1
- package/dist/components/layouts/MdSideBarNavigation.mjs.map +1 -1
- package/dist/components/layouts/NavBar.mjs.map +1 -1
- package/dist/components/layouts/NotificationsPopover.mjs.map +1 -1
- package/dist/components/layouts/ProfilePopover.mjs +9 -1
- package/dist/components/layouts/ProfilePopover.mjs.map +1 -1
- package/dist/components/layouts/SideBarNavigation.mjs.map +1 -1
- package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
- package/dist/components/layouts/WhitelabelCodes.mjs.map +1 -1
- package/dist/components/modals/BuyCreditsModal.mjs.map +1 -1
- package/dist/components/modals/ModalManager.mjs.map +1 -1
- package/dist/components/modals/Modals.mjs.map +1 -1
- package/dist/components/modals/cards/AddCardModal.mjs.map +1 -1
- package/dist/components/modals/cards/CardFormFields.mjs.map +1 -1
- package/dist/components/navigation/CancelledSubscriptionBanner.mjs.map +1 -1
- package/dist/components/navigation/NavItemsContext.mjs.map +1 -1
- package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
- package/dist/components/navigation/shells/TabsMobileShell.mjs.map +1 -1
- package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
- package/dist/components/pages/NotFoundPage.mjs.map +1 -1
- package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
- package/dist/components/ui/buttons/Button.mjs.map +1 -1
- package/dist/components/ui/buttons/CancelButton.mjs.map +1 -1
- package/dist/components/ui/buttons/CopyButton.mjs.map +1 -1
- package/dist/components/ui/data-display/Accordion.mjs.map +1 -1
- package/dist/components/ui/data-display/Badge.mjs.map +1 -1
- package/dist/components/ui/data-display/Card.mjs.map +1 -1
- package/dist/components/ui/data-display/CardBrandIcons.mjs.map +1 -1
- package/dist/components/ui/data-display/CardItem.mjs.map +1 -1
- package/dist/components/ui/data-display/Pagination.mjs.map +1 -1
- package/dist/components/ui/data-display/PaymentInfoCard.mjs.map +1 -1
- package/dist/components/ui/data-display/ScrollArea.mjs.map +1 -1
- package/dist/components/ui/data-display/Separator.mjs.map +1 -1
- package/dist/components/ui/data-display/Table.mjs.map +1 -1
- package/dist/components/ui/data-display/Tabs.mjs.map +1 -1
- package/dist/components/ui/feedback/CircularProgress.mjs.map +1 -1
- package/dist/components/ui/feedback/DefaultCircularProgress.mjs.map +1 -1
- package/dist/components/ui/feedback/LoadingOverlay.mjs.map +1 -1
- package/dist/components/ui/feedback/Progress.mjs.map +1 -1
- package/dist/components/ui/feedback/Skeleton.mjs.map +1 -1
- package/dist/components/ui/feedback/Toast.mjs.map +1 -1
- package/dist/components/ui/form/Calendar.mjs.map +1 -1
- package/dist/components/ui/form/Checkbox.mjs.map +1 -1
- package/dist/components/ui/form/ComboboxField.mjs.map +1 -1
- package/dist/components/ui/form/DatePicker.mjs.map +1 -1
- package/dist/components/ui/form/DateRangePicker.mjs.map +1 -1
- package/dist/components/ui/form/FormField.mjs.map +1 -1
- package/dist/components/ui/form/Input.mjs.map +1 -1
- package/dist/components/ui/form/InputOtp.mjs.map +1 -1
- package/dist/components/ui/form/PhoneInput.mjs.map +1 -1
- package/dist/components/ui/form/RadioGroup.mjs.map +1 -1
- package/dist/components/ui/form/Select.mjs +1 -1
- package/dist/components/ui/form/Select.mjs.map +1 -1
- package/dist/components/ui/form/Switch.mjs.map +1 -1
- package/dist/components/ui/form/Textarea.mjs.map +1 -1
- package/dist/components/ui/overlay/Command.mjs.map +1 -1
- package/dist/components/ui/overlay/Dialog.mjs.map +1 -1
- package/dist/components/ui/overlay/Popover.mjs.map +1 -1
- package/dist/components/ui/overlay/Sheet.mjs.map +1 -1
- package/dist/components/ui/overlay/Tooltip.mjs.map +1 -1
- package/dist/components/widgets/notifications/NotificationCard.mjs.map +1 -1
- package/dist/hooks/copy-to-clipboard.hook.mjs.map +1 -1
- package/dist/hooks/useDebounce.mjs.map +1 -1
- package/dist/hooks/useDebounceState.mjs.map +1 -1
- package/dist/hooks/useDebouncedEffect.mjs.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/infra/utils/clsx.mjs.map +1 -1
- package/dist/infra/utils/date.mjs.map +1 -1
- package/dist/infra/utils/parser.mjs.map +1 -1
- package/dist/infra/utils/percentage.mjs.map +1 -1
- package/dist/middleware.mjs.map +1 -1
- package/dist/modules/accounts/actions/account-management.action.mjs.map +1 -1
- package/dist/modules/accounts/actions/find-current-account.action.mjs.map +1 -1
- package/dist/modules/accounts/actions/list-currencies.action.mjs.map +1 -1
- package/dist/modules/accounts/actions/list-timezones.action.mjs.map +1 -1
- package/dist/modules/accounts/hooks/current-account.hook.mjs.map +1 -1
- package/dist/modules/accounts/hooks/useAccountManagement.mjs.map +1 -1
- package/dist/modules/accounts/hooks/useCurrencies.mjs.map +1 -1
- package/dist/modules/accounts/hooks/useTimezones.mjs.map +1 -1
- package/dist/modules/accounts/hooks/useViaCep.mjs.map +1 -1
- package/dist/modules/accounts/services/account.service.mjs.map +1 -1
- package/dist/modules/auth/actions/validate-session.action.mjs.map +1 -1
- package/dist/modules/auth/hooks/login.hook.mjs.map +1 -1
- package/dist/modules/auth/hooks/logout.hook.mjs.map +1 -1
- package/dist/modules/auth/hooks/register.hook.mjs.map +1 -1
- package/dist/modules/auth/hooks/useManagementPermissions.mjs.map +1 -1
- package/dist/modules/auth/utils/assert-management-permission.mjs.map +1 -1
- package/dist/modules/auth/utils/assert-management-subscription.mjs.map +1 -1
- package/dist/modules/auth/utils/build-wl-override.mjs.map +1 -1
- package/dist/modules/cards/actions/create-card.action.mjs.map +1 -1
- package/dist/modules/cards/actions/list-cards.action.mjs.map +1 -1
- package/dist/modules/cards/hooks/cards.hook.mjs.map +1 -1
- package/dist/modules/cards/hooks/create-card.hook.mjs.map +1 -1
- package/dist/modules/cards/services/cards.service.mjs.map +1 -1
- package/dist/modules/cards/types.mjs.map +1 -1
- package/dist/modules/ia-credits/actions/list-ia-credits.action.mjs.map +1 -1
- package/dist/modules/plans/actions/find-plan-by-id.action.mjs.map +1 -1
- package/dist/modules/plans/hooks/use-has-plan-addon.hook.mjs.map +1 -1
- package/dist/modules/plans/hooks/use-plan-by-id.hook.mjs.map +1 -1
- package/dist/modules/plans/services/plans.service.mjs.map +1 -1
- package/dist/modules/plans/types/plan.type.mjs.map +1 -1
- package/dist/modules/projects/actions/add-project-user.action.mjs.map +1 -1
- package/dist/modules/projects/actions/list-all-account-users.action.mjs.map +1 -1
- package/dist/modules/projects/actions/list-available-users.action.mjs.map +1 -1
- package/dist/modules/projects/actions/list-project-users.action.mjs.map +1 -1
- package/dist/modules/projects/actions/remove-project-user.action.mjs.map +1 -1
- package/dist/modules/projects/hooks/add-project-user.hook.mjs.map +1 -1
- package/dist/modules/projects/hooks/list-all-account-users.hook.mjs.map +1 -1
- package/dist/modules/projects/hooks/list-available-users.hook.mjs.map +1 -1
- package/dist/modules/projects/hooks/list-project-users.hook.mjs.map +1 -1
- package/dist/modules/projects/hooks/remove-project-user.hook.mjs.map +1 -1
- package/dist/modules/subscriptions/actions/calculate-subscription.action.mjs.map +1 -1
- package/dist/modules/subscriptions/actions/list-subscriptions.action.mjs.map +1 -1
- package/dist/modules/subscriptions/actions/update-subscription-plan.action.mjs.map +1 -1
- package/dist/modules/subscriptions/constants/query-keys.constants.mjs.map +1 -1
- package/dist/modules/subscriptions/hooks/calculate-subscription.hook.mjs.map +1 -1
- package/dist/modules/subscriptions/hooks/find-active-subscription.hook.mjs.map +1 -1
- package/dist/modules/subscriptions/hooks/list-subscriptions.hook.mjs.map +1 -1
- package/dist/modules/subscriptions/hooks/update-subscription-plan.hook.mjs.map +1 -1
- package/dist/modules/subscriptions/hooks/use-cancelled-subscription-guard.mjs.map +1 -1
- package/dist/modules/subscriptions/types/calculate-subscription.type.mjs.map +1 -1
- package/dist/modules/subscriptions/utils/build-plan-extras.mjs.map +1 -1
- package/dist/modules/subscriptions/utils/has-subscription-expired.mjs.map +1 -1
- package/dist/modules/subscriptions/utils/periodicity.mjs.map +1 -1
- package/dist/modules/subscriptions/utils/resolve-plan-extras-prices.mjs.map +1 -1
- package/dist/modules/users/action/find-user-by-id.action.mjs.map +1 -1
- package/dist/modules/users/action/list-messages.action.mjs.map +1 -1
- package/dist/modules/users/action/mark-all-messages-as-read.action.mjs.map +1 -1
- package/dist/modules/users/action/mark-message-as-read.action.mjs.map +1 -1
- package/dist/modules/users/hooks/messages.hook.mjs.map +1 -1
- package/dist/modules/users/services/messages.service.mjs.map +1 -1
- package/dist/modules/whitelabel/actions/find-whitelabel.action.mjs.map +1 -1
- package/dist/modules/whitelabel/actions/revalidate-whitelabel.action.mjs.map +1 -1
- package/dist/modules/whitelabel/utils/normalize-hostname.mjs.map +1 -1
- package/dist/providers/whitelabel.provider.mjs.map +1 -1
- package/dist/store/useAccountModals.mjs.map +1 -1
- package/dist/store/useBuyCreditsModal.mjs.map +1 -1
- package/dist/store/useDesktopSidebarStore.mjs.map +1 -1
- package/dist/store/useMdSidebarStore.mjs.map +1 -1
- package/dist/store/useModalManager.mjs.map +1 -1
- package/dist/utils/constants/br-states.mjs.map +1 -1
- package/dist/utils/countries.mjs.map +1 -1
- package/dist/utils/safeServerAction.mjs.map +1 -1
- package/dist/utils/withAction.mjs.map +1 -1
- package/package.json +89 -89
- package/src/components/account/AccountModals.tsx +17 -17
- package/src/components/account/ConfigurationsMyAccountModal.tsx +146 -146
- package/src/components/account/ConfirmDeleteAccountModal.tsx +55 -55
- package/src/components/account/ConfirmGlobalPreferencesModal.tsx +66 -66
- package/src/components/account/DeleteAccountModal.tsx +130 -130
- package/src/components/account/DisableTwoFactorAuthModal.tsx +86 -86
- package/src/components/account/IsntPossibleDeleteAccountModal.tsx +49 -49
- package/src/components/account/TwoFactorAuthModal.tsx +215 -215
- package/src/components/account/hooks/useChangePhoneForm.tsx +107 -107
- package/src/components/account/hooks/useTwoFactorAuthForm.tsx +101 -101
- package/src/components/account/sections/ChangeEmailModal.tsx +225 -225
- package/src/components/account/sections/ChangePasswordSection.tsx +64 -64
- package/src/components/account/sections/ChangePhoneModal.tsx +245 -245
- package/src/components/account/sections/MyProfileSection.tsx +327 -327
- package/src/components/account/sections/PreferencesSection.tsx +248 -248
- package/src/components/account/sections/SecuritySection.tsx +46 -46
- package/src/components/embeds/CrispEmbed.tsx +101 -101
- package/src/components/embeds/FrillEmbed.tsx +119 -119
- package/src/components/handlers/SearchParamsHandler.tsx +61 -61
- package/src/components/layouts/AppMobileNavBar.tsx +118 -118
- package/src/components/layouts/AppNavBar.tsx +46 -46
- package/src/components/layouts/CollapsibleSidebar.tsx +67 -67
- package/src/components/layouts/MdSideBarNavigation.tsx +56 -56
- package/src/components/layouts/NavBar.tsx +172 -172
- package/src/components/layouts/NotificationsPopover.tsx +115 -115
- package/src/components/layouts/ProfilePopover.tsx +178 -170
- package/src/components/layouts/SideBarNavigation.tsx +62 -62
- package/src/components/layouts/UsersSelectorPopover.tsx +234 -234
- package/src/components/layouts/WhitelabelCodes.tsx +59 -59
- package/src/components/modals/BuyCreditsModal.tsx +314 -314
- package/src/components/modals/ModalManager.tsx +29 -29
- package/src/components/modals/Modals.tsx +26 -26
- package/src/components/modals/cards/AddCardModal.tsx +260 -260
- package/src/components/modals/cards/CardFormFields.tsx +294 -294
- package/src/components/navigation/CancelledSubscriptionBanner.tsx +60 -60
- package/src/components/navigation/NavItemsContext.ts +20 -20
- package/src/components/navigation/ProjectSelectorPopover.tsx +160 -160
- package/src/components/navigation/shells/TabsMobileShell.tsx +72 -72
- package/src/components/navigation/subcomponents/ProjectSelector.tsx +160 -160
- package/src/components/pages/NotFoundPage.tsx +50 -50
- package/src/components/pages/notifications/Notifications.tsx +160 -160
- package/src/components/ui/buttons/Button.tsx +57 -57
- package/src/components/ui/buttons/CancelButton.tsx +14 -14
- package/src/components/ui/buttons/CopyButton.tsx +54 -54
- package/src/components/ui/data-display/Accordion.tsx +81 -81
- package/src/components/ui/data-display/Badge.tsx +47 -47
- package/src/components/ui/data-display/Card.tsx +93 -93
- package/src/components/ui/data-display/CardBrandIcons.tsx +336 -336
- package/src/components/ui/data-display/CardItem.tsx +75 -75
- package/src/components/ui/data-display/Pagination.tsx +126 -126
- package/src/components/ui/data-display/PaymentInfoCard.tsx +186 -186
- package/src/components/ui/data-display/ScrollArea.tsx +59 -59
- package/src/components/ui/data-display/Separator.tsx +29 -29
- package/src/components/ui/data-display/Table.tsx +117 -117
- package/src/components/ui/data-display/Tabs.tsx +67 -67
- package/src/components/ui/feedback/CircularProgress.tsx +75 -75
- package/src/components/ui/feedback/DefaultCircularProgress.tsx +61 -61
- package/src/components/ui/feedback/LoadingOverlay.tsx +31 -31
- package/src/components/ui/feedback/Progress.tsx +40 -40
- package/src/components/ui/feedback/Skeleton.tsx +5 -5
- package/src/components/ui/feedback/Toast.tsx +101 -101
- package/src/components/ui/form/Calendar.tsx +228 -228
- package/src/components/ui/form/Checkbox.tsx +31 -31
- package/src/components/ui/form/ComboboxField.tsx +154 -154
- package/src/components/ui/form/DatePicker.tsx +97 -97
- package/src/components/ui/form/DateRangePicker.tsx +108 -108
- package/src/components/ui/form/FormField.tsx +131 -131
- package/src/components/ui/form/Input.tsx +20 -20
- package/src/components/ui/form/InputOtp.tsx +80 -80
- package/src/components/ui/form/PhoneInput.tsx +208 -208
- package/src/components/ui/form/RadioGroup.tsx +45 -45
- package/src/components/ui/form/Select.tsx +200 -200
- package/src/components/ui/form/Switch.tsx +32 -32
- package/src/components/ui/form/Textarea.tsx +19 -19
- package/src/components/ui/overlay/Command.tsx +185 -185
- package/src/components/ui/overlay/Dialog.tsx +151 -151
- package/src/components/ui/overlay/Popover.tsx +49 -49
- package/src/components/ui/overlay/Sheet.tsx +166 -166
- package/src/components/ui/overlay/Tooltip.tsx +62 -62
- package/src/components/widgets/notifications/NotificationCard.tsx +68 -68
- package/src/hooks/copy-to-clipboard.hook.tsx +67 -67
- package/src/hooks/useDebounce.ts +26 -26
- package/src/hooks/useDebounceState.ts +11 -11
- package/src/hooks/useDebouncedEffect.ts +69 -69
- package/src/index.ts +391 -391
- package/src/infra/utils/clsx.ts +6 -6
- package/src/infra/utils/date.ts +7 -7
- package/src/infra/utils/parser.ts +52 -52
- package/src/infra/utils/percentage.ts +42 -42
- package/src/middleware.ts +4 -4
- package/src/modules/accounts/actions/account-management.action.ts +107 -107
- package/src/modules/accounts/actions/find-current-account.action.ts +9 -9
- package/src/modules/accounts/actions/list-currencies.action.ts +8 -8
- package/src/modules/accounts/actions/list-timezones.action.ts +8 -8
- package/src/modules/accounts/hooks/current-account.hook.tsx +22 -22
- package/src/modules/accounts/hooks/useAccountManagement.ts +85 -85
- package/src/modules/accounts/hooks/useCurrencies.ts +15 -15
- package/src/modules/accounts/hooks/useTimezones.ts +15 -15
- package/src/modules/accounts/hooks/useViaCep.ts +25 -25
- package/src/modules/accounts/services/account.service.ts +239 -239
- package/src/modules/accounts/types.ts +225 -225
- package/src/modules/auth/actions/validate-session.action.ts +56 -56
- package/src/modules/auth/hooks/login.hook.tsx +13 -13
- package/src/modules/auth/hooks/logout.hook.tsx +11 -11
- package/src/modules/auth/hooks/register.hook.tsx +11 -11
- package/src/modules/auth/hooks/useManagementPermissions.ts +45 -45
- package/src/modules/auth/types/management-permission.type.ts +7 -7
- package/src/modules/auth/utils/assert-management-permission.ts +46 -46
- package/src/modules/auth/utils/assert-management-subscription.ts +27 -27
- package/src/modules/auth/utils/build-wl-override.ts +43 -43
- package/src/modules/cards/actions/create-card.action.ts +9 -9
- package/src/modules/cards/actions/list-cards.action.ts +8 -8
- package/src/modules/cards/hooks/cards.hook.ts +14 -14
- package/src/modules/cards/hooks/create-card.hook.ts +18 -18
- package/src/modules/cards/services/cards.service.ts +51 -51
- package/src/modules/cards/types.ts +32 -32
- package/src/modules/ia-credits/actions/list-ia-credits.action.ts +8 -8
- package/src/modules/plans/actions/find-plan-by-id.action.ts +8 -8
- package/src/modules/plans/hooks/use-has-plan-addon.hook.ts +17 -17
- package/src/modules/plans/hooks/use-plan-by-id.hook.ts +13 -13
- package/src/modules/plans/services/plans.service.ts +36 -36
- package/src/modules/plans/types/plan.type.ts +21 -21
- package/src/modules/projects/actions/add-project-user.action.ts +9 -9
- package/src/modules/projects/actions/list-all-account-users.action.ts +9 -9
- package/src/modules/projects/actions/list-available-users.action.ts +9 -9
- package/src/modules/projects/actions/list-project-users.action.ts +9 -9
- package/src/modules/projects/actions/remove-project-user.action.ts +9 -9
- package/src/modules/projects/hooks/add-project-user.hook.ts +69 -69
- package/src/modules/projects/hooks/list-all-account-users.hook.ts +34 -34
- package/src/modules/projects/hooks/list-available-users.hook.ts +33 -33
- package/src/modules/projects/hooks/list-project-users.hook.ts +33 -33
- package/src/modules/projects/hooks/remove-project-user.hook.ts +69 -69
- package/src/modules/subscriptions/actions/calculate-subscription.action.ts +9 -9
- package/src/modules/subscriptions/actions/list-subscriptions.action.ts +9 -9
- package/src/modules/subscriptions/actions/update-subscription-plan.action.ts +14 -14
- package/src/modules/subscriptions/constants/query-keys.constants.ts +1 -1
- package/src/modules/subscriptions/hooks/calculate-subscription.hook.ts +13 -13
- package/src/modules/subscriptions/hooks/find-active-subscription.hook.ts +19 -19
- package/src/modules/subscriptions/hooks/list-subscriptions.hook.ts +16 -16
- package/src/modules/subscriptions/hooks/update-subscription-plan.hook.ts +25 -25
- package/src/modules/subscriptions/hooks/use-cancelled-subscription-guard.ts +39 -39
- package/src/modules/subscriptions/types/billing-period.type.ts +1 -1
- package/src/modules/subscriptions/types/calculate-subscription.type.ts +75 -75
- package/src/modules/subscriptions/utils/build-plan-extras.ts +56 -56
- package/src/modules/subscriptions/utils/has-subscription-expired.ts +8 -8
- package/src/modules/subscriptions/utils/periodicity.ts +52 -52
- package/src/modules/subscriptions/utils/resolve-plan-extras-prices.ts +23 -23
- package/src/modules/users/action/find-user-by-id.action.ts +8 -8
- package/src/modules/users/action/list-messages.action.ts +12 -12
- package/src/modules/users/action/mark-all-messages-as-read.action.ts +8 -8
- package/src/modules/users/action/mark-message-as-read.action.ts +8 -8
- package/src/modules/users/hooks/messages.hook.ts +60 -60
- package/src/modules/users/services/messages.service.ts +48 -48
- package/src/modules/whitelabel/actions/find-whitelabel.action.ts +23 -23
- package/src/modules/whitelabel/actions/revalidate-whitelabel.action.ts +19 -19
- package/src/modules/whitelabel/schema.ts +84 -84
- package/src/modules/whitelabel/utils/normalize-hostname.ts +26 -26
- package/src/providers/whitelabel.provider.tsx +54 -54
- package/src/store/useAccountModals.ts +55 -55
- package/src/store/useBuyCreditsModal.ts +21 -21
- package/src/store/useDesktopSidebarStore.ts +47 -47
- package/src/store/useMdSidebarStore.ts +34 -34
- package/src/store/useModalManager.ts +104 -104
- package/src/utils/constants/br-states.ts +29 -29
- package/src/utils/countries.ts +224 -224
- package/src/utils/safeServerAction.ts +21 -21
- package/src/utils/withAction.ts +13 -13
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useState, useEffect, useCallback } from 'react';
|
|
4
|
-
import { IconAlertOctagon, IconX } from '@tabler/icons-react';
|
|
5
|
-
import { formatShortDate } from '../../infra/utils/date';
|
|
6
|
-
import { useActiveSubscription } from '../../modules/subscriptions/hooks/find-active-subscription.hook';
|
|
7
|
-
|
|
8
|
-
interface CancelledSubscriptionBannerProps {
|
|
9
|
-
onReactivate?: () => void;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function CancelledSubscriptionBanner({ onReactivate }: CancelledSubscriptionBannerProps) {
|
|
13
|
-
const { data: { data: [subscription] = [] } = {} } = useActiveSubscription();
|
|
14
|
-
const [visible, setVisible] = useState(true);
|
|
15
|
-
const [animated, setAnimated] = useState(false);
|
|
16
|
-
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
const timer = setTimeout(() => setAnimated(true), 50);
|
|
19
|
-
return () => clearTimeout(timer);
|
|
20
|
-
}, []);
|
|
21
|
-
|
|
22
|
-
const dismiss = useCallback(() => setVisible(false), []);
|
|
23
|
-
const dueDate = new Date(subscription?.date_due);
|
|
24
|
-
const today = new Date();
|
|
25
|
-
const isPastDue = today >= dueDate;
|
|
26
|
-
const formattedDate = formatShortDate(dueDate);
|
|
27
|
-
|
|
28
|
-
if (!subscription?.date_cancellation || isPastDue || !visible) return null;
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<div className="fixed top-[80px] md:top-0 lg:left-[273px] left-0 right-0 z-[60] flex justify-center pointer-events-none px-4 lg:px-0">
|
|
32
|
-
<div
|
|
33
|
-
className={`flex flex-col sm:flex-row items-start sm:items-center justify-between bg-red-500 rounded-lg px-3 py-2 sm:py-1 w-full lg:w-[805px] max-w-full pointer-events-auto transition-transform duration-500 ease-out gap-2 sm:gap-0 ${animated ? 'translate-y-0 md:translate-y-9' : '-translate-y-full'}`}
|
|
34
|
-
>
|
|
35
|
-
<div className="flex items-center gap-2 flex-1 w-full sm:w-auto">
|
|
36
|
-
<IconAlertOctagon size={16} className="text-white shrink-0" />
|
|
37
|
-
<span className="paragraph-xsmall-semibold text-white">
|
|
38
|
-
{isPastDue
|
|
39
|
-
? 'Sua assinatura foi cancelada e suas páginas foram retiradas do ar.'
|
|
40
|
-
: `Assinatura cancelada! Suas páginas serão retiradas do ar no dia ${formattedDate}!`}
|
|
41
|
-
</span>
|
|
42
|
-
</div>
|
|
43
|
-
<div className="flex items-center gap-1.5 w-full sm:w-auto justify-between sm:justify-start">
|
|
44
|
-
<button
|
|
45
|
-
type="button"
|
|
46
|
-
className="flex items-center justify-center p-1.5 cursor-pointer"
|
|
47
|
-
onClick={onReactivate}
|
|
48
|
-
>
|
|
49
|
-
<span className="paragraph-xsmall-semibold text-white underline">
|
|
50
|
-
Reativar assinatura
|
|
51
|
-
</span>
|
|
52
|
-
</button>
|
|
53
|
-
<button type="button" className="cursor-pointer shrink-0" onClick={dismiss}>
|
|
54
|
-
<IconX size={18} className="text-red-200" />
|
|
55
|
-
</button>
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
4
|
+
import { IconAlertOctagon, IconX } from '@tabler/icons-react';
|
|
5
|
+
import { formatShortDate } from '../../infra/utils/date';
|
|
6
|
+
import { useActiveSubscription } from '../../modules/subscriptions/hooks/find-active-subscription.hook';
|
|
7
|
+
|
|
8
|
+
interface CancelledSubscriptionBannerProps {
|
|
9
|
+
onReactivate?: () => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function CancelledSubscriptionBanner({ onReactivate }: CancelledSubscriptionBannerProps) {
|
|
13
|
+
const { data: { data: [subscription] = [] } = {} } = useActiveSubscription();
|
|
14
|
+
const [visible, setVisible] = useState(true);
|
|
15
|
+
const [animated, setAnimated] = useState(false);
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const timer = setTimeout(() => setAnimated(true), 50);
|
|
19
|
+
return () => clearTimeout(timer);
|
|
20
|
+
}, []);
|
|
21
|
+
|
|
22
|
+
const dismiss = useCallback(() => setVisible(false), []);
|
|
23
|
+
const dueDate = new Date(subscription?.date_due);
|
|
24
|
+
const today = new Date();
|
|
25
|
+
const isPastDue = today >= dueDate;
|
|
26
|
+
const formattedDate = formatShortDate(dueDate);
|
|
27
|
+
|
|
28
|
+
if (!subscription?.date_cancellation || isPastDue || !visible) return null;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div className="fixed top-[80px] md:top-0 lg:left-[273px] left-0 right-0 z-[60] flex justify-center pointer-events-none px-4 lg:px-0">
|
|
32
|
+
<div
|
|
33
|
+
className={`flex flex-col sm:flex-row items-start sm:items-center justify-between bg-red-500 rounded-lg px-3 py-2 sm:py-1 w-full lg:w-[805px] max-w-full pointer-events-auto transition-transform duration-500 ease-out gap-2 sm:gap-0 ${animated ? 'translate-y-0 md:translate-y-9' : '-translate-y-full'}`}
|
|
34
|
+
>
|
|
35
|
+
<div className="flex items-center gap-2 flex-1 w-full sm:w-auto">
|
|
36
|
+
<IconAlertOctagon size={16} className="text-white shrink-0" />
|
|
37
|
+
<span className="paragraph-xsmall-semibold text-white">
|
|
38
|
+
{isPastDue
|
|
39
|
+
? 'Sua assinatura foi cancelada e suas páginas foram retiradas do ar.'
|
|
40
|
+
: `Assinatura cancelada! Suas páginas serão retiradas do ar no dia ${formattedDate}!`}
|
|
41
|
+
</span>
|
|
42
|
+
</div>
|
|
43
|
+
<div className="flex items-center gap-1.5 w-full sm:w-auto justify-between sm:justify-start">
|
|
44
|
+
<button
|
|
45
|
+
type="button"
|
|
46
|
+
className="flex items-center justify-center p-1.5 cursor-pointer"
|
|
47
|
+
onClick={onReactivate}
|
|
48
|
+
>
|
|
49
|
+
<span className="paragraph-xsmall-semibold text-white underline">
|
|
50
|
+
Reativar assinatura
|
|
51
|
+
</span>
|
|
52
|
+
</button>
|
|
53
|
+
<button type="button" className="cursor-pointer shrink-0" onClick={dismiss}>
|
|
54
|
+
<IconX size={18} className="text-red-200" />
|
|
55
|
+
</button>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { createContext, useContext } from 'react';
|
|
4
|
-
import type { NavItemConfig } from './subcomponents/NavItems';
|
|
5
|
-
|
|
6
|
-
interface NavItemsContextValue {
|
|
7
|
-
navItems: NavItemConfig[];
|
|
8
|
-
setNavItems: (items: NavItemConfig[]) => void;
|
|
9
|
-
mobileVariant: 'sheet' | 'tabs';
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export const NavItemsContext = createContext<NavItemsContextValue>({
|
|
13
|
-
navItems: [],
|
|
14
|
-
setNavItems: () => {},
|
|
15
|
-
mobileVariant: 'sheet',
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
export function useNavItemsContext(): NavItemsContextValue {
|
|
19
|
-
return useContext(NavItemsContext);
|
|
20
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext } from 'react';
|
|
4
|
+
import type { NavItemConfig } from './subcomponents/NavItems';
|
|
5
|
+
|
|
6
|
+
interface NavItemsContextValue {
|
|
7
|
+
navItems: NavItemConfig[];
|
|
8
|
+
setNavItems: (items: NavItemConfig[]) => void;
|
|
9
|
+
mobileVariant: 'sheet' | 'tabs';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const NavItemsContext = createContext<NavItemsContextValue>({
|
|
13
|
+
navItems: [],
|
|
14
|
+
setNavItems: () => {},
|
|
15
|
+
mobileVariant: 'sheet',
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export function useNavItemsContext(): NavItemsContextValue {
|
|
19
|
+
return useContext(NavItemsContext);
|
|
20
|
+
}
|
|
@@ -1,160 +1,160 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { Dispatch, RefObject, SetStateAction } from 'react';
|
|
4
|
-
import { ADDON_IDS } from '../../modules/subscriptions/constants/addons.constants';
|
|
5
|
-
import { useHasPlanAddon } from '../../modules/plans/hooks/use-has-plan-addon.hook';
|
|
6
|
-
import {
|
|
7
|
-
Button,
|
|
8
|
-
Command,
|
|
9
|
-
CommandEmpty,
|
|
10
|
-
CommandInput,
|
|
11
|
-
CommandItem,
|
|
12
|
-
CommandList,
|
|
13
|
-
Popover,
|
|
14
|
-
PopoverContent,
|
|
15
|
-
PopoverTrigger,
|
|
16
|
-
UserAvatar,
|
|
17
|
-
} from '../../index';
|
|
18
|
-
import { IconCheck, IconChevronDown, IconFolderOpen, IconPlus } from '@tabler/icons-react';
|
|
19
|
-
import type { NavigationProject } from './types';
|
|
20
|
-
|
|
21
|
-
interface ProjectSelectorPopoverProps {
|
|
22
|
-
open: boolean;
|
|
23
|
-
setOpen: Dispatch<SetStateAction<boolean>>;
|
|
24
|
-
titleRef?: RefObject<HTMLSpanElement | null>;
|
|
25
|
-
projects: NavigationProject[];
|
|
26
|
-
selectedProject: NavigationProject | null;
|
|
27
|
-
onSelectProject: (project: NavigationProject) => void;
|
|
28
|
-
onAddProject?: () => void;
|
|
29
|
-
onManageProjects?: () => void;
|
|
30
|
-
children?: React.ReactNode;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function ProjectItemSkeleton() {
|
|
34
|
-
return (
|
|
35
|
-
<div className="flex items-center justify-between px-2 py-1.5 gap-2">
|
|
36
|
-
<div className="flex items-center gap-2 flex-1">
|
|
37
|
-
<div className="skeleton size-8 rounded-lg shrink-0" />
|
|
38
|
-
<div className="skeleton h-3.5 w-32 rounded" />
|
|
39
|
-
</div>
|
|
40
|
-
<div className="skeleton size-4 rounded-full shrink-0" />
|
|
41
|
-
</div>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function ProjectSelectorPopover({
|
|
46
|
-
open,
|
|
47
|
-
setOpen,
|
|
48
|
-
titleRef,
|
|
49
|
-
projects,
|
|
50
|
-
selectedProject,
|
|
51
|
-
onSelectProject,
|
|
52
|
-
onAddProject,
|
|
53
|
-
onManageProjects,
|
|
54
|
-
children,
|
|
55
|
-
}: ProjectSelectorPopoverProps) {
|
|
56
|
-
const { hasAddon: canAddProject } = useHasPlanAddon(ADDON_IDS.PROJECTS);
|
|
57
|
-
|
|
58
|
-
return (
|
|
59
|
-
<Popover open={open} onOpenChange={setOpen}>
|
|
60
|
-
<PopoverTrigger asChild>
|
|
61
|
-
{children ?? (
|
|
62
|
-
<button className="cursor-pointer">
|
|
63
|
-
<IconChevronDown
|
|
64
|
-
size={20}
|
|
65
|
-
className={`transition-transform duration-200 ${open ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}
|
|
66
|
-
/>
|
|
67
|
-
</button>
|
|
68
|
-
)}
|
|
69
|
-
</PopoverTrigger>
|
|
70
|
-
<PopoverContent
|
|
71
|
-
className="w-[296px] p-0 bg-white rounded-2xl shadow-md border border-gray-200"
|
|
72
|
-
align="start"
|
|
73
|
-
sideOffset={8}
|
|
74
|
-
onOpenAutoFocus={(e: Event) => e.preventDefault()}
|
|
75
|
-
onInteractOutside={(event: Event) => {
|
|
76
|
-
if (titleRef?.current?.contains(event.target as Node)) {
|
|
77
|
-
event.preventDefault();
|
|
78
|
-
}
|
|
79
|
-
}}
|
|
80
|
-
>
|
|
81
|
-
<div className="flex flex-col p-3 gap-2">
|
|
82
|
-
<div className="flex items-center justify-between">
|
|
83
|
-
<span className="paragraph-small-semibold">Projetos</span>
|
|
84
|
-
{(onAddProject || onManageProjects) && (
|
|
85
|
-
<div className="flex items-center gap-1.5">
|
|
86
|
-
{canAddProject && onAddProject && (
|
|
87
|
-
<Button
|
|
88
|
-
variant="secondary"
|
|
89
|
-
className="h-8! paragraph-small-semibold text-gray-950"
|
|
90
|
-
onClick={onAddProject}
|
|
91
|
-
>
|
|
92
|
-
<IconPlus size={16} />
|
|
93
|
-
Adicionar
|
|
94
|
-
</Button>
|
|
95
|
-
)}
|
|
96
|
-
</div>
|
|
97
|
-
)}
|
|
98
|
-
</div>
|
|
99
|
-
<Command className="gap-2">
|
|
100
|
-
<CommandInput placeholder="Busque aqui" />
|
|
101
|
-
<CommandList className="custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]">
|
|
102
|
-
{projects.length === 0 ? (
|
|
103
|
-
<div className="flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4">
|
|
104
|
-
<IconFolderOpen size={28} className="text-gray-300" />
|
|
105
|
-
<span className="paragraph-small-medium text-center text-gray-500">
|
|
106
|
-
Nenhum projeto encontrado.
|
|
107
|
-
<br />
|
|
108
|
-
Crie um projeto para começar.
|
|
109
|
-
</span>
|
|
110
|
-
</div>
|
|
111
|
-
) : (
|
|
112
|
-
<>
|
|
113
|
-
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
|
114
|
-
{projects.map((project) => {
|
|
115
|
-
const isSelected = selectedProject?.id === project.id;
|
|
116
|
-
return (
|
|
117
|
-
<CommandItem
|
|
118
|
-
key={project.id}
|
|
119
|
-
value={`${project.title}-${project.id}`}
|
|
120
|
-
keywords={[project.title]}
|
|
121
|
-
className={isSelected ? 'bg-gray-50' : ''}
|
|
122
|
-
onSelect={() => onSelectProject(project)}
|
|
123
|
-
>
|
|
124
|
-
<div className="flex items-center justify-between w-full cursor-pointer">
|
|
125
|
-
<div className="flex items-center gap-2 w-full">
|
|
126
|
-
<UserAvatar
|
|
127
|
-
photo={project.photo}
|
|
128
|
-
name={project.title}
|
|
129
|
-
size={32}
|
|
130
|
-
/>
|
|
131
|
-
{project.title}
|
|
132
|
-
</div>
|
|
133
|
-
{isSelected && (
|
|
134
|
-
<IconCheck className="size-4 text-gray-950" />
|
|
135
|
-
)}
|
|
136
|
-
</div>
|
|
137
|
-
</CommandItem>
|
|
138
|
-
);
|
|
139
|
-
})}
|
|
140
|
-
</>
|
|
141
|
-
)}
|
|
142
|
-
</CommandList>
|
|
143
|
-
</Command>
|
|
144
|
-
{onManageProjects && (
|
|
145
|
-
<>
|
|
146
|
-
<div className="border-t border-gray-200" />
|
|
147
|
-
<Button
|
|
148
|
-
variant="ghost"
|
|
149
|
-
className="h-10! paragraph-small-medium text-gray-600 hover:text-gray-950 hover:bg-zinc-50 w-full justify-center"
|
|
150
|
-
onClick={onManageProjects}
|
|
151
|
-
>
|
|
152
|
-
Gerenciar projetos
|
|
153
|
-
</Button>
|
|
154
|
-
</>
|
|
155
|
-
)}
|
|
156
|
-
</div>
|
|
157
|
-
</PopoverContent>
|
|
158
|
-
</Popover>
|
|
159
|
-
);
|
|
160
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Dispatch, RefObject, SetStateAction } from 'react';
|
|
4
|
+
import { ADDON_IDS } from '../../modules/subscriptions/constants/addons.constants';
|
|
5
|
+
import { useHasPlanAddon } from '../../modules/plans/hooks/use-has-plan-addon.hook';
|
|
6
|
+
import {
|
|
7
|
+
Button,
|
|
8
|
+
Command,
|
|
9
|
+
CommandEmpty,
|
|
10
|
+
CommandInput,
|
|
11
|
+
CommandItem,
|
|
12
|
+
CommandList,
|
|
13
|
+
Popover,
|
|
14
|
+
PopoverContent,
|
|
15
|
+
PopoverTrigger,
|
|
16
|
+
UserAvatar,
|
|
17
|
+
} from '../../index';
|
|
18
|
+
import { IconCheck, IconChevronDown, IconFolderOpen, IconPlus } from '@tabler/icons-react';
|
|
19
|
+
import type { NavigationProject } from './types';
|
|
20
|
+
|
|
21
|
+
interface ProjectSelectorPopoverProps {
|
|
22
|
+
open: boolean;
|
|
23
|
+
setOpen: Dispatch<SetStateAction<boolean>>;
|
|
24
|
+
titleRef?: RefObject<HTMLSpanElement | null>;
|
|
25
|
+
projects: NavigationProject[];
|
|
26
|
+
selectedProject: NavigationProject | null;
|
|
27
|
+
onSelectProject: (project: NavigationProject) => void;
|
|
28
|
+
onAddProject?: () => void;
|
|
29
|
+
onManageProjects?: () => void;
|
|
30
|
+
children?: React.ReactNode;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function ProjectItemSkeleton() {
|
|
34
|
+
return (
|
|
35
|
+
<div className="flex items-center justify-between px-2 py-1.5 gap-2">
|
|
36
|
+
<div className="flex items-center gap-2 flex-1">
|
|
37
|
+
<div className="skeleton size-8 rounded-lg shrink-0" />
|
|
38
|
+
<div className="skeleton h-3.5 w-32 rounded" />
|
|
39
|
+
</div>
|
|
40
|
+
<div className="skeleton size-4 rounded-full shrink-0" />
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function ProjectSelectorPopover({
|
|
46
|
+
open,
|
|
47
|
+
setOpen,
|
|
48
|
+
titleRef,
|
|
49
|
+
projects,
|
|
50
|
+
selectedProject,
|
|
51
|
+
onSelectProject,
|
|
52
|
+
onAddProject,
|
|
53
|
+
onManageProjects,
|
|
54
|
+
children,
|
|
55
|
+
}: ProjectSelectorPopoverProps) {
|
|
56
|
+
const { hasAddon: canAddProject } = useHasPlanAddon(ADDON_IDS.PROJECTS);
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
60
|
+
<PopoverTrigger asChild>
|
|
61
|
+
{children ?? (
|
|
62
|
+
<button className="cursor-pointer">
|
|
63
|
+
<IconChevronDown
|
|
64
|
+
size={20}
|
|
65
|
+
className={`transition-transform duration-200 ${open ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}
|
|
66
|
+
/>
|
|
67
|
+
</button>
|
|
68
|
+
)}
|
|
69
|
+
</PopoverTrigger>
|
|
70
|
+
<PopoverContent
|
|
71
|
+
className="w-[296px] p-0 bg-white rounded-2xl shadow-md border border-gray-200"
|
|
72
|
+
align="start"
|
|
73
|
+
sideOffset={8}
|
|
74
|
+
onOpenAutoFocus={(e: Event) => e.preventDefault()}
|
|
75
|
+
onInteractOutside={(event: Event) => {
|
|
76
|
+
if (titleRef?.current?.contains(event.target as Node)) {
|
|
77
|
+
event.preventDefault();
|
|
78
|
+
}
|
|
79
|
+
}}
|
|
80
|
+
>
|
|
81
|
+
<div className="flex flex-col p-3 gap-2">
|
|
82
|
+
<div className="flex items-center justify-between">
|
|
83
|
+
<span className="paragraph-small-semibold">Projetos</span>
|
|
84
|
+
{(onAddProject || onManageProjects) && (
|
|
85
|
+
<div className="flex items-center gap-1.5">
|
|
86
|
+
{canAddProject && onAddProject && (
|
|
87
|
+
<Button
|
|
88
|
+
variant="secondary"
|
|
89
|
+
className="h-8! paragraph-small-semibold text-gray-950"
|
|
90
|
+
onClick={onAddProject}
|
|
91
|
+
>
|
|
92
|
+
<IconPlus size={16} />
|
|
93
|
+
Adicionar
|
|
94
|
+
</Button>
|
|
95
|
+
)}
|
|
96
|
+
</div>
|
|
97
|
+
)}
|
|
98
|
+
</div>
|
|
99
|
+
<Command className="gap-2">
|
|
100
|
+
<CommandInput placeholder="Busque aqui" />
|
|
101
|
+
<CommandList className="custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]">
|
|
102
|
+
{projects.length === 0 ? (
|
|
103
|
+
<div className="flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4">
|
|
104
|
+
<IconFolderOpen size={28} className="text-gray-300" />
|
|
105
|
+
<span className="paragraph-small-medium text-center text-gray-500">
|
|
106
|
+
Nenhum projeto encontrado.
|
|
107
|
+
<br />
|
|
108
|
+
Crie um projeto para começar.
|
|
109
|
+
</span>
|
|
110
|
+
</div>
|
|
111
|
+
) : (
|
|
112
|
+
<>
|
|
113
|
+
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
|
114
|
+
{projects.map((project) => {
|
|
115
|
+
const isSelected = selectedProject?.id === project.id;
|
|
116
|
+
return (
|
|
117
|
+
<CommandItem
|
|
118
|
+
key={project.id}
|
|
119
|
+
value={`${project.title}-${project.id}`}
|
|
120
|
+
keywords={[project.title]}
|
|
121
|
+
className={isSelected ? 'bg-gray-50' : ''}
|
|
122
|
+
onSelect={() => onSelectProject(project)}
|
|
123
|
+
>
|
|
124
|
+
<div className="flex items-center justify-between w-full cursor-pointer">
|
|
125
|
+
<div className="flex items-center gap-2 w-full">
|
|
126
|
+
<UserAvatar
|
|
127
|
+
photo={project.photo}
|
|
128
|
+
name={project.title}
|
|
129
|
+
size={32}
|
|
130
|
+
/>
|
|
131
|
+
{project.title}
|
|
132
|
+
</div>
|
|
133
|
+
{isSelected && (
|
|
134
|
+
<IconCheck className="size-4 text-gray-950" />
|
|
135
|
+
)}
|
|
136
|
+
</div>
|
|
137
|
+
</CommandItem>
|
|
138
|
+
);
|
|
139
|
+
})}
|
|
140
|
+
</>
|
|
141
|
+
)}
|
|
142
|
+
</CommandList>
|
|
143
|
+
</Command>
|
|
144
|
+
{onManageProjects && (
|
|
145
|
+
<>
|
|
146
|
+
<div className="border-t border-gray-200" />
|
|
147
|
+
<Button
|
|
148
|
+
variant="ghost"
|
|
149
|
+
className="h-10! paragraph-small-medium text-gray-600 hover:text-gray-950 hover:bg-zinc-50 w-full justify-center"
|
|
150
|
+
onClick={onManageProjects}
|
|
151
|
+
>
|
|
152
|
+
Gerenciar projetos
|
|
153
|
+
</Button>
|
|
154
|
+
</>
|
|
155
|
+
)}
|
|
156
|
+
</div>
|
|
157
|
+
</PopoverContent>
|
|
158
|
+
</Popover>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { ReactNode, useRef, useEffect } from 'react';
|
|
4
|
-
import { AppNavigationContext } from '../AppNavigationContext';
|
|
5
|
-
import { useNavItemsContext } from '../NavItemsContext';
|
|
6
|
-
|
|
7
|
-
function InternalTabsBar({ topOffset = '72px' }: { topOffset?: string }) {
|
|
8
|
-
const { navItems } = useNavItemsContext();
|
|
9
|
-
const tabsListRef = useRef<HTMLDivElement>(null);
|
|
10
|
-
const activeTabRef = useRef<HTMLButtonElement>(null);
|
|
11
|
-
|
|
12
|
-
const activeLabel = navItems.find((i) => i.isActive)?.label;
|
|
13
|
-
|
|
14
|
-
// Scroll active tab into center when active item changes
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
if (activeTabRef.current && tabsListRef.current) {
|
|
17
|
-
const tabsList = tabsListRef.current;
|
|
18
|
-
const activeTabElement = activeTabRef.current;
|
|
19
|
-
const tabsListRect = tabsList.getBoundingClientRect();
|
|
20
|
-
const activeTabRect = activeTabElement.getBoundingClientRect();
|
|
21
|
-
const scrollLeft =
|
|
22
|
-
activeTabElement.offsetLeft - tabsListRect.width / 2 + activeTabRect.width / 2;
|
|
23
|
-
tabsList.scrollTo({ left: Math.max(0, scrollLeft), behavior: 'smooth' });
|
|
24
|
-
}
|
|
25
|
-
}, [activeLabel]);
|
|
26
|
-
|
|
27
|
-
if (!navItems.length) return null;
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<div
|
|
31
|
-
ref={tabsListRef}
|
|
32
|
-
className="md:hidden fixed left-0 right-0 z-40 bg-white border-b border-gray-200 flex overflow-x-auto scrollbar-hide"
|
|
33
|
-
style={{ top: topOffset }}
|
|
34
|
-
>
|
|
35
|
-
{navItems.map((item) => (
|
|
36
|
-
<button
|
|
37
|
-
key={item.label}
|
|
38
|
-
ref={item.isActive ? activeTabRef : undefined}
|
|
39
|
-
onClick={item.onClick}
|
|
40
|
-
className={`flex items-center gap-2 px-4 py-3 shrink-0 border-b-2 transition-colors ${
|
|
41
|
-
item.isActive
|
|
42
|
-
? 'border-gray-950 text-gray-950'
|
|
43
|
-
: 'border-transparent text-gray-500 hover:text-gray-900'
|
|
44
|
-
}`}
|
|
45
|
-
>
|
|
46
|
-
{item.icon && <item.icon size={16} className="shrink-0" />}
|
|
47
|
-
<span
|
|
48
|
-
className={
|
|
49
|
-
item.isActive ? 'paragraph-small-semibold' : 'paragraph-small-medium'
|
|
50
|
-
}
|
|
51
|
-
>
|
|
52
|
-
{item.label}
|
|
53
|
-
</span>
|
|
54
|
-
</button>
|
|
55
|
-
))}
|
|
56
|
-
</div>
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function TabsMobileShell({ children, topOffset }: { children: ReactNode; topOffset?: string }) {
|
|
61
|
-
return (
|
|
62
|
-
<AppNavigationContext.Provider value={{ breakpoint: 'mobile' }}>
|
|
63
|
-
{/*
|
|
64
|
-
Children are hidden visually, but NavItems' useEffect still fires inside
|
|
65
|
-
display:none — React effects are tied to commit phase, not layout visibility.
|
|
66
|
-
This registers navItems in NavItemsContext so InternalTabsBar can read them.
|
|
67
|
-
*/}
|
|
68
|
-
<div className="hidden">{children}</div>
|
|
69
|
-
<InternalTabsBar topOffset={topOffset} />
|
|
70
|
-
</AppNavigationContext.Provider>
|
|
71
|
-
);
|
|
72
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { ReactNode, useRef, useEffect } from 'react';
|
|
4
|
+
import { AppNavigationContext } from '../AppNavigationContext';
|
|
5
|
+
import { useNavItemsContext } from '../NavItemsContext';
|
|
6
|
+
|
|
7
|
+
function InternalTabsBar({ topOffset = '72px' }: { topOffset?: string }) {
|
|
8
|
+
const { navItems } = useNavItemsContext();
|
|
9
|
+
const tabsListRef = useRef<HTMLDivElement>(null);
|
|
10
|
+
const activeTabRef = useRef<HTMLButtonElement>(null);
|
|
11
|
+
|
|
12
|
+
const activeLabel = navItems.find((i) => i.isActive)?.label;
|
|
13
|
+
|
|
14
|
+
// Scroll active tab into center when active item changes
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (activeTabRef.current && tabsListRef.current) {
|
|
17
|
+
const tabsList = tabsListRef.current;
|
|
18
|
+
const activeTabElement = activeTabRef.current;
|
|
19
|
+
const tabsListRect = tabsList.getBoundingClientRect();
|
|
20
|
+
const activeTabRect = activeTabElement.getBoundingClientRect();
|
|
21
|
+
const scrollLeft =
|
|
22
|
+
activeTabElement.offsetLeft - tabsListRect.width / 2 + activeTabRect.width / 2;
|
|
23
|
+
tabsList.scrollTo({ left: Math.max(0, scrollLeft), behavior: 'smooth' });
|
|
24
|
+
}
|
|
25
|
+
}, [activeLabel]);
|
|
26
|
+
|
|
27
|
+
if (!navItems.length) return null;
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div
|
|
31
|
+
ref={tabsListRef}
|
|
32
|
+
className="md:hidden fixed left-0 right-0 z-40 bg-white border-b border-gray-200 flex overflow-x-auto scrollbar-hide"
|
|
33
|
+
style={{ top: topOffset }}
|
|
34
|
+
>
|
|
35
|
+
{navItems.map((item) => (
|
|
36
|
+
<button
|
|
37
|
+
key={item.label}
|
|
38
|
+
ref={item.isActive ? activeTabRef : undefined}
|
|
39
|
+
onClick={item.onClick}
|
|
40
|
+
className={`flex items-center gap-2 px-4 py-3 shrink-0 border-b-2 transition-colors ${
|
|
41
|
+
item.isActive
|
|
42
|
+
? 'border-gray-950 text-gray-950'
|
|
43
|
+
: 'border-transparent text-gray-500 hover:text-gray-900'
|
|
44
|
+
}`}
|
|
45
|
+
>
|
|
46
|
+
{item.icon && <item.icon size={16} className="shrink-0" />}
|
|
47
|
+
<span
|
|
48
|
+
className={
|
|
49
|
+
item.isActive ? 'paragraph-small-semibold' : 'paragraph-small-medium'
|
|
50
|
+
}
|
|
51
|
+
>
|
|
52
|
+
{item.label}
|
|
53
|
+
</span>
|
|
54
|
+
</button>
|
|
55
|
+
))}
|
|
56
|
+
</div>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function TabsMobileShell({ children, topOffset }: { children: ReactNode; topOffset?: string }) {
|
|
61
|
+
return (
|
|
62
|
+
<AppNavigationContext.Provider value={{ breakpoint: 'mobile' }}>
|
|
63
|
+
{/*
|
|
64
|
+
Children are hidden visually, but NavItems' useEffect still fires inside
|
|
65
|
+
display:none — React effects are tied to commit phase, not layout visibility.
|
|
66
|
+
This registers navItems in NavItemsContext so InternalTabsBar can read them.
|
|
67
|
+
*/}
|
|
68
|
+
<div className="hidden">{children}</div>
|
|
69
|
+
<InternalTabsBar topOffset={topOffset} />
|
|
70
|
+
</AppNavigationContext.Provider>
|
|
71
|
+
);
|
|
72
|
+
}
|