@greatapps/common 1.1.517 → 1.1.518

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 (412) 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/account/sections/TokenSection.mjs.map +1 -1
  18. package/dist/components/embeds/ClarityEmbed.mjs +55 -0
  19. package/dist/components/embeds/ClarityEmbed.mjs.map +1 -0
  20. package/dist/components/embeds/CrispEmbed.mjs.map +1 -1
  21. package/dist/components/embeds/EmbedWidgets.mjs +3 -1
  22. package/dist/components/embeds/EmbedWidgets.mjs.map +1 -1
  23. package/dist/components/embeds/FrillEmbed.mjs.map +1 -1
  24. package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
  25. package/dist/components/layouts/AppNavBar.mjs.map +1 -1
  26. package/dist/components/layouts/MdSideBarNavigation.mjs.map +1 -1
  27. package/dist/components/layouts/NavBar.mjs.map +1 -1
  28. package/dist/components/layouts/NotificationsPopover.mjs.map +1 -1
  29. package/dist/components/layouts/ProfilePopover.mjs.map +1 -1
  30. package/dist/components/layouts/SideBarNavigation.mjs.map +1 -1
  31. package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
  32. package/dist/components/layouts/WhitelabelCodes.mjs.map +1 -1
  33. package/dist/components/modals/BuyCreditsModal.mjs.map +1 -1
  34. package/dist/components/modals/PaidPlanRequiredModal.mjs.map +1 -1
  35. package/dist/components/modals/cards/AddCardModal.mjs.map +1 -1
  36. package/dist/components/modals/cards/CardFormFields.mjs.map +1 -1
  37. package/dist/components/navigation/CancelledSubscriptionBanner.mjs.map +1 -1
  38. package/dist/components/navigation/NavItemsContext.mjs.map +1 -1
  39. package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
  40. package/dist/components/navigation/shells/TabsMobileShell.mjs.map +1 -1
  41. package/dist/components/navigation/subcomponents/BottomLinks.mjs.map +1 -1
  42. package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
  43. package/dist/components/pages/NotFoundPage.mjs.map +1 -1
  44. package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
  45. package/dist/components/ui/buttons/Button.mjs.map +1 -1
  46. package/dist/components/ui/buttons/CancelButton.mjs.map +1 -1
  47. package/dist/components/ui/buttons/CopyButton.mjs.map +1 -1
  48. package/dist/components/ui/data-display/Accordion.mjs.map +1 -1
  49. package/dist/components/ui/data-display/Badge.mjs.map +1 -1
  50. package/dist/components/ui/data-display/Card.mjs.map +1 -1
  51. package/dist/components/ui/data-display/CardBrandIcons.mjs.map +1 -1
  52. package/dist/components/ui/data-display/CardItem.mjs.map +1 -1
  53. package/dist/components/ui/data-display/Pagination.mjs.map +1 -1
  54. package/dist/components/ui/data-display/PaymentInfoCard.mjs.map +1 -1
  55. package/dist/components/ui/data-display/ScrollArea.mjs.map +1 -1
  56. package/dist/components/ui/data-display/Separator.mjs.map +1 -1
  57. package/dist/components/ui/data-display/Table.mjs.map +1 -1
  58. package/dist/components/ui/data-display/Tabs.mjs.map +1 -1
  59. package/dist/components/ui/feedback/CircularProgress.mjs.map +1 -1
  60. package/dist/components/ui/feedback/DefaultCircularProgress.mjs.map +1 -1
  61. package/dist/components/ui/feedback/LoadingOverlay.mjs.map +1 -1
  62. package/dist/components/ui/feedback/Progress.mjs.map +1 -1
  63. package/dist/components/ui/feedback/Skeleton.mjs.map +1 -1
  64. package/dist/components/ui/feedback/Toast.mjs.map +1 -1
  65. package/dist/components/ui/form/Calendar.mjs.map +1 -1
  66. package/dist/components/ui/form/Checkbox.mjs.map +1 -1
  67. package/dist/components/ui/form/ComboboxField.mjs.map +1 -1
  68. package/dist/components/ui/form/DatePicker.mjs +2 -2
  69. package/dist/components/ui/form/DatePicker.mjs.map +1 -1
  70. package/dist/components/ui/form/DateRangePicker.mjs.map +1 -1
  71. package/dist/components/ui/form/FormField.mjs.map +1 -1
  72. package/dist/components/ui/form/Input.mjs.map +1 -1
  73. package/dist/components/ui/form/InputOtp.mjs.map +1 -1
  74. package/dist/components/ui/form/PhoneInput.mjs.map +1 -1
  75. package/dist/components/ui/form/RadioGroup.mjs.map +1 -1
  76. package/dist/components/ui/form/Select.mjs +1 -1
  77. package/dist/components/ui/form/Select.mjs.map +1 -1
  78. package/dist/components/ui/form/Switch.mjs.map +1 -1
  79. package/dist/components/ui/form/Textarea.mjs.map +1 -1
  80. package/dist/components/ui/overlay/Command.mjs.map +1 -1
  81. package/dist/components/ui/overlay/Dialog.mjs.map +1 -1
  82. package/dist/components/ui/overlay/Popover.mjs.map +1 -1
  83. package/dist/components/ui/overlay/Sheet.mjs.map +1 -1
  84. package/dist/components/ui/overlay/Tooltip.mjs.map +1 -1
  85. package/dist/components/widgets/ImageUpload/ImageCropModal.mjs.map +1 -1
  86. package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs.map +1 -1
  87. package/dist/components/widgets/ImageUpload/ImageUpload.mjs.map +1 -1
  88. package/dist/components/widgets/ImageUpload/index.mjs.map +1 -1
  89. package/dist/components/widgets/notifications/NotificationCard.mjs.map +1 -1
  90. package/dist/hooks/copy-to-clipboard.hook.mjs.map +1 -1
  91. package/dist/hooks/useAuthQueryKey.mjs.map +1 -1
  92. package/dist/index.mjs +2 -0
  93. package/dist/index.mjs.map +1 -1
  94. package/dist/infra/utils/array.mjs.map +1 -1
  95. package/dist/infra/utils/date.mjs.map +1 -1
  96. package/dist/middleware.mjs.map +1 -1
  97. package/dist/modules/accounts/actions/account-management.action.mjs.map +1 -1
  98. package/dist/modules/accounts/actions/find-current-account.action.mjs.map +1 -1
  99. package/dist/modules/accounts/actions/get-account-token.action.mjs.map +1 -1
  100. package/dist/modules/accounts/actions/list-currencies.action.mjs.map +1 -1
  101. package/dist/modules/accounts/actions/list-timezones.action.mjs.map +1 -1
  102. package/dist/modules/accounts/hooks/current-account.hook.mjs.map +1 -1
  103. package/dist/modules/accounts/hooks/use-account-token.hook.mjs.map +1 -1
  104. package/dist/modules/accounts/hooks/useAccountManagement.mjs.map +1 -1
  105. package/dist/modules/accounts/hooks/useCurrencies.mjs.map +1 -1
  106. package/dist/modules/accounts/hooks/useTimezones.mjs.map +1 -1
  107. package/dist/modules/accounts/hooks/useViaCep.mjs.map +1 -1
  108. package/dist/modules/accounts/services/account-token.service.mjs.map +1 -1
  109. package/dist/modules/accounts/services/account.service.mjs.map +1 -1
  110. package/dist/modules/auth/actions/validate-session.action.mjs.map +1 -1
  111. package/dist/modules/auth/hooks/login.hook.mjs.map +1 -1
  112. package/dist/modules/auth/hooks/logout.hook.mjs.map +1 -1
  113. package/dist/modules/auth/hooks/register.hook.mjs.map +1 -1
  114. package/dist/modules/auth/hooks/useManagementPermissions.mjs.map +1 -1
  115. package/dist/modules/auth/hooks/useUserQuery.mjs.map +1 -1
  116. package/dist/modules/auth/utils/assert-management-permission.mjs.map +1 -1
  117. package/dist/modules/auth/utils/assert-management-subscription.mjs.map +1 -1
  118. package/dist/modules/auth/utils/assert-paid-subscription.mjs.map +1 -1
  119. package/dist/modules/auth/utils/assert-subscription-addon.mjs.map +1 -1
  120. package/dist/modules/auth/utils/build-wl-override.mjs.map +1 -1
  121. package/dist/modules/cards/actions/create-card.action.mjs.map +1 -1
  122. package/dist/modules/cards/actions/delete-card.action.mjs.map +1 -1
  123. package/dist/modules/cards/actions/find-card-by-id.action.mjs.map +1 -1
  124. package/dist/modules/cards/actions/list-cards.action.mjs.map +1 -1
  125. package/dist/modules/cards/actions/set-default-card.action.mjs.map +1 -1
  126. package/dist/modules/cards/hooks/card-by-id.hook.mjs.map +1 -1
  127. package/dist/modules/cards/hooks/cards.hook.mjs.map +1 -1
  128. package/dist/modules/cards/hooks/create-card.hook.mjs.map +1 -1
  129. package/dist/modules/cards/hooks/delete-card.hook.mjs.map +1 -1
  130. package/dist/modules/cards/hooks/set-default-card.hook.mjs.map +1 -1
  131. package/dist/modules/cards/services/cards.service.mjs.map +1 -1
  132. package/dist/modules/cards/types.mjs.map +1 -1
  133. package/dist/modules/ia-credits/actions/list-ia-credits.action.mjs.map +1 -1
  134. package/dist/modules/ia-credits/hooks/ia-credits.hook.mjs.map +1 -1
  135. package/dist/modules/images/actions/process-image.action.mjs.map +1 -1
  136. package/dist/modules/images/constants/image.constants.mjs.map +1 -1
  137. package/dist/modules/images/hooks/use-image-upload.hook.mjs.map +1 -1
  138. package/dist/modules/images/services/image-processing.service.mjs.map +1 -1
  139. package/dist/modules/images/utils/base64.mjs.map +1 -1
  140. package/dist/modules/images/utils/compress-image.mjs.map +1 -1
  141. package/dist/modules/images/utils/crop-image.mjs.map +1 -1
  142. package/dist/modules/images/utils/validate-image.mjs.map +1 -1
  143. package/dist/modules/plans/actions/find-plan-by-id.action.mjs.map +1 -1
  144. package/dist/modules/plans/actions/list-plans.action.mjs.map +1 -1
  145. package/dist/modules/plans/hooks/list-plans.hook.mjs.map +1 -1
  146. package/dist/modules/plans/hooks/use-has-plan-addon.hook.mjs.map +1 -1
  147. package/dist/modules/plans/hooks/use-plan-by-id.hook.mjs.map +1 -1
  148. package/dist/modules/plans/services/plans.service.mjs.map +1 -1
  149. package/dist/modules/plans/types/plan.type.mjs.map +1 -1
  150. package/dist/modules/plans/utils/map-api-plan-to-ui.mjs.map +1 -1
  151. package/dist/modules/projects/actions/add-project-user.action.mjs.map +1 -1
  152. package/dist/modules/projects/actions/create-project.action.mjs.map +1 -1
  153. package/dist/modules/projects/actions/delete-project.action.mjs.map +1 -1
  154. package/dist/modules/projects/actions/find-project.action.mjs.map +1 -1
  155. package/dist/modules/projects/actions/list-all-account-users.action.mjs.map +1 -1
  156. package/dist/modules/projects/actions/list-available-users.action.mjs.map +1 -1
  157. package/dist/modules/projects/actions/list-project-users.action.mjs.map +1 -1
  158. package/dist/modules/projects/actions/list-projects.action.mjs.map +1 -1
  159. package/dist/modules/projects/actions/remove-project-user.action.mjs.map +1 -1
  160. package/dist/modules/projects/actions/update-project.action.mjs.map +1 -1
  161. package/dist/modules/projects/hooks/add-project-user.hook.mjs.map +1 -1
  162. package/dist/modules/projects/hooks/create-project.hook.mjs.map +1 -1
  163. package/dist/modules/projects/hooks/delete-project.hook.mjs.map +1 -1
  164. package/dist/modules/projects/hooks/find-project.hook.mjs.map +1 -1
  165. package/dist/modules/projects/hooks/list-all-account-users.hook.mjs.map +1 -1
  166. package/dist/modules/projects/hooks/list-available-users.hook.mjs.map +1 -1
  167. package/dist/modules/projects/hooks/list-infinite-projects.hook.mjs.map +1 -1
  168. package/dist/modules/projects/hooks/list-project-users.hook.mjs.map +1 -1
  169. package/dist/modules/projects/hooks/list-projects.hook.mjs.map +1 -1
  170. package/dist/modules/projects/hooks/remove-project-user.hook.mjs.map +1 -1
  171. package/dist/modules/projects/hooks/update-project.hook.mjs.map +1 -1
  172. package/dist/modules/projects/services/projects.service.mjs.map +1 -1
  173. package/dist/modules/subscriptions/actions/calculate-subscription.action.mjs.map +1 -1
  174. package/dist/modules/subscriptions/actions/list-subscriptions.action.mjs.map +1 -1
  175. package/dist/modules/subscriptions/actions/update-subscription-plan.action.mjs.map +1 -1
  176. package/dist/modules/subscriptions/constants/query-keys.constants.mjs.map +1 -1
  177. package/dist/modules/subscriptions/hooks/calculate-subscription.hook.mjs.map +1 -1
  178. package/dist/modules/subscriptions/hooks/find-active-subscription.hook.mjs.map +1 -1
  179. package/dist/modules/subscriptions/hooks/list-subscriptions.hook.mjs.map +1 -1
  180. package/dist/modules/subscriptions/hooks/update-subscription-plan.hook.mjs.map +1 -1
  181. package/dist/modules/subscriptions/hooks/use-cancelled-subscription-guard.mjs.map +1 -1
  182. package/dist/modules/subscriptions/types/calculate-subscription.type.mjs.map +1 -1
  183. package/dist/modules/subscriptions/utils/build-plan-extras.mjs.map +1 -1
  184. package/dist/modules/subscriptions/utils/has-subscription-expired.mjs.map +1 -1
  185. package/dist/modules/subscriptions/utils/periodicity.mjs.map +1 -1
  186. package/dist/modules/subscriptions/utils/resolve-plan-extras-prices.mjs.map +1 -1
  187. package/dist/modules/users/action/find-user-by-id.action.mjs.map +1 -1
  188. package/dist/modules/users/action/list-messages.action.mjs.map +1 -1
  189. package/dist/modules/users/action/mark-all-messages-as-read.action.mjs.map +1 -1
  190. package/dist/modules/users/action/mark-message-as-read.action.mjs.map +1 -1
  191. package/dist/modules/users/hooks/messages.hook.mjs.map +1 -1
  192. package/dist/modules/users/services/messages.service.mjs.map +1 -1
  193. package/dist/modules/whitelabel/actions/find-whitelabel.action.mjs.map +1 -1
  194. package/dist/modules/whitelabel/actions/revalidate-whitelabel.action.mjs.map +1 -1
  195. package/dist/modules/whitelabel/utils/normalize-hostname.mjs.map +1 -1
  196. package/dist/providers/auth.provider.mjs.map +1 -1
  197. package/dist/providers/whitelabel.provider.mjs.map +1 -1
  198. package/dist/store/useBuyCreditsModal.mjs.map +1 -1
  199. package/dist/store/useDesktopSidebarStore.mjs.map +1 -1
  200. package/dist/store/useMdSidebarStore.mjs.map +1 -1
  201. package/dist/store/usePaidPlanRequiredModal.mjs.map +1 -1
  202. package/dist/utils/constants/br-states.mjs.map +1 -1
  203. package/dist/utils/countries.mjs.map +1 -1
  204. package/dist/utils/format/currency.mjs.map +1 -1
  205. package/dist/utils/safeServerAction.mjs.map +1 -1
  206. package/dist/utils/withAction.mjs.map +1 -1
  207. package/package.json +92 -92
  208. package/src/components/account/ConfigurationsMyAccountModal.tsx +161 -161
  209. package/src/components/account/ConfirmDeleteAccountModal.tsx +55 -55
  210. package/src/components/account/ConfirmGlobalPreferencesModal.tsx +66 -66
  211. package/src/components/account/DeleteAccountModal.tsx +130 -130
  212. package/src/components/account/DisableTwoFactorAuthModal.tsx +86 -86
  213. package/src/components/account/IsntPossibleDeleteAccountModal.tsx +49 -49
  214. package/src/components/account/TwoFactorAuthModal.tsx +215 -215
  215. package/src/components/account/hooks/useChangePhoneForm.tsx +107 -107
  216. package/src/components/account/hooks/useTwoFactorAuthForm.tsx +101 -101
  217. package/src/components/account/sections/ChangeEmailModal.tsx +227 -227
  218. package/src/components/account/sections/ChangePasswordSection.tsx +64 -64
  219. package/src/components/account/sections/ChangePhoneModal.tsx +247 -247
  220. package/src/components/account/sections/MyProfileSection.tsx +328 -328
  221. package/src/components/account/sections/PreferencesSection.tsx +248 -248
  222. package/src/components/account/sections/SecuritySection.tsx +46 -46
  223. package/src/components/account/sections/TokenSection.tsx +64 -64
  224. package/src/components/embeds/ClarityEmbed.tsx +70 -0
  225. package/src/components/embeds/CrispEmbed.tsx +156 -156
  226. package/src/components/embeds/EmbedWidgets.tsx +52 -50
  227. package/src/components/embeds/FrillEmbed.tsx +129 -129
  228. package/src/components/layouts/AppMobileNavBar.tsx +80 -80
  229. package/src/components/layouts/AppNavBar.tsx +40 -40
  230. package/src/components/layouts/MdSideBarNavigation.tsx +56 -56
  231. package/src/components/layouts/NavBar.tsx +175 -175
  232. package/src/components/layouts/NotificationsPopover.tsx +118 -118
  233. package/src/components/layouts/ProfilePopover.tsx +176 -176
  234. package/src/components/layouts/SideBarNavigation.tsx +65 -65
  235. package/src/components/layouts/UsersSelectorPopover.tsx +234 -234
  236. package/src/components/layouts/WhitelabelCodes.tsx +59 -59
  237. package/src/components/modals/BuyCreditsModal.tsx +354 -354
  238. package/src/components/modals/PaidPlanRequiredModal.tsx +57 -57
  239. package/src/components/modals/cards/AddCardModal.tsx +265 -265
  240. package/src/components/modals/cards/CardFormFields.tsx +348 -348
  241. package/src/components/navigation/CancelledSubscriptionBanner.tsx +64 -64
  242. package/src/components/navigation/NavItemsContext.ts +20 -20
  243. package/src/components/navigation/ProjectSelectorPopover.tsx +178 -178
  244. package/src/components/navigation/shells/TabsMobileShell.tsx +74 -74
  245. package/src/components/navigation/subcomponents/BottomLinks.tsx +37 -37
  246. package/src/components/navigation/subcomponents/ProjectSelector.tsx +182 -182
  247. package/src/components/pages/NotFoundPage.tsx +67 -67
  248. package/src/components/pages/notifications/Notifications.tsx +187 -187
  249. package/src/components/ui/buttons/Button.tsx +62 -62
  250. package/src/components/ui/buttons/CancelButton.tsx +14 -14
  251. package/src/components/ui/buttons/CopyButton.tsx +54 -54
  252. package/src/components/ui/data-display/Accordion.tsx +81 -81
  253. package/src/components/ui/data-display/Badge.tsx +47 -47
  254. package/src/components/ui/data-display/Card.tsx +93 -93
  255. package/src/components/ui/data-display/CardBrandIcons.tsx +336 -336
  256. package/src/components/ui/data-display/CardItem.tsx +75 -75
  257. package/src/components/ui/data-display/Pagination.tsx +126 -126
  258. package/src/components/ui/data-display/PaymentInfoCard.tsx +192 -192
  259. package/src/components/ui/data-display/ScrollArea.tsx +59 -59
  260. package/src/components/ui/data-display/Separator.tsx +29 -29
  261. package/src/components/ui/data-display/Table.tsx +117 -117
  262. package/src/components/ui/data-display/Tabs.tsx +67 -67
  263. package/src/components/ui/feedback/CircularProgress.tsx +75 -75
  264. package/src/components/ui/feedback/DefaultCircularProgress.tsx +65 -65
  265. package/src/components/ui/feedback/LoadingOverlay.tsx +31 -31
  266. package/src/components/ui/feedback/Progress.tsx +40 -40
  267. package/src/components/ui/feedback/Skeleton.tsx +5 -5
  268. package/src/components/ui/feedback/Toast.tsx +104 -104
  269. package/src/components/ui/form/Calendar.tsx +228 -228
  270. package/src/components/ui/form/Checkbox.tsx +31 -31
  271. package/src/components/ui/form/ComboboxField.tsx +154 -154
  272. package/src/components/ui/form/DatePicker.tsx +97 -98
  273. package/src/components/ui/form/DateRangePicker.tsx +108 -108
  274. package/src/components/ui/form/FormField.tsx +133 -133
  275. package/src/components/ui/form/Input.tsx +20 -20
  276. package/src/components/ui/form/InputOtp.tsx +80 -80
  277. package/src/components/ui/form/PhoneInput.tsx +208 -208
  278. package/src/components/ui/form/RadioGroup.tsx +45 -45
  279. package/src/components/ui/form/Select.tsx +200 -200
  280. package/src/components/ui/form/Switch.tsx +32 -32
  281. package/src/components/ui/form/Textarea.tsx +19 -19
  282. package/src/components/ui/overlay/Command.tsx +185 -185
  283. package/src/components/ui/overlay/Dialog.tsx +153 -153
  284. package/src/components/ui/overlay/Popover.tsx +49 -49
  285. package/src/components/ui/overlay/Sheet.tsx +170 -170
  286. package/src/components/ui/overlay/Tooltip.tsx +62 -62
  287. package/src/components/widgets/ImageUpload/ImageCropModal.tsx +254 -254
  288. package/src/components/widgets/ImageUpload/ImageTooSmallModal.tsx +61 -61
  289. package/src/components/widgets/ImageUpload/ImageUpload.tsx +126 -126
  290. package/src/components/widgets/ImageUpload/index.ts +3 -3
  291. package/src/components/widgets/notifications/NotificationCard.tsx +73 -73
  292. package/src/hooks/copy-to-clipboard.hook.tsx +67 -67
  293. package/src/hooks/useAuthQueryKey.ts +32 -32
  294. package/src/index.ts +507 -506
  295. package/src/infra/utils/array.ts +54 -54
  296. package/src/infra/utils/date.ts +18 -18
  297. package/src/middleware.ts +4 -4
  298. package/src/modules/accounts/actions/account-management.action.ts +107 -107
  299. package/src/modules/accounts/actions/find-current-account.action.ts +9 -9
  300. package/src/modules/accounts/actions/get-account-token.action.ts +8 -8
  301. package/src/modules/accounts/actions/list-currencies.action.ts +8 -8
  302. package/src/modules/accounts/actions/list-timezones.action.ts +8 -8
  303. package/src/modules/accounts/hooks/current-account.hook.tsx +26 -26
  304. package/src/modules/accounts/hooks/use-account-token.hook.tsx +14 -14
  305. package/src/modules/accounts/hooks/useAccountManagement.ts +94 -94
  306. package/src/modules/accounts/hooks/useCurrencies.ts +18 -18
  307. package/src/modules/accounts/hooks/useTimezones.ts +18 -18
  308. package/src/modules/accounts/hooks/useViaCep.ts +25 -25
  309. package/src/modules/accounts/services/account-token.service.ts +52 -52
  310. package/src/modules/accounts/services/account.service.ts +239 -239
  311. package/src/modules/accounts/types.ts +225 -225
  312. package/src/modules/auth/actions/validate-session.action.ts +56 -56
  313. package/src/modules/auth/hooks/login.hook.tsx +13 -13
  314. package/src/modules/auth/hooks/logout.hook.tsx +11 -11
  315. package/src/modules/auth/hooks/register.hook.tsx +11 -11
  316. package/src/modules/auth/hooks/useManagementPermissions.ts +45 -45
  317. package/src/modules/auth/hooks/useUserQuery.ts +75 -75
  318. package/src/modules/auth/types/management-permission.type.ts +7 -7
  319. package/src/modules/auth/utils/assert-management-permission.ts +46 -46
  320. package/src/modules/auth/utils/assert-management-subscription.ts +35 -35
  321. package/src/modules/auth/utils/assert-paid-subscription.ts +43 -43
  322. package/src/modules/auth/utils/assert-subscription-addon.ts +42 -42
  323. package/src/modules/auth/utils/build-wl-override.ts +43 -43
  324. package/src/modules/cards/actions/create-card.action.ts +9 -9
  325. package/src/modules/cards/actions/delete-card.action.ts +8 -8
  326. package/src/modules/cards/actions/find-card-by-id.action.ts +8 -8
  327. package/src/modules/cards/actions/list-cards.action.ts +8 -8
  328. package/src/modules/cards/actions/set-default-card.action.ts +8 -8
  329. package/src/modules/cards/hooks/card-by-id.hook.ts +21 -21
  330. package/src/modules/cards/hooks/cards.hook.ts +23 -23
  331. package/src/modules/cards/hooks/create-card.hook.ts +30 -30
  332. package/src/modules/cards/hooks/delete-card.hook.ts +54 -54
  333. package/src/modules/cards/hooks/set-default-card.hook.ts +55 -55
  334. package/src/modules/cards/services/cards.service.ts +108 -108
  335. package/src/modules/cards/types.ts +42 -42
  336. package/src/modules/ia-credits/actions/list-ia-credits.action.ts +8 -8
  337. package/src/modules/ia-credits/hooks/ia-credits.hook.ts +99 -99
  338. package/src/modules/images/actions/process-image.action.ts +40 -40
  339. package/src/modules/images/constants/image.constants.ts +11 -11
  340. package/src/modules/images/hooks/use-image-upload.hook.ts +172 -172
  341. package/src/modules/images/services/image-processing.service.ts +75 -75
  342. package/src/modules/images/types/image.type.ts +54 -54
  343. package/src/modules/images/utils/base64.ts +26 -26
  344. package/src/modules/images/utils/compress-image.ts +20 -20
  345. package/src/modules/images/utils/crop-image.ts +51 -51
  346. package/src/modules/images/utils/validate-image.ts +71 -71
  347. package/src/modules/plans/actions/find-plan-by-id.action.ts +8 -8
  348. package/src/modules/plans/actions/list-plans.action.ts +17 -17
  349. package/src/modules/plans/hooks/list-plans.hook.ts +24 -24
  350. package/src/modules/plans/hooks/use-has-plan-addon.hook.ts +14 -14
  351. package/src/modules/plans/hooks/use-plan-by-id.hook.ts +38 -38
  352. package/src/modules/plans/services/plans.service.ts +133 -133
  353. package/src/modules/plans/types/plan.type.ts +67 -67
  354. package/src/modules/plans/utils/map-api-plan-to-ui.ts +98 -98
  355. package/src/modules/projects/actions/add-project-user.action.ts +9 -9
  356. package/src/modules/projects/actions/create-project.action.ts +9 -9
  357. package/src/modules/projects/actions/delete-project.action.ts +8 -8
  358. package/src/modules/projects/actions/find-project.action.ts +8 -8
  359. package/src/modules/projects/actions/list-all-account-users.action.ts +9 -9
  360. package/src/modules/projects/actions/list-available-users.action.ts +9 -9
  361. package/src/modules/projects/actions/list-project-users.action.ts +9 -9
  362. package/src/modules/projects/actions/list-projects.action.ts +16 -16
  363. package/src/modules/projects/actions/remove-project-user.action.ts +9 -9
  364. package/src/modules/projects/actions/update-project.action.ts +9 -9
  365. package/src/modules/projects/hooks/add-project-user.hook.ts +72 -72
  366. package/src/modules/projects/hooks/create-project.hook.ts +88 -88
  367. package/src/modules/projects/hooks/delete-project.hook.ts +58 -58
  368. package/src/modules/projects/hooks/find-project.hook.ts +18 -18
  369. package/src/modules/projects/hooks/list-all-account-users.hook.ts +39 -39
  370. package/src/modules/projects/hooks/list-available-users.hook.ts +38 -38
  371. package/src/modules/projects/hooks/list-infinite-projects.hook.ts +43 -43
  372. package/src/modules/projects/hooks/list-project-users.hook.ts +38 -38
  373. package/src/modules/projects/hooks/list-projects.hook.ts +23 -23
  374. package/src/modules/projects/hooks/remove-project-user.hook.ts +72 -72
  375. package/src/modules/projects/hooks/update-project.hook.ts +86 -86
  376. package/src/modules/projects/services/projects.service.ts +144 -144
  377. package/src/modules/subscriptions/actions/calculate-subscription.action.ts +9 -9
  378. package/src/modules/subscriptions/actions/list-subscriptions.action.ts +9 -9
  379. package/src/modules/subscriptions/actions/update-subscription-plan.action.ts +14 -14
  380. package/src/modules/subscriptions/constants/query-keys.constants.ts +3 -3
  381. package/src/modules/subscriptions/hooks/calculate-subscription.hook.ts +13 -13
  382. package/src/modules/subscriptions/hooks/find-active-subscription.hook.ts +18 -18
  383. package/src/modules/subscriptions/hooks/list-subscriptions.hook.ts +19 -19
  384. package/src/modules/subscriptions/hooks/update-subscription-plan.hook.ts +28 -28
  385. package/src/modules/subscriptions/hooks/use-cancelled-subscription-guard.ts +39 -39
  386. package/src/modules/subscriptions/types/billing-period.type.ts +1 -1
  387. package/src/modules/subscriptions/types/calculate-subscription.type.ts +113 -113
  388. package/src/modules/subscriptions/utils/build-plan-extras.ts +56 -56
  389. package/src/modules/subscriptions/utils/has-subscription-expired.ts +8 -8
  390. package/src/modules/subscriptions/utils/periodicity.ts +62 -62
  391. package/src/modules/subscriptions/utils/resolve-plan-extras-prices.ts +23 -23
  392. package/src/modules/users/action/find-user-by-id.action.ts +8 -8
  393. package/src/modules/users/action/list-messages.action.ts +26 -26
  394. package/src/modules/users/action/mark-all-messages-as-read.action.ts +8 -8
  395. package/src/modules/users/action/mark-message-as-read.action.ts +8 -8
  396. package/src/modules/users/hooks/messages.hook.ts +67 -67
  397. package/src/modules/users/services/messages.service.ts +49 -49
  398. package/src/modules/whitelabel/actions/find-whitelabel.action.ts +23 -23
  399. package/src/modules/whitelabel/actions/revalidate-whitelabel.action.ts +19 -19
  400. package/src/modules/whitelabel/schema.ts +84 -84
  401. package/src/modules/whitelabel/utils/normalize-hostname.ts +26 -26
  402. package/src/providers/auth.provider.tsx +162 -162
  403. package/src/providers/whitelabel.provider.tsx +59 -59
  404. package/src/store/useBuyCreditsModal.ts +21 -21
  405. package/src/store/useDesktopSidebarStore.ts +47 -47
  406. package/src/store/useMdSidebarStore.ts +34 -34
  407. package/src/store/usePaidPlanRequiredModal.ts +19 -19
  408. package/src/utils/constants/br-states.ts +29 -29
  409. package/src/utils/countries.ts +224 -224
  410. package/src/utils/format/currency.ts +15 -15
  411. package/src/utils/safeServerAction.ts +21 -21
  412. package/src/utils/withAction.ts +13 -13
