@carlonicora/nextjs-jsonapi 6.1.0 → 6.3.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 (127) hide show
  1. package/dist/{AssistantMessageInterface-S7oyERTT.d.mts → AssistantMessageInterface-0ZQ1EJKO.d.mts} +1 -1
  2. package/dist/{AssistantMessageInterface-DHJJO_Z_.d.ts → AssistantMessageInterface-CA-hZ5Wj.d.ts} +1 -1
  3. package/dist/{BlockNoteEditor-SAU3G6H7.js → BlockNoteEditor-CT4XUXPC.js} +19 -19
  4. package/dist/{BlockNoteEditor-SAU3G6H7.js.map → BlockNoteEditor-CT4XUXPC.js.map} +1 -1
  5. package/dist/{BlockNoteEditor-FZNU4YQT.mjs → BlockNoteEditor-M6UQRVRK.mjs} +4 -4
  6. package/dist/{BlockNoteViewer-7BTV7QQA.js → BlockNoteViewer-MFLWF3Y2.js} +3 -3
  7. package/dist/{BlockNoteViewer-7BTV7QQA.js.map → BlockNoteViewer-MFLWF3Y2.js.map} +1 -1
  8. package/dist/{BlockNoteViewer-6XDDVTN6.mjs → BlockNoteViewer-XZJ5Y7WN.mjs} +2 -2
  9. package/dist/{BlogPostInterface-BB_4wcDR.d.mts → BlogPostInterface-BN2mXc46.d.mts} +1 -1
  10. package/dist/{BlogPostInterface-bWAT1rfR.d.ts → BlogPostInterface-CTGfsR1I.d.ts} +1 -1
  11. package/dist/{auth.interface-CSzJ1oP1.d.ts → auth.interface-D5606g19.d.ts} +1 -1
  12. package/dist/{auth.interface-DD4uQv2K.d.mts → auth.interface-tsOuc0Fi.d.mts} +1 -1
  13. package/dist/billing/index.d.mts +3 -3
  14. package/dist/billing/index.d.ts +3 -3
  15. package/dist/billing/index.js +501 -493
  16. package/dist/billing/index.js.map +1 -1
  17. package/dist/billing/index.mjs +13 -5
  18. package/dist/billing/index.mjs.map +1 -1
  19. package/dist/{chunk-USYZNWKS.mjs → chunk-3FD6Y734.mjs} +74 -15
  20. package/dist/chunk-3FD6Y734.mjs.map +1 -0
  21. package/dist/{chunk-F4JB7YAP.js → chunk-DSGP6GC3.js} +8 -8
  22. package/dist/{chunk-F4JB7YAP.js.map → chunk-DSGP6GC3.js.map} +1 -1
  23. package/dist/{chunk-GFGKMUPZ.mjs → chunk-O2TEUH5S.mjs} +2 -2
  24. package/dist/{chunk-MTI2UXDA.js → chunk-QJIDORHM.js} +4 -4
  25. package/dist/{chunk-MTI2UXDA.js.map → chunk-QJIDORHM.js.map} +1 -1
  26. package/dist/{chunk-JVJS5RHB.mjs → chunk-RUJCWOJE.mjs} +2 -2
  27. package/dist/{chunk-U7DR5VDT.mjs → chunk-TIT4CJYQ.mjs} +1233 -1181
  28. package/dist/chunk-TIT4CJYQ.mjs.map +1 -0
  29. package/dist/{chunk-TPZS46IM.js → chunk-V4I3XKOM.js} +3 -3
  30. package/dist/{chunk-TPZS46IM.js.map → chunk-V4I3XKOM.js.map} +1 -1
  31. package/dist/{chunk-T3YQ47EF.js → chunk-XZCCIKX3.js} +152 -93
  32. package/dist/chunk-XZCCIKX3.js.map +1 -0
  33. package/dist/{chunk-IPYXT7MH.js → chunk-Y7JIQNM6.js} +922 -870
  34. package/dist/chunk-Y7JIQNM6.js.map +1 -0
  35. package/dist/{chunk-RYZYKG6W.mjs → chunk-ZDUT5JPT.mjs} +2 -2
  36. package/dist/client/index.d.mts +4 -4
  37. package/dist/client/index.d.ts +4 -4
  38. package/dist/client/index.js +4 -4
  39. package/dist/client/index.mjs +3 -3
  40. package/dist/components/index.d.mts +22 -6
  41. package/dist/components/index.d.ts +22 -6
  42. package/dist/components/index.js +10 -4
  43. package/dist/components/index.js.map +1 -1
  44. package/dist/components/index.mjs +10 -4
  45. package/dist/contexts/index.d.mts +5 -5
  46. package/dist/contexts/index.d.ts +5 -5
  47. package/dist/contexts/index.js +4 -4
  48. package/dist/contexts/index.mjs +3 -3
  49. package/dist/core/index.d.mts +23 -13
  50. package/dist/core/index.d.ts +23 -13
  51. package/dist/core/index.js +8 -2
  52. package/dist/core/index.js.map +1 -1
  53. package/dist/core/index.mjs +7 -1
  54. package/dist/{currency-DrEVd_Xs.d.mts → currency-BhuEoBOn.d.mts} +2 -115
  55. package/dist/{currency-8ErEC39n.d.ts → currency-CBgZkS0u.d.ts} +2 -115
  56. package/dist/email-automations/index.js +92 -92
  57. package/dist/email-automations/index.mjs +3 -3
  58. package/dist/features/analytics/index.d.mts +11 -3
  59. package/dist/features/analytics/index.d.ts +11 -3
  60. package/dist/features/analytics/index.js +129 -127
  61. package/dist/features/analytics/index.js.map +1 -1
  62. package/dist/features/analytics/index.mjs +12 -10
  63. package/dist/features/analytics/index.mjs.map +1 -1
  64. package/dist/features/analytics/server.js +4 -4
  65. package/dist/features/analytics/server.mjs +2 -2
  66. package/dist/features/blog/index.d.mts +4 -4
  67. package/dist/features/blog/index.d.ts +4 -4
  68. package/dist/features/blog/index.js +150 -150
  69. package/dist/features/blog/index.mjs +3 -3
  70. package/dist/features/blog/server.d.mts +4 -4
  71. package/dist/features/blog/server.d.ts +4 -4
  72. package/dist/features/blog/server.js +16 -16
  73. package/dist/features/blog/server.mjs +1 -1
  74. package/dist/features/help/index.js +37 -37
  75. package/dist/features/help/index.mjs +3 -3
  76. package/dist/features/tokenusage/index.js +127 -127
  77. package/dist/features/tokenusage/index.mjs +4 -4
  78. package/dist/index.d.mts +8 -8
  79. package/dist/index.d.ts +8 -8
  80. package/dist/index.js +9 -3
  81. package/dist/index.js.map +1 -1
  82. package/dist/index.mjs +8 -2
  83. package/dist/{notification.interface-BB6GPpZY.d.mts → notification.interface-CF5h90U2.d.mts} +1 -1
  84. package/dist/{notification.interface-CmAGrijJ.d.ts → notification.interface-DQReXAD7.d.ts} +1 -1
  85. package/dist/{s3.service-Bz_K-tjz.d.ts → s3.service-BTCpmp5g.d.ts} +11 -4
  86. package/dist/{s3.service-D5zNCEW3.d.mts → s3.service-CzFBDEuQ.d.mts} +11 -4
  87. package/dist/server/index.d.mts +5 -5
  88. package/dist/server/index.d.ts +5 -5
  89. package/dist/server/index.js +3 -3
  90. package/dist/server/index.mjs +2 -2
  91. package/dist/stripe-price.interface-D6mKjAdr.d.mts +132 -0
  92. package/dist/stripe-price.interface-DGqcklFJ.d.ts +132 -0
  93. package/dist/{useSocket-B0H9pmmH.d.ts → useSocket-BM3q9A0C.d.ts} +1 -1
  94. package/dist/{useSocket-B5RQb6v2.d.mts → useSocket-CwSoq6VS.d.mts} +1 -1
  95. package/dist/{user.interface-CIWGlbqM.d.mts → user.interface-BYnGJ7ss.d.mts} +37 -2
  96. package/dist/{user.interface-C0ZdsBZj.d.ts → user.interface-BqPjVyJI.d.ts} +37 -2
  97. package/messages/en.json +8 -0
  98. package/messages/it.json +8 -0
  99. package/package.json +1 -1
  100. package/src/components/containers/RoundPageContainer.tsx +7 -2
  101. package/src/components/index.ts +5 -0
  102. package/src/features/analytics/components/AnalyticsTracker.tsx +22 -9
  103. package/src/features/analytics/components/__tests__/AnalyticsTracker.spec.tsx +67 -0
  104. package/src/features/analytics/data/__tests__/models.spec.ts +13 -0
  105. package/src/features/analytics/data/analytics-event.ts +1 -0
  106. package/src/features/analytics/data/analytics.types.ts +2 -0
  107. package/src/features/billing/components/containers/BillingDashboardContainer.tsx +20 -3
  108. package/src/features/billing/components/widgets/CreditWarningBanner.tsx +93 -0
  109. package/src/features/billing/data/credit-warning.spec.ts +96 -0
  110. package/src/features/billing/data/credit-warning.ts +57 -0
  111. package/src/features/billing/data/index.ts +3 -0
  112. package/src/features/billing/i18n-keys.ts +6 -0
  113. package/src/features/company/data/company.interface.ts +11 -0
  114. package/src/features/company/data/company.service.ts +17 -0
  115. package/src/features/company/data/company.spec.ts +29 -0
  116. package/src/features/company/data/company.ts +31 -0
  117. package/dist/chunk-IPYXT7MH.js.map +0 -1
  118. package/dist/chunk-T3YQ47EF.js.map +0 -1
  119. package/dist/chunk-U7DR5VDT.mjs.map +0 -1
  120. package/dist/chunk-USYZNWKS.mjs.map +0 -1
  121. package/dist/feature.interface-BO25VLlx.d.ts +0 -19
  122. package/dist/feature.interface-CXb1-vNq.d.mts +0 -19
  123. /package/dist/{BlockNoteEditor-FZNU4YQT.mjs.map → BlockNoteEditor-M6UQRVRK.mjs.map} +0 -0
  124. /package/dist/{BlockNoteViewer-6XDDVTN6.mjs.map → BlockNoteViewer-XZJ5Y7WN.mjs.map} +0 -0
  125. /package/dist/{chunk-GFGKMUPZ.mjs.map → chunk-O2TEUH5S.mjs.map} +0 -0
  126. /package/dist/{chunk-JVJS5RHB.mjs.map → chunk-RUJCWOJE.mjs.map} +0 -0
  127. /package/dist/{chunk-RYZYKG6W.mjs.map → chunk-ZDUT5JPT.mjs.map} +0 -0
