@carlonicora/nextjs-jsonapi 4.1.2 → 4.2.1

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 (285) hide show
  1. package/dist/{AssistantMessageInterface-CubxuBIJ.d.ts → AssistantMessageInterface-DHJJO_Z_.d.ts} +1 -1
  2. package/dist/{AssistantMessageInterface-sHjI2zPN.d.mts → AssistantMessageInterface-S7oyERTT.d.mts} +1 -1
  3. package/dist/{BlockNoteEditor-VOYKZOP5.mjs → BlockNoteEditor-HXAHDJA7.mjs} +34 -27
  4. package/dist/BlockNoteEditor-HXAHDJA7.mjs.map +1 -0
  5. package/dist/{BlockNoteEditor-BENYTTCZ.js → BlockNoteEditor-LLCZDFLZ.js} +50 -43
  6. package/dist/BlockNoteEditor-LLCZDFLZ.js.map +1 -0
  7. package/dist/{BlockNoteViewer-USLR4Y7C.js → BlockNoteViewer-77CCTC2U.js} +3 -3
  8. package/dist/{BlockNoteViewer-USLR4Y7C.js.map → BlockNoteViewer-77CCTC2U.js.map} +1 -1
  9. package/dist/{BlockNoteViewer-Y2ZM4ESA.mjs → BlockNoteViewer-MDPO6BXN.mjs} +2 -2
  10. package/dist/{auth.interface-Df4vXbNz.d.mts → auth.interface-CeFCz9NU.d.mts} +1 -1
  11. package/dist/{auth.interface-BzI4onI_.d.ts → auth.interface-D1R7VVky.d.ts} +1 -1
  12. package/dist/billing/index.d.mts +40 -6
  13. package/dist/billing/index.d.ts +40 -6
  14. package/dist/billing/index.js +806 -774
  15. package/dist/billing/index.js.map +1 -1
  16. package/dist/billing/index.mjs +494 -462
  17. package/dist/billing/index.mjs.map +1 -1
  18. package/dist/{chunk-6ISF5KNQ.mjs → chunk-2VXDZRYY.mjs} +1103 -816
  19. package/dist/chunk-2VXDZRYY.mjs.map +1 -0
  20. package/dist/{chunk-4BZJ4LAB.js → chunk-4ORLPEK7.js} +136 -104
  21. package/dist/chunk-4ORLPEK7.js.map +1 -0
  22. package/dist/{chunk-ZZ6E33FO.mjs → chunk-6DRSSW5O.mjs} +36 -4
  23. package/dist/chunk-6DRSSW5O.mjs.map +1 -0
  24. package/dist/{chunk-KS6WZP2E.js → chunk-6SMJRAE3.js} +4 -4
  25. package/dist/{chunk-KS6WZP2E.js.map → chunk-6SMJRAE3.js.map} +1 -1
  26. package/dist/{chunk-WQ77CUUZ.js → chunk-GPXYQMOZ.js} +7 -7
  27. package/dist/{chunk-WQ77CUUZ.js.map → chunk-GPXYQMOZ.js.map} +1 -1
  28. package/dist/{chunk-46S3KPLU.mjs → chunk-ILFFC6BG.mjs} +2 -2
  29. package/dist/{chunk-HZVVRIJQ.mjs → chunk-IUS2RHCX.mjs} +2 -2
  30. package/dist/{chunk-F7RNBGHS.js → chunk-KJMMBUOA.js} +3 -3
  31. package/dist/{chunk-F7RNBGHS.js.map → chunk-KJMMBUOA.js.map} +1 -1
  32. package/dist/{chunk-ZO3QQ5CQ.mjs → chunk-MQDR6MEE.mjs} +2 -2
  33. package/dist/{chunk-ORU7KLCY.js → chunk-VDVIUDY5.js} +1445 -1158
  34. package/dist/chunk-VDVIUDY5.js.map +1 -0
  35. package/dist/client/index.d.mts +20 -6
  36. package/dist/client/index.d.ts +20 -6
  37. package/dist/client/index.js +6 -4
  38. package/dist/client/index.js.map +1 -1
  39. package/dist/client/index.mjs +5 -3
  40. package/dist/components/index.d.mts +59 -21
  41. package/dist/components/index.d.ts +59 -21
  42. package/dist/components/index.js +4 -4
  43. package/dist/components/index.mjs +3 -3
  44. package/dist/{config-CEAq4Ozy.d.mts → config-BP2vyddw.d.mts} +5 -0
  45. package/dist/{config-DydDHCfb.d.ts → config-BhW2QrRD.d.ts} +5 -0
  46. package/dist/contexts/index.d.mts +4 -4
  47. package/dist/contexts/index.d.ts +4 -4
  48. package/dist/contexts/index.js +4 -4
  49. package/dist/contexts/index.mjs +3 -3
  50. package/dist/core/index.d.mts +17 -9
  51. package/dist/core/index.d.ts +17 -9
  52. package/dist/core/index.js +4 -2
  53. package/dist/core/index.js.map +1 -1
  54. package/dist/core/index.mjs +3 -1
  55. package/dist/features/analytics/index.d.mts +1 -1
  56. package/dist/features/analytics/index.d.ts +1 -1
  57. package/dist/features/analytics/index.js +122 -122
  58. package/dist/features/analytics/index.mjs +4 -4
  59. package/dist/features/analytics/server.js +4 -4
  60. package/dist/features/analytics/server.mjs +2 -2
  61. package/dist/features/help/index.d.mts +1 -1
  62. package/dist/features/help/index.d.ts +1 -1
  63. package/dist/features/help/index.js +42 -40
  64. package/dist/features/help/index.js.map +1 -1
  65. package/dist/features/help/index.mjs +8 -6
  66. package/dist/features/help/index.mjs.map +1 -1
  67. package/dist/features/tokenusage/index.js +125 -125
  68. package/dist/features/tokenusage/index.mjs +4 -4
  69. package/dist/index.d.mts +7 -7
  70. package/dist/index.d.ts +7 -7
  71. package/dist/index.js +5 -3
  72. package/dist/index.js.map +1 -1
  73. package/dist/index.mjs +4 -2
  74. package/dist/{notification.interface-P_pNfzZQ.d.mts → notification.interface-BB6GPpZY.d.mts} +1 -1
  75. package/dist/{notification.interface-BNCvnVCW.d.ts → notification.interface-CmAGrijJ.d.ts} +1 -1
  76. package/dist/{s3.service-CbUa6a-8.d.ts → s3.service-C-4YpEMu.d.ts} +7 -3
  77. package/dist/{s3.service-DAp8FbuG.d.mts → s3.service-dVj-nxMl.d.mts} +7 -3
  78. package/dist/server/index.d.mts +4 -4
  79. package/dist/server/index.d.ts +4 -4
  80. package/dist/server/index.js +3 -3
  81. package/dist/server/index.mjs +2 -2
  82. package/dist/{useSocket-BHVIyigI.d.ts → useSocket-B0H9pmmH.d.ts} +1 -1
  83. package/dist/{useSocket-B9gTbuCj.d.mts → useSocket-B5RQb6v2.d.mts} +1 -1
  84. package/dist/{user.interface-CrmwJLYW.d.ts → user.interface-C0ZdsBZj.d.ts} +2 -0
  85. package/dist/{user.interface-CSaGWFbg.d.mts → user.interface-CIWGlbqM.d.mts} +2 -0
  86. package/package.json +1 -1
  87. package/src/components/containers/RoundPageContainer.tsx +3 -1
  88. package/src/components/containers/RoundPageContainerTitle.tsx +5 -2
  89. package/src/components/editors/BlockNoteEditor.tsx +31 -15
  90. package/src/components/editors/BlockNoteEditorAiActions.tsx +11 -7
  91. package/src/components/editors/__tests__/{BlockNoteEditorAiActions.test.ts → BlockNoteEditorAiActions.spec.ts} +10 -3
  92. package/src/components/errors/ErrorDetails.tsx +5 -2
  93. package/src/components/forms/CommonAssociationForm.tsx +1 -1
  94. package/src/components/forms/EntityMultiSelector.tsx +6 -2
  95. package/src/components/forms/EntitySelector.tsx +4 -1
  96. package/src/components/forms/FileUploader.tsx +3 -2
  97. package/src/components/forms/MultiFileUploader.tsx +3 -1
  98. package/src/components/navigations/Breadcrumb.tsx +3 -2
  99. package/src/components/navigations/Header.tsx +3 -1
  100. package/src/components/navigations/MobileNavigationBar.tsx +3 -1
  101. package/src/components/navigations/__tests__/Header.spec.tsx +2 -2
  102. package/src/components/tables/__tests__/ContentListTable.spec.tsx +1 -1
  103. package/src/components/tables/cells/cell.id.tsx +13 -2
  104. package/src/core/abstracts/AbstractService.ts +3 -3
  105. package/src/core/abstracts/ClientAbstractService.ts +3 -2
  106. package/src/features/assistant-action/components/ApprovalActionCard.tsx +74 -5
  107. package/src/features/assistant-action/components/__tests__/ApprovalActionCard.spec.tsx +81 -0
  108. package/src/features/assistant-message/components/parts/RelevanceMeter.tsx +4 -1
  109. package/src/features/assistant-message/components/parts/tabs/UsersTab.tsx +2 -1
  110. package/src/features/auth/components/buttons/GoogleSignInButton.tsx +4 -1
  111. package/src/features/auth/components/details/LandingComponent.tsx +1 -1
  112. package/src/features/auth/components/forms/ForgotPassword.tsx +1 -1
  113. package/src/features/auth/components/forms/Login.tsx +1 -1
  114. package/src/features/auth/components/forms/Register.tsx +1 -1
  115. package/src/features/auth/components/forms/ResetPassword.tsx +2 -2
  116. package/src/features/auth/components/two-factor/BackupCodesDialog.tsx +1 -1
  117. package/src/features/auth/components/two-factor/PasskeyButton.tsx +1 -1
  118. package/src/features/billing/components/cards/BillingUsageSummaryCard.tsx +21 -11
  119. package/src/features/billing/components/cards/CustomerInfoCard.tsx +16 -13
  120. package/src/features/billing/components/cards/InvoicesSummaryCard.tsx +33 -21
  121. package/src/features/billing/components/cards/PaymentMethodSummaryCard.tsx +20 -10
  122. package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +35 -22
  123. package/src/features/billing/components/containers/BillingDashboardContainer.tsx +24 -24
  124. package/src/features/billing/components/utils/__tests__/billing-formatters.spec.ts +63 -0
  125. package/src/features/billing/components/utils/currency.ts +67 -10
  126. package/src/features/billing/components/utils/date.ts +9 -4
  127. package/src/features/billing/components/utils/format-options.ts +20 -0
  128. package/src/features/billing/components/utils/index.ts +3 -1
  129. package/src/features/billing/components/utils/useBillingFormatOptions.ts +11 -0
  130. package/src/features/billing/components/widgets/BillingAlertBanner.tsx +8 -9
  131. package/src/features/billing/contexts/PriceContext.tsx +18 -6
  132. package/src/features/billing/i18n-keys.ts +212 -0
  133. package/src/features/billing/stripe-customer/components/containers/PaymentMethodsContainer.tsx +8 -8
  134. package/src/features/billing/stripe-customer/components/details/PaymentMethodCard.tsx +11 -9
  135. package/src/features/billing/stripe-customer/components/forms/PaymentMethodEditor.tsx +4 -4
  136. package/src/features/billing/stripe-customer/components/forms/PaymentMethodForm.tsx +9 -7
  137. package/src/features/billing/stripe-invoice/components/containers/InvoicesContainer.tsx +10 -8
  138. package/src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx +34 -29
  139. package/src/features/billing/stripe-invoice/components/lists/InvoicesList.tsx +12 -9
  140. package/src/features/billing/stripe-invoice/components/widgets/InvoiceStatusBadge.tsx +9 -6
  141. package/src/features/billing/stripe-price/components/details/PriceDetails.tsx +4 -3
  142. package/src/features/billing/stripe-price/components/forms/PriceArchiver.tsx +3 -1
  143. package/src/features/billing/stripe-price/components/forms/PriceEditor.tsx +3 -1
  144. package/src/features/billing/stripe-price/hooks/useStripePriceTableStructure.tsx +6 -5
  145. package/src/features/billing/stripe-promotion-code/components/PromoCodeInput.tsx +12 -7
  146. package/src/features/billing/stripe-promotion-code/data/stripe-promotion-code.service.ts +3 -1
  147. package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +10 -6
  148. package/src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx +44 -29
  149. package/src/features/billing/stripe-subscription/components/forms/CancelSubscriptionDialog.tsx +14 -11
  150. package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +20 -17
  151. package/src/features/billing/stripe-subscription/components/widgets/IntervalToggle.tsx +4 -2
  152. package/src/features/billing/stripe-subscription/components/widgets/PricingCard.tsx +16 -7
  153. package/src/features/billing/stripe-subscription/components/widgets/ProductPricingList.tsx +3 -1
  154. package/src/features/billing/stripe-subscription/components/widgets/ProductPricingRow.tsx +3 -1
  155. package/src/features/billing/stripe-subscription/components/widgets/ProrationPreview.tsx +12 -7
  156. package/src/features/billing/stripe-subscription/components/widgets/SubscriptionConfirmation.tsx +11 -8
  157. package/src/features/billing/stripe-subscription/components/widgets/SubscriptionStatusBadge.tsx +13 -10
  158. package/src/features/billing/stripe-subscription/components/wizards/SubscriptionWizard.tsx +8 -6
  159. package/src/features/billing/stripe-subscription/components/wizards/WizardProgressIndicator.tsx +7 -4
  160. package/src/features/billing/stripe-subscription/components/wizards/WizardStepPaymentMethod.tsx +4 -2
  161. package/src/features/billing/stripe-subscription/components/wizards/WizardStepPlanSelection.tsx +3 -1
  162. package/src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx +37 -28
  163. package/src/features/billing/stripe-subscription/hooks/useConfirmSubscriptionPayment.ts +9 -7
  164. package/src/features/billing/stripe-subscription/hooks/useSubscriptionWizard.ts +20 -9
  165. package/src/features/billing/stripe-usage/components/containers/UsageContainer.tsx +6 -6
  166. package/src/features/billing/stripe-usage/components/details/UsageSummaryCard.tsx +24 -9
  167. package/src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx +16 -12
  168. package/src/features/company/components/details/TokenStatusIndicator.tsx +7 -5
  169. package/src/features/company/components/forms/CompanyEditor.tsx +2 -2
  170. package/src/features/help/components/HelpArticleBody.tsx +1 -1
  171. package/src/features/help/components/HelpHeader.tsx +1 -1
  172. package/src/features/help/components/HelpSideNav.tsx +1 -1
  173. package/src/features/help/i18n-keys.ts +2 -0
  174. package/src/features/notification/components/common/NotificationErrorBoundary.tsx +17 -12
  175. package/src/features/notification/components/containers/NotificationsListContainer.tsx +4 -2
  176. package/src/features/notification/components/notifications/Notification.tsx +6 -3
  177. package/src/features/notification/contexts/NotificationContext.tsx +9 -4
  178. package/src/features/notification/contexts/__tests__/NotificationContext.spec.tsx +13 -0
  179. package/src/features/notification/hooks/useNotificationTableStructure.tsx +4 -2
  180. package/src/features/oauth/components/OAuthClientCard.tsx +13 -7
  181. package/src/features/oauth/components/OAuthClientDetail.tsx +34 -30
  182. package/src/features/oauth/components/OAuthClientForm.tsx +24 -24
  183. package/src/features/oauth/components/OAuthClientList.tsx +10 -6
  184. package/src/features/oauth/components/OAuthClientSecretDisplay.tsx +10 -8
  185. package/src/features/oauth/components/OAuthRedirectUriInput.tsx +9 -13
  186. package/src/features/oauth/components/OAuthScopeSelector.tsx +15 -6
  187. package/src/features/oauth/components/__tests__/OAuthClientForm.spec.tsx +11 -9
  188. package/src/features/oauth/components/consent/OAuthScopeList.tsx +4 -2
  189. package/src/features/oauth/hooks/__tests__/useOAuthScopeText.spec.ts +30 -0
  190. package/src/features/oauth/hooks/index.ts +1 -0
  191. package/src/features/oauth/hooks/useOAuthClient.ts +11 -5
  192. package/src/features/oauth/hooks/useOAuthClients.ts +9 -3
  193. package/src/features/oauth/hooks/useOAuthConsent.ts +11 -5
  194. package/src/features/oauth/hooks/useOAuthScopeText.ts +33 -0
  195. package/src/features/rbac/components/RbacByRoleContainer.tsx +7 -6
  196. package/src/features/rbac/components/RbacContainer.tsx +7 -6
  197. package/src/features/rbac/contexts/RbacContext.tsx +3 -3
  198. package/src/features/user/components/containers/UserContainer.tsx +3 -1
  199. package/src/features/user/data/__tests__/user.spec.ts +66 -0
  200. package/src/features/user/data/user.interface.ts +2 -0
  201. package/src/features/user/data/user.service.ts +9 -0
  202. package/src/features/user/data/user.ts +7 -0
  203. package/src/features/waitlist/components/forms/WaitlistForm.tsx +1 -1
  204. package/src/features/waitlist/components/lists/WaitlistList.tsx +1 -1
  205. package/src/i18n/__tests__/{config.test.ts → config.spec.ts} +21 -1
  206. package/src/i18n/config.ts +13 -0
  207. package/src/i18n/index.ts +1 -0
  208. package/src/shadcnui/custom/multi-select.tsx +47 -14
  209. package/src/shadcnui/custom/multiple-selector.tsx +14 -2
  210. package/src/shadcnui/ui/__tests__/{confirm-dialog.test.tsx → confirm-dialog.spec.tsx} +1 -1
  211. package/src/shadcnui/ui/__tests__/{cursor-controls.test.tsx → cursor-controls.spec.tsx} +1 -1
  212. package/src/shadcnui/ui/__tests__/{cursor-menu-items.test.tsx → cursor-menu-items.spec.tsx} +1 -1
  213. package/src/shadcnui/ui/__tests__/{empty-state.test.tsx → empty-state.spec.tsx} +1 -1
  214. package/src/shadcnui/ui/__tests__/{spinner.test.tsx → spinner.spec.tsx} +1 -1
  215. package/src/shadcnui/ui/__tests__/use-ui-text.spec.tsx +76 -0
  216. package/src/shadcnui/ui/breadcrumb.tsx +9 -2
  217. package/src/shadcnui/ui/carousel.tsx +15 -4
  218. package/src/shadcnui/ui/dialog.tsx +15 -2
  219. package/src/shadcnui/ui/sheet.tsx +6 -1
  220. package/src/shadcnui/ui/sidebar.tsx +33 -7
  221. package/src/shadcnui/ui/spinner.tsx +6 -1
  222. package/src/shadcnui/ui/use-ui-text.ts +49 -0
  223. package/src/utils/__tests__/{date-formatter.test.ts → date-formatter.spec.ts} +24 -1
  224. package/src/utils/date-formatter.ts +16 -0
  225. package/src/utils/index.ts +1 -1
  226. package/dist/BlockNoteEditor-BENYTTCZ.js.map +0 -1
  227. package/dist/BlockNoteEditor-VOYKZOP5.mjs.map +0 -1
  228. package/dist/chunk-4BZJ4LAB.js.map +0 -1
  229. package/dist/chunk-6ISF5KNQ.mjs.map +0 -1
  230. package/dist/chunk-ORU7KLCY.js.map +0 -1
  231. package/dist/chunk-ZZ6E33FO.mjs.map +0 -1
  232. /package/dist/{BlockNoteViewer-Y2ZM4ESA.mjs.map → BlockNoteViewer-MDPO6BXN.mjs.map} +0 -0
  233. /package/dist/{chunk-46S3KPLU.mjs.map → chunk-ILFFC6BG.mjs.map} +0 -0
  234. /package/dist/{chunk-HZVVRIJQ.mjs.map → chunk-IUS2RHCX.mjs.map} +0 -0
  235. /package/dist/{chunk-ZO3QQ5CQ.mjs.map → chunk-MQDR6MEE.mjs.map} +0 -0
  236. /package/scripts/{check-rtl-classes.test.ts → check-rtl-classes.spec.ts} +0 -0
  237. /package/src/client/__tests__/{JsonApiClient.test.ts → JsonApiClient.spec.ts} +0 -0
  238. /package/src/client/__tests__/{request.test.ts → request.spec.ts} +0 -0
  239. /package/src/client/hooks/__tests__/{useJsonApiGet.test.tsx → useJsonApiGet.spec.tsx} +0 -0
  240. /package/src/client/hooks/__tests__/{useJsonApiMutation.test.tsx → useJsonApiMutation.spec.tsx} +0 -0
  241. /package/src/client/hooks/__tests__/{useRehydration.test.ts → useRehydration.spec.ts} +0 -0
  242. /package/src/components/editors/__tests__/{BlockNoteEditorMentionInlineContent.test.ts → BlockNoteEditorMentionInlineContent.spec.ts} +0 -0
  243. /package/src/components/forms/__tests__/{CommonEditorDiscardDialog.test.tsx → CommonEditorDiscardDialog.spec.tsx} +0 -0
  244. /package/src/components/forms/__tests__/{EditorSheet.test.tsx → EditorSheet.spec.tsx} +0 -0
  245. /package/src/components/forms/__tests__/{FormCheckbox.test.tsx → FormCheckbox.spec.tsx} +0 -0
  246. /package/src/components/forms/__tests__/{FormDate.test.tsx → FormDate.spec.tsx} +0 -0
  247. /package/src/components/forms/__tests__/{FormInput.test.tsx → FormInput.spec.tsx} +0 -0
  248. /package/src/components/forms/__tests__/{FormSelect.test.tsx → FormSelect.spec.tsx} +0 -0
  249. /package/src/components/forms/__tests__/{useEditorDialog.test.ts → useEditorDialog.spec.ts} +0 -0
  250. /package/src/components/grids/__tests__/{ContentListGrid.test.tsx → ContentListGrid.spec.tsx} +0 -0
  251. /package/src/components/tables/__tests__/{ContentListTable.test.tsx → ContentListTable.rendering.spec.tsx} +0 -0
  252. /package/src/contexts/__tests__/{DirectionContext.test.tsx → DirectionContext.spec.tsx} +0 -0
  253. /package/src/contexts/__tests__/{SessionContext.test.tsx → SessionContext.spec.tsx} +0 -0
  254. /package/src/contexts/__tests__/{SocketContext.session.test.tsx → SocketContext.session.spec.tsx} +0 -0
  255. /package/src/core/abstracts/__tests__/{AbstractService.locale.test.ts → AbstractService.locale.spec.ts} +0 -0
  256. /package/src/core/endpoint/__tests__/{EndpointCreator.test.ts → EndpointCreator.spec.ts} +0 -0
  257. /package/src/core/factories/__tests__/{JsonApiDataFactory.test.ts → JsonApiDataFactory.spec.ts} +0 -0
  258. /package/src/core/factories/__tests__/{RehydrationFactory.test.ts → RehydrationFactory.spec.ts} +0 -0
  259. /package/src/core/registry/__tests__/{DataClassRegistry.test.ts → DataClassRegistry.spec.ts} +0 -0
  260. /package/src/core/registry/__tests__/{ModuleRegistrar.test.ts → ModuleRegistrar.spec.ts} +0 -0
  261. /package/src/core/registry/__tests__/{viewportStore.test.ts → viewportStore.spec.ts} +0 -0
  262. /package/src/core/utils/__tests__/{translateResponse.test.ts → translateResponse.spec.ts} +0 -0
  263. /package/src/features/ai-connection/data/__tests__/{ai-connection.test.ts → ai-connection.spec.ts} +0 -0
  264. /package/src/features/company/data/{company.test.ts → company.spec.ts} +0 -0
  265. /package/src/features/company/hooks/{useSubscriptionStatus.test.ts → useSubscriptionStatus.spec.ts} +0 -0
  266. /package/src/hooks/__tests__/{useDataListRetriever.test.ts → useDataListRetriever.spec.ts} +0 -0
  267. /package/src/hooks/__tests__/{useDebounce.test.ts → useDebounce.spec.ts} +0 -0
  268. /package/src/hooks/__tests__/{useSocket.render.test.ts → useSocket.render.spec.ts} +0 -0
  269. /package/src/lib/__tests__/{direction.test.ts → direction.spec.ts} +0 -0
  270. /package/src/next-config/__tests__/{createNextConfig.test.ts → createNextConfig.spec.ts} +0 -0
  271. /package/src/server/__tests__/{JsonApiServer.test.ts → JsonApiServer.spec.ts} +0 -0
  272. /package/src/server/__tests__/{ServerSession.read.test.ts → ServerSession.read.spec.ts} +0 -0
  273. /package/src/server/__tests__/{cache.test.ts → cache.spec.ts} +0 -0
  274. /package/src/server/__tests__/{cachedGet.test.ts → cachedGet.spec.ts} +0 -0
  275. /package/src/server/__tests__/{request.test.ts → request.spec.ts} +0 -0
  276. /package/src/shadcnui/ui/__tests__/{sidebar.menu-skeleton.test.tsx → sidebar.menu-skeleton.spec.tsx} +0 -0
  277. /package/src/shadcnui/ui/__tests__/{sidebar.session.test.tsx → sidebar.session.spec.tsx} +0 -0
  278. /package/src/unified/__tests__/{JsonApiGet.cache.test.ts → JsonApiGet.cache.spec.ts} +0 -0
  279. /package/src/unified/__tests__/{JsonApiRequest.test.ts → JsonApiRequest.spec.ts} +0 -0
  280. /package/src/utils/__tests__/{exists.test.ts → exists.spec.ts} +0 -0
  281. /package/src/utils/__tests__/{italian-validators.test.ts → italian-validators.spec.ts} +0 -0
  282. /package/src/utils/__tests__/{map-thenable.test.ts → map-thenable.spec.ts} +0 -0
  283. /package/src/utils/__tests__/{use-mobile.test.tsx → use-mobile.spec.tsx} +0 -0
  284. /package/src/utils/{cn.test.ts → cn.spec.ts} +0 -0
  285. /package/src/utils/{isRemoteImageSrc.test.ts → isRemoteImageSrc.spec.ts} +0 -0
