@carlonicora/nextjs-jsonapi 1.28.0 → 1.29.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.
Files changed (95) hide show
  1. package/dist/{BlockNoteEditor-CAUNVZUF.js → BlockNoteEditor-YBVEOPV4.js} +13 -13
  2. package/dist/{BlockNoteEditor-CAUNVZUF.js.map → BlockNoteEditor-YBVEOPV4.js.map} +1 -1
  3. package/dist/{BlockNoteEditor-EOA4OEVX.mjs → BlockNoteEditor-ZM4YPXHO.mjs} +3 -3
  4. package/dist/billing/index.d.mts +47 -17
  5. package/dist/billing/index.d.ts +47 -17
  6. package/dist/billing/index.js +1241 -1073
  7. package/dist/billing/index.js.map +1 -1
  8. package/dist/billing/index.mjs +1375 -1207
  9. package/dist/billing/index.mjs.map +1 -1
  10. package/dist/{chunk-IXI4GAKB.js → chunk-3X7EEFMN.js} +488 -431
  11. package/dist/chunk-3X7EEFMN.js.map +1 -0
  12. package/dist/{chunk-ORFXBO7F.mjs → chunk-DU64WMZD.mjs} +6 -3
  13. package/dist/chunk-DU64WMZD.mjs.map +1 -0
  14. package/dist/{chunk-TSEU4KZ2.js → chunk-J22NEVSK.js} +21 -18
  15. package/dist/chunk-J22NEVSK.js.map +1 -0
  16. package/dist/{chunk-PYASRX75.mjs → chunk-UCD5CUE4.mjs} +81 -24
  17. package/dist/chunk-UCD5CUE4.mjs.map +1 -0
  18. package/dist/client/index.d.mts +14 -5
  19. package/dist/client/index.d.ts +14 -5
  20. package/dist/client/index.js +5 -3
  21. package/dist/client/index.js.map +1 -1
  22. package/dist/client/index.mjs +4 -2
  23. package/dist/components/index.d.mts +2 -2
  24. package/dist/components/index.d.ts +2 -2
  25. package/dist/components/index.js +3 -3
  26. package/dist/components/index.mjs +2 -2
  27. package/dist/{config-B4pZpLT9.d.ts → config-CHwoRDOp.d.ts} +1 -1
  28. package/dist/{config-DT1K-t6I.d.mts → config-DiWyJzk9.d.mts} +1 -1
  29. package/dist/{content.interface-B2Ldg0vg.d.mts → content.interface-BSpowEiW.d.mts} +1 -1
  30. package/dist/{content.interface-D8NHv3DX.d.ts → content.interface-DFQ7mkpL.d.ts} +1 -1
  31. package/dist/contexts/index.d.mts +2 -2
  32. package/dist/contexts/index.d.ts +2 -2
  33. package/dist/contexts/index.js +3 -3
  34. package/dist/contexts/index.mjs +2 -2
  35. package/dist/core/index.d.mts +39 -37
  36. package/dist/core/index.d.ts +39 -37
  37. package/dist/core/index.js +2 -2
  38. package/dist/core/index.mjs +1 -1
  39. package/dist/index.d.mts +4 -4
  40. package/dist/index.d.ts +4 -4
  41. package/dist/index.js +2 -2
  42. package/dist/index.mjs +1 -1
  43. package/dist/{notification.interface-H0L9WBge.d.ts → notification.interface-CmKmObIU.d.ts} +1 -0
  44. package/dist/{notification.interface-DEn-Yp_b.d.mts → notification.interface-D5MbtfZK.d.mts} +1 -0
  45. package/dist/{s3.service-BNytYanU.d.mts → s3.service-BMT7W6KS.d.mts} +19 -19
  46. package/dist/{s3.service-C7f_Ygz5.d.ts → s3.service-DsXo9nop.d.ts} +19 -19
  47. package/dist/server/index.d.mts +3 -3
  48. package/dist/server/index.d.ts +3 -3
  49. package/dist/server/index.js +3 -3
  50. package/dist/server/index.mjs +1 -1
  51. package/dist/{useSocket-BcnThTD0.d.mts → useSocket-DUqGoPya.d.mts} +1 -1
  52. package/dist/{useSocket-QZTOCzRF.d.ts → useSocket-QuHa0ZmO.d.ts} +1 -1
  53. package/package.json +1 -1
  54. package/src/client/index.ts +1 -0
  55. package/src/components/forms/FormSelect.tsx +2 -1
  56. package/src/features/auth/data/auth.ts +0 -2
  57. package/src/features/billing/components/containers/BillingDashboardContainer.tsx +60 -3
  58. package/src/features/billing/stripe-customer/components/forms/PaymentMethodEditor.tsx +12 -152
  59. package/src/features/billing/stripe-customer/components/forms/PaymentMethodForm.tsx +168 -0
  60. package/src/features/billing/stripe-customer/components/forms/index.ts +1 -0
  61. package/src/features/billing/stripe-price/components/forms/PriceEditor.tsx +19 -1
  62. package/src/features/billing/stripe-product/components/forms/ProductEditor.tsx +2 -2
  63. package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +24 -235
  64. package/src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx +7 -18
  65. package/src/features/billing/stripe-subscription/components/forms/index.ts +0 -1
  66. package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +10 -1
  67. package/src/features/billing/stripe-subscription/components/widgets/IntervalToggle.tsx +28 -0
  68. package/src/features/billing/stripe-subscription/components/widgets/ProductPricingList.tsx +128 -0
  69. package/src/features/billing/stripe-subscription/components/widgets/ProductPricingRow.tsx +54 -0
  70. package/src/features/billing/stripe-subscription/components/widgets/SubscriptionConfirmation.tsx +68 -0
  71. package/src/features/billing/stripe-subscription/components/widgets/index.ts +4 -1
  72. package/src/features/billing/stripe-subscription/components/wizards/SubscriptionWizard.tsx +114 -0
  73. package/src/features/billing/stripe-subscription/components/wizards/WizardProgressIndicator.tsx +66 -0
  74. package/src/features/billing/stripe-subscription/components/wizards/WizardStepPaymentMethod.tsx +32 -0
  75. package/src/features/billing/stripe-subscription/components/wizards/WizardStepPlanSelection.tsx +103 -0
  76. package/src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx +133 -0
  77. package/src/features/billing/stripe-subscription/components/wizards/index.ts +6 -0
  78. package/src/features/billing/stripe-subscription/hooks/useSubscriptionWizard.ts +217 -0
  79. package/src/features/billing/stripe-subscription/index.ts +3 -2
  80. package/src/features/company/components/details/TokenStatusIndicator.tsx +19 -9
  81. package/src/features/company/data/company.interface.ts +2 -0
  82. package/src/features/company/data/company.ts +7 -0
  83. package/src/features/company/hooks/index.ts +1 -0
  84. package/src/features/company/hooks/useSubscriptionStatus.ts +71 -0
  85. package/src/features/user/components/forms/UserEditor.tsx +1 -1
  86. package/src/features/user/components/lists/AdminUsersList.tsx +1 -1
  87. package/src/features/user/contexts/CurrentUserContext.tsx +1 -1
  88. package/src/features/user/data/user.ts +1 -1
  89. package/dist/chunk-IXI4GAKB.js.map +0 -1
  90. package/dist/chunk-ORFXBO7F.mjs.map +0 -1
  91. package/dist/chunk-PYASRX75.mjs.map +0 -1
  92. package/dist/chunk-TSEU4KZ2.js.map +0 -1
  93. package/src/features/billing/stripe-subscription/components/forms/SubscriptionEditor.tsx +0 -331
  94. package/src/features/billing/stripe-subscription/components/widgets/PricingCardsGrid.tsx +0 -110
  95. /package/dist/{BlockNoteEditor-EOA4OEVX.mjs.map → BlockNoteEditor-ZM4YPXHO.mjs.map} +0 -0