@@ -0,0 +1,96 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import type { CompanyInterface } from "../../company/data/company.interface";
3
+ import { SubscriptionStatus } from "../stripe-subscription/data/stripe-subscription.interface";
4
+ import type { StripeSubscriptionInterface } from "../stripe-subscription/data/stripe-subscription.interface";
5
+ import { CREDIT_WARNING_DISMISS_SEGMENT, isCreditWarningActive, resolveChangePlanTarget } from "./credit-warning";
6
+
7
+ const makeCompany = (overrides: Record<string, unknown> = {}): CompanyInterface =>
8
+ ({
9
+ aiEnabled: true,
10
+ isActiveSubscription: true,
11
+ creditsGrantedThisPeriod: 200,
12
+ creditWarningSentAt: new Date("2026-10-25T10:00:00.000Z"),
13
+ creditWarningDismissedAt: undefined,
14
+ availableMonthlyCredits: 30,
15
+ availableExtraCredits: 0,
16
+ ...overrides,
17
+ }) as unknown as CompanyInterface;
18
+
19
+ const makeSubscription = (
20
+ id: string,
21
+ status: SubscriptionStatus,
22
+ priceType: "one_time" | "recurring",
23
+ ): StripeSubscriptionInterface => ({ id, status, price: { priceType } }) as unknown as StripeSubscriptionInterface;
24
+
25
+ describe("isCreditWarningActive (threshold 80)", () => {
26
+ it("is true with 30 of 200 left", () => {
27
+ expect(isCreditWarningActive(makeCompany({ availableMonthlyCredits: 30 }), 80)).toBe(true);
28
+ });
29
+
30
+ it("is true at exactly 80% used (40 of 200 left)", () => {
31
+ expect(isCreditWarningActive(makeCompany({ availableMonthlyCredits: 40 }), 80)).toBe(true);
32
+ });
33
+
34
+ it("is false at 0 credits, which is the out-of-credits banner's job", () => {
35
+ expect(isCreditWarningActive(makeCompany({ availableMonthlyCredits: 0, availableExtraCredits: 0 }), 80)).toBe(
36
+ false,
37
+ );
38
+ expect(isCreditWarningActive(makeCompany({ availableMonthlyCredits: 0, availableExtraCredits: -0.3 }), 80)).toBe(
39
+ false,
40
+ );
41
+ });
42
+
43
+ it("is false when monthly plus extra is above the threshold (50 > 40)", () => {
44
+ expect(isCreditWarningActive(makeCompany({ availableMonthlyCredits: 30, availableExtraCredits: 20 }), 80)).toBe(
45
+ false,
46
+ );
47
+ });
48
+
49
+ it("is false once dismissed", () => {
50
+ expect(isCreditWarningActive(makeCompany({ creditWarningDismissedAt: new Date() }), 80)).toBe(false);
51
+ });
52
+
53
+ it("is false when the warning was never sent", () => {
54
+ expect(isCreditWarningActive(makeCompany({ creditWarningSentAt: undefined }), 80)).toBe(false);
55
+ });
56
+
57
+ it("is false without an active subscription", () => {
58
+ expect(isCreditWarningActive(makeCompany({ isActiveSubscription: false }), 80)).toBe(false);
59
+ });
60
+
61
+ it("is false when AI is off", () => {
62
+ expect(isCreditWarningActive(makeCompany({ aiEnabled: false }), 80)).toBe(false);
63
+ });
64
+
65
+ it("is false when nothing was granted this period", () => {
66
+ expect(isCreditWarningActive(makeCompany({ creditsGrantedThisPeriod: undefined }), 80)).toBe(false);
67
+ });
68
+ });
69
+
70
+ describe("CREDIT_WARNING_DISMISS_SEGMENT", () => {
71
+ it("matches the backend segment", () => {
72
+ expect(CREDIT_WARNING_DISMISS_SEGMENT).toBe("credit-warning/dismiss");
73
+ });
74
+ });
75
+
76
+ describe("resolveChangePlanTarget", () => {
77
+ it("picks the trialing recurring subscription over a one-time one", () => {
78
+ const oneTime = makeSubscription("one-time", SubscriptionStatus.ACTIVE, "one_time");
79
+ const trialing = makeSubscription("trialing", SubscriptionStatus.TRIALING, "recurring");
80
+
81
+ expect(resolveChangePlanTarget([oneTime, trialing])).toBe(trialing);
82
+ });
83
+
84
+ it("returns undefined when the only recurring subscription is canceled", () => {
85
+ const canceled = makeSubscription("canceled", SubscriptionStatus.CANCELED, "recurring");
86
+
87
+ expect(resolveChangePlanTarget([canceled])).toBeUndefined();
88
+ });
89
+
90
+ it("returns the first active recurring subscription in array order", () => {
91
+ const first = makeSubscription("first", SubscriptionStatus.ACTIVE, "recurring");
92
+ const second = makeSubscription("second", SubscriptionStatus.ACTIVE, "recurring");
93
+
94
+ expect(resolveChangePlanTarget([first, second])).toBe(first);
95
+ });
96
+ });
@@ -0,0 +1,57 @@
1
+ // Credit warning: shared contract with the backend and pure helpers.
2
+ // Keep this file free of any `@stripe/*` import: it is re-exported from the
3
+ // Stripe-free `components` entry, because the banner mounts on every page.
4
+
5
+ import type { CompanyInterface } from "../../company/data/company.interface";
6
+ import { SubscriptionStatus } from "../stripe-subscription/data/stripe-subscription.interface";
7
+ import type { StripeSubscriptionInterface } from "../stripe-subscription/data/stripe-subscription.interface";
8
+
9
+ /**
10
+ * The offer the server chose when it sent this period's warning.
11
+ * Mirrors the backend `CreditWarningOffer`.
12
+ */
13
+ export type CreditWarningOffer = "subscribe" | "upgrade-or-pack" | "pack";
14
+
15
+ /**
16
+ * Child segment of the dismiss route: `POST companies/:companyId/credit-warning/dismiss`.
17
+ * Must match the backend `CREDIT_WARNING_DISMISS_SEGMENT`.
18
+ */
19
+ export const CREDIT_WARNING_DISMISS_SEGMENT = "credit-warning/dismiss";
20
+
21
+ /**
22
+ * Whether the in-app credit warning should show for this company.
23
+ *
24
+ * True only when the server sent the warning this period and nobody dismissed it,
25
+ * the company has AI and an active subscription, and the credits left are at or
26
+ * below `100 - thresholdPercent` percent of this period's grant. At 0 credits
27
+ * (or below) it is false: `OutOfCreditsBanner` owns that state.
28
+ */
29
+ export function isCreditWarningActive(company: CompanyInterface, thresholdPercent: number): boolean {
30
+ if (!company.aiEnabled || !company.isActiveSubscription) return false;
31
+ if (!company.creditWarningSentAt || company.creditWarningDismissedAt) return false;
32
+
33
+ const granted = company.creditsGrantedThisPeriod;
34
+ if (granted === undefined || granted <= 0) return false;
35
+
36
+ const monthly = company.availableMonthlyCredits;
37
+ const extra = company.availableExtraCredits;
38
+ // Same "has credits" test as useHasCredits / CompanyService.hasAvailableCredits.
39
+ if (!(monthly > 0 || extra > 0)) return false;
40
+
41
+ return monthly + extra <= (granted * (100 - thresholdPercent)) / 100;
42
+ }
43
+
44
+ /**
45
+ * The subscription the `?action=change-plan` deep link opens the wizard on: the
46
+ * first active or trialing recurring subscription, in the dashboard's own order.
47
+ * `undefined` means there is none, and the subscribe wizard opens instead.
48
+ */
49
+ export function resolveChangePlanTarget(
50
+ subscriptions: StripeSubscriptionInterface[],
51
+ ): StripeSubscriptionInterface | undefined {
52
+ return subscriptions.find(
53
+ (sub) =>
54
+ (sub.status === SubscriptionStatus.ACTIVE || sub.status === SubscriptionStatus.TRIALING) &&
55
+ sub.price?.priceType === "recurring",
56
+ );
57
+ }
@@ -3,3 +3,6 @@ export { BillingService } from "./billing.service";
3
3
 
