@greatapps/common 1.1.261 → 1.1.262

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/dist/components/account/ConfigurationsMyAccountModal.mjs +1 -1
  2. package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -1
  3. package/dist/components/account/ConfirmDeleteAccountModal.mjs.map +1 -1
  4. package/dist/components/account/ConfirmGlobalPreferencesModal.mjs.map +1 -1
  5. package/dist/components/account/DeleteAccountModal.mjs.map +1 -1
  6. package/dist/components/account/DisableTwoFactorAuthModal.mjs.map +1 -1
  7. package/dist/components/account/IsntPossibleDeleteAccountModal.mjs.map +1 -1
  8. package/dist/components/account/TwoFactorAuthModal.mjs.map +1 -1
  9. package/dist/components/account/hooks/useChangePhoneForm.mjs.map +1 -1
  10. package/dist/components/account/hooks/useTwoFactorAuthForm.mjs.map +1 -1
  11. package/dist/components/account/sections/ChangeEmailModal.mjs.map +1 -1
  12. package/dist/components/account/sections/ChangePasswordSection.mjs.map +1 -1
  13. package/dist/components/account/sections/ChangePhoneModal.mjs.map +1 -1
  14. package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
  15. package/dist/components/account/sections/PreferencesSection.mjs.map +1 -1
  16. package/dist/components/account/sections/SecuritySection.mjs.map +1 -1
  17. package/dist/components/embeds/CrispEmbed.mjs.map +1 -1
  18. package/dist/components/embeds/FrillEmbed.mjs.map +1 -1
  19. package/dist/components/layouts/AppMobileNavBar.mjs +1 -1
  20. package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
  21. package/dist/components/layouts/AppNavBar.mjs.map +1 -1
  22. package/dist/components/layouts/MdSideBarNavigation.mjs.map +1 -1
  23. package/dist/components/layouts/NavBar.mjs.map +1 -1
  24. package/dist/components/layouts/NotificationsPopover.mjs.map +1 -1
  25. package/dist/components/layouts/ProfilePopover.mjs.map +1 -1
  26. package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
  27. package/dist/components/modals/BuyCreditsModal.mjs.map +1 -1
  28. package/dist/components/navigation/CancelledSubscriptionBanner.mjs.map +1 -1
  29. package/dist/components/navigation/NavItemsContext.mjs.map +1 -1
  30. package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
  31. package/dist/components/navigation/shells/TabsMobileShell.mjs.map +1 -1
  32. package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
  33. package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
  34. package/dist/components/ui/buttons/Button.mjs.map +1 -1
  35. package/dist/components/ui/buttons/CancelButton.mjs.map +1 -1
  36. package/dist/components/ui/buttons/CopyButton.mjs.map +1 -1
  37. package/dist/components/ui/data-display/Accordion.mjs.map +1 -1
  38. package/dist/components/ui/data-display/Badge.mjs.map +1 -1
  39. package/dist/components/ui/data-display/Card.mjs.map +1 -1
  40. package/dist/components/ui/data-display/CardBrandIcons.mjs.map +1 -1
  41. package/dist/components/ui/data-display/CardItem.mjs.map +1 -1
  42. package/dist/components/ui/data-display/Pagination.mjs.map +1 -1
  43. package/dist/components/ui/data-display/PaymentInfoCard.mjs.map +1 -1
  44. package/dist/components/ui/data-display/ScrollArea.mjs.map +1 -1
  45. package/dist/components/ui/data-display/Separator.mjs.map +1 -1
  46. package/dist/components/ui/data-display/Table.mjs.map +1 -1
  47. package/dist/components/ui/data-display/Tabs.mjs.map +1 -1
  48. package/dist/components/ui/feedback/CircularProgress.mjs.map +1 -1
  49. package/dist/components/ui/feedback/DefaultCircularProgress.mjs.map +1 -1
  50. package/dist/components/ui/feedback/LoadingOverlay.mjs.map +1 -1
  51. package/dist/components/ui/feedback/Progress.mjs.map +1 -1
  52. package/dist/components/ui/feedback/Skeleton.mjs.map +1 -1
  53. package/dist/components/ui/feedback/Toast.mjs.map +1 -1
  54. package/dist/components/ui/form/Calendar.mjs.map +1 -1
  55. package/dist/components/ui/form/Checkbox.mjs.map +1 -1
  56. package/dist/components/ui/form/ComboboxField.mjs.map +1 -1
  57. package/dist/components/ui/form/DatePicker.mjs.map +1 -1
  58. package/dist/components/ui/form/DateRangePicker.mjs.map +1 -1
  59. package/dist/components/ui/form/FormField.mjs.map +1 -1
  60. package/dist/components/ui/form/Input.mjs.map +1 -1
  61. package/dist/components/ui/form/InputOtp.mjs.map +1 -1
  62. package/dist/components/ui/form/PhoneInput.mjs.map +1 -1
  63. package/dist/components/ui/form/RadioGroup.mjs.map +1 -1
  64. package/dist/components/ui/form/Select.mjs +1 -1
  65. package/dist/components/ui/form/Select.mjs.map +1 -1
  66. package/dist/components/ui/form/Switch.mjs.map +1 -1
  67. package/dist/components/ui/form/Textarea.mjs.map +1 -1
  68. package/dist/components/ui/overlay/Command.mjs.map +1 -1
  69. package/dist/components/ui/overlay/Dialog.mjs.map +1 -1
  70. package/dist/components/ui/overlay/Popover.mjs.map +1 -1
  71. package/dist/components/ui/overlay/Sheet.mjs.map +1 -1
  72. package/dist/components/ui/overlay/Tooltip.mjs.map +1 -1
  73. package/dist/hooks/copy-to-clipboard.hook.mjs.map +1 -1
  74. package/dist/index.mjs.map +1 -1
  75. package/dist/middleware.mjs.map +1 -1
  76. package/dist/modules/accounts/actions/account-management.action.mjs.map +1 -1
  77. package/dist/modules/accounts/actions/find-current-account.action.mjs.map +1 -1
  78. package/dist/modules/accounts/actions/list-currencies.action.mjs.map +1 -1
  79. package/dist/modules/accounts/actions/list-timezones.action.mjs.map +1 -1
  80. package/dist/modules/accounts/hooks/current-account.hook.mjs.map +1 -1
  81. package/dist/modules/accounts/hooks/useAccountManagement.mjs.map +1 -1
  82. package/dist/modules/accounts/hooks/useCurrencies.mjs.map +1 -1
  83. package/dist/modules/accounts/hooks/useTimezones.mjs.map +1 -1
  84. package/dist/modules/accounts/services/account.service.mjs.map +1 -1
  85. package/dist/modules/auth/actions/validate-session.action.mjs.map +1 -1
  86. package/dist/modules/auth/hooks/login.hook.mjs.map +1 -1
  87. package/dist/modules/auth/hooks/logout.hook.mjs.map +1 -1
  88. package/dist/modules/auth/hooks/register.hook.mjs.map +1 -1
  89. package/dist/modules/cards/actions/list-cards.action.mjs.map +1 -1
  90. package/dist/modules/cards/hooks/cards.hook.mjs.map +1 -1
  91. package/dist/modules/cards/services/cards.service.mjs.map +1 -1
  92. package/dist/modules/cards/types.mjs.map +1 -1
  93. package/dist/modules/ia-credits/actions/list-ia-credits.action.mjs.map +1 -1
  94. package/dist/modules/plans/actions/find-plan-by-id.action.mjs.map +1 -1
  95. package/dist/modules/plans/hooks/use-has-plan-addon.hook.mjs.map +1 -1
  96. package/dist/modules/plans/hooks/use-plan-by-id.hook.mjs.map +1 -1
  97. package/dist/modules/plans/services/plans.service.mjs.map +1 -1
  98. package/dist/modules/plans/types/plan.type.mjs.map +1 -1
  99. package/dist/modules/projects/actions/add-project-user.action.mjs.map +1 -1
  100. package/dist/modules/projects/actions/list-all-account-users.action.mjs.map +1 -1
  101. package/dist/modules/projects/actions/list-available-users.action.mjs.map +1 -1
  102. package/dist/modules/projects/actions/list-project-users.action.mjs.map +1 -1
  103. package/dist/modules/projects/actions/remove-project-user.action.mjs.map +1 -1
  104. package/dist/modules/projects/hooks/add-project-user.hook.mjs.map +1 -1
  105. package/dist/modules/projects/hooks/list-all-account-users.hook.mjs.map +1 -1
  106. package/dist/modules/projects/hooks/list-available-users.hook.mjs.map +1 -1
  107. package/dist/modules/projects/hooks/list-project-users.hook.mjs.map +1 -1
  108. package/dist/modules/projects/hooks/remove-project-user.hook.mjs.map +1 -1
  109. package/dist/modules/subscriptions/actions/calculate-subscription.action.mjs.map +1 -1
  110. package/dist/modules/subscriptions/actions/list-subscriptions.action.mjs.map +1 -1
  111. package/dist/modules/subscriptions/actions/update-subscription-plan.action.mjs.map +1 -1
  112. package/dist/modules/subscriptions/constants/query-keys.constants.mjs.map +1 -1
  113. package/dist/modules/subscriptions/hooks/calculate-subscription.hook.mjs.map +1 -1
  114. package/dist/modules/subscriptions/hooks/find-active-subscription.hook.mjs.map +1 -1
  115. package/dist/modules/subscriptions/hooks/list-subscriptions.hook.mjs.map +1 -1
  116. package/dist/modules/subscriptions/hooks/update-subscription-plan.hook.mjs.map +1 -1
  117. package/dist/modules/subscriptions/types/calculate-subscription.type.mjs.map +1 -1
  118. package/dist/modules/subscriptions/utils/build-plan-extras.mjs.map +1 -1
  119. package/dist/modules/subscriptions/utils/periodicity.mjs.map +1 -1
  120. package/dist/modules/subscriptions/utils/resolve-plan-extras-prices.mjs.map +1 -1
  121. package/dist/modules/users/action/find-user-by-id.action.mjs.map +1 -1
  122. package/dist/modules/users/action/list-messages.action.mjs.map +1 -1
  123. package/dist/modules/users/action/mark-all-messages-as-read.action.mjs.map +1 -1
  124. package/dist/modules/users/action/mark-message-as-read.action.mjs.map +1 -1
  125. package/dist/modules/users/hooks/messages.hook.mjs.map +1 -1
  126. package/dist/modules/whitelabel/actions/find-whitelabel-styles.action.mjs.map +1 -1
  127. package/dist/modules/whitelabel/actions/find-whitelabel.action.mjs.map +1 -1
  128. package/dist/modules/whitelabel/actions/revalidate-whitelabel-styles.action.mjs.map +1 -1
  129. package/dist/modules/whitelabel/actions/revalidate-whitelabel.action.mjs.map +1 -1
  130. package/dist/modules/whitelabel/services/whitelabel-styles.service.mjs.map +1 -1
  131. package/dist/providers/whitelabel.provider.mjs.map +1 -1
  132. package/dist/store/useBuyCreditsModal.mjs.map +1 -1
  133. package/dist/utils/countries.mjs.map +1 -1
  134. package/dist/utils/safeServerAction.mjs.map +1 -1
  135. package/dist/utils/withAction.mjs.map +1 -1
  136. package/package.json +89 -89
  137. package/src/components/account/ConfigurationsMyAccountModal.tsx +150 -150
  138. package/src/components/account/ConfirmDeleteAccountModal.tsx +55 -55
  139. package/src/components/account/ConfirmGlobalPreferencesModal.tsx +66 -66
  140. package/src/components/account/DeleteAccountModal.tsx +130 -130
  141. package/src/components/account/DisableTwoFactorAuthModal.tsx +86 -86
  142. package/src/components/account/IsntPossibleDeleteAccountModal.tsx +49 -49
  143. package/src/components/account/TwoFactorAuthModal.tsx +223 -223
  144. package/src/components/account/hooks/useChangePhoneForm.tsx +81 -81
  145. package/src/components/account/hooks/useTwoFactorAuthForm.tsx +101 -101
  146. package/src/components/account/sections/ChangeEmailModal.tsx +225 -225
  147. package/src/components/account/sections/ChangePasswordSection.tsx +64 -64
  148. package/src/components/account/sections/ChangePhoneModal.tsx +231 -231
  149. package/src/components/account/sections/MyProfileSection.tsx +327 -327
  150. package/src/components/account/sections/PreferencesSection.tsx +273 -273
  151. package/src/components/account/sections/SecuritySection.tsx +160 -160
  152. package/src/components/embeds/CrispEmbed.tsx +101 -101
  153. package/src/components/embeds/FrillEmbed.tsx +119 -119
  154. package/src/components/layouts/AppMobileNavBar.tsx +118 -118
  155. package/src/components/layouts/AppNavBar.tsx +51 -51
  156. package/src/components/layouts/MdSideBarNavigation.tsx +56 -56
  157. package/src/components/layouts/NavBar.tsx +120 -120
  158. package/src/components/layouts/NotificationsPopover.tsx +115 -115
  159. package/src/components/layouts/ProfilePopover.tsx +164 -164
  160. package/src/components/layouts/UsersSelectorPopover.tsx +238 -238
  161. package/src/components/modals/BuyCreditsModal.tsx +301 -301
  162. package/src/components/navigation/CancelledSubscriptionBanner.tsx +69 -69
  163. package/src/components/navigation/NavItemsContext.ts +20 -20
  164. package/src/components/navigation/ProjectSelectorPopover.tsx +157 -157
  165. package/src/components/navigation/shells/TabsMobileShell.tsx +72 -72
  166. package/src/components/navigation/subcomponents/ProjectSelector.tsx +156 -156
  167. package/src/components/pages/notifications/Notifications.tsx +160 -160
  168. package/src/components/ui/buttons/Button.tsx +57 -57
  169. package/src/components/ui/buttons/CancelButton.tsx +14 -14
  170. package/src/components/ui/buttons/CopyButton.tsx +54 -54
  171. package/src/components/ui/data-display/Accordion.tsx +81 -81
  172. package/src/components/ui/data-display/Badge.tsx +47 -47
  173. package/src/components/ui/data-display/Card.tsx +93 -93
  174. package/src/components/ui/data-display/CardBrandIcons.tsx +336 -336
  175. package/src/components/ui/data-display/CardItem.tsx +75 -75
  176. package/src/components/ui/data-display/Pagination.tsx +126 -126
  177. package/src/components/ui/data-display/PaymentInfoCard.tsx +186 -186
  178. package/src/components/ui/data-display/ScrollArea.tsx +59 -59
  179. package/src/components/ui/data-display/Separator.tsx +29 -29
  180. package/src/components/ui/data-display/Table.tsx +117 -117
  181. package/src/components/ui/data-display/Tabs.tsx +67 -67
  182. package/src/components/ui/feedback/CircularProgress.tsx +75 -75
  183. package/src/components/ui/feedback/DefaultCircularProgress.tsx +61 -61
  184. package/src/components/ui/feedback/LoadingOverlay.tsx +31 -31
  185. package/src/components/ui/feedback/Progress.tsx +40 -40
  186. package/src/components/ui/feedback/Skeleton.tsx +5 -5
  187. package/src/components/ui/feedback/Toast.tsx +101 -101
  188. package/src/components/ui/form/Calendar.tsx +228 -228
  189. package/src/components/ui/form/Checkbox.tsx +31 -31
  190. package/src/components/ui/form/ComboboxField.tsx +154 -154
  191. package/src/components/ui/form/DatePicker.tsx +97 -97
  192. package/src/components/ui/form/DateRangePicker.tsx +108 -108
  193. package/src/components/ui/form/FormField.tsx +131 -131
  194. package/src/components/ui/form/Input.tsx +20 -20
  195. package/src/components/ui/form/InputOtp.tsx +80 -80
  196. package/src/components/ui/form/PhoneInput.tsx +205 -205
  197. package/src/components/ui/form/RadioGroup.tsx +45 -45
  198. package/src/components/ui/form/Select.tsx +200 -200
  199. package/src/components/ui/form/Switch.tsx +32 -32
  200. package/src/components/ui/form/Textarea.tsx +19 -19
  201. package/src/components/ui/overlay/Command.tsx +185 -185
  202. package/src/components/ui/overlay/Dialog.tsx +151 -151
  203. package/src/components/ui/overlay/Popover.tsx +49 -49
  204. package/src/components/ui/overlay/Sheet.tsx +166 -166
  205. package/src/components/ui/overlay/Tooltip.tsx +62 -62
  206. package/src/hooks/copy-to-clipboard.hook.tsx +67 -67
  207. package/src/index.ts +376 -376
  208. package/src/middleware.ts +4 -4
  209. package/src/modules/accounts/actions/account-management.action.ts +91 -91
  210. package/src/modules/accounts/actions/find-current-account.action.ts +9 -9
  211. package/src/modules/accounts/actions/list-currencies.action.ts +8 -8
  212. package/src/modules/accounts/actions/list-timezones.action.ts +8 -8
  213. package/src/modules/accounts/hooks/current-account.hook.tsx +22 -22
  214. package/src/modules/accounts/hooks/useAccountManagement.ts +85 -85
  215. package/src/modules/accounts/hooks/useCurrencies.ts +15 -15
  216. package/src/modules/accounts/hooks/useTimezones.ts +15 -15
  217. package/src/modules/accounts/services/account.service.ts +236 -236
  218. package/src/modules/accounts/types.ts +214 -214
  219. package/src/modules/auth/actions/validate-session.action.ts +56 -56
  220. package/src/modules/auth/hooks/login.hook.tsx +13 -13
  221. package/src/modules/auth/hooks/logout.hook.tsx +11 -11
  222. package/src/modules/auth/hooks/register.hook.tsx +11 -11
  223. package/src/modules/cards/actions/list-cards.action.ts +8 -8
  224. package/src/modules/cards/hooks/cards.hook.ts +14 -14
  225. package/src/modules/cards/services/cards.service.ts +32 -32
  226. package/src/modules/cards/types.ts +32 -32
  227. package/src/modules/ia-credits/actions/list-ia-credits.action.ts +8 -8
  228. package/src/modules/plans/actions/find-plan-by-id.action.ts +8 -8
  229. package/src/modules/plans/hooks/use-has-plan-addon.hook.ts +17 -17
  230. package/src/modules/plans/hooks/use-plan-by-id.hook.ts +13 -13
  231. package/src/modules/plans/services/plans.service.ts +36 -36
  232. package/src/modules/plans/types/plan.type.ts +21 -21
  233. package/src/modules/projects/actions/add-project-user.action.ts +9 -9
  234. package/src/modules/projects/actions/list-all-account-users.action.ts +9 -9
  235. package/src/modules/projects/actions/list-available-users.action.ts +9 -9
  236. package/src/modules/projects/actions/list-project-users.action.ts +9 -9
  237. package/src/modules/projects/actions/remove-project-user.action.ts +9 -9
  238. package/src/modules/projects/hooks/add-project-user.hook.ts +69 -69
  239. package/src/modules/projects/hooks/list-all-account-users.hook.ts +34 -34
  240. package/src/modules/projects/hooks/list-available-users.hook.ts +33 -33
  241. package/src/modules/projects/hooks/list-project-users.hook.ts +33 -33
  242. package/src/modules/projects/hooks/remove-project-user.hook.ts +69 -69
  243. package/src/modules/subscriptions/actions/calculate-subscription.action.ts +9 -9
  244. package/src/modules/subscriptions/actions/list-subscriptions.action.ts +9 -9
  245. package/src/modules/subscriptions/actions/update-subscription-plan.action.ts +26 -26
  246. package/src/modules/subscriptions/constants/query-keys.constants.ts +1 -1
  247. package/src/modules/subscriptions/hooks/calculate-subscription.hook.ts +13 -13
  248. package/src/modules/subscriptions/hooks/find-active-subscription.hook.ts +19 -19
  249. package/src/modules/subscriptions/hooks/list-subscriptions.hook.ts +16 -16
  250. package/src/modules/subscriptions/hooks/update-subscription-plan.hook.ts +25 -25
  251. package/src/modules/subscriptions/types/billing-period.type.ts +1 -1
  252. package/src/modules/subscriptions/types/calculate-subscription.type.ts +75 -75
  253. package/src/modules/subscriptions/utils/build-plan-extras.ts +56 -56
  254. package/src/modules/subscriptions/utils/periodicity.ts +52 -52
  255. package/src/modules/subscriptions/utils/resolve-plan-extras-prices.ts +23 -23
  256. package/src/modules/users/action/find-user-by-id.action.ts +8 -8
  257. package/src/modules/users/action/list-messages.action.ts +12 -12
  258. package/src/modules/users/action/mark-all-messages-as-read.action.ts +8 -8
  259. package/src/modules/users/action/mark-message-as-read.action.ts +8 -8
  260. package/src/modules/users/hooks/messages.hook.ts +60 -60
  261. package/src/modules/whitelabel/actions/find-whitelabel-styles.action.ts +14 -14
  262. package/src/modules/whitelabel/actions/find-whitelabel.action.ts +23 -23
  263. package/src/modules/whitelabel/actions/revalidate-whitelabel-styles.action.ts +10 -10
  264. package/src/modules/whitelabel/actions/revalidate-whitelabel.action.ts +19 -19
  265. package/src/modules/whitelabel/schema.ts +83 -83
  266. package/src/modules/whitelabel/services/whitelabel-styles.service.ts +129 -129
  267. package/src/modules/whitelabel/styles-schema.ts +37 -37
  268. package/src/providers/whitelabel.provider.tsx +54 -54
  269. package/src/store/useBuyCreditsModal.ts +25 -25
  270. package/src/utils/countries.ts +224 -224
  271. package/src/utils/safeServerAction.ts +21 -21
  272. package/src/utils/withAction.ts +13 -13
