@carlonicora/nextjs-jsonapi 1.14.0 → 1.16.0
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/{ApiResponseInterface-B4QdWh-y.d.mts → ApiResponseInterface-BvWIeLkq.d.ts} +2 -1
- package/dist/{ApiResponseInterface-QLDnxLA9.d.ts → ApiResponseInterface-CAbw0sv7.d.mts} +2 -1
- package/dist/{BlockNoteEditor-436ZHDY3.mjs → BlockNoteEditor-HFX7Z5BQ.mjs} +5 -5
- package/dist/{BlockNoteEditor-WCK43JHX.js → BlockNoteEditor-MBFDWP7X.js} +15 -15
- package/dist/{BlockNoteEditor-WCK43JHX.js.map → BlockNoteEditor-MBFDWP7X.js.map} +1 -1
- package/dist/JsonApiRequest-45CLE65I.js +24 -0
- package/dist/{JsonApiRequest-FXZCYIER.js.map → JsonApiRequest-45CLE65I.js.map} +1 -1
- package/dist/{JsonApiRequest-HFWXMKMA.mjs → JsonApiRequest-6IPS3DZJ.mjs} +2 -2
- package/dist/{chunk-R6K76UTR.js → chunk-2AZLCF6D.js} +1687 -183
- package/dist/chunk-2AZLCF6D.js.map +1 -0
- package/dist/{chunk-2FCG3K64.mjs → chunk-5RAUCUAA.mjs} +3722 -396
- package/dist/chunk-5RAUCUAA.mjs.map +1 -0
- package/dist/{chunk-TGBXBUWM.mjs → chunk-BCKYJQ3K.mjs} +8 -1
- package/dist/chunk-BCKYJQ3K.mjs.map +1 -0
- package/dist/{chunk-A333VMBO.mjs → chunk-BCQSE3EU.mjs} +1654 -150
- package/dist/chunk-BCQSE3EU.mjs.map +1 -0
- package/dist/{chunk-FPZPD4JI.js → chunk-GPGJNTHP.js} +17 -10
- package/dist/chunk-GPGJNTHP.js.map +1 -0
- package/dist/{chunk-45QMJETP.js → chunk-ONB2DAIV.js} +4090 -764
- package/dist/chunk-ONB2DAIV.js.map +1 -0
- package/dist/{chunk-SJIVGCNM.mjs → chunk-POKIJ56Q.mjs} +7 -2
- package/dist/chunk-POKIJ56Q.mjs.map +1 -0
- package/dist/{chunk-6YD42BP6.js → chunk-R5QSSISB.js} +14 -9
- package/dist/chunk-R5QSSISB.js.map +1 -0
- package/dist/client/index.d.mts +5 -5
- package/dist/client/index.d.ts +5 -5
- package/dist/client/index.js +7 -5
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +6 -4
- package/dist/components/index.d.mts +253 -9
- package/dist/components/index.d.ts +253 -9
- package/dist/components/index.js +83 -5
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +82 -4
- package/dist/{config-eceYM5kN.d.ts → config-CWsTwnsK.d.mts} +7 -2
- package/dist/{config-C5tGGrYf.d.mts → config-DEaUbBqR.d.ts} +7 -2
- package/dist/{content.interface-TB2MfJGs.d.ts → content.interface-D_4b4RQt.d.ts} +1 -1
- package/dist/{content.interface-CxBBC7ec.d.mts → content.interface-Dk4UZcJM.d.mts} +1 -1
- package/dist/contexts/index.d.mts +2 -2
- package/dist/contexts/index.d.ts +2 -2
- package/dist/contexts/index.js +5 -5
- package/dist/contexts/index.mjs +4 -4
- package/dist/core/index.d.mts +528 -22
- package/dist/core/index.d.ts +528 -22
- package/dist/core/index.js +53 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +52 -2
- package/dist/index.d.mts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +56 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +55 -3
- package/dist/{notification.interface-lG6UpTpt.d.mts → notification.interface-BllkURRm.d.mts} +1 -2
- package/dist/{notification.interface-lG6UpTpt.d.ts → notification.interface-BllkURRm.d.ts} +1 -2
- package/dist/{s3.service-DP_hsssD.d.mts → s3.service-BEfGqho0.d.ts} +20 -2
- package/dist/{s3.service-Dq-PTUNa.d.ts → s3.service-DIQRYe93.d.mts} +20 -2
- package/dist/scripts/generate-web-module/generator.d.ts.map +1 -1
- package/dist/scripts/generate-web-module/generator.js +66 -0
- package/dist/scripts/generate-web-module/generator.js.map +1 -1
- package/dist/scripts/generate-web-module/templates/data/interface.template.js +8 -1
- package/dist/scripts/generate-web-module/templates/data/interface.template.js.map +1 -1
- package/dist/scripts/generate-web-module/templates/data/model.template.js +26 -3
- package/dist/scripts/generate-web-module/templates/data/model.template.js.map +1 -1
- package/dist/scripts/generate-web-module/templates/index.d.ts +8 -0
- package/dist/scripts/generate-web-module/templates/index.d.ts.map +1 -1
- package/dist/scripts/generate-web-module/templates/index.js +18 -1
- package/dist/scripts/generate-web-module/templates/index.js.map +1 -1
- package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.d.ts +7 -0
- package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.js +141 -0
- package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/env.template.d.ts +7 -0
- package/dist/scripts/generate-web-module/templates/project/env.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/env.template.js +110 -0
- package/dist/scripts/generate-web-module/templates/project/env.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/main-layout.template.d.ts +7 -0
- package/dist/scripts/generate-web-module/templates/project/main-layout.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/main-layout.template.js +101 -0
- package/dist/scripts/generate-web-module/templates/project/main-layout.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/middleware-env.template.d.ts +7 -0
- package/dist/scripts/generate-web-module/templates/project/middleware-env.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/middleware-env.template.js +66 -0
- package/dist/scripts/generate-web-module/templates/project/middleware-env.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/settings-container.template.d.ts +7 -0
- package/dist/scripts/generate-web-module/templates/project/settings-container.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/settings-container.template.js +257 -0
- package/dist/scripts/generate-web-module/templates/project/settings-container.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/settings-context.template.d.ts +7 -0
- package/dist/scripts/generate-web-module/templates/project/settings-context.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/settings-context.template.js +124 -0
- package/dist/scripts/generate-web-module/templates/project/settings-context.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.d.ts +7 -0
- package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.js +78 -0
- package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/settings-page.template.d.ts +7 -0
- package/dist/scripts/generate-web-module/templates/project/settings-page.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/project/settings-page.template.js +75 -0
- package/dist/scripts/generate-web-module/templates/project/settings-page.template.js.map +1 -0
- package/dist/scripts/generate-web-module/types/template-data.interface.d.ts +1 -1
- package/dist/scripts/generate-web-module/types/template-data.interface.d.ts.map +1 -1
- package/dist/server/index.d.mts +4 -4
- package/dist/server/index.d.ts +4 -4
- package/dist/server/index.js +12 -12
- package/dist/server/index.mjs +2 -2
- package/dist/stripe-subscription.interface-C63L6hVg.d.mts +226 -0
- package/dist/stripe-subscription.interface-CUvNDvw5.d.ts +226 -0
- package/dist/{useSocket-Bua6MwLi.d.mts → useSocket-BpenBR2z.d.mts} +1 -1
- package/dist/{useSocket-D5dhUp4m.d.ts → useSocket-D-QYA0Sr.d.ts} +1 -1
- package/package.json +9 -1
- package/scripts/generate-web-module/generator.ts +83 -0
- package/scripts/generate-web-module/templates/data/interface.template.ts +7 -1
- package/scripts/generate-web-module/templates/data/model.template.ts +28 -5
- package/scripts/generate-web-module/templates/index.ts +10 -0
- package/scripts/generate-web-module/templates/project/bootstrapper.template.ts +108 -0
- package/scripts/generate-web-module/templates/project/env.template.ts +77 -0
- package/scripts/generate-web-module/templates/project/main-layout.template.tsx +68 -0
- package/scripts/generate-web-module/templates/project/middleware-env.template.ts +33 -0
- package/scripts/generate-web-module/templates/project/settings-container.template.tsx +224 -0
- package/scripts/generate-web-module/templates/project/settings-context.template.tsx +91 -0
- package/scripts/generate-web-module/templates/project/settings-module-page.template.tsx +45 -0
- package/scripts/generate-web-module/templates/project/settings-page.template.tsx +42 -0
- package/scripts/generate-web-module/types/template-data.interface.ts +1 -1
- package/src/client/config.ts +9 -0
- package/src/components/index.ts +7 -0
- package/src/core/abstracts/AbstractApiData.ts +79 -16
- package/src/core/abstracts/AbstractService.ts +104 -0
- package/src/core/endpoint/EndpointCreator.ts +7 -4
- package/src/core/index.ts +12 -4
- package/src/core/interfaces/ApiResponseInterface.ts +1 -0
- package/src/core/registry/ModuleRegistry.ts +11 -2
- package/src/core/utils/translateResponse.ts +17 -0
- package/src/features/billing/components/cards/BillingUsageSummaryCard.tsx +97 -0
- package/src/features/billing/components/cards/CustomerInfoCard.tsx +112 -0
- package/src/features/billing/components/cards/InvoicesSummaryCard.tsx +114 -0
- package/src/features/billing/components/cards/PaymentMethodSummaryCard.tsx +119 -0
- package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +146 -0
- package/src/features/billing/components/cards/index.ts +5 -0
- package/src/features/billing/components/containers/BillingDashboardContainer.tsx +427 -0
- package/src/features/billing/components/containers/index.ts +1 -0
- package/src/features/billing/components/index.ts +6 -0
- package/src/features/billing/components/modals/BillingDetailModal.tsx +36 -0
- package/src/features/billing/components/modals/index.ts +1 -0
- package/src/features/billing/components/providers/StripeProvider.tsx +48 -0
- package/src/features/billing/components/providers/index.ts +1 -0
- package/src/features/billing/components/utils/currency.ts +49 -0
- package/src/features/billing/components/utils/date.ts +21 -0
- package/src/features/billing/components/utils/index.ts +2 -0
- package/src/features/billing/components/widgets/BillingAlertBanner.tsx +63 -0
- package/src/features/billing/components/widgets/index.ts +1 -0
- package/src/features/billing/data/Billing.ts +17 -0
- package/src/features/billing/data/billing.service.ts +58 -0
- package/src/features/billing/data/index.ts +5 -0
- package/src/features/billing/index.ts +3 -0
- package/src/features/billing/modules/billing.module.ts +9 -0
- package/src/features/billing/modules/index.ts +1 -0
- package/src/features/billing/stripe-customer/components/containers/PaymentMethodsContainer.tsx +79 -0
- package/src/features/billing/stripe-customer/components/containers/index.ts +1 -0
- package/src/features/billing/stripe-customer/components/details/PaymentMethodCard.tsx +151 -0
- package/src/features/billing/stripe-customer/components/details/index.ts +1 -0
- package/src/features/billing/stripe-customer/components/forms/PaymentMethodEditor.tsx +186 -0
- package/src/features/billing/stripe-customer/components/forms/index.ts +1 -0
- package/src/features/billing/stripe-customer/components/index.ts +4 -0
- package/src/features/billing/stripe-customer/components/lists/PaymentMethodsList.tsx +19 -0
- package/src/features/billing/stripe-customer/components/lists/index.ts +1 -0
- package/src/features/billing/stripe-customer/data/index.ts +5 -0
- package/src/features/billing/stripe-customer/data/payment-method.interface.ts +27 -0
- package/src/features/billing/stripe-customer/data/payment-method.ts +119 -0
- package/src/features/billing/stripe-customer/data/stripe-customer.interface.ts +16 -0
- package/src/features/billing/stripe-customer/data/stripe-customer.service.ts +128 -0
- package/src/features/billing/stripe-customer/data/stripe-customer.ts +71 -0
- package/src/features/billing/stripe-customer/index.ts +3 -0
- package/src/features/billing/stripe-customer/stripe-customer.module.ts +9 -0
- package/src/features/billing/stripe-customer/stripe-payment-method.module.ts +9 -0
- package/src/features/billing/stripe-invoice/components/containers/InvoicesContainer.tsx +66 -0
- package/src/features/billing/stripe-invoice/components/containers/index.ts +1 -0
- package/src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx +172 -0
- package/src/features/billing/stripe-invoice/components/details/index.ts +1 -0
- package/src/features/billing/stripe-invoice/components/index.ts +4 -0
- package/src/features/billing/stripe-invoice/components/lists/InvoicesList.tsx +84 -0
- package/src/features/billing/stripe-invoice/components/lists/index.ts +1 -0
- package/src/features/billing/stripe-invoice/components/widgets/InvoiceStatusBadge.tsx +41 -0
- package/src/features/billing/stripe-invoice/components/widgets/index.ts +1 -0
- package/src/features/billing/stripe-invoice/data/index.ts +3 -0
- package/src/features/billing/stripe-invoice/data/stripe-invoice.interface.ts +65 -0
- package/src/features/billing/stripe-invoice/data/stripe-invoice.service.ts +64 -0
- package/src/features/billing/stripe-invoice/data/stripe-invoice.ts +177 -0
- package/src/features/billing/stripe-invoice/index.ts +2 -0
- package/src/features/billing/stripe-invoice/stripe-invoice.module.ts +9 -0
- package/src/features/billing/stripe-price/components/forms/PriceEditor.tsx +304 -0
- package/src/features/billing/stripe-price/components/forms/index.ts +1 -0
- package/src/features/billing/stripe-price/components/index.ts +2 -0
- package/src/features/billing/stripe-price/components/lists/PricesList.tsx +283 -0
- package/src/features/billing/stripe-price/components/lists/index.ts +1 -0
- package/src/features/billing/stripe-price/data/index.ts +3 -0
- package/src/features/billing/stripe-price/data/stripe-price.interface.ts +48 -0
- package/src/features/billing/stripe-price/data/stripe-price.service.ts +123 -0
- package/src/features/billing/stripe-price/data/stripe-price.ts +156 -0
- package/src/features/billing/stripe-price/index.ts +2 -0
- package/src/features/billing/stripe-price/stripe-price.module.ts +9 -0
- package/src/features/billing/stripe-product/components/containers/ProductsAdminContainer.tsx +86 -0
- package/src/features/billing/stripe-product/components/containers/index.ts +1 -0
- package/src/features/billing/stripe-product/components/forms/ProductEditor.tsx +100 -0
- package/src/features/billing/stripe-product/components/forms/index.ts +1 -0
- package/src/features/billing/stripe-product/components/index.ts +3 -0
- package/src/features/billing/stripe-product/components/lists/ProductsList.tsx +206 -0
- package/src/features/billing/stripe-product/components/lists/index.ts +1 -0
- package/src/features/billing/stripe-product/data/index.ts +3 -0
- package/src/features/billing/stripe-product/data/stripe-product.interface.ts +18 -0
- package/src/features/billing/stripe-product/data/stripe-product.service.ts +112 -0
- package/src/features/billing/stripe-product/data/stripe-product.ts +74 -0
- package/src/features/billing/stripe-product/index.ts +2 -0
- package/src/features/billing/stripe-product/stripe-product.module.ts +9 -0
- package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +304 -0
- package/src/features/billing/stripe-subscription/components/containers/index.ts +1 -0
- package/src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx +223 -0
- package/src/features/billing/stripe-subscription/components/details/index.ts +1 -0
- package/src/features/billing/stripe-subscription/components/forms/CancelSubscriptionDialog.tsx +116 -0
- package/src/features/billing/stripe-subscription/components/forms/SubscriptionEditor.tsx +331 -0
- package/src/features/billing/stripe-subscription/components/forms/index.ts +2 -0
- package/src/features/billing/stripe-subscription/components/index.ts +5 -0
- package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +104 -0
- package/src/features/billing/stripe-subscription/components/lists/index.ts +1 -0
- package/src/features/billing/stripe-subscription/components/widgets/PricingCard.tsx +95 -0
- package/src/features/billing/stripe-subscription/components/widgets/PricingCardsGrid.tsx +110 -0
- package/src/features/billing/stripe-subscription/components/widgets/ProrationPreview.tsx +41 -0
- package/src/features/billing/stripe-subscription/components/widgets/SubscriptionStatusBadge.tsx +60 -0
- package/src/features/billing/stripe-subscription/components/widgets/index.ts +4 -0
- package/src/features/billing/stripe-subscription/data/index.ts +3 -0
- package/src/features/billing/stripe-subscription/data/stripe-subscription.interface.ts +66 -0
- package/src/features/billing/stripe-subscription/data/stripe-subscription.service.ts +193 -0
- package/src/features/billing/stripe-subscription/data/stripe-subscription.ts +135 -0
- package/src/features/billing/stripe-subscription/hooks/index.ts +1 -0
- package/src/features/billing/stripe-subscription/hooks/useConfirmSubscriptionPayment.ts +111 -0
- package/src/features/billing/stripe-subscription/index.ts +5 -0
- package/src/features/billing/stripe-subscription/stripe-subscription.module.ts +9 -0
- package/src/features/billing/stripe-usage/components/containers/UsageContainer.tsx +109 -0
- package/src/features/billing/stripe-usage/components/containers/index.ts +1 -0
- package/src/features/billing/stripe-usage/components/details/UsageSummaryCard.tsx +90 -0
- package/src/features/billing/stripe-usage/components/details/index.ts +1 -0
- package/src/features/billing/stripe-usage/components/index.ts +4 -0
- package/src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx +72 -0
- package/src/features/billing/stripe-usage/components/lists/index.ts +1 -0
- package/src/features/billing/stripe-usage/components/widgets/UsageSummaryCards.tsx +19 -0
- package/src/features/billing/stripe-usage/components/widgets/index.ts +1 -0
- package/src/features/billing/stripe-usage/data/index.ts +3 -0
- package/src/features/billing/stripe-usage/data/stripe-usage.interface.ts +55 -0
- package/src/features/billing/stripe-usage/data/stripe-usage.service.ts +129 -0
- package/src/features/billing/stripe-usage/data/stripe-usage.ts +70 -0
- package/src/features/billing/stripe-usage/index.ts +2 -0
- package/src/features/billing/stripe-usage/stripe-usage.module.ts +9 -0
- package/src/features/company/components/forms/CompanyEditor.tsx +2 -2
- package/src/features/company/components/forms/CompanyLicense.tsx +4 -4
- package/src/features/company/contexts/CompanyContext.tsx +2 -2
- package/src/features/feature/components/forms/FormFeatures.tsx +13 -106
- package/src/features/feature/data/feature.interface.ts +1 -1
- package/src/features/feature/data/feature.ts +4 -4
- package/src/features/index.ts +7 -0
- package/src/features/module/data/module.interface.ts +0 -1
- package/src/features/module/data/module.ts +0 -6
- package/src/features/user/components/lists/ContributorsList.tsx +2 -2
- package/src/features/user/components/widgets/UserAvatar.tsx +1 -1
- package/src/index.ts +1 -1
- package/src/shadcnui/custom/link.tsx +16 -6
- package/src/utils/blocknote-diff.util.ts +2 -1
- package/src/utils/blocknote-word-diff-renderer.util.ts +8 -7
- package/dist/AuthComponent-hxOPs9o8.d.mts +0 -11
- package/dist/AuthComponent-hxOPs9o8.d.ts +0 -11
- package/dist/JsonApiRequest-FXZCYIER.js +0 -24
- package/dist/chunk-2FCG3K64.mjs.map +0 -1
- package/dist/chunk-45QMJETP.js.map +0 -1
- package/dist/chunk-6YD42BP6.js.map +0 -1
- package/dist/chunk-A333VMBO.mjs.map +0 -1
- package/dist/chunk-FPZPD4JI.js.map +0 -1
- package/dist/chunk-R6K76UTR.js.map +0 -1
- package/dist/chunk-SJIVGCNM.mjs.map +0 -1
- package/dist/chunk-TGBXBUWM.mjs.map +0 -1
- /package/dist/{BlockNoteEditor-436ZHDY3.mjs.map → BlockNoteEditor-HFX7Z5BQ.mjs.map} +0 -0
- /package/dist/{JsonApiRequest-HFWXMKMA.mjs.map → JsonApiRequest-6IPS3DZJ.mjs.map} +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Activity } from "lucide-react";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
import { StripeSubscriptionInterface, StripeSubscriptionService } from "../../../stripe-subscription";
|
|
6
|
+
import { MeterInterface, MeterSummaryInterface } from "../../data/stripe-usage.interface";
|
|
7
|
+
import { StripeUsageService } from "../../data/stripe-usage.service";
|
|
8
|
+
import { UsageSummaryCards } from "../widgets/UsageSummaryCards";
|
|
9
|
+
|
|
10
|
+
export function UsageContainer() {
|
|
11
|
+
const [meters, setMeters] = useState<MeterInterface[]>([]);
|
|
12
|
+
const [summaries, setSummaries] = useState<Record<string, MeterSummaryInterface | null>>({});
|
|
13
|
+
const [loading, setLoading] = useState<boolean>(true);
|
|
14
|
+
const [subscriptions, setSubscriptions] = useState<StripeSubscriptionInterface[]>([]);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
loadUsageData();
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
const loadUsageData = async () => {
|
|
21
|
+
setLoading(true);
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
// First, check if there are any metered subscriptions
|
|
25
|
+
const fetchedSubscriptions = await StripeSubscriptionService.listSubscriptions();
|
|
26
|
+
setSubscriptions(fetchedSubscriptions);
|
|
27
|
+
|
|
28
|
+
const hasMeteredSubscriptions = fetchedSubscriptions.some((sub) => sub.price?.recurring?.usageType === "metered");
|
|
29
|
+
|
|
30
|
+
if (!hasMeteredSubscriptions) {
|
|
31
|
+
setLoading(false);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Load meters
|
|
36
|
+
const fetchedMeters = await StripeUsageService.listMeters();
|
|
37
|
+
setMeters(fetchedMeters);
|
|
38
|
+
|
|
39
|
+
// Load summaries for each meter (current month)
|
|
40
|
+
const summariesMap: Record<string, MeterSummaryInterface | null> = {};
|
|
41
|
+
const now = new Date();
|
|
42
|
+
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
|
|
43
|
+
const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
|
|
44
|
+
|
|
45
|
+
for (const meter of fetchedMeters) {
|
|
46
|
+
try {
|
|
47
|
+
const meterSummaries = await StripeUsageService.getMeterSummaries({
|
|
48
|
+
meterId: meter.id,
|
|
49
|
+
startTime: startOfMonth,
|
|
50
|
+
endTime: endOfMonth,
|
|
51
|
+
});
|
|
52
|
+
// Use the first (most recent) summary
|
|
53
|
+
summariesMap[meter.id] = meterSummaries.length > 0 ? meterSummaries[0] : null;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error(`[UsageContainer] Failed to load summaries for meter ${meter.id}:`, error);
|
|
56
|
+
summariesMap[meter.id] = null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
setSummaries(summariesMap);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error("[UsageContainer] Failed to load usage data:", error);
|
|
63
|
+
} finally {
|
|
64
|
+
setLoading(false);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Check if there are any metered subscriptions
|
|
69
|
+
const hasMeteredSubscriptions = subscriptions.some((sub) => sub.price?.recurring?.usageType === "metered");
|
|
70
|
+
|
|
71
|
+
// Don't render if no metered subscriptions
|
|
72
|
+
if (!loading && !hasMeteredSubscriptions) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (loading) {
|
|
77
|
+
return (
|
|
78
|
+
<div className="flex h-64 items-center justify-center">
|
|
79
|
+
<p className="text-muted-foreground">Loading usage data...</p>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<div className="flex w-full flex-col gap-y-6">
|
|
86
|
+
{/* Header */}
|
|
87
|
+
<div className="flex items-center gap-x-3">
|
|
88
|
+
<Activity className="h-8 w-8" />
|
|
89
|
+
<h1 className="text-3xl font-bold">Usage Tracking</h1>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
{/* Empty State */}
|
|
93
|
+
{meters.length === 0 && (
|
|
94
|
+
<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">
|
|
95
|
+
<Activity className="text-muted-foreground h-16 w-16" />
|
|
96
|
+
<div className="text-center">
|
|
97
|
+
<h3 className="mb-2 text-xl font-semibold">No usage meters configured</h3>
|
|
98
|
+
<p className="text-muted-foreground">
|
|
99
|
+
Usage tracking will appear here when you have metered subscriptions with configured meters.
|
|
100
|
+
</p>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
)}
|
|
104
|
+
|
|
105
|
+
{/* Usage Summary Cards */}
|
|
106
|
+
{meters.length > 0 && <UsageSummaryCards meters={meters} summaries={summaries} />}
|
|
107
|
+
</div>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./UsageContainer";
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Activity } from "lucide-react";
|
|
4
|
+
import { Card, CardContent, CardHeader } from "../../../../../shadcnui";
|
|
5
|
+
import { MeterInterface, MeterSummaryInterface } from "../../data/stripe-usage.interface";
|
|
6
|
+
|
|
7
|
+
type UsageSummaryCardProps = {
|
|
8
|
+
meter: MeterInterface;
|
|
9
|
+
summary: MeterSummaryInterface | null;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get progress bar color based on usage percentage
|
|
14
|
+
*/
|
|
15
|
+
function getProgressColor(percentage: number | null): string {
|
|
16
|
+
if (percentage === null) return "bg-blue-500";
|
|
17
|
+
if (percentage >= 90) return "bg-red-500";
|
|
18
|
+
if (percentage >= 75) return "bg-orange-500";
|
|
19
|
+
return "bg-green-500";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Format a Unix timestamp to readable date
|
|
24
|
+
*/
|
|
25
|
+
function formatDate(date: Date | undefined): string {
|
|
26
|
+
if (!date) return "N/A";
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
30
|
+
month: "short",
|
|
31
|
+
day: "numeric",
|
|
32
|
+
}).format(new Date(date));
|
|
33
|
+
} catch (error) {
|
|
34
|
+
return "Invalid Date";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function UsageSummaryCard({ meter, summary }: UsageSummaryCardProps) {
|
|
39
|
+
const currentUsage = summary?.aggregatedValue ?? 0;
|
|
40
|
+
const limit = (meter as any).limit; // Meters may have optional limit field
|
|
41
|
+
const percentage = limit && limit > 0 ? (currentUsage / limit) * 100 : null;
|
|
42
|
+
const progressColor = getProgressColor(percentage);
|
|
43
|
+
const progressWidth = percentage !== null ? Math.min(percentage, 100) : 0;
|
|
44
|
+
|
|
45
|
+
const displayName = meter.displayName || meter.eventName;
|
|
46
|
+
const hasLimit = limit !== null && limit !== undefined;
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<Card>
|
|
50
|
+
<CardHeader className="flex flex-row items-center gap-x-3 pb-3">
|
|
51
|
+
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-100 text-blue-600">
|
|
52
|
+
<Activity className="h-5 w-5" />
|
|
53
|
+
</div>
|
|
54
|
+
<div className="flex flex-col">
|
|
55
|
+
<h3 className="font-semibold">{displayName}</h3>
|
|
56
|
+
<p className="text-xs text-gray-500">{meter.id}</p>
|
|
57
|
+
</div>
|
|
58
|
+
</CardHeader>
|
|
59
|
+
|
|
60
|
+
<CardContent className="flex flex-col gap-y-4">
|
|
61
|
+
{/* Current Usage */}
|
|
62
|
+
<div>
|
|
63
|
+
<p className="text-3xl font-bold">{currentUsage.toLocaleString()}</p>
|
|
64
|
+
{hasLimit && <p className="text-sm text-gray-500">of {limit.toLocaleString()} used</p>}
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
{/* Progress Bar */}
|
|
68
|
+
{hasLimit ? (
|
|
69
|
+
<div className="flex flex-col gap-y-2">
|
|
70
|
+
<div className="h-2 w-full overflow-hidden rounded-full bg-gray-200">
|
|
71
|
+
<div className={`h-full transition-all ${progressColor}`} style={{ width: `${progressWidth}%` }} />
|
|
72
|
+
</div>
|
|
73
|
+
<p className="text-sm text-gray-500">{percentage?.toFixed(1)}% used</p>
|
|
74
|
+
</div>
|
|
75
|
+
) : (
|
|
76
|
+
<p className="text-sm text-gray-500">No limit set</p>
|
|
77
|
+
)}
|
|
78
|
+
|
|
79
|
+
{/* Period Information */}
|
|
80
|
+
{summary && summary.start && summary.end && (
|
|
81
|
+
<div className="border-t pt-3">
|
|
82
|
+
<p className="text-xs text-gray-500">
|
|
83
|
+
Period: {formatDate(summary.start)} - {formatDate(summary.end)}
|
|
84
|
+
</p>
|
|
85
|
+
</div>
|
|
86
|
+
)}
|
|
87
|
+
</CardContent>
|
|
88
|
+
</Card>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./UsageSummaryCard";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../../../../../shadcnui";
|
|
4
|
+
import { StripeUsageInterface } from "../../data/stripe-usage.interface";
|
|
5
|
+
|
|
6
|
+
type UsageHistoryTableProps = {
|
|
7
|
+
usageRecords: StripeUsageInterface[];
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Format a date with time for usage history
|
|
12
|
+
*/
|
|
13
|
+
function formatDateTime(date: Date | string | undefined): string {
|
|
14
|
+
if (!date) return "N/A";
|
|
15
|
+
|
|
16
|
+
const dateObj = typeof date === "string" ? new Date(date) : date;
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
20
|
+
month: "short",
|
|
21
|
+
day: "numeric",
|
|
22
|
+
year: "numeric",
|
|
23
|
+
hour: "numeric",
|
|
24
|
+
minute: "2-digit",
|
|
25
|
+
}).format(dateObj);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
return "Invalid Date";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function UsageHistoryTable({ usageRecords }: UsageHistoryTableProps) {
|
|
32
|
+
if (usageRecords.length === 0) {
|
|
33
|
+
return (
|
|
34
|
+
<div className="rounded-lg border p-8 text-center">
|
|
35
|
+
<p className="text-muted-foreground">No usage history available.</p>
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div className="flex w-full flex-col gap-y-4">
|
|
42
|
+
<h2 className="text-xl font-semibold">Usage History</h2>
|
|
43
|
+
<div className="overflow-hidden rounded-lg border">
|
|
44
|
+
<Table>
|
|
45
|
+
<TableHeader className="bg-muted">
|
|
46
|
+
<TableRow>
|
|
47
|
+
<TableHead>Date & Time</TableHead>
|
|
48
|
+
<TableHead>Meter Event</TableHead>
|
|
49
|
+
<TableHead className="text-right">Quantity</TableHead>
|
|
50
|
+
<TableHead>Event ID</TableHead>
|
|
51
|
+
</TableRow>
|
|
52
|
+
</TableHeader>
|
|
53
|
+
<TableBody>
|
|
54
|
+
{usageRecords.map((record) => {
|
|
55
|
+
const dateTime = formatDateTime(record.timestamp);
|
|
56
|
+
const quantity = record.quantity.toLocaleString();
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<TableRow key={record.id}>
|
|
60
|
+
<TableCell className="font-medium">{dateTime}</TableCell>
|
|
61
|
+
<TableCell className="text-muted-foreground">{record.meterEventName}</TableCell>
|
|
62
|
+
<TableCell className="text-right font-medium">{quantity}</TableCell>
|
|
63
|
+
<TableCell className="text-muted-foreground text-sm font-mono">{record.stripeEventId}</TableCell>
|
|
64
|
+
</TableRow>
|
|
65
|
+
);
|
|
66
|
+
})}
|
|
67
|
+
</TableBody>
|
|
68
|
+
</Table>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./UsageHistoryTable";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { MeterInterface, MeterSummaryInterface } from "../../data/stripe-usage.interface";
|
|
4
|
+
import { UsageSummaryCard } from "../details/UsageSummaryCard";
|
|
5
|
+
|
|
6
|
+
type UsageSummaryCardsProps = {
|
|
7
|
+
meters: MeterInterface[];
|
|
8
|
+
summaries: Record<string, MeterSummaryInterface | null>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export function UsageSummaryCards({ meters, summaries }: UsageSummaryCardsProps) {
|
|
12
|
+
return (
|
|
13
|
+
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
14
|
+
{meters.map((meter) => (
|
|
15
|
+
<UsageSummaryCard key={meter.id} meter={meter} summary={summaries[meter.id] || null} />
|
|
16
|
+
))}
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./UsageSummaryCards";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ApiDataInterface } from "../../../../core";
|
|
2
|
+
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Usage Record Interfaces
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
export interface StripeUsageInterface extends ApiDataInterface {
|
|
8
|
+
get subscriptionId(): string;
|
|
9
|
+
get meterId(): string;
|
|
10
|
+
get meterEventName(): string;
|
|
11
|
+
get stripeEventId(): string;
|
|
12
|
+
get quantity(): number;
|
|
13
|
+
get timestamp(): Date | undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Meter Interfaces
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
export interface MeterInterface {
|
|
21
|
+
id: string;
|
|
22
|
+
displayName: string;
|
|
23
|
+
eventName: string;
|
|
24
|
+
status: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface MeterSummaryInterface {
|
|
28
|
+
meterId: string;
|
|
29
|
+
start: Date;
|
|
30
|
+
end: Date;
|
|
31
|
+
aggregatedValue: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface UsageSummaryInterface {
|
|
35
|
+
subscriptionItemId: string;
|
|
36
|
+
period: {
|
|
37
|
+
start: Date;
|
|
38
|
+
end: Date;
|
|
39
|
+
};
|
|
40
|
+
totalUsage: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// Usage Input DTOs
|
|
45
|
+
// ============================================================================
|
|
46
|
+
|
|
47
|
+
export type ReportUsageInput = {
|
|
48
|
+
subscriptionItemId: string;
|
|
49
|
+
quantity: number;
|
|
50
|
+
timestamp?: number;
|
|
51
|
+
action?: "increment" | "set";
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Backwards compatibility alias
|
|
55
|
+
export type UsageRecordInterface = StripeUsageInterface;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { AbstractService, EndpointCreator, HttpMethod, Modules, NextRef, PreviousRef } from "../../../../core";
|
|
2
|
+
import {
|
|
3
|
+
MeterInterface,
|
|
4
|
+
MeterSummaryInterface,
|
|
5
|
+
ReportUsageInput,
|
|
6
|
+
StripeUsageInterface,
|
|
7
|
+
UsageSummaryInterface,
|
|
8
|
+
} from "./stripe-usage.interface";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Service for managing Stripe usage tracking
|
|
12
|
+
*/
|
|
13
|
+
export class StripeUsageService extends AbstractService {
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Meter Methods
|
|
16
|
+
// ============================================================================
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* List all available usage meters
|
|
20
|
+
*/
|
|
21
|
+
static async listMeters(params?: { next?: NextRef; prev?: PreviousRef }): Promise<MeterInterface[]> {
|
|
22
|
+
const endpoint = new EndpointCreator({
|
|
23
|
+
endpoint: Modules.StripeUsage,
|
|
24
|
+
childEndpoint: "meters",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return this.callApi({
|
|
28
|
+
type: Modules.StripeUsage,
|
|
29
|
+
method: HttpMethod.GET,
|
|
30
|
+
endpoint: endpoint.generate(),
|
|
31
|
+
next: params?.next,
|
|
32
|
+
previous: params?.prev,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get meter summaries for a specific time period
|
|
38
|
+
*/
|
|
39
|
+
static async getMeterSummaries(params: {
|
|
40
|
+
meterId: string;
|
|
41
|
+
startTime: Date;
|
|
42
|
+
endTime: Date;
|
|
43
|
+
}): Promise<MeterSummaryInterface[]> {
|
|
44
|
+
const endpoint = new EndpointCreator({
|
|
45
|
+
endpoint: Modules.StripeUsage,
|
|
46
|
+
childEndpoint: `meters/${params.meterId}/summaries`,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
endpoint.addAdditionalParam("startTime", params.startTime.toISOString());
|
|
50
|
+
endpoint.addAdditionalParam("endTime", params.endTime.toISOString());
|
|
51
|
+
|
|
52
|
+
return this.callApi({
|
|
53
|
+
type: Modules.StripeUsage,
|
|
54
|
+
method: HttpMethod.GET,
|
|
55
|
+
endpoint: endpoint.generate(),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// Usage Record Methods
|
|
61
|
+
// ============================================================================
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Report usage for a subscription item
|
|
65
|
+
*/
|
|
66
|
+
static async reportUsage(params: ReportUsageInput): Promise<StripeUsageInterface> {
|
|
67
|
+
const endpoint = new EndpointCreator({
|
|
68
|
+
endpoint: Modules.StripeUsage,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return this.callApi<StripeUsageInterface>({
|
|
72
|
+
type: Modules.StripeUsage,
|
|
73
|
+
method: HttpMethod.POST,
|
|
74
|
+
endpoint: endpoint.generate(),
|
|
75
|
+
input: params,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* List usage records for a subscription item
|
|
81
|
+
*/
|
|
82
|
+
static async listUsageRecords(params: {
|
|
83
|
+
subscriptionItemId: string;
|
|
84
|
+
next?: NextRef;
|
|
85
|
+
prev?: PreviousRef;
|
|
86
|
+
}): Promise<StripeUsageInterface[]> {
|
|
87
|
+
const endpoint = new EndpointCreator({
|
|
88
|
+
endpoint: Modules.StripeUsage,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
endpoint.addAdditionalParam("subscriptionItemId", params.subscriptionItemId);
|
|
92
|
+
|
|
93
|
+
return this.callApi({
|
|
94
|
+
type: Modules.StripeUsage,
|
|
95
|
+
method: HttpMethod.GET,
|
|
96
|
+
endpoint: endpoint.generate(),
|
|
97
|
+
next: params?.next,
|
|
98
|
+
previous: params?.prev,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Get usage summary for a subscription item
|
|
104
|
+
*/
|
|
105
|
+
static async getUsageSummary(params: {
|
|
106
|
+
subscriptionItemId: string;
|
|
107
|
+
start?: Date;
|
|
108
|
+
end?: Date;
|
|
109
|
+
}): Promise<UsageSummaryInterface> {
|
|
110
|
+
const endpoint = new EndpointCreator({
|
|
111
|
+
endpoint: Modules.StripeUsage,
|
|
112
|
+
childEndpoint: "summary",
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
endpoint.addAdditionalParam("subscriptionItemId", params.subscriptionItemId);
|
|
116
|
+
if (params.start) {
|
|
117
|
+
endpoint.addAdditionalParam("start", params.start.toISOString());
|
|
118
|
+
}
|
|
119
|
+
if (params.end) {
|
|
120
|
+
endpoint.addAdditionalParam("end", params.end.toISOString());
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return this.callApi({
|
|
124
|
+
type: Modules.StripeUsage,
|
|
125
|
+
method: HttpMethod.GET,
|
|
126
|
+
endpoint: endpoint.generate(),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { AbstractApiData, JsonApiHydratedDataInterface, Modules } from "../../../../core";
|
|
2
|
+
import { ReportUsageInput, StripeUsageInterface } from "./stripe-usage.interface";
|
|
3
|
+
|
|
4
|
+
export class StripeUsage extends AbstractApiData implements StripeUsageInterface {
|
|
5
|
+
private _subscriptionId?: string;
|
|
6
|
+
private _meterId?: string;
|
|
7
|
+
private _meterEventName?: string;
|
|
8
|
+
private _stripeEventId?: string;
|
|
9
|
+
private _quantity?: number;
|
|
10
|
+
private _timestamp?: Date;
|
|
11
|
+
|
|
12
|
+
get subscriptionId(): string {
|
|
13
|
+
if (!this._subscriptionId) throw new Error("subscriptionId is not defined");
|
|
14
|
+
return this._subscriptionId;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get meterId(): string {
|
|
18
|
+
if (!this._meterId) throw new Error("meterId is not defined");
|
|
19
|
+
return this._meterId;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get meterEventName(): string {
|
|
23
|
+
if (!this._meterEventName) throw new Error("meterEventName is not defined");
|
|
24
|
+
return this._meterEventName;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get stripeEventId(): string {
|
|
28
|
+
if (!this._stripeEventId) throw new Error("stripeEventId is not defined");
|
|
29
|
+
return this._stripeEventId;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get quantity(): number {
|
|
33
|
+
if (this._quantity === undefined) throw new Error("quantity is not defined");
|
|
34
|
+
return this._quantity;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get timestamp(): Date | undefined {
|
|
38
|
+
return this._timestamp;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
rehydrate(data: JsonApiHydratedDataInterface): this {
|
|
42
|
+
super.rehydrate(data);
|
|
43
|
+
|
|
44
|
+
this._subscriptionId = data.jsonApi.attributes.subscriptionId;
|
|
45
|
+
this._meterId = data.jsonApi.attributes.meterId;
|
|
46
|
+
this._meterEventName = data.jsonApi.attributes.meterEventName;
|
|
47
|
+
this._stripeEventId = data.jsonApi.attributes.stripeEventId;
|
|
48
|
+
this._quantity = data.jsonApi.attributes.quantity;
|
|
49
|
+
this._timestamp = data.jsonApi.attributes.timestamp ? new Date(data.jsonApi.attributes.timestamp) : undefined;
|
|
50
|
+
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
createJsonApi(data: ReportUsageInput): any {
|
|
55
|
+
const response: any = {
|
|
56
|
+
data: {
|
|
57
|
+
type: Modules.StripeUsage.name,
|
|
58
|
+
attributes: {
|
|
59
|
+
subscriptionItemId: data.subscriptionItemId,
|
|
60
|
+
quantity: data.quantity,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
if (data.timestamp !== undefined) response.data.attributes.timestamp = data.timestamp;
|
|
66
|
+
if (data.action !== undefined) response.data.attributes.action = data.action;
|
|
67
|
+
|
|
68
|
+
return response;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ModuleFactory } from "../../../permissions";
|
|
2
|
+
import { StripeUsage } from "./data/stripe-usage";
|
|
3
|
+
|
|
4
|
+
export const StripeUsageModule = (factory: ModuleFactory) =>
|
|
5
|
+
factory({
|
|
6
|
+
name: "stripe-usage-records",
|
|
7
|
+
model: StripeUsage,
|
|
8
|
+
moduleId: "c2e9f4a6-1d7b-4e3a-8f5c-9b2d6a1e7f3c",
|
|
9
|
+
});
|
|
@@ -26,8 +26,8 @@ import { useI18nRouter } from "../../../../i18n";
|
|
|
26
26
|
import { getRoleId } from "../../../../roles";
|
|
27
27
|
import { Dialog, DialogContent, Form, ScrollArea } from "../../../../shadcnui";
|
|
28
28
|
import { FeatureInterface } from "../../../feature";
|
|
29
|
-
import { S3Interface } from "../../../s3";
|
|
30
29
|
import { FeatureService } from "../../../feature/data/feature.service";
|
|
30
|
+
import { S3Interface } from "../../../s3";
|
|
31
31
|
import { S3Service } from "../../../s3/data/s3.service";
|
|
32
32
|
import { UserInterface } from "../../../user";
|
|
33
33
|
import { useCurrentUserContext } from "../../../user/contexts";
|
|
@@ -122,7 +122,7 @@ function CompanyEditorInternal({ company, propagateChanges, onRevalidate }: Comp
|
|
|
122
122
|
if (hasRole(getRoleId().Administrator)) {
|
|
123
123
|
setFeatures(allfeatures);
|
|
124
124
|
} else {
|
|
125
|
-
setFeatures(allfeatures.filter((feature) => feature.
|
|
125
|
+
setFeatures(allfeatures.filter((feature) => feature.isCore));
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
if (
|
|
@@ -26,8 +26,8 @@ import {
|
|
|
26
26
|
Link,
|
|
27
27
|
} from "../../../../shadcnui";
|
|
28
28
|
import { UserInterface } from "../../../user";
|
|
29
|
-
import { UserService } from "../../../user/data/user.service";
|
|
30
29
|
import { useCurrentUserContext } from "../../../user/contexts";
|
|
30
|
+
import { UserService } from "../../../user/data/user.service";
|
|
31
31
|
import { CompanyInput } from "../../data";
|
|
32
32
|
import { CompanyService } from "../../data/company.service";
|
|
33
33
|
|
|
@@ -154,11 +154,11 @@ export default function CompanyLicense({ onRevalidate, onUpdateToken }: CompanyL
|
|
|
154
154
|
<CardHeader>
|
|
155
155
|
<CardTitle>Company License Required</CardTitle>
|
|
156
156
|
<CardDescription className={`flex w-full flex-col`}>
|
|
157
|
-
<div>You need to activate your license to use
|
|
157
|
+
<div>You need to activate your license to use Only35.</div>
|
|
158
158
|
<div>
|
|
159
159
|
<span>To obtain your license, please visit</span>
|
|
160
|
-
<Link href="https://
|
|
161
|
-
our website (https://
|
|
160
|
+
<Link href="https://only35.com" target="_blank" className={`text-primary`}>
|
|
161
|
+
our website (https://only35.com)
|
|
162
162
|
</Link>
|
|
163
163
|
<span>, register for an account and follow the instructions provided.</span>
|
|
164
164
|
</div>
|
|
@@ -10,7 +10,7 @@ import { Action } from "../../../permissions";
|
|
|
10
10
|
import { getRoleId } from "../../../roles";
|
|
11
11
|
import { UserInterface } from "../../user";
|
|
12
12
|
import { useCurrentUserContext } from "../../user/contexts";
|
|
13
|
-
import {
|
|
13
|
+
import { CompanyDeleter, CompanyEditor } from "../components";
|
|
14
14
|
import { CompanyInterface } from "../data";
|
|
15
15
|
|
|
16
16
|
interface CompanyContextType {
|
|
@@ -71,7 +71,7 @@ export const CompanyProvider = ({ children, dehydratedCompany }: CompanyProvider
|
|
|
71
71
|
hasRole(getRoleId().Administrator) ||
|
|
72
72
|
hasPermissionToModule({ module: Modules.Company, action: Action.Update })
|
|
73
73
|
) {
|
|
74
|
-
if (company) functions.push(<CompanyConfigurationEditor key="companyConfigurationEditor" company={company} />);
|
|
74
|
+
// if (company) functions.push(<CompanyConfigurationEditor key="companyConfigurationEditor" company={company} />);
|
|
75
75
|
functions.push(<CompanyEditor key="companyEditor" company={company} propagateChanges={setCompany} />);
|
|
76
76
|
}
|
|
77
77
|
|