@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.
- package/dist/{AssistantMessageInterface-CubxuBIJ.d.ts → AssistantMessageInterface-DHJJO_Z_.d.ts} +1 -1
- package/dist/{AssistantMessageInterface-sHjI2zPN.d.mts → AssistantMessageInterface-S7oyERTT.d.mts} +1 -1
- package/dist/{BlockNoteEditor-VOYKZOP5.mjs → BlockNoteEditor-HXAHDJA7.mjs} +34 -27
- package/dist/BlockNoteEditor-HXAHDJA7.mjs.map +1 -0
- package/dist/{BlockNoteEditor-BENYTTCZ.js → BlockNoteEditor-LLCZDFLZ.js} +50 -43
- package/dist/BlockNoteEditor-LLCZDFLZ.js.map +1 -0
- package/dist/{BlockNoteViewer-USLR4Y7C.js → BlockNoteViewer-77CCTC2U.js} +3 -3
- package/dist/{BlockNoteViewer-USLR4Y7C.js.map → BlockNoteViewer-77CCTC2U.js.map} +1 -1
- package/dist/{BlockNoteViewer-Y2ZM4ESA.mjs → BlockNoteViewer-MDPO6BXN.mjs} +2 -2
- package/dist/{auth.interface-Df4vXbNz.d.mts → auth.interface-CeFCz9NU.d.mts} +1 -1
- package/dist/{auth.interface-BzI4onI_.d.ts → auth.interface-D1R7VVky.d.ts} +1 -1
- package/dist/billing/index.d.mts +40 -6
- package/dist/billing/index.d.ts +40 -6
- package/dist/billing/index.js +806 -774
- package/dist/billing/index.js.map +1 -1
- package/dist/billing/index.mjs +494 -462
- package/dist/billing/index.mjs.map +1 -1
- package/dist/{chunk-6ISF5KNQ.mjs → chunk-2VXDZRYY.mjs} +1103 -816
- package/dist/chunk-2VXDZRYY.mjs.map +1 -0
- package/dist/{chunk-4BZJ4LAB.js → chunk-4ORLPEK7.js} +136 -104
- package/dist/chunk-4ORLPEK7.js.map +1 -0
- package/dist/{chunk-ZZ6E33FO.mjs → chunk-6DRSSW5O.mjs} +36 -4
- package/dist/chunk-6DRSSW5O.mjs.map +1 -0
- package/dist/{chunk-KS6WZP2E.js → chunk-6SMJRAE3.js} +4 -4
- package/dist/{chunk-KS6WZP2E.js.map → chunk-6SMJRAE3.js.map} +1 -1
- package/dist/{chunk-WQ77CUUZ.js → chunk-GPXYQMOZ.js} +7 -7
- package/dist/{chunk-WQ77CUUZ.js.map → chunk-GPXYQMOZ.js.map} +1 -1
- package/dist/{chunk-46S3KPLU.mjs → chunk-ILFFC6BG.mjs} +2 -2
- package/dist/{chunk-HZVVRIJQ.mjs → chunk-IUS2RHCX.mjs} +2 -2
- package/dist/{chunk-F7RNBGHS.js → chunk-KJMMBUOA.js} +3 -3
- package/dist/{chunk-F7RNBGHS.js.map → chunk-KJMMBUOA.js.map} +1 -1
- package/dist/{chunk-ZO3QQ5CQ.mjs → chunk-MQDR6MEE.mjs} +2 -2
- package/dist/{chunk-ORU7KLCY.js → chunk-VDVIUDY5.js} +1445 -1158
- package/dist/chunk-VDVIUDY5.js.map +1 -0
- package/dist/client/index.d.mts +20 -6
- package/dist/client/index.d.ts +20 -6
- package/dist/client/index.js +6 -4
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +5 -3
- package/dist/components/index.d.mts +59 -21
- package/dist/components/index.d.ts +59 -21
- package/dist/components/index.js +4 -4
- package/dist/components/index.mjs +3 -3
- package/dist/{config-CEAq4Ozy.d.mts → config-BP2vyddw.d.mts} +5 -0
- package/dist/{config-DydDHCfb.d.ts → config-BhW2QrRD.d.ts} +5 -0
- package/dist/contexts/index.d.mts +4 -4
- package/dist/contexts/index.d.ts +4 -4
- package/dist/contexts/index.js +4 -4
- package/dist/contexts/index.mjs +3 -3
- package/dist/core/index.d.mts +17 -9
- package/dist/core/index.d.ts +17 -9
- package/dist/core/index.js +4 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +3 -1
- package/dist/features/analytics/index.d.mts +1 -1
- package/dist/features/analytics/index.d.ts +1 -1
- package/dist/features/analytics/index.js +122 -122
- package/dist/features/analytics/index.mjs +4 -4
- package/dist/features/analytics/server.js +4 -4
- package/dist/features/analytics/server.mjs +2 -2
- package/dist/features/help/index.d.mts +1 -1
- package/dist/features/help/index.d.ts +1 -1
- package/dist/features/help/index.js +42 -40
- package/dist/features/help/index.js.map +1 -1
- package/dist/features/help/index.mjs +8 -6
- package/dist/features/help/index.mjs.map +1 -1
- package/dist/features/tokenusage/index.js +125 -125
- package/dist/features/tokenusage/index.mjs +4 -4
- package/dist/index.d.mts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -2
- package/dist/{notification.interface-P_pNfzZQ.d.mts → notification.interface-BB6GPpZY.d.mts} +1 -1
- package/dist/{notification.interface-BNCvnVCW.d.ts → notification.interface-CmAGrijJ.d.ts} +1 -1
- package/dist/{s3.service-CbUa6a-8.d.ts → s3.service-C-4YpEMu.d.ts} +7 -3
- package/dist/{s3.service-DAp8FbuG.d.mts → s3.service-dVj-nxMl.d.mts} +7 -3
- package/dist/server/index.d.mts +4 -4
- package/dist/server/index.d.ts +4 -4
- package/dist/server/index.js +3 -3
- package/dist/server/index.mjs +2 -2
- package/dist/{useSocket-BHVIyigI.d.ts → useSocket-B0H9pmmH.d.ts} +1 -1
- package/dist/{useSocket-B9gTbuCj.d.mts → useSocket-B5RQb6v2.d.mts} +1 -1
- package/dist/{user.interface-CrmwJLYW.d.ts → user.interface-C0ZdsBZj.d.ts} +2 -0
- package/dist/{user.interface-CSaGWFbg.d.mts → user.interface-CIWGlbqM.d.mts} +2 -0
- package/package.json +1 -1
- package/src/components/containers/RoundPageContainer.tsx +3 -1
- package/src/components/containers/RoundPageContainerTitle.tsx +5 -2
- package/src/components/editors/BlockNoteEditor.tsx +31 -15
- package/src/components/editors/BlockNoteEditorAiActions.tsx +11 -7
- package/src/components/editors/__tests__/{BlockNoteEditorAiActions.test.ts → BlockNoteEditorAiActions.spec.ts} +10 -3
- package/src/components/errors/ErrorDetails.tsx +5 -2
- package/src/components/forms/CommonAssociationForm.tsx +1 -1
- package/src/components/forms/EntityMultiSelector.tsx +6 -2
- package/src/components/forms/EntitySelector.tsx +4 -1
- package/src/components/forms/FileUploader.tsx +3 -2
- package/src/components/forms/MultiFileUploader.tsx +3 -1
- package/src/components/navigations/Breadcrumb.tsx +3 -2
- package/src/components/navigations/Header.tsx +3 -1
- package/src/components/navigations/MobileNavigationBar.tsx +3 -1
- package/src/components/navigations/__tests__/Header.spec.tsx +2 -2
- package/src/components/tables/__tests__/ContentListTable.spec.tsx +1 -1
- package/src/components/tables/cells/cell.id.tsx +13 -2
- package/src/core/abstracts/AbstractService.ts +3 -3
- package/src/core/abstracts/ClientAbstractService.ts +3 -2
- package/src/features/assistant-action/components/ApprovalActionCard.tsx +74 -5
- package/src/features/assistant-action/components/__tests__/ApprovalActionCard.spec.tsx +81 -0
- package/src/features/assistant-message/components/parts/RelevanceMeter.tsx +4 -1
- package/src/features/assistant-message/components/parts/tabs/UsersTab.tsx +2 -1
- package/src/features/auth/components/buttons/GoogleSignInButton.tsx +4 -1
- package/src/features/auth/components/details/LandingComponent.tsx +1 -1
- package/src/features/auth/components/forms/ForgotPassword.tsx +1 -1
- package/src/features/auth/components/forms/Login.tsx +1 -1
- package/src/features/auth/components/forms/Register.tsx +1 -1
- package/src/features/auth/components/forms/ResetPassword.tsx +2 -2
- package/src/features/auth/components/two-factor/BackupCodesDialog.tsx +1 -1
- package/src/features/auth/components/two-factor/PasskeyButton.tsx +1 -1
- package/src/features/billing/components/cards/BillingUsageSummaryCard.tsx +21 -11
- package/src/features/billing/components/cards/CustomerInfoCard.tsx +16 -13
- package/src/features/billing/components/cards/InvoicesSummaryCard.tsx +33 -21
- package/src/features/billing/components/cards/PaymentMethodSummaryCard.tsx +20 -10
- package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +35 -22
- package/src/features/billing/components/containers/BillingDashboardContainer.tsx +24 -24
- package/src/features/billing/components/utils/__tests__/billing-formatters.spec.ts +63 -0
- package/src/features/billing/components/utils/currency.ts +67 -10
- package/src/features/billing/components/utils/date.ts +9 -4
- package/src/features/billing/components/utils/format-options.ts +20 -0
- package/src/features/billing/components/utils/index.ts +3 -1
- package/src/features/billing/components/utils/useBillingFormatOptions.ts +11 -0
- package/src/features/billing/components/widgets/BillingAlertBanner.tsx +8 -9
- package/src/features/billing/contexts/PriceContext.tsx +18 -6
- package/src/features/billing/i18n-keys.ts +212 -0
- package/src/features/billing/stripe-customer/components/containers/PaymentMethodsContainer.tsx +8 -8
- package/src/features/billing/stripe-customer/components/details/PaymentMethodCard.tsx +11 -9
- package/src/features/billing/stripe-customer/components/forms/PaymentMethodEditor.tsx +4 -4
- package/src/features/billing/stripe-customer/components/forms/PaymentMethodForm.tsx +9 -7
- package/src/features/billing/stripe-invoice/components/containers/InvoicesContainer.tsx +10 -8
- package/src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx +34 -29
- package/src/features/billing/stripe-invoice/components/lists/InvoicesList.tsx +12 -9
- package/src/features/billing/stripe-invoice/components/widgets/InvoiceStatusBadge.tsx +9 -6
- package/src/features/billing/stripe-price/components/details/PriceDetails.tsx +4 -3
- package/src/features/billing/stripe-price/components/forms/PriceArchiver.tsx +3 -1
- package/src/features/billing/stripe-price/components/forms/PriceEditor.tsx +3 -1
- package/src/features/billing/stripe-price/hooks/useStripePriceTableStructure.tsx +6 -5
- package/src/features/billing/stripe-promotion-code/components/PromoCodeInput.tsx +12 -7
- package/src/features/billing/stripe-promotion-code/data/stripe-promotion-code.service.ts +3 -1
- package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +10 -6
- package/src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx +44 -29
- package/src/features/billing/stripe-subscription/components/forms/CancelSubscriptionDialog.tsx +14 -11
- package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +20 -17
- package/src/features/billing/stripe-subscription/components/widgets/IntervalToggle.tsx +4 -2
- package/src/features/billing/stripe-subscription/components/widgets/PricingCard.tsx +16 -7
- package/src/features/billing/stripe-subscription/components/widgets/ProductPricingList.tsx +3 -1
- package/src/features/billing/stripe-subscription/components/widgets/ProductPricingRow.tsx +3 -1
- package/src/features/billing/stripe-subscription/components/widgets/ProrationPreview.tsx +12 -7
- package/src/features/billing/stripe-subscription/components/widgets/SubscriptionConfirmation.tsx +11 -8
- package/src/features/billing/stripe-subscription/components/widgets/SubscriptionStatusBadge.tsx +13 -10
- package/src/features/billing/stripe-subscription/components/wizards/SubscriptionWizard.tsx +8 -6
- package/src/features/billing/stripe-subscription/components/wizards/WizardProgressIndicator.tsx +7 -4
- package/src/features/billing/stripe-subscription/components/wizards/WizardStepPaymentMethod.tsx +4 -2
- package/src/features/billing/stripe-subscription/components/wizards/WizardStepPlanSelection.tsx +3 -1
- package/src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx +37 -28
- package/src/features/billing/stripe-subscription/hooks/useConfirmSubscriptionPayment.ts +9 -7
- package/src/features/billing/stripe-subscription/hooks/useSubscriptionWizard.ts +20 -9
- package/src/features/billing/stripe-usage/components/containers/UsageContainer.tsx +6 -6
- package/src/features/billing/stripe-usage/components/details/UsageSummaryCard.tsx +24 -9
- package/src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx +16 -12
- package/src/features/company/components/details/TokenStatusIndicator.tsx +7 -5
- package/src/features/company/components/forms/CompanyEditor.tsx +2 -2
- package/src/features/help/components/HelpArticleBody.tsx +1 -1
- package/src/features/help/components/HelpHeader.tsx +1 -1
- package/src/features/help/components/HelpSideNav.tsx +1 -1
- package/src/features/help/i18n-keys.ts +2 -0
- package/src/features/notification/components/common/NotificationErrorBoundary.tsx +17 -12
- package/src/features/notification/components/containers/NotificationsListContainer.tsx +4 -2
- package/src/features/notification/components/notifications/Notification.tsx +6 -3
- package/src/features/notification/contexts/NotificationContext.tsx +9 -4
- package/src/features/notification/contexts/__tests__/NotificationContext.spec.tsx +13 -0
- package/src/features/notification/hooks/useNotificationTableStructure.tsx +4 -2
- package/src/features/oauth/components/OAuthClientCard.tsx +13 -7
- package/src/features/oauth/components/OAuthClientDetail.tsx +34 -30
- package/src/features/oauth/components/OAuthClientForm.tsx +24 -24
- package/src/features/oauth/components/OAuthClientList.tsx +10 -6
- package/src/features/oauth/components/OAuthClientSecretDisplay.tsx +10 -8
- package/src/features/oauth/components/OAuthRedirectUriInput.tsx +9 -13
- package/src/features/oauth/components/OAuthScopeSelector.tsx +15 -6
- package/src/features/oauth/components/__tests__/OAuthClientForm.spec.tsx +11 -9
- package/src/features/oauth/components/consent/OAuthScopeList.tsx +4 -2
- package/src/features/oauth/hooks/__tests__/useOAuthScopeText.spec.ts +30 -0
- package/src/features/oauth/hooks/index.ts +1 -0
- package/src/features/oauth/hooks/useOAuthClient.ts +11 -5
- package/src/features/oauth/hooks/useOAuthClients.ts +9 -3
- package/src/features/oauth/hooks/useOAuthConsent.ts +11 -5
- package/src/features/oauth/hooks/useOAuthScopeText.ts +33 -0
- package/src/features/rbac/components/RbacByRoleContainer.tsx +7 -6
- package/src/features/rbac/components/RbacContainer.tsx +7 -6
- package/src/features/rbac/contexts/RbacContext.tsx +3 -3
- package/src/features/user/components/containers/UserContainer.tsx +3 -1
- package/src/features/user/data/__tests__/user.spec.ts +66 -0
- package/src/features/user/data/user.interface.ts +2 -0
- package/src/features/user/data/user.service.ts +9 -0
- package/src/features/user/data/user.ts +7 -0
- package/src/features/waitlist/components/forms/WaitlistForm.tsx +1 -1
- package/src/features/waitlist/components/lists/WaitlistList.tsx +1 -1
- package/src/i18n/__tests__/{config.test.ts → config.spec.ts} +21 -1
- package/src/i18n/config.ts +13 -0
- package/src/i18n/index.ts +1 -0
- package/src/shadcnui/custom/multi-select.tsx +47 -14
- package/src/shadcnui/custom/multiple-selector.tsx +14 -2
- package/src/shadcnui/ui/__tests__/{confirm-dialog.test.tsx → confirm-dialog.spec.tsx} +1 -1
- package/src/shadcnui/ui/__tests__/{cursor-controls.test.tsx → cursor-controls.spec.tsx} +1 -1
- package/src/shadcnui/ui/__tests__/{cursor-menu-items.test.tsx → cursor-menu-items.spec.tsx} +1 -1
- package/src/shadcnui/ui/__tests__/{empty-state.test.tsx → empty-state.spec.tsx} +1 -1
- package/src/shadcnui/ui/__tests__/{spinner.test.tsx → spinner.spec.tsx} +1 -1
- package/src/shadcnui/ui/__tests__/use-ui-text.spec.tsx +76 -0
- package/src/shadcnui/ui/breadcrumb.tsx +9 -2
- package/src/shadcnui/ui/carousel.tsx +15 -4
- package/src/shadcnui/ui/dialog.tsx +15 -2
- package/src/shadcnui/ui/sheet.tsx +6 -1
- package/src/shadcnui/ui/sidebar.tsx +33 -7
- package/src/shadcnui/ui/spinner.tsx +6 -1
- package/src/shadcnui/ui/use-ui-text.ts +49 -0
- package/src/utils/__tests__/{date-formatter.test.ts → date-formatter.spec.ts} +24 -1
- package/src/utils/date-formatter.ts +16 -0
- package/src/utils/index.ts +1 -1
- package/dist/BlockNoteEditor-BENYTTCZ.js.map +0 -1
- package/dist/BlockNoteEditor-VOYKZOP5.mjs.map +0 -1
- package/dist/chunk-4BZJ4LAB.js.map +0 -1
- package/dist/chunk-6ISF5KNQ.mjs.map +0 -1
- package/dist/chunk-ORU7KLCY.js.map +0 -1
- package/dist/chunk-ZZ6E33FO.mjs.map +0 -1
- /package/dist/{BlockNoteViewer-Y2ZM4ESA.mjs.map → BlockNoteViewer-MDPO6BXN.mjs.map} +0 -0
- /package/dist/{chunk-46S3KPLU.mjs.map → chunk-ILFFC6BG.mjs.map} +0 -0
- /package/dist/{chunk-HZVVRIJQ.mjs.map → chunk-IUS2RHCX.mjs.map} +0 -0
- /package/dist/{chunk-ZO3QQ5CQ.mjs.map → chunk-MQDR6MEE.mjs.map} +0 -0
- /package/scripts/{check-rtl-classes.test.ts → check-rtl-classes.spec.ts} +0 -0
- /package/src/client/__tests__/{JsonApiClient.test.ts → JsonApiClient.spec.ts} +0 -0
- /package/src/client/__tests__/{request.test.ts → request.spec.ts} +0 -0
- /package/src/client/hooks/__tests__/{useJsonApiGet.test.tsx → useJsonApiGet.spec.tsx} +0 -0
- /package/src/client/hooks/__tests__/{useJsonApiMutation.test.tsx → useJsonApiMutation.spec.tsx} +0 -0
- /package/src/client/hooks/__tests__/{useRehydration.test.ts → useRehydration.spec.ts} +0 -0
- /package/src/components/editors/__tests__/{BlockNoteEditorMentionInlineContent.test.ts → BlockNoteEditorMentionInlineContent.spec.ts} +0 -0
- /package/src/components/forms/__tests__/{CommonEditorDiscardDialog.test.tsx → CommonEditorDiscardDialog.spec.tsx} +0 -0
- /package/src/components/forms/__tests__/{EditorSheet.test.tsx → EditorSheet.spec.tsx} +0 -0
- /package/src/components/forms/__tests__/{FormCheckbox.test.tsx → FormCheckbox.spec.tsx} +0 -0
- /package/src/components/forms/__tests__/{FormDate.test.tsx → FormDate.spec.tsx} +0 -0
- /package/src/components/forms/__tests__/{FormInput.test.tsx → FormInput.spec.tsx} +0 -0
- /package/src/components/forms/__tests__/{FormSelect.test.tsx → FormSelect.spec.tsx} +0 -0
- /package/src/components/forms/__tests__/{useEditorDialog.test.ts → useEditorDialog.spec.ts} +0 -0
- /package/src/components/grids/__tests__/{ContentListGrid.test.tsx → ContentListGrid.spec.tsx} +0 -0
- /package/src/components/tables/__tests__/{ContentListTable.test.tsx → ContentListTable.rendering.spec.tsx} +0 -0
- /package/src/contexts/__tests__/{DirectionContext.test.tsx → DirectionContext.spec.tsx} +0 -0
- /package/src/contexts/__tests__/{SessionContext.test.tsx → SessionContext.spec.tsx} +0 -0
- /package/src/contexts/__tests__/{SocketContext.session.test.tsx → SocketContext.session.spec.tsx} +0 -0
- /package/src/core/abstracts/__tests__/{AbstractService.locale.test.ts → AbstractService.locale.spec.ts} +0 -0
- /package/src/core/endpoint/__tests__/{EndpointCreator.test.ts → EndpointCreator.spec.ts} +0 -0
- /package/src/core/factories/__tests__/{JsonApiDataFactory.test.ts → JsonApiDataFactory.spec.ts} +0 -0
- /package/src/core/factories/__tests__/{RehydrationFactory.test.ts → RehydrationFactory.spec.ts} +0 -0
- /package/src/core/registry/__tests__/{DataClassRegistry.test.ts → DataClassRegistry.spec.ts} +0 -0
- /package/src/core/registry/__tests__/{ModuleRegistrar.test.ts → ModuleRegistrar.spec.ts} +0 -0
- /package/src/core/registry/__tests__/{viewportStore.test.ts → viewportStore.spec.ts} +0 -0
- /package/src/core/utils/__tests__/{translateResponse.test.ts → translateResponse.spec.ts} +0 -0
- /package/src/features/ai-connection/data/__tests__/{ai-connection.test.ts → ai-connection.spec.ts} +0 -0
- /package/src/features/company/data/{company.test.ts → company.spec.ts} +0 -0
- /package/src/features/company/hooks/{useSubscriptionStatus.test.ts → useSubscriptionStatus.spec.ts} +0 -0
- /package/src/hooks/__tests__/{useDataListRetriever.test.ts → useDataListRetriever.spec.ts} +0 -0
- /package/src/hooks/__tests__/{useDebounce.test.ts → useDebounce.spec.ts} +0 -0
- /package/src/hooks/__tests__/{useSocket.render.test.ts → useSocket.render.spec.ts} +0 -0
- /package/src/lib/__tests__/{direction.test.ts → direction.spec.ts} +0 -0
- /package/src/next-config/__tests__/{createNextConfig.test.ts → createNextConfig.spec.ts} +0 -0
- /package/src/server/__tests__/{JsonApiServer.test.ts → JsonApiServer.spec.ts} +0 -0
- /package/src/server/__tests__/{ServerSession.read.test.ts → ServerSession.read.spec.ts} +0 -0
- /package/src/server/__tests__/{cache.test.ts → cache.spec.ts} +0 -0
- /package/src/server/__tests__/{cachedGet.test.ts → cachedGet.spec.ts} +0 -0
- /package/src/server/__tests__/{request.test.ts → request.spec.ts} +0 -0
- /package/src/shadcnui/ui/__tests__/{sidebar.menu-skeleton.test.tsx → sidebar.menu-skeleton.spec.tsx} +0 -0
- /package/src/shadcnui/ui/__tests__/{sidebar.session.test.tsx → sidebar.session.spec.tsx} +0 -0
- /package/src/unified/__tests__/{JsonApiGet.cache.test.ts → JsonApiGet.cache.spec.ts} +0 -0
- /package/src/unified/__tests__/{JsonApiRequest.test.ts → JsonApiRequest.spec.ts} +0 -0
- /package/src/utils/__tests__/{exists.test.ts → exists.spec.ts} +0 -0
- /package/src/utils/__tests__/{italian-validators.test.ts → italian-validators.spec.ts} +0 -0
- /package/src/utils/__tests__/{map-thenable.test.ts → map-thenable.spec.ts} +0 -0
- /package/src/utils/__tests__/{use-mobile.test.tsx → use-mobile.spec.tsx} +0 -0
- /package/src/utils/{cn.test.ts → cn.spec.ts} +0 -0
- /package/src/utils/{isRemoteImageSrc.test.ts → isRemoteImageSrc.spec.ts} +0 -0
package/dist/billing/index.mjs
CHANGED
|
@@ -58,19 +58,23 @@ import {
|
|
|
58
58
|
TabsTrigger,
|
|
59
59
|
errorToast,
|
|
60
60
|
formatCurrency,
|
|
61
|
+
formatDate,
|
|
62
|
+
formatFixed,
|
|
61
63
|
formatInterval,
|
|
64
|
+
useBillingFormatOptions,
|
|
62
65
|
useCurrentUserContext,
|
|
63
66
|
useDataListRetriever,
|
|
64
67
|
usePageUrlGenerator
|
|
65
|
-
} from "../chunk-
|
|
68
|
+
} from "../chunk-2VXDZRYY.mjs";
|
|
66
69
|
import {
|
|
67
70
|
getStripePublishableKey
|
|
68
|
-
} from "../chunk-
|
|
71
|
+
} from "../chunk-MQDR6MEE.mjs";
|
|
69
72
|
import {
|
|
70
73
|
getRoleId
|
|
71
74
|
} from "../chunk-PW42LRSL.mjs";
|
|
72
75
|
import {
|
|
73
76
|
FeatureService,
|
|
77
|
+
InvoiceStatus,
|
|
74
78
|
Modules,
|
|
75
79
|
StripeCustomerService,
|
|
76
80
|
StripeInvoiceService,
|
|
@@ -79,11 +83,13 @@ import {
|
|
|
79
83
|
StripePromotionCodeService,
|
|
80
84
|
StripeSubscriptionService,
|
|
81
85
|
StripeUsageService,
|
|
86
|
+
SubscriptionStatus,
|
|
82
87
|
cn,
|
|
83
88
|
rehydrate,
|
|
84
89
|
showToast,
|
|
90
|
+
useI18nLocale,
|
|
85
91
|
useI18nRouter
|
|
86
|
-
} from "../chunk-
|
|
92
|
+
} from "../chunk-6DRSSW5O.mjs";
|
|
87
93
|
import "../chunk-AUXK7QSA.mjs";
|
|
88
94
|
import "../chunk-PI56A4DG.mjs";
|
|
89
95
|
import "../chunk-V5MI7RNB.mjs";
|
|
@@ -93,8 +99,10 @@ import {
|
|
|
93
99
|
} from "../chunk-PAWJFY3S.mjs";
|
|
94
100
|
|
|
95
101
|
// src/features/billing/components/cards/SubscriptionSummaryCard.tsx
|
|
102
|
+
import { useTranslations } from "next-intl";
|
|
96
103
|
import { ChevronRight, CreditCard } from "lucide-react";
|
|
97
104
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
105
|
+
var SUBSCRIPTION_STATUSES = Object.values(SubscriptionStatus);
|
|
98
106
|
function getStatusBadgeVariant(status) {
|
|
99
107
|
switch (status) {
|
|
100
108
|
case "active" /* ACTIVE */:
|
|
@@ -110,21 +118,13 @@ function getStatusBadgeVariant(status) {
|
|
|
110
118
|
}
|
|
111
119
|
}
|
|
112
120
|
__name(getStatusBadgeVariant, "getStatusBadgeVariant");
|
|
113
|
-
function
|
|
114
|
-
return new Date(date).toLocaleDateString(void 0, {
|
|
115
|
-
year: "numeric",
|
|
116
|
-
month: "short",
|
|
117
|
-
day: "numeric"
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
__name(formatDate, "formatDate");
|
|
121
|
-
function formatPlanName(subscription) {
|
|
121
|
+
function formatPlanName(subscription, fallback) {
|
|
122
122
|
const productName = subscription.price?.product?.name || "";
|
|
123
123
|
const nickname = subscription.price?.nickname || "";
|
|
124
124
|
if (productName && nickname) {
|
|
125
125
|
return `${productName} - ${nickname}`;
|
|
126
126
|
}
|
|
127
|
-
return productName || nickname ||
|
|
127
|
+
return productName || nickname || fallback;
|
|
128
128
|
}
|
|
129
129
|
__name(formatPlanName, "formatPlanName");
|
|
130
130
|
function SubscriptionSummaryCard({
|
|
@@ -133,10 +133,12 @@ function SubscriptionSummaryCard({
|
|
|
133
133
|
error,
|
|
134
134
|
onManageClick
|
|
135
135
|
}) {
|
|
136
|
+
const t = useTranslations();
|
|
137
|
+
const fmt = useBillingFormatOptions();
|
|
136
138
|
if (loading) {
|
|
137
139
|
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
138
140
|
/* @__PURE__ */ jsxs(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
139
|
-
/* @__PURE__ */ jsx(CardTitle, { children: "
|
|
141
|
+
/* @__PURE__ */ jsx(CardTitle, { children: t("billing.ui.subscriptions.title") }),
|
|
140
142
|
/* @__PURE__ */ jsx(CreditCard, { className: "h-4 w-4 text-muted-foreground" })
|
|
141
143
|
] }),
|
|
142
144
|
/* @__PURE__ */ jsxs(CardContent, { children: [
|
|
@@ -149,7 +151,7 @@ function SubscriptionSummaryCard({
|
|
|
149
151
|
if (error) {
|
|
150
152
|
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
151
153
|
/* @__PURE__ */ jsxs(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
152
|
-
/* @__PURE__ */ jsx(CardTitle, { children: "
|
|
154
|
+
/* @__PURE__ */ jsx(CardTitle, { children: t("billing.ui.subscriptions.title") }),
|
|
153
155
|
/* @__PURE__ */ jsx(CreditCard, { className: "h-4 w-4 text-muted-foreground" })
|
|
154
156
|
] }),
|
|
155
157
|
/* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx("p", { className: "text-destructive text-xs/relaxed", children: error }) })
|
|
@@ -161,12 +163,12 @@ function SubscriptionSummaryCard({
|
|
|
161
163
|
const primarySubscription = activeSubscriptions[0];
|
|
162
164
|
return /* @__PURE__ */ jsxs(Card, { className: "cursor-pointer hover:bg-accent/50 transition-colors", onClick: onManageClick, children: [
|
|
163
165
|
/* @__PURE__ */ jsxs(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
164
|
-
/* @__PURE__ */ jsx(CardTitle, { children: "
|
|
166
|
+
/* @__PURE__ */ jsx(CardTitle, { children: t("billing.ui.subscriptions.title") }),
|
|
165
167
|
/* @__PURE__ */ jsx(CreditCard, { className: "h-4 w-4 text-muted-foreground" })
|
|
166
168
|
] }),
|
|
167
169
|
/* @__PURE__ */ jsx(CardContent, { children: subscriptions.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
168
|
-
/* @__PURE__ */ jsx("p", { className: "text-xl font-bold text-muted-foreground", children: "
|
|
169
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "
|
|
170
|
+
/* @__PURE__ */ jsx("p", { className: "text-xl font-bold text-muted-foreground", children: t("billing.ui.cards.subscriptions.empty_title") }),
|
|
171
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("billing.ui.cards.subscriptions.empty_description") }),
|
|
170
172
|
/* @__PURE__ */ jsxs(
|
|
171
173
|
Button,
|
|
172
174
|
{
|
|
@@ -178,34 +180,37 @@ function SubscriptionSummaryCard({
|
|
|
178
180
|
onManageClick();
|
|
179
181
|
},
|
|
180
182
|
children: [
|
|
181
|
-
"
|
|
183
|
+
t("billing.ui.cards.subscriptions.view_plans"),
|
|
182
184
|
/* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4 ms-1 rtl:rotate-180" })
|
|
183
185
|
]
|
|
184
186
|
}
|
|
185
187
|
)
|
|
186
188
|
] }) : primarySubscription ? /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
187
189
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
188
|
-
/* @__PURE__ */ jsx("p", { className: "text-xl font-bold", children: formatPlanName(primarySubscription) }),
|
|
190
|
+
/* @__PURE__ */ jsx("p", { className: "text-xl font-bold", children: formatPlanName(primarySubscription, t("billing.ui.cards.subscriptions.fallback_name")) }),
|
|
189
191
|
/* @__PURE__ */ jsx(
|
|
190
192
|
Badge,
|
|
191
193
|
{
|
|
192
194
|
variant: primarySubscription.cancelAtPeriodEnd ? "secondary" : getStatusBadgeVariant(primarySubscription.status),
|
|
193
|
-
children: primarySubscription.cancelAtPeriodEnd ? "
|
|
195
|
+
children: primarySubscription.cancelAtPeriodEnd ? t("billing.ui.cards.subscriptions.canceling") : SUBSCRIPTION_STATUSES.includes(primarySubscription.status) ? t(`billing.ui.subscription_status.${primarySubscription.status}`) : primarySubscription.status
|
|
194
196
|
}
|
|
195
197
|
)
|
|
196
198
|
] }),
|
|
197
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: !primarySubscription.price?.isTrial ?
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
199
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: !primarySubscription.price?.isTrial ? t("billing.ui.cards.subscriptions.ends_on", {
|
|
200
|
+
date: formatDate(primarySubscription.currentPeriodEnd, fmt)
|
|
201
|
+
}) : primarySubscription.cancelAtPeriodEnd ? t("billing.ui.cards.subscriptions.cancels_on", {
|
|
202
|
+
date: formatDate(primarySubscription.currentPeriodEnd, fmt)
|
|
203
|
+
}) : t("billing.ui.cards.subscriptions.renews_on", {
|
|
204
|
+
date: formatDate(primarySubscription.currentPeriodEnd, fmt)
|
|
205
|
+
}) }),
|
|
206
|
+
activeSubscriptions.length > 1 && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("billing.ui.cards.subscriptions.more", { count: activeSubscriptions.length - 1 }) })
|
|
203
207
|
] }) : null })
|
|
204
208
|
] });
|
|
205
209
|
}
|
|
206
210
|
__name(SubscriptionSummaryCard, "SubscriptionSummaryCard");
|
|
207
211
|
|
|
208
212
|
// src/features/billing/components/cards/PaymentMethodSummaryCard.tsx
|
|
213
|
+
import { useTranslations as useTranslations2 } from "next-intl";
|
|
209
214
|
import { Wallet, ChevronRight as ChevronRight2 } from "lucide-react";
|
|
210
215
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
211
216
|
function getCardBrandIcon(brand) {
|
|
@@ -228,10 +233,11 @@ function PaymentMethodSummaryCard({
|
|
|
228
233
|
error,
|
|
229
234
|
onManageClick
|
|
230
235
|
}) {
|
|
236
|
+
const t = useTranslations2();
|
|
231
237
|
if (loading) {
|
|
232
238
|
return /* @__PURE__ */ jsxs2(Card, { children: [
|
|
233
239
|
/* @__PURE__ */ jsxs2(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
234
|
-
/* @__PURE__ */ jsx2(CardTitle, { children: "
|
|
240
|
+
/* @__PURE__ */ jsx2(CardTitle, { children: t("billing.ui.payment_method.title") }),
|
|
235
241
|
/* @__PURE__ */ jsx2(Wallet, { className: "h-4 w-4 text-muted-foreground" })
|
|
236
242
|
] }),
|
|
237
243
|
/* @__PURE__ */ jsxs2(CardContent, { children: [
|
|
@@ -243,7 +249,7 @@ function PaymentMethodSummaryCard({
|
|
|
243
249
|
if (error) {
|
|
244
250
|
return /* @__PURE__ */ jsxs2(Card, { children: [
|
|
245
251
|
/* @__PURE__ */ jsxs2(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
246
|
-
/* @__PURE__ */ jsx2(CardTitle, { children: "
|
|
252
|
+
/* @__PURE__ */ jsx2(CardTitle, { children: t("billing.ui.payment_method.title") }),
|
|
247
253
|
/* @__PURE__ */ jsx2(Wallet, { className: "h-4 w-4 text-muted-foreground" })
|
|
248
254
|
] }),
|
|
249
255
|
/* @__PURE__ */ jsx2(CardContent, { children: /* @__PURE__ */ jsx2("p", { className: "text-destructive text-xs/relaxed", children: error }) })
|
|
@@ -252,12 +258,12 @@ function PaymentMethodSummaryCard({
|
|
|
252
258
|
const defaultMethod = paymentMethods.find((pm) => pm.id === defaultPaymentMethodId) || paymentMethods[0];
|
|
253
259
|
return /* @__PURE__ */ jsxs2(Card, { className: "cursor-pointer hover:bg-accent/50 transition-colors", onClick: onManageClick, children: [
|
|
254
260
|
/* @__PURE__ */ jsxs2(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
255
|
-
/* @__PURE__ */ jsx2(CardTitle, { children: "
|
|
261
|
+
/* @__PURE__ */ jsx2(CardTitle, { children: t("billing.ui.payment_method.title") }),
|
|
256
262
|
/* @__PURE__ */ jsx2(Wallet, { className: "h-4 w-4 text-muted-foreground" })
|
|
257
263
|
] }),
|
|
258
264
|
/* @__PURE__ */ jsx2(CardContent, { children: paymentMethods.length === 0 ? /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
259
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xl font-bold text-muted-foreground", children: "
|
|
260
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xs text-muted-foreground", children: "
|
|
265
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xl font-bold text-muted-foreground", children: t("billing.ui.cards.payment_method.empty_title") }),
|
|
266
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-muted-foreground", children: t("billing.ui.cards.payment_method.empty_description") }),
|
|
261
267
|
/* @__PURE__ */ jsxs2(
|
|
262
268
|
Button,
|
|
263
269
|
{
|
|
@@ -269,7 +275,7 @@ function PaymentMethodSummaryCard({
|
|
|
269
275
|
onManageClick();
|
|
270
276
|
},
|
|
271
277
|
children: [
|
|
272
|
-
"
|
|
278
|
+
t("billing.ui.cards.payment_method.add_card"),
|
|
273
279
|
/* @__PURE__ */ jsx2(ChevronRight2, { className: "h-4 w-4 ms-1 rtl:rotate-180" })
|
|
274
280
|
]
|
|
275
281
|
}
|
|
@@ -280,44 +286,35 @@ function PaymentMethodSummaryCard({
|
|
|
280
286
|
" ****",
|
|
281
287
|
defaultMethod.card.last4
|
|
282
288
|
] }),
|
|
283
|
-
/* @__PURE__ */
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
defaultMethod.card.expYear
|
|
288
|
-
] }),
|
|
289
|
-
paymentMethods.length > 1 && /* @__PURE__ */ jsxs2("p", { className: "text-xs text-muted-foreground", children: [
|
|
290
|
-
"+",
|
|
291
|
-
paymentMethods.length - 1,
|
|
292
|
-
" more card(s)"
|
|
293
|
-
] })
|
|
289
|
+
/* @__PURE__ */ jsx2("p", { className: "text-sm text-muted-foreground", children: t("billing.ui.payment_method.expires", {
|
|
290
|
+
date: `${String(defaultMethod.card.expMonth).padStart(2, "0")}/${defaultMethod.card.expYear}`
|
|
291
|
+
}) }),
|
|
292
|
+
paymentMethods.length > 1 && /* @__PURE__ */ jsx2("p", { className: "text-xs text-muted-foreground", children: t("billing.ui.cards.payment_method.more_cards", { count: paymentMethods.length - 1 }) })
|
|
294
293
|
] }) : /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
295
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xl font-bold", children: defaultMethod?.type || "
|
|
296
|
-
paymentMethods.length > 1 && /* @__PURE__ */
|
|
297
|
-
"+",
|
|
298
|
-
paymentMethods.length - 1,
|
|
299
|
-
" more method(s)"
|
|
300
|
-
] })
|
|
294
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xl font-bold", children: defaultMethod?.type || t("billing.ui.payment_method.title") }),
|
|
295
|
+
paymentMethods.length > 1 && /* @__PURE__ */ jsx2("p", { className: "text-xs text-muted-foreground", children: t("billing.ui.cards.payment_method.more_methods", { count: paymentMethods.length - 1 }) })
|
|
301
296
|
] }) })
|
|
302
297
|
] });
|
|
303
298
|
}
|
|
304
299
|
__name(PaymentMethodSummaryCard, "PaymentMethodSummaryCard");
|
|
305
300
|
|
|
306
301
|
// src/features/billing/components/cards/CustomerInfoCard.tsx
|
|
302
|
+
import { useTranslations as useTranslations3 } from "next-intl";
|
|
307
303
|
import { ExternalLink, User } from "lucide-react";
|
|
308
304
|
import { useState } from "react";
|
|
309
305
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
310
|
-
function formatBalance(balance, currency) {
|
|
311
|
-
if (balance === void 0 || balance === 0) return "$0.00";
|
|
306
|
+
function formatBalance(balance, currency, locale) {
|
|
312
307
|
const currencyCode = currency?.toUpperCase() || "USD";
|
|
313
|
-
const displayBalance = -balance;
|
|
314
|
-
return new Intl.NumberFormat(
|
|
308
|
+
const displayBalance = balance ? -balance : 0;
|
|
309
|
+
return new Intl.NumberFormat(locale, {
|
|
315
310
|
style: "currency",
|
|
316
311
|
currency: currencyCode
|
|
317
312
|
}).format(displayBalance / 100);
|
|
318
313
|
}
|
|
319
314
|
__name(formatBalance, "formatBalance");
|
|
320
315
|
function CustomerInfoCard({ customer, loading, error }) {
|
|
316
|
+
const t = useTranslations3();
|
|
317
|
+
const locale = useI18nLocale();
|
|
321
318
|
const [portalLoading, setPortalLoading] = useState(false);
|
|
322
319
|
const handlePortalClick = /* @__PURE__ */ __name(async (e) => {
|
|
323
320
|
e.stopPropagation();
|
|
@@ -334,7 +331,7 @@ function CustomerInfoCard({ customer, loading, error }) {
|
|
|
334
331
|
if (loading) {
|
|
335
332
|
return /* @__PURE__ */ jsxs3(Card, { children: [
|
|
336
333
|
/* @__PURE__ */ jsxs3(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
337
|
-
/* @__PURE__ */ jsx3(CardTitle, { children: "
|
|
334
|
+
/* @__PURE__ */ jsx3(CardTitle, { children: t("billing.ui.cards.customer.title") }),
|
|
338
335
|
/* @__PURE__ */ jsx3(User, { className: "h-4 w-4 text-muted-foreground" })
|
|
339
336
|
] }),
|
|
340
337
|
/* @__PURE__ */ jsxs3(CardContent, { children: [
|
|
@@ -347,7 +344,7 @@ function CustomerInfoCard({ customer, loading, error }) {
|
|
|
347
344
|
if (error) {
|
|
348
345
|
return /* @__PURE__ */ jsxs3(Card, { children: [
|
|
349
346
|
/* @__PURE__ */ jsxs3(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
350
|
-
/* @__PURE__ */ jsx3(CardTitle, { children: "
|
|
347
|
+
/* @__PURE__ */ jsx3(CardTitle, { children: t("billing.ui.cards.customer.title") }),
|
|
351
348
|
/* @__PURE__ */ jsx3(User, { className: "h-4 w-4 text-muted-foreground" })
|
|
352
349
|
] }),
|
|
353
350
|
/* @__PURE__ */ jsx3(CardContent, { children: /* @__PURE__ */ jsx3("p", { className: "text-destructive text-xs/relaxed", children: error }) })
|
|
@@ -356,29 +353,32 @@ function CustomerInfoCard({ customer, loading, error }) {
|
|
|
356
353
|
if (!customer) {
|
|
357
354
|
return /* @__PURE__ */ jsxs3(Card, { children: [
|
|
358
355
|
/* @__PURE__ */ jsxs3(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
359
|
-
/* @__PURE__ */ jsx3(CardTitle, { children: "
|
|
356
|
+
/* @__PURE__ */ jsx3(CardTitle, { children: t("billing.ui.cards.customer.title") }),
|
|
360
357
|
/* @__PURE__ */ jsx3(User, { className: "h-4 w-4 text-muted-foreground" })
|
|
361
358
|
] }),
|
|
362
359
|
/* @__PURE__ */ jsxs3(CardContent, { children: [
|
|
363
|
-
/* @__PURE__ */ jsx3("p", { className: "text-xl font-bold text-muted-foreground", children: "
|
|
364
|
-
/* @__PURE__ */ jsx3("p", { className: "text-xs text-muted-foreground", children: "
|
|
360
|
+
/* @__PURE__ */ jsx3("p", { className: "text-xl font-bold text-muted-foreground", children: t("billing.ui.cards.customer.not_set_up") }),
|
|
361
|
+
/* @__PURE__ */ jsx3("p", { className: "text-xs text-muted-foreground", children: t("billing.ui.cards.customer.not_set_up_description") })
|
|
365
362
|
] })
|
|
366
363
|
] });
|
|
367
364
|
}
|
|
368
365
|
return /* @__PURE__ */ jsxs3(Card, { children: [
|
|
369
366
|
/* @__PURE__ */ jsxs3(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
370
|
-
/* @__PURE__ */ jsx3(CardTitle, { children: "
|
|
367
|
+
/* @__PURE__ */ jsx3(CardTitle, { children: t("billing.ui.cards.customer.title") }),
|
|
371
368
|
/* @__PURE__ */ jsx3(User, { className: "h-4 w-4 text-muted-foreground" })
|
|
372
369
|
] }),
|
|
373
370
|
/* @__PURE__ */ jsx3(CardContent, { children: /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
|
|
374
371
|
customer.name && /* @__PURE__ */ jsx3("p", { className: "text-xl font-bold", children: customer.name }),
|
|
375
372
|
customer.email && /* @__PURE__ */ jsx3("p", { className: "text-sm text-muted-foreground", children: customer.email }),
|
|
376
373
|
customer.balance !== void 0 && customer.balance !== 0 && /* @__PURE__ */ jsxs3("p", { className: "text-sm", children: [
|
|
377
|
-
/* @__PURE__ */
|
|
378
|
-
|
|
374
|
+
/* @__PURE__ */ jsxs3("span", { className: "text-muted-foreground", children: [
|
|
375
|
+
t("billing.ui.cards.customer.credit_balance"),
|
|
376
|
+
" "
|
|
377
|
+
] }),
|
|
378
|
+
/* @__PURE__ */ jsx3("span", { className: customer.balance < 0 ? "text-success" : "text-destructive", children: formatBalance(customer.balance, customer.currency, locale) })
|
|
379
379
|
] }),
|
|
380
380
|
/* @__PURE__ */ jsxs3(Button, { variant: "outline", size: "sm", className: "mt-2", onClick: handlePortalClick, disabled: portalLoading, children: [
|
|
381
|
-
portalLoading ? "
|
|
381
|
+
portalLoading ? t("common.loading") : t("billing.ui.cards.customer.manage_portal"),
|
|
382
382
|
/* @__PURE__ */ jsx3(ExternalLink, { className: "h-4 w-4 ms-1" })
|
|
383
383
|
] })
|
|
384
384
|
] }) })
|
|
@@ -387,8 +387,10 @@ function CustomerInfoCard({ customer, loading, error }) {
|
|
|
387
387
|
__name(CustomerInfoCard, "CustomerInfoCard");
|
|
388
388
|
|
|
389
389
|
// src/features/billing/components/cards/InvoicesSummaryCard.tsx
|
|
390
|
+
import { useTranslations as useTranslations4 } from "next-intl";
|
|
390
391
|
import { ChevronRight as ChevronRight3, ReceiptIcon } from "lucide-react";
|
|
391
392
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
393
|
+
var INVOICE_STATUSES = Object.values(InvoiceStatus);
|
|
392
394
|
function getStatusBadgeVariant2(status) {
|
|
393
395
|
switch (status) {
|
|
394
396
|
case "paid" /* PAID */:
|
|
@@ -403,27 +405,21 @@ function getStatusBadgeVariant2(status) {
|
|
|
403
405
|
}
|
|
404
406
|
}
|
|
405
407
|
__name(getStatusBadgeVariant2, "getStatusBadgeVariant");
|
|
406
|
-
function
|
|
407
|
-
return new Date(date).toLocaleDateString(void 0, {
|
|
408
|
-
year: "numeric",
|
|
409
|
-
month: "short",
|
|
410
|
-
day: "numeric"
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
__name(formatDate2, "formatDate");
|
|
414
|
-
function formatAmount(amount, currency) {
|
|
408
|
+
function formatAmount(amount, currency, locale) {
|
|
415
409
|
const currencyCode = currency?.toUpperCase() || "USD";
|
|
416
|
-
return new Intl.NumberFormat(
|
|
410
|
+
return new Intl.NumberFormat(locale, {
|
|
417
411
|
style: "currency",
|
|
418
412
|
currency: currencyCode
|
|
419
413
|
}).format(amount / 100);
|
|
420
414
|
}
|
|
421
415
|
__name(formatAmount, "formatAmount");
|
|
422
416
|
function InvoicesSummaryCard({ invoices, loading, error, onViewAllClick }) {
|
|
417
|
+
const t = useTranslations4();
|
|
418
|
+
const fmt = useBillingFormatOptions();
|
|
423
419
|
if (loading) {
|
|
424
420
|
return /* @__PURE__ */ jsxs4(Card, { children: [
|
|
425
421
|
/* @__PURE__ */ jsxs4(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
426
|
-
/* @__PURE__ */ jsx4(CardTitle, { children: "
|
|
422
|
+
/* @__PURE__ */ jsx4(CardTitle, { children: t("billing.ui.cards.invoices.title") }),
|
|
427
423
|
/* @__PURE__ */ jsx4(ReceiptIcon, { className: "h-4 w-4 text-muted-foreground" })
|
|
428
424
|
] }),
|
|
429
425
|
/* @__PURE__ */ jsxs4(CardContent, { children: [
|
|
@@ -436,7 +432,7 @@ function InvoicesSummaryCard({ invoices, loading, error, onViewAllClick }) {
|
|
|
436
432
|
if (error) {
|
|
437
433
|
return /* @__PURE__ */ jsxs4(Card, { children: [
|
|
438
434
|
/* @__PURE__ */ jsxs4(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
439
|
-
/* @__PURE__ */ jsx4(CardTitle, { children: "
|
|
435
|
+
/* @__PURE__ */ jsx4(CardTitle, { children: t("billing.ui.cards.invoices.title") }),
|
|
440
436
|
/* @__PURE__ */ jsx4(ReceiptIcon, { className: "h-4 w-4 text-muted-foreground" })
|
|
441
437
|
] }),
|
|
442
438
|
/* @__PURE__ */ jsx4(CardContent, { children: /* @__PURE__ */ jsx4("p", { className: "text-destructive text-xs/relaxed", children: error }) })
|
|
@@ -447,29 +443,23 @@ function InvoicesSummaryCard({ invoices, loading, error, onViewAllClick }) {
|
|
|
447
443
|
const openInvoices = invoices.filter((inv) => inv.status === "open" /* OPEN */);
|
|
448
444
|
return /* @__PURE__ */ jsxs4(Card, { className: "cursor-pointer hover:bg-accent/50 transition-colors", onClick: onViewAllClick, children: [
|
|
449
445
|
/* @__PURE__ */ jsxs4(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
450
|
-
/* @__PURE__ */ jsx4(CardTitle, { children: "
|
|
446
|
+
/* @__PURE__ */ jsx4(CardTitle, { children: t("billing.ui.cards.invoices.title") }),
|
|
451
447
|
/* @__PURE__ */ jsx4(ReceiptIcon, { className: "h-4 w-4 text-muted-foreground" })
|
|
452
448
|
] }),
|
|
453
449
|
/* @__PURE__ */ jsx4(CardContent, { children: invoices.length === 0 ? /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
|
|
454
|
-
/* @__PURE__ */ jsx4("p", { className: "text-xl font-bold text-muted-foreground", children: "
|
|
455
|
-
/* @__PURE__ */ jsx4("p", { className: "text-xs text-muted-foreground", children: "
|
|
450
|
+
/* @__PURE__ */ jsx4("p", { className: "text-xl font-bold text-muted-foreground", children: t("billing.ui.invoices.empty_title") }),
|
|
451
|
+
/* @__PURE__ */ jsx4("p", { className: "text-xs text-muted-foreground", children: t("billing.ui.cards.invoices.empty_description") })
|
|
456
452
|
] }) : latestInvoice ? /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
|
|
457
453
|
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
|
|
458
|
-
/* @__PURE__ */ jsx4("p", { className: "text-xl font-bold", children: formatAmount(latestInvoice.total, latestInvoice.currency) }),
|
|
459
|
-
/* @__PURE__ */ jsx4(Badge, { variant: getStatusBadgeVariant2(latestInvoice.status), children: latestInvoice.status })
|
|
454
|
+
/* @__PURE__ */ jsx4("p", { className: "text-xl font-bold", children: formatAmount(latestInvoice.total, latestInvoice.currency, fmt.locale) }),
|
|
455
|
+
/* @__PURE__ */ jsx4(Badge, { variant: getStatusBadgeVariant2(latestInvoice.status), children: INVOICE_STATUSES.includes(latestInvoice.status) ? t(`billing.ui.invoice_status.${latestInvoice.status}`) : latestInvoice.status })
|
|
460
456
|
] }),
|
|
461
|
-
/* @__PURE__ */ jsx4("p", { className: "text-sm text-muted-foreground", children: latestInvoice.stripeInvoiceNumber ||
|
|
457
|
+
/* @__PURE__ */ jsx4("p", { className: "text-sm text-muted-foreground", children: latestInvoice.stripeInvoiceNumber || t("billing.ui.cards.invoices.invoice_from", { date: formatDate(latestInvoice.periodStart, fmt) }) }),
|
|
462
458
|
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-4 text-xs text-muted-foreground", children: [
|
|
463
|
-
paidInvoices.length > 0 && /* @__PURE__ */
|
|
464
|
-
|
|
465
|
-
" paid"
|
|
466
|
-
] }),
|
|
467
|
-
openInvoices.length > 0 && /* @__PURE__ */ jsxs4("span", { className: "text-warning", children: [
|
|
468
|
-
openInvoices.length,
|
|
469
|
-
" open"
|
|
470
|
-
] }),
|
|
459
|
+
paidInvoices.length > 0 && /* @__PURE__ */ jsx4("span", { children: t("billing.ui.cards.invoices.paid_count", { count: paidInvoices.length }) }),
|
|
460
|
+
openInvoices.length > 0 && /* @__PURE__ */ jsx4("span", { className: "text-warning", children: t("billing.ui.cards.invoices.open_count", { count: openInvoices.length }) }),
|
|
471
461
|
/* @__PURE__ */ jsxs4("span", { className: "flex items-center", children: [
|
|
472
|
-
"
|
|
462
|
+
t("billing.ui.cards.view_all"),
|
|
473
463
|
/* @__PURE__ */ jsx4(ChevronRight3, { className: "h-3 w-3 ms-1 rtl:rotate-180" })
|
|
474
464
|
] })
|
|
475
465
|
] })
|
|
@@ -479,10 +469,11 @@ function InvoicesSummaryCard({ invoices, loading, error, onViewAllClick }) {
|
|
|
479
469
|
__name(InvoicesSummaryCard, "InvoicesSummaryCard");
|
|
480
470
|
|
|
481
471
|
// src/features/billing/components/cards/BillingUsageSummaryCard.tsx
|
|
472
|
+
import { useTranslations as useTranslations5 } from "next-intl";
|
|
482
473
|
import { Activity, ChevronRight as ChevronRight4 } from "lucide-react";
|
|
483
474
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
484
|
-
function formatNumber(value) {
|
|
485
|
-
return new Intl.NumberFormat(
|
|
475
|
+
function formatNumber(value, locale) {
|
|
476
|
+
return new Intl.NumberFormat(locale, {
|
|
486
477
|
notation: "compact",
|
|
487
478
|
compactDisplay: "short"
|
|
488
479
|
}).format(value);
|
|
@@ -495,10 +486,12 @@ function BillingUsageSummaryCard({
|
|
|
495
486
|
error,
|
|
496
487
|
onViewDetailsClick
|
|
497
488
|
}) {
|
|
489
|
+
const t = useTranslations5();
|
|
490
|
+
const locale = useI18nLocale();
|
|
498
491
|
if (loading) {
|
|
499
492
|
return /* @__PURE__ */ jsxs5(Card, { children: [
|
|
500
493
|
/* @__PURE__ */ jsxs5(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
501
|
-
/* @__PURE__ */ jsx5(CardTitle, { children: "
|
|
494
|
+
/* @__PURE__ */ jsx5(CardTitle, { children: t("billing.ui.cards.usage.title") }),
|
|
502
495
|
/* @__PURE__ */ jsx5(Activity, { className: "h-4 w-4 text-muted-foreground" })
|
|
503
496
|
] }),
|
|
504
497
|
/* @__PURE__ */ jsxs5(CardContent, { children: [
|
|
@@ -510,7 +503,7 @@ function BillingUsageSummaryCard({
|
|
|
510
503
|
if (error) {
|
|
511
504
|
return /* @__PURE__ */ jsxs5(Card, { children: [
|
|
512
505
|
/* @__PURE__ */ jsxs5(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
513
|
-
/* @__PURE__ */ jsx5(CardTitle, { children: "
|
|
506
|
+
/* @__PURE__ */ jsx5(CardTitle, { children: t("billing.ui.cards.usage.title") }),
|
|
514
507
|
/* @__PURE__ */ jsx5(Activity, { className: "h-4 w-4 text-muted-foreground" })
|
|
515
508
|
] }),
|
|
516
509
|
/* @__PURE__ */ jsx5(CardContent, { children: /* @__PURE__ */ jsx5("p", { className: "text-destructive text-xs/relaxed", children: error }) })
|
|
@@ -523,29 +516,22 @@ function BillingUsageSummaryCard({
|
|
|
523
516
|
const primarySummary = primaryMeter ? summaries[primaryMeter.id] : null;
|
|
524
517
|
return /* @__PURE__ */ jsxs5(Card, { className: "cursor-pointer hover:bg-accent/50 transition-colors", onClick: onViewDetailsClick, children: [
|
|
525
518
|
/* @__PURE__ */ jsxs5(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
|
|
526
|
-
/* @__PURE__ */ jsx5(CardTitle, { children: "
|
|
519
|
+
/* @__PURE__ */ jsx5(CardTitle, { children: t("billing.ui.cards.usage.title") }),
|
|
527
520
|
/* @__PURE__ */ jsx5(Activity, { className: "h-4 w-4 text-muted-foreground" })
|
|
528
521
|
] }),
|
|
529
522
|
/* @__PURE__ */ jsx5(CardContent, { children: meters.length === 0 ? /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
|
|
530
|
-
/* @__PURE__ */ jsx5("p", { className: "text-xl font-bold text-muted-foreground", children: "
|
|
531
|
-
/* @__PURE__ */ jsx5("p", { className: "text-xs text-muted-foreground", children: "
|
|
523
|
+
/* @__PURE__ */ jsx5("p", { className: "text-xl font-bold text-muted-foreground", children: t("billing.ui.cards.usage.no_meters") }),
|
|
524
|
+
/* @__PURE__ */ jsx5("p", { className: "text-xs text-muted-foreground", children: t("billing.ui.cards.usage.no_meters_description") })
|
|
532
525
|
] }) : /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
|
|
533
|
-
/* @__PURE__ */
|
|
534
|
-
formatNumber(totalUsage),
|
|
535
|
-
" units"
|
|
536
|
-
] }),
|
|
526
|
+
/* @__PURE__ */ jsx5("p", { className: "text-xl font-bold", children: t("billing.ui.cards.usage.units", { value: formatNumber(totalUsage, locale) }) }),
|
|
537
527
|
primaryMeter && primarySummary && /* @__PURE__ */ jsxs5("p", { className: "text-sm text-muted-foreground", children: [
|
|
538
528
|
primaryMeter.displayName,
|
|
539
529
|
": ",
|
|
540
|
-
formatNumber(primarySummary.aggregatedValue)
|
|
541
|
-
] }),
|
|
542
|
-
meters.length > 1 && /* @__PURE__ */ jsxs5("p", { className: "text-xs text-muted-foreground", children: [
|
|
543
|
-
"Across ",
|
|
544
|
-
meters.length,
|
|
545
|
-
" meters"
|
|
530
|
+
formatNumber(primarySummary.aggregatedValue, locale)
|
|
546
531
|
] }),
|
|
532
|
+
meters.length > 1 && /* @__PURE__ */ jsx5("p", { className: "text-xs text-muted-foreground", children: t("billing.ui.cards.usage.across_meters", { count: meters.length }) }),
|
|
547
533
|
/* @__PURE__ */ jsxs5("span", { className: "flex items-center text-xs text-muted-foreground", children: [
|
|
548
|
-
"
|
|
534
|
+
t("billing.ui.cards.view_details"),
|
|
549
535
|
/* @__PURE__ */ jsx5(ChevronRight4, { className: "h-3 w-3 ms-1 rtl:rotate-180" })
|
|
550
536
|
] })
|
|
551
537
|
] }) })
|
|
@@ -554,19 +540,26 @@ function BillingUsageSummaryCard({
|
|
|
554
540
|
__name(BillingUsageSummaryCard, "BillingUsageSummaryCard");
|
|
555
541
|
|
|
556
542
|
// src/features/billing/components/containers/BillingDashboardContainer.tsx
|
|
543
|
+
import { useTranslations as useTranslations36 } from "next-intl";
|
|
557
544
|
import { CreditCard as CreditCard4, Loader2 as Loader23, Wallet as Wallet2 } from "lucide-react";
|
|
558
545
|
import { useSearchParams } from "next/navigation";
|
|
559
546
|
import { useCallback as useCallback4, useEffect as useEffect9, useMemo as useMemo3, useState as useState14 } from "react";
|
|
560
547
|
|
|
561
548
|
// src/features/billing/stripe-customer/components/containers/PaymentMethodsContainer.tsx
|
|
549
|
+
import { useTranslations as useTranslations9 } from "next-intl";
|
|
562
550
|
import { CreditCard as CreditCard2 } from "lucide-react";
|
|
563
551
|
import { useEffect as useEffect3, useState as useState4 } from "react";
|
|
564
552
|
|
|
553
|
+
// src/features/billing/stripe-customer/components/forms/PaymentMethodEditor.tsx
|
|
554
|
+
import { useTranslations as useTranslations7 } from "next-intl";
|
|
555
|
+
|
|
565
556
|
// src/features/billing/stripe-customer/components/forms/PaymentMethodForm.tsx
|
|
557
|
+
import { useTranslations as useTranslations6 } from "next-intl";
|
|
566
558
|
import { CardElement, useElements, useStripe } from "@stripe/react-stripe-js";
|
|
567
559
|
import { useEffect, useState as useState2 } from "react";
|
|
568
560
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
569
561
|
function PaymentMethodForm({ onSuccess, onCancel, isLoading = false }) {
|
|
562
|
+
const t = useTranslations6();
|
|
570
563
|
const stripe = useStripe();
|
|
571
564
|
const elements = useElements();
|
|
572
565
|
const [setupIntent, setSetupIntent] = useState2(null);
|
|
@@ -582,7 +575,7 @@ function PaymentMethodForm({ onSuccess, onCancel, isLoading = false }) {
|
|
|
582
575
|
setSetupIntent(intent);
|
|
583
576
|
} catch (err) {
|
|
584
577
|
console.error("[PaymentMethodForm] Failed to create setup intent:", err);
|
|
585
|
-
setError("
|
|
578
|
+
setError(t("billing.ui.payment_form.errors.init"));
|
|
586
579
|
} finally {
|
|
587
580
|
setLoading(false);
|
|
588
581
|
}
|
|
@@ -611,7 +604,7 @@ function PaymentMethodForm({ onSuccess, onCancel, isLoading = false }) {
|
|
|
611
604
|
);
|
|
612
605
|
if (stripeError) {
|
|
613
606
|
console.error("[PaymentMethodForm] Stripe error:", stripeError);
|
|
614
|
-
setError(stripeError.message || "
|
|
607
|
+
setError(stripeError.message || t("billing.ui.payment_form.errors.add"));
|
|
615
608
|
setIsSubmitting(false);
|
|
616
609
|
return;
|
|
617
610
|
}
|
|
@@ -623,13 +616,13 @@ function PaymentMethodForm({ onSuccess, onCancel, isLoading = false }) {
|
|
|
623
616
|
onSuccess();
|
|
624
617
|
} catch (err) {
|
|
625
618
|
console.error("[PaymentMethodForm] Error:", err);
|
|
626
|
-
setError(err.message || "
|
|
619
|
+
setError(err.message || t("billing.ui.payment_form.errors.unexpected"));
|
|
627
620
|
} finally {
|
|
628
621
|
setIsSubmitting(false);
|
|
629
622
|
}
|
|
630
623
|
}, "handleSubmit");
|
|
631
624
|
if (loading) {
|
|
632
|
-
return /* @__PURE__ */ jsx6("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx6("p", { className: "text-muted-foreground", children: "
|
|
625
|
+
return /* @__PURE__ */ jsx6("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx6("p", { className: "text-muted-foreground", children: t("billing.ui.payment_form.loading") }) });
|
|
633
626
|
}
|
|
634
627
|
if (!setupIntent && error) {
|
|
635
628
|
return /* @__PURE__ */ jsx6(Alert, { variant: "destructive", className: "bg-red-50 border-red-200", children: /* @__PURE__ */ jsx6(AlertDescription, { children: error }) });
|
|
@@ -656,12 +649,12 @@ function PaymentMethodForm({ onSuccess, onCancel, isLoading = false }) {
|
|
|
656
649
|
) }),
|
|
657
650
|
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-x-2", children: [
|
|
658
651
|
/* @__PURE__ */ jsx6(Checkbox, { id: "setAsDefault", checked: setAsDefault, onCheckedChange: (checked) => setSetAsDefault(!!checked) }),
|
|
659
|
-
/* @__PURE__ */ jsx6(Label, { htmlFor: "setAsDefault", className: "cursor-pointer font-normal", children: "
|
|
652
|
+
/* @__PURE__ */ jsx6(Label, { htmlFor: "setAsDefault", className: "cursor-pointer font-normal", children: t("billing.ui.payment_form.set_default") })
|
|
660
653
|
] }),
|
|
661
654
|
error && /* @__PURE__ */ jsx6(Alert, { variant: "destructive", className: "bg-red-50 border-red-200", children: /* @__PURE__ */ jsx6(AlertDescription, { children: error }) }),
|
|
662
655
|
/* @__PURE__ */ jsxs6("div", { className: "flex justify-end gap-x-2", children: [
|
|
663
|
-
/* @__PURE__ */ jsx6(Button, { type: "button", variant: "outline", onClick: onCancel, disabled: isSubmitting || isLoading, children: "
|
|
664
|
-
/* @__PURE__ */ jsx6(Button, { type: "submit", disabled: !stripe || isSubmitting || isLoading, children: isSubmitting ? "
|
|
656
|
+
/* @__PURE__ */ jsx6(Button, { type: "button", variant: "outline", onClick: onCancel, disabled: isSubmitting || isLoading, children: t("ui.buttons.cancel") }),
|
|
657
|
+
/* @__PURE__ */ jsx6(Button, { type: "submit", disabled: !stripe || isSubmitting || isLoading, children: isSubmitting ? t("billing.ui.wizard.review.processing") : t("billing.ui.cards.payment_method.add_card") })
|
|
665
658
|
] })
|
|
666
659
|
] });
|
|
667
660
|
}
|
|
@@ -670,6 +663,7 @@ __name(PaymentMethodForm, "PaymentMethodForm");
|
|
|
670
663
|
// src/features/billing/stripe-customer/components/forms/PaymentMethodEditor.tsx
|
|
671
664
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
672
665
|
function PaymentMethodEditor({ open, onOpenChange, onSuccess }) {
|
|
666
|
+
const t = useTranslations7();
|
|
673
667
|
const handleSuccess = /* @__PURE__ */ __name(() => {
|
|
674
668
|
onSuccess();
|
|
675
669
|
onOpenChange(false);
|
|
@@ -679,8 +673,8 @@ function PaymentMethodEditor({ open, onOpenChange, onSuccess }) {
|
|
|
679
673
|
}, "handleCancel");
|
|
680
674
|
return /* @__PURE__ */ jsx7(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs7(DialogContent, { className: "max-w-md", children: [
|
|
681
675
|
/* @__PURE__ */ jsxs7(DialogHeader, { children: [
|
|
682
|
-
/* @__PURE__ */ jsx7(DialogTitle, { children: "
|
|
683
|
-
/* @__PURE__ */ jsx7(DialogDescription, { children: "
|
|
676
|
+
/* @__PURE__ */ jsx7(DialogTitle, { children: t("billing.ui.payment_methods.add") }),
|
|
677
|
+
/* @__PURE__ */ jsx7(DialogDescription, { children: t("billing.ui.payment_methods.add_description") })
|
|
684
678
|
] }),
|
|
685
679
|
open && /* @__PURE__ */ jsx7(PaymentMethodForm, { onSuccess: handleSuccess, onCancel: handleCancel })
|
|
686
680
|
] }) });
|
|
@@ -688,6 +682,7 @@ function PaymentMethodEditor({ open, onOpenChange, onSuccess }) {
|
|
|
688
682
|
__name(PaymentMethodEditor, "PaymentMethodEditor");
|
|
689
683
|
|
|
690
684
|
// src/features/billing/stripe-customer/components/details/PaymentMethodCard.tsx
|
|
685
|
+
import { useTranslations as useTranslations8 } from "next-intl";
|
|
691
686
|
import { MoreVertical } from "lucide-react";
|
|
692
687
|
import { useEffect as useEffect2, useState as useState3 } from "react";
|
|
693
688
|
import { Fragment, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
@@ -698,6 +693,7 @@ var brandIcons = {
|
|
|
698
693
|
discover: "\u{1F4B3}"
|
|
699
694
|
};
|
|
700
695
|
function PaymentMethodCard({ paymentMethod, onUpdate }) {
|
|
696
|
+
const t = useTranslations8();
|
|
701
697
|
const [loading, setLoading] = useState3(false);
|
|
702
698
|
const [customer, setCustomer] = useState3(null);
|
|
703
699
|
const [showRemoveDialog, setShowRemoveDialog] = useState3(false);
|
|
@@ -742,7 +738,7 @@ function PaymentMethodCard({ paymentMethod, onUpdate }) {
|
|
|
742
738
|
}, "handleRemove");
|
|
743
739
|
return /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
744
740
|
/* @__PURE__ */ jsxs8(Card, { className: "relative", children: [
|
|
745
|
-
isDefault && /* @__PURE__ */ jsx8(Badge, { variant: "softGreen", className: "absolute end-2 top-2", children: "
|
|
741
|
+
isDefault && /* @__PURE__ */ jsx8(Badge, { variant: "softGreen", className: "absolute end-2 top-2", children: t("billing.ui.payment_methods.default") }),
|
|
746
742
|
/* @__PURE__ */ jsxs8(CardHeader, { className: "flex flex-row items-center justify-between pb-2", children: [
|
|
747
743
|
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-x-2", children: [
|
|
748
744
|
/* @__PURE__ */ jsx8("span", { className: "text-2xl", children: brandIcon }),
|
|
@@ -762,14 +758,14 @@ function PaymentMethodCard({ paymentMethod, onUpdate }) {
|
|
|
762
758
|
}
|
|
763
759
|
) }),
|
|
764
760
|
/* @__PURE__ */ jsxs8(DropdownMenuContent, { align: "end", children: [
|
|
765
|
-
!isDefault && /* @__PURE__ */ jsx8(DropdownMenuItem, { onClick: handleSetDefault, disabled: loading, children: "
|
|
761
|
+
!isDefault && /* @__PURE__ */ jsx8(DropdownMenuItem, { onClick: handleSetDefault, disabled: loading, children: t("billing.ui.payment_methods.set_default") }),
|
|
766
762
|
/* @__PURE__ */ jsx8(
|
|
767
763
|
DropdownMenuItem,
|
|
768
764
|
{
|
|
769
765
|
onClick: () => setShowRemoveDialog(true),
|
|
770
766
|
disabled: loading,
|
|
771
767
|
className: "text-destructive",
|
|
772
|
-
children: "
|
|
768
|
+
children: t("ui.buttons.remove")
|
|
773
769
|
}
|
|
774
770
|
)
|
|
775
771
|
] })
|
|
@@ -780,25 +776,20 @@ function PaymentMethodCard({ paymentMethod, onUpdate }) {
|
|
|
780
776
|
"\u2022\u2022\u2022\u2022 ",
|
|
781
777
|
last4
|
|
782
778
|
] }),
|
|
783
|
-
/* @__PURE__ */
|
|
784
|
-
"Expires ",
|
|
785
|
-
String(expMonth).padStart(2, "0"),
|
|
786
|
-
"/",
|
|
787
|
-
expYear
|
|
788
|
-
] })
|
|
779
|
+
/* @__PURE__ */ jsx8("p", { className: "text-sm text-muted-foreground", children: t("billing.ui.payment_method.expires", { date: `${String(expMonth).padStart(2, "0")}/${expYear}` }) })
|
|
789
780
|
] }) })
|
|
790
781
|
] }),
|
|
791
782
|
/* @__PURE__ */ jsx8(AlertDialog, { open: showRemoveDialog, onOpenChange: setShowRemoveDialog, children: /* @__PURE__ */ jsxs8(AlertDialogContent, { children: [
|
|
792
783
|
/* @__PURE__ */ jsxs8(AlertDialogHeader, { children: [
|
|
793
|
-
/* @__PURE__ */ jsx8(AlertDialogTitle, { children: "
|
|
784
|
+
/* @__PURE__ */ jsx8(AlertDialogTitle, { children: t("billing.ui.payment_methods.remove_title") }),
|
|
794
785
|
/* @__PURE__ */ jsxs8(AlertDialogDescription, { children: [
|
|
795
|
-
"
|
|
796
|
-
isDefault && "
|
|
786
|
+
t("billing.ui.payment_methods.remove_description"),
|
|
787
|
+
isDefault && ` ${t("billing.ui.payment_methods.remove_default_warning")}`
|
|
797
788
|
] })
|
|
798
789
|
] }),
|
|
799
790
|
/* @__PURE__ */ jsxs8(AlertDialogFooter, { children: [
|
|
800
|
-
/* @__PURE__ */ jsx8(AlertDialogCancel, { disabled: loading, children: "
|
|
801
|
-
/* @__PURE__ */ jsx8(AlertDialogAction, { onClick: handleRemove, disabled: loading, className: "bg-red-600 hover:bg-red-700", children: loading ? "
|
|
791
|
+
/* @__PURE__ */ jsx8(AlertDialogCancel, { disabled: loading, children: t("ui.buttons.cancel") }),
|
|
792
|
+
/* @__PURE__ */ jsx8(AlertDialogAction, { onClick: handleRemove, disabled: loading, className: "bg-red-600 hover:bg-red-700", children: loading ? t("billing.ui.payment_methods.removing") : t("ui.buttons.remove") })
|
|
802
793
|
] })
|
|
803
794
|
] }) })
|
|
804
795
|
] });
|
|
@@ -815,6 +806,7 @@ __name(PaymentMethodsList, "PaymentMethodsList");
|
|
|
815
806
|
// src/features/billing/stripe-customer/components/containers/PaymentMethodsContainer.tsx
|
|
816
807
|
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
817
808
|
function PaymentMethodsContainer() {
|
|
809
|
+
const t = useTranslations9();
|
|
818
810
|
const [paymentMethods, setPaymentMethods] = useState4([]);
|
|
819
811
|
const [loading, setLoading] = useState4(true);
|
|
820
812
|
const [showAddPaymentMethod, setShowAddPaymentMethod] = useState4(false);
|
|
@@ -833,22 +825,22 @@ function PaymentMethodsContainer() {
|
|
|
833
825
|
loadPaymentMethods();
|
|
834
826
|
}, []);
|
|
835
827
|
if (loading) {
|
|
836
|
-
return /* @__PURE__ */ jsx10("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx10("p", { className: "text-muted-foreground", children: "
|
|
828
|
+
return /* @__PURE__ */ jsx10("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx10("p", { className: "text-muted-foreground", children: t("billing.ui.payment_methods.loading") }) });
|
|
837
829
|
}
|
|
838
830
|
return /* @__PURE__ */ jsxs9("div", { className: "flex w-full flex-col gap-y-6", children: [
|
|
839
831
|
/* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
|
|
840
832
|
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-x-3", children: [
|
|
841
833
|
/* @__PURE__ */ jsx10(CreditCard2, { className: "h-8 w-8" }),
|
|
842
|
-
/* @__PURE__ */ jsx10("h1", { className: "text-primary text-3xl font-semibold", children: "
|
|
834
|
+
/* @__PURE__ */ jsx10("h1", { className: "text-primary text-3xl font-semibold", children: t("billing.ui.payment_methods.title") })
|
|
843
835
|
] }),
|
|
844
|
-
/* @__PURE__ */ jsx10(Button, { onClick: () => setShowAddPaymentMethod(true), children: "
|
|
836
|
+
/* @__PURE__ */ jsx10(Button, { onClick: () => setShowAddPaymentMethod(true), children: t("billing.ui.payment_methods.add") })
|
|
845
837
|
] }),
|
|
846
838
|
paymentMethods.length === 0 && /* @__PURE__ */ jsxs9("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", children: [
|
|
847
839
|
/* @__PURE__ */ jsx10(CreditCard2, { className: "h-16 w-16 text-muted-foreground" }),
|
|
848
840
|
/* @__PURE__ */ jsxs9("div", { className: "text-center", children: [
|
|
849
|
-
/* @__PURE__ */ jsx10("h3", { className: "mb-2 text-sm font-medium", children: "
|
|
850
|
-
/* @__PURE__ */ jsx10("p", { className: "mb-4 text-muted-foreground", children: "
|
|
851
|
-
/* @__PURE__ */ jsx10(Button, { onClick: () => setShowAddPaymentMethod(true), children: "
|
|
841
|
+
/* @__PURE__ */ jsx10("h3", { className: "mb-2 text-sm font-medium", children: t("billing.ui.payment_methods.empty_title") }),
|
|
842
|
+
/* @__PURE__ */ jsx10("p", { className: "mb-4 text-muted-foreground", children: t("billing.ui.payment_methods.empty_description") }),
|
|
843
|
+
/* @__PURE__ */ jsx10(Button, { onClick: () => setShowAddPaymentMethod(true), children: t("billing.ui.payment_methods.add_first") })
|
|
852
844
|
] })
|
|
853
845
|
] }),
|
|
854
846
|
paymentMethods.length > 0 && /* @__PURE__ */ jsx10(PaymentMethodsList, { paymentMethods, onUpdate: loadPaymentMethods }),
|
|
@@ -865,58 +857,46 @@ function PaymentMethodsContainer() {
|
|
|
865
857
|
__name(PaymentMethodsContainer, "PaymentMethodsContainer");
|
|
866
858
|
|
|
867
859
|
// src/features/billing/stripe-invoice/components/containers/InvoicesContainer.tsx
|
|
860
|
+
import { useTranslations as useTranslations13 } from "next-intl";
|
|
868
861
|
import { useEffect as useEffect4, useState as useState6 } from "react";
|
|
869
862
|
|
|
870
863
|
// src/features/billing/stripe-invoice/components/lists/InvoicesList.tsx
|
|
864
|
+
import { useTranslations as useTranslations12 } from "next-intl";
|
|
871
865
|
import { useState as useState5 } from "react";
|
|
872
866
|
|
|
873
|
-
// src/features/billing/components/utils/date.ts
|
|
874
|
-
function formatDate3(date) {
|
|
875
|
-
if (!date) return "N/A";
|
|
876
|
-
const dateObj = typeof date === "string" ? new Date(date) : date;
|
|
877
|
-
try {
|
|
878
|
-
return new Intl.DateTimeFormat("en-US", {
|
|
879
|
-
month: "short",
|
|
880
|
-
day: "numeric",
|
|
881
|
-
year: "numeric"
|
|
882
|
-
}).format(dateObj);
|
|
883
|
-
} catch (error) {
|
|
884
|
-
console.error("Error formatting date:", error);
|
|
885
|
-
return "Invalid Date";
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
__name(formatDate3, "formatDate");
|
|
889
|
-
|
|
890
867
|
// src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx
|
|
868
|
+
import { useTranslations as useTranslations11 } from "next-intl";
|
|
891
869
|
import { Download, ExternalLink as ExternalLink2, RefreshCw } from "lucide-react";
|
|
892
870
|
|
|
893
871
|
// src/features/billing/stripe-invoice/components/widgets/InvoiceStatusBadge.tsx
|
|
872
|
+
import { useTranslations as useTranslations10 } from "next-intl";
|
|
894
873
|
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
895
874
|
var statusConfig = {
|
|
896
875
|
["draft" /* DRAFT */]: {
|
|
897
|
-
label: "
|
|
876
|
+
label: "billing.ui.invoice_status.draft",
|
|
898
877
|
variant: "softGray"
|
|
899
878
|
},
|
|
900
879
|
["open" /* OPEN */]: {
|
|
901
|
-
label: "
|
|
880
|
+
label: "billing.ui.invoice_status.open",
|
|
902
881
|
variant: "softBlue"
|
|
903
882
|
},
|
|
904
883
|
["paid" /* PAID */]: {
|
|
905
|
-
label: "
|
|
884
|
+
label: "billing.ui.invoice_status.paid",
|
|
906
885
|
variant: "softGreen"
|
|
907
886
|
},
|
|
908
887
|
["void" /* VOID */]: {
|
|
909
|
-
label: "
|
|
888
|
+
label: "billing.ui.invoice_status.void",
|
|
910
889
|
variant: "softGray"
|
|
911
890
|
},
|
|
912
891
|
["uncollectible" /* UNCOLLECTIBLE */]: {
|
|
913
|
-
label: "
|
|
892
|
+
label: "billing.ui.invoice_status.uncollectible",
|
|
914
893
|
variant: "softRed"
|
|
915
894
|
}
|
|
916
895
|
};
|
|
917
896
|
function InvoiceStatusBadge({ status }) {
|
|
897
|
+
const t = useTranslations10();
|
|
918
898
|
const config = statusConfig[status] || statusConfig["draft" /* DRAFT */];
|
|
919
|
-
return /* @__PURE__ */ jsx11(Badge, { variant: config.variant, children: config.label });
|
|
899
|
+
return /* @__PURE__ */ jsx11(Badge, { variant: config.variant, children: t(config.label) });
|
|
920
900
|
}
|
|
921
901
|
__name(InvoiceStatusBadge, "InvoiceStatusBadge");
|
|
922
902
|
|
|
@@ -928,6 +908,8 @@ function InvoiceDetails({
|
|
|
928
908
|
onOpenChange,
|
|
929
909
|
onInvoiceChange: _onInvoiceChange
|
|
930
910
|
}) {
|
|
911
|
+
const t = useTranslations11();
|
|
912
|
+
const fmt = useBillingFormatOptions();
|
|
931
913
|
const handleDownloadPDF = /* @__PURE__ */ __name(() => {
|
|
932
914
|
if (invoice.stripePdfUrl) {
|
|
933
915
|
window.open(invoice.stripePdfUrl, "_blank");
|
|
@@ -946,89 +928,86 @@ function InvoiceDetails({
|
|
|
946
928
|
}
|
|
947
929
|
return invoice.stripeInvoiceId.slice(-8);
|
|
948
930
|
}, "getInvoiceNumber");
|
|
949
|
-
const productName = invoice.subscription?.price?.product?.name || "
|
|
931
|
+
const productName = invoice.subscription?.price?.product?.name || t("billing.ui.cards.subscriptions.fallback_name");
|
|
950
932
|
return /* @__PURE__ */ jsx12(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs10(DialogContent, { className: "max-w-2xl", children: [
|
|
951
933
|
/* @__PURE__ */ jsxs10(DialogHeader, { children: [
|
|
952
|
-
/* @__PURE__ */
|
|
953
|
-
|
|
954
|
-
getInvoiceNumber()
|
|
955
|
-
] }),
|
|
956
|
-
/* @__PURE__ */ jsx12(DialogDescription, { children: formatDate3(invoice.periodStart) })
|
|
934
|
+
/* @__PURE__ */ jsx12(DialogTitle, { children: t("billing.ui.invoice.title", { number: getInvoiceNumber() }) }),
|
|
935
|
+
/* @__PURE__ */ jsx12(DialogDescription, { children: formatDate(invoice.periodStart, fmt) })
|
|
957
936
|
] }),
|
|
958
937
|
/* @__PURE__ */ jsxs10("div", { className: "space-y-6", children: [
|
|
959
938
|
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-x-3", children: [
|
|
960
|
-
/* @__PURE__ */ jsx12("span", { className: "text-sm font-medium text-muted-foreground", children: "
|
|
939
|
+
/* @__PURE__ */ jsx12("span", { className: "text-sm font-medium text-muted-foreground", children: t("billing.ui.labels.status") }),
|
|
961
940
|
/* @__PURE__ */ jsx12(InvoiceStatusBadge, { status: invoice.status })
|
|
962
941
|
] }),
|
|
963
942
|
/* @__PURE__ */ jsxs10("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
964
943
|
/* @__PURE__ */ jsxs10("div", { children: [
|
|
965
|
-
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: "
|
|
944
|
+
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: t("billing.ui.invoice.billing_period") }),
|
|
966
945
|
/* @__PURE__ */ jsxs10("p", { className: "text-sm", children: [
|
|
967
|
-
|
|
946
|
+
formatDate(invoice.periodStart, fmt),
|
|
968
947
|
" - ",
|
|
969
|
-
|
|
948
|
+
formatDate(invoice.periodEnd, fmt)
|
|
970
949
|
] })
|
|
971
950
|
] }),
|
|
972
951
|
invoice.dueDate && /* @__PURE__ */ jsxs10("div", { children: [
|
|
973
|
-
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: "
|
|
974
|
-
/* @__PURE__ */ jsx12("p", { className: "text-sm", children:
|
|
952
|
+
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: t("billing.ui.invoice.due_date") }),
|
|
953
|
+
/* @__PURE__ */ jsx12("p", { className: "text-sm", children: formatDate(invoice.dueDate, fmt) })
|
|
975
954
|
] }),
|
|
976
955
|
invoice.paidAt && /* @__PURE__ */ jsxs10("div", { children: [
|
|
977
|
-
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: "
|
|
978
|
-
/* @__PURE__ */ jsx12("p", { className: "text-sm", children:
|
|
956
|
+
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: t("billing.ui.invoice.paid_date") }),
|
|
957
|
+
/* @__PURE__ */ jsx12("p", { className: "text-sm", children: formatDate(invoice.paidAt, fmt) })
|
|
979
958
|
] }),
|
|
980
959
|
/* @__PURE__ */ jsxs10("div", { children: [
|
|
981
|
-
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: "
|
|
960
|
+
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: t("billing.ui.invoice.attempt_count") }),
|
|
982
961
|
/* @__PURE__ */ jsx12("p", { className: "text-sm", children: invoice.attemptCount })
|
|
983
962
|
] })
|
|
984
963
|
] }),
|
|
985
964
|
/* @__PURE__ */ jsxs10("div", { children: [
|
|
986
|
-
/* @__PURE__ */ jsx12("h4", { className: "text-sm font-medium text-muted-foreground mb-2", children: "
|
|
965
|
+
/* @__PURE__ */ jsx12("h4", { className: "text-sm font-medium text-muted-foreground mb-2", children: t("billing.ui.invoice.line_items") }),
|
|
987
966
|
/* @__PURE__ */ jsx12("div", { className: "border rounded-lg overflow-clip", children: /* @__PURE__ */ jsxs10("table", { className: "w-full", children: [
|
|
988
967
|
/* @__PURE__ */ jsx12("thead", { className: "bg-muted", children: /* @__PURE__ */ jsxs10("tr", { children: [
|
|
989
|
-
/* @__PURE__ */ jsx12("th", { className: "text-start p-3 text-sm font-medium", children: "
|
|
990
|
-
/* @__PURE__ */ jsx12("th", { className: "text-end p-3 text-sm font-medium", children: "
|
|
968
|
+
/* @__PURE__ */ jsx12("th", { className: "text-start p-3 text-sm font-medium", children: t("billing.ui.columns.description") }),
|
|
969
|
+
/* @__PURE__ */ jsx12("th", { className: "text-end p-3 text-sm font-medium", children: t("billing.ui.columns.amount") })
|
|
991
970
|
] }) }),
|
|
992
971
|
/* @__PURE__ */ jsx12("tbody", { children: /* @__PURE__ */ jsxs10("tr", { className: "border-t", children: [
|
|
993
972
|
/* @__PURE__ */ jsx12("td", { className: "p-3", children: productName }),
|
|
994
|
-
/* @__PURE__ */ jsx12("td", { className: "p-3 text-end", children: formatCurrency(invoice.subtotal, invoice.currency) })
|
|
973
|
+
/* @__PURE__ */ jsx12("td", { className: "p-3 text-end", children: formatCurrency(invoice.subtotal, invoice.currency, fmt) })
|
|
995
974
|
] }) })
|
|
996
975
|
] }) })
|
|
997
976
|
] }),
|
|
998
977
|
/* @__PURE__ */ jsxs10("div", { className: "space-y-2 border-t pt-4", children: [
|
|
999
978
|
/* @__PURE__ */ jsxs10("div", { className: "flex justify-between", children: [
|
|
1000
|
-
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: "
|
|
1001
|
-
/* @__PURE__ */ jsx12("span", { className: "text-sm", children: formatCurrency(invoice.subtotal, invoice.currency) })
|
|
979
|
+
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: t("billing.ui.invoice.subtotal") }),
|
|
980
|
+
/* @__PURE__ */ jsx12("span", { className: "text-sm", children: formatCurrency(invoice.subtotal, invoice.currency, fmt) })
|
|
1002
981
|
] }),
|
|
1003
982
|
invoice.tax !== void 0 && invoice.tax > 0 && /* @__PURE__ */ jsxs10("div", { className: "flex justify-between", children: [
|
|
1004
|
-
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: "
|
|
1005
|
-
/* @__PURE__ */ jsx12("span", { className: "text-sm", children: formatCurrency(invoice.tax, invoice.currency) })
|
|
983
|
+
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: t("billing.ui.invoice.tax") }),
|
|
984
|
+
/* @__PURE__ */ jsx12("span", { className: "text-sm", children: formatCurrency(invoice.tax, invoice.currency, fmt) })
|
|
1006
985
|
] }),
|
|
1007
986
|
/* @__PURE__ */ jsxs10("div", { className: "flex justify-between text-lg font-semibold border-t pt-2", children: [
|
|
1008
|
-
/* @__PURE__ */ jsx12("span", { children: "
|
|
1009
|
-
/* @__PURE__ */ jsx12("span", { children: formatCurrency(invoice.total, invoice.currency) })
|
|
987
|
+
/* @__PURE__ */ jsx12("span", { children: t("billing.ui.invoice.total") }),
|
|
988
|
+
/* @__PURE__ */ jsx12("span", { children: formatCurrency(invoice.total, invoice.currency, fmt) })
|
|
1010
989
|
] }),
|
|
1011
990
|
invoice.amountPaid > 0 && /* @__PURE__ */ jsxs10("div", { className: "flex justify-between", children: [
|
|
1012
|
-
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: "
|
|
1013
|
-
/* @__PURE__ */ jsx12("span", { className: "text-sm text-success", children: formatCurrency(invoice.amountPaid, invoice.currency) })
|
|
991
|
+
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: t("billing.ui.invoice.amount_paid") }),
|
|
992
|
+
/* @__PURE__ */ jsx12("span", { className: "text-sm text-success", children: formatCurrency(invoice.amountPaid, invoice.currency, fmt) })
|
|
1014
993
|
] }),
|
|
1015
994
|
invoice.amountRemaining > 0 && /* @__PURE__ */ jsxs10("div", { className: "flex justify-between", children: [
|
|
1016
|
-
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: "
|
|
1017
|
-
/* @__PURE__ */ jsx12("span", { className: "text-sm text-destructive", children: formatCurrency(invoice.amountRemaining, invoice.currency) })
|
|
995
|
+
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: t("billing.ui.invoice.amount_due") }),
|
|
996
|
+
/* @__PURE__ */ jsx12("span", { className: "text-sm text-destructive", children: formatCurrency(invoice.amountRemaining, invoice.currency, fmt) })
|
|
1018
997
|
] })
|
|
1019
998
|
] }),
|
|
1020
999
|
/* @__PURE__ */ jsxs10("div", { className: "flex flex-wrap gap-2 pt-4 border-t", children: [
|
|
1021
1000
|
invoice.stripePdfUrl && /* @__PURE__ */ jsxs10(Button, { variant: "outline", onClick: handleDownloadPDF, children: [
|
|
1022
1001
|
/* @__PURE__ */ jsx12(Download, { className: "me-2 h-4 w-4" }),
|
|
1023
|
-
"
|
|
1002
|
+
t("billing.ui.invoice.download_pdf")
|
|
1024
1003
|
] }),
|
|
1025
1004
|
invoice.status === "open" /* OPEN */ && invoice.attempted && /* @__PURE__ */ jsxs10(Button, { variant: "default", onClick: handleRetryPayment, children: [
|
|
1026
1005
|
/* @__PURE__ */ jsx12(RefreshCw, { className: "me-2 h-4 w-4" }),
|
|
1027
|
-
"
|
|
1006
|
+
t("billing.ui.invoice.retry_payment")
|
|
1028
1007
|
] }),
|
|
1029
1008
|
invoice.stripeHostedInvoiceUrl && /* @__PURE__ */ jsxs10(Button, { variant: "outline", onClick: handleViewInStripe, children: [
|
|
1030
1009
|
/* @__PURE__ */ jsx12(ExternalLink2, { className: "me-2 h-4 w-4" }),
|
|
1031
|
-
"
|
|
1010
|
+
t("billing.ui.invoice.view_in_stripe")
|
|
1032
1011
|
] })
|
|
1033
1012
|
] })
|
|
1034
1013
|
] })
|
|
@@ -1039,6 +1018,8 @@ __name(InvoiceDetails, "InvoiceDetails");
|
|
|
1039
1018
|
// src/features/billing/stripe-invoice/components/lists/InvoicesList.tsx
|
|
1040
1019
|
import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1041
1020
|
function InvoicesList({ invoices, onInvoicesChange }) {
|
|
1021
|
+
const t = useTranslations12();
|
|
1022
|
+
const fmt = useBillingFormatOptions();
|
|
1042
1023
|
const [selectedInvoice, setSelectedInvoice] = useState5(null);
|
|
1043
1024
|
const handleRowClick = /* @__PURE__ */ __name((invoice) => {
|
|
1044
1025
|
setSelectedInvoice(invoice);
|
|
@@ -1052,17 +1033,17 @@ function InvoicesList({ invoices, onInvoicesChange }) {
|
|
|
1052
1033
|
return /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
1053
1034
|
/* @__PURE__ */ jsx13("div", { className: "border rounded-lg overflow-clip", children: /* @__PURE__ */ jsxs11(Table, { children: [
|
|
1054
1035
|
/* @__PURE__ */ jsx13(TableHeader, { className: "bg-muted", children: /* @__PURE__ */ jsxs11(TableRow, { children: [
|
|
1055
|
-
/* @__PURE__ */ jsx13(TableHead, { children: "
|
|
1056
|
-
/* @__PURE__ */ jsx13(TableHead, { children: "
|
|
1057
|
-
/* @__PURE__ */ jsx13(TableHead, { children: "
|
|
1058
|
-
/* @__PURE__ */ jsx13(TableHead, { className: "text-end", children: "
|
|
1059
|
-
/* @__PURE__ */ jsx13(TableHead, { children: "
|
|
1036
|
+
/* @__PURE__ */ jsx13(TableHead, { children: t("billing.ui.columns.invoice_number") }),
|
|
1037
|
+
/* @__PURE__ */ jsx13(TableHead, { children: t("billing.ui.columns.date") }),
|
|
1038
|
+
/* @__PURE__ */ jsx13(TableHead, { children: t("billing.ui.columns.status") }),
|
|
1039
|
+
/* @__PURE__ */ jsx13(TableHead, { className: "text-end", children: t("billing.ui.columns.amount") }),
|
|
1040
|
+
/* @__PURE__ */ jsx13(TableHead, { children: t("billing.ui.columns.period") })
|
|
1060
1041
|
] }) }),
|
|
1061
1042
|
/* @__PURE__ */ jsx13(TableBody, { children: invoices.map((invoice) => {
|
|
1062
1043
|
const invoiceNumber = getInvoiceNumber(invoice);
|
|
1063
|
-
const date =
|
|
1064
|
-
const amount = formatCurrency(invoice.total, invoice.currency);
|
|
1065
|
-
const period = `${
|
|
1044
|
+
const date = formatDate(invoice.periodStart, fmt);
|
|
1045
|
+
const amount = formatCurrency(invoice.total, invoice.currency, fmt);
|
|
1046
|
+
const period = `${formatDate(invoice.periodStart, fmt)} - ${formatDate(invoice.periodEnd, fmt)}`;
|
|
1066
1047
|
return /* @__PURE__ */ jsxs11(
|
|
1067
1048
|
TableRow,
|
|
1068
1049
|
{
|
|
@@ -1099,6 +1080,7 @@ __name(InvoicesList, "InvoicesList");
|
|
|
1099
1080
|
// src/features/billing/stripe-invoice/components/containers/InvoicesContainer.tsx
|
|
1100
1081
|
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1101
1082
|
function InvoicesContainer() {
|
|
1083
|
+
const t = useTranslations13();
|
|
1102
1084
|
const [invoices, setInvoices] = useState6([]);
|
|
1103
1085
|
const [loading, setLoading] = useState6(true);
|
|
1104
1086
|
const [statusFilter, setStatusFilter] = useState6("all");
|
|
@@ -1123,16 +1105,16 @@ function InvoicesContainer() {
|
|
|
1123
1105
|
}, "handleFilterChange");
|
|
1124
1106
|
return /* @__PURE__ */ jsxs12("div", { className: "space-y-4", children: [
|
|
1125
1107
|
/* @__PURE__ */ jsx14(Tabs, { value: statusFilter, onValueChange: handleFilterChange, children: /* @__PURE__ */ jsxs12(TabsList, { children: [
|
|
1126
|
-
/* @__PURE__ */ jsx14(TabsTrigger, { value: "all", children: "
|
|
1127
|
-
/* @__PURE__ */ jsx14(TabsTrigger, { value: "paid" /* PAID */, children: "
|
|
1128
|
-
/* @__PURE__ */ jsx14(TabsTrigger, { value: "open" /* OPEN */, children: "
|
|
1129
|
-
/* @__PURE__ */ jsx14(TabsTrigger, { value: "void" /* VOID */, children: "
|
|
1130
|
-
/* @__PURE__ */ jsx14(TabsTrigger, { value: "uncollectible" /* UNCOLLECTIBLE */, children: "
|
|
1108
|
+
/* @__PURE__ */ jsx14(TabsTrigger, { value: "all", children: t("billing.ui.invoices.filter_all") }),
|
|
1109
|
+
/* @__PURE__ */ jsx14(TabsTrigger, { value: "paid" /* PAID */, children: t("billing.ui.invoice_status.paid") }),
|
|
1110
|
+
/* @__PURE__ */ jsx14(TabsTrigger, { value: "open" /* OPEN */, children: t("billing.ui.invoice_status.open") }),
|
|
1111
|
+
/* @__PURE__ */ jsx14(TabsTrigger, { value: "void" /* VOID */, children: t("billing.ui.invoice_status.void") }),
|
|
1112
|
+
/* @__PURE__ */ jsx14(TabsTrigger, { value: "uncollectible" /* UNCOLLECTIBLE */, children: t("billing.ui.invoice_status.uncollectible") })
|
|
1131
1113
|
] }) }),
|
|
1132
|
-
loading && /* @__PURE__ */ jsx14("div", { className: "text-center py-8 text-muted-foreground", children: "
|
|
1114
|
+
loading && /* @__PURE__ */ jsx14("div", { className: "text-center py-8 text-muted-foreground", children: t("billing.ui.invoices.loading") }),
|
|
1133
1115
|
!loading && invoices.length === 0 && /* @__PURE__ */ jsxs12("div", { className: "border border-dashed border-gray-300 rounded-lg p-8 text-center", children: [
|
|
1134
|
-
/* @__PURE__ */ jsx14("p", { className: "text-lg font-medium text-muted-foreground mb-2", children: "
|
|
1135
|
-
/* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: "
|
|
1116
|
+
/* @__PURE__ */ jsx14("p", { className: "text-lg font-medium text-muted-foreground mb-2", children: t("billing.ui.invoices.empty_title") }),
|
|
1117
|
+
/* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: t("billing.ui.invoices.empty_description") })
|
|
1136
1118
|
] }),
|
|
1137
1119
|
!loading && invoices.length > 0 && /* @__PURE__ */ jsx14(InvoicesList, { invoices, onInvoicesChange: loadInvoices })
|
|
1138
1120
|
] });
|
|
@@ -1140,16 +1122,20 @@ function InvoicesContainer() {
|
|
|
1140
1122
|
__name(InvoicesContainer, "InvoicesContainer");
|
|
1141
1123
|
|
|
1142
1124
|
// src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx
|
|
1125
|
+
import { useTranslations as useTranslations18 } from "next-intl";
|
|
1143
1126
|
import { CreditCard as CreditCard3 } from "lucide-react";
|
|
1144
1127
|
import { useCallback, useEffect as useEffect5, useState as useState10 } from "react";
|
|
1145
1128
|
|
|
1146
1129
|
// src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx
|
|
1130
|
+
import { useTranslations as useTranslations17 } from "next-intl";
|
|
1147
1131
|
import { useState as useState9 } from "react";
|
|
1148
1132
|
|
|
1149
1133
|
// src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx
|
|
1134
|
+
import { useTranslations as useTranslations16 } from "next-intl";
|
|
1150
1135
|
import { useState as useState8 } from "react";
|
|
1151
1136
|
|
|
1152
1137
|
// src/features/billing/stripe-subscription/components/forms/CancelSubscriptionDialog.tsx
|
|
1138
|
+
import { useTranslations as useTranslations14 } from "next-intl";
|
|
1153
1139
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
1154
1140
|
import { useState as useState7 } from "react";
|
|
1155
1141
|
import { useForm } from "react-hook-form";
|
|
@@ -1164,6 +1150,8 @@ function CancelSubscriptionDialog({
|
|
|
1164
1150
|
onOpenChange,
|
|
1165
1151
|
onSuccess
|
|
1166
1152
|
}) {
|
|
1153
|
+
const t = useTranslations14();
|
|
1154
|
+
const fmt = useBillingFormatOptions();
|
|
1167
1155
|
const [isSubmitting, setIsSubmitting] = useState7(false);
|
|
1168
1156
|
const form = useForm({
|
|
1169
1157
|
resolver: zodResolver(formSchema),
|
|
@@ -1186,31 +1174,27 @@ function CancelSubscriptionDialog({
|
|
|
1186
1174
|
setIsSubmitting(false);
|
|
1187
1175
|
}
|
|
1188
1176
|
}, "onSubmit");
|
|
1189
|
-
const periodEndDate =
|
|
1177
|
+
const periodEndDate = formatDate(subscription.currentPeriodEnd, fmt);
|
|
1190
1178
|
return /* @__PURE__ */ jsx15(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs13(DialogContent, { className: "max-w-md", children: [
|
|
1191
1179
|
/* @__PURE__ */ jsxs13(DialogHeader, { children: [
|
|
1192
|
-
/* @__PURE__ */ jsx15(DialogTitle, { children: "
|
|
1193
|
-
/* @__PURE__ */ jsx15(DialogDescription, { children: "
|
|
1180
|
+
/* @__PURE__ */ jsx15(DialogTitle, { children: t("billing.ui.subscription.cancel.title") }),
|
|
1181
|
+
/* @__PURE__ */ jsx15(DialogDescription, { children: t("billing.ui.subscription.cancel.description") })
|
|
1194
1182
|
] }),
|
|
1195
1183
|
/* @__PURE__ */ jsx15(Form, { ...form, children: /* @__PURE__ */ jsxs13("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-col gap-y-4", children: [
|
|
1196
|
-
/* @__PURE__ */
|
|
1197
|
-
"Your subscription will remain active until ",
|
|
1198
|
-
periodEndDate,
|
|
1199
|
-
". You can continue using the service until then."
|
|
1200
|
-
] }),
|
|
1184
|
+
/* @__PURE__ */ jsx15("div", { className: "bg-primary/10 border-primary/30 text-foreground rounded-lg border p-3 text-sm", children: t("billing.ui.subscription.cancel.remains_active", { date: periodEndDate }) }),
|
|
1201
1185
|
/* @__PURE__ */ jsx15(
|
|
1202
1186
|
FormTextarea,
|
|
1203
1187
|
{
|
|
1204
1188
|
form,
|
|
1205
1189
|
id: "reason",
|
|
1206
|
-
name: "
|
|
1207
|
-
placeholder: "
|
|
1190
|
+
name: t("billing.ui.subscription.cancel.reason"),
|
|
1191
|
+
placeholder: t("billing.ui.subscription.cancel.reason_placeholder"),
|
|
1208
1192
|
className: "min-h-24"
|
|
1209
1193
|
}
|
|
1210
1194
|
),
|
|
1211
1195
|
/* @__PURE__ */ jsxs13("div", { className: "flex gap-x-2 justify-end pt-2", children: [
|
|
1212
|
-
/* @__PURE__ */ jsx15(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), disabled: isSubmitting, children: "
|
|
1213
|
-
/* @__PURE__ */ jsx15(Button, { type: "submit", variant: "destructive", disabled: isSubmitting, children: isSubmitting ? "
|
|
1196
|
+
/* @__PURE__ */ jsx15(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), disabled: isSubmitting, children: t("billing.ui.subscription.cancel.keep") }),
|
|
1197
|
+
/* @__PURE__ */ jsx15(Button, { type: "submit", variant: "destructive", disabled: isSubmitting, children: isSubmitting ? t("billing.ui.subscription.cancel.canceling") : t("billing.ui.subscription.cancel.confirm") })
|
|
1214
1198
|
] })
|
|
1215
1199
|
] }) })
|
|
1216
1200
|
] }) });
|
|
@@ -1218,75 +1202,77 @@ function CancelSubscriptionDialog({
|
|
|
1218
1202
|
__name(CancelSubscriptionDialog, "CancelSubscriptionDialog");
|
|
1219
1203
|
|
|
1220
1204
|
// src/features/billing/stripe-subscription/components/widgets/SubscriptionStatusBadge.tsx
|
|
1205
|
+
import { useTranslations as useTranslations15 } from "next-intl";
|
|
1221
1206
|
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
1222
1207
|
var statusConfig2 = {
|
|
1223
1208
|
["active" /* ACTIVE */]: {
|
|
1224
|
-
label: "
|
|
1209
|
+
label: "billing.ui.subscription_status.active",
|
|
1225
1210
|
variant: "softGreen"
|
|
1226
1211
|
},
|
|
1227
1212
|
["trialing" /* TRIALING */]: {
|
|
1228
|
-
label: "
|
|
1213
|
+
label: "billing.ui.subscription_status.trialing",
|
|
1229
1214
|
variant: "softBlue"
|
|
1230
1215
|
},
|
|
1231
1216
|
["past_due" /* PAST_DUE */]: {
|
|
1232
|
-
label: "
|
|
1217
|
+
label: "billing.ui.subscription_status.past_due",
|
|
1233
1218
|
variant: "softRed"
|
|
1234
1219
|
},
|
|
1235
1220
|
["canceled" /* CANCELED */]: {
|
|
1236
|
-
label: "
|
|
1221
|
+
label: "billing.ui.subscription_status.canceled",
|
|
1237
1222
|
variant: "softGray"
|
|
1238
1223
|
},
|
|
1239
1224
|
["paused" /* PAUSED */]: {
|
|
1240
|
-
label: "
|
|
1225
|
+
label: "billing.ui.subscription_status.paused",
|
|
1241
1226
|
variant: "softYellow"
|
|
1242
1227
|
},
|
|
1243
1228
|
["unpaid" /* UNPAID */]: {
|
|
1244
|
-
label: "
|
|
1229
|
+
label: "billing.ui.subscription_status.unpaid",
|
|
1245
1230
|
variant: "softOrange"
|
|
1246
1231
|
},
|
|
1247
1232
|
["incomplete" /* INCOMPLETE */]: {
|
|
1248
|
-
label: "
|
|
1233
|
+
label: "billing.ui.subscription_status.incomplete",
|
|
1249
1234
|
variant: "softGray"
|
|
1250
1235
|
},
|
|
1251
1236
|
["incomplete_expired" /* INCOMPLETE_EXPIRED */]: {
|
|
1252
|
-
label: "
|
|
1237
|
+
label: "billing.ui.subscription_status.incomplete_expired",
|
|
1253
1238
|
variant: "softGray"
|
|
1254
1239
|
}
|
|
1255
1240
|
};
|
|
1256
1241
|
var cancelingConfig = {
|
|
1257
|
-
label: "
|
|
1242
|
+
label: "billing.ui.cards.subscriptions.canceling",
|
|
1258
1243
|
variant: "softAmber"
|
|
1259
1244
|
};
|
|
1260
1245
|
function SubscriptionStatusBadge({ status, cancelAtPeriodEnd }) {
|
|
1246
|
+
const t = useTranslations15();
|
|
1261
1247
|
const config = cancelAtPeriodEnd ? cancelingConfig : statusConfig2[status] || statusConfig2["canceled" /* CANCELED */];
|
|
1262
|
-
return /* @__PURE__ */ jsx16(Badge, { variant: config.variant, children: config.label });
|
|
1248
|
+
return /* @__PURE__ */ jsx16(Badge, { variant: config.variant, children: t(config.label) });
|
|
1263
1249
|
}
|
|
1264
1250
|
__name(SubscriptionStatusBadge, "SubscriptionStatusBadge");
|
|
1265
1251
|
|
|
1266
1252
|
// src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx
|
|
1267
1253
|
import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1268
|
-
function formatPlanName2(price) {
|
|
1269
|
-
if (!price) return "
|
|
1254
|
+
function formatPlanName2(price, t) {
|
|
1255
|
+
if (!price) return t("billing.ui.not_available");
|
|
1270
1256
|
const productName = price.product?.name || "";
|
|
1271
1257
|
const nickname = price.nickname || "";
|
|
1272
1258
|
let interval = "";
|
|
1273
1259
|
if (price.recurring?.interval) {
|
|
1274
1260
|
const intervalMap = {
|
|
1275
|
-
day: "
|
|
1276
|
-
week: "
|
|
1277
|
-
month: "
|
|
1278
|
-
year: "
|
|
1261
|
+
day: t("billing.admin.prices.interval.day"),
|
|
1262
|
+
week: t("billing.admin.prices.interval.week"),
|
|
1263
|
+
month: t("billing.admin.prices.interval.month"),
|
|
1264
|
+
year: t("billing.admin.prices.interval.year")
|
|
1279
1265
|
};
|
|
1280
1266
|
interval = intervalMap[price.recurring.interval] || price.recurring.interval;
|
|
1281
1267
|
}
|
|
1282
1268
|
const parts = [productName, nickname].filter(Boolean);
|
|
1283
1269
|
const planLabel = parts.join(" - ");
|
|
1284
|
-
return interval ? `${planLabel} (${interval})` : planLabel || "
|
|
1270
|
+
return interval ? `${planLabel} (${interval})` : planLabel || t("billing.ui.not_available");
|
|
1285
1271
|
}
|
|
1286
1272
|
__name(formatPlanName2, "formatPlanName");
|
|
1287
|
-
function formatBillingAmount(price) {
|
|
1288
|
-
if (!price?.unitAmount) return
|
|
1289
|
-
return formatCurrency(price.unitAmount, price.currency);
|
|
1273
|
+
function formatBillingAmount(price, notAvailable, fmt) {
|
|
1274
|
+
if (!price?.unitAmount) return notAvailable;
|
|
1275
|
+
return formatCurrency(price.unitAmount, price.currency, fmt);
|
|
1290
1276
|
}
|
|
1291
1277
|
__name(formatBillingAmount, "formatBillingAmount");
|
|
1292
1278
|
function SubscriptionDetails({
|
|
@@ -1296,6 +1282,8 @@ function SubscriptionDetails({
|
|
|
1296
1282
|
onSubscriptionChange,
|
|
1297
1283
|
onChangePlan
|
|
1298
1284
|
}) {
|
|
1285
|
+
const t = useTranslations16();
|
|
1286
|
+
const fmt = useBillingFormatOptions();
|
|
1299
1287
|
const [showCancel, setShowCancel] = useState8(false);
|
|
1300
1288
|
const [isProcessing, setIsProcessing] = useState8(false);
|
|
1301
1289
|
const handlePause = /* @__PURE__ */ __name(async () => {
|
|
@@ -1334,12 +1322,12 @@ function SubscriptionDetails({
|
|
|
1334
1322
|
return /* @__PURE__ */ jsxs14(Fragment3, { children: [
|
|
1335
1323
|
/* @__PURE__ */ jsx17(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs14(DialogContent, { className: "max-w-2xl", children: [
|
|
1336
1324
|
/* @__PURE__ */ jsxs14(DialogHeader, { children: [
|
|
1337
|
-
/* @__PURE__ */ jsx17(DialogTitle, { children: "
|
|
1338
|
-
/* @__PURE__ */ jsx17(DialogDescription, { children: "
|
|
1325
|
+
/* @__PURE__ */ jsx17(DialogTitle, { children: t("billing.ui.subscription.details_title") }),
|
|
1326
|
+
/* @__PURE__ */ jsx17(DialogDescription, { children: t("billing.ui.subscription.details_description") })
|
|
1339
1327
|
] }),
|
|
1340
1328
|
/* @__PURE__ */ jsxs14("div", { className: "space-y-6", children: [
|
|
1341
1329
|
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-x-3", children: [
|
|
1342
|
-
/* @__PURE__ */ jsx17("span", { className: "text-muted-foreground text-xs", children: "
|
|
1330
|
+
/* @__PURE__ */ jsx17("span", { className: "text-muted-foreground text-xs", children: t("billing.ui.labels.status") }),
|
|
1343
1331
|
/* @__PURE__ */ jsx17(
|
|
1344
1332
|
SubscriptionStatusBadge,
|
|
1345
1333
|
{
|
|
@@ -1350,38 +1338,35 @@ function SubscriptionDetails({
|
|
|
1350
1338
|
] }),
|
|
1351
1339
|
/* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
|
|
1352
1340
|
/* @__PURE__ */ jsxs14("div", { className: "flex justify-between", children: [
|
|
1353
|
-
/* @__PURE__ */ jsx17("span", { className: "text-muted-foreground text-xs", children: "
|
|
1354
|
-
/* @__PURE__ */ jsx17("span", { className: "text-sm", children: formatPlanName2(subscription.price) })
|
|
1341
|
+
/* @__PURE__ */ jsx17("span", { className: "text-muted-foreground text-xs", children: t("billing.ui.labels.plan") }),
|
|
1342
|
+
/* @__PURE__ */ jsx17("span", { className: "text-sm", children: formatPlanName2(subscription.price, t) })
|
|
1355
1343
|
] }),
|
|
1356
1344
|
/* @__PURE__ */ jsxs14("div", { className: "flex justify-between", children: [
|
|
1357
|
-
/* @__PURE__ */ jsx17("span", { className: "text-muted-foreground text-xs", children: "
|
|
1358
|
-
/* @__PURE__ */ jsx17("span", { className: "text-sm", children: formatBillingAmount(subscription.price) })
|
|
1345
|
+
/* @__PURE__ */ jsx17("span", { className: "text-muted-foreground text-xs", children: t("billing.ui.subscription.billing_amount") }),
|
|
1346
|
+
/* @__PURE__ */ jsx17("span", { className: "text-sm", children: formatBillingAmount(subscription.price, t("billing.ui.not_available"), fmt) })
|
|
1359
1347
|
] })
|
|
1360
1348
|
] }),
|
|
1361
1349
|
/* @__PURE__ */ jsx17("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs14("div", { className: "flex justify-between", children: [
|
|
1362
|
-
/* @__PURE__ */ jsx17("span", { className: "text-muted-foreground text-xs", children: "
|
|
1350
|
+
/* @__PURE__ */ jsx17("span", { className: "text-muted-foreground text-xs", children: t("billing.ui.subscription.current_period") }),
|
|
1363
1351
|
/* @__PURE__ */ jsxs14("span", { className: "text-sm", children: [
|
|
1364
|
-
|
|
1352
|
+
formatDate(subscription.currentPeriodStart, fmt),
|
|
1365
1353
|
" - ",
|
|
1366
|
-
|
|
1354
|
+
formatDate(subscription.currentPeriodEnd, fmt)
|
|
1367
1355
|
] })
|
|
1368
1356
|
] }) }),
|
|
1369
1357
|
subscription.trialEnd && /* @__PURE__ */ jsxs14("div", { className: "flex justify-between", children: [
|
|
1370
|
-
/* @__PURE__ */ jsx17("span", { className: "text-muted-foreground text-xs", children: "
|
|
1371
|
-
/* @__PURE__ */ jsx17("span", { className: "text-sm", children:
|
|
1358
|
+
/* @__PURE__ */ jsx17("span", { className: "text-muted-foreground text-xs", children: t("billing.ui.subscription.trial_ends") }),
|
|
1359
|
+
/* @__PURE__ */ jsx17("span", { className: "text-sm", children: formatDate(subscription.trialEnd, fmt) })
|
|
1372
1360
|
] }),
|
|
1373
|
-
subscription.cancelAtPeriodEnd && /* @__PURE__ */ jsx17("div", { className: "bg-warning/15 border-warning/30 rounded-lg border p-3", children: /* @__PURE__ */
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
formatDate3(subscription.currentPeriodEnd),
|
|
1377
|
-
"."
|
|
1378
|
-
] }) }),
|
|
1361
|
+
subscription.cancelAtPeriodEnd && /* @__PURE__ */ jsx17("div", { className: "bg-warning/15 border-warning/30 rounded-lg border p-3", children: /* @__PURE__ */ jsx17("p", { className: "text-warning text-xs/relaxed", children: t("billing.ui.subscription.cancel_at_period_end", {
|
|
1362
|
+
date: formatDate(subscription.currentPeriodEnd, fmt)
|
|
1363
|
+
}) }) }),
|
|
1379
1364
|
/* @__PURE__ */ jsxs14("div", { className: "flex flex-wrap gap-2 pt-4 border-t", children: [
|
|
1380
|
-
onChangePlan && /* @__PURE__ */ jsx17(Button, { variant: "default", onClick: () => onChangePlan(subscription), children: "
|
|
1381
|
-
canPause && /* @__PURE__ */ jsx17(Button, { variant: "outline", onClick: handlePause, disabled: isProcessing, children: isProcessing ? "
|
|
1382
|
-
canResume && /* @__PURE__ */ jsx17(Button, { variant: "outline", onClick: handleResume, disabled: isProcessing, children: isProcessing ? "
|
|
1383
|
-
canCancel && /* @__PURE__ */ jsx17(Button, { variant: "destructive", onClick: () => setShowCancel(true), children: "
|
|
1384
|
-
/* @__PURE__ */ jsx17(Button, { variant: "outline", onClick: handleManageViaPortal, children: "
|
|
1365
|
+
onChangePlan && /* @__PURE__ */ jsx17(Button, { variant: "default", onClick: () => onChangePlan(subscription), children: t("billing.ui.subscription.change_plan") }),
|
|
1366
|
+
canPause && /* @__PURE__ */ jsx17(Button, { variant: "outline", onClick: handlePause, disabled: isProcessing, children: isProcessing ? t("billing.ui.subscription.pausing") : t("billing.ui.subscription.pause") }),
|
|
1367
|
+
canResume && /* @__PURE__ */ jsx17(Button, { variant: "outline", onClick: handleResume, disabled: isProcessing, children: isProcessing ? t("billing.ui.subscription.resuming") : t("billing.ui.subscription.resume") }),
|
|
1368
|
+
canCancel && /* @__PURE__ */ jsx17(Button, { variant: "destructive", onClick: () => setShowCancel(true), children: t("ui.buttons.cancel") }),
|
|
1369
|
+
/* @__PURE__ */ jsx17(Button, { variant: "outline", onClick: handleManageViaPortal, children: t("billing.ui.subscription.manage_portal") })
|
|
1385
1370
|
] })
|
|
1386
1371
|
] })
|
|
1387
1372
|
] }) }),
|
|
@@ -1403,26 +1388,28 @@ __name(SubscriptionDetails, "SubscriptionDetails");
|
|
|
1403
1388
|
|
|
1404
1389
|
// src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx
|
|
1405
1390
|
import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1406
|
-
function formatPlanName3(price) {
|
|
1407
|
-
if (!price) return "
|
|
1391
|
+
function formatPlanName3(price, t) {
|
|
1392
|
+
if (!price) return t("billing.ui.not_available");
|
|
1408
1393
|
const productName = price.product?.name || "";
|
|
1409
1394
|
const nickname = price.nickname || "";
|
|
1410
1395
|
let interval = "";
|
|
1411
1396
|
if (price.recurring?.interval) {
|
|
1412
1397
|
const intervalMap = {
|
|
1413
|
-
day: "
|
|
1414
|
-
week: "
|
|
1415
|
-
month: "
|
|
1416
|
-
year: "
|
|
1398
|
+
day: t("billing.admin.prices.interval.day"),
|
|
1399
|
+
week: t("billing.admin.prices.interval.week"),
|
|
1400
|
+
month: t("billing.admin.prices.interval.month"),
|
|
1401
|
+
year: t("billing.admin.prices.interval.year")
|
|
1417
1402
|
};
|
|
1418
1403
|
interval = intervalMap[price.recurring.interval] || price.recurring.interval;
|
|
1419
1404
|
}
|
|
1420
1405
|
const parts = [productName, nickname].filter(Boolean);
|
|
1421
1406
|
const planLabel = parts.join(" - ");
|
|
1422
|
-
return interval ? `${planLabel} (${interval})` : planLabel || "
|
|
1407
|
+
return interval ? `${planLabel} (${interval})` : planLabel || t("billing.ui.not_available");
|
|
1423
1408
|
}
|
|
1424
1409
|
__name(formatPlanName3, "formatPlanName");
|
|
1425
1410
|
function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChangePlan }) {
|
|
1411
|
+
const t = useTranslations17();
|
|
1412
|
+
const fmt = useBillingFormatOptions();
|
|
1426
1413
|
const [selectedSub, setSelectedSub] = useState9(null);
|
|
1427
1414
|
const handleRowClick = /* @__PURE__ */ __name((subscription) => {
|
|
1428
1415
|
setSelectedSub(subscription);
|
|
@@ -1430,16 +1417,16 @@ function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChangePlan
|
|
|
1430
1417
|
return /* @__PURE__ */ jsxs15(Fragment4, { children: [
|
|
1431
1418
|
/* @__PURE__ */ jsx18("div", { className: "border rounded-lg overflow-clip", children: /* @__PURE__ */ jsxs15(Table, { children: [
|
|
1432
1419
|
/* @__PURE__ */ jsx18(TableHeader, { className: "bg-muted", children: /* @__PURE__ */ jsxs15(TableRow, { children: [
|
|
1433
|
-
/* @__PURE__ */ jsx18(TableHead, { children: "
|
|
1434
|
-
/* @__PURE__ */ jsx18(TableHead, { children: "
|
|
1435
|
-
/* @__PURE__ */ jsx18(TableHead, { children: "
|
|
1436
|
-
/* @__PURE__ */ jsx18(TableHead, { className: "text-end", children: "
|
|
1437
|
-
/* @__PURE__ */ jsx18(TableHead, { className: "text-end", children: "
|
|
1420
|
+
/* @__PURE__ */ jsx18(TableHead, { children: t("billing.ui.columns.status") }),
|
|
1421
|
+
/* @__PURE__ */ jsx18(TableHead, { children: t("billing.ui.columns.plan") }),
|
|
1422
|
+
/* @__PURE__ */ jsx18(TableHead, { children: t("billing.ui.columns.period") }),
|
|
1423
|
+
/* @__PURE__ */ jsx18(TableHead, { className: "text-end", children: t("billing.ui.columns.amount") }),
|
|
1424
|
+
/* @__PURE__ */ jsx18(TableHead, { className: "text-end", children: t("billing.ui.columns.actions") })
|
|
1438
1425
|
] }) }),
|
|
1439
1426
|
/* @__PURE__ */ jsx18(TableBody, { children: subscriptions.map((subscription) => {
|
|
1440
1427
|
const price = subscription.price;
|
|
1441
|
-
const amount = price?.unitAmount ? formatCurrency(price.unitAmount, price.currency) : "0";
|
|
1442
|
-
const period = `${
|
|
1428
|
+
const amount = price?.unitAmount ? formatCurrency(price.unitAmount, price.currency, fmt) : "0";
|
|
1429
|
+
const period = `${formatDate(subscription.currentPeriodStart, fmt)} - ${formatDate(subscription.currentPeriodEnd, fmt)}`;
|
|
1443
1430
|
return /* @__PURE__ */ jsxs15(
|
|
1444
1431
|
TableRow,
|
|
1445
1432
|
{
|
|
@@ -1453,7 +1440,7 @@ function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChangePlan
|
|
|
1453
1440
|
cancelAtPeriodEnd: subscription.cancelAtPeriodEnd
|
|
1454
1441
|
}
|
|
1455
1442
|
) }),
|
|
1456
|
-
/* @__PURE__ */ jsx18(TableCell, { className: "font-medium", children: formatPlanName3(price) }),
|
|
1443
|
+
/* @__PURE__ */ jsx18(TableCell, { className: "font-medium", children: formatPlanName3(price, t) }),
|
|
1457
1444
|
/* @__PURE__ */ jsx18(TableCell, { className: "text-muted-foreground text-sm", children: period }),
|
|
1458
1445
|
/* @__PURE__ */ jsx18(TableCell, { className: "text-end font-medium", children: amount }),
|
|
1459
1446
|
/* @__PURE__ */ jsx18(TableCell, { className: "text-end", children: (subscription.status === "active" /* ACTIVE */ || subscription.status === "trialing" /* TRIALING */) && onChangePlan && /* @__PURE__ */ jsx18(
|
|
@@ -1465,7 +1452,7 @@ function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChangePlan
|
|
|
1465
1452
|
e.stopPropagation();
|
|
1466
1453
|
onChangePlan(subscription);
|
|
1467
1454
|
},
|
|
1468
|
-
children: "
|
|
1455
|
+
children: t("billing.ui.subscription.upgrade")
|
|
1469
1456
|
}
|
|
1470
1457
|
) })
|
|
1471
1458
|
]
|
|
@@ -1497,6 +1484,7 @@ __name(SubscriptionsList, "SubscriptionsList");
|
|
|
1497
1484
|
// src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx
|
|
1498
1485
|
import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1499
1486
|
function SubscriptionsContainer({ onOpenWizard, hasActiveRecurringSubscription }) {
|
|
1487
|
+
const t = useTranslations18();
|
|
1500
1488
|
const [subscriptions, setSubscriptions] = useState10([]);
|
|
1501
1489
|
const [loading, setLoading] = useState10(true);
|
|
1502
1490
|
const loadSubscriptions = useCallback(async () => {
|
|
@@ -1517,23 +1505,23 @@ function SubscriptionsContainer({ onOpenWizard, hasActiveRecurringSubscription }
|
|
|
1517
1505
|
(sub) => sub.status === "past_due" /* PAST_DUE */ || sub.status === "trialing" /* TRIALING */ && sub.trialEnd && new Date(sub.trialEnd).getTime() - (/* @__PURE__ */ new Date()).getTime() <= 7 * 24 * 60 * 60 * 1e3
|
|
1518
1506
|
);
|
|
1519
1507
|
if (loading) {
|
|
1520
|
-
return /* @__PURE__ */ jsx19("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx19("p", { className: "text-muted-foreground", children: "
|
|
1508
|
+
return /* @__PURE__ */ jsx19("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx19("p", { className: "text-muted-foreground", children: t("billing.ui.subscriptions.loading") }) });
|
|
1521
1509
|
}
|
|
1522
1510
|
return /* @__PURE__ */ jsxs16("div", { className: "flex w-full flex-col gap-y-6", children: [
|
|
1523
1511
|
/* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between", children: [
|
|
1524
1512
|
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-x-3", children: [
|
|
1525
1513
|
/* @__PURE__ */ jsx19(CreditCard3, { className: "h-8 w-8" }),
|
|
1526
|
-
/* @__PURE__ */ jsx19("h1", { className: "text-primary text-3xl font-semibold", children: "
|
|
1514
|
+
/* @__PURE__ */ jsx19("h1", { className: "text-primary text-3xl font-semibold", children: t("billing.ui.subscriptions.title") })
|
|
1527
1515
|
] }),
|
|
1528
|
-
subscriptions.length > 0 && /* @__PURE__ */ jsx19(Button, { onClick: () => onOpenWizard?.(), children: hasActiveRecurringSubscription ? "
|
|
1516
|
+
subscriptions.length > 0 && /* @__PURE__ */ jsx19(Button, { onClick: () => onOpenWizard?.(), children: hasActiveRecurringSubscription ? t("billing.ui.subscriptions.purchase_addons") : t("billing.ui.subscriptions.subscribe") })
|
|
1529
1517
|
] }),
|
|
1530
1518
|
criticalSubscriptions.map((subscription) => /* @__PURE__ */ jsx19(BillingAlertBanner, { subscription }, subscription.id)),
|
|
1531
1519
|
subscriptions.length === 0 && /* @__PURE__ */ jsxs16("div", { className: "flex flex-col items-center justify-center py-12 space-y-4", children: [
|
|
1532
1520
|
/* @__PURE__ */ jsx19(CreditCard3, { className: "h-16 w-16 text-muted-foreground" }),
|
|
1533
1521
|
/* @__PURE__ */ jsxs16("div", { className: "text-center", children: [
|
|
1534
|
-
/* @__PURE__ */ jsx19("h3", { className: "text-sm font-medium mb-2", children: "
|
|
1535
|
-
/* @__PURE__ */ jsx19("p", { className: "text-muted-foreground mb-6", children: "
|
|
1536
|
-
/* @__PURE__ */ jsx19(Button, { onClick: () => onOpenWizard?.(), children: "
|
|
1522
|
+
/* @__PURE__ */ jsx19("h3", { className: "text-sm font-medium mb-2", children: t("billing.ui.subscriptions.empty_title") }),
|
|
1523
|
+
/* @__PURE__ */ jsx19("p", { className: "text-muted-foreground mb-6", children: t("billing.ui.subscriptions.empty_description") }),
|
|
1524
|
+
/* @__PURE__ */ jsx19(Button, { onClick: () => onOpenWizard?.(), children: t("billing.ui.subscriptions.subscribe") })
|
|
1537
1525
|
] })
|
|
1538
1526
|
] }),
|
|
1539
1527
|
subscriptions.length > 0 && /* @__PURE__ */ jsx19(
|
|
@@ -1549,19 +1537,22 @@ function SubscriptionsContainer({ onOpenWizard, hasActiveRecurringSubscription }
|
|
|
1549
1537
|
__name(SubscriptionsContainer, "SubscriptionsContainer");
|
|
1550
1538
|
|
|
1551
1539
|
// src/features/billing/stripe-subscription/components/widgets/IntervalToggle.tsx
|
|
1540
|
+
import { useTranslations as useTranslations19 } from "next-intl";
|
|
1552
1541
|
import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1553
1542
|
function IntervalToggle({ value, onChange, hasMonthly, hasYearly }) {
|
|
1543
|
+
const t = useTranslations19();
|
|
1554
1544
|
if (!hasMonthly || !hasYearly) {
|
|
1555
1545
|
return null;
|
|
1556
1546
|
}
|
|
1557
1547
|
return /* @__PURE__ */ jsx20(Tabs, { value, onValueChange: (v) => onChange(v), children: /* @__PURE__ */ jsxs17(TabsList, { children: [
|
|
1558
|
-
/* @__PURE__ */ jsx20(TabsTrigger, { value: "month", children: "
|
|
1559
|
-
/* @__PURE__ */ jsx20(TabsTrigger, { value: "year", children: "
|
|
1548
|
+
/* @__PURE__ */ jsx20(TabsTrigger, { value: "month", children: t("billing.admin.prices.interval.month") }),
|
|
1549
|
+
/* @__PURE__ */ jsx20(TabsTrigger, { value: "year", children: t("billing.admin.prices.interval.year") })
|
|
1560
1550
|
] }) });
|
|
1561
1551
|
}
|
|
1562
1552
|
__name(IntervalToggle, "IntervalToggle");
|
|
1563
1553
|
|
|
1564
1554
|
// src/features/billing/stripe-subscription/components/widgets/PricingCard.tsx
|
|
1555
|
+
import { useTranslations as useTranslations20 } from "next-intl";
|
|
1565
1556
|
import { Check } from "lucide-react";
|
|
1566
1557
|
import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1567
1558
|
function PricingCard({
|
|
@@ -1572,10 +1563,12 @@ function PricingCard({
|
|
|
1572
1563
|
isLoading = false,
|
|
1573
1564
|
onSelect
|
|
1574
1565
|
}) {
|
|
1575
|
-
const
|
|
1566
|
+
const t = useTranslations20();
|
|
1567
|
+
const fmt = useBillingFormatOptions();
|
|
1568
|
+
const description = price.description || price.nickname || t("billing.ui.pricing.standard");
|
|
1576
1569
|
const features = price.features || [];
|
|
1577
|
-
const formattedPrice = formatCurrency(price.unitAmount, price.currency);
|
|
1578
|
-
const interval = formatInterval(price);
|
|
1570
|
+
const formattedPrice = formatCurrency(price.unitAmount, price.currency, fmt);
|
|
1571
|
+
const interval = formatInterval(price, fmt);
|
|
1579
1572
|
const handleKeyDown = /* @__PURE__ */ __name((e) => {
|
|
1580
1573
|
if ((e.key === "Enter" || e.key === " ") && !isDisabled && !isCurrentPlan) {
|
|
1581
1574
|
e.preventDefault();
|
|
@@ -1592,7 +1585,7 @@ function PricingCard({
|
|
|
1592
1585
|
{
|
|
1593
1586
|
role: "radio",
|
|
1594
1587
|
"aria-checked": isSelected,
|
|
1595
|
-
"aria-label":
|
|
1588
|
+
"aria-label": t("billing.ui.pricing.card_aria", { description, price: formattedPrice, interval }),
|
|
1596
1589
|
tabIndex: isDisabled ? -1 : 0,
|
|
1597
1590
|
onKeyDown: handleKeyDown,
|
|
1598
1591
|
onClick: handleClick,
|
|
@@ -1606,7 +1599,7 @@ function PricingCard({
|
|
|
1606
1599
|
isLoading && "pointer-events-none"
|
|
1607
1600
|
),
|
|
1608
1601
|
children: [
|
|
1609
|
-
isCurrentPlan && /* @__PURE__ */ jsx21(Badge, { variant: "secondary", className: "absolute top-2 end-2", children: "
|
|
1602
|
+
isCurrentPlan && /* @__PURE__ */ jsx21(Badge, { variant: "secondary", className: "absolute top-2 end-2", children: t("billing.ui.pricing.current") }),
|
|
1610
1603
|
/* @__PURE__ */ jsx21(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsx21("h3", { className: "text-sm font-medium", children: description }) }),
|
|
1611
1604
|
/* @__PURE__ */ jsxs18(CardContent, { className: "pb-4 grow", children: [
|
|
1612
1605
|
/* @__PURE__ */ jsxs18("div", { className: "mb-4", children: [
|
|
@@ -1624,7 +1617,7 @@ function PricingCard({
|
|
|
1624
1617
|
variant: isCurrentPlan ? "secondary" : isSelected ? "default" : "outline",
|
|
1625
1618
|
className: "w-full",
|
|
1626
1619
|
disabled: isDisabled || isCurrentPlan || isLoading,
|
|
1627
|
-
children: isLoading ? "
|
|
1620
|
+
children: isLoading ? t("billing.ui.wizard.review.processing") : isCurrentPlan ? t("billing.ui.pricing.current_plan") : isSelected ? t("billing.ui.pricing.selected") : t("billing.ui.wizard.steps.select_plan")
|
|
1628
1621
|
}
|
|
1629
1622
|
) })
|
|
1630
1623
|
]
|
|
@@ -1633,7 +1626,11 @@ function PricingCard({
|
|
|
1633
1626
|
}
|
|
1634
1627
|
__name(PricingCard, "PricingCard");
|
|
1635
1628
|
|
|
1629
|
+
// src/features/billing/stripe-subscription/components/widgets/ProductPricingList.tsx
|
|
1630
|
+
import { useTranslations as useTranslations22 } from "next-intl";
|
|
1631
|
+
|
|
1636
1632
|
// src/features/billing/stripe-subscription/components/widgets/ProductPricingRow.tsx
|
|
1633
|
+
import { useTranslations as useTranslations21 } from "next-intl";
|
|
1637
1634
|
import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1638
1635
|
function ProductPricingRow({
|
|
1639
1636
|
product,
|
|
@@ -1643,6 +1640,7 @@ function ProductPricingRow({
|
|
|
1643
1640
|
loadingPriceId,
|
|
1644
1641
|
onSelectPrice
|
|
1645
1642
|
}) {
|
|
1643
|
+
const t = useTranslations21();
|
|
1646
1644
|
if (prices.length === 0) {
|
|
1647
1645
|
return null;
|
|
1648
1646
|
}
|
|
@@ -1653,7 +1651,7 @@ function ProductPricingRow({
|
|
|
1653
1651
|
{
|
|
1654
1652
|
className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4",
|
|
1655
1653
|
role: "radiogroup",
|
|
1656
|
-
"aria-label":
|
|
1654
|
+
"aria-label": t("billing.ui.pricing.options_aria", { name: product.name }),
|
|
1657
1655
|
children: prices.sort((a, b) => (a.unitAmount ?? 0) - (b.unitAmount ?? 0)).map((price) => /* @__PURE__ */ jsx22(
|
|
1658
1656
|
PricingCard,
|
|
1659
1657
|
{
|
|
@@ -1703,11 +1701,12 @@ function ProductPricingList({
|
|
|
1703
1701
|
hideRecurringPrices = false,
|
|
1704
1702
|
hideOneTimePrices = false
|
|
1705
1703
|
}) {
|
|
1704
|
+
const t = useTranslations22();
|
|
1706
1705
|
if (loading) {
|
|
1707
1706
|
return /* @__PURE__ */ jsx23(ProductPricingListSkeleton, {});
|
|
1708
1707
|
}
|
|
1709
1708
|
if (products.length === 0) {
|
|
1710
|
-
return /* @__PURE__ */ jsx23("div", { className: "text-center py-8 text-muted-foreground", children: "
|
|
1709
|
+
return /* @__PURE__ */ jsx23("div", { className: "text-center py-8 text-muted-foreground", children: t("billing.ui.pricing.no_plans") });
|
|
1711
1710
|
}
|
|
1712
1711
|
const sortedProducts = [...products].sort((a, b) => {
|
|
1713
1712
|
const aRecurring = isRecurringProduct(a.stripePrices || []);
|
|
@@ -1762,59 +1761,62 @@ function ProductPricingListSkeleton() {
|
|
|
1762
1761
|
__name(ProductPricingListSkeleton, "ProductPricingListSkeleton");
|
|
1763
1762
|
|
|
1764
1763
|
// src/features/billing/stripe-subscription/components/widgets/ProrationPreview.tsx
|
|
1764
|
+
import { useTranslations as useTranslations23 } from "next-intl";
|
|
1765
1765
|
import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1766
1766
|
function ProrationPreview({ preview }) {
|
|
1767
|
+
const t = useTranslations23();
|
|
1768
|
+
const fmt = useBillingFormatOptions();
|
|
1767
1769
|
return /* @__PURE__ */ jsxs21("div", { className: "bg-primary/10 border-primary/30 rounded-lg border p-4", children: [
|
|
1768
|
-
/* @__PURE__ */ jsx24("h4", { className: "text-primary mb-3 font-semibold", children: "
|
|
1770
|
+
/* @__PURE__ */ jsx24("h4", { className: "text-primary mb-3 font-semibold", children: t("billing.ui.proration.title") }),
|
|
1769
1771
|
/* @__PURE__ */ jsxs21("div", { className: "space-y-2", children: [
|
|
1770
1772
|
preview.lineItems.map((item, index) => /* @__PURE__ */ jsxs21("div", { className: "flex justify-between text-sm", children: [
|
|
1771
1773
|
/* @__PURE__ */ jsx24("span", { className: "text-muted-foreground", children: item.description }),
|
|
1772
|
-
/* @__PURE__ */ jsx24("span", { className: `font-medium ${item.amount < 0 ? "text-success" : "text-foreground"}`, children: formatCurrency(item.amount, preview.currency) })
|
|
1774
|
+
/* @__PURE__ */ jsx24("span", { className: `font-medium ${item.amount < 0 ? "text-success" : "text-foreground"}`, children: formatCurrency(item.amount, preview.currency, fmt) })
|
|
1773
1775
|
] }, index)),
|
|
1774
1776
|
/* @__PURE__ */ jsx24("div", { className: "border-primary/30 mt-2 border-t pt-2", children: /* @__PURE__ */ jsxs21("div", { className: "flex justify-between font-semibold", children: [
|
|
1775
|
-
/* @__PURE__ */ jsx24("span", { className: "text-foreground", children: "
|
|
1776
|
-
/* @__PURE__ */ jsx24("span", { className: "text-foreground", children: formatCurrency(preview.immediateCharge, preview.currency) })
|
|
1777
|
+
/* @__PURE__ */ jsx24("span", { className: "text-foreground", children: t("billing.ui.proration.net_due_today") }),
|
|
1778
|
+
/* @__PURE__ */ jsx24("span", { className: "text-foreground", children: formatCurrency(preview.immediateCharge, preview.currency, fmt) })
|
|
1777
1779
|
] }) }),
|
|
1778
|
-
preview.lineItems.length > 0 && preview.lineItems[0].period && /* @__PURE__ */
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
" ",
|
|
1783
|
-
formatCurrency(preview.amountDue, preview.currency)
|
|
1784
|
-
] })
|
|
1780
|
+
preview.lineItems.length > 0 && preview.lineItems[0].period && /* @__PURE__ */ jsx24("div", { className: "text-muted-foreground mt-2 text-xs", children: t("billing.ui.proration.next_invoice", {
|
|
1781
|
+
date: formatDate(preview.lineItems[0].period.end, fmt),
|
|
1782
|
+
amount: formatCurrency(preview.amountDue, preview.currency, fmt)
|
|
1783
|
+
}) })
|
|
1785
1784
|
] })
|
|
1786
1785
|
] });
|
|
1787
1786
|
}
|
|
1788
1787
|
__name(ProrationPreview, "ProrationPreview");
|
|
1789
1788
|
|
|
1790
1789
|
// src/features/billing/stripe-subscription/components/widgets/SubscriptionConfirmation.tsx
|
|
1790
|
+
import { useTranslations as useTranslations24 } from "next-intl";
|
|
1791
1791
|
import { Check as Check2, Loader2 } from "lucide-react";
|
|
1792
1792
|
import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1793
1793
|
function SubscriptionConfirmation({ price, isLoading, onConfirm, onCancel }) {
|
|
1794
|
-
const
|
|
1794
|
+
const t = useTranslations24();
|
|
1795
|
+
const fmt = useBillingFormatOptions();
|
|
1796
|
+
const productName = price.product?.name || price.nickname || t("billing.ui.wizard.review.selected_plan");
|
|
1795
1797
|
const productDescription = price.product?.description || price.description;
|
|
1796
1798
|
const features = price.features || [];
|
|
1797
1799
|
return /* @__PURE__ */ jsxs22("div", { className: "bg-accent/10 border border-accent/30 rounded-lg p-4", children: [
|
|
1798
|
-
/* @__PURE__ */ jsx25("h4", { className: "font-semibold mb-3", children: "
|
|
1800
|
+
/* @__PURE__ */ jsx25("h4", { className: "font-semibold mb-3", children: t("billing.ui.confirmation.title") }),
|
|
1799
1801
|
/* @__PURE__ */ jsxs22("div", { className: "space-y-3", children: [
|
|
1800
1802
|
/* @__PURE__ */ jsxs22("div", { children: [
|
|
1801
1803
|
/* @__PURE__ */ jsx25("div", { className: "font-medium", children: productName }),
|
|
1802
1804
|
productDescription && /* @__PURE__ */ jsx25("div", { className: "text-sm text-muted-foreground", children: productDescription })
|
|
1803
1805
|
] }),
|
|
1804
1806
|
/* @__PURE__ */ jsxs22("div", { className: "text-lg font-semibold", children: [
|
|
1805
|
-
formatCurrency(price.unitAmount, price.currency),
|
|
1806
|
-
/* @__PURE__ */ jsx25("span", { className: "text-sm font-normal text-muted-foreground", children: formatInterval(price) })
|
|
1807
|
+
formatCurrency(price.unitAmount, price.currency, fmt),
|
|
1808
|
+
/* @__PURE__ */ jsx25("span", { className: "text-sm font-normal text-muted-foreground", children: formatInterval(price, fmt) })
|
|
1807
1809
|
] }),
|
|
1808
1810
|
features.length > 0 && /* @__PURE__ */ jsx25("div", { className: "space-y-1", children: features.map((feature, index) => /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-2 text-sm ", children: [
|
|
1809
1811
|
/* @__PURE__ */ jsx25(Check2, { className: "h-4 w-4 text-primary" }),
|
|
1810
1812
|
/* @__PURE__ */ jsx25("span", { children: feature })
|
|
1811
1813
|
] }, index)) }),
|
|
1812
1814
|
/* @__PURE__ */ jsxs22("div", { className: "flex justify-end gap-3 pt-2 border-t border-accent/30", children: [
|
|
1813
|
-
/* @__PURE__ */ jsx25(Button, { variant: "outline", onClick: onCancel, disabled: isLoading, children: "
|
|
1815
|
+
/* @__PURE__ */ jsx25(Button, { variant: "outline", onClick: onCancel, disabled: isLoading, children: t("ui.buttons.cancel") }),
|
|
1814
1816
|
/* @__PURE__ */ jsx25(Button, { onClick: onConfirm, disabled: isLoading, children: isLoading ? /* @__PURE__ */ jsxs22(Fragment5, { children: [
|
|
1815
1817
|
/* @__PURE__ */ jsx25(Loader2, { className: "h-4 w-4 animate-spin me-2" }),
|
|
1816
|
-
"
|
|
1817
|
-
] }) : "
|
|
1818
|
+
t("billing.ui.wizard.review.processing")
|
|
1819
|
+
] }) : t("billing.ui.confirmation.subscribe") })
|
|
1818
1820
|
] })
|
|
1819
1821
|
] })
|
|
1820
1822
|
] });
|
|
@@ -1822,9 +1824,11 @@ function SubscriptionConfirmation({ price, isLoading, onConfirm, onCancel }) {
|
|
|
1822
1824
|
__name(SubscriptionConfirmation, "SubscriptionConfirmation");
|
|
1823
1825
|
|
|
1824
1826
|
// src/features/billing/stripe-subscription/components/wizards/SubscriptionWizard.tsx
|
|
1827
|
+
import { useTranslations as useTranslations31 } from "next-intl";
|
|
1825
1828
|
import { useCallback as useCallback3, useEffect as useEffect7, useRef as useRef2 } from "react";
|
|
1826
1829
|
|
|
1827
1830
|
// src/features/billing/stripe-subscription/hooks/useSubscriptionWizard.ts
|
|
1831
|
+
import { useTranslations as useTranslations25 } from "next-intl";
|
|
1828
1832
|
import { useCallback as useCallback2, useMemo, useReducer, useRef } from "react";
|
|
1829
1833
|
import { v4 } from "uuid";
|
|
1830
1834
|
var initialState = {
|
|
@@ -1872,6 +1876,8 @@ function wizardReducer(state, action) {
|
|
|
1872
1876
|
}
|
|
1873
1877
|
__name(wizardReducer, "wizardReducer");
|
|
1874
1878
|
function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
1879
|
+
const t = useTranslations25();
|
|
1880
|
+
const locale = useI18nLocale();
|
|
1875
1881
|
const [state, dispatch] = useReducer(wizardReducer, {
|
|
1876
1882
|
...initialState,
|
|
1877
1883
|
selectedPrice: subscription?.price || null
|
|
@@ -1911,7 +1917,7 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1911
1917
|
dispatch({ type: "SET_STEP", step: "payment-method" });
|
|
1912
1918
|
dispatch({
|
|
1913
1919
|
type: "SET_ERROR",
|
|
1914
|
-
error: "
|
|
1920
|
+
error: t("billing.ui.wizard.errors.payment_method_required")
|
|
1915
1921
|
});
|
|
1916
1922
|
return;
|
|
1917
1923
|
}
|
|
@@ -1926,11 +1932,11 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1926
1932
|
dispatch({ type: "SET_STEP", step: "review" });
|
|
1927
1933
|
} catch (error) {
|
|
1928
1934
|
console.error("[useSubscriptionWizard] Error preparing review:", error);
|
|
1929
|
-
dispatch({ type: "SET_ERROR", error: error?.message || "
|
|
1935
|
+
dispatch({ type: "SET_ERROR", error: error?.message || t("billing.ui.wizard.errors.prepare_review") });
|
|
1930
1936
|
} finally {
|
|
1931
1937
|
dispatch({ type: "SET_PROCESSING", isProcessing: false });
|
|
1932
1938
|
}
|
|
1933
|
-
}, [state.selectedPrice, state.hasPaymentMethod, subscription, checkPaymentMethod]);
|
|
1939
|
+
}, [state.selectedPrice, state.hasPaymentMethod, subscription, checkPaymentMethod, t]);
|
|
1934
1940
|
const confirmSubscription = useCallback2(async () => {
|
|
1935
1941
|
if (!state.selectedPrice) return;
|
|
1936
1942
|
dispatch({ type: "SET_PROCESSING", isProcessing: true });
|
|
@@ -1957,7 +1963,7 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1957
1963
|
if (error?.status === 409 || error?.response?.status === 409) {
|
|
1958
1964
|
dispatch({
|
|
1959
1965
|
type: "SET_ERROR",
|
|
1960
|
-
error: "
|
|
1966
|
+
error: t("billing.ui.wizard.errors.already_subscribed")
|
|
1961
1967
|
});
|
|
1962
1968
|
return;
|
|
1963
1969
|
}
|
|
@@ -1966,11 +1972,11 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1966
1972
|
dispatch({ type: "SET_STEP", step: "payment-method" });
|
|
1967
1973
|
return;
|
|
1968
1974
|
}
|
|
1969
|
-
dispatch({ type: "SET_ERROR", error: error?.message || "
|
|
1975
|
+
dispatch({ type: "SET_ERROR", error: error?.message || t("billing.ui.wizard.errors.process_subscription") });
|
|
1970
1976
|
} finally {
|
|
1971
1977
|
dispatch({ type: "SET_PROCESSING", isProcessing: false });
|
|
1972
1978
|
}
|
|
1973
|
-
}, [state.selectedPrice, state.promotionCode, subscription]);
|
|
1979
|
+
}, [state.selectedPrice, state.promotionCode, subscription, t]);
|
|
1974
1980
|
const handlePaymentMethodSuccess = useCallback2(async () => {
|
|
1975
1981
|
dispatch({ type: "SET_HAS_PAYMENT_METHOD", hasMethod: true });
|
|
1976
1982
|
dispatch({ type: "SET_STEP", step: "review" });
|
|
@@ -1985,21 +1991,28 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
1985
1991
|
try {
|
|
1986
1992
|
const result = await StripePromotionCodeService.validatePromotionCode({
|
|
1987
1993
|
code,
|
|
1988
|
-
stripePriceId: state.selectedPrice?.id
|
|
1994
|
+
stripePriceId: state.selectedPrice?.id,
|
|
1995
|
+
language: locale
|
|
1989
1996
|
});
|
|
1990
1997
|
if (result.valid) {
|
|
1991
1998
|
dispatch({ type: "SET_PROMOTION_CODE", code: result });
|
|
1992
1999
|
} else {
|
|
1993
|
-
dispatch({
|
|
2000
|
+
dispatch({
|
|
2001
|
+
type: "SET_PROMO_CODE_ERROR",
|
|
2002
|
+
error: result.errorMessage || t("billing.ui.wizard.errors.invalid_promo_code")
|
|
2003
|
+
});
|
|
1994
2004
|
}
|
|
1995
2005
|
} catch (error) {
|
|
1996
2006
|
console.error("[useSubscriptionWizard] Promo code validation error:", error);
|
|
1997
|
-
dispatch({
|
|
2007
|
+
dispatch({
|
|
2008
|
+
type: "SET_PROMO_CODE_ERROR",
|
|
2009
|
+
error: error?.message || t("billing.ui.wizard.errors.validate_promo_code")
|
|
2010
|
+
});
|
|
1998
2011
|
} finally {
|
|
1999
2012
|
dispatch({ type: "SET_VALIDATING_PROMO_CODE", isValidating: false });
|
|
2000
2013
|
}
|
|
2001
2014
|
},
|
|
2002
|
-
[state.selectedPrice?.id]
|
|
2015
|
+
[state.selectedPrice?.id, t, locale]
|
|
2003
2016
|
);
|
|
2004
2017
|
const clearPromoCode = useCallback2(() => {
|
|
2005
2018
|
dispatch({ type: "SET_PROMOTION_CODE", code: null });
|
|
@@ -2040,18 +2053,20 @@ function useSubscriptionWizard({ subscription, onSuccess, onClose }) {
|
|
|
2040
2053
|
__name(useSubscriptionWizard, "useSubscriptionWizard");
|
|
2041
2054
|
|
|
2042
2055
|
// src/features/billing/stripe-subscription/components/wizards/WizardProgressIndicator.tsx
|
|
2056
|
+
import { useTranslations as useTranslations26 } from "next-intl";
|
|
2043
2057
|
import { Check as Check3 } from "lucide-react";
|
|
2044
2058
|
import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2045
2059
|
var STEPS = [
|
|
2046
|
-
{ key: "plan-selection", label: "
|
|
2047
|
-
{ key: "review", label: "
|
|
2048
|
-
{ key: "payment-method", label: "
|
|
2060
|
+
{ key: "plan-selection", label: "billing.ui.wizard.steps.select_plan" },
|
|
2061
|
+
{ key: "review", label: "billing.ui.wizard.steps.review" },
|
|
2062
|
+
{ key: "payment-method", label: "billing.ui.wizard.steps.payment" }
|
|
2049
2063
|
];
|
|
2050
2064
|
function getStepIndex(step) {
|
|
2051
2065
|
return STEPS.findIndex((s) => s.key === step);
|
|
2052
2066
|
}
|
|
2053
2067
|
__name(getStepIndex, "getStepIndex");
|
|
2054
2068
|
function WizardProgressIndicator({ currentStep }) {
|
|
2069
|
+
const t = useTranslations26();
|
|
2055
2070
|
const currentIndex = getStepIndex(currentStep);
|
|
2056
2071
|
return /* @__PURE__ */ jsx26("div", { className: "flex items-center justify-center gap-x-2 py-4", children: STEPS.map((step, index) => {
|
|
2057
2072
|
const isCompleted = index < currentIndex;
|
|
@@ -2064,7 +2079,7 @@ function WizardProgressIndicator({ currentStep }) {
|
|
|
2064
2079
|
children: isCompleted ? /* @__PURE__ */ jsx26(Check3, { className: "h-4 w-4" }) : index + 1
|
|
2065
2080
|
}
|
|
2066
2081
|
),
|
|
2067
|
-
/* @__PURE__ */ jsx26("span", { className: `text-sm ${isCurrent ? "font-medium text-foreground" : "text-muted-foreground"}`, children: step.label }),
|
|
2082
|
+
/* @__PURE__ */ jsx26("span", { className: `text-sm ${isCurrent ? "font-medium text-foreground" : "text-muted-foreground"}`, children: t(step.label) }),
|
|
2068
2083
|
index < STEPS.length - 1 && /* @__PURE__ */ jsx26("div", { className: `h-0.5 w-8 ${index < currentIndex ? "bg-primary" : "bg-muted"}` })
|
|
2069
2084
|
] }, step.key);
|
|
2070
2085
|
}) });
|
|
@@ -2072,6 +2087,7 @@ function WizardProgressIndicator({ currentStep }) {
|
|
|
2072
2087
|
__name(WizardProgressIndicator, "WizardProgressIndicator");
|
|
2073
2088
|
|
|
2074
2089
|
// src/features/billing/stripe-subscription/components/wizards/WizardStepPlanSelection.tsx
|
|
2090
|
+
import { useTranslations as useTranslations27 } from "next-intl";
|
|
2075
2091
|
import { useEffect as useEffect6, useMemo as useMemo2, useState as useState11 } from "react";
|
|
2076
2092
|
import { jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2077
2093
|
function WizardStepPlanSelection({
|
|
@@ -2085,6 +2101,7 @@ function WizardStepPlanSelection({
|
|
|
2085
2101
|
onNext,
|
|
2086
2102
|
isProcessing
|
|
2087
2103
|
}) {
|
|
2104
|
+
const t = useTranslations27();
|
|
2088
2105
|
const [products, setProducts] = useState11([]);
|
|
2089
2106
|
const [loading, setLoading] = useState11(true);
|
|
2090
2107
|
useEffect6(() => {
|
|
@@ -2141,15 +2158,17 @@ function WizardStepPlanSelection({
|
|
|
2141
2158
|
onSelectPrice: handleSelectPrice
|
|
2142
2159
|
}
|
|
2143
2160
|
),
|
|
2144
|
-
/* @__PURE__ */ jsx27("div", { className: "flex justify-end pt-4 border-t", children: /* @__PURE__ */ jsx27(Button, { onClick: onNext, disabled: !selectedPrice || isProcessing, children: isProcessing ? "
|
|
2161
|
+
/* @__PURE__ */ jsx27("div", { className: "flex justify-end pt-4 border-t", children: /* @__PURE__ */ jsx27(Button, { onClick: onNext, disabled: !selectedPrice || isProcessing, children: isProcessing ? t("common.loading") : t("billing.ui.wizard.next_review") }) })
|
|
2145
2162
|
] });
|
|
2146
2163
|
}
|
|
2147
2164
|
__name(WizardStepPlanSelection, "WizardStepPlanSelection");
|
|
2148
2165
|
|
|
2149
2166
|
// src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx
|
|
2167
|
+
import { useTranslations as useTranslations29 } from "next-intl";
|
|
2150
2168
|
import { AlertCircle } from "lucide-react";
|
|
2151
2169
|
|
|
2152
2170
|
// src/features/billing/stripe-promotion-code/components/PromoCodeInput.tsx
|
|
2171
|
+
import { useTranslations as useTranslations28 } from "next-intl";
|
|
2153
2172
|
import { useState as useState12 } from "react";
|
|
2154
2173
|
import { Check as Check4, X, Loader2 as Loader22 } from "lucide-react";
|
|
2155
2174
|
import { jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
@@ -2161,6 +2180,8 @@ function PromoCodeInput({
|
|
|
2161
2180
|
onRemove,
|
|
2162
2181
|
disabled = false
|
|
2163
2182
|
}) {
|
|
2183
|
+
const t = useTranslations28();
|
|
2184
|
+
const locale = useI18nLocale();
|
|
2164
2185
|
const [code, setCode] = useState12("");
|
|
2165
2186
|
const handleApply = /* @__PURE__ */ __name(() => {
|
|
2166
2187
|
if (code.trim()) {
|
|
@@ -2175,20 +2196,20 @@ function PromoCodeInput({
|
|
|
2175
2196
|
}, "handleKeyDown");
|
|
2176
2197
|
const formatDiscount = /* @__PURE__ */ __name((result) => {
|
|
2177
2198
|
if (result.discountType === "percent_off") {
|
|
2178
|
-
return
|
|
2199
|
+
return t("billing.ui.wizard.review.percent_off", { value: String(result.discountValue) });
|
|
2179
2200
|
}
|
|
2180
2201
|
const amount = (result.discountValue || 0) / 100;
|
|
2181
2202
|
const currency = result.currency?.toUpperCase() || "USD";
|
|
2182
|
-
return `${currency} ${amount
|
|
2203
|
+
return t("billing.ui.wizard.review.amount_off", { amount: `${currency} ${formatFixed(amount, locale, 2)}` });
|
|
2183
2204
|
}, "formatDiscount");
|
|
2184
2205
|
const formatDuration = /* @__PURE__ */ __name((result) => {
|
|
2185
2206
|
switch (result.duration) {
|
|
2186
2207
|
case "forever":
|
|
2187
|
-
return "
|
|
2208
|
+
return t("billing.ui.promo_code.duration_forever");
|
|
2188
2209
|
case "once":
|
|
2189
|
-
return "
|
|
2210
|
+
return t("billing.ui.promo_code.duration_once");
|
|
2190
2211
|
case "repeating":
|
|
2191
|
-
return
|
|
2212
|
+
return t("billing.ui.promo_code.duration_repeating", { months: String(result.durationInMonths) });
|
|
2192
2213
|
default:
|
|
2193
2214
|
return "";
|
|
2194
2215
|
}
|
|
@@ -2221,7 +2242,7 @@ function PromoCodeInput({
|
|
|
2221
2242
|
/* @__PURE__ */ jsx28(
|
|
2222
2243
|
Input,
|
|
2223
2244
|
{
|
|
2224
|
-
placeholder: "
|
|
2245
|
+
placeholder: t("billing.ui.promo_code.placeholder"),
|
|
2225
2246
|
value: code,
|
|
2226
2247
|
onChange: (e) => setCode(e.target.value.toUpperCase()),
|
|
2227
2248
|
onKeyDown: handleKeyDown,
|
|
@@ -2229,7 +2250,7 @@ function PromoCodeInput({
|
|
|
2229
2250
|
className: "flex-1"
|
|
2230
2251
|
}
|
|
2231
2252
|
),
|
|
2232
|
-
/* @__PURE__ */ jsx28(Button, { variant: "outline", onClick: handleApply, disabled: disabled || isValidating || !code.trim(), children: isValidating ? /* @__PURE__ */ jsx28(Loader22, { className: "h-4 w-4 animate-spin" }) : "
|
|
2253
|
+
/* @__PURE__ */ jsx28(Button, { variant: "outline", onClick: handleApply, disabled: disabled || isValidating || !code.trim(), children: isValidating ? /* @__PURE__ */ jsx28(Loader22, { className: "h-4 w-4 animate-spin" }) : t("billing.ui.promo_code.apply") })
|
|
2233
2254
|
] }),
|
|
2234
2255
|
error && /* @__PURE__ */ jsx28("p", { className: "text-destructive text-xs/relaxed", children: error })
|
|
2235
2256
|
] });
|
|
@@ -2255,14 +2276,16 @@ function WizardStepReview({
|
|
|
2255
2276
|
onRemovePromoCode,
|
|
2256
2277
|
isTrialUpgrade
|
|
2257
2278
|
}) {
|
|
2279
|
+
const t = useTranslations29();
|
|
2280
|
+
const fmt = useBillingFormatOptions();
|
|
2258
2281
|
if (!selectedPrice) {
|
|
2259
|
-
return /* @__PURE__ */ jsx29("div", { className: "text-center py-8 text-muted-foreground", children: "
|
|
2282
|
+
return /* @__PURE__ */ jsx29("div", { className: "text-center py-8 text-muted-foreground", children: t("billing.ui.wizard.review.no_plan") });
|
|
2260
2283
|
}
|
|
2261
2284
|
const isChangingPlan = subscription && subscription.price?.id !== selectedPrice.id;
|
|
2262
2285
|
const formatInterval2 = /* @__PURE__ */ __name((price) => {
|
|
2263
|
-
if (price.priceType === "one_time") return "
|
|
2286
|
+
if (price.priceType === "one_time") return t("billing.ui.wizard.review.interval_one_time");
|
|
2264
2287
|
const interval = price.recurring?.interval || "month";
|
|
2265
|
-
return interval === "year" ? "
|
|
2288
|
+
return interval === "year" ? t("billing.ui.wizard.review.interval_yearly") : t("billing.ui.wizard.review.interval_monthly");
|
|
2266
2289
|
}, "formatInterval");
|
|
2267
2290
|
const calculateDiscountedPrice = /* @__PURE__ */ __name(() => {
|
|
2268
2291
|
if (!promotionCode?.valid || !selectedPrice.unitAmount) return null;
|
|
@@ -2291,17 +2314,19 @@ function WizardStepReview({
|
|
|
2291
2314
|
const getDiscountDescription = /* @__PURE__ */ __name(() => {
|
|
2292
2315
|
if (!promotionCode?.valid) return null;
|
|
2293
2316
|
if (promotionCode.discountType === "percent_off" && promotionCode.discountValue) {
|
|
2294
|
-
return
|
|
2317
|
+
return t("billing.ui.wizard.review.percent_off", { value: promotionCode.discountValue });
|
|
2295
2318
|
}
|
|
2296
2319
|
if (promotionCode.discountType === "amount_off" && promotionCode.discountValue) {
|
|
2297
|
-
return
|
|
2320
|
+
return t("billing.ui.wizard.review.amount_off", {
|
|
2321
|
+
amount: formatCurrency(promotionCode.discountValue, promotionCode.currency || selectedPrice.currency, fmt)
|
|
2322
|
+
});
|
|
2298
2323
|
}
|
|
2299
2324
|
return null;
|
|
2300
2325
|
}, "getDiscountDescription");
|
|
2301
2326
|
const discountDescription = getDiscountDescription();
|
|
2302
2327
|
return /* @__PURE__ */ jsxs26("div", { className: "space-y-6", children: [
|
|
2303
2328
|
/* @__PURE__ */ jsxs26("div", { className: "bg-muted/50 rounded-lg p-4 space-y-3", children: [
|
|
2304
|
-
/* @__PURE__ */ jsx29(SectionHeader, { children: "
|
|
2329
|
+
/* @__PURE__ */ jsx29(SectionHeader, { children: t("billing.ui.wizard.review.selected_plan") }),
|
|
2305
2330
|
/* @__PURE__ */ jsxs26("div", { className: "flex justify-between items-center", children: [
|
|
2306
2331
|
/* @__PURE__ */ jsxs26("div", { children: [
|
|
2307
2332
|
/* @__PURE__ */ jsx29("p", { className: "font-medium", children: selectedPrice.product?.name }),
|
|
@@ -2309,10 +2334,10 @@ function WizardStepReview({
|
|
|
2309
2334
|
] }),
|
|
2310
2335
|
/* @__PURE__ */ jsxs26("div", { className: "text-end", children: [
|
|
2311
2336
|
discountedPrice !== null ? /* @__PURE__ */ jsxs26(Fragment6, { children: [
|
|
2312
|
-
/* @__PURE__ */ jsx29("p", { className: "text-sm text-muted-foreground line-through", children: formatCurrency(selectedPrice.unitAmount || 0, selectedPrice.currency) }),
|
|
2313
|
-
/* @__PURE__ */ jsx29("p", { className: "text-success text-lg font-semibold", children: formatCurrency(discountedPrice, selectedPrice.currency) }),
|
|
2337
|
+
/* @__PURE__ */ jsx29("p", { className: "text-sm text-muted-foreground line-through", children: formatCurrency(selectedPrice.unitAmount || 0, selectedPrice.currency, fmt) }),
|
|
2338
|
+
/* @__PURE__ */ jsx29("p", { className: "text-success text-lg font-semibold", children: formatCurrency(discountedPrice, selectedPrice.currency, fmt) }),
|
|
2314
2339
|
discountDescription && /* @__PURE__ */ jsx29(Badge, { variant: "softGreen", children: discountDescription })
|
|
2315
|
-
] }) : /* @__PURE__ */ jsx29("p", { className: "font-semibold text-lg", children: formatCurrency(selectedPrice.unitAmount || 0, selectedPrice.currency) }),
|
|
2340
|
+
] }) : /* @__PURE__ */ jsx29("p", { className: "font-semibold text-lg", children: formatCurrency(selectedPrice.unitAmount || 0, selectedPrice.currency, fmt) }),
|
|
2316
2341
|
/* @__PURE__ */ jsx29("p", { className: "text-sm text-muted-foreground", children: formatInterval2(selectedPrice) })
|
|
2317
2342
|
] })
|
|
2318
2343
|
] })
|
|
@@ -2322,20 +2347,20 @@ function WizardStepReview({
|
|
|
2322
2347
|
{
|
|
2323
2348
|
className: `${isTrialUpgrade ? "bg-warning/15 border-warning/30" : "bg-primary/10 border-primary/30"} space-y-2 rounded-lg border p-4`,
|
|
2324
2349
|
children: [
|
|
2325
|
-
/* @__PURE__ */ jsx29("h4", { className: `font-medium ${isTrialUpgrade ? "text-warning" : "text-primary"}`, children: isTrialUpgrade ? "
|
|
2326
|
-
/* @__PURE__ */ jsx29("p", { className: `text-sm ${isTrialUpgrade ? "text-warning" : "text-foreground"}`, children: isTrialUpgrade ? "
|
|
2350
|
+
/* @__PURE__ */ jsx29("h4", { className: `font-medium ${isTrialUpgrade ? "text-warning" : "text-primary"}`, children: isTrialUpgrade ? t("billing.ui.wizard.review.trial_upgrade") : t("billing.ui.wizard.review.proration_summary") }),
|
|
2351
|
+
/* @__PURE__ */ jsx29("p", { className: `text-sm ${isTrialUpgrade ? "text-warning" : "text-foreground"}`, children: isTrialUpgrade ? t("billing.ui.wizard.review.trial_upgrade_description") : t("billing.ui.wizard.review.proration_description") }),
|
|
2327
2352
|
/* @__PURE__ */ jsxs26("div", { className: "flex justify-between text-sm", children: [
|
|
2328
|
-
/* @__PURE__ */ jsx29("span", { className: `${isTrialUpgrade ? "text-warning" : "text-muted-foreground"}`, children: isTrialUpgrade ? "
|
|
2353
|
+
/* @__PURE__ */ jsx29("span", { className: `${isTrialUpgrade ? "text-warning" : "text-muted-foreground"}`, children: isTrialUpgrade ? t("billing.ui.wizard.review.charge_now") : t("billing.ui.wizard.review.due_now") }),
|
|
2329
2354
|
/* @__PURE__ */ jsx29("span", { className: `font-medium ${isTrialUpgrade ? "text-warning" : "text-foreground"}`, children: discountedImmediateCharge !== null ? /* @__PURE__ */ jsxs26(Fragment6, { children: [
|
|
2330
|
-
/* @__PURE__ */ jsx29("span", { className: "line-through text-muted-foreground me-2", children: formatCurrency(prorationPreview.immediateCharge, prorationPreview.currency) }),
|
|
2331
|
-
/* @__PURE__ */ jsx29("span", { className: "text-success", children: formatCurrency(discountedImmediateCharge, prorationPreview.currency) })
|
|
2332
|
-
] }) : formatCurrency(prorationPreview.immediateCharge, prorationPreview.currency) })
|
|
2355
|
+
/* @__PURE__ */ jsx29("span", { className: "line-through text-muted-foreground me-2", children: formatCurrency(prorationPreview.immediateCharge, prorationPreview.currency, fmt) }),
|
|
2356
|
+
/* @__PURE__ */ jsx29("span", { className: "text-success", children: formatCurrency(discountedImmediateCharge, prorationPreview.currency, fmt) })
|
|
2357
|
+
] }) : formatCurrency(prorationPreview.immediateCharge, prorationPreview.currency, fmt) })
|
|
2333
2358
|
] })
|
|
2334
2359
|
]
|
|
2335
2360
|
}
|
|
2336
2361
|
),
|
|
2337
2362
|
/* @__PURE__ */ jsxs26("div", { className: "border rounded-lg p-4 space-y-3", children: [
|
|
2338
|
-
/* @__PURE__ */ jsx29("h4", { className: "font-medium", children: "
|
|
2363
|
+
/* @__PURE__ */ jsx29("h4", { className: "font-medium", children: t("billing.ui.wizard.review.promotion_code") }),
|
|
2339
2364
|
/* @__PURE__ */ jsx29(
|
|
2340
2365
|
PromoCodeInput,
|
|
2341
2366
|
{
|
|
@@ -2350,30 +2375,32 @@ function WizardStepReview({
|
|
|
2350
2375
|
] }),
|
|
2351
2376
|
/* @__PURE__ */ jsx29("div", { className: "border rounded-lg p-4", children: /* @__PURE__ */ jsxs26("div", { className: "flex justify-between items-center", children: [
|
|
2352
2377
|
/* @__PURE__ */ jsxs26("div", { children: [
|
|
2353
|
-
/* @__PURE__ */ jsx29("h4", { className: "font-medium", children: "
|
|
2354
|
-
/* @__PURE__ */ jsx29("p", { className: "text-sm text-muted-foreground", children: hasPaymentMethod ? "
|
|
2378
|
+
/* @__PURE__ */ jsx29("h4", { className: "font-medium", children: t("billing.ui.payment_method.title") }),
|
|
2379
|
+
/* @__PURE__ */ jsx29("p", { className: "text-sm text-muted-foreground", children: hasPaymentMethod ? t("billing.ui.wizard.review.payment_on_file") : t("billing.ui.wizard.review.no_payment_on_file") })
|
|
2355
2380
|
] }),
|
|
2356
|
-
!hasPaymentMethod && /* @__PURE__ */ jsx29(Button, { variant: "outline", onClick: onAddPaymentMethod, children: "
|
|
2381
|
+
!hasPaymentMethod && /* @__PURE__ */ jsx29(Button, { variant: "outline", onClick: onAddPaymentMethod, children: t("billing.ui.payment_methods.add") })
|
|
2357
2382
|
] }) }),
|
|
2358
2383
|
error && /* @__PURE__ */ jsxs26(Alert, { variant: "destructive", children: [
|
|
2359
2384
|
/* @__PURE__ */ jsx29(AlertCircle, { className: "h-4 w-4" }),
|
|
2360
2385
|
/* @__PURE__ */ jsx29(AlertDescription, { children: error })
|
|
2361
2386
|
] }),
|
|
2362
2387
|
/* @__PURE__ */ jsxs26("div", { className: "flex justify-between pt-4 border-t", children: [
|
|
2363
|
-
/* @__PURE__ */ jsx29(Button, { variant: "outline", onClick: onBack, disabled: isProcessing, children: "
|
|
2364
|
-
/* @__PURE__ */ jsx29(Button, { onClick: hasPaymentMethod ? onConfirm : onAddPaymentMethod, disabled: isProcessing, children: isProcessing ? "
|
|
2388
|
+
/* @__PURE__ */ jsx29(Button, { variant: "outline", onClick: onBack, disabled: isProcessing, children: t("billing.ui.wizard.back") }),
|
|
2389
|
+
/* @__PURE__ */ jsx29(Button, { onClick: hasPaymentMethod ? onConfirm : onAddPaymentMethod, disabled: isProcessing, children: isProcessing ? t("billing.ui.wizard.review.processing") : hasPaymentMethod ? isChangingPlan ? t("billing.ui.wizard.review.confirm_change") : t("billing.ui.wizard.review.subscribe_now") : t("billing.ui.payment_methods.add") })
|
|
2365
2390
|
] })
|
|
2366
2391
|
] });
|
|
2367
2392
|
}
|
|
2368
2393
|
__name(WizardStepReview, "WizardStepReview");
|
|
2369
2394
|
|
|
2370
2395
|
// src/features/billing/stripe-subscription/components/wizards/WizardStepPaymentMethod.tsx
|
|
2396
|
+
import { useTranslations as useTranslations30 } from "next-intl";
|
|
2371
2397
|
import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2372
2398
|
function WizardStepPaymentMethod({ onBack, onSuccess, isProcessing }) {
|
|
2399
|
+
const t = useTranslations30();
|
|
2373
2400
|
return /* @__PURE__ */ jsxs27("div", { className: "space-y-6", children: [
|
|
2374
2401
|
/* @__PURE__ */ jsxs27("div", { className: "text-center", children: [
|
|
2375
|
-
/* @__PURE__ */ jsx30(SectionHeader, { children: "
|
|
2376
|
-
/* @__PURE__ */ jsx30("p", { className: "text-sm text-muted-foreground", children: "
|
|
2402
|
+
/* @__PURE__ */ jsx30(SectionHeader, { children: t("billing.ui.payment_methods.add") }),
|
|
2403
|
+
/* @__PURE__ */ jsx30("p", { className: "text-sm text-muted-foreground", children: t("billing.ui.wizard.payment_description") })
|
|
2377
2404
|
] }),
|
|
2378
2405
|
/* @__PURE__ */ jsx30(PaymentMethodForm, { onSuccess, onCancel: onBack, isLoading: isProcessing })
|
|
2379
2406
|
] });
|
|
@@ -2389,6 +2416,7 @@ function SubscriptionWizard({
|
|
|
2389
2416
|
hasActiveRecurringSubscription,
|
|
2390
2417
|
subscription
|
|
2391
2418
|
}) {
|
|
2419
|
+
const t = useTranslations31();
|
|
2392
2420
|
const handleClose = useCallback3(() => onOpenChange(false), [onOpenChange]);
|
|
2393
2421
|
const { state, actions } = useSubscriptionWizard({
|
|
2394
2422
|
subscription,
|
|
@@ -2412,8 +2440,8 @@ function SubscriptionWizard({
|
|
|
2412
2440
|
}, [open, actions.reset]);
|
|
2413
2441
|
const isPurchasingAddons = hasActiveRecurringSubscription && !subscription;
|
|
2414
2442
|
const isChangePlanMode = !!subscription;
|
|
2415
|
-
const dialogTitle = subscription ? "
|
|
2416
|
-
const dialogDescription = subscription ? "
|
|
2443
|
+
const dialogTitle = subscription ? t("billing.ui.wizard.change_title") : isPurchasingAddons ? t("billing.ui.subscriptions.purchase_addons") : t("billing.ui.subscriptions.subscribe");
|
|
2444
|
+
const dialogDescription = subscription ? t("billing.ui.wizard.change_description") : isPurchasingAddons ? t("billing.ui.wizard.addons_description") : t("billing.ui.wizard.subscribe_description");
|
|
2417
2445
|
return /* @__PURE__ */ jsx31(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs28(DialogContent, { className: "max-w-2xl", children: [
|
|
2418
2446
|
/* @__PURE__ */ jsxs28(DialogHeader, { children: [
|
|
2419
2447
|
/* @__PURE__ */ jsx31(DialogTitle, { children: dialogTitle }),
|
|
@@ -2467,10 +2495,12 @@ function SubscriptionWizard({
|
|
|
2467
2495
|
__name(SubscriptionWizard, "SubscriptionWizard");
|
|
2468
2496
|
|
|
2469
2497
|
// src/features/billing/stripe-usage/components/containers/UsageContainer.tsx
|
|
2498
|
+
import { useTranslations as useTranslations33 } from "next-intl";
|
|
2470
2499
|
import { Activity as Activity3 } from "lucide-react";
|
|
2471
2500
|
import { useEffect as useEffect8, useState as useState13 } from "react";
|
|
2472
2501
|
|
|
2473
2502
|
// src/features/billing/stripe-usage/components/details/UsageSummaryCard.tsx
|
|
2503
|
+
import { useTranslations as useTranslations32 } from "next-intl";
|
|
2474
2504
|
import { Activity as Activity2 } from "lucide-react";
|
|
2475
2505
|
import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2476
2506
|
function getProgressColor(percentage) {
|
|
@@ -2480,19 +2510,21 @@ function getProgressColor(percentage) {
|
|
|
2480
2510
|
return "bg-green-500";
|
|
2481
2511
|
}
|
|
2482
2512
|
__name(getProgressColor, "getProgressColor");
|
|
2483
|
-
function
|
|
2484
|
-
if (!date) return "
|
|
2513
|
+
function formatDate2(date, { locale, t }) {
|
|
2514
|
+
if (!date) return t("billing.ui.not_available");
|
|
2485
2515
|
try {
|
|
2486
|
-
return new Intl.DateTimeFormat(
|
|
2516
|
+
return new Intl.DateTimeFormat(locale, {
|
|
2487
2517
|
month: "short",
|
|
2488
2518
|
day: "numeric"
|
|
2489
2519
|
}).format(new Date(date));
|
|
2490
2520
|
} catch (_error) {
|
|
2491
|
-
return "
|
|
2521
|
+
return t("billing.ui.invalid_date");
|
|
2492
2522
|
}
|
|
2493
2523
|
}
|
|
2494
|
-
__name(
|
|
2524
|
+
__name(formatDate2, "formatDate");
|
|
2495
2525
|
function UsageSummaryCard({ meter, summary }) {
|
|
2526
|
+
const t = useTranslations32();
|
|
2527
|
+
const fmt = useBillingFormatOptions();
|
|
2496
2528
|
const currentUsage = summary?.aggregatedValue ?? 0;
|
|
2497
2529
|
const limit = meter.limit;
|
|
2498
2530
|
const percentage = limit && limit > 0 ? currentUsage / limit * 100 : null;
|
|
@@ -2510,26 +2542,19 @@ function UsageSummaryCard({ meter, summary }) {
|
|
|
2510
2542
|
] }),
|
|
2511
2543
|
/* @__PURE__ */ jsxs29(CardContent, { className: "flex flex-col gap-y-4", children: [
|
|
2512
2544
|
/* @__PURE__ */ jsxs29("div", { children: [
|
|
2513
|
-
/* @__PURE__ */ jsx32("p", { className: "text-3xl font-bold", children: currentUsage.toLocaleString() }),
|
|
2514
|
-
hasLimit && /* @__PURE__ */
|
|
2515
|
-
"of ",
|
|
2516
|
-
limit.toLocaleString(),
|
|
2517
|
-
" used"
|
|
2518
|
-
] })
|
|
2545
|
+
/* @__PURE__ */ jsx32("p", { className: "text-3xl font-bold", children: currentUsage.toLocaleString(fmt.locale) }),
|
|
2546
|
+
hasLimit && /* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-sm", children: t("billing.ui.usage.of_limit_used", { limit: limit.toLocaleString(fmt.locale) }) })
|
|
2519
2547
|
] }),
|
|
2520
2548
|
hasLimit ? /* @__PURE__ */ jsxs29("div", { className: "flex flex-col gap-y-2", children: [
|
|
2521
2549
|
/* @__PURE__ */ jsx32("div", { className: "h-2 w-full overflow-hidden rounded-full bg-gray-200", children: /* @__PURE__ */ jsx32("div", { className: `h-full transition-all ${progressColor}`, style: { width: `${progressWidth}%` } }) }),
|
|
2522
|
-
/* @__PURE__ */
|
|
2523
|
-
percentage
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
" - ",
|
|
2531
|
-
formatDate4(summary.end)
|
|
2532
|
-
] }) })
|
|
2550
|
+
/* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-sm", children: t("billing.ui.usage.percent_used", {
|
|
2551
|
+
value: percentage !== null ? formatFixed(percentage, fmt.locale, 1) : ""
|
|
2552
|
+
}) })
|
|
2553
|
+
] }) : /* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-sm", children: t("billing.ui.usage.no_limit") }),
|
|
2554
|
+
summary && summary.start && summary.end && /* @__PURE__ */ jsx32("div", { className: "border-t pt-3", children: /* @__PURE__ */ jsx32("p", { className: "text-muted-foreground text-xs", children: t("billing.ui.usage.period", {
|
|
2555
|
+
start: formatDate2(summary.start, fmt),
|
|
2556
|
+
end: formatDate2(summary.end, fmt)
|
|
2557
|
+
}) }) })
|
|
2533
2558
|
] })
|
|
2534
2559
|
] });
|
|
2535
2560
|
}
|
|
@@ -2545,6 +2570,7 @@ __name(UsageSummaryCards, "UsageSummaryCards");
|
|
|
2545
2570
|
// src/features/billing/stripe-usage/components/containers/UsageContainer.tsx
|
|
2546
2571
|
import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2547
2572
|
function UsageContainer() {
|
|
2573
|
+
const t = useTranslations33();
|
|
2548
2574
|
const [meters, setMeters] = useState13([]);
|
|
2549
2575
|
const [summaries, setSummaries] = useState13({});
|
|
2550
2576
|
const [loading, setLoading] = useState13(true);
|
|
@@ -2593,18 +2619,18 @@ function UsageContainer() {
|
|
|
2593
2619
|
return null;
|
|
2594
2620
|
}
|
|
2595
2621
|
if (loading) {
|
|
2596
|
-
return /* @__PURE__ */ jsx34("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx34("p", { className: "text-muted-foreground", children: "
|
|
2622
|
+
return /* @__PURE__ */ jsx34("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx34("p", { className: "text-muted-foreground", children: t("billing.ui.usage.loading") }) });
|
|
2597
2623
|
}
|
|
2598
2624
|
return /* @__PURE__ */ jsxs30("div", { className: "flex w-full flex-col gap-y-6", children: [
|
|
2599
2625
|
/* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-x-3", children: [
|
|
2600
2626
|
/* @__PURE__ */ jsx34(Activity3, { className: "h-8 w-8" }),
|
|
2601
|
-
/* @__PURE__ */ jsx34("h1", { className: "text-primary text-3xl font-semibold", children: "
|
|
2627
|
+
/* @__PURE__ */ jsx34("h1", { className: "text-primary text-3xl font-semibold", children: t("billing.ui.usage.title") })
|
|
2602
2628
|
] }),
|
|
2603
2629
|
meters.length === 0 && /* @__PURE__ */ jsxs30("div", { className: "bg-muted/50 flex flex-col items-center justify-center gap-y-4 rounded-lg border-2 border-dashed border-gray-300 p-12", children: [
|
|
2604
2630
|
/* @__PURE__ */ jsx34(Activity3, { className: "text-muted-foreground h-16 w-16" }),
|
|
2605
2631
|
/* @__PURE__ */ jsxs30("div", { className: "text-center", children: [
|
|
2606
|
-
/* @__PURE__ */ jsx34("h3", { className: "mb-2 text-sm font-medium", children: "
|
|
2607
|
-
/* @__PURE__ */ jsx34("p", { className: "text-muted-foreground", children: "
|
|
2632
|
+
/* @__PURE__ */ jsx34("h3", { className: "mb-2 text-sm font-medium", children: t("billing.ui.usage.empty_title") }),
|
|
2633
|
+
/* @__PURE__ */ jsx34("p", { className: "text-muted-foreground", children: t("billing.ui.usage.empty_description") })
|
|
2608
2634
|
] })
|
|
2609
2635
|
] }),
|
|
2610
2636
|
meters.length > 0 && /* @__PURE__ */ jsx34(UsageSummaryCards, { meters, summaries })
|
|
@@ -2613,12 +2639,13 @@ function UsageContainer() {
|
|
|
2613
2639
|
__name(UsageContainer, "UsageContainer");
|
|
2614
2640
|
|
|
2615
2641
|
// src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx
|
|
2642
|
+
import { useTranslations as useTranslations34 } from "next-intl";
|
|
2616
2643
|
import { jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2617
|
-
function formatDateTime(date) {
|
|
2618
|
-
if (!date) return "
|
|
2644
|
+
function formatDateTime(date, { locale, t }) {
|
|
2645
|
+
if (!date) return t("billing.ui.not_available");
|
|
2619
2646
|
const dateObj = typeof date === "string" ? new Date(date) : date;
|
|
2620
2647
|
try {
|
|
2621
|
-
return new Intl.DateTimeFormat(
|
|
2648
|
+
return new Intl.DateTimeFormat(locale, {
|
|
2622
2649
|
month: "short",
|
|
2623
2650
|
day: "numeric",
|
|
2624
2651
|
year: "numeric",
|
|
@@ -2626,26 +2653,28 @@ function formatDateTime(date) {
|
|
|
2626
2653
|
minute: "2-digit"
|
|
2627
2654
|
}).format(dateObj);
|
|
2628
2655
|
} catch (_error) {
|
|
2629
|
-
return "
|
|
2656
|
+
return t("billing.ui.invalid_date");
|
|
2630
2657
|
}
|
|
2631
2658
|
}
|
|
2632
2659
|
__name(formatDateTime, "formatDateTime");
|
|
2633
2660
|
function UsageHistoryTable({ usageRecords }) {
|
|
2661
|
+
const t = useTranslations34();
|
|
2662
|
+
const fmt = useBillingFormatOptions();
|
|
2634
2663
|
if (usageRecords.length === 0) {
|
|
2635
|
-
return /* @__PURE__ */ jsx35("div", { className: "rounded-lg border p-8 text-center", children: /* @__PURE__ */ jsx35("p", { className: "text-muted-foreground", children: "
|
|
2664
|
+
return /* @__PURE__ */ jsx35("div", { className: "rounded-lg border p-8 text-center", children: /* @__PURE__ */ jsx35("p", { className: "text-muted-foreground", children: t("billing.ui.usage.history_empty") }) });
|
|
2636
2665
|
}
|
|
2637
2666
|
return /* @__PURE__ */ jsxs31("div", { className: "flex w-full flex-col gap-y-4", children: [
|
|
2638
|
-
/* @__PURE__ */ jsx35(SectionHeader, { level: 2, children: "
|
|
2667
|
+
/* @__PURE__ */ jsx35(SectionHeader, { level: 2, children: t("billing.ui.usage.history_title") }),
|
|
2639
2668
|
/* @__PURE__ */ jsx35("div", { className: "overflow-clip rounded-lg border", children: /* @__PURE__ */ jsxs31(Table, { children: [
|
|
2640
2669
|
/* @__PURE__ */ jsx35(TableHeader, { className: "bg-muted", children: /* @__PURE__ */ jsxs31(TableRow, { children: [
|
|
2641
|
-
/* @__PURE__ */ jsx35(TableHead, { children: "
|
|
2642
|
-
/* @__PURE__ */ jsx35(TableHead, { children: "
|
|
2643
|
-
/* @__PURE__ */ jsx35(TableHead, { className: "text-end", children: "
|
|
2644
|
-
/* @__PURE__ */ jsx35(TableHead, { children: "
|
|
2670
|
+
/* @__PURE__ */ jsx35(TableHead, { children: t("billing.ui.columns.date_time") }),
|
|
2671
|
+
/* @__PURE__ */ jsx35(TableHead, { children: t("billing.ui.columns.meter_event") }),
|
|
2672
|
+
/* @__PURE__ */ jsx35(TableHead, { className: "text-end", children: t("billing.ui.columns.quantity") }),
|
|
2673
|
+
/* @__PURE__ */ jsx35(TableHead, { children: t("billing.ui.columns.event_id") })
|
|
2645
2674
|
] }) }),
|
|
2646
2675
|
/* @__PURE__ */ jsx35(TableBody, { children: usageRecords.map((record) => {
|
|
2647
|
-
const dateTime = formatDateTime(record.timestamp);
|
|
2648
|
-
const quantity = record.quantity.toLocaleString();
|
|
2676
|
+
const dateTime = formatDateTime(record.timestamp, fmt);
|
|
2677
|
+
const quantity = record.quantity.toLocaleString(fmt.locale);
|
|
2649
2678
|
return /* @__PURE__ */ jsxs31(TableRow, { children: [
|
|
2650
2679
|
/* @__PURE__ */ jsx35(TableCell, { className: "font-medium", children: dateTime }),
|
|
2651
2680
|
/* @__PURE__ */ jsx35(TableCell, { className: "text-muted-foreground", children: record.meterEventName }),
|
|
@@ -2669,17 +2698,19 @@ function BillingDetailModal({ open, onOpenChange, title, children, className })
|
|
|
2669
2698
|
__name(BillingDetailModal, "BillingDetailModal");
|
|
2670
2699
|
|
|
2671
2700
|
// src/features/billing/components/widgets/BillingAlertBanner.tsx
|
|
2701
|
+
import { useTranslations as useTranslations35 } from "next-intl";
|
|
2672
2702
|
import { AlertCircle as AlertCircle2 } from "lucide-react";
|
|
2673
2703
|
import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2674
2704
|
function BillingAlertBanner({ subscription, onUpdatePayment, onAddPayment }) {
|
|
2705
|
+
const t = useTranslations35();
|
|
2675
2706
|
if (subscription.status === "past_due" /* PAST_DUE */) {
|
|
2676
2707
|
return /* @__PURE__ */ jsxs33("div", { className: "bg-red-50 border border-red-200 rounded-lg p-4 flex items-start gap-x-3", children: [
|
|
2677
2708
|
/* @__PURE__ */ jsx37(AlertCircle2, { className: "text-destructive mt-0.5 h-5 w-5" }),
|
|
2678
2709
|
/* @__PURE__ */ jsxs33("div", { className: "flex-1", children: [
|
|
2679
|
-
/* @__PURE__ */ jsx37("h3", { className: "text-destructive text-sm font-medium", children: "
|
|
2680
|
-
/* @__PURE__ */ jsx37("p", { className: "text-destructive mt-1 text-sm", children: "
|
|
2710
|
+
/* @__PURE__ */ jsx37("h3", { className: "text-destructive text-sm font-medium", children: t("billing.ui.alert.payment_failed_title") }),
|
|
2711
|
+
/* @__PURE__ */ jsx37("p", { className: "text-destructive mt-1 text-sm", children: t("billing.ui.alert.payment_failed_description") })
|
|
2681
2712
|
] }),
|
|
2682
|
-
onUpdatePayment && /* @__PURE__ */ jsx37(Button, { variant: "outline", size: "sm", onClick: onUpdatePayment, className: "text-destructive border-red-300", children: "
|
|
2713
|
+
onUpdatePayment && /* @__PURE__ */ jsx37(Button, { variant: "outline", size: "sm", onClick: onUpdatePayment, className: "text-destructive border-red-300", children: t("billing.ui.alert.update_payment_method") })
|
|
2683
2714
|
] });
|
|
2684
2715
|
}
|
|
2685
2716
|
if (subscription.status === "trialing" /* TRIALING */ && subscription.trialEnd) {
|
|
@@ -2690,16 +2721,10 @@ function BillingAlertBanner({ subscription, onUpdatePayment, onAddPayment }) {
|
|
|
2690
2721
|
return /* @__PURE__ */ jsxs33("div", { className: "bg-yellow-50 border border-yellow-200 rounded-lg p-4 flex items-start gap-x-3", children: [
|
|
2691
2722
|
/* @__PURE__ */ jsx37(AlertCircle2, { className: "text-warning mt-0.5 h-5 w-5" }),
|
|
2692
2723
|
/* @__PURE__ */ jsxs33("div", { className: "flex-1", children: [
|
|
2693
|
-
/* @__PURE__ */ jsx37("h3", { className: "text-warning text-sm font-medium", children: "
|
|
2694
|
-
/* @__PURE__ */
|
|
2695
|
-
"Your trial ends in ",
|
|
2696
|
-
daysRemaining,
|
|
2697
|
-
" ",
|
|
2698
|
-
daysRemaining === 1 ? "day" : "days",
|
|
2699
|
-
". Add a payment method to continue your subscription."
|
|
2700
|
-
] })
|
|
2724
|
+
/* @__PURE__ */ jsx37("h3", { className: "text-warning text-sm font-medium", children: t("billing.ui.alert.trial_ending_title") }),
|
|
2725
|
+
/* @__PURE__ */ jsx37("p", { className: "text-warning mt-1 text-sm", children: t("billing.ui.alert.trial_ending_description", { count: daysRemaining }) })
|
|
2701
2726
|
] }),
|
|
2702
|
-
onAddPayment && /* @__PURE__ */ jsx37(Button, { variant: "outline", size: "sm", onClick: onAddPayment, className: "text-warning border-yellow-300", children: "
|
|
2727
|
+
onAddPayment && /* @__PURE__ */ jsx37(Button, { variant: "outline", size: "sm", onClick: onAddPayment, className: "text-warning border-yellow-300", children: t("billing.ui.payment_methods.add") })
|
|
2703
2728
|
] });
|
|
2704
2729
|
}
|
|
2705
2730
|
}
|
|
@@ -2710,6 +2735,7 @@ __name(BillingAlertBanner, "BillingAlertBanner");
|
|
|
2710
2735
|
// src/features/billing/components/containers/BillingDashboardContainer.tsx
|
|
2711
2736
|
import { Fragment as Fragment7, jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2712
2737
|
function BillingDashboardContainer() {
|
|
2738
|
+
const t = useTranslations36();
|
|
2713
2739
|
const [data, setData] = useState14({
|
|
2714
2740
|
customer: null,
|
|
2715
2741
|
subscriptions: [],
|
|
@@ -2759,7 +2785,7 @@ function BillingDashboardContainer() {
|
|
|
2759
2785
|
if (error?.status === 404) {
|
|
2760
2786
|
setNoCustomerExists(true);
|
|
2761
2787
|
} else {
|
|
2762
|
-
setErrors((prev) => ({ ...prev, customer: "
|
|
2788
|
+
setErrors((prev) => ({ ...prev, customer: "billing.ui.dashboard.errors.load_customer" }));
|
|
2763
2789
|
}
|
|
2764
2790
|
} finally {
|
|
2765
2791
|
setLoading((prev) => ({ ...prev, customer: false }));
|
|
@@ -2782,7 +2808,7 @@ function BillingDashboardContainer() {
|
|
|
2782
2808
|
return subscriptions2;
|
|
2783
2809
|
} catch (error) {
|
|
2784
2810
|
console.error("[BillingDashboard] Failed to load subscriptions:", error);
|
|
2785
|
-
setErrors((prev) => ({ ...prev, subscriptions: "
|
|
2811
|
+
setErrors((prev) => ({ ...prev, subscriptions: "billing.ui.dashboard.errors.load_subscriptions" }));
|
|
2786
2812
|
return [];
|
|
2787
2813
|
} finally {
|
|
2788
2814
|
setLoading((prev) => ({ ...prev, subscriptions: false }));
|
|
@@ -2795,7 +2821,7 @@ function BillingDashboardContainer() {
|
|
|
2795
2821
|
setErrors((prev) => ({ ...prev, paymentMethods: null }));
|
|
2796
2822
|
} catch (error) {
|
|
2797
2823
|
console.error("[BillingDashboard] Failed to load payment methods:", error);
|
|
2798
|
-
setErrors((prev) => ({ ...prev, paymentMethods: "
|
|
2824
|
+
setErrors((prev) => ({ ...prev, paymentMethods: "billing.ui.dashboard.errors.load_payment_methods" }));
|
|
2799
2825
|
} finally {
|
|
2800
2826
|
setLoading((prev) => ({ ...prev, paymentMethods: false }));
|
|
2801
2827
|
}
|
|
@@ -2807,7 +2833,7 @@ function BillingDashboardContainer() {
|
|
|
2807
2833
|
setErrors((prev) => ({ ...prev, invoices: null }));
|
|
2808
2834
|
} catch (error) {
|
|
2809
2835
|
console.error("[BillingDashboard] Failed to load invoices:", error);
|
|
2810
|
-
setErrors((prev) => ({ ...prev, invoices: "
|
|
2836
|
+
setErrors((prev) => ({ ...prev, invoices: "billing.ui.dashboard.errors.load_invoices" }));
|
|
2811
2837
|
} finally {
|
|
2812
2838
|
setLoading((prev) => ({ ...prev, invoices: false }));
|
|
2813
2839
|
}
|
|
@@ -2830,7 +2856,7 @@ function BillingDashboardContainer() {
|
|
|
2830
2856
|
await fetchAllData();
|
|
2831
2857
|
} catch (error) {
|
|
2832
2858
|
console.error("[BillingDashboard] Failed to create customer:", error);
|
|
2833
|
-
setErrors((prev) => ({ ...prev, customer: "
|
|
2859
|
+
setErrors((prev) => ({ ...prev, customer: "billing.ui.dashboard.errors.setup" }));
|
|
2834
2860
|
} finally {
|
|
2835
2861
|
setCreatingCustomer(false);
|
|
2836
2862
|
}
|
|
@@ -2860,7 +2886,7 @@ function BillingDashboardContainer() {
|
|
|
2860
2886
|
setErrors((prev) => ({ ...prev, usage: null }));
|
|
2861
2887
|
} catch (error) {
|
|
2862
2888
|
console.error("[BillingDashboard] Failed to load usage data:", error);
|
|
2863
|
-
setErrors((prev) => ({ ...prev, usage: "
|
|
2889
|
+
setErrors((prev) => ({ ...prev, usage: "billing.ui.dashboard.errors.load_usage" }));
|
|
2864
2890
|
} finally {
|
|
2865
2891
|
setLoading((prev) => ({ ...prev, usage: false }));
|
|
2866
2892
|
}
|
|
@@ -2906,13 +2932,13 @@ function BillingDashboardContainer() {
|
|
|
2906
2932
|
const getModalTitle = /* @__PURE__ */ __name((type) => {
|
|
2907
2933
|
switch (type) {
|
|
2908
2934
|
case "subscriptions":
|
|
2909
|
-
return "
|
|
2935
|
+
return t("billing.ui.dashboard.modal.subscriptions");
|
|
2910
2936
|
case "payment-methods":
|
|
2911
|
-
return "
|
|
2937
|
+
return t("billing.ui.payment_methods.title");
|
|
2912
2938
|
case "invoices":
|
|
2913
|
-
return "
|
|
2939
|
+
return t("billing.ui.dashboard.modal.invoices");
|
|
2914
2940
|
case "usage":
|
|
2915
|
-
return "
|
|
2941
|
+
return t("billing.ui.usage.title");
|
|
2916
2942
|
default:
|
|
2917
2943
|
return "";
|
|
2918
2944
|
}
|
|
@@ -2921,20 +2947,20 @@ function BillingDashboardContainer() {
|
|
|
2921
2947
|
return /* @__PURE__ */ jsxs34("div", { className: "flex w-full flex-col gap-y-6", children: [
|
|
2922
2948
|
/* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-x-3", children: [
|
|
2923
2949
|
/* @__PURE__ */ jsx38(Wallet2, { className: "h-8 w-8" }),
|
|
2924
|
-
/* @__PURE__ */ jsx38("h1", { className: "text-primary text-3xl font-semibold", children: "
|
|
2950
|
+
/* @__PURE__ */ jsx38("h1", { className: "text-primary text-3xl font-semibold", children: t("billing.title") })
|
|
2925
2951
|
] }),
|
|
2926
2952
|
isInitialLoading && /* @__PURE__ */ jsx38(Card, { children: /* @__PURE__ */ jsx38(CardContent, { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx38(Loader23, { className: "h-8 w-8 animate-spin text-muted-foreground" }) }) }),
|
|
2927
2953
|
noCustomerExists && !isInitialLoading && /* @__PURE__ */ jsxs34(Card, { children: [
|
|
2928
2954
|
/* @__PURE__ */ jsxs34(CardHeader, { className: "text-center", children: [
|
|
2929
2955
|
/* @__PURE__ */ jsx38("div", { className: "mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsx38(CreditCard4, { className: "h-8 w-8 text-primary" }) }),
|
|
2930
|
-
/* @__PURE__ */ jsx38(CardTitle, { children: "
|
|
2931
|
-
/* @__PURE__ */ jsx38(CardDescription, { children: "
|
|
2956
|
+
/* @__PURE__ */ jsx38(CardTitle, { children: t("billing.ui.dashboard.setup_title") }),
|
|
2957
|
+
/* @__PURE__ */ jsx38(CardDescription, { children: t("billing.ui.dashboard.setup_description") })
|
|
2932
2958
|
] }),
|
|
2933
2959
|
/* @__PURE__ */ jsx38(CardContent, { className: "flex justify-center pb-8", children: /* @__PURE__ */ jsx38(Button, { onClick: handleCreateCustomer, disabled: creatingCustomer, size: "lg", children: creatingCustomer ? /* @__PURE__ */ jsxs34(Fragment7, { children: [
|
|
2934
2960
|
/* @__PURE__ */ jsx38(Loader23, { className: "me-2 h-4 w-4 animate-spin" }),
|
|
2935
|
-
"
|
|
2936
|
-
] }) : "
|
|
2937
|
-
errors.customer && /* @__PURE__ */ jsx38(CardContent, { className: "pt-0", children: /* @__PURE__ */ jsx38("p", { className: "text-center text-destructive text-xs/relaxed", children: errors.customer }) })
|
|
2961
|
+
t("billing.ui.dashboard.setting_up")
|
|
2962
|
+
] }) : t("billing.ui.dashboard.setup_button") }) }),
|
|
2963
|
+
errors.customer && /* @__PURE__ */ jsx38(CardContent, { className: "pt-0", children: /* @__PURE__ */ jsx38("p", { className: "text-center text-destructive text-xs/relaxed", children: t(errors.customer) }) })
|
|
2938
2964
|
] }),
|
|
2939
2965
|
!noCustomerExists && !isInitialLoading && /* @__PURE__ */ jsxs34(Fragment7, { children: [
|
|
2940
2966
|
criticalSubscriptions.map((subscription) => /* @__PURE__ */ jsx38(
|
|
@@ -2952,7 +2978,7 @@ function BillingDashboardContainer() {
|
|
|
2952
2978
|
{
|
|
2953
2979
|
subscriptions: data.subscriptions,
|
|
2954
2980
|
loading: loading.subscriptions,
|
|
2955
|
-
error: errors.subscriptions
|
|
2981
|
+
error: errors.subscriptions ? t(errors.subscriptions) : void 0,
|
|
2956
2982
|
onManageClick: () => {
|
|
2957
2983
|
if (data.subscriptions.length === 0) {
|
|
2958
2984
|
setShowWizard(true);
|
|
@@ -2968,7 +2994,7 @@ function BillingDashboardContainer() {
|
|
|
2968
2994
|
paymentMethods: data.paymentMethods,
|
|
2969
2995
|
defaultPaymentMethodId: data.customer?.defaultPaymentMethodId,
|
|
2970
2996
|
loading: loading.paymentMethods,
|
|
2971
|
-
error: errors.paymentMethods
|
|
2997
|
+
error: errors.paymentMethods ? t(errors.paymentMethods) : void 0,
|
|
2972
2998
|
onManageClick: () => setActiveModal("payment-methods")
|
|
2973
2999
|
}
|
|
2974
3000
|
),
|
|
@@ -2977,7 +3003,7 @@ function BillingDashboardContainer() {
|
|
|
2977
3003
|
{
|
|
2978
3004
|
customer: data.customer,
|
|
2979
3005
|
loading: loading.customer,
|
|
2980
|
-
error: errors.customer
|
|
3006
|
+
error: errors.customer ? t(errors.customer) : void 0
|
|
2981
3007
|
}
|
|
2982
3008
|
),
|
|
2983
3009
|
/* @__PURE__ */ jsx38(
|
|
@@ -2985,7 +3011,7 @@ function BillingDashboardContainer() {
|
|
|
2985
3011
|
{
|
|
2986
3012
|
invoices: data.invoices,
|
|
2987
3013
|
loading: loading.invoices,
|
|
2988
|
-
error: errors.invoices
|
|
3014
|
+
error: errors.invoices ? t(errors.invoices) : void 0,
|
|
2989
3015
|
onViewAllClick: () => setActiveModal("invoices")
|
|
2990
3016
|
}
|
|
2991
3017
|
),
|
|
@@ -2995,7 +3021,7 @@ function BillingDashboardContainer() {
|
|
|
2995
3021
|
meters: data.meters,
|
|
2996
3022
|
summaries: data.meterSummaries,
|
|
2997
3023
|
loading: loading.usage,
|
|
2998
|
-
error: errors.usage
|
|
3024
|
+
error: errors.usage ? t(errors.usage) : void 0,
|
|
2999
3025
|
onViewDetailsClick: () => setActiveModal("usage")
|
|
3000
3026
|
}
|
|
3001
3027
|
)
|
|
@@ -3091,16 +3117,17 @@ function isStripeConfigured() {
|
|
|
3091
3117
|
__name(isStripeConfigured, "isStripeConfigured");
|
|
3092
3118
|
|
|
3093
3119
|
// src/features/billing/contexts/PriceContext.tsx
|
|
3094
|
-
import { useTranslations as
|
|
3120
|
+
import { useTranslations as useTranslations39 } from "next-intl";
|
|
3095
3121
|
import { createContext, useCallback as useCallback6, useContext, useMemo as useMemo6, useState as useState17 } from "react";
|
|
3096
3122
|
|
|
3097
3123
|
// src/features/billing/stripe-price/components/forms/PriceArchiver.tsx
|
|
3098
3124
|
import { ArchiveIcon, RotateCcwIcon } from "lucide-react";
|
|
3099
|
-
import { useTranslations } from "next-intl";
|
|
3125
|
+
import { useTranslations as useTranslations37 } from "next-intl";
|
|
3100
3126
|
import { useState as useState15 } from "react";
|
|
3101
3127
|
import { Fragment as Fragment9, jsx as jsx40, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
3102
3128
|
function PriceArchiver({ price }) {
|
|
3103
|
-
const t =
|
|
3129
|
+
const t = useTranslations37();
|
|
3130
|
+
const fmt = useBillingFormatOptions();
|
|
3104
3131
|
const { archivePrice, restorePrice } = usePriceContext();
|
|
3105
3132
|
const [open, setOpen] = useState15(false);
|
|
3106
3133
|
const isArchived = !price.active;
|
|
@@ -3116,7 +3143,7 @@ function PriceArchiver({ price }) {
|
|
|
3116
3143
|
open,
|
|
3117
3144
|
onOpenChange: setOpen,
|
|
3118
3145
|
title: t(`billing.admin.prices.${scope}.title`),
|
|
3119
|
-
description: t(`billing.admin.prices.${scope}.description`, { label: priceLabel(price) }),
|
|
3146
|
+
description: t(`billing.admin.prices.${scope}.description`, { label: priceLabel(price, fmt) }),
|
|
3120
3147
|
confirmLabel: t(`billing.admin.prices.${scope}.confirm`),
|
|
3121
3148
|
cancelLabel: t("ui.buttons.cancel"),
|
|
3122
3149
|
destructive: !isArchived,
|
|
@@ -3138,7 +3165,7 @@ __name(PriceArchiver, "PriceArchiver");
|
|
|
3138
3165
|
// src/features/billing/stripe-price/components/forms/PriceEditor.tsx
|
|
3139
3166
|
import { zodResolver as zodResolver2 } from "@hookform/resolvers/zod";
|
|
3140
3167
|
import { PlusIcon, XIcon } from "lucide-react";
|
|
3141
|
-
import { useTranslations as
|
|
3168
|
+
import { useTranslations as useTranslations38 } from "next-intl";
|
|
3142
3169
|
import { useCallback as useCallback5, useEffect as useEffect10, useMemo as useMemo5, useRef as useRef3, useState as useState16 } from "react";
|
|
3143
3170
|
import { useForm as useForm2 } from "react-hook-form";
|
|
3144
3171
|
import { v4 as v42 } from "uuid";
|
|
@@ -3156,7 +3183,8 @@ function PriceEditorInternal({
|
|
|
3156
3183
|
dialogOpen,
|
|
3157
3184
|
onDialogOpenChange
|
|
3158
3185
|
}) {
|
|
3159
|
-
const t =
|
|
3186
|
+
const t = useTranslations38();
|
|
3187
|
+
const fmt = useBillingFormatOptions();
|
|
3160
3188
|
const router = useI18nRouter();
|
|
3161
3189
|
const { createPrice, updatePrice, productId: contextProductId } = usePriceContext();
|
|
3162
3190
|
const [allFeatures, setAllFeatures] = useState16([]);
|
|
@@ -3302,7 +3330,7 @@ function PriceEditorInternal({
|
|
|
3302
3330
|
{
|
|
3303
3331
|
form,
|
|
3304
3332
|
entityType: t("billing.admin.prices.entity"),
|
|
3305
|
-
entityName: price ? priceLabel(price) : void 0,
|
|
3333
|
+
entityName: price ? priceLabel(price, fmt) : void 0,
|
|
3306
3334
|
isEdit,
|
|
3307
3335
|
module: Modules.StripePrice,
|
|
3308
3336
|
size: "lg",
|
|
@@ -3554,8 +3582,8 @@ var defaultContextValue = {
|
|
|
3554
3582
|
}, "refreshPrices"),
|
|
3555
3583
|
productId: void 0
|
|
3556
3584
|
};
|
|
3557
|
-
function priceLabel(price) {
|
|
3558
|
-
return price.nickname ?? `${formatCurrency(price.unitAmount, price.currency)} ${formatInterval(price)}`.trim();
|
|
3585
|
+
function priceLabel(price, fmt = {}) {
|
|
3586
|
+
return price.nickname ?? `${formatCurrency(price.unitAmount, price.currency, fmt)} ${formatInterval(price, fmt)}`.trim();
|
|
3559
3587
|
}
|
|
3560
3588
|
__name(priceLabel, "priceLabel");
|
|
3561
3589
|
var PriceProvider = /* @__PURE__ */ __name(({
|
|
@@ -3564,7 +3592,8 @@ var PriceProvider = /* @__PURE__ */ __name(({
|
|
|
3564
3592
|
publishChrome = true,
|
|
3565
3593
|
productId: productIdProp
|
|
3566
3594
|
}) => {
|
|
3567
|
-
const t =
|
|
3595
|
+
const t = useTranslations39();
|
|
3596
|
+
const fmt = useBillingFormatOptions();
|
|
3568
3597
|
const generateUrl = usePageUrlGenerator();
|
|
3569
3598
|
const { hasRole } = useCurrentUserContext();
|
|
3570
3599
|
const [price, setPrice] = useState17(
|
|
@@ -3639,13 +3668,13 @@ var PriceProvider = /* @__PURE__ */ __name(({
|
|
|
3639
3668
|
name: price.product.name,
|
|
3640
3669
|
href: generateUrl({ page: Modules.StripeProduct, id: price.product.id })
|
|
3641
3670
|
});
|
|
3642
|
-
if (price) items.push({ name: priceLabel(price) });
|
|
3671
|
+
if (price) items.push({ name: priceLabel(price, fmt) });
|
|
3643
3672
|
return items;
|
|
3644
3673
|
}, "breadcrumb");
|
|
3645
3674
|
const title = /* @__PURE__ */ __name(() => {
|
|
3646
3675
|
const response = { type: t("billing.admin.prices.title") };
|
|
3647
3676
|
if (!price) return response;
|
|
3648
|
-
response.element = priceLabel(price);
|
|
3677
|
+
response.element = priceLabel(price, fmt);
|
|
3649
3678
|
if (hasRole(getRoleId().Administrator)) {
|
|
3650
3679
|
response.functions = [
|
|
3651
3680
|
/* @__PURE__ */ jsx42(PriceArchiver, { price }, "priceArchiver"),
|
|
@@ -3659,16 +3688,16 @@ var PriceProvider = /* @__PURE__ */ __name(({
|
|
|
3659
3688
|
var usePriceContext = /* @__PURE__ */ __name(() => useContext(PriceContext) ?? defaultContextValue, "usePriceContext");
|
|
3660
3689
|
|
|
3661
3690
|
// src/features/billing/contexts/ProductContext.tsx
|
|
3662
|
-
import { useTranslations as
|
|
3691
|
+
import { useTranslations as useTranslations42 } from "next-intl";
|
|
3663
3692
|
import { createContext as createContext2, useCallback as useCallback8, useContext as useContext2, useMemo as useMemo8, useState as useState19 } from "react";
|
|
3664
3693
|
|
|
3665
3694
|
// src/features/billing/stripe-product/components/forms/ProductArchiver.tsx
|
|
3666
3695
|
import { ArchiveIcon as ArchiveIcon2, RotateCcwIcon as RotateCcwIcon2 } from "lucide-react";
|
|
3667
|
-
import { useTranslations as
|
|
3696
|
+
import { useTranslations as useTranslations40 } from "next-intl";
|
|
3668
3697
|
import { useState as useState18 } from "react";
|
|
3669
3698
|
import { Fragment as Fragment10, jsx as jsx43, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3670
3699
|
function ProductArchiver({ product }) {
|
|
3671
|
-
const t =
|
|
3700
|
+
const t = useTranslations40();
|
|
3672
3701
|
const { archiveProduct, restoreProduct } = useProductContext();
|
|
3673
3702
|
const [open, setOpen] = useState18(false);
|
|
3674
3703
|
const isArchived = !product.active;
|
|
@@ -3705,7 +3734,7 @@ __name(ProductArchiver, "ProductArchiver");
|
|
|
3705
3734
|
|
|
3706
3735
|
// src/features/billing/stripe-product/components/forms/ProductEditor.tsx
|
|
3707
3736
|
import { zodResolver as zodResolver3 } from "@hookform/resolvers/zod";
|
|
3708
|
-
import { useTranslations as
|
|
3737
|
+
import { useTranslations as useTranslations41 } from "next-intl";
|
|
3709
3738
|
import { useCallback as useCallback7, useMemo as useMemo7 } from "react";
|
|
3710
3739
|
import { useForm as useForm3 } from "react-hook-form";
|
|
3711
3740
|
import { v4 as v43 } from "uuid";
|
|
@@ -3721,7 +3750,7 @@ function ProductEditorInternal({
|
|
|
3721
3750
|
dialogOpen,
|
|
3722
3751
|
onDialogOpenChange
|
|
3723
3752
|
}) {
|
|
3724
|
-
const t =
|
|
3753
|
+
const t = useTranslations41();
|
|
3725
3754
|
const router = useI18nRouter();
|
|
3726
3755
|
const { createProduct, updateProduct } = useProductContext();
|
|
3727
3756
|
const isEdit = !!product;
|
|
@@ -3822,7 +3851,7 @@ var defaultContextValue2 = {
|
|
|
3822
3851
|
}, "refreshCatalogue")
|
|
3823
3852
|
};
|
|
3824
3853
|
var ProductProvider = /* @__PURE__ */ __name(({ children, dehydratedProduct, publishChrome = true }) => {
|
|
3825
|
-
const t =
|
|
3854
|
+
const t = useTranslations42();
|
|
3826
3855
|
const generateUrl = usePageUrlGenerator();
|
|
3827
3856
|
const { hasRole } = useCurrentUserContext();
|
|
3828
3857
|
const [product, setProduct] = useState19(
|
|
@@ -3923,10 +3952,11 @@ var ProductProvider = /* @__PURE__ */ __name(({ children, dehydratedProduct, pub
|
|
|
3923
3952
|
var useProductContext = /* @__PURE__ */ __name(() => useContext2(ProductContext) ?? defaultContextValue2, "useProductContext");
|
|
3924
3953
|
|
|
3925
3954
|
// src/features/billing/stripe-price/components/details/PriceDetails.tsx
|
|
3926
|
-
import { useTranslations as
|
|
3955
|
+
import { useTranslations as useTranslations43 } from "next-intl";
|
|
3927
3956
|
import { jsx as jsx46, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3928
3957
|
function PriceDetails() {
|
|
3929
|
-
const t =
|
|
3958
|
+
const t = useTranslations43();
|
|
3959
|
+
const fmt = useBillingFormatOptions();
|
|
3930
3960
|
const generateUrl = usePageUrlGenerator();
|
|
3931
3961
|
const { price } = usePriceContext();
|
|
3932
3962
|
if (!price) return null;
|
|
@@ -3956,7 +3986,7 @@ function PriceDetails() {
|
|
|
3956
3986
|
DetailField,
|
|
3957
3987
|
{
|
|
3958
3988
|
label: t("billing.admin.prices.fields.amount"),
|
|
3959
|
-
value: /* @__PURE__ */ jsx46("span", { className: "tabular-nums", children: formatCurrency(price.unitAmount, price.currency) })
|
|
3989
|
+
value: /* @__PURE__ */ jsx46("span", { className: "tabular-nums", children: formatCurrency(price.unitAmount, price.currency, fmt) })
|
|
3960
3990
|
}
|
|
3961
3991
|
),
|
|
3962
3992
|
/* @__PURE__ */ jsx46(DetailField, { label: t("billing.admin.prices.fields.currency"), value: price.currency.toUpperCase() }),
|
|
@@ -3967,7 +3997,7 @@ function PriceDetails() {
|
|
|
3967
3997
|
value: isRecurring ? t("billing.admin.prices.type.recurring") : t("billing.admin.prices.type.oneTime")
|
|
3968
3998
|
}
|
|
3969
3999
|
),
|
|
3970
|
-
/* @__PURE__ */ jsx46(DetailField, { label: t("billing.admin.prices.fields.billing"), value: formatInterval(price) }),
|
|
4000
|
+
/* @__PURE__ */ jsx46(DetailField, { label: t("billing.admin.prices.fields.billing"), value: formatInterval(price, fmt) }),
|
|
3971
4001
|
isRecurring && /* @__PURE__ */ jsx46(
|
|
3972
4002
|
DetailField,
|
|
3973
4003
|
{
|
|
@@ -4042,7 +4072,7 @@ __name(PriceContainer, "PriceContainer");
|
|
|
4042
4072
|
|
|
4043
4073
|
// src/features/billing/stripe-price/components/lists/PricesList.tsx
|
|
4044
4074
|
import { DollarSignIcon, UploadIcon } from "lucide-react";
|
|
4045
|
-
import { useTranslations as
|
|
4075
|
+
import { useTranslations as useTranslations44 } from "next-intl";
|
|
4046
4076
|
import { Fragment as Fragment11, useCallback as useCallback9, useEffect as useEffect11, useMemo as useMemo9, useRef as useRef4, useState as useState20 } from "react";
|
|
4047
4077
|
|
|
4048
4078
|
// src/features/billing/stripe-price/data/stripe-price.transfer.ts
|
|
@@ -4156,7 +4186,7 @@ __name(parseStripePriceTransferDocument, "parseStripePriceTransferDocument");
|
|
|
4156
4186
|
// src/features/billing/stripe-price/components/lists/PricesList.tsx
|
|
4157
4187
|
import { Fragment as Fragment12, jsx as jsx48, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
4158
4188
|
function PricesList({ productId, fullWidth }) {
|
|
4159
|
-
const t =
|
|
4189
|
+
const t = useTranslations44();
|
|
4160
4190
|
const { priceVersion } = usePriceContext();
|
|
4161
4191
|
const importInputRef = useRef4(null);
|
|
4162
4192
|
const [seed, setSeed] = useState20(void 0);
|
|
@@ -4283,13 +4313,13 @@ function PricesList({ productId, fullWidth }) {
|
|
|
4283
4313
|
__name(PricesList, "PricesList");
|
|
4284
4314
|
|
|
4285
4315
|
// src/features/billing/stripe-product/components/containers/ProductContainer.tsx
|
|
4286
|
-
import { useTranslations as
|
|
4316
|
+
import { useTranslations as useTranslations46 } from "next-intl";
|
|
4287
4317
|
|
|
4288
4318
|
// src/features/billing/stripe-product/components/details/ProductDetails.tsx
|
|
4289
|
-
import { useTranslations as
|
|
4319
|
+
import { useTranslations as useTranslations45 } from "next-intl";
|
|
4290
4320
|
import { jsx as jsx49, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
4291
4321
|
function ProductDetails() {
|
|
4292
|
-
const t =
|
|
4322
|
+
const t = useTranslations45();
|
|
4293
4323
|
const { product } = useProductContext();
|
|
4294
4324
|
if (!product) return null;
|
|
4295
4325
|
return /* @__PURE__ */ jsxs41("div", { className: "flex w-full flex-col gap-y-4", children: [
|
|
@@ -4333,7 +4363,7 @@ __name(ProductDetails, "ProductDetails");
|
|
|
4333
4363
|
// src/features/billing/stripe-product/components/containers/ProductContainer.tsx
|
|
4334
4364
|
import { jsx as jsx50 } from "react/jsx-runtime";
|
|
4335
4365
|
function ProductContainer() {
|
|
4336
|
-
const t =
|
|
4366
|
+
const t = useTranslations46();
|
|
4337
4367
|
const { product } = useProductContext();
|
|
4338
4368
|
if (!product) return null;
|
|
4339
4369
|
return /* @__PURE__ */ jsx50(
|
|
@@ -4366,11 +4396,11 @@ __name(ProductContainer, "ProductContainer");
|
|
|
4366
4396
|
|
|
4367
4397
|
// src/features/billing/stripe-product/components/lists/ProductsList.tsx
|
|
4368
4398
|
import { PackageIcon } from "lucide-react";
|
|
4369
|
-
import { useTranslations as
|
|
4399
|
+
import { useTranslations as useTranslations47 } from "next-intl";
|
|
4370
4400
|
import { useEffect as useEffect12 } from "react";
|
|
4371
4401
|
import { jsx as jsx51 } from "react/jsx-runtime";
|
|
4372
4402
|
function ProductsList({ fullWidth } = {}) {
|
|
4373
|
-
const t =
|
|
4403
|
+
const t = useTranslations47();
|
|
4374
4404
|
const { catalogueVersion } = useProductContext();
|
|
4375
4405
|
const data = useDataListRetriever({
|
|
4376
4406
|
retriever: /* @__PURE__ */ __name((params) => StripeProductService.listProducts(params), "retriever"),
|
|
@@ -4463,10 +4493,12 @@ export {
|
|
|
4463
4493
|
WizardStepPlanSelection,
|
|
4464
4494
|
WizardStepReview,
|
|
4465
4495
|
formatCurrency,
|
|
4466
|
-
|
|
4496
|
+
formatDate,
|
|
4497
|
+
formatFixed,
|
|
4467
4498
|
formatInterval,
|
|
4468
4499
|
isStripeConfigured,
|
|
4469
4500
|
priceLabel,
|
|
4501
|
+
useBillingFormatOptions,
|
|
4470
4502
|
usePriceContext,
|
|
4471
4503
|
useProductContext
|
|
4472
4504
|
};
|