@greatapps/common 1.1.516 → 1.1.517

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 (407) 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/CrispEmbed.mjs.map +1 -1
  19. package/dist/components/embeds/EmbedWidgets.mjs.map +1 -1
  20. package/dist/components/embeds/FrillEmbed.mjs.map +1 -1
  21. package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
  22. package/dist/components/layouts/AppNavBar.mjs.map +1 -1
  23. package/dist/components/layouts/MdSideBarNavigation.mjs.map +1 -1
  24. package/dist/components/layouts/NavBar.mjs.map +1 -1
  25. package/dist/components/layouts/NotificationsPopover.mjs.map +1 -1
  26. package/dist/components/layouts/ProfilePopover.mjs.map +1 -1
  27. package/dist/components/layouts/SideBarNavigation.mjs.map +1 -1
  28. package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
  29. package/dist/components/layouts/WhitelabelCodes.mjs.map +1 -1
  30. package/dist/components/modals/BuyCreditsModal.mjs.map +1 -1
  31. package/dist/components/modals/PaidPlanRequiredModal.mjs.map +1 -1
  32. package/dist/components/modals/cards/AddCardModal.mjs.map +1 -1
  33. package/dist/components/modals/cards/CardFormFields.mjs.map +1 -1
  34. package/dist/components/navigation/CancelledSubscriptionBanner.mjs.map +1 -1
  35. package/dist/components/navigation/NavItemsContext.mjs.map +1 -1
  36. package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
  37. package/dist/components/navigation/shells/TabsMobileShell.mjs.map +1 -1
  38. package/dist/components/navigation/subcomponents/BottomLinks.mjs.map +1 -1
  39. package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
  40. package/dist/components/pages/NotFoundPage.mjs.map +1 -1
  41. package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
  42. package/dist/components/ui/buttons/Button.mjs.map +1 -1
  43. package/dist/components/ui/buttons/CancelButton.mjs.map +1 -1
  44. package/dist/components/ui/buttons/CopyButton.mjs.map +1 -1
  45. package/dist/components/ui/data-display/Accordion.mjs.map +1 -1
  46. package/dist/components/ui/data-display/Badge.mjs.map +1 -1
  47. package/dist/components/ui/data-display/Card.mjs.map +1 -1
  48. package/dist/components/ui/data-display/CardBrandIcons.mjs.map +1 -1
  49. package/dist/components/ui/data-display/CardItem.mjs.map +1 -1
  50. package/dist/components/ui/data-display/Pagination.mjs.map +1 -1
  51. package/dist/components/ui/data-display/PaymentInfoCard.mjs.map +1 -1
  52. package/dist/components/ui/data-display/ScrollArea.mjs.map +1 -1
  53. package/dist/components/ui/data-display/Separator.mjs.map +1 -1
  54. package/dist/components/ui/data-display/Table.mjs.map +1 -1
  55. package/dist/components/ui/data-display/Tabs.mjs.map +1 -1
  56. package/dist/components/ui/feedback/CircularProgress.mjs.map +1 -1
  57. package/dist/components/ui/feedback/DefaultCircularProgress.mjs.map +1 -1
  58. package/dist/components/ui/feedback/LoadingOverlay.mjs.map +1 -1
  59. package/dist/components/ui/feedback/Progress.mjs.map +1 -1
  60. package/dist/components/ui/feedback/Skeleton.mjs.map +1 -1
  61. package/dist/components/ui/feedback/Toast.mjs.map +1 -1
  62. package/dist/components/ui/form/Calendar.mjs.map +1 -1
  63. package/dist/components/ui/form/Checkbox.mjs.map +1 -1
  64. package/dist/components/ui/form/ComboboxField.mjs.map +1 -1
  65. package/dist/components/ui/form/DatePicker.mjs +2 -2
  66. package/dist/components/ui/form/DatePicker.mjs.map +1 -1
  67. package/dist/components/ui/form/DateRangePicker.mjs.map +1 -1
  68. package/dist/components/ui/form/FormField.mjs.map +1 -1
  69. package/dist/components/ui/form/Input.mjs.map +1 -1
  70. package/dist/components/ui/form/InputOtp.mjs.map +1 -1
  71. package/dist/components/ui/form/PhoneInput.mjs.map +1 -1
  72. package/dist/components/ui/form/RadioGroup.mjs.map +1 -1
  73. package/dist/components/ui/form/Select.mjs +1 -1
  74. package/dist/components/ui/form/Select.mjs.map +1 -1
  75. package/dist/components/ui/form/Switch.mjs.map +1 -1
  76. package/dist/components/ui/form/Textarea.mjs.map +1 -1
  77. package/dist/components/ui/overlay/Command.mjs.map +1 -1
  78. package/dist/components/ui/overlay/Dialog.mjs.map +1 -1
  79. package/dist/components/ui/overlay/Popover.mjs.map +1 -1
  80. package/dist/components/ui/overlay/Sheet.mjs.map +1 -1
  81. package/dist/components/ui/overlay/Tooltip.mjs.map +1 -1
  82. package/dist/components/widgets/ImageUpload/ImageCropModal.mjs.map +1 -1
  83. package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs.map +1 -1
  84. package/dist/components/widgets/ImageUpload/ImageUpload.mjs.map +1 -1
  85. package/dist/components/widgets/ImageUpload/index.mjs.map +1 -1
  86. package/dist/components/widgets/notifications/NotificationCard.mjs.map +1 -1
  87. package/dist/hooks/copy-to-clipboard.hook.mjs.map +1 -1
  88. package/dist/hooks/useAuthQueryKey.mjs.map +1 -1
  89. package/dist/index.mjs.map +1 -1
  90. package/dist/infra/utils/array.mjs.map +1 -1
  91. package/dist/infra/utils/date.mjs.map +1 -1
  92. package/dist/middleware.mjs.map +1 -1
  93. package/dist/modules/accounts/actions/account-management.action.mjs.map +1 -1
  94. package/dist/modules/accounts/actions/find-current-account.action.mjs.map +1 -1
  95. package/dist/modules/accounts/actions/get-account-token.action.mjs.map +1 -1
  96. package/dist/modules/accounts/actions/list-currencies.action.mjs.map +1 -1
  97. package/dist/modules/accounts/actions/list-timezones.action.mjs.map +1 -1
  98. package/dist/modules/accounts/hooks/current-account.hook.mjs.map +1 -1
  99. package/dist/modules/accounts/hooks/use-account-token.hook.mjs.map +1 -1
  100. package/dist/modules/accounts/hooks/useAccountManagement.mjs.map +1 -1
  101. package/dist/modules/accounts/hooks/useCurrencies.mjs.map +1 -1
  102. package/dist/modules/accounts/hooks/useTimezones.mjs.map +1 -1
  103. package/dist/modules/accounts/hooks/useViaCep.mjs.map +1 -1
  104. package/dist/modules/accounts/services/account-token.service.mjs.map +1 -1
  105. package/dist/modules/accounts/services/account.service.mjs.map +1 -1
  106. package/dist/modules/auth/actions/validate-session.action.mjs.map +1 -1
  107. package/dist/modules/auth/hooks/login.hook.mjs.map +1 -1
  108. package/dist/modules/auth/hooks/logout.hook.mjs.map +1 -1
  109. package/dist/modules/auth/hooks/register.hook.mjs.map +1 -1
  110. package/dist/modules/auth/hooks/useManagementPermissions.mjs.map +1 -1
  111. package/dist/modules/auth/hooks/useUserQuery.mjs.map +1 -1
  112. package/dist/modules/auth/utils/assert-management-permission.mjs.map +1 -1
  113. package/dist/modules/auth/utils/assert-management-subscription.mjs.map +1 -1
  114. package/dist/modules/auth/utils/assert-paid-subscription.mjs.map +1 -1
  115. package/dist/modules/auth/utils/assert-subscription-addon.mjs.map +1 -1
  116. package/dist/modules/auth/utils/build-wl-override.mjs.map +1 -1
  117. package/dist/modules/cards/actions/create-card.action.mjs.map +1 -1
  118. package/dist/modules/cards/actions/delete-card.action.mjs.map +1 -1
  119. package/dist/modules/cards/actions/find-card-by-id.action.mjs.map +1 -1
  120. package/dist/modules/cards/actions/list-cards.action.mjs.map +1 -1
  121. package/dist/modules/cards/actions/set-default-card.action.mjs.map +1 -1
  122. package/dist/modules/cards/hooks/card-by-id.hook.mjs.map +1 -1
  123. package/dist/modules/cards/hooks/cards.hook.mjs.map +1 -1
  124. package/dist/modules/cards/hooks/create-card.hook.mjs.map +1 -1
  125. package/dist/modules/cards/hooks/delete-card.hook.mjs.map +1 -1
  126. package/dist/modules/cards/hooks/set-default-card.hook.mjs.map +1 -1
  127. package/dist/modules/cards/services/cards.service.mjs.map +1 -1
  128. package/dist/modules/cards/types.mjs.map +1 -1
  129. package/dist/modules/ia-credits/actions/list-ia-credits.action.mjs.map +1 -1
  130. package/dist/modules/ia-credits/hooks/ia-credits.hook.mjs.map +1 -1
  131. package/dist/modules/images/actions/process-image.action.mjs.map +1 -1
  132. package/dist/modules/images/constants/image.constants.mjs.map +1 -1
  133. package/dist/modules/images/hooks/use-image-upload.hook.mjs.map +1 -1
  134. package/dist/modules/images/services/image-processing.service.mjs.map +1 -1
  135. package/dist/modules/images/utils/base64.mjs.map +1 -1
  136. package/dist/modules/images/utils/compress-image.mjs.map +1 -1
  137. package/dist/modules/images/utils/crop-image.mjs.map +1 -1
  138. package/dist/modules/images/utils/validate-image.mjs.map +1 -1
  139. package/dist/modules/plans/actions/find-plan-by-id.action.mjs.map +1 -1
  140. package/dist/modules/plans/actions/list-plans.action.mjs.map +1 -1
  141. package/dist/modules/plans/hooks/list-plans.hook.mjs.map +1 -1
  142. package/dist/modules/plans/hooks/use-has-plan-addon.hook.mjs.map +1 -1
  143. package/dist/modules/plans/hooks/use-plan-by-id.hook.mjs.map +1 -1
  144. package/dist/modules/plans/services/plans.service.mjs.map +1 -1
  145. package/dist/modules/plans/types/plan.type.mjs.map +1 -1
  146. package/dist/modules/plans/utils/map-api-plan-to-ui.mjs.map +1 -1
  147. package/dist/modules/projects/actions/add-project-user.action.mjs.map +1 -1
  148. package/dist/modules/projects/actions/create-project.action.mjs.map +1 -1
  149. package/dist/modules/projects/actions/delete-project.action.mjs.map +1 -1
  150. package/dist/modules/projects/actions/find-project.action.mjs.map +1 -1
  151. package/dist/modules/projects/actions/list-all-account-users.action.mjs.map +1 -1
  152. package/dist/modules/projects/actions/list-available-users.action.mjs.map +1 -1
  153. package/dist/modules/projects/actions/list-project-users.action.mjs.map +1 -1
  154. package/dist/modules/projects/actions/list-projects.action.mjs.map +1 -1
  155. package/dist/modules/projects/actions/remove-project-user.action.mjs.map +1 -1
  156. package/dist/modules/projects/actions/update-project.action.mjs.map +1 -1
  157. package/dist/modules/projects/hooks/add-project-user.hook.mjs.map +1 -1
  158. package/dist/modules/projects/hooks/create-project.hook.mjs.map +1 -1
  159. package/dist/modules/projects/hooks/delete-project.hook.mjs.map +1 -1
  160. package/dist/modules/projects/hooks/find-project.hook.mjs.map +1 -1
  161. package/dist/modules/projects/hooks/list-all-account-users.hook.mjs.map +1 -1
  162. package/dist/modules/projects/hooks/list-available-users.hook.mjs.map +1 -1
  163. package/dist/modules/projects/hooks/list-infinite-projects.hook.mjs.map +1 -1
  164. package/dist/modules/projects/hooks/list-project-users.hook.mjs.map +1 -1
  165. package/dist/modules/projects/hooks/list-projects.hook.mjs.map +1 -1
  166. package/dist/modules/projects/hooks/remove-project-user.hook.mjs.map +1 -1
  167. package/dist/modules/projects/hooks/update-project.hook.mjs.map +1 -1
  168. package/dist/modules/projects/services/projects.service.mjs.map +1 -1
  169. package/dist/modules/subscriptions/actions/calculate-subscription.action.mjs.map +1 -1
  170. package/dist/modules/subscriptions/actions/list-subscriptions.action.mjs.map +1 -1
  171. package/dist/modules/subscriptions/actions/update-subscription-plan.action.mjs.map +1 -1
  172. package/dist/modules/subscriptions/constants/query-keys.constants.mjs.map +1 -1
  173. package/dist/modules/subscriptions/hooks/calculate-subscription.hook.mjs.map +1 -1
  174. package/dist/modules/subscriptions/hooks/find-active-subscription.hook.mjs.map +1 -1
  175. package/dist/modules/subscriptions/hooks/list-subscriptions.hook.mjs.map +1 -1
  176. package/dist/modules/subscriptions/hooks/update-subscription-plan.hook.mjs.map +1 -1
  177. package/dist/modules/subscriptions/hooks/use-cancelled-subscription-guard.mjs.map +1 -1
  178. package/dist/modules/subscriptions/types/calculate-subscription.type.mjs.map +1 -1
  179. package/dist/modules/subscriptions/utils/build-plan-extras.mjs.map +1 -1
  180. package/dist/modules/subscriptions/utils/has-subscription-expired.mjs.map +1 -1
  181. package/dist/modules/subscriptions/utils/periodicity.mjs.map +1 -1
  182. package/dist/modules/subscriptions/utils/resolve-plan-extras-prices.mjs.map +1 -1
  183. package/dist/modules/users/action/find-user-by-id.action.mjs.map +1 -1
  184. package/dist/modules/users/action/list-messages.action.mjs.map +1 -1
  185. package/dist/modules/users/action/mark-all-messages-as-read.action.mjs.map +1 -1
  186. package/dist/modules/users/action/mark-message-as-read.action.mjs.map +1 -1
  187. package/dist/modules/users/hooks/messages.hook.mjs.map +1 -1
  188. package/dist/modules/users/services/messages.service.mjs.map +1 -1
  189. package/dist/modules/whitelabel/actions/find-whitelabel.action.mjs.map +1 -1
  190. package/dist/modules/whitelabel/actions/revalidate-whitelabel.action.mjs.map +1 -1
  191. package/dist/modules/whitelabel/utils/normalize-hostname.mjs.map +1 -1
  192. package/dist/providers/auth.provider.mjs.map +1 -1
  193. package/dist/providers/whitelabel.provider.mjs.map +1 -1
  194. package/dist/store/useBuyCreditsModal.mjs.map +1 -1
  195. package/dist/store/useDesktopSidebarStore.mjs.map +1 -1
  196. package/dist/store/useMdSidebarStore.mjs.map +1 -1
  197. package/dist/store/usePaidPlanRequiredModal.mjs.map +1 -1
  198. package/dist/utils/constants/br-states.mjs.map +1 -1
  199. package/dist/utils/countries.mjs.map +1 -1
  200. package/dist/utils/format/currency.mjs.map +1 -1
  201. package/dist/utils/safeServerAction.mjs.map +1 -1
  202. package/dist/utils/withAction.mjs.map +1 -1
  203. package/package.json +92 -92
  204. package/src/components/account/ConfigurationsMyAccountModal.tsx +161 -161
  205. package/src/components/account/ConfirmDeleteAccountModal.tsx +55 -55
  206. package/src/components/account/ConfirmGlobalPreferencesModal.tsx +66 -66
  207. package/src/components/account/DeleteAccountModal.tsx +130 -130
  208. package/src/components/account/DisableTwoFactorAuthModal.tsx +86 -86
  209. package/src/components/account/IsntPossibleDeleteAccountModal.tsx +49 -49
  210. package/src/components/account/TwoFactorAuthModal.tsx +215 -215
  211. package/src/components/account/hooks/useChangePhoneForm.tsx +107 -107
  212. package/src/components/account/hooks/useTwoFactorAuthForm.tsx +101 -101
  213. package/src/components/account/sections/ChangeEmailModal.tsx +227 -227
  214. package/src/components/account/sections/ChangePasswordSection.tsx +64 -64
  215. package/src/components/account/sections/ChangePhoneModal.tsx +247 -247
  216. package/src/components/account/sections/MyProfileSection.tsx +328 -328
  217. package/src/components/account/sections/PreferencesSection.tsx +248 -248
  218. package/src/components/account/sections/SecuritySection.tsx +46 -46
  219. package/src/components/account/sections/TokenSection.tsx +64 -64
  220. package/src/components/embeds/CrispEmbed.tsx +156 -156
  221. package/src/components/embeds/EmbedWidgets.tsx +50 -50
  222. package/src/components/embeds/FrillEmbed.tsx +129 -129
  223. package/src/components/layouts/AppMobileNavBar.tsx +80 -80
  224. package/src/components/layouts/AppNavBar.tsx +40 -40
  225. package/src/components/layouts/MdSideBarNavigation.tsx +56 -56
  226. package/src/components/layouts/NavBar.tsx +175 -175
  227. package/src/components/layouts/NotificationsPopover.tsx +118 -118
  228. package/src/components/layouts/ProfilePopover.tsx +176 -176
  229. package/src/components/layouts/SideBarNavigation.tsx +65 -65
  230. package/src/components/layouts/UsersSelectorPopover.tsx +234 -234
  231. package/src/components/layouts/WhitelabelCodes.tsx +59 -59
  232. package/src/components/modals/BuyCreditsModal.tsx +354 -354
  233. package/src/components/modals/PaidPlanRequiredModal.tsx +57 -57
  234. package/src/components/modals/cards/AddCardModal.tsx +265 -265
  235. package/src/components/modals/cards/CardFormFields.tsx +348 -348
  236. package/src/components/navigation/CancelledSubscriptionBanner.tsx +64 -64
  237. package/src/components/navigation/NavItemsContext.ts +20 -20
  238. package/src/components/navigation/ProjectSelectorPopover.tsx +178 -178
  239. package/src/components/navigation/shells/TabsMobileShell.tsx +74 -74
  240. package/src/components/navigation/subcomponents/BottomLinks.tsx +37 -37
  241. package/src/components/navigation/subcomponents/ProjectSelector.tsx +182 -182
  242. package/src/components/pages/NotFoundPage.tsx +67 -67
  243. package/src/components/pages/notifications/Notifications.tsx +187 -187
  244. package/src/components/ui/buttons/Button.tsx +62 -62
  245. package/src/components/ui/buttons/CancelButton.tsx +14 -14
  246. package/src/components/ui/buttons/CopyButton.tsx +54 -54
  247. package/src/components/ui/data-display/Accordion.tsx +81 -81
  248. package/src/components/ui/data-display/Badge.tsx +47 -47
  249. package/src/components/ui/data-display/Card.tsx +93 -93
  250. package/src/components/ui/data-display/CardBrandIcons.tsx +336 -336
  251. package/src/components/ui/data-display/CardItem.tsx +75 -75
  252. package/src/components/ui/data-display/Pagination.tsx +126 -126
  253. package/src/components/ui/data-display/PaymentInfoCard.tsx +192 -192
  254. package/src/components/ui/data-display/ScrollArea.tsx +59 -59
  255. package/src/components/ui/data-display/Separator.tsx +29 -29
  256. package/src/components/ui/data-display/Table.tsx +117 -117
  257. package/src/components/ui/data-display/Tabs.tsx +67 -67
  258. package/src/components/ui/feedback/CircularProgress.tsx +75 -75
  259. package/src/components/ui/feedback/DefaultCircularProgress.tsx +65 -65
  260. package/src/components/ui/feedback/LoadingOverlay.tsx +31 -31
  261. package/src/components/ui/feedback/Progress.tsx +40 -40
  262. package/src/components/ui/feedback/Skeleton.tsx +5 -5
  263. package/src/components/ui/feedback/Toast.tsx +104 -104
  264. package/src/components/ui/form/Calendar.tsx +228 -228
  265. package/src/components/ui/form/Checkbox.tsx +31 -31
  266. package/src/components/ui/form/ComboboxField.tsx +154 -154
  267. package/src/components/ui/form/DatePicker.tsx +98 -97
  268. package/src/components/ui/form/DateRangePicker.tsx +108 -108
  269. package/src/components/ui/form/FormField.tsx +133 -133
  270. package/src/components/ui/form/Input.tsx +20 -20
  271. package/src/components/ui/form/InputOtp.tsx +80 -80
  272. package/src/components/ui/form/PhoneInput.tsx +208 -208
  273. package/src/components/ui/form/RadioGroup.tsx +45 -45
  274. package/src/components/ui/form/Select.tsx +200 -200
  275. package/src/components/ui/form/Switch.tsx +32 -32
  276. package/src/components/ui/form/Textarea.tsx +19 -19
  277. package/src/components/ui/overlay/Command.tsx +185 -185
  278. package/src/components/ui/overlay/Dialog.tsx +153 -153
  279. package/src/components/ui/overlay/Popover.tsx +49 -49
  280. package/src/components/ui/overlay/Sheet.tsx +170 -170
  281. package/src/components/ui/overlay/Tooltip.tsx +62 -62
  282. package/src/components/widgets/ImageUpload/ImageCropModal.tsx +254 -254
  283. package/src/components/widgets/ImageUpload/ImageTooSmallModal.tsx +61 -61
  284. package/src/components/widgets/ImageUpload/ImageUpload.tsx +126 -126
  285. package/src/components/widgets/ImageUpload/index.ts +3 -3
  286. package/src/components/widgets/notifications/NotificationCard.tsx +73 -73
  287. package/src/hooks/copy-to-clipboard.hook.tsx +67 -67
  288. package/src/hooks/useAuthQueryKey.ts +32 -32
  289. package/src/index.ts +506 -506
  290. package/src/infra/utils/array.ts +54 -54
  291. package/src/infra/utils/date.ts +18 -18
  292. package/src/middleware.ts +4 -4
  293. package/src/modules/accounts/actions/account-management.action.ts +107 -107
  294. package/src/modules/accounts/actions/find-current-account.action.ts +9 -9
  295. package/src/modules/accounts/actions/get-account-token.action.ts +8 -8
  296. package/src/modules/accounts/actions/list-currencies.action.ts +8 -8
  297. package/src/modules/accounts/actions/list-timezones.action.ts +8 -8
  298. package/src/modules/accounts/hooks/current-account.hook.tsx +26 -26
  299. package/src/modules/accounts/hooks/use-account-token.hook.tsx +14 -14
  300. package/src/modules/accounts/hooks/useAccountManagement.ts +94 -94
  301. package/src/modules/accounts/hooks/useCurrencies.ts +18 -18
  302. package/src/modules/accounts/hooks/useTimezones.ts +18 -18
  303. package/src/modules/accounts/hooks/useViaCep.ts +25 -25
  304. package/src/modules/accounts/services/account-token.service.ts +52 -52
  305. package/src/modules/accounts/services/account.service.ts +239 -239
  306. package/src/modules/accounts/types.ts +225 -225
  307. package/src/modules/auth/actions/validate-session.action.ts +56 -56
  308. package/src/modules/auth/hooks/login.hook.tsx +13 -13
  309. package/src/modules/auth/hooks/logout.hook.tsx +11 -11
  310. package/src/modules/auth/hooks/register.hook.tsx +11 -11
  311. package/src/modules/auth/hooks/useManagementPermissions.ts +45 -45
  312. package/src/modules/auth/hooks/useUserQuery.ts +75 -75
  313. package/src/modules/auth/types/management-permission.type.ts +7 -7
  314. package/src/modules/auth/utils/assert-management-permission.ts +46 -46
  315. package/src/modules/auth/utils/assert-management-subscription.ts +35 -35
  316. package/src/modules/auth/utils/assert-paid-subscription.ts +43 -43
  317. package/src/modules/auth/utils/assert-subscription-addon.ts +42 -42
  318. package/src/modules/auth/utils/build-wl-override.ts +43 -43
  319. package/src/modules/cards/actions/create-card.action.ts +9 -9
  320. package/src/modules/cards/actions/delete-card.action.ts +8 -8
  321. package/src/modules/cards/actions/find-card-by-id.action.ts +8 -8
  322. package/src/modules/cards/actions/list-cards.action.ts +8 -8
  323. package/src/modules/cards/actions/set-default-card.action.ts +8 -8
  324. package/src/modules/cards/hooks/card-by-id.hook.ts +21 -21
  325. package/src/modules/cards/hooks/cards.hook.ts +23 -23
  326. package/src/modules/cards/hooks/create-card.hook.ts +30 -30
  327. package/src/modules/cards/hooks/delete-card.hook.ts +54 -54
  328. package/src/modules/cards/hooks/set-default-card.hook.ts +55 -55
  329. package/src/modules/cards/services/cards.service.ts +108 -108
  330. package/src/modules/cards/types.ts +42 -42
  331. package/src/modules/ia-credits/actions/list-ia-credits.action.ts +8 -8
  332. package/src/modules/ia-credits/hooks/ia-credits.hook.ts +99 -99
  333. package/src/modules/images/actions/process-image.action.ts +40 -40
  334. package/src/modules/images/constants/image.constants.ts +11 -11
  335. package/src/modules/images/hooks/use-image-upload.hook.ts +172 -172
  336. package/src/modules/images/services/image-processing.service.ts +75 -75
  337. package/src/modules/images/types/image.type.ts +54 -54
  338. package/src/modules/images/utils/base64.ts +26 -26
  339. package/src/modules/images/utils/compress-image.ts +20 -20
  340. package/src/modules/images/utils/crop-image.ts +51 -51
  341. package/src/modules/images/utils/validate-image.ts +71 -71
  342. package/src/modules/plans/actions/find-plan-by-id.action.ts +8 -8
  343. package/src/modules/plans/actions/list-plans.action.ts +17 -17
  344. package/src/modules/plans/hooks/list-plans.hook.ts +24 -24
  345. package/src/modules/plans/hooks/use-has-plan-addon.hook.ts +14 -14
  346. package/src/modules/plans/hooks/use-plan-by-id.hook.ts +38 -38
  347. package/src/modules/plans/services/plans.service.ts +133 -133
  348. package/src/modules/plans/types/plan.type.ts +67 -67
  349. package/src/modules/plans/utils/map-api-plan-to-ui.ts +98 -98
  350. package/src/modules/projects/actions/add-project-user.action.ts +9 -9
  351. package/src/modules/projects/actions/create-project.action.ts +9 -9
  352. package/src/modules/projects/actions/delete-project.action.ts +8 -8
  353. package/src/modules/projects/actions/find-project.action.ts +8 -8
  354. package/src/modules/projects/actions/list-all-account-users.action.ts +9 -9
  355. package/src/modules/projects/actions/list-available-users.action.ts +9 -9
  356. package/src/modules/projects/actions/list-project-users.action.ts +9 -9
  357. package/src/modules/projects/actions/list-projects.action.ts +16 -16
  358. package/src/modules/projects/actions/remove-project-user.action.ts +9 -9
  359. package/src/modules/projects/actions/update-project.action.ts +9 -9
  360. package/src/modules/projects/hooks/add-project-user.hook.ts +72 -72
  361. package/src/modules/projects/hooks/create-project.hook.ts +88 -88
  362. package/src/modules/projects/hooks/delete-project.hook.ts +58 -58
  363. package/src/modules/projects/hooks/find-project.hook.ts +18 -18
  364. package/src/modules/projects/hooks/list-all-account-users.hook.ts +39 -39
  365. package/src/modules/projects/hooks/list-available-users.hook.ts +38 -38
  366. package/src/modules/projects/hooks/list-infinite-projects.hook.ts +43 -43
  367. package/src/modules/projects/hooks/list-project-users.hook.ts +38 -38
  368. package/src/modules/projects/hooks/list-projects.hook.ts +23 -23
  369. package/src/modules/projects/hooks/remove-project-user.hook.ts +72 -72
  370. package/src/modules/projects/hooks/update-project.hook.ts +86 -86
  371. package/src/modules/projects/services/projects.service.ts +144 -144
  372. package/src/modules/subscriptions/actions/calculate-subscription.action.ts +9 -9
  373. package/src/modules/subscriptions/actions/list-subscriptions.action.ts +9 -9
  374. package/src/modules/subscriptions/actions/update-subscription-plan.action.ts +14 -14
  375. package/src/modules/subscriptions/constants/query-keys.constants.ts +3 -3
  376. package/src/modules/subscriptions/hooks/calculate-subscription.hook.ts +13 -13
  377. package/src/modules/subscriptions/hooks/find-active-subscription.hook.ts +18 -18
  378. package/src/modules/subscriptions/hooks/list-subscriptions.hook.ts +19 -19
  379. package/src/modules/subscriptions/hooks/update-subscription-plan.hook.ts +28 -28
  380. package/src/modules/subscriptions/hooks/use-cancelled-subscription-guard.ts +39 -39
  381. package/src/modules/subscriptions/types/billing-period.type.ts +1 -1
  382. package/src/modules/subscriptions/types/calculate-subscription.type.ts +113 -113
  383. package/src/modules/subscriptions/utils/build-plan-extras.ts +56 -56
  384. package/src/modules/subscriptions/utils/has-subscription-expired.ts +8 -8
  385. package/src/modules/subscriptions/utils/periodicity.ts +62 -62
  386. package/src/modules/subscriptions/utils/resolve-plan-extras-prices.ts +23 -23
  387. package/src/modules/users/action/find-user-by-id.action.ts +8 -8
  388. package/src/modules/users/action/list-messages.action.ts +26 -26
  389. package/src/modules/users/action/mark-all-messages-as-read.action.ts +8 -8
  390. package/src/modules/users/action/mark-message-as-read.action.ts +8 -8
  391. package/src/modules/users/hooks/messages.hook.ts +67 -67
  392. package/src/modules/users/services/messages.service.ts +49 -49
  393. package/src/modules/whitelabel/actions/find-whitelabel.action.ts +23 -23
  394. package/src/modules/whitelabel/actions/revalidate-whitelabel.action.ts +19 -19
  395. package/src/modules/whitelabel/schema.ts +84 -84
  396. package/src/modules/whitelabel/utils/normalize-hostname.ts +26 -26
  397. package/src/providers/auth.provider.tsx +162 -162
  398. package/src/providers/whitelabel.provider.tsx +59 -59
  399. package/src/store/useBuyCreditsModal.ts +21 -21
  400. package/src/store/useDesktopSidebarStore.ts +47 -47
  401. package/src/store/useMdSidebarStore.ts +34 -34
  402. package/src/store/usePaidPlanRequiredModal.ts +19 -19
  403. package/src/utils/constants/br-states.ts +29 -29
  404. package/src/utils/countries.ts +224 -224
  405. package/src/utils/format/currency.ts +15 -15
  406. package/src/utils/safeServerAction.ts +21 -21
  407. 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
+ }