@greatapps/common 1.1.517 → 1.1.519

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