4
4
  // Data classes
5
5
  export { Billing } from "./Billing";
6
+
7
+ // Credit warning (Stripe-free)
8
+ export * from "./credit-warning";
@@ -397,4 +397,10 @@ export const BILLING_UI_I18N_KEYS = [
397
397
  "billing.ui.wizard.review.use_another_card",
398
398
  "billing.ui.wizard.steps.select_plan",
399
399
  "billing.ui.wizard.subscribe_description",
400
+ "billing.ui.credit_warning.title",
401
+ "billing.ui.credit_warning.body",
402
+ "billing.ui.credit_warning.subscribe",
403
+ "billing.ui.credit_warning.upgrade",
404
+ "billing.ui.credit_warning.add_pack",
405
+ "billing.ui.credit_warning.dismiss",
400
406
  ] as const;
@@ -1,6 +1,7 @@
1
1
  import { ApiDataInterface } from "../../../core";
2
2
  import { FeatureInterface } from "../../feature/data/feature.interface";
3
3
  import { ModuleInterface } from "../../module/data/module.interface";
4
+ import type { CreditWarningOffer } from "../../billing/data/credit-warning";
4
5
 
5
6
  export type CompanyInput = {
6
7
  id: string;
@@ -45,6 +46,16 @@ export interface CompanyInterface extends ApiDataInterface {
45
46
  */
46
47
  get aiEnabled(): boolean;
47
48
 
49
+ /**
50
+ * Credit-warning state, written by the server only (never sent by
51
+ * `createJsonApi()`). All four are absent until the feature is on and the
52
+ * company has received a monthly grant.
53
+ */
54
+ get creditsGrantedThisPeriod(): number | undefined;
55
+ get creditWarningSentAt(): Date | undefined;
56
+ get creditWarningDismissedAt(): Date | undefined;
57
+ get creditWarningOffer(): CreditWarningOffer | undefined;
58
+
48
59
  get features(): FeatureInterface[];
49
60
  get modules(): ModuleInterface[];
50
61
  get legal_address(): string | undefined;
@@ -1,4 +1,5 @@
1
1
  import { AbstractService, EndpointCreator, HttpMethod, Modules, NextRef } from "../../../core";
2
+ import { CREDIT_WARNING_DISMISS_SEGMENT } from "../../billing/data/credit-warning";
2
3
  import { CompanyInput, CompanyInterface } from "./company.interface";
3
4
 
4
5
  export class CompanyService extends AbstractService {
@@ -82,4 +83,20 @@ export class CompanyService extends AbstractService {
82
83
  input: params,
83
84
  });
84
85
  }
86
+
87
+ /**
88
+ * Dismisses this period's credit warning for the company. The request has no
89
+ * body: the server stamps the dismissal itself and answers 204.
90
+ */
91
+ static async dismissCreditWarning(params: { companyId: string }): Promise<void> {
92
+ await this.callApi({
93
+ type: Modules.Company,
94
+ method: HttpMethod.POST,
95
+ endpoint: new EndpointCreator({
96
+ endpoint: Modules.Company,
97
+ id: params.companyId,
98
+ childEndpoint: CREDIT_WARNING_DISMISS_SEGMENT,
99
+ }).generate(),
100
+ });
101
+ }
85
102
  }