@@ -1,10 +1,11 @@
1
1
  "use client";
2
2
 
3
3
  import { Battery, BatteryFull, BatteryLow, BatteryMedium, PlusCircle } from "lucide-react";
4
+ import Link from "next/link";
4
5
 
5
6
  import { cn } from "@/lib/utils";
6
7
  import { useTranslations } from "next-intl";
7
- import { Tooltip, TooltipContent, TooltipTrigger } from "../../../../shadcnui";
8
+ import { Button, Separator, Tooltip, TooltipContent, TooltipTrigger } from "../../../../shadcnui";
8
9
  import { useCurrentUserContext } from "../../../user/contexts";
9
10
 
10
11
  interface TokenStatusIndicatorProps {
@@ -99,14 +100,23 @@ export function TokenStatusIndicator({ className, size = "md", showExtraPages =
99
100
  <span className="text-muted-foreground">{t("generic.tokens.available", { defaultValue: "Available" })}:</span>
100
101
  <span className={cn("font-medium", getStatusColor())}>{percentage.toFixed(0)}%</span>
101
102
  </div>
102
- {showExtraPages && (
103
- <div className="flex items-center justify-between gap-4 border-t pt-1 mt-1">
104
- <span className="text-muted-foreground">
105
- {t("generic.tokens.available_extra", { defaultValue: "Extra Pages" })}:
106
- </span>
107
- <span className="font-medium text-blue-500">{availableExtraTokens}</span>
108
- </div>
109
- )}
103
+ <Link href="/settings/billing?action=subscribe" className="w-full flex justify-end my-4">
104
+ <Button variant="outline" size="sm">
105
+ {t("generic.tokens.upgrade_plan", { defaultValue: "Upgrade plan" })}
106
+ </Button>
107
+ </Link>
108
+ <Separator />
109
+ <div className="flex items-center justify-between gap-4 pt-1 mt-1">
110
+ <span className="text-muted-foreground">
111
+ {t("generic.tokens.available_extra", { defaultValue: "Extra Pages" })}:
112
+ </span>
113
+ <span className="font-medium text-blue-500">{availableExtraTokens}</span>
114
+ </div>
115
+ <Link href="/settings/billing?action=subscribe" className="w-full flex justify-end my-4">
116
+ <Button variant="outline" size="sm">
117
+ {t("generic.tokens.purchase_extra", { defaultValue: "Purchase additional analysis" })}
118
+ </Button>
119
+ </Link>
110
120
  </div>
111
121
  </div>
112
122
  );
@@ -22,6 +22,8 @@ export interface CompanyInterface extends ApiDataInterface {
22
22
  get logo(): string | undefined;
23
23
  get logoUrl(): string | undefined;
24
24
 
25
+ get isActiveSubscription(): boolean;
26
+
25
27
  get monthlyTokens(): number;
26
28
  get availableMonthlyTokens(): number;
27
29
  get availableExtraTokens(): number;
@@ -9,6 +9,8 @@ export class Company extends AbstractApiData implements CompanyInterface {
9
9
  private _logoUrl?: string;
10
10
  private _configurations?: any;
11
11
 
12
+ private _isActiveSubscription: boolean = false;
13
+
12
14
  private _monthlyTokens: number = 0;
13
15
  private _availableMonthlyTokens: number = 0;
14
16
  private _availableExtraTokens: number = 0;
@@ -29,6 +31,10 @@ export class Company extends AbstractApiData implements CompanyInterface {
29
31
  return this._logoUrl;
30
32
  }
31
33
 
34
+ get isActiveSubscription(): boolean {
35
+ return this._isActiveSubscription ?? false;
36
+ }
37
+
32
38
  get monthlyTokens(): number {
33
39
  return this._monthlyTokens ?? 0;
34
40
  }
@@ -62,6 +68,7 @@ export class Company extends AbstractApiData implements CompanyInterface {
62
68
  : undefined;
63
69
  this._logo = data.jsonApi.attributes.logo;
64
70
  this._logoUrl = data.jsonApi.attributes.logoUrl;
71
+ this._isActiveSubscription = data.jsonApi.attributes.isActiveSubscription ?? false;
65
72
  this._monthlyTokens = data.jsonApi.attributes.monthlyTokens ?? 0;
66
73
  this._availableMonthlyTokens = data.jsonApi.attributes.availableMonthlyTokens ?? 0;
67
74
  this._availableExtraTokens = data.jsonApi.attributes.availableExtraTokens ?? 0;
@@ -1 +1,2 @@
1
1
  export * from "./useCompanyTableStructure";
2
+ export * from "./useSubscriptionStatus";
@@ -0,0 +1,71 @@
1
+ "use client";
2
+
3
+ import { useMemo } from "react";
4
+ import { useCurrentUserContext } from "../../user/contexts/CurrentUserContext";
5
+
6
+ export interface TrialSubscriptionStatus {
7
+ status: "loading" | "trial" | "active" | "expired";
8
+ trialEndsAt: Date | null;
9
+ daysRemaining: number;
10
+ isGracePeriod: boolean; // Last 3 days
11
+ isBlocked: boolean;
12
+ }
13
+
14
+ const TRIAL_DAYS = 14;
15
+ const GRACE_DAYS = 3;
16
+
17
+ export function useSubscriptionStatus(): TrialSubscriptionStatus {
18
+ const { company, currentUser } = useCurrentUserContext();
19
+
20
+ return useMemo(() => {
21
+ // Still loading user data - don't block yet
22
+ if (currentUser === null) {
23
+ return {
24
+ status: "loading",
25
+ trialEndsAt: null,
26
+ daysRemaining: 0,
27
+ isGracePeriod: false,
28
+ isBlocked: false,
29
+ };
30
+ }
31
+
32
+ // No company after loading = blocked
33
+ if (!company) {
34
+ return {
35
+ status: "expired",
36
+ trialEndsAt: null,
37
+ daysRemaining: 0,
38
+ isGracePeriod: false,
39
+ isBlocked: true,
40
+ };
41
+ }
42
+
43
+ // Has active subscription = never blocked
44
+ if (company.isActiveSubscription) {
45
+ return {
46
+ status: "active",
47
+ trialEndsAt: null,
48
+ daysRemaining: 0,
49
+ isGracePeriod: false,
50
+ isBlocked: false,
51
+ };
52
+ }
53
+
54
+ // Calculate trial status from createdAt
55
+ const createdAt = new Date(company.createdAt);
56
+ const trialEndsAt = new Date(createdAt);
57
+ trialEndsAt.setDate(trialEndsAt.getDate() + TRIAL_DAYS);
58
+
59
+ const now = new Date();
60
+ const msRemaining = trialEndsAt.getTime() - now.getTime();
61
+ const daysRemaining = Math.ceil(msRemaining / (1000 * 60 * 60 * 24));
62
+
63
+ return {
64
+ status: daysRemaining > 0 ? "trial" : "expired",
65
+ trialEndsAt,
66
+ daysRemaining: Math.max(0, daysRemaining),
67
+ isGracePeriod: daysRemaining > 0 && daysRemaining <= GRACE_DAYS,
68
+ isBlocked: daysRemaining <= 0,
69
+ };
70
+ }, [company, currentUser]);
71
+ }
@@ -23,7 +23,7 @@ import { useI18nRouter, usePageUrlGenerator } from "../../../../hooks";
23
23
  import { Action } from "../../../../permissions";
24
24
  import { getRoleId } from "../../../../roles";
25
25
  import { Dialog, DialogContent, DialogTrigger, Form } from "../../../../shadcnui";
26
- import { CompanyInterface } from "../../../company";
26
+ import { CompanyInterface } from "../../../company/data/company.interface";
27
27
  import { RoleInterface } from "../../../role";
28
28
  import { RoleService } from "../../../role/data/role.service";
29
29
  import { S3Interface } from "../../../s3";
@@ -5,7 +5,7 @@ import { ContentListTable } from "../../../../components";
5
5
  import { useCompanyContext } from "../../../../contexts";
6
6
  import { Modules } from "../../../../core";
7
7
  import { DataListRetriever, useDataListRetriever } from "../../../../hooks";
8
- import { CompanyInterface } from "../../../company";
8
+ import { CompanyInterface } from "../../../company/data/company.interface";
9
9
  import { UserFields, UserInterface } from "../../data";
10
10
  import { UserService } from "../../data/user.service";
11
11
  import { UserEditor } from "../forms";
@@ -8,7 +8,7 @@ import React, { createContext, useCallback, useContext, useEffect, useRef, useSt
8
8
  import { Modules, rehydrate } from "../../../core";
9
9
  import { Action, checkPermissions, ModuleWithPermissions } from "../../../permissions";
10
10
  import { getRoleId } from "../../../roles";
11
- import { CompanyInterface } from "../../company";
11
+ import { CompanyInterface } from "../../company/data/company.interface";
12
12
  import { FeatureInterface } from "../../feature";
13
13
  import { RoleInterface } from "../../role";
14
14
  import { UserInterface, UserService } from "../data";
@@ -1,5 +1,5 @@
1
1
  import { AbstractApiData, JsonApiHydratedDataInterface, Modules } from "../../../core";
2
- import { CompanyInterface } from "../../company";
2
+ import { CompanyInterface } from "../../company/data/company.interface";
3
3
  import { ModuleInterface } from "../../module";
4
4
  import { RoleInterface } from "../../role";
5
5
  import { SearchResultInterface } from "../../search";