@@ -8,7 +8,12 @@ import { usePageUrlGenerator } from "../../../hooks";
8
8
  import { BreadcrumbItemData } from "../../../interfaces";
9
9
  import { getRoleId } from "../../../roles";
10
10
  import { useCurrentUserContext } from "../../user/contexts";
11
- import { formatCurrency, formatInterval } from "../components/utils/currency";
11
+ import {
12
+ type BillingFormatOptions,
13
+ formatCurrency,
14
+ formatInterval,
15
+ useBillingFormatOptions,
16
+ } from "../components/utils";
12
17
  import { PriceArchiver } from "../stripe-price/components/forms/PriceArchiver";
13
18
  import PriceEditor from "../stripe-price/components/forms/PriceEditor";
14
19
  import { StripePriceInput, StripePriceInterface } from "../stripe-price/data/stripe-price.interface";
@@ -63,9 +68,15 @@ const defaultContextValue: PriceContextType = {
63
68
  productId: undefined,
64
69
  };
65
70
 
66
- /** Human label for a price: its nickname, else amount + interval. */
67
- export function priceLabel(price: StripePriceInterface): string {
68
- return price.nickname ?? `${formatCurrency(price.unitAmount, price.currency)} ${formatInterval(price)}`.trim();
71
+ /**
72
+ * Human label for a price: its nickname, else amount + interval. Pass the
73
+ * caller's `useBillingFormatOptions()` so the amount and interval follow the
74
+ * active locale; without it the label is formatted in English.
75
+ */
76
+ export function priceLabel(price: StripePriceInterface, fmt: BillingFormatOptions = {}): string {
77
+ return (
78
+ price.nickname ?? `${formatCurrency(price.unitAmount, price.currency, fmt)} ${formatInterval(price, fmt)}`.trim()
79
+ );
69
80
  }
70
81
 
71
82
  export const PriceProvider = ({
@@ -75,6 +86,7 @@ export const PriceProvider = ({
75
86
  productId: productIdProp,
76
87
  }: PriceProviderProps) => {
77
88
  const t = useTranslations();
89
+ const fmt = useBillingFormatOptions();
78
90
  const generateUrl = usePageUrlGenerator();
79
91
  const { hasRole } = useCurrentUserContext();
80
92
 
@@ -170,7 +182,7 @@ export const PriceProvider = ({
170
182
  name: price.product.name,
171
183
  href: generateUrl({ page: Modules.StripeProduct, id: price.product.id }),
172
184
  });
173
- if (price) items.push({ name: priceLabel(price) });
185
+ if (price) items.push({ name: priceLabel(price, fmt) });
174
186
  return items;
175
187
  };
176
188
 
@@ -178,7 +190,7 @@ export const PriceProvider = ({
178
190
  const response: any = { type: t("billing.admin.prices.title") };
179
191
  if (!price) return response;
180
192
 
181
- response.element = priceLabel(price);
193
+ response.element = priceLabel(price, fmt);
182
194
 
183
195
  // narr8 note: gate on hasRole ONLY. hasPermissionToModule always returns
184
196
  // false in this app, so gating an editor on it hides the editor outright.
@@ -108,3 +108,215 @@ export const BILLING_TOKENS_I18N_KEYS = [
108
108
  "billing.tokens.purchase_extra",
109
109
  "billing.tokens.upgrade_plan",
110
110
  ] as const;
111
+
112
+ /**
113
+ * The `billing.ui.*` namespace (plus `billing.title`), read by the customer-facing
114
+ * billing surfaces: dashboard, cards, subscription wizard, invoices, payment
115
+ * methods and usage. A third export because these screens are neither the admin
116
+ * catalogue above nor the token indicator.
117
+ */
118
+ export const BILLING_UI_I18N_KEYS = [
119
+ "billing.title",
120
+ "billing.ui.alert.payment_failed_description",
121
+ "billing.ui.alert.payment_failed_title",
122
+ "billing.ui.alert.trial_ending_description",
123
+ "billing.ui.alert.trial_ending_title",
124
+ "billing.ui.alert.update_payment_method",
125
+ "billing.ui.cards.customer.credit_balance",
126
+ "billing.ui.cards.customer.manage_portal",
127
+ "billing.ui.cards.customer.not_set_up",
128
+ "billing.ui.cards.customer.not_set_up_description",
129
+ "billing.ui.cards.customer.title",
130
+ "billing.ui.cards.invoices.empty_description",
131
+ "billing.ui.cards.invoices.invoice_from",
132
+ "billing.ui.cards.invoices.open_count",
133
+ "billing.ui.cards.invoices.paid_count",
134
+ "billing.ui.cards.invoices.title",
135
+ "billing.ui.cards.payment_method.add_card",
136
+ "billing.ui.cards.payment_method.empty_description",
137
+ "billing.ui.cards.payment_method.empty_title",
138
+ "billing.ui.cards.payment_method.more_cards",
139
+ "billing.ui.cards.payment_method.more_methods",
140
+ "billing.ui.cards.subscriptions.canceling",
141
+ "billing.ui.cards.subscriptions.cancels_on",
142
+ "billing.ui.cards.subscriptions.empty_description",
143
+ "billing.ui.cards.subscriptions.empty_title",
144
+ "billing.ui.cards.subscriptions.ends_on",
145
+ "billing.ui.cards.subscriptions.fallback_name",
146
+ "billing.ui.cards.subscriptions.more",
147
+ "billing.ui.cards.subscriptions.renews_on",
148
+ "billing.ui.cards.subscriptions.view_plans",
149
+ "billing.ui.cards.usage.across_meters",
150
+ "billing.ui.cards.usage.no_meters",
151
+ "billing.ui.cards.usage.no_meters_description",
152
+ "billing.ui.cards.usage.title",
153
+ "billing.ui.cards.usage.units",
154
+ "billing.ui.cards.view_all",
155
+ "billing.ui.cards.view_details",
156
+ "billing.ui.columns.actions",
157
+ "billing.ui.columns.amount",
158
+ "billing.ui.columns.date",
159
+ "billing.ui.columns.date_time",
160
+ "billing.ui.columns.description",
161
+ "billing.ui.columns.event_id",
162
+ "billing.ui.columns.invoice_number",
163
+ "billing.ui.columns.meter_event",
164
+ "billing.ui.columns.period",
165
+ "billing.ui.columns.plan",
166
+ "billing.ui.columns.quantity",
167
+ "billing.ui.columns.status",
168
+ "billing.ui.confirmation.subscribe",
169
+ "billing.ui.confirmation.title",
170
+ "billing.ui.dashboard.modal.invoices",
171
+ "billing.ui.dashboard.modal.subscriptions",
172
+ "billing.ui.dashboard.setting_up",
173
+ "billing.ui.dashboard.setup_button",
174
+ "billing.ui.dashboard.setup_description",
175
+ "billing.ui.dashboard.setup_title",
176
+ "billing.ui.interval.one_time",
177
+ "billing.ui.interval.per_day",
178
+ "billing.ui.interval.per_days",
179
+ "billing.ui.interval.per_month",
180
+ "billing.ui.interval.per_months",
181
+ "billing.ui.interval.per_week",
182
+ "billing.ui.interval.per_weeks",
183
+ "billing.ui.interval.per_year",
184
+ "billing.ui.interval.per_years",
185
+ "billing.ui.invalid_date",
186
+ "billing.ui.invoice_status.open",
187
+ "billing.ui.invoice_status.paid",
188
+ "billing.ui.invoice_status.uncollectible",
189
+ "billing.ui.invoice_status.void",
190
+ "billing.ui.invoice.amount_due",
191
+ "billing.ui.invoice.amount_paid",
192
+ "billing.ui.invoice.attempt_count",
193
+ "billing.ui.invoice.billing_period",
194
+ "billing.ui.invoice.download_pdf",
195
+ "billing.ui.invoice.due_date",
196
+ "billing.ui.invoice.line_items",
197
+ "billing.ui.invoice.paid_date",
198
+ "billing.ui.invoice.retry_payment",
199
+ "billing.ui.invoice.subtotal",
200
+ "billing.ui.invoice.tax",
201
+ "billing.ui.invoice.title",
202
+ "billing.ui.invoice.total",
203
+ "billing.ui.invoice.view_in_stripe",
204
+ "billing.ui.invoices.empty_description",
205
+ "billing.ui.invoices.empty_title",
206
+ "billing.ui.invoices.filter_all",
207
+ "billing.ui.invoices.loading",
208
+ "billing.ui.labels.plan",
209
+ "billing.ui.labels.status",
210
+ "billing.ui.not_available",
211
+ "billing.ui.payment_confirm.errors.failed",
212
+ "billing.ui.payment_confirm.errors.missing_details",
213
+ "billing.ui.payment_confirm.errors.not_completed",
214
+ "billing.ui.payment_confirm.errors.not_initialized",
215
+ "billing.ui.payment_confirm.errors.requires_action",
216
+ "billing.ui.payment_confirm.errors.unexpected",
217
+ "billing.ui.payment_form.errors.add",
218
+ "billing.ui.payment_form.errors.init",
219
+ "billing.ui.payment_form.errors.unexpected",
220
+ "billing.ui.payment_form.loading",
221
+ "billing.ui.payment_form.set_default",
222
+ "billing.ui.payment_method.expires",
223
+ "billing.ui.payment_method.title",
224
+ "billing.ui.payment_methods.add",
225
+ "billing.ui.payment_methods.add_description",
226
+ "billing.ui.payment_methods.add_first",
227
+ "billing.ui.payment_methods.default",
228
+ "billing.ui.payment_methods.empty_description",
229
+ "billing.ui.payment_methods.empty_title",
230
+ "billing.ui.payment_methods.loading",
231
+ "billing.ui.payment_methods.remove_default_warning",
232
+ "billing.ui.payment_methods.remove_description",
233
+ "billing.ui.payment_methods.remove_title",
234
+ "billing.ui.payment_methods.removing",
235
+ "billing.ui.payment_methods.set_default",
236
+ "billing.ui.payment_methods.title",
237
+ "billing.ui.pricing.card_aria",
238
+ "billing.ui.pricing.current",
239
+ "billing.ui.pricing.current_plan",
240
+ "billing.ui.pricing.no_plans",
241
+ "billing.ui.pricing.options_aria",
242
+ "billing.ui.pricing.selected",
243
+ "billing.ui.pricing.standard",
244
+ "billing.ui.promo_code.apply",
245
+ "billing.ui.promo_code.duration_forever",
246
+ "billing.ui.promo_code.duration_once",
247
+ "billing.ui.promo_code.duration_repeating",
248
+ "billing.ui.promo_code.placeholder",
249
+ "billing.ui.proration.net_due_today",
250
+ "billing.ui.proration.next_invoice",
251
+ "billing.ui.proration.title",
252
+ "billing.ui.subscription.billing_amount",
253
+ "billing.ui.subscription.cancel_at_period_end",
254
+ "billing.ui.subscription.cancel.canceling",
255
+ "billing.ui.subscription.cancel.confirm",
256
+ "billing.ui.subscription.cancel.description",
257
+ "billing.ui.subscription.cancel.keep",
258
+ "billing.ui.subscription.cancel.reason",
259
+ "billing.ui.subscription.cancel.reason_placeholder",
260
+ "billing.ui.subscription.cancel.remains_active",
261
+ "billing.ui.subscription.cancel.title",
262
+ "billing.ui.subscription.change_plan",
263
+ "billing.ui.subscription.current_period",
264
+ "billing.ui.subscription.details_description",
265
+ "billing.ui.subscription.details_title",
266
+ "billing.ui.subscription.manage_portal",
267
+ "billing.ui.subscription.pause",
268
+ "billing.ui.subscription.pausing",
269
+ "billing.ui.subscription.resume",
270
+ "billing.ui.subscription.resuming",
271
+ "billing.ui.subscription.trial_ends",
272
+ "billing.ui.subscription.upgrade",
273
+ "billing.ui.subscriptions.empty_description",
274
+ "billing.ui.subscriptions.empty_title",
275
+ "billing.ui.subscriptions.loading",
276
+ "billing.ui.subscriptions.purchase_addons",
277
+ "billing.ui.subscriptions.subscribe",
278
+ "billing.ui.subscriptions.title",
279
+ "billing.ui.usage.empty_description",
280
+ "billing.ui.usage.empty_title",
281
+ "billing.ui.usage.history_empty",
282
+ "billing.ui.usage.history_title",
283
+ "billing.ui.usage.loading",
284
+ "billing.ui.usage.no_limit",
285
+ "billing.ui.usage.of_limit_used",
286
+ "billing.ui.usage.percent_used",
287
+ "billing.ui.usage.period",
288
+ "billing.ui.usage.title",
289
+ "billing.ui.wizard.addons_description",
290
+ "billing.ui.wizard.back",
291
+ "billing.ui.wizard.errors.already_subscribed",
292
+ "billing.ui.wizard.errors.invalid_promo_code",
293
+ "billing.ui.wizard.errors.payment_method_required",
294
+ "billing.ui.wizard.errors.prepare_review",
295
+ "billing.ui.wizard.errors.process_subscription",
296
+ "billing.ui.wizard.errors.validate_promo_code",
297
+ "billing.ui.wizard.change_description",
298
+ "billing.ui.wizard.change_title",
299
+ "billing.ui.wizard.next_review",
300
+ "billing.ui.wizard.payment_description",
301
+ "billing.ui.wizard.review.amount_off",
302
+ "billing.ui.wizard.review.charge_now",
303
+ "billing.ui.wizard.review.confirm_change",
304
+ "billing.ui.wizard.review.due_now",
305
+ "billing.ui.wizard.review.interval_monthly",
306
+ "billing.ui.wizard.review.interval_one_time",
307
+ "billing.ui.wizard.review.interval_yearly",
308
+ "billing.ui.wizard.review.no_payment_on_file",
309
+ "billing.ui.wizard.review.no_plan",
310
+ "billing.ui.wizard.review.payment_on_file",
311
+ "billing.ui.wizard.review.percent_off",
312
+ "billing.ui.wizard.review.processing",
313
+ "billing.ui.wizard.review.promotion_code",
314
+ "billing.ui.wizard.review.proration_description",
315
+ "billing.ui.wizard.review.proration_summary",
316
+ "billing.ui.wizard.review.selected_plan",
317
+ "billing.ui.wizard.review.subscribe_now",
318
+ "billing.ui.wizard.review.trial_upgrade",
319
+ "billing.ui.wizard.review.trial_upgrade_description",
320
+ "billing.ui.wizard.steps.select_plan",
321
+ "billing.ui.wizard.subscribe_description",
322
+ ] as const;
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
 
3
+ import { useTranslations } from "next-intl";
3
4
  import { CreditCard } from "lucide-react";
4
5
  import { useEffect, useState } from "react";
5
6
  import { Button } from "../../../../../shadcnui";
@@ -8,6 +9,7 @@ import { PaymentMethodEditor } from "../forms/PaymentMethodEditor";
8
9
  import { PaymentMethodsList } from "../lists/PaymentMethodsList";
9
10
 
10
11
  export function PaymentMethodsContainer() {
12
+ const t = useTranslations();
11
13
  const [paymentMethods, setPaymentMethods] = useState<PaymentMethodInterface[]>([]);
12
14
  const [loading, setLoading] = useState<boolean>(true);
13
15
  const [showAddPaymentMethod, setShowAddPaymentMethod] = useState<boolean>(false);
@@ -31,7 +33,7 @@ export function PaymentMethodsContainer() {
31
33
  if (loading) {
32
34
  return (
33
35
  <div className="flex h-64 items-center justify-center">
34
- <p className="text-muted-foreground">Loading payment methods...</p>
36
+ <p className="text-muted-foreground">{t("billing.ui.payment_methods.loading")}</p>
35
37
  </div>
36
38
  );
37
39
  }
@@ -42,9 +44,9 @@ export function PaymentMethodsContainer() {
42
44
  <div className="flex items-center justify-between">
43
45
  <div className="flex items-center gap-x-3">
44
46
  <CreditCard className="h-8 w-8" />
45
- <h1 className="text-primary text-3xl font-semibold">Payment Methods</h1>
47
+ <h1 className="text-primary text-3xl font-semibold">{t("billing.ui.payment_methods.title")}</h1>
46
48
  </div>
47
- <Button onClick={() => setShowAddPaymentMethod(true)}>Add Payment Method</Button>
49
+ <Button onClick={() => setShowAddPaymentMethod(true)}>{t("billing.ui.payment_methods.add")}</Button>
48
50
  </div>
49
51
 
50
52
  {/* Empty State */}
@@ -52,11 +54,9 @@ export function PaymentMethodsContainer() {
52
54
  <div className="flex flex-col items-center justify-center gap-y-4 rounded-lg border-2 border-dashed border-gray-300 bg-muted/50 p-12">
53
55
  <CreditCard className="h-16 w-16 text-muted-foreground" />
54
56
  <div className="text-center">
55
- <h3 className="mb-2 text-sm font-medium">No payment methods</h3>
56
- <p className="mb-4 text-muted-foreground">
57
- Add a payment method to enable subscriptions and secure checkout.
58
- </p>
59
- <Button onClick={() => setShowAddPaymentMethod(true)}>Add Your First Card</Button>
57
+ <h3 className="mb-2 text-sm font-medium">{t("billing.ui.payment_methods.empty_title")}</h3>
58
+ <p className="mb-4 text-muted-foreground">{t("billing.ui.payment_methods.empty_description")}</p>
59
+ <Button onClick={() => setShowAddPaymentMethod(true)}>{t("billing.ui.payment_methods.add_first")}</Button>
60
60
  </div>
61
61
  </div>
62
62
  )}
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
 
3
+ import { useTranslations } from "next-intl";
3
4
  import { MoreVertical } from "lucide-react";
4
5
  import { useEffect, useState } from "react";
5
6
  import {
@@ -37,6 +38,7 @@ const brandIcons: Record<string, string> = {
37
38
  };
38
39
 
39
40
  export function PaymentMethodCard({ paymentMethod, onUpdate }: PaymentMethodCardProps) {
41
+ const t = useTranslations();
40
42
  const [loading, setLoading] = useState<boolean>(false);
41
43
  const [customer, setCustomer] = useState<StripeCustomerInterface | null>(null);
42
44
  const [showRemoveDialog, setShowRemoveDialog] = useState<boolean>(false);
@@ -92,7 +94,7 @@ export function PaymentMethodCard({ paymentMethod, onUpdate }: PaymentMethodCard
92
94
  {/* Default Badge */}
93
95
  {isDefault && (
94
96
  <Badge variant="softGreen" className="absolute end-2 top-2">
95
- Default
97
+ {t("billing.ui.payment_methods.default")}
96
98
  </Badge>
97
99
  )}
98
100
 
@@ -117,7 +119,7 @@ export function PaymentMethodCard({ paymentMethod, onUpdate }: PaymentMethodCard
117
119
  <DropdownMenuContent align="end">
118
120
  {!isDefault && (
119
121
  <DropdownMenuItem onClick={handleSetDefault} disabled={loading}>
120
- Set as Default
122
+ {t("billing.ui.payment_methods.set_default")}
121
123
  </DropdownMenuItem>
122
124
  )}
123
125
  <DropdownMenuItem
@@ -125,7 +127,7 @@ export function PaymentMethodCard({ paymentMethod, onUpdate }: PaymentMethodCard
125
127
  disabled={loading}
126
128
  className="text-destructive"
127
129
  >
128
- Remove
130
+ {t("ui.buttons.remove")}
129
131
  </DropdownMenuItem>
130
132
  </DropdownMenuContent>
131
133
  </DropdownMenu>
@@ -135,7 +137,7 @@ export function PaymentMethodCard({ paymentMethod, onUpdate }: PaymentMethodCard
135
137
  <div className="flex flex-col gap-y-1">
136
138
  <p className="text-lg font-semibold">•••• {last4}</p>
137
139
  <p className="text-sm text-muted-foreground">
138
- Expires {String(expMonth).padStart(2, "0")}/{expYear}
140
+ {t("billing.ui.payment_method.expires", { date: `${String(expMonth).padStart(2, "0")}/${expYear}` })}
139
141
  </p>
140
142
  </div>
141
143
  </CardContent>
@@ -145,16 +147,16 @@ export function PaymentMethodCard({ paymentMethod, onUpdate }: PaymentMethodCard
145
147
  <AlertDialog open={showRemoveDialog} onOpenChange={setShowRemoveDialog}>
146
148
  <AlertDialogContent>
147
149
  <AlertDialogHeader>
148
- <AlertDialogTitle>Remove Payment Method</AlertDialogTitle>
150
+ <AlertDialogTitle>{t("billing.ui.payment_methods.remove_title")}</AlertDialogTitle>
149
151
  <AlertDialogDescription>
150
- Are you sure you want to remove this payment method? This action cannot be undone.
151
- {isDefault && " This is your default payment method."}
152
+ {t("billing.ui.payment_methods.remove_description")}
153
+ {isDefault && ` ${t("billing.ui.payment_methods.remove_default_warning")}`}
152
154
  </AlertDialogDescription>
153
155
  </AlertDialogHeader>
154
156
  <AlertDialogFooter>
155
- <AlertDialogCancel disabled={loading}>Cancel</AlertDialogCancel>
157
+ <AlertDialogCancel disabled={loading}>{t("ui.buttons.cancel")}</AlertDialogCancel>
156
158
  <AlertDialogAction onClick={handleRemove} disabled={loading} className="bg-red-600 hover:bg-red-700">
157
- {loading ? "Removing..." : "Remove"}
159
+ {loading ? t("billing.ui.payment_methods.removing") : t("ui.buttons.remove")}
158
160
  </AlertDialogAction>
159
161
  </AlertDialogFooter>
160
162
  </AlertDialogContent>
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
 
3
+ import { useTranslations } from "next-intl";
3
4
  import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "../../../../../shadcnui";
4
5
  import { PaymentMethodForm } from "./PaymentMethodForm";
5
6
 
@@ -10,6 +11,7 @@ type PaymentMethodEditorProps = {
10
11
  };
11
12
 
12
13
  export function PaymentMethodEditor({ open, onOpenChange, onSuccess }: PaymentMethodEditorProps) {
14
+ const t = useTranslations();
13
15
  const handleSuccess = () => {
14
16
  onSuccess();
15
17
  onOpenChange(false);
@@ -23,10 +25,8 @@ export function PaymentMethodEditor({ open, onOpenChange, onSuccess }: PaymentMe
23
25
  <Dialog open={open} onOpenChange={onOpenChange}>
24
26
  <DialogContent className="max-w-md">
25
27
  <DialogHeader>
26
- <DialogTitle>Add Payment Method</DialogTitle>
27
- <DialogDescription>
28
- Add a new payment method to your account. Your card information is securely processed by Stripe.
29
- </DialogDescription>
28
+ <DialogTitle>{t("billing.ui.payment_methods.add")}</DialogTitle>
29
+ <DialogDescription>{t("billing.ui.payment_methods.add_description")}</DialogDescription>
30
30
  </DialogHeader>
31
31
  {open && <PaymentMethodForm onSuccess={handleSuccess} onCancel={handleCancel} />}
32
32
  </DialogContent>
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
 
3
+ import { useTranslations } from "next-intl";
3
4
  import { CardElement, useElements, useStripe } from "@stripe/react-stripe-js";
4
5
  import { useEffect, useState } from "react";
5
6
  import { Alert, AlertDescription, Button, Checkbox, Label } from "../../../../../shadcnui";
@@ -12,6 +13,7 @@ type PaymentMethodFormProps = {
12
13
  };
13
14
 
14
15
  export function PaymentMethodForm({ onSuccess, onCancel, isLoading = false }: PaymentMethodFormProps) {
16
+ const t = useTranslations();
15
17
  const stripe = useStripe();
16
18
  const elements = useElements();
17
19
 
@@ -30,7 +32,7 @@ export function PaymentMethodForm({ onSuccess, onCancel, isLoading = false }: Pa
30
32
  setSetupIntent(intent);
31
33
  } catch (err) {
32
34
  console.error("[PaymentMethodForm] Failed to create setup intent:", err);
33
- setError("Failed to initialize payment form. Please try again.");
35
+ setError(t("billing.ui.payment_form.errors.init"));
34
36
  } finally {
35
37
  setLoading(false);
36
38
  }
@@ -67,7 +69,7 @@ export function PaymentMethodForm({ onSuccess, onCancel, isLoading = false }: Pa
67
69
 
68
70
  if (stripeError) {
69
71
  console.error("[PaymentMethodForm] Stripe error:", stripeError);
70
- setError(stripeError.message || "Failed to add payment method. Please check your card details.");
72
+ setError(stripeError.message || t("billing.ui.payment_form.errors.add"));
71
73
  setIsSubmitting(false);
72
74
  return;
73
75
  }
@@ -85,7 +87,7 @@ export function PaymentMethodForm({ onSuccess, onCancel, isLoading = false }: Pa
85
87
  onSuccess();
86
88
  } catch (err: any) {
87
89
  console.error("[PaymentMethodForm] Error:", err);
88
- setError(err.message || "An unexpected error occurred. Please try again.");
90
+ setError(err.message || t("billing.ui.payment_form.errors.unexpected"));
89
91
  } finally {
90
92
  setIsSubmitting(false);
91
93
  }
@@ -94,7 +96,7 @@ export function PaymentMethodForm({ onSuccess, onCancel, isLoading = false }: Pa
94
96
  if (loading) {
95
97
  return (
96
98
  <div className="flex items-center justify-center py-8">
97
- <p className="text-muted-foreground">Loading payment form...</p>
99
+ <p className="text-muted-foreground">{t("billing.ui.payment_form.loading")}</p>
98
100
  </div>
99
101
  );
100
102
  }
@@ -133,7 +135,7 @@ export function PaymentMethodForm({ onSuccess, onCancel, isLoading = false }: Pa
133
135
  <div className="flex items-center gap-x-2">
134
136
  <Checkbox id="setAsDefault" checked={setAsDefault} onCheckedChange={(checked) => setSetAsDefault(!!checked)} />
135
137
  <Label htmlFor="setAsDefault" className="cursor-pointer font-normal">
136
- Set as default payment method
138
+ {t("billing.ui.payment_form.set_default")}
137
139
  </Label>
138
140
  </div>
139
141
 
@@ -147,10 +149,10 @@ export function PaymentMethodForm({ onSuccess, onCancel, isLoading = false }: Pa
147
149
  {/* Action Buttons */}
148
150
  <div className="flex justify-end gap-x-2">
149
151
  <Button type="button" variant="outline" onClick={onCancel} disabled={isSubmitting || isLoading}>
150
- Cancel
152
+ {t("ui.buttons.cancel")}
151
153
  </Button>
152
154
  <Button type="submit" disabled={!stripe || isSubmitting || isLoading}>
153
- {isSubmitting ? "Processing..." : "Add Card"}
155
+ {isSubmitting ? t("billing.ui.wizard.review.processing") : t("billing.ui.cards.payment_method.add_card")}
154
156
  </Button>
155
157
  </div>
156
158
  </form>
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
 
3
+ import { useTranslations } from "next-intl";
3
4
  import { useEffect, useState } from "react";
4
5
  import { Tabs, TabsList, TabsTrigger } from "../../../../../shadcnui";
5
6
  import { InvoiceStatus, StripeInvoiceInterface } from "../../data/stripe-invoice.interface";
@@ -9,6 +10,7 @@ import { InvoicesList } from "../lists/InvoicesList";
9
10
  type StatusFilter = InvoiceStatus | "all";
10
11
 
11
12
  export function InvoicesContainer() {
13
+ const t = useTranslations();
12
14
  const [invoices, setInvoices] = useState<StripeInvoiceInterface[]>([]);
13
15
  const [loading, setLoading] = useState<boolean>(true);
14
16
  const [statusFilter, setStatusFilter] = useState<StatusFilter>("all");
@@ -40,22 +42,22 @@ export function InvoicesContainer() {
40
42
  {/* Status Filter Tabs */}
41
43
  <Tabs value={statusFilter} onValueChange={handleFilterChange}>
42
44
  <TabsList>
43
- <TabsTrigger value="all">All</TabsTrigger>
44
- <TabsTrigger value={InvoiceStatus.PAID}>Paid</TabsTrigger>
45
- <TabsTrigger value={InvoiceStatus.OPEN}>Open</TabsTrigger>
46
- <TabsTrigger value={InvoiceStatus.VOID}>Void</TabsTrigger>
47
- <TabsTrigger value={InvoiceStatus.UNCOLLECTIBLE}>Uncollectible</TabsTrigger>
45
+ <TabsTrigger value="all">{t("billing.ui.invoices.filter_all")}</TabsTrigger>
46
+ <TabsTrigger value={InvoiceStatus.PAID}>{t("billing.ui.invoice_status.paid")}</TabsTrigger>
47
+ <TabsTrigger value={InvoiceStatus.OPEN}>{t("billing.ui.invoice_status.open")}</TabsTrigger>
48
+ <TabsTrigger value={InvoiceStatus.VOID}>{t("billing.ui.invoice_status.void")}</TabsTrigger>
49
+ <TabsTrigger value={InvoiceStatus.UNCOLLECTIBLE}>{t("billing.ui.invoice_status.uncollectible")}</TabsTrigger>
48
50
  </TabsList>
49
51
  </Tabs>
50
52
 
51
53
  {/* Loading State */}
52
- {loading && <div className="text-center py-8 text-muted-foreground">Loading invoices...</div>}
54
+ {loading && <div className="text-center py-8 text-muted-foreground">{t("billing.ui.invoices.loading")}</div>}
53
55
 
54
56
  {/* Empty State */}
55
57
  {!loading && invoices.length === 0 && (
56
58
  <div className="border border-dashed border-gray-300 rounded-lg p-8 text-center">
57
- <p className="text-lg font-medium text-muted-foreground mb-2">No invoices yet</p>
58
- <p className="text-sm text-muted-foreground">Invoices will appear here after your first billing cycle</p>
59
+ <p className="text-lg font-medium text-muted-foreground mb-2">{t("billing.ui.invoices.empty_title")}</p>
60
+ <p className="text-sm text-muted-foreground">{t("billing.ui.invoices.empty_description")}</p>
59
61
  </div>
60
62
  )}
61
63