@@ -38,3 +38,32 @@ describe("Company.aiEnabled", () => {
38
38
  expect(company.aiEnabled).toBe(true);
39
39
  });
40
40
  });
41
+
42
+ describe("Company credit-warning fields", () => {
43
+ it("rehydrates credit-warning fields", () => {
44
+ const company = new Company().rehydrate({
45
+ jsonApi: {
46
+ attributes: {
47
+ creditsGrantedThisPeriod: 200,
48
+ creditWarningSentAt: "2026-10-25T10:00:00.000Z",
49
+ creditWarningOffer: "pack",
50
+ },
51
+ },
52
+ } as any);
53
+
54
+ expect(company.creditsGrantedThisPeriod).toBe(200);
55
+ expect(company.creditWarningSentAt).toBeInstanceOf(Date);
56
+ expect(company.creditWarningSentAt?.toISOString()).toBe("2026-10-25T10:00:00.000Z");
57
+ expect(company.creditWarningDismissedAt).toBeUndefined();
58
+ expect(company.creditWarningOffer).toBe("pack");
59
+ });
60
+
61
+ it("leaves every credit-warning getter undefined when the attributes are absent", () => {
62
+ const company = new Company().rehydrate({ jsonApi: { attributes: {} } } as any);
63
+
64
+ expect(company.creditsGrantedThisPeriod).toBeUndefined();
65
+ expect(company.creditWarningSentAt).toBeUndefined();
66
+ expect(company.creditWarningDismissedAt).toBeUndefined();
67
+ expect(company.creditWarningOffer).toBeUndefined();
68
+ });
69
+ });
@@ -1,6 +1,7 @@
1
1
  import { AbstractApiData, JsonApiHydratedDataInterface, Modules } from "../../../core";