@@ -1,69 +1,69 @@
1
- 'use client';
2
-
3
- import { useState, useEffect, useCallback } from 'react';
4
- import { IconAlertOctagon, IconX } from '@tabler/icons-react';
5
- import { useActiveSubscription } from '../../modules/subscriptions/hooks/find-active-subscription.hook';
6
-
7
- function daysBetween(a: Date, b: Date): number {
8
- const msPerDay = 24 * 60 * 60 * 1000;
9
- const da = new Date(a.getFullYear(), a.getMonth(), a.getDate());
10
- const db = new Date(b.getFullYear(), b.getMonth(), b.getDate());
11
- return Math.round((db.getTime() - da.getTime()) / msPerDay);
12
- }
13
-
14
- interface CancelledSubscriptionBannerProps {
15
- onReactivate?: () => void;
16
- }
17
-
18
- export function CancelledSubscriptionBanner({ onReactivate }: CancelledSubscriptionBannerProps) {
19
- const { data: { data: [subscription] = [] } = {} } = useActiveSubscription();
20
- const [visible, setVisible] = useState(true);
21
- const [animated, setAnimated] = useState(false);
22
-
23
- useEffect(() => {
24
- const timer = setTimeout(() => setAnimated(true), 50);
25
- return () => clearTimeout(timer);
26
- }, []);
27
-
28
- const dismiss = useCallback(() => setVisible(false), []);
29
-
30
- const cancellationDate = subscription?.date_cancellation;
31
- if (!cancellationDate || !visible) return null;
32
-
33
- const today = new Date();
34
- const daysSinceCancellation = daysBetween(new Date(cancellationDate), today);
35
- if (daysSinceCancellation < 0 || daysSinceCancellation > 5) return null;
36
-
37
- const daysRemaining = Math.max(0, 5 - daysSinceCancellation);
38
-
39
- return (
40
- <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">
41
- <div
42
- 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'}`}
43
- >
44
- {daysRemaining > 0 && (
45
- <div className="flex items-center gap-2 flex-1 w-full sm:w-auto">
46
- <IconAlertOctagon size={16} className="text-white shrink-0" />
47
- <span className="paragraph-xsmall-semibold text-white">
48
- Assinatura cancelada! Em {daysRemaining} dias suas páginas serão tiradas do ar!
49
- </span>
50
- </div>
51
- )}
52
- <div className="flex items-center gap-1.5 w-full sm:w-auto justify-between sm:justify-start">
53
- <button
54
- type="button"
55
- className="flex items-center justify-center p-1.5 cursor-pointer"
56
- onClick={onReactivate}
57
- >
58
- <span className="paragraph-xsmall-semibold text-white underline">
59
- Reativar assinatura
60
- </span>
61
- </button>
62
- <button type="button" className="cursor-pointer shrink-0" onClick={dismiss}>
63
- <IconX size={18} className="text-red-200" />
64
- </button>
65
- </div>
66
- </div>
67
- </div>
68
- );
69
- }
1
+ 'use client';
2
+
3
+ import { useState, useEffect, useCallback } from 'react';
4
+ import { IconAlertOctagon, IconX } from '@tabler/icons-react';
5
+ import { useActiveSubscription } from '../../modules/subscriptions/hooks/find-active-subscription.hook';
6
+
7
+ function daysBetween(a: Date, b: Date): number {
8
+ const msPerDay = 24 * 60 * 60 * 1000;
9
+ const da = new Date(a.getFullYear(), a.getMonth(), a.getDate());
10
+ const db = new Date(b.getFullYear(), b.getMonth(), b.getDate());
11
+ return Math.round((db.getTime() - da.getTime()) / msPerDay);
12
+ }
13
+
14
+ interface CancelledSubscriptionBannerProps {
15
+ onReactivate?: () => void;
16
+ }
17
+
18
+ export function CancelledSubscriptionBanner({ onReactivate }: CancelledSubscriptionBannerProps) {
19
+ const { data: { data: [subscription] = [] } = {} } = useActiveSubscription();
20
+ const [visible, setVisible] = useState(true);
21
+ const [animated, setAnimated] = useState(false);
22
+
23
+ useEffect(() => {
24
+ const timer = setTimeout(() => setAnimated(true), 50);
25
+ return () => clearTimeout(timer);
26
+ }, []);
27
+
28
+ const dismiss = useCallback(() => setVisible(false), []);
29
+
30
+ const cancellationDate = subscription?.date_cancellation;
31
+ if (!cancellationDate || !visible) return null;
32
+
33
+ const today = new Date();
34
+ const daysSinceCancellation = daysBetween(new Date(cancellationDate), today);
35
+ if (daysSinceCancellation < 0 || daysSinceCancellation > 5) return null;
36
+
37
+ const daysRemaining = Math.max(0, 5 - daysSinceCancellation);
38
+
39
+ return (
40
+ <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">
41
+ <div
42
+ 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'}`}
43
+ >
44
+ {daysRemaining > 0 && (
45
+ <div className="flex items-center gap-2 flex-1 w-full sm:w-auto">
46
+ <IconAlertOctagon size={16} className="text-white shrink-0" />
47
+ <span className="paragraph-xsmall-semibold text-white">
48
+ Assinatura cancelada! Em {daysRemaining} dias suas páginas serão tiradas do ar!
49
+ </span>
50
+ </div>
51
+ )}
52
+ <div className="flex items-center gap-1.5 w-full sm:w-auto justify-between sm:justify-start">
53
+ <button
54
+ type="button"
55
+ className="flex items-center justify-center p-1.5 cursor-pointer"
56
+ onClick={onReactivate}
57
+ >
58
+ <span className="paragraph-xsmall-semibold text-white underline">
59
+ Reativar assinatura
60
+ </span>
61
+ </button>
62
+ <button type="button" className="cursor-pointer shrink-0" onClick={dismiss}>
63
+ <IconX size={18} className="text-red-200" />
64
+ </button>
65
+ </div>
66
+ </div>
67
+ </div>
68
+ );
69
+ }
@@ -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,157 +1,157 @@
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
- Tooltip,
17
- TooltipContent,
18
- TooltipTrigger,
19
- UserAvatar,
20
- } from '../../index';
21
- import { IconCheck, IconChevronDown, IconFolderOpen, IconPlus, IconSettings } from '@tabler/icons-react';
22
- import type { NavigationProject } from './types';
23
-
24
- interface ProjectSelectorPopoverProps {
25
- open: boolean;
26
- setOpen: Dispatch<SetStateAction<boolean>>;
27
- titleRef?: RefObject<HTMLSpanElement | null>;
28
- projects: NavigationProject[];
29
- selectedProject: NavigationProject | null;
30
- onSelectProject: (project: NavigationProject) => void;
31
- onAddProject: () => void;
32
- onManageProjects: () => void;
33
- children?: React.ReactNode;
34
- }
35
-
36
- function ProjectItemSkeleton() {
37
- return (
38
- <div className="flex items-center justify-between px-2 py-1.5 gap-2">
39
- <div className="flex items-center gap-2 flex-1">
40
- <div className="skeleton size-8 rounded-lg shrink-0" />
41
- <div className="skeleton h-3.5 w-32 rounded" />
42
- </div>
43
- <div className="skeleton size-4 rounded-full shrink-0" />
44
- </div>
45
- );
46
- }
47
-
48
- export function ProjectSelectorPopover({
49
- open,
50
- setOpen,
51
- titleRef,
52
- projects,
53
- selectedProject,
54
- onSelectProject,
55
- onAddProject,
56
- onManageProjects,
57
- children,
58
- }: ProjectSelectorPopoverProps) {
59
- const { hasAddon: canAddProject } = useHasPlanAddon(ADDON_IDS.PROJECTS);
60
-
61
- return (
62
- <Popover open={open} onOpenChange={setOpen}>
63
- <PopoverTrigger asChild>
64
- {children ?? (
65
- <button className="cursor-pointer">
66
- <IconChevronDown
67
- size={20}
68
- className={`transition-transform duration-200 ${open ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}
69
- />
70
- </button>
71
- )}
72
- </PopoverTrigger>
73
- <PopoverContent
74
- className="w-[296px] p-0 bg-white rounded-2xl shadow-md border border-gray-200"
75
- align="start"
76
- sideOffset={8}
77
- onOpenAutoFocus={(e: Event) => e.preventDefault()}
78
- onInteractOutside={(event: Event) => {
79
- if (titleRef?.current?.contains(event.target as Node)) {
80
- event.preventDefault();
81
- }
82
- }}
83
- >
84
- <div className="flex flex-col p-3 gap-2">
85
- <div className="flex items-center justify-between">
86
- <span className="paragraph-small-semibold">Projetos</span>
87
- <div className="flex items-center gap-1.5">
88
- {canAddProject && (
89
- <Button
90
- variant="secondary"
91
- className="h-8! paragraph-small-semibold text-gray-950"
92
- onClick={onAddProject}
93
- >
94
- <IconPlus size={16} />
95
- Adicionar
96
- </Button>
97
- )}
98
- <Tooltip>
99
- <TooltipTrigger asChild>
100
- <Button variant="secondary" className="p-0 size-8" onClick={onManageProjects}>
101
- <IconSettings size={18} />
102
- </Button>
103
- </TooltipTrigger>
104
- <TooltipContent className="z-[1002]">Visualizar todos projetos</TooltipContent>
105
- </Tooltip>
106
- </div>
107
- </div>
108
- <Command className="gap-2">
109
- <CommandInput placeholder="Busque aqui" />
110
- <CommandList className="custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]">
111
- {projects.length === 0 ? (
112
- <div className="flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4">
113
- <IconFolderOpen size={28} className="text-gray-300" />
114
- <span className="paragraph-small-medium text-center text-gray-500">
115
- Nenhum projeto encontrado.
116
- <br />
117
- Crie um projeto para começar.
118
- </span>
119
- </div>
120
- ) : (
121
- <>
122
- <CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
123
- {projects.map((project) => {
124
- const isSelected = selectedProject?.id === project.id;
125
- return (
126
- <CommandItem
127
- key={project.id}
128
- value={`${project.title}-${project.id}`}
129
- keywords={[project.title]}
130
- className={isSelected ? 'bg-gray-50' : ''}
131
- onSelect={() => onSelectProject(project)}
132
- >
133
- <div className="flex items-center justify-between w-full cursor-pointer">
134
- <div className="flex items-center gap-2 w-full">
135
- <UserAvatar
136
- photo={project.photo}
137
- name={project.title}
138
- size={32}
139
- />
140
- {project.title}
141
- </div>
142
- {isSelected && (
143
- <IconCheck className="size-4 text-gray-950" />
144
- )}
145
- </div>
146
- </CommandItem>
147
- );
148
- })}
149
- </>
150
- )}
151
- </CommandList>
152
- </Command>
153
- </div>
154
- </PopoverContent>
155
- </Popover>
156
- );
157
- }
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
+ Tooltip,
17
+ TooltipContent,
18
+ TooltipTrigger,
19
+ UserAvatar,
20
+ } from '../../index';
21
+ import { IconCheck, IconChevronDown, IconFolderOpen, IconPlus, IconSettings } from '@tabler/icons-react';
22
+ import type { NavigationProject } from './types';
23
+
24
+ interface ProjectSelectorPopoverProps {
25
+ open: boolean;
26
+ setOpen: Dispatch<SetStateAction<boolean>>;
27
+ titleRef?: RefObject<HTMLSpanElement | null>;
28
+ projects: NavigationProject[];
29
+ selectedProject: NavigationProject | null;
30
+ onSelectProject: (project: NavigationProject) => void;
31
+ onAddProject: () => void;
32
+ onManageProjects: () => void;
33
+ children?: React.ReactNode;
34
+ }
35
+
36
+ function ProjectItemSkeleton() {
37
+ return (
38
+ <div className="flex items-center justify-between px-2 py-1.5 gap-2">
39
+ <div className="flex items-center gap-2 flex-1">
40
+ <div className="skeleton size-8 rounded-lg shrink-0" />
41
+ <div className="skeleton h-3.5 w-32 rounded" />
42
+ </div>
43
+ <div className="skeleton size-4 rounded-full shrink-0" />
44
+ </div>
45
+ );
46
+ }
47
+
48
+ export function ProjectSelectorPopover({
49
+ open,
50
+ setOpen,
51
+ titleRef,
52
+ projects,
53
+ selectedProject,
54
+ onSelectProject,
55
+ onAddProject,
56
+ onManageProjects,
57
+ children,
58
+ }: ProjectSelectorPopoverProps) {
59
+ const { hasAddon: canAddProject } = useHasPlanAddon(ADDON_IDS.PROJECTS);
60
+
61
+ return (
62
+ <Popover open={open} onOpenChange={setOpen}>
63
+ <PopoverTrigger asChild>
64
+ {children ?? (
65
+ <button className="cursor-pointer">
66
+ <IconChevronDown
67
+ size={20}
68
+ className={`transition-transform duration-200 ${open ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}
69
+ />
70
+ </button>
71
+ )}
72
+ </PopoverTrigger>
73
+ <PopoverContent
74
+ className="w-[296px] p-0 bg-white rounded-2xl shadow-md border border-gray-200"
75
+ align="start"
76
+ sideOffset={8}
77
+ onOpenAutoFocus={(e: Event) => e.preventDefault()}
78
+ onInteractOutside={(event: Event) => {
79
+ if (titleRef?.current?.contains(event.target as Node)) {
80
+ event.preventDefault();
81
+ }
82
+ }}
83
+ >
84
+ <div className="flex flex-col p-3 gap-2">
85
+ <div className="flex items-center justify-between">
86
+ <span className="paragraph-small-semibold">Projetos</span>
87
+ <div className="flex items-center gap-1.5">
88
+ {canAddProject && (
89
+ <Button
90
+ variant="secondary"
91
+ className="h-8! paragraph-small-semibold text-gray-950"
92
+ onClick={onAddProject}
93
+ >
94
+ <IconPlus size={16} />
95
+ Adicionar
96
+ </Button>
97
+ )}
98
+ <Tooltip>
99
+ <TooltipTrigger asChild>
100
+ <Button variant="secondary" className="p-0 size-8" onClick={onManageProjects}>
101
+ <IconSettings size={18} />
102
+ </Button>
103
+ </TooltipTrigger>
104
+ <TooltipContent className="z-[1002]">Visualizar todos projetos</TooltipContent>
105
+ </Tooltip>
106
+ </div>
107
+ </div>
108
+ <Command className="gap-2">
109
+ <CommandInput placeholder="Busque aqui" />
110
+ <CommandList className="custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]">
111
+ {projects.length === 0 ? (
112
+ <div className="flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4">
113
+ <IconFolderOpen size={28} className="text-gray-300" />
114
+ <span className="paragraph-small-medium text-center text-gray-500">
115
+ Nenhum projeto encontrado.
116
+ <br />
117
+ Crie um projeto para começar.
118
+ </span>
119
+ </div>
120
+ ) : (
121
+ <>
122
+ <CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
123
+ {projects.map((project) => {
124
+ const isSelected = selectedProject?.id === project.id;
125
+ return (
126
+ <CommandItem
127
+ key={project.id}
128
+ value={`${project.title}-${project.id}`}
129
+ keywords={[project.title]}
130
+ className={isSelected ? 'bg-gray-50' : ''}
131
+ onSelect={() => onSelectProject(project)}
132
+ >
133
+ <div className="flex items-center justify-between w-full cursor-pointer">
134
+ <div className="flex items-center gap-2 w-full">
135
+ <UserAvatar
136
+ photo={project.photo}
137
+ name={project.title}
138
+ size={32}
139
+ />
140
+ {project.title}
141
+ </div>
142
+ {isSelected && (
143
+ <IconCheck className="size-4 text-gray-950" />
144
+ )}
145
+ </div>
146
+ </CommandItem>
147
+ );
148
+ })}
149
+ </>
150
+ )}
151
+ </CommandList>
152
+ </Command>
153
+ </div>
154
+ </PopoverContent>
155
+ </Popover>
156
+ );
157
+ }
@@ -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
+ }