@@ -1,74 +1,74 @@
1
- 'use client';
2
-
3
- import { ReactNode, useRef, useEffect } from 'react';
4
- import Link from 'next/link';
5
- import { AppNavigationContext } from '../AppNavigationContext';
6
- import { useNavItemsContext } from '../NavItemsContext';
7
-
8
- function InternalTabsBar({ topOffset = '72px' }: { topOffset?: string }) {
9
- const { navItems } = useNavItemsContext();
10
- const tabsListRef = useRef<HTMLDivElement>(null);
11
- const activeTabRef = useRef<HTMLAnchorElement>(null);
12
-
13
- const activeLabel = navItems.find((i) => i.isActive)?.label;
14
-
15
- // Scroll active tab into center when active item changes
16
- useEffect(() => {
17
- if (activeTabRef.current && tabsListRef.current) {
18
- const tabsList = tabsListRef.current;
19
- const activeTabElement = activeTabRef.current;
20
- const tabsListRect = tabsList.getBoundingClientRect();
21
- const activeTabRect = activeTabElement.getBoundingClientRect();
22
- const scrollLeft =
23
- activeTabElement.offsetLeft - tabsListRect.width / 2 + activeTabRect.width / 2;
24
- tabsList.scrollTo({ left: Math.max(0, scrollLeft), behavior: 'smooth' });
25
- }
26
- }, [activeLabel]);
27
-
28
- if (!navItems.length) return null;
29
-
30
- return (
31
- <div
32
- ref={tabsListRef}
33
- className="md:hidden fixed left-0 right-0 z-40 bg-white border-b border-gray-200 flex overflow-x-auto scrollbar-hide"
34
- style={{ top: topOffset }}
35
- >
36
- {navItems.map((item) => (
37
- <Link
38
- key={item.label}
39
- ref={item.isActive ? activeTabRef : undefined}
40
- href={item.href}
41
- prefetch
42
- className={`flex items-center gap-2 px-4 py-3 shrink-0 border-b-2 transition-colors ${
43
- item.isActive
44
- ? 'border-gray-950 text-gray-950'
45
- : 'border-transparent text-gray-500 hover:text-gray-900'
46
- }`}
47
- >
48
- {item.icon && <item.icon size={16} className="shrink-0" />}
49
- <span
50
- className={
51
- item.isActive ? 'paragraph-small-semibold' : 'paragraph-small-medium'
52
- }
53
- >
54
- {item.label}
55
- </span>
56
- </Link>
57
- ))}
58
- </div>
59
- );
60
- }
61
-
62
- export function TabsMobileShell({ children, topOffset }: { children: ReactNode; topOffset?: string }) {
63
- return (
64
- <AppNavigationContext.Provider value={{ breakpoint: 'mobile' }}>
65
- {/*
66
- Children are hidden visually, but NavItems' useEffect still fires inside
67
- display:none — React effects are tied to commit phase, not layout visibility.
68
- This registers navItems in NavItemsContext so InternalTabsBar can read them.
69
- */}
70
- <div className="hidden">{children}</div>
71
- <InternalTabsBar topOffset={topOffset} />
72
- </AppNavigationContext.Provider>
73
- );
74
- }
1
+ 'use client';
2
+
3
+ import { ReactNode, useRef, useEffect } from 'react';
4
+ import Link from 'next/link';
5
+ import { AppNavigationContext } from '../AppNavigationContext';
6
+ import { useNavItemsContext } from '../NavItemsContext';
7
+
8
+ function InternalTabsBar({ topOffset = '72px' }: { topOffset?: string }) {
9
+ const { navItems } = useNavItemsContext();
10
+ const tabsListRef = useRef<HTMLDivElement>(null);
11
+ const activeTabRef = useRef<HTMLAnchorElement>(null);
12
+
13
+ const activeLabel = navItems.find((i) => i.isActive)?.label;
14
+
15
+ // Scroll active tab into center when active item changes
16
+ useEffect(() => {
17
+ if (activeTabRef.current && tabsListRef.current) {
18
+ const tabsList = tabsListRef.current;
19
+ const activeTabElement = activeTabRef.current;
20
+ const tabsListRect = tabsList.getBoundingClientRect();
21
+ const activeTabRect = activeTabElement.getBoundingClientRect();
22
+ const scrollLeft =
23
+ activeTabElement.offsetLeft - tabsListRect.width / 2 + activeTabRect.width / 2;
24
+ tabsList.scrollTo({ left: Math.max(0, scrollLeft), behavior: 'smooth' });
25
+ }
26
+ }, [activeLabel]);
27
+
28
+ if (!navItems.length) return null;
29
+
30
+ return (
31
+ <div
32
+ ref={tabsListRef}
33
+ className="md:hidden fixed left-0 right-0 z-40 bg-white border-b border-gray-200 flex overflow-x-auto scrollbar-hide"
34
+ style={{ top: topOffset }}
35
+ >
36
+ {navItems.map((item) => (
37
+ <Link
38
+ key={item.label}
39
+ ref={item.isActive ? activeTabRef : undefined}
40
+ href={item.href}
41
+ prefetch
42
+ className={`flex items-center gap-2 px-4 py-3 shrink-0 border-b-2 transition-colors ${
43
+ item.isActive
44
+ ? 'border-gray-950 text-gray-950'
45
+ : 'border-transparent text-gray-500 hover:text-gray-900'
46
+ }`}
47
+ >
48
+ {item.icon && <item.icon size={16} className="shrink-0" />}
49
+ <span
50
+ className={
51
+ item.isActive ? 'paragraph-small-semibold' : 'paragraph-small-medium'
52
+ }
53
+ >
54
+ {item.label}
55
+ </span>
56
+ </Link>
57
+ ))}
58
+ </div>
59
+ );
60
+ }
61
+
62
+ export function TabsMobileShell({ children, topOffset }: { children: ReactNode; topOffset?: string }) {
63
+ return (
64
+ <AppNavigationContext.Provider value={{ breakpoint: 'mobile' }}>
65
+ {/*
66
+ Children are hidden visually, but NavItems' useEffect still fires inside
67
+ display:none — React effects are tied to commit phase, not layout visibility.
68
+ This registers navItems in NavItemsContext so InternalTabsBar can read them.
69
+ */}
70
+ <div className="hidden">{children}</div>
71
+ <InternalTabsBar topOffset={topOffset} />
72
+ </AppNavigationContext.Provider>
73
+ );
74
+ }
@@ -1,37 +1,37 @@
1
- 'use client';
2
-
3
- import { IconHelp, IconBulb } from '@tabler/icons-react';
4
-
5
- const LINKS = [
6
- {
7
- label: 'Central de ajuda',
8
- icon: IconHelp,
9
- href: 'https://ajuda.greatsoftwares.com.br/pt-br/',
10
- },
11
- {
12
- label: 'Enviar sugestões',
13
- icon: IconBulb,
14
- href: 'https://ideias.greatpages.com.br/b/y0geg1ve/feature-ideas',
15
- },
16
- ] as const;
17
-
18
- export function BottomLinks() {
19
- return (
20
- <div className="flex flex-col">
21
- {LINKS.map((link) => (
22
- <a
23
- key={link.label}
24
- href={link.href}
25
- target="_blank"
26
- rel="noopener noreferrer"
27
- className="rounded-md flex items-center gap-2 p-3 cursor-pointer transition-colors no-underline bg-white hover:bg-gray-100 active:bg-gray-50"
28
- >
29
- <link.icon size={20} className="text-gray-400" />
30
- <span className="paragraph-small-medium text-gray-500">
31
- {link.label}
32
- </span>
33
- </a>
34
- ))}
35
- </div>
36
- );
37
- }
1
+ 'use client';
2
+
3
+ import { IconHelp, IconBulb } from '@tabler/icons-react';
4
+
5
+ const LINKS = [
6
+ {
7
+ label: 'Central de ajuda',
8
+ icon: IconHelp,
9
+ href: 'https://ajuda.greatsoftwares.com.br/pt-br/',
10
+ },
11
+ {
12
+ label: 'Enviar sugestões',
13
+ icon: IconBulb,
14
+ href: 'https://ideias.greatpages.com.br/b/y0geg1ve/feature-ideas',
15
+ },
16
+ ] as const;
17
+
18
+ export function BottomLinks() {
19
+ return (
20
+ <div className="flex flex-col">
21
+ {LINKS.map((link) => (
22
+ <a
23
+ key={link.label}
24
+ href={link.href}
25
+ target="_blank"
26
+ rel="noopener noreferrer"
27
+ className="rounded-md flex items-center gap-2 p-3 cursor-pointer transition-colors no-underline bg-white hover:bg-gray-100 active:bg-gray-50"
28
+ >
29
+ <link.icon size={20} className="text-gray-400" />
30
+ <span className="paragraph-small-medium text-gray-500">
31
+ {link.label}
32
+ </span>
33
+ </a>
34
+ ))}
35
+ </div>
36
+ );
37
+ }
@@ -1,182 +1,182 @@
1
- 'use client';
2
-
3
- import { useState, useRef, useEffect, useMemo, RefObject } from 'react';
4
- import { useMobileNavbarSheet } from '../../../store/useMobileNavbarSheet';
5
- import { useAppNavigationContext } from '../AppNavigationContext';
6
- import { ProjectSelectorPopover } from '../ProjectSelectorPopover';
7
- import { cn, Command, CommandEmpty, CommandInput, CommandItem, CommandList, UserAvatar, useWhitelabel, useDebounce } from '../../../index';
8
- import { useInfiniteProjects } from '../../../modules/projects/hooks/list-infinite-projects.hook';
9
- import { IconChevronDown } from '@tabler/icons-react';
10
- import type { Project } from '../../../modules/projects/types';
11
-
12
- export interface ProjectSelectorProps {
13
- selectedProject: Project | null;
14
- onSelectProject: (project: Project) => void;
15
- onAddProject?: () => void;
16
- onManageProjects?: () => void;
17
- }
18
-
19
- function ProjectItemSkeleton() {
20
- return (
21
- <div className="flex items-center gap-2 p-[8.8px]">
22
- <div className="skeleton size-9 rounded-lg shrink-0" />
23
- <div className="skeleton h-4 w-36 rounded" />
24
- </div>
25
- );
26
- }
27
-
28
- export function ProjectSelector({
29
- selectedProject,
30
- onSelectProject,
31
- onManageProjects,
32
- }: ProjectSelectorProps) {
33
- const { whitelabel } = useWhitelabel();
34
- const { breakpoint } = useAppNavigationContext();
35
- const [isPopoverOpen, setIsPopoverOpen] = useState(false);
36
- const [activeSection, setActiveSection] = useState<'projects' | null>(null);
37
- const titleRef = useRef<HTMLDivElement>(null);
38
- const { openProjectList, clearProjectList } = useMobileNavbarSheet();
39
-
40
- const [search, setSearch] = useState('');
41
- const debouncedSearch = useDebounce(search, 300);
42
-
43
- const { data, isLoading, isFetching, isFetchingNextPage, hasNextPage, fetchNextPage } = useInfiniteProjects({
44
- sort: 'title',
45
- limit: 20,
46
- ...(debouncedSearch ? { search: debouncedSearch } : {}),
47
- });
48
- const projects = useMemo(() => data?.pages.flatMap((page) => page.data) ?? [], [data]);
49
- const showListSkeleton = isLoading || (isFetching && !isFetchingNextPage && !!debouncedSearch);
50
-
51
- const handlePopoverOpenChange: typeof setIsPopoverOpen = (value) => {
52
- setIsPopoverOpen((prev) => {
53
- const next = typeof value === 'function' ? value(prev) : value;
54
- if (!next) setSearch('');
55
- return next;
56
- });
57
- };
58
-
59
- useEffect(() => {
60
- if (openProjectList && breakpoint === 'mobile') {
61
- setActiveSection('projects');
62
- clearProjectList();
63
- }
64
- }, [openProjectList, breakpoint, clearProjectList]);
65
-
66
- // Desktop and md: title + popover (aligned with NavBar logo + separator)
67
- if (breakpoint === 'desktop' || breakpoint === 'md') {
68
- return (
69
- <div className={cn(
70
- whitelabel?.id != 1 ? "mt-[14.5px.5px] mb-[7px]" : "mt-[6.5px] mb-[3px]"
71
- )}>
72
- <div className="flex items-center h-7">
73
- <ProjectSelectorPopover
74
- open={isPopoverOpen}
75
- setOpen={handlePopoverOpenChange}
76
- titleRef={titleRef as unknown as RefObject<HTMLSpanElement | null>}
77
- projects={projects}
78
- selectedProject={selectedProject}
79
- isLoading={showListSkeleton}
80
- isFetchingNextPage={isFetchingNextPage}
81
- hasNextPage={hasNextPage}
82
- onLoadMore={() => fetchNextPage()}
83
- onSelectProject={onSelectProject}
84
- onManageProjects={onManageProjects}
85
- search={search}
86
- onSearchChange={setSearch}
87
- >
88
- <div className="flex items-center gap-2 truncate select-none cursor-pointer" ref={titleRef}>
89
- {isLoading ? (
90
- <div className="skeleton h-4 w-32 rounded" />
91
- ) : (
92
- <span className="paragraph-medium-semibold text-gray-600 truncate max-w-[120px]">
93
- {selectedProject?.title}
94
- </span>
95
- )}
96
- <IconChevronDown
97
- size={20}
98
- className={`transition-transform duration-200 ${isPopoverOpen ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}
99
- />
100
- </div>
101
- </ProjectSelectorPopover>
102
- </div>
103
- </div>
104
- );
105
- }
106
-
107
- // Mobile: inline collapsible accordion
108
- return (
109
- <div className="flex flex-col gap-2.5">
110
- <div className="flex items-center justify-between">
111
- <div
112
- className="flex items-center gap-1 cursor-pointer"
113
- onClick={() => { const next = activeSection === 'projects' ? null : 'projects'; setActiveSection(next); if (!next) setSearch(''); }}
114
- >
115
- <span className="paragraph-medium-semibold text-gray-600">{selectedProject?.title}</span>
116
- <IconChevronDown
117
- size={20}
118
- className={`transition-transform duration-200 ${
119
- activeSection === 'projects' ? 'rotate-180 text-gray-950' : 'text-gray-400'
120
- }`}
121
- />
122
- </div>
123
- </div>
124
- {activeSection === 'projects' && (
125
- <div className="flex flex-col p-3 gap-2 border border-gray-200 rounded-lg animate-in fade-in duration-400">
126
- <div className="flex items-center justify-between">
127
- <span className="paragraph-small-semibold">Projetos</span>
128
- </div>
129
- <Command className="gap-2" shouldFilter={false}>
130
- <CommandInput placeholder="Busque aqui" value={search} onValueChange={setSearch} />
131
- <CommandList
132
- className="custom-scrollbar paragraph-small-medium text-gray-600 h-[227px]"
133
- onScroll={(event) => {
134
- if (!hasNextPage || isFetchingNextPage || !fetchNextPage) return;
135
-
136
- const target = event.currentTarget;
137
- const distanceToBottom = target.scrollHeight - target.scrollTop - target.clientHeight;
138
-
139
- if (distanceToBottom <= 80) {
140
- fetchNextPage();
141
- }
142
- }}
143
- >
144
- <CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
145
- {showListSkeleton ? (
146
- <>
147
- <ProjectItemSkeleton />
148
- <ProjectItemSkeleton />
149
- <ProjectItemSkeleton />
150
- <ProjectItemSkeleton />
151
- </>
152
- ) : (
153
- projects.map((project) => (
154
- <CommandItem
155
- key={project.id}
156
- value={`${project.title}-${project.id}`}
157
- keywords={[project.title]}
158
- className={selectedProject?.id === project.id ? 'bg-gray-50 min-h-[39px]' : 'min-h-[39px]'}
159
- onSelect={() => { onSelectProject(project); setActiveSection(null); setSearch(''); }}
160
- >
161
- <UserAvatar
162
- photo={project.photo}
163
- name={project.title}
164
- size={36}
165
- />
166
- {project.title}
167
- </CommandItem>
168
- ))
169
- )}
170
- {isFetchingNextPage && (
171
- <>
172
- <ProjectItemSkeleton />
173
- <ProjectItemSkeleton />
174
- </>
175
- )}
176
- </CommandList>
177
- </Command>
178
- </div>
179
- )}
180
- </div>
181
- );
182
- }
1
+ 'use client';
2
+
3
+ import { useState, useRef, useEffect, useMemo, RefObject } from 'react';
4
+ import { useMobileNavbarSheet } from '../../../store/useMobileNavbarSheet';
5
+ import { useAppNavigationContext } from '../AppNavigationContext';
6
+ import { ProjectSelectorPopover } from '../ProjectSelectorPopover';
7
+ import { cn, Command, CommandEmpty, CommandInput, CommandItem, CommandList, UserAvatar, useWhitelabel, useDebounce } from '../../../index';
8
+ import { useInfiniteProjects } from '../../../modules/projects/hooks/list-infinite-projects.hook';
9
+ import { IconChevronDown } from '@tabler/icons-react';
10
+ import type { Project } from '../../../modules/projects/types';
11
+
12
+ export interface ProjectSelectorProps {
13
+ selectedProject: Project | null;
14
+ onSelectProject: (project: Project) => void;
15
+ onAddProject?: () => void;
16
+ onManageProjects?: () => void;
17
+ }
18
+
19
+ function ProjectItemSkeleton() {
20
+ return (
21
+ <div className="flex items-center gap-2 p-[8.8px]">
22
+ <div className="skeleton size-9 rounded-lg shrink-0" />
23
+ <div className="skeleton h-4 w-36 rounded" />
24
+ </div>
25
+ );
26
+ }
27
+
28
+ export function ProjectSelector({
29
+ selectedProject,
30
+ onSelectProject,
31
+ onManageProjects,
32
+ }: ProjectSelectorProps) {
33
+ const { whitelabel } = useWhitelabel();
34
+ const { breakpoint } = useAppNavigationContext();
35
+ const [isPopoverOpen, setIsPopoverOpen] = useState(false);
36
+ const [activeSection, setActiveSection] = useState<'projects' | null>(null);
37
+ const titleRef = useRef<HTMLDivElement>(null);
38
+ const { openProjectList, clearProjectList } = useMobileNavbarSheet();
39
+
40
+ const [search, setSearch] = useState('');
41
+ const debouncedSearch = useDebounce(search, 300);
42
+
43
+ const { data, isLoading, isFetching, isFetchingNextPage, hasNextPage, fetchNextPage } = useInfiniteProjects({
44
+ sort: 'title',
45
+ limit: 20,
46
+ ...(debouncedSearch ? { search: debouncedSearch } : {}),
47
+ });
48
+ const projects = useMemo(() => data?.pages.flatMap((page) => page.data) ?? [], [data]);
49
+ const showListSkeleton = isLoading || (isFetching && !isFetchingNextPage && !!debouncedSearch);
50
+
51
+ const handlePopoverOpenChange: typeof setIsPopoverOpen = (value) => {
52
+ setIsPopoverOpen((prev) => {
53
+ const next = typeof value === 'function' ? value(prev) : value;
54
+ if (!next) setSearch('');
55
+ return next;
56
+ });
57
+ };
58
+
59
+ useEffect(() => {
60
+ if (openProjectList && breakpoint === 'mobile') {
61
+ setActiveSection('projects');
62
+ clearProjectList();
63
+ }
64
+ }, [openProjectList, breakpoint, clearProjectList]);
65
+
66
+ // Desktop and md: title + popover (aligned with NavBar logo + separator)
67
+ if (breakpoint === 'desktop' || breakpoint === 'md') {
68
+ return (
69
+ <div className={cn(
70
+ whitelabel?.id != 1 ? "mt-[14.5px.5px] mb-[7px]" : "mt-[6.5px] mb-[3px]"
71
+ )}>
72
+ <div className="flex items-center h-7">
73
+ <ProjectSelectorPopover
74
+ open={isPopoverOpen}
75
+ setOpen={handlePopoverOpenChange}
76
+ titleRef={titleRef as unknown as RefObject<HTMLSpanElement | null>}
77
+ projects={projects}
78
+ selectedProject={selectedProject}
79
+ isLoading={showListSkeleton}
80
+ isFetchingNextPage={isFetchingNextPage}
81
+ hasNextPage={hasNextPage}
82
+ onLoadMore={() => fetchNextPage()}
83
+ onSelectProject={onSelectProject}
84
+ onManageProjects={onManageProjects}
85
+ search={search}
86
+ onSearchChange={setSearch}
87
+ >
88
+ <div className="flex items-center gap-2 truncate select-none cursor-pointer" ref={titleRef}>
89
+ {isLoading ? (
90
+ <div className="skeleton h-4 w-32 rounded" />
91
+ ) : (
92
+ <span className="paragraph-medium-semibold text-gray-600 truncate max-w-[120px]">
93
+ {selectedProject?.title}
94
+ </span>
95
+ )}
96
+ <IconChevronDown
97
+ size={20}
98
+ className={`transition-transform duration-200 ${isPopoverOpen ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}
99
+ />
100
+ </div>
101
+ </ProjectSelectorPopover>
102
+ </div>
103
+ </div>
104
+ );
105
+ }
106
+
107
+ // Mobile: inline collapsible accordion
108
+ return (
109
+ <div className="flex flex-col gap-2.5">
110
+ <div className="flex items-center justify-between">
111
+ <div
112
+ className="flex items-center gap-1 cursor-pointer"
113
+ onClick={() => { const next = activeSection === 'projects' ? null : 'projects'; setActiveSection(next); if (!next) setSearch(''); }}
114
+ >
115
+ <span className="paragraph-medium-semibold text-gray-600">{selectedProject?.title}</span>
116
+ <IconChevronDown
117
+ size={20}
118
+ className={`transition-transform duration-200 ${
119
+ activeSection === 'projects' ? 'rotate-180 text-gray-950' : 'text-gray-400'
120
+ }`}
121
+ />
122
+ </div>
123
+ </div>
124
+ {activeSection === 'projects' && (
125
+ <div className="flex flex-col p-3 gap-2 border border-gray-200 rounded-lg animate-in fade-in duration-400">
126
+ <div className="flex items-center justify-between">
127
+ <span className="paragraph-small-semibold">Projetos</span>
128
+ </div>
129
+ <Command className="gap-2" shouldFilter={false}>
130
+ <CommandInput placeholder="Busque aqui" value={search} onValueChange={setSearch} />
131
+ <CommandList
132
+ className="custom-scrollbar paragraph-small-medium text-gray-600 h-[227px]"
133
+ onScroll={(event) => {
134
+ if (!hasNextPage || isFetchingNextPage || !fetchNextPage) return;
135
+
136
+ const target = event.currentTarget;
137
+ const distanceToBottom = target.scrollHeight - target.scrollTop - target.clientHeight;
138
+
139
+ if (distanceToBottom <= 80) {
140
+ fetchNextPage();
141
+ }
142
+ }}
143
+ >
144
+ <CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
145
+ {showListSkeleton ? (
146
+ <>
147
+ <ProjectItemSkeleton />
148
+ <ProjectItemSkeleton />
149
+ <ProjectItemSkeleton />
150
+ <ProjectItemSkeleton />
151
+ </>
152
+ ) : (
153
+ projects.map((project) => (
154
+ <CommandItem
155
+ key={project.id}
156
+ value={`${project.title}-${project.id}`}
157
+ keywords={[project.title]}
158
+ className={selectedProject?.id === project.id ? 'bg-gray-50 min-h-[39px]' : 'min-h-[39px]'}
159
+ onSelect={() => { onSelectProject(project); setActiveSection(null); setSearch(''); }}
160
+ >
161
+ <UserAvatar
162
+ photo={project.photo}
163
+ name={project.title}
164
+ size={36}
165
+ />
166
+ {project.title}
167
+ </CommandItem>
168
+ ))
169
+ )}
170
+ {isFetchingNextPage && (
171
+ <>
172
+ <ProjectItemSkeleton />
173
+ <ProjectItemSkeleton />
174
+ </>
175
+ )}
176
+ </CommandList>
177
+ </Command>
178
+ </div>
179
+ )}
180
+ </div>
181
+ );
182
+ }