2
2
  import { FeatureInterface } from "../../feature";
3
3
  import { ModuleInterface } from "../../module";
4
+ import type { CreditWarningOffer } from "../../billing/data/credit-warning";
4
5
  import { CompanyInput, CompanyInterface } from "./company.interface";
5
6
 
6
7
  export class Company extends AbstractApiData implements CompanyInterface {
@@ -16,6 +17,11 @@ export class Company extends AbstractApiData implements CompanyInterface {
16
17
  private _availableExtraCredits: number = 0;
17
18
  private _aiEnabled?: boolean;
18
19
 
20
+ private _creditsGrantedThisPeriod?: number;
21
+ private _creditWarningSentAt?: Date;
22
+ private _creditWarningDismissedAt?: Date;
23
+ private _creditWarningOffer?: CreditWarningOffer;
24
+
19
25
  private _features?: FeatureInterface[];
20
26
  private _modules?: ModuleInterface[];
21
27
 
@@ -63,6 +69,22 @@ export class Company extends AbstractApiData implements CompanyInterface {
63
69
  return this._aiEnabled ?? true;
64
70
  }
65
71
 
72
+ get creditsGrantedThisPeriod(): number | undefined {
73
+ return this._creditsGrantedThisPeriod;
74
+ }
75
+
76
+ get creditWarningSentAt(): Date | undefined {
77
+ return this._creditWarningSentAt;
78
+ }
79
+
80
+ get creditWarningDismissedAt(): Date | undefined {
81
+ return this._creditWarningDismissedAt;
82
+ }
83
+
84
+ get creditWarningOffer(): CreditWarningOffer | undefined {
85
+ return this._creditWarningOffer;
86
+ }
87
+
66
88
  get features(): FeatureInterface[] {
67
89
  return this._features ?? [];
68
90
  }
@@ -130,6 +152,15 @@ export class Company extends AbstractApiData implements CompanyInterface {
130
152
  this._availableExtraCredits = data.jsonApi.attributes.availableExtraCredits ?? 0;
131
153
  this._aiEnabled = data.jsonApi.attributes.aiEnabled ?? true;
132
154
 
155
+ this._creditsGrantedThisPeriod = data.jsonApi.attributes.creditsGrantedThisPeriod ?? undefined;
156
+ this._creditWarningSentAt = data.jsonApi.attributes.creditWarningSentAt
157
+ ? new Date(data.jsonApi.attributes.creditWarningSentAt)
158
+ : undefined;
159
+ this._creditWarningDismissedAt = data.jsonApi.attributes.creditWarningDismissedAt
160
+ ? new Date(data.jsonApi.attributes.creditWarningDismissedAt)
161
+ : undefined;
162
+ this._creditWarningOffer = data.jsonApi.attributes.creditWarningOffer ?? undefined;
163
+
133
164
  this._legal_address = data.jsonApi.attributes.legal_address;
134
165
  this._street_number = data.jsonApi.attributes.street_number;
135
166
  this._street = data.jsonApi.attributes.street;