@metrifox/angular-sdk 0.0.2-beta.1 → 0.0.2-beta.3
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/README.md +310 -320
- package/dist/README.md +310 -320
- package/dist/fesm2022/index.mjs +1568 -1320
- package/dist/lib/metrifox.service.d.ts +5 -5
- package/dist/lib/types/enum.d.ts +4 -2
- package/dist/lib/types/interface.d.ts +5 -0
- package/dist/modules/customer-portal/components/billing-history.component.d.ts +3 -2
- package/dist/modules/customer-portal/components/credit/credit-balance-section.component.d.ts +12 -10
- package/dist/modules/customer-portal/components/customer-portal.component.d.ts +15 -10
- package/dist/modules/customer-portal/components/entitlements/entitlement-summary.component.d.ts +15 -0
- package/dist/modules/customer-portal/components/entitlements/entitlement-usage.component.d.ts +35 -0
- package/dist/modules/customer-portal/components/entitlements/entitlements-section.component.d.ts +5 -21
- package/dist/modules/customer-portal/components/invoice-preview.component.d.ts +8 -7
- package/dist/modules/customer-portal/components/payment.component.d.ts +4 -3
- package/dist/modules/customer-portal/components/plan/plans-section.component.d.ts +28 -26
- package/dist/modules/customer-portal/components/subscription/subscription-details.component.d.ts +12 -0
- package/dist/modules/customer-portal/components/subscription/subscription-items.component.d.ts +27 -0
- package/dist/modules/customer-portal/components/subscription/subscription-section.component.d.ts +5 -25
- package/dist/modules/pricing-table/components/pricing-table.component.d.ts +13 -7
- package/dist/modules/pricing-table/utils/defaults.d.ts +2 -0
- package/dist/public-api.d.ts +10 -10
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/fesm2022/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, Injectable, EventEmitter,
|
|
2
|
+
import { signal, Injectable, EventEmitter, Output, Input, ChangeDetectionStrategy, Component, inject, computed, NgModule } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common/http';
|
|
4
4
|
import { HttpHeaders, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
|
5
5
|
import { BehaviorSubject, throwError, Subject, takeUntil, forkJoin } from 'rxjs';
|
|
@@ -175,6 +175,9 @@ function customerPortalThemeToCssVars(theme) {
|
|
|
175
175
|
// Plan Button
|
|
176
176
|
s(vars, '--pt-button-bg', theme.plans?.planButton?.background);
|
|
177
177
|
s(vars, '--pt-button-text', theme.plans?.planButton?.textColor);
|
|
178
|
+
s(vars, '--pt-button-secondary-bg', theme.plans?.planButton?.secondaryBackground);
|
|
179
|
+
s(vars, '--pt-button-secondary-text', theme.plans?.planButton?.secondaryTextColor);
|
|
180
|
+
s(vars, '--pt-button-link', theme.plans?.planButton?.textButtonColor);
|
|
178
181
|
// Plan Toggle
|
|
179
182
|
s(vars, '--pt-interval-bg', theme.plans?.planToggle?.background);
|
|
180
183
|
s(vars, '--pt-interval-active-bg', theme.plans?.planToggle?.activeBackground);
|
|
@@ -269,8 +272,8 @@ function getGradient(theme) {
|
|
|
269
272
|
const gradientColor = theme.plans?.currentPlanCard?.gradientColor;
|
|
270
273
|
return {
|
|
271
274
|
gradient: {
|
|
272
|
-
100: `linear-gradient(180deg, ${gradientColor} 4.81%, rgba(222, 247, 100, 0) 42.31%)
|
|
273
|
-
}
|
|
275
|
+
100: `linear-gradient(180deg, ${gradientColor} 4.81%, rgba(222, 247, 100, 0) 42.31%)`
|
|
276
|
+
}
|
|
274
277
|
};
|
|
275
278
|
}
|
|
276
279
|
/**
|
|
@@ -326,7 +329,7 @@ class MetrifoxService {
|
|
|
326
329
|
const fullConfig = {
|
|
327
330
|
...config,
|
|
328
331
|
baseUrl: config.baseUrl || DEFAULT_BASE_URL,
|
|
329
|
-
webAppUrl: config.webAppUrl || DEFAULT_WEB_APP_URL
|
|
332
|
+
webAppUrl: config.webAppUrl || DEFAULT_WEB_APP_URL
|
|
330
333
|
};
|
|
331
334
|
MetrifoxService._config.set(fullConfig);
|
|
332
335
|
MetrifoxService._initialized.set(true);
|
|
@@ -397,7 +400,7 @@ class MetrifoxService {
|
|
|
397
400
|
const clientKey = MetrifoxService.getClientKey();
|
|
398
401
|
return new HttpHeaders({
|
|
399
402
|
'x-client-key': clientKey,
|
|
400
|
-
'Content-Type': 'application/json'
|
|
403
|
+
'Content-Type': 'application/json'
|
|
401
404
|
});
|
|
402
405
|
}
|
|
403
406
|
/**
|
|
@@ -442,7 +445,7 @@ class MetrifoxService {
|
|
|
442
445
|
return this.http
|
|
443
446
|
.get(url, {
|
|
444
447
|
headers: this.getHeaders(),
|
|
445
|
-
params: params
|
|
448
|
+
params: params
|
|
446
449
|
})
|
|
447
450
|
.pipe(map((response) => response.data), catchError(this.handleError));
|
|
448
451
|
}
|
|
@@ -537,7 +540,7 @@ class MetrifoxService {
|
|
|
537
540
|
const url = `${MetrifoxService.getBaseUrl()}/sdk/subscriptions/schedule-cancellation`;
|
|
538
541
|
return this.http
|
|
539
542
|
.post(url, { subscription_id: subscriptionId, ...options }, {
|
|
540
|
-
headers: this.getHeaders()
|
|
543
|
+
headers: this.getHeaders()
|
|
541
544
|
})
|
|
542
545
|
.pipe(map((response) => response.data), catchError(this.handleError));
|
|
543
546
|
}
|
|
@@ -612,8 +615,8 @@ class MetrifoxService {
|
|
|
612
615
|
params: {
|
|
613
616
|
offering_key: params.offeringKey,
|
|
614
617
|
...(params.billingInterval && { billing_interval: params.billingInterval }),
|
|
615
|
-
...(params.customerKey && { customer_key: params.customerKey })
|
|
616
|
-
}
|
|
618
|
+
...(params.customerKey && { customer_key: params.customerKey })
|
|
619
|
+
}
|
|
617
620
|
})
|
|
618
621
|
.pipe(map((response) => response.data.checkout_url), catchError(this.handleError));
|
|
619
622
|
}
|
|
@@ -621,7 +624,7 @@ class MetrifoxService {
|
|
|
621
624
|
* Build checkout URL manually
|
|
622
625
|
*/
|
|
623
626
|
buildCheckoutUrl(checkoutUsername, offeringKey, options) {
|
|
624
|
-
|
|
627
|
+
const url = `${MetrifoxService.getWebAppUrl()}/${checkoutUsername}/checkout/${offeringKey}`;
|
|
625
628
|
const params = new URLSearchParams();
|
|
626
629
|
if (options?.billingPeriod) {
|
|
627
630
|
params.set('billing_period', options.billingPeriod);
|
|
@@ -644,7 +647,7 @@ class MetrifoxService {
|
|
|
644
647
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: MetrifoxService, decorators: [{
|
|
645
648
|
type: Injectable,
|
|
646
649
|
args: [{
|
|
647
|
-
providedIn: 'root'
|
|
650
|
+
providedIn: 'root'
|
|
648
651
|
}]
|
|
649
652
|
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
650
653
|
/**
|
|
@@ -656,20 +659,20 @@ function metrifoxInit(config) {
|
|
|
656
659
|
}
|
|
657
660
|
|
|
658
661
|
const ICONS$1 = {
|
|
659
|
-
money:
|
|
660
|
-
cardReceive:
|
|
661
|
-
settings:
|
|
662
|
-
settingsAlt:
|
|
663
|
-
closeCircle:
|
|
664
|
-
walletEmpty:
|
|
665
|
-
noteEmpty:
|
|
666
|
-
receipt:
|
|
667
|
-
radar:
|
|
668
|
-
arrowDown:
|
|
669
|
-
arrowDownRight:
|
|
670
|
-
subtitle:
|
|
671
|
-
subtitleLarge:
|
|
672
|
-
check:
|
|
662
|
+
money: '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M17 21.25H7c-3.65 0-5.75-2.1-5.75-5.75v-7c0-3.65 2.1-5.75 5.75-5.75h10c3.65 0 5.75 2.1 5.75 5.75v7c0 3.65-2.1 5.75-5.75 5.75Zm-10-17c-2.86 0-4.25 1.39-4.25 4.25v7c0 2.86 1.39 4.25 4.25 4.25h10c2.86 0 4.25-1.39 4.25-4.25v-7c0-2.86-1.39-4.25-4.25-4.25H7Z"></path><path d="M12 15.75c-2.07 0-3.75-1.68-3.75-3.75 0-2.07 1.68-3.75 3.75-3.75 2.07 0 3.75 1.68 3.75 3.75 0 2.07-1.68 3.75-3.75 3.75Zm0-6c-1.24 0-2.25 1.01-2.25 2.25s1.01 2.25 2.25 2.25 2.25-1.01 2.25-2.25S13.24 9.75 12 9.75ZM5.5 15.25c-.41 0-.75-.34-.75-.75v-5c0-.41.34-.75.75-.75s.75.34.75.75v5c0 .41-.34.75-.75.75ZM18.5 15.25c-.41 0-.75-.34-.75-.75v-5c0-.41.34-.75.75-.75s.75.34.75.75v5c0 .41-.34.75-.75.75Z"></path></svg>',
|
|
663
|
+
cardReceive: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 8.5H14.5"/><path d="M6 16.5H8"/><path d="M10.5 16.5H14.5"/><path d="M22 12.03V16.11C22 19.62 21.11 20.5 17.56 20.5H6.44C2.89 20.5 2 19.62 2 16.11V7.89C2 4.38 2.89 3.5 6.44 3.5H14.5"/><path d="M20 3.5V9.5L22 7.5"/><path d="M20 9.5L18 7.5"/></svg>',
|
|
664
|
+
settings: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>',
|
|
665
|
+
settingsAlt: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>',
|
|
666
|
+
closeCircle: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.49 2 2 6.49 2 12s4.49 10 10 10 10-4.49 10-10S17.51 2 12 2Zm3.36 12.3c.29.29.29.77 0 1.06-.15.15-.34.22-.53.22s-.38-.07-.53-.22l-2.3-2.3-2.3 2.3c-.15.15-.34.22-.53.22s-.38-.07-.53-.22a.754.754 0 0 1 0-1.06l2.3-2.3-2.3-2.3a.754.754 0 0 1 0-1.06c.29-.29.77-.29 1.06 0l2.3 2.3 2.3-2.3c.29-.29.77-.29 1.06 0 .29.29.29.77 0 1.06l-2.3 2.3 2.3 2.3Z"/></svg>',
|
|
667
|
+
walletEmpty: '<svg xmlns="http://www.w3.org/2000/svg" width="84" height="84" viewBox="0 0 24 24" fill="none" stroke="#9CA3AF" stroke-width="1"><path d="M18.04 13.55c-.42.41-.66 1-.6 1.63.09 1.08 1.08 1.87 2.16 1.87h1.9v1.19c0 2.07-1.69 3.76-3.76 3.76H6.26c-2.07 0-3.76-1.69-3.76-3.76v-6.73c0-2.07 1.69-3.76 3.76-3.76h11.48c2.07 0 3.76 1.69 3.76 3.76v1.44h-2.02c-.56 0-1.07.22-1.44.6Z"/><path d="M2.5 12.41V7.84c0-1.19.73-2.25 1.84-2.67l7.94-3a1.9 1.9 0 0 1 2.57 1.78v3.8"/><path d="M22.56 13.97v2.06c0 .55-.44 1-1 1.02h-1.96c-1.08 0-2.07-.79-2.16-1.87-.06-.63.18-1.22.6-1.63.37-.38.88-.6 1.44-.6h2.08c.56.02 1 .47 1 1.02Z"/><path d="M7 12h7"/></svg>',
|
|
668
|
+
noteEmpty: '<svg xmlns="http://www.w3.org/2000/svg" width="72" height="72" viewBox="0 0 24 24" fill="none" stroke="#E5E5E5" stroke-width="1"><path d="M8 2v3M16 2v3M3.5 9.09h17M21 8.5V17c0 3-1.5 5-5 5H8c-3.5 0-5-2-5-5V8.5c0-3 1.5-5 5-5h8c3.5 0 5 2 5 5Z"/><path d="M15.695 13.7h.009M15.695 16.7h.009M11.995 13.7h.01M11.995 16.7h.01M8.294 13.7h.01M8.294 16.7h.01"/></svg>',
|
|
669
|
+
receipt: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M22 6V8.42C22 10 21 11 19.42 11H16V4.01C16 2.9 16.91 2 18.02 2C19.11 2.01 20.11 2.45 20.83 3.17C21.55 3.9 22 4.9 22 6Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M2 7V21C2 21.83 2.94 22.3 3.6 21.8L5.31 20.52C5.71 20.22 6.27 20.26 6.63 20.62L8.29 22.29C8.68 22.68 9.32 22.68 9.71 22.29L11.39 20.61C11.74 20.26 12.3 20.22 12.69 20.52L14.4 21.8C15.06 22.29 16 21.82 16 21V4C16 2.9 16.9 2 18 2H7H6C3 2 2 3.79 2 6V7Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M9 13.01H12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M9 9.01H12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M5.99609 13H6.00508" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M5.99609 9H6.00508" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
|
|
670
|
+
radar: '<svg width="16" height="16" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3.99967 3.33333C5.11301 2.5 6.49967 2 7.99967 2C11.6797 2 14.6663 4.98667 14.6663 8.66667C14.6663 12.3467 11.6797 15.3333 7.99967 15.3333C4.31967 15.3333 1.33301 12.3467 1.33301 8.66667C1.33301 7.46 1.653 6.32666 2.21967 5.34666L7.99967 8.66667" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
|
|
671
|
+
arrowDown: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"></path></svg>',
|
|
672
|
+
arrowDownRight: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M7 7l10 10M17 7v10H7"/></svg>',
|
|
673
|
+
subtitle: '<svg width="18" height="18" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M9.99967 15.1663H5.99967C2.37967 15.1663 0.833008 13.6197 0.833008 9.99967V5.99967C0.833008 2.37967 2.37967 0.833008 5.99967 0.833008H9.99967C13.6197 0.833008 15.1663 2.37967 15.1663 5.99967V9.99967C15.1663 13.6197 13.6197 15.1663 9.99967 15.1663ZM5.99967 1.83301C2.92634 1.83301 1.83301 2.92634 1.83301 5.99967V9.99967C1.83301 13.073 2.92634 14.1663 5.99967 14.1663H9.99967C13.073 14.1663 14.1663 13.073 14.1663 9.99967V5.99967C14.1663 2.92634 13.073 1.83301 9.99967 1.83301H5.99967Z"/><path d="M11.6669 11.8867H10.4336C10.1603 11.8867 9.93359 11.6601 9.93359 11.3867C9.93359 11.1134 10.1603 10.8867 10.4336 10.8867H11.6669C11.9403 10.8867 12.1669 11.1134 12.1669 11.3867C12.1669 11.6601 11.9403 11.8867 11.6669 11.8867Z"/><path d="M8.64634 11.8867H4.33301C4.05967 11.8867 3.83301 11.6601 3.83301 11.3867C3.83301 11.1134 4.05967 10.8867 4.33301 10.8867H8.64634C8.91967 10.8867 9.14634 11.1134 9.14634 11.3867C9.14634 11.6601 8.92634 11.8867 8.64634 11.8867Z"/><path d="M11.6671 9.37988H7.98047C7.70714 9.37988 7.48047 9.15322 7.48047 8.87988C7.48047 8.60655 7.70714 8.37988 7.98047 8.37988H11.6671C11.9405 8.37988 12.1671 8.60655 12.1671 8.87988C12.1671 9.15322 11.9405 9.37988 11.6671 9.37988Z"/><path d="M6.17967 9.37988H4.33301C4.05967 9.37988 3.83301 9.15322 3.83301 8.87988C3.83301 8.60655 4.05967 8.37988 4.33301 8.37988H6.17967C6.45301 8.37988 6.67967 8.60655 6.67967 8.87988C6.67967 9.15322 6.45301 9.37988 6.17967 9.37988Z"/></svg>',
|
|
674
|
+
subtitleLarge: '<svg width="40" height="40" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M9.99967 15.1663H5.99967C2.37967 15.1663 0.833008 13.6197 0.833008 9.99967V5.99967C0.833008 2.37967 2.37967 0.833008 5.99967 0.833008H9.99967C13.6197 0.833008 15.1663 2.37967 15.1663 5.99967V9.99967C15.1663 13.6197 13.6197 15.1663 9.99967 15.1663ZM5.99967 1.83301C2.92634 1.83301 1.83301 2.92634 1.83301 5.99967V9.99967C1.83301 13.073 2.92634 14.1663 5.99967 14.1663H9.99967C13.073 14.1663 14.1663 13.073 14.1663 9.99967V5.99967C14.1663 2.92634 13.073 1.83301 9.99967 1.83301H5.99967Z"/><path d="M11.6669 11.8867H10.4336C10.1603 11.8867 9.93359 11.6601 9.93359 11.3867C9.93359 11.1134 10.1603 10.8867 10.4336 10.8867H11.6669C11.9403 10.8867 12.1669 11.1134 12.1669 11.3867C12.1669 11.6601 11.9403 11.8867 11.6669 11.8867Z"/><path d="M8.64634 11.8867H4.33301C4.05967 11.8867 3.83301 11.6601 3.83301 11.3867C3.83301 11.1134 4.05967 10.8867 4.33301 10.8867H8.64634C8.91967 10.8867 9.14634 11.1134 9.14634 11.3867C9.14634 11.6601 8.92634 11.8867 8.64634 11.8867Z"/><path d="M11.6671 9.37988H7.98047C7.70714 9.37988 7.48047 9.15322 7.48047 8.87988C7.48047 8.60655 7.70714 8.37988 7.98047 8.37988H11.6671C11.9405 8.37988 12.1671 8.60655 12.1671 8.87988C12.1671 9.15322 11.9405 9.37988 11.6671 9.37988Z"/><path d="M6.17967 9.37988H4.33301C4.05967 9.37988 3.83301 9.15322 3.83301 8.87988C3.83301 8.60655 4.05967 8.37988 4.33301 8.37988H6.17967C6.45301 8.37988 6.67967 8.60655 6.67967 8.87988C6.67967 9.15322 6.45301 9.37988 6.17967 9.37988Z"/></svg>',
|
|
675
|
+
check: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>'
|
|
673
676
|
};
|
|
674
677
|
|
|
675
678
|
const iconCache = new Map();
|
|
@@ -688,30 +691,30 @@ const defaultCustomerPortalTheme = {
|
|
|
688
691
|
backgroundColor: '#ffffff',
|
|
689
692
|
borderRadius: '16px',
|
|
690
693
|
fontFamily: 'inherit',
|
|
691
|
-
containerPadding: '24px'
|
|
694
|
+
containerPadding: '24px'
|
|
692
695
|
},
|
|
693
696
|
tabs: {
|
|
694
697
|
tabBackground: '#ffffff',
|
|
695
698
|
tabBorderColor: '#E4E4E7',
|
|
696
699
|
activeTabBackground: '#3D3D3D',
|
|
697
700
|
activeTabTextColor: '#ffffff',
|
|
698
|
-
inactiveTabTextColor: '#71717A'
|
|
701
|
+
inactiveTabTextColor: '#71717A'
|
|
699
702
|
},
|
|
700
703
|
sections: {
|
|
701
704
|
background: '#ffffff',
|
|
702
|
-
padding: '
|
|
705
|
+
padding: '16px',
|
|
703
706
|
borderColor: 'transparent',
|
|
704
707
|
borderRadius: '8px',
|
|
705
708
|
emptyTextColor: '#A1A1AA',
|
|
706
709
|
usage: {
|
|
707
710
|
barColor: '#006FEE',
|
|
708
|
-
trackColor: '#E4E4E7'
|
|
711
|
+
trackColor: '#E4E4E7'
|
|
709
712
|
},
|
|
710
713
|
content: {
|
|
711
714
|
background: '#F4F4F5',
|
|
712
715
|
padding: '24px',
|
|
713
716
|
borderColor: '#E4E4E7',
|
|
714
|
-
borderRadius: '8px'
|
|
717
|
+
borderRadius: '8px'
|
|
715
718
|
},
|
|
716
719
|
summaryBalance: {
|
|
717
720
|
background: '#ffffff',
|
|
@@ -720,23 +723,23 @@ const defaultCustomerPortalTheme = {
|
|
|
720
723
|
borderRadius: '8px',
|
|
721
724
|
label: { fontSize: '13px', fontWeight: '500', color: '#71717A' },
|
|
722
725
|
value: { fontSize: '20px', fontWeight: '700', color: '#52525B' },
|
|
723
|
-
unit: { fontSize: '13px', fontWeight: '500', color: '#52525B' }
|
|
726
|
+
unit: { fontSize: '13px', fontWeight: '500', color: '#52525B' }
|
|
724
727
|
},
|
|
725
728
|
header: { fontSize: '16px', fontWeight: '600', color: '#52525B' },
|
|
726
729
|
label: { fontSize: '13px', fontWeight: '500', color: '#71717A' },
|
|
727
|
-
value: { fontSize: '
|
|
730
|
+
value: { fontSize: '14px', fontWeight: '500', color: '#52525B' }
|
|
728
731
|
},
|
|
729
732
|
buttons: {
|
|
730
733
|
primary: {
|
|
731
734
|
backgroundColor: '#3D3D3D',
|
|
732
735
|
border: { color: '#52525B', width: '1px', radius: '8px' },
|
|
733
|
-
typography: { fontSize: '14px', fontWeight: '500', color: '#ffffff' }
|
|
736
|
+
typography: { fontSize: '14px', fontWeight: '500', color: '#ffffff' }
|
|
734
737
|
},
|
|
735
738
|
secondary: {
|
|
736
739
|
backgroundColor: '#E4E4E7',
|
|
737
740
|
border: { color: '#E4E4E7', width: '1px', radius: '8px' },
|
|
738
|
-
typography: { fontSize: '13px', fontWeight: '500', color: '#3F3F46' }
|
|
739
|
-
}
|
|
741
|
+
typography: { fontSize: '13px', fontWeight: '500', color: '#3F3F46' }
|
|
742
|
+
}
|
|
740
743
|
},
|
|
741
744
|
lineItems: {
|
|
742
745
|
parentRow: {
|
|
@@ -744,17 +747,17 @@ const defaultCustomerPortalTheme = {
|
|
|
744
747
|
borderColor: '#E4E4E7',
|
|
745
748
|
typography: {
|
|
746
749
|
label: { color: '#111827' },
|
|
747
|
-
quantity: { color: '#71717A' }
|
|
748
|
-
}
|
|
750
|
+
quantity: { color: '#71717A' }
|
|
751
|
+
}
|
|
749
752
|
},
|
|
750
753
|
childRow: {
|
|
751
754
|
background: '#ffffff',
|
|
752
755
|
borderColor: '#E4E4E7',
|
|
753
756
|
typography: {
|
|
754
757
|
label: { color: '#111827' },
|
|
755
|
-
quantity: { color: '#71717A' }
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
+
quantity: { color: '#71717A' }
|
|
759
|
+
}
|
|
760
|
+
}
|
|
758
761
|
},
|
|
759
762
|
tables: {
|
|
760
763
|
headerBackground: '#E4E4E7',
|
|
@@ -766,11 +769,11 @@ const defaultCustomerPortalTheme = {
|
|
|
766
769
|
cellPadding: '1rem 0.75rem',
|
|
767
770
|
expandIconColor: '#71717A',
|
|
768
771
|
typography: {
|
|
769
|
-
fontSize: '
|
|
770
|
-
fontWeight: '
|
|
771
|
-
headerFontSize: '
|
|
772
|
-
headerFontWeight: '
|
|
773
|
-
}
|
|
772
|
+
fontSize: '14px',
|
|
773
|
+
fontWeight: '400',
|
|
774
|
+
headerFontSize: '14px',
|
|
775
|
+
headerFontWeight: '500'
|
|
776
|
+
}
|
|
774
777
|
},
|
|
775
778
|
modals: {
|
|
776
779
|
overlayColor: 'rgba(0, 0, 0, 0.4)',
|
|
@@ -787,14 +790,14 @@ const defaultCustomerPortalTheme = {
|
|
|
787
790
|
backgroundColor: 'transparent',
|
|
788
791
|
textColor: '#3F3F46',
|
|
789
792
|
borderColor: '#E4E4E7',
|
|
790
|
-
borderWidth: '1px'
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
+
borderWidth: '1px'
|
|
794
|
+
}
|
|
795
|
+
}
|
|
793
796
|
},
|
|
794
797
|
plans: {
|
|
795
798
|
currentPlanCard: {
|
|
796
799
|
header: { background: '#E4E4E7', textColor: '#111827' },
|
|
797
|
-
gradientColor: '#E4E4E7'
|
|
800
|
+
gradientColor: '#E4E4E7'
|
|
798
801
|
},
|
|
799
802
|
planCards: {
|
|
800
803
|
background: '#ffffff',
|
|
@@ -806,19 +809,25 @@ const defaultCustomerPortalTheme = {
|
|
|
806
809
|
primaryTextColor: '#71717A',
|
|
807
810
|
secondaryTextColor: '#A1A1AA',
|
|
808
811
|
background: 'transparent',
|
|
809
|
-
borderColor: 'transparent'
|
|
810
|
-
}
|
|
812
|
+
borderColor: 'transparent'
|
|
813
|
+
}
|
|
811
814
|
},
|
|
812
815
|
planFeatures: { textColor: '#3F3F46', iconColor: '#0BB02F' },
|
|
813
|
-
planButton: {
|
|
816
|
+
planButton: {
|
|
817
|
+
background: '#3D3D3D',
|
|
818
|
+
textColor: '#ffffff',
|
|
819
|
+
secondaryBackground: '#E4E4E7',
|
|
820
|
+
secondaryTextColor: '#3F3F46',
|
|
821
|
+
textButtonColor: '#2563eb'
|
|
822
|
+
},
|
|
814
823
|
planToggle: {
|
|
815
824
|
background: '#E4E4E7',
|
|
816
825
|
activeBackground: '#1f2937',
|
|
817
826
|
activeText: '#ffffff',
|
|
818
|
-
inactiveText: '#71717A'
|
|
827
|
+
inactiveText: '#71717A'
|
|
819
828
|
},
|
|
820
|
-
planTags: { freeTrialBackground: '#dbeafe', freeTrialText: '#1e40af' }
|
|
821
|
-
}
|
|
829
|
+
planTags: { freeTrialBackground: '#dbeafe', freeTrialText: '#1e40af' }
|
|
830
|
+
}
|
|
822
831
|
};
|
|
823
832
|
|
|
824
833
|
function formatDate(dateString) {
|
|
@@ -874,7 +883,7 @@ function formatPriceAmount(amount) {
|
|
|
874
883
|
function getResetIntervalLabel(interval) {
|
|
875
884
|
const map = {
|
|
876
885
|
daily: 'per day', weekly: 'per week', monthly: 'per month',
|
|
877
|
-
quarterly: 'per quarter', yearly: 'per year', biannually: 'per 6 months'
|
|
886
|
+
quarterly: 'per quarter', yearly: 'per year', biannually: 'per 6 months'
|
|
878
887
|
};
|
|
879
888
|
return map[interval?.toLowerCase()] || interval;
|
|
880
889
|
}
|
|
@@ -911,22 +920,342 @@ const DEFAULT_SECTION_LABELS = {
|
|
|
911
920
|
entitlementUsage: 'Entitlements',
|
|
912
921
|
paymentOverview: 'Payment',
|
|
913
922
|
billingHistory: 'Billing history',
|
|
914
|
-
plan: 'Plans'
|
|
923
|
+
plan: 'Plans'
|
|
915
924
|
};
|
|
916
925
|
function getSectionLabel(sectionsConfig, key) {
|
|
917
926
|
const config = sectionsConfig?.find((s) => s.key === key);
|
|
918
927
|
return config?.label || DEFAULT_SECTION_LABELS[key] || key;
|
|
919
928
|
}
|
|
920
929
|
|
|
921
|
-
class
|
|
922
|
-
|
|
923
|
-
sectionsConfig;
|
|
924
|
-
customerKey = '';
|
|
925
|
-
tenantCheckoutUsername = '';
|
|
930
|
+
class SubscriptionDetailsComponent {
|
|
931
|
+
sub;
|
|
926
932
|
invoicePreview = new EventEmitter();
|
|
927
|
-
|
|
933
|
+
_formatDate(d) {
|
|
934
|
+
return formatDate(d);
|
|
935
|
+
}
|
|
936
|
+
_formatCurrency(amount, currency) {
|
|
937
|
+
return formatCurrency(amount, currency);
|
|
938
|
+
}
|
|
939
|
+
_formatStatus(status) {
|
|
940
|
+
return formatStatus(status);
|
|
941
|
+
}
|
|
942
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: SubscriptionDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
943
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: SubscriptionDetailsComponent, isStandalone: true, selector: "cp-subscription-details", inputs: { sub: "sub" }, outputs: { invoicePreview: "invoicePreview" }, ngImport: i0, template: `
|
|
944
|
+
<!-- Plan details content box -->
|
|
945
|
+
<div data-testid="subscription-content-box"
|
|
946
|
+
class="bg-[var(--cp-section-content-bg,#F4F4F5)] border border-[var(--cp-section-content-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)]"
|
|
947
|
+
[style.padding]="'var(--cp-section-content-padding)'">
|
|
948
|
+
<div class="flex justify-between flex-wrap gap-6">
|
|
949
|
+
<div>
|
|
950
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
951
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
952
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Current plan</span>
|
|
953
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
954
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
955
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
956
|
+
{{ sub.plan_name || '-' }}
|
|
957
|
+
</div>
|
|
958
|
+
</div>
|
|
959
|
+
<div>
|
|
960
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
961
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
962
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Status</span>
|
|
963
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
964
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
965
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
966
|
+
{{ _formatStatus(sub.status) }}
|
|
967
|
+
</div>
|
|
968
|
+
</div>
|
|
969
|
+
<div>
|
|
970
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
971
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
972
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Start date</span>
|
|
973
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
974
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
975
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
976
|
+
{{ _formatDate(sub.starts_at) || '-' }}
|
|
977
|
+
</div>
|
|
978
|
+
</div>
|
|
979
|
+
@if (sub.status === 'active') {
|
|
980
|
+
<div>
|
|
981
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
982
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
983
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Current billing period</span>
|
|
984
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
985
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
986
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
987
|
+
@if (sub.current_billing_period_start && sub.current_billing_period_end) {
|
|
988
|
+
<div class="font-medium">{{ _formatDate(sub.current_billing_period_start) }} - {{ _formatDate(sub.current_billing_period_end) }}</div>
|
|
989
|
+
<div class="mt-1 text-sm opacity-80">(Auto-renew)</div>
|
|
990
|
+
} @else {
|
|
991
|
+
<span>-</span>
|
|
992
|
+
}
|
|
993
|
+
</div>
|
|
994
|
+
</div>
|
|
995
|
+
}
|
|
996
|
+
@if (sub.status === 'trialing' && sub.trial_end_date) {
|
|
997
|
+
<div>
|
|
998
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
999
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1000
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Trial end date</span>
|
|
1001
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1002
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1003
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1004
|
+
{{ _formatDate(sub.trial_end_date) }}
|
|
1005
|
+
</div>
|
|
1006
|
+
</div>
|
|
1007
|
+
<div>
|
|
1008
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1009
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1010
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Trial period</span>
|
|
1011
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1012
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1013
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1014
|
+
{{ _formatDate(sub.starts_at) }} - {{ _formatDate(sub.trial_end_date) }}
|
|
1015
|
+
</div>
|
|
1016
|
+
</div>
|
|
1017
|
+
}
|
|
1018
|
+
@if (sub.status === 'active') {
|
|
1019
|
+
<div>
|
|
1020
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1021
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1022
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">End date</span>
|
|
1023
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1024
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1025
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1026
|
+
{{ sub.ends_at ? _formatDate(sub.ends_at) : '-' }}
|
|
1027
|
+
</div>
|
|
1028
|
+
</div>
|
|
1029
|
+
}
|
|
1030
|
+
</div>
|
|
1031
|
+
</div>
|
|
1032
|
+
|
|
1033
|
+
<!-- Preview invoice link -->
|
|
1034
|
+
@if (sub.upcoming_invoice) {
|
|
1035
|
+
<div class="flex justify-end mt-2">
|
|
1036
|
+
<button type="button"
|
|
1037
|
+
class="text-[var(--cp-link-color,#3b82f6)] underline p-0 text-sm bg-transparent border-none cursor-pointer"
|
|
1038
|
+
(click)="$event.stopPropagation(); invoicePreview.emit(sub.upcoming_invoice!)">
|
|
1039
|
+
Preview invoice
|
|
1040
|
+
</button>
|
|
1041
|
+
</div>
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
<!-- Billing details content box (active only) -->
|
|
1045
|
+
@if (sub.status === 'active') {
|
|
1046
|
+
<div data-testid="subscription-content-box"
|
|
1047
|
+
class="bg-[var(--cp-section-content-bg,#F4F4F5)] border border-[var(--cp-section-content-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] mt-2"
|
|
1048
|
+
[style.padding]="'var(--cp-section-content-padding)'">
|
|
1049
|
+
<div class="flex justify-between flex-wrap gap-6">
|
|
1050
|
+
<div>
|
|
1051
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1052
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1053
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Next billing date</span>
|
|
1054
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1055
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1056
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1057
|
+
{{ sub.renews_at ? _formatDate(sub.renews_at) : '-' }}
|
|
1058
|
+
</div>
|
|
1059
|
+
</div>
|
|
1060
|
+
<div>
|
|
1061
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1062
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1063
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Invoice due</span>
|
|
1064
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1065
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1066
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1067
|
+
{{ sub.renews_at ? _formatDate(sub.renews_at) : '-' }}
|
|
1068
|
+
</div>
|
|
1069
|
+
</div>
|
|
1070
|
+
<div>
|
|
1071
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1072
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1073
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Next estimated bill</span>
|
|
1074
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1075
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1076
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1077
|
+
@if (sub.next_billing_amount) {
|
|
1078
|
+
<div class="font-medium">{{ _formatCurrency(sub.next_billing_amount, sub.currency_code) }}</div>
|
|
1079
|
+
<div class="text-sm opacity-80 mt-0.5">(Monthly)</div>
|
|
1080
|
+
} @else {
|
|
1081
|
+
<span>-</span>
|
|
1082
|
+
}
|
|
1083
|
+
</div>
|
|
1084
|
+
</div>
|
|
1085
|
+
</div>
|
|
1086
|
+
</div>
|
|
1087
|
+
}
|
|
1088
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1089
|
+
}
|
|
1090
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: SubscriptionDetailsComponent, decorators: [{
|
|
1091
|
+
type: Component,
|
|
1092
|
+
args: [{
|
|
1093
|
+
selector: 'cp-subscription-details',
|
|
1094
|
+
standalone: true,
|
|
1095
|
+
imports: [CommonModule],
|
|
1096
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1097
|
+
template: `
|
|
1098
|
+
<!-- Plan details content box -->
|
|
1099
|
+
<div data-testid="subscription-content-box"
|
|
1100
|
+
class="bg-[var(--cp-section-content-bg,#F4F4F5)] border border-[var(--cp-section-content-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)]"
|
|
1101
|
+
[style.padding]="'var(--cp-section-content-padding)'">
|
|
1102
|
+
<div class="flex justify-between flex-wrap gap-6">
|
|
1103
|
+
<div>
|
|
1104
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1105
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1106
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Current plan</span>
|
|
1107
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1108
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1109
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1110
|
+
{{ sub.plan_name || '-' }}
|
|
1111
|
+
</div>
|
|
1112
|
+
</div>
|
|
1113
|
+
<div>
|
|
1114
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1115
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1116
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Status</span>
|
|
1117
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1118
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1119
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1120
|
+
{{ _formatStatus(sub.status) }}
|
|
1121
|
+
</div>
|
|
1122
|
+
</div>
|
|
1123
|
+
<div>
|
|
1124
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1125
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1126
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Start date</span>
|
|
1127
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1128
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1129
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1130
|
+
{{ _formatDate(sub.starts_at) || '-' }}
|
|
1131
|
+
</div>
|
|
1132
|
+
</div>
|
|
1133
|
+
@if (sub.status === 'active') {
|
|
1134
|
+
<div>
|
|
1135
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1136
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1137
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Current billing period</span>
|
|
1138
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1139
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1140
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1141
|
+
@if (sub.current_billing_period_start && sub.current_billing_period_end) {
|
|
1142
|
+
<div class="font-medium">{{ _formatDate(sub.current_billing_period_start) }} - {{ _formatDate(sub.current_billing_period_end) }}</div>
|
|
1143
|
+
<div class="mt-1 text-sm opacity-80">(Auto-renew)</div>
|
|
1144
|
+
} @else {
|
|
1145
|
+
<span>-</span>
|
|
1146
|
+
}
|
|
1147
|
+
</div>
|
|
1148
|
+
</div>
|
|
1149
|
+
}
|
|
1150
|
+
@if (sub.status === 'trialing' && sub.trial_end_date) {
|
|
1151
|
+
<div>
|
|
1152
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1153
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1154
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Trial end date</span>
|
|
1155
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1156
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1157
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1158
|
+
{{ _formatDate(sub.trial_end_date) }}
|
|
1159
|
+
</div>
|
|
1160
|
+
</div>
|
|
1161
|
+
<div>
|
|
1162
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1163
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1164
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Trial period</span>
|
|
1165
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1166
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1167
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1168
|
+
{{ _formatDate(sub.starts_at) }} - {{ _formatDate(sub.trial_end_date) }}
|
|
1169
|
+
</div>
|
|
1170
|
+
</div>
|
|
1171
|
+
}
|
|
1172
|
+
@if (sub.status === 'active') {
|
|
1173
|
+
<div>
|
|
1174
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1175
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1176
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">End date</span>
|
|
1177
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1178
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1179
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1180
|
+
{{ sub.ends_at ? _formatDate(sub.ends_at) : '-' }}
|
|
1181
|
+
</div>
|
|
1182
|
+
</div>
|
|
1183
|
+
}
|
|
1184
|
+
</div>
|
|
1185
|
+
</div>
|
|
1186
|
+
|
|
1187
|
+
<!-- Preview invoice link -->
|
|
1188
|
+
@if (sub.upcoming_invoice) {
|
|
1189
|
+
<div class="flex justify-end mt-2">
|
|
1190
|
+
<button type="button"
|
|
1191
|
+
class="text-[var(--cp-link-color,#3b82f6)] underline p-0 text-sm bg-transparent border-none cursor-pointer"
|
|
1192
|
+
(click)="$event.stopPropagation(); invoicePreview.emit(sub.upcoming_invoice!)">
|
|
1193
|
+
Preview invoice
|
|
1194
|
+
</button>
|
|
1195
|
+
</div>
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
<!-- Billing details content box (active only) -->
|
|
1199
|
+
@if (sub.status === 'active') {
|
|
1200
|
+
<div data-testid="subscription-content-box"
|
|
1201
|
+
class="bg-[var(--cp-section-content-bg,#F4F4F5)] border border-[var(--cp-section-content-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] mt-2"
|
|
1202
|
+
[style.padding]="'var(--cp-section-content-padding)'">
|
|
1203
|
+
<div class="flex justify-between flex-wrap gap-6">
|
|
1204
|
+
<div>
|
|
1205
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1206
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1207
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Next billing date</span>
|
|
1208
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1209
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1210
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1211
|
+
{{ sub.renews_at ? _formatDate(sub.renews_at) : '-' }}
|
|
1212
|
+
</div>
|
|
1213
|
+
</div>
|
|
1214
|
+
<div>
|
|
1215
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1216
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1217
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Invoice due</span>
|
|
1218
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1219
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1220
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1221
|
+
{{ sub.renews_at ? _formatDate(sub.renews_at) : '-' }}
|
|
1222
|
+
</div>
|
|
1223
|
+
</div>
|
|
1224
|
+
<div>
|
|
1225
|
+
<span class="text-[var(--cp-section-label-color)]"
|
|
1226
|
+
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1227
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Next estimated bill</span>
|
|
1228
|
+
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1229
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1230
|
+
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1231
|
+
@if (sub.next_billing_amount) {
|
|
1232
|
+
<div class="font-medium">{{ _formatCurrency(sub.next_billing_amount, sub.currency_code) }}</div>
|
|
1233
|
+
<div class="text-sm opacity-80 mt-0.5">(Monthly)</div>
|
|
1234
|
+
} @else {
|
|
1235
|
+
<span>-</span>
|
|
1236
|
+
}
|
|
1237
|
+
</div>
|
|
1238
|
+
</div>
|
|
1239
|
+
</div>
|
|
1240
|
+
</div>
|
|
1241
|
+
}
|
|
1242
|
+
`
|
|
1243
|
+
}]
|
|
1244
|
+
}], propDecorators: { sub: [{
|
|
1245
|
+
type: Input,
|
|
1246
|
+
args: [{ required: true }]
|
|
1247
|
+
}], invoicePreview: [{
|
|
1248
|
+
type: Output
|
|
1249
|
+
}] } });
|
|
1250
|
+
|
|
1251
|
+
class SubscriptionItemsComponent {
|
|
928
1252
|
expandedAddons = new Set();
|
|
929
|
-
|
|
1253
|
+
items = [];
|
|
1254
|
+
canUpdateQuantities = false;
|
|
1255
|
+
tenantCheckoutUsername = '';
|
|
1256
|
+
customerKey = '';
|
|
1257
|
+
subscriptionId = '';
|
|
1258
|
+
offeringKey = '';
|
|
930
1259
|
toggleAddon(key) {
|
|
931
1260
|
if (this.expandedAddons.has(key)) {
|
|
932
1261
|
this.expandedAddons.delete(key);
|
|
@@ -938,32 +1267,27 @@ class SubscriptionSectionComponent {
|
|
|
938
1267
|
isAddonExpanded(key) {
|
|
939
1268
|
return this.expandedAddons.has(key);
|
|
940
1269
|
}
|
|
941
|
-
openUpdateItems(
|
|
942
|
-
if (!this.tenantCheckoutUsername || !
|
|
1270
|
+
openUpdateItems() {
|
|
1271
|
+
if (!this.tenantCheckoutUsername || !this.subscriptionId || !this.offeringKey)
|
|
943
1272
|
return;
|
|
944
|
-
const updateQtyUrl = `${window.location.origin}/${this.tenantCheckoutUsername}/${
|
|
1273
|
+
const updateQtyUrl = `${window.location.origin}/${this.tenantCheckoutUsername}/${this.offeringKey}/subscriptions/${this.subscriptionId}?customer=${this.customerKey}`;
|
|
945
1274
|
window.open(updateQtyUrl, '_blank', 'noopener,noreferrer');
|
|
946
1275
|
}
|
|
947
|
-
handleManagePlan() {
|
|
948
|
-
this.managePlan.emit(this.subscription);
|
|
949
|
-
}
|
|
950
1276
|
handleAddAddon() {
|
|
951
|
-
|
|
952
|
-
const subscriptionId = this.subscription?.subscription?.id;
|
|
953
|
-
if (!this.tenantCheckoutUsername || !offeringKey || !subscriptionId)
|
|
1277
|
+
if (!this.tenantCheckoutUsername || !this.offeringKey || !this.subscriptionId)
|
|
954
1278
|
return;
|
|
955
1279
|
const webAppUrl = 'https://app.metrifox.com';
|
|
956
|
-
const url = `${webAppUrl}/${this.tenantCheckoutUsername}/${offeringKey}/addons?subscription=${subscriptionId}&manage=addon_add`;
|
|
1280
|
+
const url = `${webAppUrl}/${this.tenantCheckoutUsername}/${this.offeringKey}/addons?subscription=${this.subscriptionId}&manage=addon_add`;
|
|
957
1281
|
window.open(url, '_blank', 'noopener,noreferrer');
|
|
958
1282
|
}
|
|
959
|
-
getPlanLineItems(
|
|
960
|
-
return (items || []).filter((item) => !item.is_addon);
|
|
1283
|
+
getPlanLineItems() {
|
|
1284
|
+
return (this.items || []).filter((item) => !item.is_addon);
|
|
961
1285
|
}
|
|
962
|
-
getAddonLineItems(
|
|
963
|
-
return (items || []).filter((item) => item.is_addon);
|
|
1286
|
+
getAddonLineItems() {
|
|
1287
|
+
return (this.items || []).filter((item) => item.is_addon);
|
|
964
1288
|
}
|
|
965
|
-
getGroupedAddonItems(
|
|
966
|
-
const addonItems = this.getAddonLineItems(
|
|
1289
|
+
getGroupedAddonItems() {
|
|
1290
|
+
const addonItems = this.getAddonLineItems();
|
|
967
1291
|
const groups = new Map();
|
|
968
1292
|
for (const item of addonItems) {
|
|
969
1293
|
const key = item.offering_key || item.name || item.price_option_id;
|
|
@@ -977,666 +1301,427 @@ class SubscriptionSectionComponent {
|
|
|
977
1301
|
return { key, name: baseItem?.name || key, baseItem, children };
|
|
978
1302
|
});
|
|
979
1303
|
}
|
|
980
|
-
getStatusBgClass(status) {
|
|
981
|
-
switch (status?.toLowerCase()) {
|
|
982
|
-
case 'active': return 'bg-green-500';
|
|
983
|
-
case 'trialing': return 'bg-blue-500';
|
|
984
|
-
case 'canceled':
|
|
985
|
-
case 'canceling': return 'bg-red-500';
|
|
986
|
-
case 'past_due':
|
|
987
|
-
case 'unpaid': return 'bg-yellow-500';
|
|
988
|
-
case 'paused': return 'bg-gray-500';
|
|
989
|
-
default: return 'bg-gray-500';
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
_formatDate(d) {
|
|
993
|
-
return formatDate(d);
|
|
994
|
-
}
|
|
995
|
-
_formatCurrency(amount, currency) {
|
|
996
|
-
return formatCurrency(amount, currency);
|
|
997
|
-
}
|
|
998
|
-
_formatStatus(status) {
|
|
999
|
-
return formatStatus(status);
|
|
1000
|
-
}
|
|
1001
1304
|
_capitalize(str) {
|
|
1002
1305
|
return capitalize(str || '');
|
|
1003
1306
|
}
|
|
1004
|
-
|
|
1005
|
-
return
|
|
1006
|
-
}
|
|
1007
|
-
_getSectionLabel(key) {
|
|
1008
|
-
return getSectionLabel(this.sectionsConfig, key);
|
|
1009
|
-
}
|
|
1010
|
-
_getIcon(name) {
|
|
1011
|
-
return getIcon(this.sanitizer, name);
|
|
1307
|
+
_formatCurrency(amount, currency) {
|
|
1308
|
+
return formatCurrency(amount, currency);
|
|
1012
1309
|
}
|
|
1013
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type:
|
|
1014
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type:
|
|
1015
|
-
@if (
|
|
1016
|
-
<div class="
|
|
1017
|
-
|
|
1018
|
-
[style.backgroundColor]="'var(--cp-section-bg)'"
|
|
1019
|
-
[style.borderColor]="'var(--cp-section-border)'"
|
|
1020
|
-
[style.borderRadius]="'var(--cp-section-radius)'"
|
|
1021
|
-
[style.borderWidth]="'1px'"
|
|
1022
|
-
[style.borderStyle]="'solid'">
|
|
1023
|
-
<!-- Header: title + Manage plan -->
|
|
1024
|
-
<div class="flex justify-between items-center mb-4">
|
|
1310
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: SubscriptionItemsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1311
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: SubscriptionItemsComponent, isStandalone: true, selector: "cp-subscription-items", inputs: { items: "items", canUpdateQuantities: "canUpdateQuantities", tenantCheckoutUsername: "tenantCheckoutUsername", customerKey: "customerKey", subscriptionId: "subscriptionId", offeringKey: "offeringKey" }, ngImport: i0, template: `
|
|
1312
|
+
@if (items?.length) {
|
|
1313
|
+
<div class="mt-8">
|
|
1314
|
+
<div class="flex items-center justify-between mb-4">
|
|
1025
1315
|
<span class="text-[var(--cp-section-header-color)]"
|
|
1026
1316
|
[style.fontSize]="'var(--cp-section-header-size)'"
|
|
1027
1317
|
[style.fontWeight]="'var(--cp-section-header-weight)'">
|
|
1028
|
-
|
|
1318
|
+
Subscription items
|
|
1029
1319
|
</span>
|
|
1030
|
-
@if (
|
|
1320
|
+
@if (canUpdateQuantities) {
|
|
1031
1321
|
<button type="button"
|
|
1032
|
-
class="
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
[style.borderWidth]="'var(--cp-btn-primary-border-width, 1px)'"
|
|
1036
|
-
[style.borderStyle]="'solid'"
|
|
1037
|
-
(click)="handleManagePlan()">
|
|
1038
|
-
Manage plan
|
|
1322
|
+
class="text-[var(--cp-link-color,#3b82f6)] underline p-0 font-medium bg-transparent border-none cursor-pointer"
|
|
1323
|
+
(click)="$event.stopPropagation(); openUpdateItems()">
|
|
1324
|
+
Manage item quantities
|
|
1039
1325
|
</button>
|
|
1040
1326
|
}
|
|
1041
1327
|
</div>
|
|
1042
1328
|
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
class="bg-[var(--cp-section-content-bg,#F4F4F5)] border border-[var(--cp-section-content-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)]"
|
|
1329
|
+
<div data-testid="subscription-items-container"
|
|
1330
|
+
class="rounded-[var(--cp-section-content-radius)] overflow-hidden bg-[var(--cp-section-content-bg,#F4F4F5)] border border-[var(--cp-section-content-border,#e4e4e7)]"
|
|
1046
1331
|
[style.padding]="'var(--cp-section-content-padding)'">
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Current plan</span>
|
|
1052
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1053
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1054
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1055
|
-
{{ subscription.subscription.plan_name || '-' }}
|
|
1056
|
-
</div>
|
|
1057
|
-
</div>
|
|
1058
|
-
<div>
|
|
1059
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1060
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1061
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Status</span>
|
|
1062
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1063
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1064
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1065
|
-
{{ _formatStatus(subscription.subscription.status) }}
|
|
1066
|
-
</div>
|
|
1067
|
-
</div>
|
|
1068
|
-
<div>
|
|
1332
|
+
|
|
1333
|
+
<!-- Plan items -->
|
|
1334
|
+
@if (getPlanLineItems().length > 0) {
|
|
1335
|
+
<div class="mb-3 mt-4">
|
|
1069
1336
|
<span class="text-[var(--cp-section-label-color)]"
|
|
1070
1337
|
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1071
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">
|
|
1072
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1073
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1074
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1075
|
-
{{ _formatDate(subscription.subscription.starts_at) || '-' }}
|
|
1076
|
-
</div>
|
|
1338
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Plan</span>
|
|
1077
1339
|
</div>
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
<
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Trial end date</span>
|
|
1100
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1101
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1102
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1103
|
-
{{ _formatDate(subscription.subscription.trial_end_date) }}
|
|
1104
|
-
</div>
|
|
1105
|
-
</div>
|
|
1106
|
-
<div>
|
|
1107
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1108
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1109
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Trial period</span>
|
|
1110
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1111
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1112
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1113
|
-
{{ _formatDate(subscription.subscription.starts_at) }} - {{ _formatDate(subscription.subscription.trial_end_date) }}
|
|
1114
|
-
</div>
|
|
1115
|
-
</div>
|
|
1116
|
-
}
|
|
1117
|
-
@if (subscription.subscription.status === 'active') {
|
|
1118
|
-
<div>
|
|
1119
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1120
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1121
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">End date</span>
|
|
1122
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1123
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1124
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1125
|
-
{{ subscription.subscription.ends_at ? _formatDate(subscription.subscription.ends_at) : '-' }}
|
|
1340
|
+
<div class="space-y-2">
|
|
1341
|
+
@for (item of getPlanLineItems(); track item.price_option_id) {
|
|
1342
|
+
<div class="bg-[var(--cp-subscription-item-bg,white)] border border-[var(--cp-subscription-item-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] px-4 py-3 flex items-center justify-between">
|
|
1343
|
+
<div class="flex items-center gap-2">
|
|
1344
|
+
<span class="text-[var(--cp-subscription-item-text)]"
|
|
1345
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1346
|
+
[style.fontWeight]="'var(--cp-section-value-weight, 600)'">
|
|
1347
|
+
{{ _capitalize(item.name) }}
|
|
1348
|
+
</span>
|
|
1349
|
+
@if (item.quantity > 0 && item.source_type !== 'plan') {
|
|
1350
|
+
<span class="text-[var(--cp-subscription-item-quantity,#6b7280)] opacity-75">•</span>
|
|
1351
|
+
<span class="text-[var(--cp-subscription-item-quantity,#6b7280)] font-normal text-sm">
|
|
1352
|
+
{{ item.quantity }} {{ item.name?.toLowerCase() }}
|
|
1353
|
+
</span>
|
|
1354
|
+
}
|
|
1355
|
+
</div>
|
|
1356
|
+
<span class="text-[var(--cp-subscription-item-text)]"
|
|
1357
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1358
|
+
[style.fontWeight]="'var(--cp-section-value-weight, 500)'">
|
|
1359
|
+
{{ _formatCurrency(item.total_amount || item.unit_price, item.currency_code) }}
|
|
1360
|
+
</span>
|
|
1126
1361
|
</div>
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
</div>
|
|
1131
|
-
|
|
1132
|
-
<!-- Preview invoice link -->
|
|
1133
|
-
@if (subscription.subscription.upcoming_invoice) {
|
|
1134
|
-
<div class="flex justify-end mt-2">
|
|
1135
|
-
<button type="button"
|
|
1136
|
-
class="text-[var(--cp-link-color,#3b82f6)] underline p-0 text-sm bg-transparent border-none cursor-pointer"
|
|
1137
|
-
(click)="$event.stopPropagation(); invoicePreview.emit(subscription.subscription.upcoming_invoice)">
|
|
1138
|
-
Preview invoice
|
|
1139
|
-
</button>
|
|
1140
|
-
</div>
|
|
1141
|
-
}
|
|
1362
|
+
}
|
|
1363
|
+
</div>
|
|
1364
|
+
}
|
|
1142
1365
|
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
[style.padding]="'var(--cp-section-content-padding)'">
|
|
1148
|
-
<div class="flex justify-between flex-wrap gap-6">
|
|
1149
|
-
<div>
|
|
1150
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1151
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1152
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Next billing date</span>
|
|
1153
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1154
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1155
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1156
|
-
{{ subscription.subscription.renews_at ? _formatDate(subscription.subscription.renews_at) : '-' }}
|
|
1157
|
-
</div>
|
|
1158
|
-
</div>
|
|
1159
|
-
<div>
|
|
1160
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1161
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1162
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Invoice due</span>
|
|
1163
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1164
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1165
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1166
|
-
{{ subscription.subscription.renews_at ? _formatDate(subscription.subscription.renews_at) : '-' }}
|
|
1167
|
-
</div>
|
|
1168
|
-
</div>
|
|
1169
|
-
<div>
|
|
1366
|
+
<!-- Add-on items -->
|
|
1367
|
+
@if (getAddonLineItems().length > 0) {
|
|
1368
|
+
<div class="mt-4">
|
|
1369
|
+
<div class="relative z-[100] flex items-center justify-between mb-3 mt-4">
|
|
1170
1370
|
<span class="text-[var(--cp-section-label-color)]"
|
|
1171
1371
|
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1172
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">
|
|
1173
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1174
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1175
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1176
|
-
@if (subscription.subscription.next_billing_amount) {
|
|
1177
|
-
<div class="font-medium">{{ _formatCurrency(subscription.subscription.next_billing_amount, subscription.subscription.currency_code) }}</div>
|
|
1178
|
-
<div class="text-sm opacity-80 mt-0.5">(Monthly)</div>
|
|
1179
|
-
} @else {
|
|
1180
|
-
<span>-</span>
|
|
1181
|
-
}
|
|
1182
|
-
</div>
|
|
1183
|
-
</div>
|
|
1184
|
-
</div>
|
|
1185
|
-
</div>
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
|
-
<!-- Subscription Line Items -->
|
|
1189
|
-
@if (subscription.subscription.subscription_items?.length) {
|
|
1190
|
-
<div class="mt-8">
|
|
1191
|
-
<div class="flex items-center justify-between mb-4">
|
|
1192
|
-
<span class="text-[var(--cp-section-header-color)]"
|
|
1193
|
-
[style.fontSize]="'var(--cp-section-header-size)'"
|
|
1194
|
-
[style.fontWeight]="'var(--cp-section-header-weight)'">
|
|
1195
|
-
Subscription items
|
|
1196
|
-
</span>
|
|
1197
|
-
@if (subscription.subscription.can_update_quantities) {
|
|
1372
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Add-ons</span>
|
|
1198
1373
|
<button type="button"
|
|
1199
|
-
class="
|
|
1200
|
-
|
|
1201
|
-
|
|
1374
|
+
class="bg-[var(--cp-btn-secondary-bg)] text-[var(--cp-btn-secondary-text)] border-[var(--cp-btn-secondary-border)] rounded-[var(--cp-btn-secondary-radius)] px-5 py-2"
|
|
1375
|
+
[style.fontSize]="'var(--cp-btn-secondary-size)'"
|
|
1376
|
+
[style.fontWeight]="'var(--cp-btn-secondary-weight)'"
|
|
1377
|
+
[style.borderWidth]="'var(--cp-btn-secondary-border-width, 1px)'"
|
|
1378
|
+
[style.borderStyle]="'solid'"
|
|
1379
|
+
(click)="handleAddAddon()">
|
|
1380
|
+
Manage add-on
|
|
1202
1381
|
</button>
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
<!-- Plan items -->
|
|
1211
|
-
@if (getPlanLineItems(subscription.subscription.subscription_items).length > 0) {
|
|
1212
|
-
<div class="mb-3 mt-4">
|
|
1213
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1214
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1215
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Plan</span>
|
|
1216
|
-
</div>
|
|
1217
|
-
<div class="space-y-2">
|
|
1218
|
-
@for (item of getPlanLineItems(subscription.subscription.subscription_items); track item.price_option_id) {
|
|
1219
|
-
<div class="bg-[var(--cp-subscription-item-bg,white)] border border-[var(--cp-subscription-item-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] px-4 py-3 flex items-center justify-between">
|
|
1220
|
-
<div class="flex items-center gap-2">
|
|
1221
|
-
<span class="text-[var(--cp-subscription-item-text)]"
|
|
1222
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1223
|
-
[style.fontWeight]="'var(--cp-section-value-weight, 600)'">
|
|
1224
|
-
{{ _capitalize(item.name) }}
|
|
1225
|
-
</span>
|
|
1226
|
-
@if (item.quantity > 0 && item.source_type !== 'plan') {
|
|
1227
|
-
<span class="text-[var(--cp-subscription-item-quantity,#6b7280)] opacity-75">•</span>
|
|
1228
|
-
<span class="text-[var(--cp-subscription-item-quantity,#6b7280)] font-normal text-sm">
|
|
1229
|
-
{{ item.quantity }} {{ item.name?.toLowerCase() }}
|
|
1230
|
-
</span>
|
|
1231
|
-
}
|
|
1232
|
-
</div>
|
|
1382
|
+
</div>
|
|
1383
|
+
<div class="space-y-2">
|
|
1384
|
+
@for (group of getGroupedAddonItems(); track group.key) {
|
|
1385
|
+
<div class="bg-[var(--cp-subscription-item-bg,white)] border border-[var(--cp-subscription-item-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] px-4 py-3">
|
|
1386
|
+
<div class="flex justify-between items-center gap-2 w-full"
|
|
1387
|
+
[class.cursor-pointer]="group.children.length > 0"
|
|
1388
|
+
(click)="group.children.length > 0 && toggleAddon(group.key)">
|
|
1233
1389
|
<span class="text-[var(--cp-subscription-item-text)]"
|
|
1234
1390
|
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1235
|
-
[style.fontWeight]="'var(--cp-section-value-weight,
|
|
1236
|
-
{{
|
|
1391
|
+
[style.fontWeight]="'var(--cp-section-value-weight, 600)'">
|
|
1392
|
+
{{ _capitalize(group.name) }}
|
|
1237
1393
|
</span>
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
</div>
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
<!-- Add-on items -->
|
|
1244
|
-
@if (getAddonLineItems(subscription.subscription.subscription_items).length > 0) {
|
|
1245
|
-
<div class="mt-4">
|
|
1246
|
-
<div class="relative z-[100] flex items-center justify-between mb-3 mt-4">
|
|
1247
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1248
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1249
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Add-ons</span>
|
|
1250
|
-
<button type="button"
|
|
1251
|
-
class="bg-[var(--cp-btn-secondary-bg)] text-[var(--cp-btn-secondary-text)] border-[var(--cp-btn-secondary-border)] rounded-[var(--cp-btn-secondary-radius)] px-5 py-2"
|
|
1252
|
-
[style.fontSize]="'var(--cp-btn-secondary-size)'"
|
|
1253
|
-
[style.fontWeight]="'var(--cp-btn-secondary-weight)'"
|
|
1254
|
-
[style.borderWidth]="'var(--cp-btn-secondary-border-width, 1px)'"
|
|
1255
|
-
[style.borderStyle]="'solid'"
|
|
1256
|
-
(click)="handleAddAddon()">
|
|
1257
|
-
Manage add-on
|
|
1258
|
-
</button>
|
|
1259
|
-
</div>
|
|
1260
|
-
<div class="space-y-2">
|
|
1261
|
-
@for (group of getGroupedAddonItems(subscription.subscription.subscription_items); track group.key) {
|
|
1262
|
-
<div class="bg-[var(--cp-subscription-item-bg,white)] border border-[var(--cp-subscription-item-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] px-4 py-3">
|
|
1263
|
-
<div class="flex justify-between items-center gap-2 w-full"
|
|
1264
|
-
[class.cursor-pointer]="group.children.length > 0"
|
|
1265
|
-
(click)="group.children.length > 0 && toggleAddon(group.key)">
|
|
1394
|
+
<div class="flex justify-end items-center">
|
|
1395
|
+
@if (group.baseItem) {
|
|
1266
1396
|
<span class="text-[var(--cp-subscription-item-text)]"
|
|
1267
1397
|
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1268
|
-
[style.fontWeight]="'var(--cp-section-value-weight,
|
|
1269
|
-
{{
|
|
1398
|
+
[style.fontWeight]="'var(--cp-section-value-weight, 500)'">
|
|
1399
|
+
{{ _formatCurrency(group.baseItem.total_amount || group.baseItem.unit_price, group.baseItem.currency_code) }}
|
|
1270
1400
|
</span>
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1401
|
+
}
|
|
1402
|
+
@if (group.children.length > 0) {
|
|
1403
|
+
<span class="ml-2 inline-flex transition-transform duration-200"
|
|
1404
|
+
[class.rotate-180]="isAddonExpanded(group.key)"
|
|
1405
|
+
[style.color]="'var(--cp-table-expand-icon-color, #71717a)'">
|
|
1406
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"></path></svg>
|
|
1407
|
+
</span>
|
|
1408
|
+
}
|
|
1409
|
+
</div>
|
|
1410
|
+
</div>
|
|
1411
|
+
@if (isAddonExpanded(group.key) && group.children.length > 0) {
|
|
1412
|
+
<div class="bg-[var(--cp-section-content-bg,#F4F4F5)] space-y-2 p-4 mt-3 rounded-[var(--cp-section-content-radius)]">
|
|
1413
|
+
@for (child of group.children; track child.price_option_id || child.id) {
|
|
1414
|
+
<div class="bg-[var(--cp-subscription-child-bg,white)] border border-[var(--cp-subscription-child-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] px-4 py-3 flex items-center justify-between">
|
|
1415
|
+
<div class="flex items-center gap-2">
|
|
1416
|
+
<span class="text-[var(--cp-subscription-child-text)]"
|
|
1274
1417
|
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1275
|
-
[style.fontWeight]="'var(--cp-section-value-weight,
|
|
1276
|
-
{{
|
|
1418
|
+
[style.fontWeight]="'var(--cp-section-value-weight, 600)'">
|
|
1419
|
+
{{ _capitalize(child.name) }}
|
|
1277
1420
|
</span>
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
[innerHTML]="_getIcon('arrowDown')"></span>
|
|
1283
|
-
}
|
|
1284
|
-
</div>
|
|
1285
|
-
</div>
|
|
1286
|
-
@if (isAddonExpanded(group.key) && group.children.length > 0) {
|
|
1287
|
-
<div class="bg-[var(--cp-section-content-bg,#F4F4F5)] space-y-2 p-4 mt-3 rounded-[var(--cp-section-content-radius)]">
|
|
1288
|
-
@for (child of group.children; track child.price_option_id || child.id) {
|
|
1289
|
-
<div class="bg-[var(--cp-subscription-child-bg,white)] border border-[var(--cp-subscription-child-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] px-4 py-3 flex items-center justify-between">
|
|
1290
|
-
<div class="flex items-center gap-2">
|
|
1291
|
-
<span class="text-[var(--cp-subscription-child-text)]"
|
|
1292
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1293
|
-
[style.fontWeight]="'var(--cp-section-value-weight, 600)'">
|
|
1294
|
-
{{ _capitalize(child.name) }}
|
|
1295
|
-
</span>
|
|
1296
|
-
@if (child.quantity > 0) {
|
|
1297
|
-
<span class="text-[var(--cp-subscription-child-quantity,#6b7280)] opacity-75">•</span>
|
|
1298
|
-
<span class="text-[var(--cp-subscription-child-quantity,#6b7280)] font-normal text-sm">
|
|
1299
|
-
{{ child.quantity }} {{ child.name?.toLowerCase() }}
|
|
1300
|
-
</span>
|
|
1301
|
-
}
|
|
1302
|
-
</div>
|
|
1303
|
-
<span class="text-[var(--cp-subscription-child-text)]"
|
|
1304
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1305
|
-
[style.fontWeight]="'var(--cp-section-value-weight, 500)'">
|
|
1306
|
-
{{ _formatCurrency(child.total_amount || child.unit_price, child.currency_code) }}
|
|
1421
|
+
@if (child.quantity > 0) {
|
|
1422
|
+
<span class="text-[var(--cp-subscription-child-quantity,#6b7280)] opacity-75">•</span>
|
|
1423
|
+
<span class="text-[var(--cp-subscription-child-quantity,#6b7280)] font-normal text-sm">
|
|
1424
|
+
{{ child.quantity }} {{ child.name?.toLowerCase() }}
|
|
1307
1425
|
</span>
|
|
1308
|
-
|
|
1309
|
-
|
|
1426
|
+
}
|
|
1427
|
+
</div>
|
|
1428
|
+
<span class="text-[var(--cp-subscription-child-text)]"
|
|
1429
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1430
|
+
[style.fontWeight]="'var(--cp-section-value-weight, 500)'">
|
|
1431
|
+
{{ _formatCurrency(child.total_amount || child.unit_price, child.currency_code) }}
|
|
1432
|
+
</span>
|
|
1310
1433
|
</div>
|
|
1311
1434
|
}
|
|
1312
1435
|
</div>
|
|
1313
1436
|
}
|
|
1314
1437
|
</div>
|
|
1315
|
-
|
|
1316
|
-
|
|
1438
|
+
}
|
|
1439
|
+
</div>
|
|
1317
1440
|
</div>
|
|
1318
|
-
|
|
1319
|
-
|
|
1441
|
+
}
|
|
1442
|
+
</div>
|
|
1320
1443
|
</div>
|
|
1321
1444
|
}
|
|
1322
1445
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1323
1446
|
}
|
|
1324
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type:
|
|
1447
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: SubscriptionItemsComponent, decorators: [{
|
|
1325
1448
|
type: Component,
|
|
1326
1449
|
args: [{
|
|
1327
|
-
selector: 'cp-subscription-
|
|
1450
|
+
selector: 'cp-subscription-items',
|
|
1328
1451
|
standalone: true,
|
|
1329
1452
|
imports: [CommonModule],
|
|
1330
1453
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1331
1454
|
template: `
|
|
1332
|
-
@if (
|
|
1333
|
-
<div class="
|
|
1334
|
-
|
|
1335
|
-
[style.backgroundColor]="'var(--cp-section-bg)'"
|
|
1336
|
-
[style.borderColor]="'var(--cp-section-border)'"
|
|
1337
|
-
[style.borderRadius]="'var(--cp-section-radius)'"
|
|
1338
|
-
[style.borderWidth]="'1px'"
|
|
1339
|
-
[style.borderStyle]="'solid'">
|
|
1340
|
-
<!-- Header: title + Manage plan -->
|
|
1341
|
-
<div class="flex justify-between items-center mb-4">
|
|
1455
|
+
@if (items?.length) {
|
|
1456
|
+
<div class="mt-8">
|
|
1457
|
+
<div class="flex items-center justify-between mb-4">
|
|
1342
1458
|
<span class="text-[var(--cp-section-header-color)]"
|
|
1343
1459
|
[style.fontSize]="'var(--cp-section-header-size)'"
|
|
1344
1460
|
[style.fontWeight]="'var(--cp-section-header-weight)'">
|
|
1345
|
-
|
|
1461
|
+
Subscription items
|
|
1346
1462
|
</span>
|
|
1347
|
-
@if (
|
|
1463
|
+
@if (canUpdateQuantities) {
|
|
1348
1464
|
<button type="button"
|
|
1349
|
-
class="
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
[style.borderWidth]="'var(--cp-btn-primary-border-width, 1px)'"
|
|
1353
|
-
[style.borderStyle]="'solid'"
|
|
1354
|
-
(click)="handleManagePlan()">
|
|
1355
|
-
Manage plan
|
|
1465
|
+
class="text-[var(--cp-link-color,#3b82f6)] underline p-0 font-medium bg-transparent border-none cursor-pointer"
|
|
1466
|
+
(click)="$event.stopPropagation(); openUpdateItems()">
|
|
1467
|
+
Manage item quantities
|
|
1356
1468
|
</button>
|
|
1357
1469
|
}
|
|
1358
1470
|
</div>
|
|
1359
1471
|
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
class="bg-[var(--cp-section-content-bg,#F4F4F5)] border border-[var(--cp-section-content-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)]"
|
|
1472
|
+
<div data-testid="subscription-items-container"
|
|
1473
|
+
class="rounded-[var(--cp-section-content-radius)] overflow-hidden bg-[var(--cp-section-content-bg,#F4F4F5)] border border-[var(--cp-section-content-border,#e4e4e7)]"
|
|
1363
1474
|
[style.padding]="'var(--cp-section-content-padding)'">
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Current plan</span>
|
|
1369
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1370
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1371
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1372
|
-
{{ subscription.subscription.plan_name || '-' }}
|
|
1373
|
-
</div>
|
|
1374
|
-
</div>
|
|
1375
|
-
<div>
|
|
1376
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1377
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1378
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Status</span>
|
|
1379
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1380
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1381
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1382
|
-
{{ _formatStatus(subscription.subscription.status) }}
|
|
1383
|
-
</div>
|
|
1384
|
-
</div>
|
|
1385
|
-
<div>
|
|
1475
|
+
|
|
1476
|
+
<!-- Plan items -->
|
|
1477
|
+
@if (getPlanLineItems().length > 0) {
|
|
1478
|
+
<div class="mb-3 mt-4">
|
|
1386
1479
|
<span class="text-[var(--cp-section-label-color)]"
|
|
1387
1480
|
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1388
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">
|
|
1389
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1390
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1391
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1392
|
-
{{ _formatDate(subscription.subscription.starts_at) || '-' }}
|
|
1393
|
-
</div>
|
|
1481
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Plan</span>
|
|
1394
1482
|
</div>
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
<
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Trial end date</span>
|
|
1417
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1418
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1419
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1420
|
-
{{ _formatDate(subscription.subscription.trial_end_date) }}
|
|
1421
|
-
</div>
|
|
1422
|
-
</div>
|
|
1423
|
-
<div>
|
|
1424
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1425
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1426
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Trial period</span>
|
|
1427
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1428
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1429
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1430
|
-
{{ _formatDate(subscription.subscription.starts_at) }} - {{ _formatDate(subscription.subscription.trial_end_date) }}
|
|
1431
|
-
</div>
|
|
1432
|
-
</div>
|
|
1433
|
-
}
|
|
1434
|
-
@if (subscription.subscription.status === 'active') {
|
|
1435
|
-
<div>
|
|
1436
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1437
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1438
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">End date</span>
|
|
1439
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1440
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1441
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1442
|
-
{{ subscription.subscription.ends_at ? _formatDate(subscription.subscription.ends_at) : '-' }}
|
|
1483
|
+
<div class="space-y-2">
|
|
1484
|
+
@for (item of getPlanLineItems(); track item.price_option_id) {
|
|
1485
|
+
<div class="bg-[var(--cp-subscription-item-bg,white)] border border-[var(--cp-subscription-item-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] px-4 py-3 flex items-center justify-between">
|
|
1486
|
+
<div class="flex items-center gap-2">
|
|
1487
|
+
<span class="text-[var(--cp-subscription-item-text)]"
|
|
1488
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1489
|
+
[style.fontWeight]="'var(--cp-section-value-weight, 600)'">
|
|
1490
|
+
{{ _capitalize(item.name) }}
|
|
1491
|
+
</span>
|
|
1492
|
+
@if (item.quantity > 0 && item.source_type !== 'plan') {
|
|
1493
|
+
<span class="text-[var(--cp-subscription-item-quantity,#6b7280)] opacity-75">•</span>
|
|
1494
|
+
<span class="text-[var(--cp-subscription-item-quantity,#6b7280)] font-normal text-sm">
|
|
1495
|
+
{{ item.quantity }} {{ item.name?.toLowerCase() }}
|
|
1496
|
+
</span>
|
|
1497
|
+
}
|
|
1498
|
+
</div>
|
|
1499
|
+
<span class="text-[var(--cp-subscription-item-text)]"
|
|
1500
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1501
|
+
[style.fontWeight]="'var(--cp-section-value-weight, 500)'">
|
|
1502
|
+
{{ _formatCurrency(item.total_amount || item.unit_price, item.currency_code) }}
|
|
1503
|
+
</span>
|
|
1443
1504
|
</div>
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
</div>
|
|
1448
|
-
|
|
1449
|
-
<!-- Preview invoice link -->
|
|
1450
|
-
@if (subscription.subscription.upcoming_invoice) {
|
|
1451
|
-
<div class="flex justify-end mt-2">
|
|
1452
|
-
<button type="button"
|
|
1453
|
-
class="text-[var(--cp-link-color,#3b82f6)] underline p-0 text-sm bg-transparent border-none cursor-pointer"
|
|
1454
|
-
(click)="$event.stopPropagation(); invoicePreview.emit(subscription.subscription.upcoming_invoice)">
|
|
1455
|
-
Preview invoice
|
|
1456
|
-
</button>
|
|
1457
|
-
</div>
|
|
1458
|
-
}
|
|
1505
|
+
}
|
|
1506
|
+
</div>
|
|
1507
|
+
}
|
|
1459
1508
|
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
[style.padding]="'var(--cp-section-content-padding)'">
|
|
1465
|
-
<div class="flex justify-between flex-wrap gap-6">
|
|
1466
|
-
<div>
|
|
1467
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1468
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1469
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Next billing date</span>
|
|
1470
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1471
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1472
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1473
|
-
{{ subscription.subscription.renews_at ? _formatDate(subscription.subscription.renews_at) : '-' }}
|
|
1474
|
-
</div>
|
|
1475
|
-
</div>
|
|
1476
|
-
<div>
|
|
1477
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1478
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1479
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Invoice due</span>
|
|
1480
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1481
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1482
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1483
|
-
{{ subscription.subscription.renews_at ? _formatDate(subscription.subscription.renews_at) : '-' }}
|
|
1484
|
-
</div>
|
|
1485
|
-
</div>
|
|
1486
|
-
<div>
|
|
1509
|
+
<!-- Add-on items -->
|
|
1510
|
+
@if (getAddonLineItems().length > 0) {
|
|
1511
|
+
<div class="mt-4">
|
|
1512
|
+
<div class="relative z-[100] flex items-center justify-between mb-3 mt-4">
|
|
1487
1513
|
<span class="text-[var(--cp-section-label-color)]"
|
|
1488
1514
|
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1489
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">
|
|
1490
|
-
<div class="text-[var(--cp-section-value-color)] mt-2"
|
|
1491
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1492
|
-
[style.fontWeight]="'var(--cp-section-value-weight)'">
|
|
1493
|
-
@if (subscription.subscription.next_billing_amount) {
|
|
1494
|
-
<div class="font-medium">{{ _formatCurrency(subscription.subscription.next_billing_amount, subscription.subscription.currency_code) }}</div>
|
|
1495
|
-
<div class="text-sm opacity-80 mt-0.5">(Monthly)</div>
|
|
1496
|
-
} @else {
|
|
1497
|
-
<span>-</span>
|
|
1498
|
-
}
|
|
1499
|
-
</div>
|
|
1500
|
-
</div>
|
|
1501
|
-
</div>
|
|
1502
|
-
</div>
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
|
-
<!-- Subscription Line Items -->
|
|
1506
|
-
@if (subscription.subscription.subscription_items?.length) {
|
|
1507
|
-
<div class="mt-8">
|
|
1508
|
-
<div class="flex items-center justify-between mb-4">
|
|
1509
|
-
<span class="text-[var(--cp-section-header-color)]"
|
|
1510
|
-
[style.fontSize]="'var(--cp-section-header-size)'"
|
|
1511
|
-
[style.fontWeight]="'var(--cp-section-header-weight)'">
|
|
1512
|
-
Subscription items
|
|
1513
|
-
</span>
|
|
1514
|
-
@if (subscription.subscription.can_update_quantities) {
|
|
1515
|
+
[style.fontWeight]="'var(--cp-section-label-weight)'">Add-ons</span>
|
|
1515
1516
|
<button type="button"
|
|
1516
|
-
class="
|
|
1517
|
-
|
|
1518
|
-
|
|
1517
|
+
class="bg-[var(--cp-btn-secondary-bg)] text-[var(--cp-btn-secondary-text)] border-[var(--cp-btn-secondary-border)] rounded-[var(--cp-btn-secondary-radius)] px-5 py-2"
|
|
1518
|
+
[style.fontSize]="'var(--cp-btn-secondary-size)'"
|
|
1519
|
+
[style.fontWeight]="'var(--cp-btn-secondary-weight)'"
|
|
1520
|
+
[style.borderWidth]="'var(--cp-btn-secondary-border-width, 1px)'"
|
|
1521
|
+
[style.borderStyle]="'solid'"
|
|
1522
|
+
(click)="handleAddAddon()">
|
|
1523
|
+
Manage add-on
|
|
1519
1524
|
</button>
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
<!-- Plan items -->
|
|
1528
|
-
@if (getPlanLineItems(subscription.subscription.subscription_items).length > 0) {
|
|
1529
|
-
<div class="mb-3 mt-4">
|
|
1530
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1531
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1532
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Plan</span>
|
|
1533
|
-
</div>
|
|
1534
|
-
<div class="space-y-2">
|
|
1535
|
-
@for (item of getPlanLineItems(subscription.subscription.subscription_items); track item.price_option_id) {
|
|
1536
|
-
<div class="bg-[var(--cp-subscription-item-bg,white)] border border-[var(--cp-subscription-item-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] px-4 py-3 flex items-center justify-between">
|
|
1537
|
-
<div class="flex items-center gap-2">
|
|
1538
|
-
<span class="text-[var(--cp-subscription-item-text)]"
|
|
1539
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1540
|
-
[style.fontWeight]="'var(--cp-section-value-weight, 600)'">
|
|
1541
|
-
{{ _capitalize(item.name) }}
|
|
1542
|
-
</span>
|
|
1543
|
-
@if (item.quantity > 0 && item.source_type !== 'plan') {
|
|
1544
|
-
<span class="text-[var(--cp-subscription-item-quantity,#6b7280)] opacity-75">•</span>
|
|
1545
|
-
<span class="text-[var(--cp-subscription-item-quantity,#6b7280)] font-normal text-sm">
|
|
1546
|
-
{{ item.quantity }} {{ item.name?.toLowerCase() }}
|
|
1547
|
-
</span>
|
|
1548
|
-
}
|
|
1549
|
-
</div>
|
|
1525
|
+
</div>
|
|
1526
|
+
<div class="space-y-2">
|
|
1527
|
+
@for (group of getGroupedAddonItems(); track group.key) {
|
|
1528
|
+
<div class="bg-[var(--cp-subscription-item-bg,white)] border border-[var(--cp-subscription-item-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] px-4 py-3">
|
|
1529
|
+
<div class="flex justify-between items-center gap-2 w-full"
|
|
1530
|
+
[class.cursor-pointer]="group.children.length > 0"
|
|
1531
|
+
(click)="group.children.length > 0 && toggleAddon(group.key)">
|
|
1550
1532
|
<span class="text-[var(--cp-subscription-item-text)]"
|
|
1551
1533
|
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1552
|
-
[style.fontWeight]="'var(--cp-section-value-weight,
|
|
1553
|
-
{{
|
|
1534
|
+
[style.fontWeight]="'var(--cp-section-value-weight, 600)'">
|
|
1535
|
+
{{ _capitalize(group.name) }}
|
|
1554
1536
|
</span>
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
</div>
|
|
1558
|
-
}
|
|
1559
|
-
|
|
1560
|
-
<!-- Add-on items -->
|
|
1561
|
-
@if (getAddonLineItems(subscription.subscription.subscription_items).length > 0) {
|
|
1562
|
-
<div class="mt-4">
|
|
1563
|
-
<div class="relative z-[100] flex items-center justify-between mb-3 mt-4">
|
|
1564
|
-
<span class="text-[var(--cp-section-label-color)]"
|
|
1565
|
-
[style.fontSize]="'var(--cp-section-label-size)'"
|
|
1566
|
-
[style.fontWeight]="'var(--cp-section-label-weight)'">Add-ons</span>
|
|
1567
|
-
<button type="button"
|
|
1568
|
-
class="bg-[var(--cp-btn-secondary-bg)] text-[var(--cp-btn-secondary-text)] border-[var(--cp-btn-secondary-border)] rounded-[var(--cp-btn-secondary-radius)] px-5 py-2"
|
|
1569
|
-
[style.fontSize]="'var(--cp-btn-secondary-size)'"
|
|
1570
|
-
[style.fontWeight]="'var(--cp-btn-secondary-weight)'"
|
|
1571
|
-
[style.borderWidth]="'var(--cp-btn-secondary-border-width, 1px)'"
|
|
1572
|
-
[style.borderStyle]="'solid'"
|
|
1573
|
-
(click)="handleAddAddon()">
|
|
1574
|
-
Manage add-on
|
|
1575
|
-
</button>
|
|
1576
|
-
</div>
|
|
1577
|
-
<div class="space-y-2">
|
|
1578
|
-
@for (group of getGroupedAddonItems(subscription.subscription.subscription_items); track group.key) {
|
|
1579
|
-
<div class="bg-[var(--cp-subscription-item-bg,white)] border border-[var(--cp-subscription-item-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] px-4 py-3">
|
|
1580
|
-
<div class="flex justify-between items-center gap-2 w-full"
|
|
1581
|
-
[class.cursor-pointer]="group.children.length > 0"
|
|
1582
|
-
(click)="group.children.length > 0 && toggleAddon(group.key)">
|
|
1537
|
+
<div class="flex justify-end items-center">
|
|
1538
|
+
@if (group.baseItem) {
|
|
1583
1539
|
<span class="text-[var(--cp-subscription-item-text)]"
|
|
1584
1540
|
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1585
|
-
[style.fontWeight]="'var(--cp-section-value-weight,
|
|
1586
|
-
{{
|
|
1541
|
+
[style.fontWeight]="'var(--cp-section-value-weight, 500)'">
|
|
1542
|
+
{{ _formatCurrency(group.baseItem.total_amount || group.baseItem.unit_price, group.baseItem.currency_code) }}
|
|
1543
|
+
</span>
|
|
1544
|
+
}
|
|
1545
|
+
@if (group.children.length > 0) {
|
|
1546
|
+
<span class="ml-2 inline-flex transition-transform duration-200"
|
|
1547
|
+
[class.rotate-180]="isAddonExpanded(group.key)"
|
|
1548
|
+
[style.color]="'var(--cp-table-expand-icon-color, #71717a)'">
|
|
1549
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"></path></svg>
|
|
1587
1550
|
</span>
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1551
|
+
}
|
|
1552
|
+
</div>
|
|
1553
|
+
</div>
|
|
1554
|
+
@if (isAddonExpanded(group.key) && group.children.length > 0) {
|
|
1555
|
+
<div class="bg-[var(--cp-section-content-bg,#F4F4F5)] space-y-2 p-4 mt-3 rounded-[var(--cp-section-content-radius)]">
|
|
1556
|
+
@for (child of group.children; track child.price_option_id || child.id) {
|
|
1557
|
+
<div class="bg-[var(--cp-subscription-child-bg,white)] border border-[var(--cp-subscription-child-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] px-4 py-3 flex items-center justify-between">
|
|
1558
|
+
<div class="flex items-center gap-2">
|
|
1559
|
+
<span class="text-[var(--cp-subscription-child-text)]"
|
|
1591
1560
|
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1592
|
-
[style.fontWeight]="'var(--cp-section-value-weight,
|
|
1593
|
-
{{
|
|
1594
|
-
</span>
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
[innerHTML]="_getIcon('arrowDown')"></span>
|
|
1600
|
-
}
|
|
1601
|
-
</div>
|
|
1602
|
-
</div>
|
|
1603
|
-
@if (isAddonExpanded(group.key) && group.children.length > 0) {
|
|
1604
|
-
<div class="bg-[var(--cp-section-content-bg,#F4F4F5)] space-y-2 p-4 mt-3 rounded-[var(--cp-section-content-radius)]">
|
|
1605
|
-
@for (child of group.children; track child.price_option_id || child.id) {
|
|
1606
|
-
<div class="bg-[var(--cp-subscription-child-bg,white)] border border-[var(--cp-subscription-child-border,#e4e4e7)] rounded-[var(--cp-section-content-radius)] px-4 py-3 flex items-center justify-between">
|
|
1607
|
-
<div class="flex items-center gap-2">
|
|
1608
|
-
<span class="text-[var(--cp-subscription-child-text)]"
|
|
1609
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1610
|
-
[style.fontWeight]="'var(--cp-section-value-weight, 600)'">
|
|
1611
|
-
{{ _capitalize(child.name) }}
|
|
1612
|
-
</span>
|
|
1613
|
-
@if (child.quantity > 0) {
|
|
1614
|
-
<span class="text-[var(--cp-subscription-child-quantity,#6b7280)] opacity-75">•</span>
|
|
1615
|
-
<span class="text-[var(--cp-subscription-child-quantity,#6b7280)] font-normal text-sm">
|
|
1616
|
-
{{ child.quantity }} {{ child.name?.toLowerCase() }}
|
|
1617
|
-
</span>
|
|
1618
|
-
}
|
|
1619
|
-
</div>
|
|
1620
|
-
<span class="text-[var(--cp-subscription-child-text)]"
|
|
1621
|
-
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1622
|
-
[style.fontWeight]="'var(--cp-section-value-weight, 500)'">
|
|
1623
|
-
{{ _formatCurrency(child.total_amount || child.unit_price, child.currency_code) }}
|
|
1561
|
+
[style.fontWeight]="'var(--cp-section-value-weight, 600)'">
|
|
1562
|
+
{{ _capitalize(child.name) }}
|
|
1563
|
+
</span>
|
|
1564
|
+
@if (child.quantity > 0) {
|
|
1565
|
+
<span class="text-[var(--cp-subscription-child-quantity,#6b7280)] opacity-75">•</span>
|
|
1566
|
+
<span class="text-[var(--cp-subscription-child-quantity,#6b7280)] font-normal text-sm">
|
|
1567
|
+
{{ child.quantity }} {{ child.name?.toLowerCase() }}
|
|
1624
1568
|
</span>
|
|
1625
|
-
|
|
1626
|
-
|
|
1569
|
+
}
|
|
1570
|
+
</div>
|
|
1571
|
+
<span class="text-[var(--cp-subscription-child-text)]"
|
|
1572
|
+
[style.fontSize]="'var(--cp-section-value-size)'"
|
|
1573
|
+
[style.fontWeight]="'var(--cp-section-value-weight, 500)'">
|
|
1574
|
+
{{ _formatCurrency(child.total_amount || child.unit_price, child.currency_code) }}
|
|
1575
|
+
</span>
|
|
1627
1576
|
</div>
|
|
1628
1577
|
}
|
|
1629
1578
|
</div>
|
|
1630
1579
|
}
|
|
1631
1580
|
</div>
|
|
1632
|
-
|
|
1633
|
-
|
|
1581
|
+
}
|
|
1582
|
+
</div>
|
|
1634
1583
|
</div>
|
|
1635
|
-
|
|
1584
|
+
}
|
|
1585
|
+
</div>
|
|
1586
|
+
</div>
|
|
1587
|
+
}
|
|
1588
|
+
`
|
|
1589
|
+
}]
|
|
1590
|
+
}], propDecorators: { items: [{
|
|
1591
|
+
type: Input
|
|
1592
|
+
}], canUpdateQuantities: [{
|
|
1593
|
+
type: Input
|
|
1594
|
+
}], tenantCheckoutUsername: [{
|
|
1595
|
+
type: Input
|
|
1596
|
+
}], customerKey: [{
|
|
1597
|
+
type: Input
|
|
1598
|
+
}], subscriptionId: [{
|
|
1599
|
+
type: Input
|
|
1600
|
+
}], offeringKey: [{
|
|
1601
|
+
type: Input
|
|
1602
|
+
}] } });
|
|
1603
|
+
|
|
1604
|
+
class SubscriptionSectionComponent {
|
|
1605
|
+
subscription;
|
|
1606
|
+
sectionsConfig;
|
|
1607
|
+
customerKey = '';
|
|
1608
|
+
tenantCheckoutUsername = '';
|
|
1609
|
+
invoicePreview = new EventEmitter();
|
|
1610
|
+
managePlan = new EventEmitter();
|
|
1611
|
+
handleManagePlan() {
|
|
1612
|
+
if (this.subscription) {
|
|
1613
|
+
this.managePlan.emit(this.subscription);
|
|
1636
1614
|
}
|
|
1615
|
+
}
|
|
1616
|
+
_isSectionHidden(key) {
|
|
1617
|
+
return isSectionHidden(this.sectionsConfig, key);
|
|
1618
|
+
}
|
|
1619
|
+
_getSectionLabel(key) {
|
|
1620
|
+
return getSectionLabel(this.sectionsConfig, key);
|
|
1621
|
+
}
|
|
1622
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: SubscriptionSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1623
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: SubscriptionSectionComponent, isStandalone: true, selector: "cp-subscription-section", inputs: { subscription: "subscription", sectionsConfig: "sectionsConfig", customerKey: "customerKey", tenantCheckoutUsername: "tenantCheckoutUsername" }, outputs: { invoicePreview: "invoicePreview", managePlan: "managePlan" }, ngImport: i0, template: `
|
|
1624
|
+
@if (!_isSectionHidden('subscription') && subscription?.subscription) {
|
|
1625
|
+
<div class="w-full"
|
|
1626
|
+
[style.padding]="'var(--cp-section-padding)'"
|
|
1627
|
+
[style.backgroundColor]="'var(--cp-section-bg)'"
|
|
1628
|
+
[style.borderColor]="'var(--cp-section-border)'"
|
|
1629
|
+
[style.borderRadius]="'var(--cp-section-radius)'"
|
|
1630
|
+
[style.borderWidth]="'1px'"
|
|
1631
|
+
[style.borderStyle]="'solid'">
|
|
1632
|
+
<!-- Header: title + Manage plan -->
|
|
1633
|
+
<div class="flex justify-between items-center mb-4">
|
|
1634
|
+
<span class="text-[var(--cp-section-header-color)]"
|
|
1635
|
+
[style.fontSize]="'var(--cp-section-header-size)'"
|
|
1636
|
+
[style.fontWeight]="'var(--cp-section-header-weight)'">
|
|
1637
|
+
{{ _getSectionLabel('subscription') }}
|
|
1638
|
+
</span>
|
|
1639
|
+
@if (subscription.subscription.status !== 'canceled') {
|
|
1640
|
+
<button type="button"
|
|
1641
|
+
class="bg-[var(--cp-btn-primary-bg)] text-[var(--cp-btn-primary-text)] border-[var(--cp-btn-primary-border)] rounded-[var(--cp-btn-primary-radius)] px-5 py-2"
|
|
1642
|
+
[style.fontSize]="'var(--cp-btn-primary-size)'"
|
|
1643
|
+
[style.fontWeight]="'var(--cp-btn-primary-weight)'"
|
|
1644
|
+
[style.borderWidth]="'var(--cp-btn-primary-border-width, 1px)'"
|
|
1645
|
+
[style.borderStyle]="'solid'"
|
|
1646
|
+
(click)="handleManagePlan()">
|
|
1647
|
+
Manage plan
|
|
1648
|
+
</button>
|
|
1649
|
+
}
|
|
1650
|
+
</div>
|
|
1651
|
+
|
|
1652
|
+
<!-- Subscription Details (plan info + billing) -->
|
|
1653
|
+
<cp-subscription-details
|
|
1654
|
+
[sub]="subscription.subscription"
|
|
1655
|
+
(invoicePreview)="invoicePreview.emit($event)">
|
|
1656
|
+
</cp-subscription-details>
|
|
1657
|
+
|
|
1658
|
+
<!-- Subscription Line Items -->
|
|
1659
|
+
<cp-subscription-items
|
|
1660
|
+
[items]="subscription.subscription.subscription_items || []"
|
|
1661
|
+
[canUpdateQuantities]="!!subscription.subscription.can_update_quantities"
|
|
1662
|
+
[tenantCheckoutUsername]="tenantCheckoutUsername"
|
|
1663
|
+
[customerKey]="customerKey"
|
|
1664
|
+
[subscriptionId]="subscription.subscription.id || ''"
|
|
1665
|
+
[offeringKey]="subscription.subscription.offering_key || ''">
|
|
1666
|
+
</cp-subscription-items>
|
|
1667
|
+
</div>
|
|
1668
|
+
}
|
|
1669
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SubscriptionDetailsComponent, selector: "cp-subscription-details", inputs: ["sub"], outputs: ["invoicePreview"] }, { kind: "component", type: SubscriptionItemsComponent, selector: "cp-subscription-items", inputs: ["items", "canUpdateQuantities", "tenantCheckoutUsername", "customerKey", "subscriptionId", "offeringKey"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1670
|
+
}
|
|
1671
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: SubscriptionSectionComponent, decorators: [{
|
|
1672
|
+
type: Component,
|
|
1673
|
+
args: [{
|
|
1674
|
+
selector: 'cp-subscription-section',
|
|
1675
|
+
standalone: true,
|
|
1676
|
+
imports: [CommonModule, SubscriptionDetailsComponent, SubscriptionItemsComponent],
|
|
1677
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1678
|
+
template: `
|
|
1679
|
+
@if (!_isSectionHidden('subscription') && subscription?.subscription) {
|
|
1680
|
+
<div class="w-full"
|
|
1681
|
+
[style.padding]="'var(--cp-section-padding)'"
|
|
1682
|
+
[style.backgroundColor]="'var(--cp-section-bg)'"
|
|
1683
|
+
[style.borderColor]="'var(--cp-section-border)'"
|
|
1684
|
+
[style.borderRadius]="'var(--cp-section-radius)'"
|
|
1685
|
+
[style.borderWidth]="'1px'"
|
|
1686
|
+
[style.borderStyle]="'solid'">
|
|
1687
|
+
<!-- Header: title + Manage plan -->
|
|
1688
|
+
<div class="flex justify-between items-center mb-4">
|
|
1689
|
+
<span class="text-[var(--cp-section-header-color)]"
|
|
1690
|
+
[style.fontSize]="'var(--cp-section-header-size)'"
|
|
1691
|
+
[style.fontWeight]="'var(--cp-section-header-weight)'">
|
|
1692
|
+
{{ _getSectionLabel('subscription') }}
|
|
1693
|
+
</span>
|
|
1694
|
+
@if (subscription.subscription.status !== 'canceled') {
|
|
1695
|
+
<button type="button"
|
|
1696
|
+
class="bg-[var(--cp-btn-primary-bg)] text-[var(--cp-btn-primary-text)] border-[var(--cp-btn-primary-border)] rounded-[var(--cp-btn-primary-radius)] px-5 py-2"
|
|
1697
|
+
[style.fontSize]="'var(--cp-btn-primary-size)'"
|
|
1698
|
+
[style.fontWeight]="'var(--cp-btn-primary-weight)'"
|
|
1699
|
+
[style.borderWidth]="'var(--cp-btn-primary-border-width, 1px)'"
|
|
1700
|
+
[style.borderStyle]="'solid'"
|
|
1701
|
+
(click)="handleManagePlan()">
|
|
1702
|
+
Manage plan
|
|
1703
|
+
</button>
|
|
1704
|
+
}
|
|
1705
|
+
</div>
|
|
1706
|
+
|
|
1707
|
+
<!-- Subscription Details (plan info + billing) -->
|
|
1708
|
+
<cp-subscription-details
|
|
1709
|
+
[sub]="subscription.subscription"
|
|
1710
|
+
(invoicePreview)="invoicePreview.emit($event)">
|
|
1711
|
+
</cp-subscription-details>
|
|
1712
|
+
|
|
1713
|
+
<!-- Subscription Line Items -->
|
|
1714
|
+
<cp-subscription-items
|
|
1715
|
+
[items]="subscription.subscription.subscription_items || []"
|
|
1716
|
+
[canUpdateQuantities]="!!subscription.subscription.can_update_quantities"
|
|
1717
|
+
[tenantCheckoutUsername]="tenantCheckoutUsername"
|
|
1718
|
+
[customerKey]="customerKey"
|
|
1719
|
+
[subscriptionId]="subscription.subscription.id || ''"
|
|
1720
|
+
[offeringKey]="subscription.subscription.offering_key || ''">
|
|
1721
|
+
</cp-subscription-items>
|
|
1637
1722
|
</div>
|
|
1638
1723
|
}
|
|
1639
|
-
|
|
1724
|
+
`
|
|
1640
1725
|
}]
|
|
1641
1726
|
}], propDecorators: { subscription: [{
|
|
1642
1727
|
type: Input
|
|
@@ -1666,7 +1751,7 @@ class CreditBalanceSectionComponent {
|
|
|
1666
1751
|
walletTabs = [
|
|
1667
1752
|
{ key: 'active', label: 'Active' },
|
|
1668
1753
|
{ key: 'expired', label: 'Expired' },
|
|
1669
|
-
{ key: 'overage', label: 'Overage' }
|
|
1754
|
+
{ key: 'overage', label: 'Overage' }
|
|
1670
1755
|
];
|
|
1671
1756
|
showCreditTransactions = signal(false);
|
|
1672
1757
|
selectedAllocation = signal(null);
|
|
@@ -1725,7 +1810,7 @@ class CreditBalanceSectionComponent {
|
|
|
1725
1810
|
year: 'numeric',
|
|
1726
1811
|
hour: 'numeric',
|
|
1727
1812
|
minute: '2-digit',
|
|
1728
|
-
hour12: true
|
|
1813
|
+
hour12: true
|
|
1729
1814
|
})
|
|
1730
1815
|
.replace(',', '');
|
|
1731
1816
|
}
|
|
@@ -1747,7 +1832,7 @@ class CreditBalanceSectionComponent {
|
|
|
1747
1832
|
return date.toLocaleDateString('en-US', {
|
|
1748
1833
|
month: 'numeric',
|
|
1749
1834
|
day: 'numeric',
|
|
1750
|
-
year: 'numeric'
|
|
1835
|
+
year: 'numeric'
|
|
1751
1836
|
});
|
|
1752
1837
|
}
|
|
1753
1838
|
getAllocationBalance(allocation) {
|
|
@@ -1769,13 +1854,13 @@ class CreditBalanceSectionComponent {
|
|
|
1769
1854
|
.pipe(takeUntil(this.destroy$))
|
|
1770
1855
|
.subscribe({
|
|
1771
1856
|
next: (data) => {
|
|
1772
|
-
this.creditTransactions.set(data
|
|
1857
|
+
this.creditTransactions.set(data || []);
|
|
1773
1858
|
this.creditTransactionsLoading.set(false);
|
|
1774
1859
|
},
|
|
1775
1860
|
error: () => {
|
|
1776
1861
|
this.creditTransactions.set([]);
|
|
1777
1862
|
this.creditTransactionsLoading.set(false);
|
|
1778
|
-
}
|
|
1863
|
+
}
|
|
1779
1864
|
});
|
|
1780
1865
|
}
|
|
1781
1866
|
closeCreditTransactions() {
|
|
@@ -1801,13 +1886,16 @@ class CreditBalanceSectionComponent {
|
|
|
1801
1886
|
getWalletSettingsValidationErrors() {
|
|
1802
1887
|
const errors = [];
|
|
1803
1888
|
if (this.lowBalanceEnabled) {
|
|
1804
|
-
if (!this.walletSettingThreshold?.trim())
|
|
1889
|
+
if (!this.walletSettingThreshold?.trim()) {
|
|
1805
1890
|
errors.push('Set a low balance threshold is required');
|
|
1891
|
+
}
|
|
1806
1892
|
if (this.walletSettingBehaviour === 'auto_top_up') {
|
|
1807
|
-
if (!this.walletSettingTargetBalance?.trim())
|
|
1893
|
+
if (!this.walletSettingTargetBalance?.trim()) {
|
|
1808
1894
|
errors.push('Bring wallet balance back up to is required for auto top-up');
|
|
1809
|
-
|
|
1895
|
+
}
|
|
1896
|
+
if (!this.walletSettingMonthlyLimit?.trim()) {
|
|
1810
1897
|
errors.push('Limit the amount of automatic top up per month is required for auto top-up');
|
|
1898
|
+
}
|
|
1811
1899
|
}
|
|
1812
1900
|
}
|
|
1813
1901
|
return errors;
|
|
@@ -1844,7 +1932,7 @@ class CreditBalanceSectionComponent {
|
|
|
1844
1932
|
error: (err) => {
|
|
1845
1933
|
this.walletSettingsError.set(err?.message || 'Failed to delete settings');
|
|
1846
1934
|
this.walletSettingsSaving.set(false);
|
|
1847
|
-
}
|
|
1935
|
+
}
|
|
1848
1936
|
});
|
|
1849
1937
|
}
|
|
1850
1938
|
else {
|
|
@@ -1861,8 +1949,8 @@ class CreditBalanceSectionComponent {
|
|
|
1861
1949
|
threshold_amount: Number(this.walletSettingThreshold) || 0,
|
|
1862
1950
|
...(this.walletSettingBehaviour === 'auto_top_up' && {
|
|
1863
1951
|
target_balance: Number(this.walletSettingTargetBalance) || 0,
|
|
1864
|
-
monthly_top_up_count_limit: Number(this.walletSettingMonthlyLimit) || 0
|
|
1865
|
-
})
|
|
1952
|
+
monthly_top_up_count_limit: Number(this.walletSettingMonthlyLimit) || 0
|
|
1953
|
+
})
|
|
1866
1954
|
};
|
|
1867
1955
|
this.walletSettingsSaving.set(true);
|
|
1868
1956
|
const editId = this.walletSettingEditId();
|
|
@@ -1878,7 +1966,7 @@ class CreditBalanceSectionComponent {
|
|
|
1878
1966
|
error: (err) => {
|
|
1879
1967
|
this.walletSettingsError.set(err?.message || 'Failed to save settings');
|
|
1880
1968
|
this.walletSettingsSaving.set(false);
|
|
1881
|
-
}
|
|
1969
|
+
}
|
|
1882
1970
|
});
|
|
1883
1971
|
}
|
|
1884
1972
|
onWalletSelectChange(event) {
|
|
@@ -1916,7 +2004,7 @@ class CreditBalanceSectionComponent {
|
|
|
1916
2004
|
error: (err) => {
|
|
1917
2005
|
this.walletSettingsError.set(err?.message || 'Failed to load wallet settings');
|
|
1918
2006
|
this.walletSettingsLoading.set(false);
|
|
1919
|
-
}
|
|
2007
|
+
}
|
|
1920
2008
|
});
|
|
1921
2009
|
}
|
|
1922
2010
|
applyExistingWalletSetting() {
|
|
@@ -2160,7 +2248,7 @@ class CreditBalanceSectionComponent {
|
|
|
2160
2248
|
|
|
2161
2249
|
<!-- Credit Transactions Modal (compact width) -->
|
|
2162
2250
|
@if (showCreditTransactions()) {
|
|
2163
|
-
<div class="fixed inset-0 flex items-center justify-center z-
|
|
2251
|
+
<div class="fixed inset-0 flex items-center justify-center z-[100] p-4" [style.background-color]="'var(--cp-modal-overlay-bg)'" (click)="closeCreditTransactions()">
|
|
2164
2252
|
<div class="w-full max-w-sm max-h-[80vh] flex flex-col mx-auto" [style.background-color]="'var(--cp-modal-bg)'" [style.border-radius]="'var(--cp-modal-radius)'" (click)="$event.stopPropagation()">
|
|
2165
2253
|
<!-- Modal Header -->
|
|
2166
2254
|
<div class="flex justify-between items-center p-4 border-b border-gray-100">
|
|
@@ -2264,7 +2352,7 @@ class CreditBalanceSectionComponent {
|
|
|
2264
2352
|
|
|
2265
2353
|
<!-- Wallet Settings Modal -->
|
|
2266
2354
|
@if (showWalletSettings()) {
|
|
2267
|
-
<div class="fixed inset-0 flex items-center justify-center z-
|
|
2355
|
+
<div class="fixed inset-0 flex items-center justify-center z-[100] p-6" [style.background-color]="'var(--cp-modal-overlay-bg)'" (click)="closeWalletSettings()">
|
|
2268
2356
|
<div class="w-full max-w-3xl min-h-[75vh] max-h-[85vh] flex flex-col shadow-xl" [style.background-color]="'var(--cp-modal-bg)'" [style.border-radius]="'var(--cp-modal-radius)'" (click)="$event.stopPropagation()">
|
|
2269
2357
|
<!-- Modal Header -->
|
|
2270
2358
|
<div class="flex justify-between items-center p-4 border-b border-gray-100">
|
|
@@ -2624,7 +2712,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
2624
2712
|
|
|
2625
2713
|
<!-- Credit Transactions Modal (compact width) -->
|
|
2626
2714
|
@if (showCreditTransactions()) {
|
|
2627
|
-
<div class="fixed inset-0 flex items-center justify-center z-
|
|
2715
|
+
<div class="fixed inset-0 flex items-center justify-center z-[100] p-4" [style.background-color]="'var(--cp-modal-overlay-bg)'" (click)="closeCreditTransactions()">
|
|
2628
2716
|
<div class="w-full max-w-sm max-h-[80vh] flex flex-col mx-auto" [style.background-color]="'var(--cp-modal-bg)'" [style.border-radius]="'var(--cp-modal-radius)'" (click)="$event.stopPropagation()">
|
|
2629
2717
|
<!-- Modal Header -->
|
|
2630
2718
|
<div class="flex justify-between items-center p-4 border-b border-gray-100">
|
|
@@ -2728,7 +2816,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
2728
2816
|
|
|
2729
2817
|
<!-- Wallet Settings Modal -->
|
|
2730
2818
|
@if (showWalletSettings()) {
|
|
2731
|
-
<div class="fixed inset-0 flex items-center justify-center z-
|
|
2819
|
+
<div class="fixed inset-0 flex items-center justify-center z-[100] p-6" [style.background-color]="'var(--cp-modal-overlay-bg)'" (click)="closeWalletSettings()">
|
|
2732
2820
|
<div class="w-full max-w-3xl min-h-[75vh] max-h-[85vh] flex flex-col shadow-xl" [style.background-color]="'var(--cp-modal-bg)'" [style.border-radius]="'var(--cp-modal-radius)'" (click)="$event.stopPropagation()">
|
|
2733
2821
|
<!-- Modal Header -->
|
|
2734
2822
|
<div class="flex justify-between items-center p-4 border-b border-gray-100">
|
|
@@ -2861,7 +2949,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
2861
2949
|
</div>
|
|
2862
2950
|
</div>
|
|
2863
2951
|
}
|
|
2864
|
-
|
|
2952
|
+
`
|
|
2865
2953
|
}]
|
|
2866
2954
|
}], propDecorators: { wallets: [{
|
|
2867
2955
|
type: Input
|
|
@@ -2881,46 +2969,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
2881
2969
|
type: Output
|
|
2882
2970
|
}] } });
|
|
2883
2971
|
|
|
2884
|
-
class
|
|
2972
|
+
class EntitlementSummaryComponent {
|
|
2885
2973
|
sanitizer = inject(DomSanitizer);
|
|
2886
2974
|
entitlementSummary = [];
|
|
2887
|
-
entitlementUsage = [];
|
|
2888
|
-
sectionsConfig;
|
|
2889
|
-
entitlementTab = signal('summary');
|
|
2890
|
-
expandedEntitlements = new Set();
|
|
2891
|
-
Math = Math;
|
|
2892
|
-
_isSectionHidden(key) {
|
|
2893
|
-
return isSectionHidden(this.sectionsConfig, key);
|
|
2894
|
-
}
|
|
2895
|
-
_getSectionLabel(key) {
|
|
2896
|
-
return getSectionLabel(this.sectionsConfig, key);
|
|
2897
|
-
}
|
|
2898
2975
|
_getIcon(name) {
|
|
2899
2976
|
return getIcon(this.sanitizer, name);
|
|
2900
2977
|
}
|
|
2901
2978
|
_capitalize(str) {
|
|
2902
2979
|
return capitalize(str);
|
|
2903
2980
|
}
|
|
2904
|
-
_formatNumber(num) {
|
|
2905
|
-
return formatNumber(num);
|
|
2906
|
-
}
|
|
2907
|
-
changeEntitlementTab(tab) {
|
|
2908
|
-
this.entitlementTab.set(tab);
|
|
2909
|
-
}
|
|
2910
|
-
getMeteredEntitlements() {
|
|
2911
|
-
return (this.entitlementUsage || []).filter((usage) => usage.type !== 'boolean' && usage.feature_type !== 'boolean');
|
|
2912
|
-
}
|
|
2913
2981
|
formatUsageModel(entitlement) {
|
|
2914
2982
|
if (!entitlement.usage_model)
|
|
2915
2983
|
return '';
|
|
2916
|
-
const model = entitlement.usage_model.split('_').join(' ');
|
|
2984
|
+
const model = String(entitlement.usage_model).split('_').join(' ');
|
|
2917
2985
|
let result = capitalize(model);
|
|
2918
2986
|
if (entitlement.feature_type === 'metered') {
|
|
2919
2987
|
if (entitlement.prepaid) {
|
|
2920
2988
|
result += '/ Prepaid';
|
|
2921
2989
|
}
|
|
2922
2990
|
else if (entitlement.price_type) {
|
|
2923
|
-
result += '/ ' + capitalize(entitlement.price_type);
|
|
2991
|
+
result += '/ ' + capitalize(String(entitlement.price_type));
|
|
2924
2992
|
}
|
|
2925
2993
|
}
|
|
2926
2994
|
return result;
|
|
@@ -2933,9 +3001,9 @@ class EntitlementsSectionComponent {
|
|
|
2933
3001
|
return 'Unlimited';
|
|
2934
3002
|
if (allowance === null || allowance === undefined)
|
|
2935
3003
|
return '0';
|
|
2936
|
-
let result = formatNumber(allowance);
|
|
3004
|
+
let result = formatNumber(Number(allowance));
|
|
2937
3005
|
if (entitlement.included_allowance_reset_interval && entitlement.included_allowance_reset_interval !== 'none') {
|
|
2938
|
-
result += ' ' + getResetIntervalLabel(entitlement.included_allowance_reset_interval);
|
|
3006
|
+
result += ' ' + getResetIntervalLabel(String(entitlement.included_allowance_reset_interval));
|
|
2939
3007
|
}
|
|
2940
3008
|
return result;
|
|
2941
3009
|
}
|
|
@@ -2946,17 +3014,17 @@ class EntitlementsSectionComponent {
|
|
|
2946
3014
|
const limit = entitlement.usage_limit ?? 'Unlimited';
|
|
2947
3015
|
if (limit === -1)
|
|
2948
3016
|
return 'Unlimited';
|
|
2949
|
-
let result = typeof limit === 'number' ? formatNumber(limit) : limit;
|
|
3017
|
+
let result = typeof limit === 'number' ? formatNumber(limit) : String(limit);
|
|
2950
3018
|
if (entitlement.usage_limit_reset_interval && entitlement.usage_limit_reset_interval !== 'none') {
|
|
2951
|
-
result += ' ' + getResetIntervalLabel(entitlement.usage_limit_reset_interval);
|
|
3019
|
+
result += ' ' + getResetIntervalLabel(String(entitlement.usage_limit_reset_interval));
|
|
2952
3020
|
}
|
|
2953
3021
|
return result;
|
|
2954
3022
|
}
|
|
2955
3023
|
if (entitlement.purchased_qty !== null && entitlement.purchased_qty !== undefined) {
|
|
2956
|
-
const qty = entitlement.purchased_qty === -1 ? 'Unlimited' : formatNumber(entitlement.purchased_qty);
|
|
3024
|
+
const qty = entitlement.purchased_qty === -1 ? 'Unlimited' : formatNumber(Number(entitlement.purchased_qty));
|
|
2957
3025
|
let interval = '';
|
|
2958
3026
|
if (entitlement.billing_interval && entitlement.billing_interval !== 'none') {
|
|
2959
|
-
interval = ' ' + getResetIntervalLabel(entitlement.billing_interval);
|
|
3027
|
+
interval = ' ' + getResetIntervalLabel(String(entitlement.billing_interval));
|
|
2960
3028
|
}
|
|
2961
3029
|
const softLimit = entitlement.soft_limit_enabled ? ' Soft limits enabled' : '';
|
|
2962
3030
|
return qty + interval + softLimit;
|
|
@@ -2964,15 +3032,192 @@ class EntitlementsSectionComponent {
|
|
|
2964
3032
|
if (entitlement.included_allowance !== null && entitlement.included_allowance !== undefined) {
|
|
2965
3033
|
if (entitlement.included_allowance === -1)
|
|
2966
3034
|
return 'Unlimited';
|
|
2967
|
-
let result = formatNumber(entitlement.included_allowance);
|
|
3035
|
+
let result = formatNumber(Number(entitlement.included_allowance));
|
|
2968
3036
|
if (entitlement.included_allowance_reset_interval && entitlement.included_allowance_reset_interval !== 'none') {
|
|
2969
|
-
result += ' ' + getResetIntervalLabel(entitlement.included_allowance_reset_interval);
|
|
3037
|
+
result += ' ' + getResetIntervalLabel(String(entitlement.included_allowance_reset_interval));
|
|
2970
3038
|
}
|
|
2971
3039
|
return result;
|
|
2972
3040
|
}
|
|
2973
3041
|
return '0';
|
|
2974
3042
|
}
|
|
2975
|
-
|
|
3043
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: EntitlementSummaryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3044
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: EntitlementSummaryComponent, isStandalone: true, selector: "cp-entitlement-summary", inputs: { entitlementSummary: "entitlementSummary" }, ngImport: i0, template: `
|
|
3045
|
+
<div class="overflow-x-auto bg-transparent">
|
|
3046
|
+
@if (entitlementSummary.length > 0) {
|
|
3047
|
+
<table class="min-w-full border-collapse text-left relative">
|
|
3048
|
+
<thead>
|
|
3049
|
+
<tr>
|
|
3050
|
+
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3051
|
+
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3052
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3053
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Feature</th>
|
|
3054
|
+
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3055
|
+
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3056
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3057
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Meter type</th>
|
|
3058
|
+
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3059
|
+
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3060
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3061
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Included allowance</th>
|
|
3062
|
+
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3063
|
+
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3064
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3065
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Usage limits</th>
|
|
3066
|
+
</tr>
|
|
3067
|
+
</thead>
|
|
3068
|
+
<tbody>
|
|
3069
|
+
@for (entitlement of entitlementSummary; track entitlement.id || $index; let rowIdx = $index) {
|
|
3070
|
+
<tr [class]="rowIdx % 2 === 0 ? 'bg-[var(--cp-table-row-even-bg)]' : 'bg-[var(--cp-table-row-odd-bg)]'">
|
|
3071
|
+
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3072
|
+
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3073
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3074
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3075
|
+
<div class="flex flex-col gap-y-1 items-start max-w-[130px]">
|
|
3076
|
+
<span>{{ entitlement.feature_name || '-' }}</span>
|
|
3077
|
+
<span class="text-[var(--cp-table-text)] max-w-[120px] truncate"
|
|
3078
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3079
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ entitlement.feature_key }}</span>
|
|
3080
|
+
</div>
|
|
3081
|
+
</td>
|
|
3082
|
+
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3083
|
+
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3084
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3085
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3086
|
+
<div>
|
|
3087
|
+
<span>{{ _capitalize(entitlement.feature_type) }}</span>
|
|
3088
|
+
@if (entitlement.usage_model) {
|
|
3089
|
+
<span class="block mt-1">{{ formatUsageModel(entitlement) }}</span>
|
|
3090
|
+
}
|
|
3091
|
+
</div>
|
|
3092
|
+
</td>
|
|
3093
|
+
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3094
|
+
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3095
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3096
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3097
|
+
{{ formatIncludedAllowance(entitlement) }}
|
|
3098
|
+
</td>
|
|
3099
|
+
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3100
|
+
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3101
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3102
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3103
|
+
{{ formatUsageLimits(entitlement) }}
|
|
3104
|
+
</td>
|
|
3105
|
+
</tr>
|
|
3106
|
+
}
|
|
3107
|
+
</tbody>
|
|
3108
|
+
</table>
|
|
3109
|
+
} @else {
|
|
3110
|
+
<div class="flex flex-col items-center gap-y-3 py-12">
|
|
3111
|
+
<span [innerHTML]="_getIcon('noteEmpty')"></span>
|
|
3112
|
+
<span class="text-sm text-[var(--cp-section-empty-text)]">No entitlements attached to this subscription</span>
|
|
3113
|
+
</div>
|
|
3114
|
+
}
|
|
3115
|
+
</div>
|
|
3116
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3117
|
+
}
|
|
3118
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: EntitlementSummaryComponent, decorators: [{
|
|
3119
|
+
type: Component,
|
|
3120
|
+
args: [{
|
|
3121
|
+
selector: 'cp-entitlement-summary',
|
|
3122
|
+
standalone: true,
|
|
3123
|
+
imports: [CommonModule],
|
|
3124
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3125
|
+
template: `
|
|
3126
|
+
<div class="overflow-x-auto bg-transparent">
|
|
3127
|
+
@if (entitlementSummary.length > 0) {
|
|
3128
|
+
<table class="min-w-full border-collapse text-left relative">
|
|
3129
|
+
<thead>
|
|
3130
|
+
<tr>
|
|
3131
|
+
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3132
|
+
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3133
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3134
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Feature</th>
|
|
3135
|
+
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3136
|
+
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3137
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3138
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Meter type</th>
|
|
3139
|
+
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3140
|
+
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3141
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3142
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Included allowance</th>
|
|
3143
|
+
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3144
|
+
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3145
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3146
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Usage limits</th>
|
|
3147
|
+
</tr>
|
|
3148
|
+
</thead>
|
|
3149
|
+
<tbody>
|
|
3150
|
+
@for (entitlement of entitlementSummary; track entitlement.id || $index; let rowIdx = $index) {
|
|
3151
|
+
<tr [class]="rowIdx % 2 === 0 ? 'bg-[var(--cp-table-row-even-bg)]' : 'bg-[var(--cp-table-row-odd-bg)]'">
|
|
3152
|
+
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3153
|
+
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3154
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3155
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3156
|
+
<div class="flex flex-col gap-y-1 items-start max-w-[130px]">
|
|
3157
|
+
<span>{{ entitlement.feature_name || '-' }}</span>
|
|
3158
|
+
<span class="text-[var(--cp-table-text)] max-w-[120px] truncate"
|
|
3159
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3160
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ entitlement.feature_key }}</span>
|
|
3161
|
+
</div>
|
|
3162
|
+
</td>
|
|
3163
|
+
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3164
|
+
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3165
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3166
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3167
|
+
<div>
|
|
3168
|
+
<span>{{ _capitalize(entitlement.feature_type) }}</span>
|
|
3169
|
+
@if (entitlement.usage_model) {
|
|
3170
|
+
<span class="block mt-1">{{ formatUsageModel(entitlement) }}</span>
|
|
3171
|
+
}
|
|
3172
|
+
</div>
|
|
3173
|
+
</td>
|
|
3174
|
+
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3175
|
+
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3176
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3177
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3178
|
+
{{ formatIncludedAllowance(entitlement) }}
|
|
3179
|
+
</td>
|
|
3180
|
+
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3181
|
+
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3182
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3183
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3184
|
+
{{ formatUsageLimits(entitlement) }}
|
|
3185
|
+
</td>
|
|
3186
|
+
</tr>
|
|
3187
|
+
}
|
|
3188
|
+
</tbody>
|
|
3189
|
+
</table>
|
|
3190
|
+
} @else {
|
|
3191
|
+
<div class="flex flex-col items-center gap-y-3 py-12">
|
|
3192
|
+
<span [innerHTML]="_getIcon('noteEmpty')"></span>
|
|
3193
|
+
<span class="text-sm text-[var(--cp-section-empty-text)]">No entitlements attached to this subscription</span>
|
|
3194
|
+
</div>
|
|
3195
|
+
}
|
|
3196
|
+
</div>
|
|
3197
|
+
`
|
|
3198
|
+
}]
|
|
3199
|
+
}], propDecorators: { entitlementSummary: [{
|
|
3200
|
+
type: Input
|
|
3201
|
+
}] } });
|
|
3202
|
+
|
|
3203
|
+
class EntitlementUsageComponent {
|
|
3204
|
+
sanitizer = inject(DomSanitizer);
|
|
3205
|
+
expandedEntitlements = new Set();
|
|
3206
|
+
Math = Math;
|
|
3207
|
+
entitlementUsage = [];
|
|
3208
|
+
get meteredEntitlements() {
|
|
3209
|
+
return (this.entitlementUsage || []).filter((usage) => usage.type !== 'boolean');
|
|
3210
|
+
}
|
|
3211
|
+
_getIcon(name) {
|
|
3212
|
+
return getIcon(this.sanitizer, name);
|
|
3213
|
+
}
|
|
3214
|
+
_capitalize(str) {
|
|
3215
|
+
return capitalize(str);
|
|
3216
|
+
}
|
|
3217
|
+
_formatNumber(num) {
|
|
3218
|
+
return formatNumber(num);
|
|
3219
|
+
}
|
|
3220
|
+
toggleExpand(id) {
|
|
2976
3221
|
if (this.expandedEntitlements.has(id)) {
|
|
2977
3222
|
this.expandedEntitlements.delete(id);
|
|
2978
3223
|
}
|
|
@@ -2980,10 +3225,10 @@ class EntitlementsSectionComponent {
|
|
|
2980
3225
|
this.expandedEntitlements.add(id);
|
|
2981
3226
|
}
|
|
2982
3227
|
}
|
|
2983
|
-
|
|
3228
|
+
isExpanded(id) {
|
|
2984
3229
|
return this.expandedEntitlements.has(id);
|
|
2985
3230
|
}
|
|
2986
|
-
|
|
3231
|
+
getUsageBalance(usage) {
|
|
2987
3232
|
const pools = this.getProcessedPools(usage);
|
|
2988
3233
|
const isAnyUnlimited = pools.some((p) => p.isUnlimited);
|
|
2989
3234
|
const totalBalance = pools.filter((p) => !p.isUnlimited).reduce((sum, p) => sum + p.balance, 0);
|
|
@@ -2993,7 +3238,7 @@ class EntitlementsSectionComponent {
|
|
|
2993
3238
|
return formatNumber(Math.abs(totalBalance)) + ' used above limit';
|
|
2994
3239
|
return formatNumber(totalBalance) + ' left';
|
|
2995
3240
|
}
|
|
2996
|
-
|
|
3241
|
+
getUsagePercent(usage) {
|
|
2997
3242
|
const pools = this.getProcessedPools(usage);
|
|
2998
3243
|
const isAnyUnlimited = pools.some((p) => p.isUnlimited);
|
|
2999
3244
|
if (isAnyUnlimited)
|
|
@@ -3004,7 +3249,7 @@ class EntitlementsSectionComponent {
|
|
|
3004
3249
|
return 0;
|
|
3005
3250
|
return Math.min((totalUsed / totalAmount) * 100, 100);
|
|
3006
3251
|
}
|
|
3007
|
-
|
|
3252
|
+
getUsageText(usage) {
|
|
3008
3253
|
const pools = this.getProcessedPools(usage);
|
|
3009
3254
|
const isAnyUnlimited = pools.some((p) => p.isUnlimited);
|
|
3010
3255
|
const totalAmount = pools.filter((p) => !p.isUnlimited).reduce((sum, p) => sum + p.amount, 0);
|
|
@@ -3019,13 +3264,14 @@ class EntitlementsSectionComponent {
|
|
|
3019
3264
|
{ key: 'included_pool', name: 'Included', color: 'gray-400', order: 1 },
|
|
3020
3265
|
{ key: 'purchased_pool', name: 'Purchased', color: 'gray-400', order: 2 },
|
|
3021
3266
|
{ key: 'pay_as_you_go_pool', name: 'Pay as you go', color: 'blue-500', order: 3 },
|
|
3022
|
-
{ key: 'rollover_quantity_pool', name: 'Rollover', color: 'green-500', order: 4 }
|
|
3267
|
+
{ key: 'rollover_quantity_pool', name: 'Rollover', color: 'green-500', order: 4 }
|
|
3023
3268
|
];
|
|
3024
3269
|
for (const config of poolConfigs) {
|
|
3025
|
-
const
|
|
3026
|
-
if (
|
|
3027
|
-
const
|
|
3028
|
-
const
|
|
3270
|
+
const rawPool = usage[config.key];
|
|
3271
|
+
if (rawPool && typeof rawPool === 'object') {
|
|
3272
|
+
const pool = rawPool;
|
|
3273
|
+
const amount = pool.amount === null ? Infinity : parseFloat(String(pool.amount)) || 0;
|
|
3274
|
+
const used = parseFloat(String(pool.used)) || 0;
|
|
3029
3275
|
const balance = amount === Infinity ? Infinity : amount - used;
|
|
3030
3276
|
const isUnlimited = amount === Infinity;
|
|
3031
3277
|
const percent = isUnlimited ? 100 : (amount > 0 ? (used / amount) * 100 : 0);
|
|
@@ -3038,26 +3284,297 @@ class EntitlementsSectionComponent {
|
|
|
3038
3284
|
percent: Math.min(percent, 100),
|
|
3039
3285
|
isUnlimited,
|
|
3040
3286
|
order: config.order,
|
|
3041
|
-
nextResetAt: pool.next_reset_at ? this.formatResetDate(pool.next_reset_at) : null
|
|
3287
|
+
nextResetAt: pool.next_reset_at ? this.formatResetDate(String(pool.next_reset_at)) : null
|
|
3042
3288
|
});
|
|
3043
3289
|
}
|
|
3044
3290
|
}
|
|
3045
|
-
return pools.sort((a, b) => a.order - b.order);
|
|
3291
|
+
return pools.sort((a, b) => a.order - b.order);
|
|
3292
|
+
}
|
|
3293
|
+
formatResetDate(dateStr) {
|
|
3294
|
+
if (!dateStr)
|
|
3295
|
+
return '';
|
|
3296
|
+
const date = new Date(dateStr);
|
|
3297
|
+
return date
|
|
3298
|
+
.toLocaleDateString('en-US', {
|
|
3299
|
+
month: 'short',
|
|
3300
|
+
day: 'numeric',
|
|
3301
|
+
year: 'numeric',
|
|
3302
|
+
hour: 'numeric',
|
|
3303
|
+
minute: '2-digit',
|
|
3304
|
+
hour12: true
|
|
3305
|
+
})
|
|
3306
|
+
.toLowerCase();
|
|
3307
|
+
}
|
|
3308
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: EntitlementUsageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3309
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: EntitlementUsageComponent, isStandalone: true, selector: "cp-entitlement-usage", inputs: { entitlementUsage: "entitlementUsage" }, ngImport: i0, template: `
|
|
3310
|
+
<div class="bg-transparent rounded-2xl px-3 pt-5">
|
|
3311
|
+
@if (meteredEntitlements.length > 0) {
|
|
3312
|
+
<!-- Header -->
|
|
3313
|
+
<div class="grid grid-cols-4 border-b border-[var(--cp-table-border)] gap-x-4 pr-12 bg-[var(--cp-table-header-bg)]"
|
|
3314
|
+
[style.padding]="'var(--cp-table-cell-padding, 0.75rem 1.5rem)'">
|
|
3315
|
+
<div class="text-[var(--cp-table-header-text)]"
|
|
3316
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3317
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Feature</div>
|
|
3318
|
+
<div class="text-[var(--cp-table-header-text)]"
|
|
3319
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3320
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Type</div>
|
|
3321
|
+
<div class="col-span-2 text-[var(--cp-table-header-text)]"
|
|
3322
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3323
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Usage</div>
|
|
3324
|
+
</div>
|
|
3325
|
+
|
|
3326
|
+
<!-- Rows -->
|
|
3327
|
+
@for (usage of meteredEntitlements; track usage.id || $index; let rowIdx = $index) {
|
|
3328
|
+
<div class="border-b border-[var(--cp-table-border)] last:border-0"
|
|
3329
|
+
[class]="rowIdx % 2 === 0 ? 'bg-[var(--cp-table-row-even-bg)]' : 'bg-[var(--cp-table-row-odd-bg)]'"
|
|
3330
|
+
[style.padding]="'var(--cp-table-cell-padding, 1rem 1.5rem)'">
|
|
3331
|
+
<!-- Main Row (Collapsible Trigger) -->
|
|
3332
|
+
<div class="flex items-center cursor-pointer" (click)="toggleExpand(usage.id)">
|
|
3333
|
+
<div class="flex-1 grid grid-cols-4 gap-4 items-center pr-8">
|
|
3334
|
+
<!-- Feature -->
|
|
3335
|
+
<div class="flex flex-col gap-y-1 items-start max-w-[120px] text-balance">
|
|
3336
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3337
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3338
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ usage.feature_name || '-' }}</span>
|
|
3339
|
+
<span class="text-[var(--cp-table-text)] max-w-[120px] truncate"
|
|
3340
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3341
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ usage.feature_key }}</span>
|
|
3342
|
+
</div>
|
|
3343
|
+
|
|
3344
|
+
<!-- Type -->
|
|
3345
|
+
<div>
|
|
3346
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3347
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3348
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ _capitalize(usage.type?.split('_').join(' ') || '') }}</span>
|
|
3349
|
+
</div>
|
|
3350
|
+
|
|
3351
|
+
<!-- Usage -->
|
|
3352
|
+
<div class="col-span-2">
|
|
3353
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3354
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3355
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ getUsageBalance(usage) }}</span>
|
|
3356
|
+
<div class="w-full flex items-center gap-x-2">
|
|
3357
|
+
<div class="w-full max-w-[24rem] h-[6px] my-[6px] bg-[var(--cp-section-usage-bar-track-color,#E4E4E7)] flex items-center justify-start rounded overflow-hidden">
|
|
3358
|
+
<div class="h-[6px] rounded" [style.width.%]="getUsagePercent(usage)" [style.backgroundColor]="'var(--cp-section-usage-bar-color)'"></div>
|
|
3359
|
+
</div>
|
|
3360
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3361
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3362
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ getUsageText(usage) }}</span>
|
|
3363
|
+
</div>
|
|
3364
|
+
</div>
|
|
3365
|
+
</div>
|
|
3366
|
+
|
|
3367
|
+
<!-- Expand Icon -->
|
|
3368
|
+
<div class="transform transition-transform duration-200"
|
|
3369
|
+
[class.rotate-180]="isExpanded(usage.id)"
|
|
3370
|
+
[style.color]="'var(--cp-table-expand-icon-color, #71717a)'">
|
|
3371
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"></path></svg>
|
|
3372
|
+
</div>
|
|
3373
|
+
</div>
|
|
3374
|
+
|
|
3375
|
+
<!-- Expanded Content (Pools) -->
|
|
3376
|
+
@if (isExpanded(usage.id)) {
|
|
3377
|
+
<div class="w-full rounded-lg overflow-hidden flex flex-col items-start justify-start gap-y-0 pt-4">
|
|
3378
|
+
@for (pool of getProcessedPools(usage); track pool.pool) {
|
|
3379
|
+
<div class="w-full flex items-center px-2 py-3 gap-x-12 sm:gap-x-20 md:gap-x-40">
|
|
3380
|
+
<span class="w-20 text-[var(--cp-table-text)]"
|
|
3381
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3382
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ pool.pool }}</span>
|
|
3383
|
+
<div class="flex-1">
|
|
3384
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3385
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3386
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3387
|
+
@if (!pool.isUnlimited) {
|
|
3388
|
+
@if (pool.balance < 0) {
|
|
3389
|
+
{{ _formatNumber(Math.abs(pool.balance)) }} used above limit
|
|
3390
|
+
} @else {
|
|
3391
|
+
{{ _formatNumber(pool.balance) }} left
|
|
3392
|
+
}
|
|
3393
|
+
}
|
|
3394
|
+
</span>
|
|
3395
|
+
<div class="w-full flex items-center gap-x-2">
|
|
3396
|
+
<div class="w-full max-w-[18rem] h-[6px] my-[6px] bg-[var(--cp-section-usage-bar-track-color,#E4E4E7)] flex items-center justify-start rounded overflow-hidden">
|
|
3397
|
+
<div class="h-[6px]" [style.width.%]="pool.percent" [style.backgroundColor]="'var(--cp-section-usage-bar-color)'"></div>
|
|
3398
|
+
</div>
|
|
3399
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3400
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3401
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3402
|
+
@if (pool.isUnlimited) {
|
|
3403
|
+
{{ _formatNumber(pool.used) }}/ Unlimited
|
|
3404
|
+
} @else {
|
|
3405
|
+
{{ _formatNumber(pool.used) }}/{{ _formatNumber(pool.amount) }}
|
|
3406
|
+
}
|
|
3407
|
+
</span>
|
|
3408
|
+
</div>
|
|
3409
|
+
@if (pool.nextResetAt) {
|
|
3410
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3411
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3412
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">resets on {{ pool.nextResetAt }}</span>
|
|
3413
|
+
}
|
|
3414
|
+
</div>
|
|
3415
|
+
</div>
|
|
3416
|
+
}
|
|
3417
|
+
</div>
|
|
3418
|
+
}
|
|
3419
|
+
</div>
|
|
3420
|
+
}
|
|
3421
|
+
} @else {
|
|
3422
|
+
<div class="flex flex-col items-center gap-y-3 py-12">
|
|
3423
|
+
<span [innerHTML]="_getIcon('noteEmpty')"></span>
|
|
3424
|
+
<span class="text-sm text-[var(--cp-section-empty-text)]">No metered entitlements attached to this subscription</span>
|
|
3425
|
+
</div>
|
|
3426
|
+
}
|
|
3427
|
+
</div>
|
|
3428
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3429
|
+
}
|
|
3430
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: EntitlementUsageComponent, decorators: [{
|
|
3431
|
+
type: Component,
|
|
3432
|
+
args: [{
|
|
3433
|
+
selector: 'cp-entitlement-usage',
|
|
3434
|
+
standalone: true,
|
|
3435
|
+
imports: [CommonModule],
|
|
3436
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3437
|
+
template: `
|
|
3438
|
+
<div class="bg-transparent rounded-2xl px-3 pt-5">
|
|
3439
|
+
@if (meteredEntitlements.length > 0) {
|
|
3440
|
+
<!-- Header -->
|
|
3441
|
+
<div class="grid grid-cols-4 border-b border-[var(--cp-table-border)] gap-x-4 pr-12 bg-[var(--cp-table-header-bg)]"
|
|
3442
|
+
[style.padding]="'var(--cp-table-cell-padding, 0.75rem 1.5rem)'">
|
|
3443
|
+
<div class="text-[var(--cp-table-header-text)]"
|
|
3444
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3445
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Feature</div>
|
|
3446
|
+
<div class="text-[var(--cp-table-header-text)]"
|
|
3447
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3448
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Type</div>
|
|
3449
|
+
<div class="col-span-2 text-[var(--cp-table-header-text)]"
|
|
3450
|
+
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3451
|
+
[style.fontWeight]="'var(--cp-table-header-weight)'">Usage</div>
|
|
3452
|
+
</div>
|
|
3453
|
+
|
|
3454
|
+
<!-- Rows -->
|
|
3455
|
+
@for (usage of meteredEntitlements; track usage.id || $index; let rowIdx = $index) {
|
|
3456
|
+
<div class="border-b border-[var(--cp-table-border)] last:border-0"
|
|
3457
|
+
[class]="rowIdx % 2 === 0 ? 'bg-[var(--cp-table-row-even-bg)]' : 'bg-[var(--cp-table-row-odd-bg)]'"
|
|
3458
|
+
[style.padding]="'var(--cp-table-cell-padding, 1rem 1.5rem)'">
|
|
3459
|
+
<!-- Main Row (Collapsible Trigger) -->
|
|
3460
|
+
<div class="flex items-center cursor-pointer" (click)="toggleExpand(usage.id)">
|
|
3461
|
+
<div class="flex-1 grid grid-cols-4 gap-4 items-center pr-8">
|
|
3462
|
+
<!-- Feature -->
|
|
3463
|
+
<div class="flex flex-col gap-y-1 items-start max-w-[120px] text-balance">
|
|
3464
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3465
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3466
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ usage.feature_name || '-' }}</span>
|
|
3467
|
+
<span class="text-[var(--cp-table-text)] max-w-[120px] truncate"
|
|
3468
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3469
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ usage.feature_key }}</span>
|
|
3470
|
+
</div>
|
|
3471
|
+
|
|
3472
|
+
<!-- Type -->
|
|
3473
|
+
<div>
|
|
3474
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3475
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3476
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ _capitalize(usage.type?.split('_').join(' ') || '') }}</span>
|
|
3477
|
+
</div>
|
|
3478
|
+
|
|
3479
|
+
<!-- Usage -->
|
|
3480
|
+
<div class="col-span-2">
|
|
3481
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3482
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3483
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ getUsageBalance(usage) }}</span>
|
|
3484
|
+
<div class="w-full flex items-center gap-x-2">
|
|
3485
|
+
<div class="w-full max-w-[24rem] h-[6px] my-[6px] bg-[var(--cp-section-usage-bar-track-color,#E4E4E7)] flex items-center justify-start rounded overflow-hidden">
|
|
3486
|
+
<div class="h-[6px] rounded" [style.width.%]="getUsagePercent(usage)" [style.backgroundColor]="'var(--cp-section-usage-bar-color)'"></div>
|
|
3487
|
+
</div>
|
|
3488
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3489
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3490
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ getUsageText(usage) }}</span>
|
|
3491
|
+
</div>
|
|
3492
|
+
</div>
|
|
3493
|
+
</div>
|
|
3494
|
+
|
|
3495
|
+
<!-- Expand Icon -->
|
|
3496
|
+
<div class="transform transition-transform duration-200"
|
|
3497
|
+
[class.rotate-180]="isExpanded(usage.id)"
|
|
3498
|
+
[style.color]="'var(--cp-table-expand-icon-color, #71717a)'">
|
|
3499
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"></path></svg>
|
|
3500
|
+
</div>
|
|
3501
|
+
</div>
|
|
3502
|
+
|
|
3503
|
+
<!-- Expanded Content (Pools) -->
|
|
3504
|
+
@if (isExpanded(usage.id)) {
|
|
3505
|
+
<div class="w-full rounded-lg overflow-hidden flex flex-col items-start justify-start gap-y-0 pt-4">
|
|
3506
|
+
@for (pool of getProcessedPools(usage); track pool.pool) {
|
|
3507
|
+
<div class="w-full flex items-center px-2 py-3 gap-x-12 sm:gap-x-20 md:gap-x-40">
|
|
3508
|
+
<span class="w-20 text-[var(--cp-table-text)]"
|
|
3509
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3510
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ pool.pool }}</span>
|
|
3511
|
+
<div class="flex-1">
|
|
3512
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3513
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3514
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3515
|
+
@if (!pool.isUnlimited) {
|
|
3516
|
+
@if (pool.balance < 0) {
|
|
3517
|
+
{{ _formatNumber(Math.abs(pool.balance)) }} used above limit
|
|
3518
|
+
} @else {
|
|
3519
|
+
{{ _formatNumber(pool.balance) }} left
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3522
|
+
</span>
|
|
3523
|
+
<div class="w-full flex items-center gap-x-2">
|
|
3524
|
+
<div class="w-full max-w-[18rem] h-[6px] my-[6px] bg-[var(--cp-section-usage-bar-track-color,#E4E4E7)] flex items-center justify-start rounded overflow-hidden">
|
|
3525
|
+
<div class="h-[6px]" [style.width.%]="pool.percent" [style.backgroundColor]="'var(--cp-section-usage-bar-color)'"></div>
|
|
3526
|
+
</div>
|
|
3527
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3528
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3529
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3530
|
+
@if (pool.isUnlimited) {
|
|
3531
|
+
{{ _formatNumber(pool.used) }}/ Unlimited
|
|
3532
|
+
} @else {
|
|
3533
|
+
{{ _formatNumber(pool.used) }}/{{ _formatNumber(pool.amount) }}
|
|
3534
|
+
}
|
|
3535
|
+
</span>
|
|
3536
|
+
</div>
|
|
3537
|
+
@if (pool.nextResetAt) {
|
|
3538
|
+
<span class="text-[var(--cp-table-text)]"
|
|
3539
|
+
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3540
|
+
[style.fontWeight]="'var(--cp-table-row-weight)'">resets on {{ pool.nextResetAt }}</span>
|
|
3541
|
+
}
|
|
3542
|
+
</div>
|
|
3543
|
+
</div>
|
|
3544
|
+
}
|
|
3545
|
+
</div>
|
|
3546
|
+
}
|
|
3547
|
+
</div>
|
|
3548
|
+
}
|
|
3549
|
+
} @else {
|
|
3550
|
+
<div class="flex flex-col items-center gap-y-3 py-12">
|
|
3551
|
+
<span [innerHTML]="_getIcon('noteEmpty')"></span>
|
|
3552
|
+
<span class="text-sm text-[var(--cp-section-empty-text)]">No metered entitlements attached to this subscription</span>
|
|
3553
|
+
</div>
|
|
3554
|
+
}
|
|
3555
|
+
</div>
|
|
3556
|
+
`
|
|
3557
|
+
}]
|
|
3558
|
+
}], propDecorators: { entitlementUsage: [{
|
|
3559
|
+
type: Input
|
|
3560
|
+
}] } });
|
|
3561
|
+
|
|
3562
|
+
class EntitlementsSectionComponent {
|
|
3563
|
+
entitlementSummary = [];
|
|
3564
|
+
entitlementUsage = [];
|
|
3565
|
+
sectionsConfig;
|
|
3566
|
+
entitlementTab = signal('summary');
|
|
3567
|
+
get hasMeteredEntitlements() {
|
|
3568
|
+
return (this.entitlementUsage || []).some((usage) => usage.type !== 'boolean');
|
|
3046
3569
|
}
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
return
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
year: 'numeric',
|
|
3056
|
-
hour: 'numeric',
|
|
3057
|
-
minute: '2-digit',
|
|
3058
|
-
hour12: true,
|
|
3059
|
-
})
|
|
3060
|
-
.toLowerCase();
|
|
3570
|
+
_isSectionHidden(key) {
|
|
3571
|
+
return isSectionHidden(this.sectionsConfig, key);
|
|
3572
|
+
}
|
|
3573
|
+
_getSectionLabel(key) {
|
|
3574
|
+
return getSectionLabel(this.sectionsConfig, key);
|
|
3575
|
+
}
|
|
3576
|
+
changeEntitlementTab(tab) {
|
|
3577
|
+
this.entitlementTab.set(tab);
|
|
3061
3578
|
}
|
|
3062
3579
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: EntitlementsSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3063
3580
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: EntitlementsSectionComponent, isStandalone: true, selector: "cp-entitlements-section", inputs: { entitlementSummary: "entitlementSummary", entitlementUsage: "entitlementUsage", sectionsConfig: "sectionsConfig" }, ngImport: i0, template: `
|
|
@@ -3089,7 +3606,7 @@ class EntitlementsSectionComponent {
|
|
|
3089
3606
|
(click)="changeEntitlementTab('summary')">
|
|
3090
3607
|
Summary
|
|
3091
3608
|
</button>
|
|
3092
|
-
@if (
|
|
3609
|
+
@if (hasMeteredEntitlements) {
|
|
3093
3610
|
<button
|
|
3094
3611
|
type="button"
|
|
3095
3612
|
class="px-6 py-1.5 rounded-md text-sm font-medium transition-all outline-none"
|
|
@@ -3104,188 +3621,24 @@ class EntitlementsSectionComponent {
|
|
|
3104
3621
|
|
|
3105
3622
|
<!-- Summary Tab Content -->
|
|
3106
3623
|
@if (entitlementTab() === 'summary') {
|
|
3107
|
-
<
|
|
3108
|
-
@if (entitlementSummary.length > 0) {
|
|
3109
|
-
<table class="min-w-full border-collapse text-left relative">
|
|
3110
|
-
<thead>
|
|
3111
|
-
<tr>
|
|
3112
|
-
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3113
|
-
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3114
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3115
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Feature</th>
|
|
3116
|
-
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3117
|
-
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3118
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3119
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Meter type</th>
|
|
3120
|
-
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3121
|
-
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3122
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3123
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Included allowance</th>
|
|
3124
|
-
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3125
|
-
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3126
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3127
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Usage limits</th>
|
|
3128
|
-
</tr>
|
|
3129
|
-
</thead>
|
|
3130
|
-
<tbody>
|
|
3131
|
-
@for (entitlement of entitlementSummary; track entitlement.id || $index; let rowIdx = $index) {
|
|
3132
|
-
<tr [class]="rowIdx % 2 === 0 ? 'bg-[var(--cp-table-row-even-bg)]' : 'bg-[var(--cp-table-row-odd-bg)]'">
|
|
3133
|
-
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3134
|
-
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3135
|
-
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3136
|
-
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3137
|
-
<div class="flex flex-col gap-y-1 items-start max-w-[130px]">
|
|
3138
|
-
<span>{{ entitlement.feature_name || '-' }}</span>
|
|
3139
|
-
<span class="text-xs bg-gray-100 text-gray-800 px-2 py-0.5 rounded max-w-[120px] truncate">{{ entitlement.feature_key }}</span>
|
|
3140
|
-
</div>
|
|
3141
|
-
</td>
|
|
3142
|
-
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3143
|
-
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3144
|
-
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3145
|
-
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3146
|
-
<div>
|
|
3147
|
-
<span>{{ _capitalize(entitlement.feature_type) }}</span>
|
|
3148
|
-
@if (entitlement.usage_model) {
|
|
3149
|
-
<span class="block mt-1">{{ formatUsageModel(entitlement) }}</span>
|
|
3150
|
-
}
|
|
3151
|
-
</div>
|
|
3152
|
-
</td>
|
|
3153
|
-
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3154
|
-
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3155
|
-
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3156
|
-
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3157
|
-
{{ formatIncludedAllowance(entitlement) }}
|
|
3158
|
-
</td>
|
|
3159
|
-
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3160
|
-
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3161
|
-
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3162
|
-
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3163
|
-
{{ formatUsageLimits(entitlement) }}
|
|
3164
|
-
</td>
|
|
3165
|
-
</tr>
|
|
3166
|
-
}
|
|
3167
|
-
</tbody>
|
|
3168
|
-
</table>
|
|
3169
|
-
} @else {
|
|
3170
|
-
<div class="flex flex-col items-center gap-y-3 py-12">
|
|
3171
|
-
<span [innerHTML]="_getIcon('noteEmpty')"></span>
|
|
3172
|
-
<span class="text-sm text-[var(--cp-section-empty-text)]">No entitlements attached to this subscription</span>
|
|
3173
|
-
</div>
|
|
3174
|
-
}
|
|
3175
|
-
</div>
|
|
3624
|
+
<cp-entitlement-summary [entitlementSummary]="entitlementSummary"></cp-entitlement-summary>
|
|
3176
3625
|
}
|
|
3177
3626
|
|
|
3178
3627
|
<!-- Usage Tab Content -->
|
|
3179
3628
|
@if (entitlementTab() === 'usage') {
|
|
3180
|
-
<
|
|
3181
|
-
@if (getMeteredEntitlements().length > 0) {
|
|
3182
|
-
<!-- Header -->
|
|
3183
|
-
<div class="grid grid-cols-4 border-b border-[var(--cp-table-border)] gap-x-4 py-3 pl-3 pr-12 bg-[var(--cp-table-header-bg)]">
|
|
3184
|
-
<div class="text-[var(--cp-table-header-text)]"
|
|
3185
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3186
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Feature</div>
|
|
3187
|
-
<div class="text-[var(--cp-table-header-text)]"
|
|
3188
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3189
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Type</div>
|
|
3190
|
-
<div class="col-span-2 text-[var(--cp-table-header-text)]"
|
|
3191
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3192
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Usage</div>
|
|
3193
|
-
</div>
|
|
3194
|
-
|
|
3195
|
-
<!-- Rows -->
|
|
3196
|
-
@for (usage of getMeteredEntitlements(); track usage.id || $index) {
|
|
3197
|
-
<div class="py-4 px-4 border-b border-[var(--cp-table-border)] last:border-0">
|
|
3198
|
-
<!-- Main Row (Collapsible Trigger) -->
|
|
3199
|
-
<div class="flex items-center cursor-pointer" (click)="toggleEntitlementExpand(usage.id)">
|
|
3200
|
-
<div class="flex-1 grid grid-cols-4 gap-4 items-center pr-8">
|
|
3201
|
-
<!-- Feature -->
|
|
3202
|
-
<div class="flex flex-col gap-y-1 items-start max-w-[120px]">
|
|
3203
|
-
<span class="text-[13px] leading-[120%] text-[var(--cp-table-text)]">{{ usage.feature_name || '-' }}</span>
|
|
3204
|
-
<span class="text-xs bg-gray-100 text-gray-800 px-2 py-0.5 rounded max-w-[120px] truncate">{{ usage.feature_key }}</span>
|
|
3205
|
-
</div>
|
|
3206
|
-
|
|
3207
|
-
<!-- Type -->
|
|
3208
|
-
<div>
|
|
3209
|
-
<span class="text-xs text-[var(--cp-link-color)]">{{ _capitalize(usage.type?.split('_').join(' ') || '') }}</span>
|
|
3210
|
-
</div>
|
|
3211
|
-
|
|
3212
|
-
<!-- Usage -->
|
|
3213
|
-
<div class="col-span-2">
|
|
3214
|
-
<span class="text-[13px] leading-[120%] text-[var(--cp-table-text)]">{{ getEntitlementUsageBalance(usage) }}</span>
|
|
3215
|
-
<div class="flex items-center gap-x-2">
|
|
3216
|
-
<div class="w-96 h-1.5 my-1.5 bg-[var(--cp-section-usage-bar-track-color,#E4E4E7)] flex items-start justify-start rounded overflow-hidden">
|
|
3217
|
-
<div class="h-1.5 bg-[var(--cp-section-usage-bar-color,#006FEE)] rounded" [style.width.%]="getEntitlementUsagePercent(usage)"></div>
|
|
3218
|
-
</div>
|
|
3219
|
-
<span class="text-[var(--cp-table-text)]"
|
|
3220
|
-
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3221
|
-
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ getEntitlementUsageText(usage) }}</span>
|
|
3222
|
-
</div>
|
|
3223
|
-
</div>
|
|
3224
|
-
</div>
|
|
3225
|
-
|
|
3226
|
-
<!-- Expand Icon -->
|
|
3227
|
-
<div class="transform transition-transform duration-200" [class.rotate-180]="isEntitlementExpanded(usage.id)">
|
|
3228
|
-
<span [innerHTML]="_getIcon('arrowDown')"></span>
|
|
3229
|
-
</div>
|
|
3230
|
-
</div>
|
|
3231
|
-
|
|
3232
|
-
<!-- Expanded Content (Pools) -->
|
|
3233
|
-
@if (isEntitlementExpanded(usage.id)) {
|
|
3234
|
-
<div class="w-full rounded-lg overflow-hidden flex flex-col items-start justify-start gap-y-0 pt-4">
|
|
3235
|
-
@for (pool of getProcessedPools(usage); track pool.pool) {
|
|
3236
|
-
<div class="w-full flex items-center px-6 py-3 gap-x-40">
|
|
3237
|
-
<span class="text-[13px] leading-[120%] text-[var(--cp-table-text)] w-20">{{ pool.pool }}</span>
|
|
3238
|
-
<div>
|
|
3239
|
-
<span class="text-[13px] leading-[120%] text-[var(--cp-table-text)]">
|
|
3240
|
-
@if (!pool.isUnlimited) {
|
|
3241
|
-
@if (pool.balance < 0) {
|
|
3242
|
-
{{ _formatNumber(Math.abs(pool.balance)) }} used above limit
|
|
3243
|
-
} @else {
|
|
3244
|
-
{{ _formatNumber(pool.balance) }} left
|
|
3245
|
-
}
|
|
3246
|
-
}
|
|
3247
|
-
</span>
|
|
3248
|
-
<div class="flex items-center gap-x-2">
|
|
3249
|
-
<div class="w-72 h-1.5 my-1.5 bg-[var(--cp-section-usage-bar-track-color,#E4E4E7)] flex items-start justify-start rounded overflow-hidden">
|
|
3250
|
-
<div class="h-1.5 rounded" [class]="'bg-' + pool.color" [style.width.%]="pool.percent"></div>
|
|
3251
|
-
</div>
|
|
3252
|
-
<span class="text-[13px] leading-[120%] text-[var(--cp-table-text)]">
|
|
3253
|
-
@if (pool.isUnlimited) {
|
|
3254
|
-
{{ _formatNumber(pool.used) }}/ Unlimited
|
|
3255
|
-
} @else {
|
|
3256
|
-
{{ _formatNumber(pool.used) }}/{{ _formatNumber(pool.amount) }}
|
|
3257
|
-
}
|
|
3258
|
-
</span>
|
|
3259
|
-
</div>
|
|
3260
|
-
@if (pool.nextResetAt) {
|
|
3261
|
-
<span class="text-[13px] leading-[120%] text-[var(--cp-table-text)]">resets on {{ pool.nextResetAt }}</span>
|
|
3262
|
-
}
|
|
3263
|
-
</div>
|
|
3264
|
-
</div>
|
|
3265
|
-
}
|
|
3266
|
-
</div>
|
|
3267
|
-
}
|
|
3268
|
-
</div>
|
|
3269
|
-
}
|
|
3270
|
-
} @else {
|
|
3271
|
-
<div class="flex flex-col items-center gap-y-3 py-12">
|
|
3272
|
-
<span [innerHTML]="_getIcon('noteEmpty')"></span>
|
|
3273
|
-
<span class="text-sm text-[var(--cp-section-empty-text)]">No metered entitlements attached to this subscription</span>
|
|
3274
|
-
</div>
|
|
3275
|
-
}
|
|
3276
|
-
</div>
|
|
3629
|
+
<cp-entitlement-usage [entitlementUsage]="entitlementUsage"></cp-entitlement-usage>
|
|
3277
3630
|
}
|
|
3278
3631
|
</div>
|
|
3279
3632
|
</div>
|
|
3280
3633
|
}
|
|
3281
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3634
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: EntitlementSummaryComponent, selector: "cp-entitlement-summary", inputs: ["entitlementSummary"] }, { kind: "component", type: EntitlementUsageComponent, selector: "cp-entitlement-usage", inputs: ["entitlementUsage"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3282
3635
|
}
|
|
3283
3636
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: EntitlementsSectionComponent, decorators: [{
|
|
3284
3637
|
type: Component,
|
|
3285
3638
|
args: [{
|
|
3286
3639
|
selector: 'cp-entitlements-section',
|
|
3287
3640
|
standalone: true,
|
|
3288
|
-
imports: [CommonModule],
|
|
3641
|
+
imports: [CommonModule, EntitlementSummaryComponent, EntitlementUsageComponent],
|
|
3289
3642
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3290
3643
|
template: `
|
|
3291
3644
|
@if (!_isSectionHidden('entitlementUsage')) {
|
|
@@ -3316,7 +3669,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
3316
3669
|
(click)="changeEntitlementTab('summary')">
|
|
3317
3670
|
Summary
|
|
3318
3671
|
</button>
|
|
3319
|
-
@if (
|
|
3672
|
+
@if (hasMeteredEntitlements) {
|
|
3320
3673
|
<button
|
|
3321
3674
|
type="button"
|
|
3322
3675
|
class="px-6 py-1.5 rounded-md text-sm font-medium transition-all outline-none"
|
|
@@ -3331,181 +3684,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
3331
3684
|
|
|
3332
3685
|
<!-- Summary Tab Content -->
|
|
3333
3686
|
@if (entitlementTab() === 'summary') {
|
|
3334
|
-
<
|
|
3335
|
-
@if (entitlementSummary.length > 0) {
|
|
3336
|
-
<table class="min-w-full border-collapse text-left relative">
|
|
3337
|
-
<thead>
|
|
3338
|
-
<tr>
|
|
3339
|
-
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3340
|
-
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3341
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3342
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Feature</th>
|
|
3343
|
-
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3344
|
-
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3345
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3346
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Meter type</th>
|
|
3347
|
-
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3348
|
-
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3349
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3350
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Included allowance</th>
|
|
3351
|
-
<th class="text-[var(--cp-table-header-text)] bg-[var(--cp-table-header-bg)] border-b border-[var(--cp-table-border)] whitespace-nowrap"
|
|
3352
|
-
[style.padding]="'var(--cp-table-cell-padding, 0.5rem 0.75rem)'"
|
|
3353
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3354
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Usage limits</th>
|
|
3355
|
-
</tr>
|
|
3356
|
-
</thead>
|
|
3357
|
-
<tbody>
|
|
3358
|
-
@for (entitlement of entitlementSummary; track entitlement.id || $index; let rowIdx = $index) {
|
|
3359
|
-
<tr [class]="rowIdx % 2 === 0 ? 'bg-[var(--cp-table-row-even-bg)]' : 'bg-[var(--cp-table-row-odd-bg)]'">
|
|
3360
|
-
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3361
|
-
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3362
|
-
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3363
|
-
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3364
|
-
<div class="flex flex-col gap-y-1 items-start max-w-[130px]">
|
|
3365
|
-
<span>{{ entitlement.feature_name || '-' }}</span>
|
|
3366
|
-
<span class="text-xs bg-gray-100 text-gray-800 px-2 py-0.5 rounded max-w-[120px] truncate">{{ entitlement.feature_key }}</span>
|
|
3367
|
-
</div>
|
|
3368
|
-
</td>
|
|
3369
|
-
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3370
|
-
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3371
|
-
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3372
|
-
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3373
|
-
<div>
|
|
3374
|
-
<span>{{ _capitalize(entitlement.feature_type) }}</span>
|
|
3375
|
-
@if (entitlement.usage_model) {
|
|
3376
|
-
<span class="block mt-1">{{ formatUsageModel(entitlement) }}</span>
|
|
3377
|
-
}
|
|
3378
|
-
</div>
|
|
3379
|
-
</td>
|
|
3380
|
-
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3381
|
-
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3382
|
-
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3383
|
-
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3384
|
-
{{ formatIncludedAllowance(entitlement) }}
|
|
3385
|
-
</td>
|
|
3386
|
-
<td class="text-[var(--cp-table-text)] border-y border-[var(--cp-table-border)]"
|
|
3387
|
-
[style.padding]="'var(--cp-table-cell-padding, 1rem 0.75rem)'"
|
|
3388
|
-
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3389
|
-
[style.fontWeight]="'var(--cp-table-row-weight)'">
|
|
3390
|
-
{{ formatUsageLimits(entitlement) }}
|
|
3391
|
-
</td>
|
|
3392
|
-
</tr>
|
|
3393
|
-
}
|
|
3394
|
-
</tbody>
|
|
3395
|
-
</table>
|
|
3396
|
-
} @else {
|
|
3397
|
-
<div class="flex flex-col items-center gap-y-3 py-12">
|
|
3398
|
-
<span [innerHTML]="_getIcon('noteEmpty')"></span>
|
|
3399
|
-
<span class="text-sm text-[var(--cp-section-empty-text)]">No entitlements attached to this subscription</span>
|
|
3400
|
-
</div>
|
|
3401
|
-
}
|
|
3402
|
-
</div>
|
|
3687
|
+
<cp-entitlement-summary [entitlementSummary]="entitlementSummary"></cp-entitlement-summary>
|
|
3403
3688
|
}
|
|
3404
3689
|
|
|
3405
3690
|
<!-- Usage Tab Content -->
|
|
3406
3691
|
@if (entitlementTab() === 'usage') {
|
|
3407
|
-
<
|
|
3408
|
-
@if (getMeteredEntitlements().length > 0) {
|
|
3409
|
-
<!-- Header -->
|
|
3410
|
-
<div class="grid grid-cols-4 border-b border-[var(--cp-table-border)] gap-x-4 py-3 pl-3 pr-12 bg-[var(--cp-table-header-bg)]">
|
|
3411
|
-
<div class="text-[var(--cp-table-header-text)]"
|
|
3412
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3413
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Feature</div>
|
|
3414
|
-
<div class="text-[var(--cp-table-header-text)]"
|
|
3415
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3416
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Type</div>
|
|
3417
|
-
<div class="col-span-2 text-[var(--cp-table-header-text)]"
|
|
3418
|
-
[style.fontSize]="'var(--cp-table-header-size)'"
|
|
3419
|
-
[style.fontWeight]="'var(--cp-table-header-weight)'">Usage</div>
|
|
3420
|
-
</div>
|
|
3421
|
-
|
|
3422
|
-
<!-- Rows -->
|
|
3423
|
-
@for (usage of getMeteredEntitlements(); track usage.id || $index) {
|
|
3424
|
-
<div class="py-4 px-4 border-b border-[var(--cp-table-border)] last:border-0">
|
|
3425
|
-
<!-- Main Row (Collapsible Trigger) -->
|
|
3426
|
-
<div class="flex items-center cursor-pointer" (click)="toggleEntitlementExpand(usage.id)">
|
|
3427
|
-
<div class="flex-1 grid grid-cols-4 gap-4 items-center pr-8">
|
|
3428
|
-
<!-- Feature -->
|
|
3429
|
-
<div class="flex flex-col gap-y-1 items-start max-w-[120px]">
|
|
3430
|
-
<span class="text-[13px] leading-[120%] text-[var(--cp-table-text)]">{{ usage.feature_name || '-' }}</span>
|
|
3431
|
-
<span class="text-xs bg-gray-100 text-gray-800 px-2 py-0.5 rounded max-w-[120px] truncate">{{ usage.feature_key }}</span>
|
|
3432
|
-
</div>
|
|
3433
|
-
|
|
3434
|
-
<!-- Type -->
|
|
3435
|
-
<div>
|
|
3436
|
-
<span class="text-xs text-[var(--cp-link-color)]">{{ _capitalize(usage.type?.split('_').join(' ') || '') }}</span>
|
|
3437
|
-
</div>
|
|
3438
|
-
|
|
3439
|
-
<!-- Usage -->
|
|
3440
|
-
<div class="col-span-2">
|
|
3441
|
-
<span class="text-[13px] leading-[120%] text-[var(--cp-table-text)]">{{ getEntitlementUsageBalance(usage) }}</span>
|
|
3442
|
-
<div class="flex items-center gap-x-2">
|
|
3443
|
-
<div class="w-96 h-1.5 my-1.5 bg-[var(--cp-section-usage-bar-track-color,#E4E4E7)] flex items-start justify-start rounded overflow-hidden">
|
|
3444
|
-
<div class="h-1.5 bg-[var(--cp-section-usage-bar-color,#006FEE)] rounded" [style.width.%]="getEntitlementUsagePercent(usage)"></div>
|
|
3445
|
-
</div>
|
|
3446
|
-
<span class="text-[var(--cp-table-text)]"
|
|
3447
|
-
[style.fontSize]="'var(--cp-table-row-size)'"
|
|
3448
|
-
[style.fontWeight]="'var(--cp-table-row-weight)'">{{ getEntitlementUsageText(usage) }}</span>
|
|
3449
|
-
</div>
|
|
3450
|
-
</div>
|
|
3451
|
-
</div>
|
|
3452
|
-
|
|
3453
|
-
<!-- Expand Icon -->
|
|
3454
|
-
<div class="transform transition-transform duration-200" [class.rotate-180]="isEntitlementExpanded(usage.id)">
|
|
3455
|
-
<span [innerHTML]="_getIcon('arrowDown')"></span>
|
|
3456
|
-
</div>
|
|
3457
|
-
</div>
|
|
3458
|
-
|
|
3459
|
-
<!-- Expanded Content (Pools) -->
|
|
3460
|
-
@if (isEntitlementExpanded(usage.id)) {
|
|
3461
|
-
<div class="w-full rounded-lg overflow-hidden flex flex-col items-start justify-start gap-y-0 pt-4">
|
|
3462
|
-
@for (pool of getProcessedPools(usage); track pool.pool) {
|
|
3463
|
-
<div class="w-full flex items-center px-6 py-3 gap-x-40">
|
|
3464
|
-
<span class="text-[13px] leading-[120%] text-[var(--cp-table-text)] w-20">{{ pool.pool }}</span>
|
|
3465
|
-
<div>
|
|
3466
|
-
<span class="text-[13px] leading-[120%] text-[var(--cp-table-text)]">
|
|
3467
|
-
@if (!pool.isUnlimited) {
|
|
3468
|
-
@if (pool.balance < 0) {
|
|
3469
|
-
{{ _formatNumber(Math.abs(pool.balance)) }} used above limit
|
|
3470
|
-
} @else {
|
|
3471
|
-
{{ _formatNumber(pool.balance) }} left
|
|
3472
|
-
}
|
|
3473
|
-
}
|
|
3474
|
-
</span>
|
|
3475
|
-
<div class="flex items-center gap-x-2">
|
|
3476
|
-
<div class="w-72 h-1.5 my-1.5 bg-[var(--cp-section-usage-bar-track-color,#E4E4E7)] flex items-start justify-start rounded overflow-hidden">
|
|
3477
|
-
<div class="h-1.5 rounded" [class]="'bg-' + pool.color" [style.width.%]="pool.percent"></div>
|
|
3478
|
-
</div>
|
|
3479
|
-
<span class="text-[13px] leading-[120%] text-[var(--cp-table-text)]">
|
|
3480
|
-
@if (pool.isUnlimited) {
|
|
3481
|
-
{{ _formatNumber(pool.used) }}/ Unlimited
|
|
3482
|
-
} @else {
|
|
3483
|
-
{{ _formatNumber(pool.used) }}/{{ _formatNumber(pool.amount) }}
|
|
3484
|
-
}
|
|
3485
|
-
</span>
|
|
3486
|
-
</div>
|
|
3487
|
-
@if (pool.nextResetAt) {
|
|
3488
|
-
<span class="text-[13px] leading-[120%] text-[var(--cp-table-text)]">resets on {{ pool.nextResetAt }}</span>
|
|
3489
|
-
}
|
|
3490
|
-
</div>
|
|
3491
|
-
</div>
|
|
3492
|
-
}
|
|
3493
|
-
</div>
|
|
3494
|
-
}
|
|
3495
|
-
</div>
|
|
3496
|
-
}
|
|
3497
|
-
} @else {
|
|
3498
|
-
<div class="flex flex-col items-center gap-y-3 py-12">
|
|
3499
|
-
<span [innerHTML]="_getIcon('noteEmpty')"></span>
|
|
3500
|
-
<span class="text-sm text-[var(--cp-section-empty-text)]">No metered entitlements attached to this subscription</span>
|
|
3501
|
-
</div>
|
|
3502
|
-
}
|
|
3503
|
-
</div>
|
|
3692
|
+
<cp-entitlement-usage [entitlementUsage]="entitlementUsage"></cp-entitlement-usage>
|
|
3504
3693
|
}
|
|
3505
3694
|
</div>
|
|
3506
3695
|
</div>
|
|
3507
3696
|
}
|
|
3508
|
-
|
|
3697
|
+
`
|
|
3509
3698
|
}]
|
|
3510
3699
|
}], propDecorators: { entitlementSummary: [{
|
|
3511
3700
|
type: Input
|
|
@@ -3696,7 +3885,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
3696
3885
|
</div>
|
|
3697
3886
|
</div>
|
|
3698
3887
|
}
|
|
3699
|
-
|
|
3888
|
+
`
|
|
3700
3889
|
}]
|
|
3701
3890
|
}], propDecorators: { subscription: [{
|
|
3702
3891
|
type: Input
|
|
@@ -3927,7 +4116,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
3927
4116
|
</div>
|
|
3928
4117
|
</div>
|
|
3929
4118
|
}
|
|
3930
|
-
|
|
4119
|
+
`
|
|
3931
4120
|
}]
|
|
3932
4121
|
}], propDecorators: { billingHistory: [{
|
|
3933
4122
|
type: Input
|
|
@@ -3973,7 +4162,7 @@ class PlansSectionComponent {
|
|
|
3973
4162
|
monthly: 'Monthly',
|
|
3974
4163
|
quarterly: 'Quarterly',
|
|
3975
4164
|
biannually: 'Biannually',
|
|
3976
|
-
yearly: 'Yearly'
|
|
4165
|
+
yearly: 'Yearly'
|
|
3977
4166
|
};
|
|
3978
4167
|
return labels[interval] || capitalize(interval);
|
|
3979
4168
|
}
|
|
@@ -3981,36 +4170,40 @@ class PlansSectionComponent {
|
|
|
3981
4170
|
const allPriceOptions = [
|
|
3982
4171
|
...(plan.price_options || []),
|
|
3983
4172
|
...(plan.entitlement_price_options || []),
|
|
3984
|
-
...(plan.credit_attachment_price_options || [])
|
|
4173
|
+
...(plan.credit_attachment_price_options || [])
|
|
3985
4174
|
];
|
|
3986
4175
|
return allPriceOptions.find((po) => po.price?.billing_interval === this.selectedPlanInterval());
|
|
3987
4176
|
}
|
|
3988
4177
|
getPlanPriceInteger(plan) {
|
|
3989
4178
|
const priceOption = this.getPlanPriceOption(plan);
|
|
3990
|
-
|
|
4179
|
+
const price = priceOption?.price;
|
|
4180
|
+
if (!price)
|
|
3991
4181
|
return 'Contact';
|
|
3992
|
-
let amount =
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
4182
|
+
let amount = price.price;
|
|
4183
|
+
const tiers = price.tiers;
|
|
4184
|
+
if (tiers && tiers.length > 0) {
|
|
4185
|
+
const tier = tiers[0];
|
|
4186
|
+
amount = (tier.unit_price || tier.package_price || tier.flat_fee || 0);
|
|
3996
4187
|
}
|
|
3997
|
-
const currency =
|
|
4188
|
+
const currency = price.currency || 'USD';
|
|
3998
4189
|
const symbol = getCurrencySymbol(currency);
|
|
3999
|
-
const
|
|
4000
|
-
const amountParts =
|
|
4190
|
+
const formatted = formatPriceAmount(amount);
|
|
4191
|
+
const amountParts = formatted?.split('.');
|
|
4001
4192
|
return `${symbol}${amountParts?.[0] ?? '0'}`;
|
|
4002
4193
|
}
|
|
4003
4194
|
getPlanPriceDecimal(plan) {
|
|
4004
4195
|
const priceOption = this.getPlanPriceOption(plan);
|
|
4005
|
-
|
|
4196
|
+
const price = priceOption?.price;
|
|
4197
|
+
if (!price)
|
|
4006
4198
|
return '00';
|
|
4007
|
-
let amount =
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4199
|
+
let amount = price.price;
|
|
4200
|
+
const tiers = price.tiers;
|
|
4201
|
+
if (tiers && tiers.length > 0) {
|
|
4202
|
+
const tier = tiers[0];
|
|
4203
|
+
amount = (tier.unit_price || tier.package_price || tier.flat_fee || 0);
|
|
4011
4204
|
}
|
|
4012
|
-
const
|
|
4013
|
-
const amountParts =
|
|
4205
|
+
const formatted = formatPriceAmount(amount);
|
|
4206
|
+
const amountParts = formatted?.split('.');
|
|
4014
4207
|
return amountParts && amountParts.length > 1 ? amountParts[1].padEnd(2, '0').slice(0, 2) : '00';
|
|
4015
4208
|
}
|
|
4016
4209
|
getMultiplyNumber(interval, intervalValue) {
|
|
@@ -4021,26 +4214,29 @@ class PlansSectionComponent {
|
|
|
4021
4214
|
monthly: v,
|
|
4022
4215
|
quarterly: 3 * v,
|
|
4023
4216
|
biannually: 6 * v,
|
|
4024
|
-
yearly: 12 * v
|
|
4217
|
+
yearly: 12 * v
|
|
4025
4218
|
};
|
|
4026
4219
|
return map[interval] ?? v;
|
|
4027
4220
|
}
|
|
4028
4221
|
getPlanFixedPriceBilledAmount(plan) {
|
|
4029
4222
|
const priceOption = this.getPlanPriceOption(plan);
|
|
4030
|
-
|
|
4223
|
+
const price = priceOption?.price;
|
|
4224
|
+
if (!price)
|
|
4031
4225
|
return 0;
|
|
4032
|
-
let unitPrice =
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4226
|
+
let unitPrice = price.price;
|
|
4227
|
+
const tiers = price.tiers;
|
|
4228
|
+
if (tiers?.length) {
|
|
4229
|
+
const tier = tiers[0];
|
|
4230
|
+
unitPrice = (tier.unit_price ?? tier.package_price ?? tier.flat_fee ?? 0);
|
|
4036
4231
|
}
|
|
4037
4232
|
const interval = this.selectedPlanInterval();
|
|
4038
|
-
const intervalValue =
|
|
4233
|
+
const intervalValue = price.billing_interval_value ?? 1;
|
|
4039
4234
|
return this.getMultiplyNumber(interval, intervalValue) * (unitPrice ?? 0);
|
|
4040
4235
|
}
|
|
4041
4236
|
getPlanFixedPriceCurrencySymbol(plan) {
|
|
4042
4237
|
const po = this.getPlanPriceOption(plan);
|
|
4043
|
-
|
|
4238
|
+
const price = po?.price;
|
|
4239
|
+
return getCurrencySymbol(price?.currency || 'USD');
|
|
4044
4240
|
}
|
|
4045
4241
|
hasFixedPrice(plan) {
|
|
4046
4242
|
const interval = this.selectedPlanInterval();
|
|
@@ -4056,49 +4252,56 @@ class PlansSectionComponent {
|
|
|
4056
4252
|
const interval = this.selectedPlanInterval();
|
|
4057
4253
|
return [
|
|
4058
4254
|
...(plan.entitlement_price_options || []).filter((po) => po.price?.billing_interval === interval),
|
|
4059
|
-
...(plan.credit_attachment_price_options || []).filter((po) => po.price?.billing_interval === interval)
|
|
4255
|
+
...(plan.credit_attachment_price_options || []).filter((po) => po.price?.billing_interval === interval)
|
|
4060
4256
|
];
|
|
4061
4257
|
}
|
|
4062
4258
|
getDynamicPriceName(priceOption) {
|
|
4063
|
-
|
|
4259
|
+
const price = priceOption?.price;
|
|
4260
|
+
const owner = price?.owner;
|
|
4261
|
+
const feature = owner && 'feature' in owner ? owner.feature : undefined;
|
|
4262
|
+
return price?.name || feature?.name || owner?.name || 'Feature';
|
|
4064
4263
|
}
|
|
4065
4264
|
formatDynamicPrice(priceOption) {
|
|
4066
|
-
|
|
4265
|
+
const price = priceOption?.price;
|
|
4266
|
+
if (!price)
|
|
4067
4267
|
return '';
|
|
4068
|
-
const tiers =
|
|
4268
|
+
const tiers = price.tiers || [];
|
|
4069
4269
|
if (tiers.length === 0)
|
|
4070
4270
|
return '';
|
|
4071
4271
|
const tier = tiers[0];
|
|
4072
|
-
const currency =
|
|
4272
|
+
const currency = price.currency || 'USD';
|
|
4073
4273
|
const symbol = getCurrencySymbol(currency);
|
|
4074
|
-
const amount = tier.unit_price || tier.package_price || tier.flat_fee || 0;
|
|
4274
|
+
const amount = (tier.unit_price || tier.package_price || tier.flat_fee || 0);
|
|
4075
4275
|
const formattedAmount = formatPriceAmount(amount);
|
|
4076
|
-
const owner =
|
|
4077
|
-
const
|
|
4276
|
+
const owner = price.owner;
|
|
4277
|
+
const feature = owner && 'feature' in owner ? owner.feature : undefined;
|
|
4278
|
+
const unitLabel = feature?.unit_singular || owner?.unit_singular || feature?.name || owner?.name || '';
|
|
4078
4279
|
return unitLabel ? `${symbol}${formattedAmount}/${unitLabel}` : `${symbol}${formattedAmount}`;
|
|
4079
4280
|
}
|
|
4080
4281
|
formatDynamicPriceFull(priceOption) {
|
|
4081
|
-
|
|
4282
|
+
const price = priceOption?.price;
|
|
4283
|
+
if (!price)
|
|
4082
4284
|
return '';
|
|
4083
|
-
const tiers =
|
|
4285
|
+
const tiers = price.tiers || [];
|
|
4084
4286
|
if (tiers.length === 0)
|
|
4085
4287
|
return '';
|
|
4086
4288
|
const tier = tiers[0];
|
|
4087
|
-
const currency =
|
|
4289
|
+
const currency = price.currency || 'USD';
|
|
4088
4290
|
const symbol = getCurrencySymbol(currency);
|
|
4089
|
-
const amount = tier.unit_price || tier.package_price || tier.flat_fee || 0;
|
|
4291
|
+
const amount = (tier.unit_price || tier.package_price || tier.flat_fee || 0);
|
|
4090
4292
|
const name = this.getDynamicPriceName(priceOption);
|
|
4091
4293
|
return `${symbol}${amount.toFixed(2)}/${name}`;
|
|
4092
4294
|
}
|
|
4093
4295
|
getDynamicPriceAmountDisplay(priceOption) {
|
|
4094
|
-
|
|
4296
|
+
const price = priceOption?.price;
|
|
4297
|
+
if (!price)
|
|
4095
4298
|
return '';
|
|
4096
|
-
const tiers =
|
|
4299
|
+
const tiers = price.tiers || [];
|
|
4097
4300
|
if (tiers.length === 0)
|
|
4098
4301
|
return '';
|
|
4099
4302
|
const tier = tiers[0];
|
|
4100
|
-
const amount = tier.unit_price || tier.package_price || tier.flat_fee || 0;
|
|
4101
|
-
const currency =
|
|
4303
|
+
const amount = (tier.unit_price || tier.package_price || tier.flat_fee || 0);
|
|
4304
|
+
const currency = price.currency || 'USD';
|
|
4102
4305
|
const symbol = getCurrencySymbol(currency);
|
|
4103
4306
|
return `${symbol}${amount.toFixed(2)}`;
|
|
4104
4307
|
}
|
|
@@ -4106,30 +4309,30 @@ class PlansSectionComponent {
|
|
|
4106
4309
|
const prices = this.getDynamicPrices(plan);
|
|
4107
4310
|
if (prices.length === 0)
|
|
4108
4311
|
return '0';
|
|
4109
|
-
const
|
|
4110
|
-
const tiers =
|
|
4312
|
+
const firstPriceObj = prices[0].price;
|
|
4313
|
+
const tiers = firstPriceObj?.tiers || [];
|
|
4111
4314
|
if (tiers.length === 0)
|
|
4112
4315
|
return '0';
|
|
4113
4316
|
const tier = tiers[0];
|
|
4114
|
-
const amount = tier.unit_price || tier.package_price || tier.flat_fee || 0;
|
|
4115
|
-
const currency =
|
|
4317
|
+
const amount = (tier.unit_price || tier.package_price || tier.flat_fee || 0);
|
|
4318
|
+
const currency = firstPriceObj?.currency || 'USD';
|
|
4116
4319
|
const symbol = getCurrencySymbol(currency);
|
|
4117
|
-
const
|
|
4118
|
-
const amountParts =
|
|
4320
|
+
const formatted = formatPriceAmount(amount);
|
|
4321
|
+
const amountParts = formatted?.split('.');
|
|
4119
4322
|
return `${symbol}${amountParts?.[0] ?? '0'}`;
|
|
4120
4323
|
}
|
|
4121
4324
|
getMainDynamicPriceDecimal(plan) {
|
|
4122
4325
|
const prices = this.getDynamicPrices(plan);
|
|
4123
4326
|
if (prices.length === 0)
|
|
4124
4327
|
return '00';
|
|
4125
|
-
const
|
|
4126
|
-
const tiers =
|
|
4328
|
+
const firstPriceObj = prices[0].price;
|
|
4329
|
+
const tiers = firstPriceObj?.tiers || [];
|
|
4127
4330
|
if (tiers.length === 0)
|
|
4128
4331
|
return '00';
|
|
4129
4332
|
const tier = tiers[0];
|
|
4130
|
-
const amount = tier.unit_price || tier.package_price || tier.flat_fee || 0;
|
|
4131
|
-
const
|
|
4132
|
-
const amountParts =
|
|
4333
|
+
const amount = (tier.unit_price || tier.package_price || tier.flat_fee || 0);
|
|
4334
|
+
const formatted = formatPriceAmount(amount);
|
|
4335
|
+
const amountParts = formatted?.split('.');
|
|
4133
4336
|
return amountParts && amountParts.length > 1 ? amountParts[1].padEnd(2, '0').slice(0, 2) : '00';
|
|
4134
4337
|
}
|
|
4135
4338
|
getMainDynamicPriceUnit(plan) {
|
|
@@ -4247,15 +4450,14 @@ class PlansSectionComponent {
|
|
|
4247
4450
|
<div class="flex gap-x-2 overflow-x-auto whitespace-nowrap px-6 py-4 -mx-4">
|
|
4248
4451
|
@for (plan of plans; track plan.id; let idx = $index) {
|
|
4249
4452
|
<div
|
|
4250
|
-
class="flex flex-col shrink-0 w-[330px]
|
|
4251
|
-
[style.borderRadius]="'var(--pt-card-radius,
|
|
4453
|
+
class="flex flex-col shrink-0 w-[330px]"
|
|
4454
|
+
[style.borderRadius]="plan.is_current_plan ? 'var(--pt-current-sub-card-radius, var(--pt-card-radius, 1rem))' : 'var(--pt-card-radius, 1rem)'"
|
|
4252
4455
|
[style.borderWidth]="'var(--pt-card-border-width, 1px)'"
|
|
4253
4456
|
[style.borderStyle]="'solid'"
|
|
4254
|
-
[style.borderColor]="'var(--pt-card-border)'"
|
|
4457
|
+
[style.borderColor]="'var(--pt-card-border, #e5e7eb)'"
|
|
4255
4458
|
[style.background-color]="plan.is_current_plan ? 'var(--pt-current-sub-card-header-bg)' : 'var(--pt-card-header-bg)'">
|
|
4256
4459
|
<!-- Card Header -->
|
|
4257
|
-
<div class="flex items-center justify-between pl-4 pr-[5px] pt-[6px] pb-[2px]
|
|
4258
|
-
[style.background-color]="plan.is_current_plan ? 'var(--pt-current-sub-card-header-bg)' : 'var(--pt-card-header-bg)'">
|
|
4460
|
+
<div class="flex items-center justify-between pl-4 pr-[5px] pt-[6px] pb-[2px]">
|
|
4259
4461
|
<span
|
|
4260
4462
|
class="text-sm font-medium"
|
|
4261
4463
|
[style.color]="plan.is_current_plan ? 'var(--pt-current-sub-card-header-text)' : 'var(--pt-card-header-text)'">
|
|
@@ -4272,12 +4474,11 @@ class PlansSectionComponent {
|
|
|
4272
4474
|
|
|
4273
4475
|
<!-- Card Body -->
|
|
4274
4476
|
<div
|
|
4275
|
-
class="flex-grow
|
|
4276
|
-
[style.
|
|
4277
|
-
[style.border]="'1px solid var(--pt-card-
|
|
4278
|
-
[style.
|
|
4279
|
-
[
|
|
4280
|
-
[class.border-t-0]="!plan.is_current_plan">
|
|
4477
|
+
class="flex-grow w-full p-2 pb-10"
|
|
4478
|
+
[style.borderRadius]="'calc(' + (plan.is_current_plan ? 'var(--pt-current-sub-card-radius, var(--pt-card-radius, 1rem))' : 'var(--pt-card-radius, 1rem)') + ' - 2px)'"
|
|
4479
|
+
[style.border]="'1px solid ' + (plan.is_current_plan ? 'var(--pt-current-sub-card-header-bg)' : 'var(--pt-card-header-bg)')"
|
|
4480
|
+
[style.background-color]="'var(--pt-card-bg, #ffffff)'"
|
|
4481
|
+
[style.backgroundImage]="plan.is_current_plan ? 'var(--pt-card-gradient)' : undefined">
|
|
4281
4482
|
|
|
4282
4483
|
<!-- Description -->
|
|
4283
4484
|
@if (shouldShowPlanDescription()) {
|
|
@@ -4563,15 +4764,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
4563
4764
|
<div class="flex gap-x-2 overflow-x-auto whitespace-nowrap px-6 py-4 -mx-4">
|
|
4564
4765
|
@for (plan of plans; track plan.id; let idx = $index) {
|
|
4565
4766
|
<div
|
|
4566
|
-
class="flex flex-col shrink-0 w-[330px]
|
|
4567
|
-
[style.borderRadius]="'var(--pt-card-radius,
|
|
4767
|
+
class="flex flex-col shrink-0 w-[330px]"
|
|
4768
|
+
[style.borderRadius]="plan.is_current_plan ? 'var(--pt-current-sub-card-radius, var(--pt-card-radius, 1rem))' : 'var(--pt-card-radius, 1rem)'"
|
|
4568
4769
|
[style.borderWidth]="'var(--pt-card-border-width, 1px)'"
|
|
4569
4770
|
[style.borderStyle]="'solid'"
|
|
4570
|
-
[style.borderColor]="'var(--pt-card-border)'"
|
|
4771
|
+
[style.borderColor]="'var(--pt-card-border, #e5e7eb)'"
|
|
4571
4772
|
[style.background-color]="plan.is_current_plan ? 'var(--pt-current-sub-card-header-bg)' : 'var(--pt-card-header-bg)'">
|
|
4572
4773
|
<!-- Card Header -->
|
|
4573
|
-
<div class="flex items-center justify-between pl-4 pr-[5px] pt-[6px] pb-[2px]
|
|
4574
|
-
[style.background-color]="plan.is_current_plan ? 'var(--pt-current-sub-card-header-bg)' : 'var(--pt-card-header-bg)'">
|
|
4774
|
+
<div class="flex items-center justify-between pl-4 pr-[5px] pt-[6px] pb-[2px]">
|
|
4575
4775
|
<span
|
|
4576
4776
|
class="text-sm font-medium"
|
|
4577
4777
|
[style.color]="plan.is_current_plan ? 'var(--pt-current-sub-card-header-text)' : 'var(--pt-card-header-text)'">
|
|
@@ -4588,12 +4788,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
4588
4788
|
|
|
4589
4789
|
<!-- Card Body -->
|
|
4590
4790
|
<div
|
|
4591
|
-
class="flex-grow
|
|
4592
|
-
[style.
|
|
4593
|
-
[style.border]="'1px solid var(--pt-card-
|
|
4594
|
-
[style.
|
|
4595
|
-
[
|
|
4596
|
-
[class.border-t-0]="!plan.is_current_plan">
|
|
4791
|
+
class="flex-grow w-full p-2 pb-10"
|
|
4792
|
+
[style.borderRadius]="'calc(' + (plan.is_current_plan ? 'var(--pt-current-sub-card-radius, var(--pt-card-radius, 1rem))' : 'var(--pt-card-radius, 1rem)') + ' - 2px)'"
|
|
4793
|
+
[style.border]="'1px solid ' + (plan.is_current_plan ? 'var(--pt-current-sub-card-header-bg)' : 'var(--pt-card-header-bg)')"
|
|
4794
|
+
[style.background-color]="'var(--pt-card-bg, #ffffff)'"
|
|
4795
|
+
[style.backgroundImage]="plan.is_current_plan ? 'var(--pt-card-gradient)' : undefined">
|
|
4597
4796
|
|
|
4598
4797
|
<!-- Description -->
|
|
4599
4798
|
@if (shouldShowPlanDescription()) {
|
|
@@ -4813,7 +5012,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
4813
5012
|
</div>
|
|
4814
5013
|
</div>
|
|
4815
5014
|
}
|
|
4816
|
-
|
|
5015
|
+
`
|
|
4817
5016
|
}]
|
|
4818
5017
|
}], propDecorators: { plans: [{
|
|
4819
5018
|
type: Input
|
|
@@ -4843,7 +5042,7 @@ class InvoicePreviewComponent {
|
|
|
4843
5042
|
return date.toLocaleDateString(undefined, {
|
|
4844
5043
|
month: 'short',
|
|
4845
5044
|
day: 'numeric',
|
|
4846
|
-
year: 'numeric'
|
|
5045
|
+
year: 'numeric'
|
|
4847
5046
|
});
|
|
4848
5047
|
}
|
|
4849
5048
|
formatInvoicePrice(amount) {
|
|
@@ -4864,12 +5063,12 @@ class InvoicePreviewComponent {
|
|
|
4864
5063
|
if (!invoice)
|
|
4865
5064
|
return '$';
|
|
4866
5065
|
const c = invoice.currency;
|
|
4867
|
-
return c?.symbol ??
|
|
5066
|
+
return (c?.symbol ?? '$');
|
|
4868
5067
|
}
|
|
4869
5068
|
getInvoiceSummaryNumber(invoice, ...keys) {
|
|
4870
5069
|
if (!invoice)
|
|
4871
5070
|
return 0;
|
|
4872
|
-
const s = invoice.summary ?? {};
|
|
5071
|
+
const s = (invoice.summary ?? {});
|
|
4873
5072
|
for (const k of keys) {
|
|
4874
5073
|
const v = s[k];
|
|
4875
5074
|
if (v !== undefined && v !== null && v !== '') {
|
|
@@ -4882,51 +5081,45 @@ class InvoicePreviewComponent {
|
|
|
4882
5081
|
getInvoiceLineItems(invoice) {
|
|
4883
5082
|
if (!invoice)
|
|
4884
5083
|
return [];
|
|
4885
|
-
const lineItems = invoice.line_items ??
|
|
4886
|
-
const chargeItems = invoice.charge_items ??
|
|
4887
|
-
const usageItems = invoice.usage_items ??
|
|
4888
|
-
const creditItems = invoice.credit_items ??
|
|
5084
|
+
const lineItems = invoice.line_items ?? [];
|
|
5085
|
+
const chargeItems = invoice.charge_items ?? [];
|
|
5086
|
+
const usageItems = invoice.usage_items ?? [];
|
|
5087
|
+
const creditItems = invoice.credit_items ?? [];
|
|
4889
5088
|
const normalize = (item, itemType) => this.normalizeInvoiceLineItem(item, itemType);
|
|
4890
5089
|
return [
|
|
4891
|
-
...
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
...
|
|
4895
|
-
? chargeItems.map((i) => normalize(i, 'charge_item'))
|
|
4896
|
-
: []),
|
|
4897
|
-
...(Array.isArray(usageItems)
|
|
4898
|
-
? usageItems.map((i) => normalize(i, 'usage_item'))
|
|
4899
|
-
: []),
|
|
4900
|
-
...(Array.isArray(creditItems)
|
|
4901
|
-
? creditItems.map((i) => normalize(i, 'credit_item'))
|
|
4902
|
-
: []),
|
|
5090
|
+
...lineItems.map((i) => normalize(i, 'line_item')),
|
|
5091
|
+
...chargeItems.map((i) => normalize(i, 'charge_item')),
|
|
5092
|
+
...usageItems.map((i) => normalize(i, 'usage_item')),
|
|
5093
|
+
...creditItems.map((i) => normalize(i, 'credit_item'))
|
|
4903
5094
|
];
|
|
4904
5095
|
}
|
|
4905
5096
|
getInvoiceLineItemRangeLabel(raw) {
|
|
4906
|
-
const
|
|
4907
|
-
const
|
|
5097
|
+
const usageTiers = raw['usage_tiers'];
|
|
5098
|
+
const tiers = usageTiers?.['tiers'] ?? raw['tiers'] ?? [];
|
|
5099
|
+
const tier = (Array.isArray(tiers) && tiers.length > 0 ? tiers[0] : null);
|
|
4908
5100
|
if (!tier)
|
|
4909
5101
|
return '';
|
|
4910
|
-
const first = tier
|
|
4911
|
-
const last = tier
|
|
4912
|
-
if (last === -1 || last
|
|
5102
|
+
const first = tier['first_unit'] ?? tier['firstUnit'] ?? 0;
|
|
5103
|
+
const last = tier['last_unit'] ?? tier['lastUnit'] ?? -1;
|
|
5104
|
+
if (last === -1 || last === null || last === undefined)
|
|
4913
5105
|
return `${first} and above`;
|
|
4914
5106
|
return `${first} to ${last}`;
|
|
4915
5107
|
}
|
|
4916
5108
|
normalizeInvoiceLineItem(item, itemType) {
|
|
4917
5109
|
const raw = item || {};
|
|
4918
|
-
const id = raw
|
|
4919
|
-
const name = raw
|
|
4920
|
-
const description = (raw
|
|
4921
|
-
const quantity = Number(raw
|
|
4922
|
-
const totalAmountNum = this.toNumber(raw
|
|
4923
|
-
const amountStr = String(raw
|
|
4924
|
-
const totalAmountStr = String(raw
|
|
4925
|
-
const
|
|
4926
|
-
const
|
|
4927
|
-
const
|
|
5110
|
+
const id = raw['id'] ?? raw['Id'] ?? '';
|
|
5111
|
+
const name = raw['name'] ?? raw['Name'] ?? '';
|
|
5112
|
+
const description = (raw['description'] ?? raw['Description'] ?? '') || this.getInvoiceLineItemRangeLabel(raw);
|
|
5113
|
+
const quantity = Number(raw['quantity'] ?? raw['Quantity'] ?? 0);
|
|
5114
|
+
const totalAmountNum = this.toNumber((raw['total_amount'] ?? raw['totalAmount'] ?? raw['amount'] ?? raw['Amount'] ?? 0));
|
|
5115
|
+
const amountStr = String(raw['amount'] ?? raw['Amount'] ?? raw['total_amount'] ?? raw['totalAmount'] ?? '0');
|
|
5116
|
+
const totalAmountStr = String(raw['total_amount'] ?? raw['totalAmount'] ?? raw['amount'] ?? raw['Amount'] ?? '0');
|
|
5117
|
+
const usageTiers = raw['usage_tiers'];
|
|
5118
|
+
const tiers = usageTiers?.['tiers'] ?? raw['tiers'] ?? [];
|
|
5119
|
+
const firstTier = (Array.isArray(tiers) && tiers.length > 0 ? tiers[0] : null);
|
|
5120
|
+
const tierUnitPrice = firstTier !== null && firstTier !== undefined ? (firstTier['unit_price'] ?? firstTier['unitPrice']) : undefined;
|
|
4928
5121
|
const derivedUnitPrice = quantity > 0 && totalAmountNum > 0 ? totalAmountNum / quantity : undefined;
|
|
4929
|
-
const rawUnitPrice = raw
|
|
5122
|
+
const rawUnitPrice = raw['unit_price'] ?? raw['unitPrice'] ?? tierUnitPrice;
|
|
4930
5123
|
const rawUnitNum = rawUnitPrice !== undefined &&
|
|
4931
5124
|
rawUnitPrice !== null &&
|
|
4932
5125
|
String(rawUnitPrice).trim() !== ''
|
|
@@ -4941,7 +5134,7 @@ class InvoicePreviewComponent {
|
|
|
4941
5134
|
unit_price: String(unitPriceNum),
|
|
4942
5135
|
amount: amountStr,
|
|
4943
5136
|
total_amount: totalAmountStr,
|
|
4944
|
-
itemType
|
|
5137
|
+
itemType
|
|
4945
5138
|
};
|
|
4946
5139
|
}
|
|
4947
5140
|
buildTenantAddress(addr) {
|
|
@@ -4953,41 +5146,29 @@ class InvoicePreviewComponent {
|
|
|
4953
5146
|
addr.city,
|
|
4954
5147
|
addr.state,
|
|
4955
5148
|
addr.postal_code,
|
|
4956
|
-
addr.country
|
|
5149
|
+
addr.country
|
|
4957
5150
|
].filter(Boolean);
|
|
4958
5151
|
return parts.length ? parts.join(', ') : 'No Tenant address provided';
|
|
4959
5152
|
}
|
|
4960
5153
|
buildBilledToAddress(customer) {
|
|
4961
5154
|
if (!customer)
|
|
4962
5155
|
return '-';
|
|
4963
|
-
const billing = customer
|
|
5156
|
+
const billing = customer.billing_address;
|
|
4964
5157
|
if (billing) {
|
|
4965
5158
|
const parts = [
|
|
4966
|
-
billing.
|
|
4967
|
-
billing.
|
|
5159
|
+
billing.address_line_one,
|
|
5160
|
+
billing.address_line_two,
|
|
4968
5161
|
billing.city,
|
|
4969
5162
|
billing.state,
|
|
4970
|
-
billing.
|
|
4971
|
-
billing.country
|
|
4972
|
-
].filter(Boolean);
|
|
4973
|
-
return parts.length ? parts.join(', ') : '-';
|
|
4974
|
-
}
|
|
4975
|
-
const addr = customer?.address;
|
|
4976
|
-
if (addr) {
|
|
4977
|
-
const parts = [
|
|
4978
|
-
addr.line_1,
|
|
4979
|
-
addr.line_2,
|
|
4980
|
-
addr.city,
|
|
4981
|
-
addr.state,
|
|
4982
|
-
addr.postal_code,
|
|
4983
|
-
addr.country,
|
|
5163
|
+
billing.zip_code,
|
|
5164
|
+
billing.country
|
|
4984
5165
|
].filter(Boolean);
|
|
4985
5166
|
return parts.length ? parts.join(', ') : '-';
|
|
4986
5167
|
}
|
|
4987
5168
|
return '-';
|
|
4988
5169
|
}
|
|
4989
5170
|
escapeHtml(s) {
|
|
4990
|
-
if (s
|
|
5171
|
+
if (s === null || s === undefined)
|
|
4991
5172
|
return '';
|
|
4992
5173
|
return String(s)
|
|
4993
5174
|
.replace(/&/g, '&')
|
|
@@ -5030,14 +5211,14 @@ class InvoicePreviewComponent {
|
|
|
5030
5211
|
const paid = fmt(this.getInvoiceSummaryNumber(inv, 'total_amount_paid', 'totalAmountPaid'));
|
|
5031
5212
|
const due = fmt(this.getInvoiceSummaryNumber(inv, 'total_outstanding_amount', 'totalOutstandingAmount'));
|
|
5032
5213
|
const rows = items
|
|
5033
|
-
.map((item) => `<div style="border-top:1px solid #e5e7eb;display:grid;grid-template-columns:minmax(8rem,1fr) auto auto auto auto;gap:1rem;align-items:start;padding:1rem 0.75rem;font-size:13px;color:#374151;"><div><span style="font-weight:500;color:#2563eb;">${this.escapeHtml(item
|
|
5214
|
+
.map((item) => `<div style="border-top:1px solid #e5e7eb;display:grid;grid-template-columns:minmax(8rem,1fr) auto auto auto auto;gap:1rem;align-items:start;padding:1rem 0.75rem;font-size:13px;color:#374151;"><div><span style="font-weight:500;color:#2563eb;">${this.escapeHtml(String(item['name']))}</span>${item['description'] ? `<p style="font-size:12px;color:#6b7280;margin:2px 0 0 0;">${this.escapeHtml(String(item['description']))}</p>` : ''}</div><div>${sym}${fmt(this.toNumber(item['unit_price']))}</div><div>${item['quantity']}</div><div>${sym}${fmt(this.toNumber((item['total_amount'] || item['amount'])))}</div><div>${sym}${fmt(this.toNumber((item['total_amount'] || item['amount'])))}</div></div>`)
|
|
5034
5215
|
.join('');
|
|
5035
|
-
return `<!DOCTYPE html><html><head><meta charset="utf-8"><title>Invoice</title><style>*{box-sizing:border-box;}body{margin:0;padding:0;font-family:ui-sans-serif,system-ui,sans-serif;font-size:16px;color:#111827;line-height:1.5;background:#fff;}</style></head><body><div style="max-width:48rem;margin:0 auto;padding:2rem;"><div style="background:#fff;padding:2rem;border-radius:0.75rem;border-top:4px solid #111827;box-shadow:0 1px 3px 0 rgb(0 0 0/0.1);"><div style="display:flex;justify-content:space-between;align-items:flex-start;"><div style="display:flex;align-items:center;gap:0.75rem;"><strong style="font-size:1.25rem;font-weight:700;color:#111827;">${this.escapeHtml(inv.tenant?.business_name || 'Metrifox Sandbox')}</strong></div><div style="text-align:right;"><div style="font-size:1.25rem;font-weight:700;color:#111827;text-transform:uppercase;">INVOICE</div><div style="font-size:13px;color:#111827;margin-top:2px;">${this.escapeHtml(inv.invoice_number || '-')}</div></div></div><div style="display:grid;grid-template-columns:minmax(8rem,1fr) auto auto auto auto;gap:1rem;background:#e5e7eb;padding:0.5rem 0.75rem;border-radius:0.375rem;font-size:13px;font-weight:500;color:#374151;margin-top:2rem;"><span>Item name</span><span>Price</span><span>Qty</span><span>Subtotal</span><span>Amount</span></div>${rows}<div style="background:#f5f5f5;padding:0.75rem;width:50%;margin-left:auto;margin-top:1.25rem;border-radius:0.25rem;"><div style="display:flex;justify-content:space-between;border-bottom:1px solid #e5e7eb;padding-bottom:0.5rem;"><div><div style="font-size:13px;font-weight:500;color:#111827;">Subtotal</div><div style="font-size:10px;color:#737373;margin:0.5rem 0;">Discount</div><div style="font-size:10px;color:#737373;">Tax</div><div style="font-size:13px;font-weight:500;color:#111827;margin-top:8px;">Grand total</div></div><div style="text-align:right;"><div style="font-size:13px;font-weight:500;color:#1f2937;">${sym}${sub}</div><div style="font-size:10px;color:#737373;margin:0.5rem 0;">${sym}${disc}</div><div style="font-size:10px;color:#737373;">${sym}${tax}</div><div style="font-size:13px;font-weight:500;color:#1f2937;margin-top:8px;">${sym}${grand}</div></div></div><div style="display:flex;justify-content:space-between;padding-top:0.5rem;"><div><div style="font-size:13px;font-weight:500;color:#111827;">Amount paid</div><div style="font-size:13px;font-weight:500;color:#111827;">Amount due</div></div><div style="text-align:right;"><div style="font-size:13px;font-weight:500;color:#1f2937;">${sym}${paid}</div><div style="font-size:16px;font-weight:500;">${sym}${due}</div></div></div></div><div style="border-top:1px solid #d1d5db;padding-top:1rem;margin-top:3rem;text-align:center;font-size:10px;color:#111827;">Powered by MetriFox</div></div></div></body></html>`;
|
|
5216
|
+
return `<!DOCTYPE html><html><head><meta charset="utf-8"><title>Invoice</title><style>*{box-sizing:border-box;}body{margin:0;padding:0;font-family:ui-sans-serif,system-ui,sans-serif;font-size:16px;color:#111827;line-height:1.5;background:#fff;}</style></head><body><div style="max-width:48rem;margin:0 auto;padding:2rem;"><div style="background:#fff;padding:2rem;border-radius:0.75rem;border-top:4px solid #111827;box-shadow:0 1px 3px 0 rgb(0 0 0/0.1);"><div style="display:flex;justify-content:space-between;align-items:flex-start;"><div style="display:flex;align-items:center;gap:0.75rem;"><strong style="font-size:1.25rem;font-weight:700;color:#111827;">${this.escapeHtml(String(inv.tenant?.business_name || 'Metrifox Sandbox'))}</strong></div><div style="text-align:right;"><div style="font-size:1.25rem;font-weight:700;color:#111827;text-transform:uppercase;">INVOICE</div><div style="font-size:13px;color:#111827;margin-top:2px;">${this.escapeHtml(String(inv.invoice_number || '-'))}</div></div></div><div style="display:grid;grid-template-columns:minmax(8rem,1fr) auto auto auto auto;gap:1rem;background:#e5e7eb;padding:0.5rem 0.75rem;border-radius:0.375rem;font-size:13px;font-weight:500;color:#374151;margin-top:2rem;"><span>Item name</span><span>Price</span><span>Qty</span><span>Subtotal</span><span>Amount</span></div>${rows}<div style="background:#f5f5f5;padding:0.75rem;width:50%;margin-left:auto;margin-top:1.25rem;border-radius:0.25rem;"><div style="display:flex;justify-content:space-between;border-bottom:1px solid #e5e7eb;padding-bottom:0.5rem;"><div><div style="font-size:13px;font-weight:500;color:#111827;">Subtotal</div><div style="font-size:10px;color:#737373;margin:0.5rem 0;">Discount</div><div style="font-size:10px;color:#737373;">Tax</div><div style="font-size:13px;font-weight:500;color:#111827;margin-top:8px;">Grand total</div></div><div style="text-align:right;"><div style="font-size:13px;font-weight:500;color:#1f2937;">${sym}${sub}</div><div style="font-size:10px;color:#737373;margin:0.5rem 0;">${sym}${disc}</div><div style="font-size:10px;color:#737373;">${sym}${tax}</div><div style="font-size:13px;font-weight:500;color:#1f2937;margin-top:8px;">${sym}${grand}</div></div></div><div style="display:flex;justify-content:space-between;padding-top:0.5rem;"><div><div style="font-size:13px;font-weight:500;color:#111827;">Amount paid</div><div style="font-size:13px;font-weight:500;color:#111827;">Amount due</div></div><div style="text-align:right;"><div style="font-size:13px;font-weight:500;color:#1f2937;">${sym}${paid}</div><div style="font-size:16px;font-weight:500;">${sym}${due}</div></div></div></div><div style="border-top:1px solid #d1d5db;padding-top:1rem;margin-top:3rem;text-align:center;font-size:10px;color:#111827;">Powered by MetriFox</div></div></div></body></html>`;
|
|
5036
5217
|
}
|
|
5037
5218
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: InvoicePreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5038
5219
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: InvoicePreviewComponent, isStandalone: true, selector: "cp-invoice-preview", inputs: { show: "show", selectedInvoice: "selectedInvoice", invoiceDetails: "invoiceDetails", invoiceDetailsLoading: "invoiceDetailsLoading" }, outputs: { close: "close" }, ngImport: i0, template: `
|
|
5039
5220
|
@if (show && selectedInvoice) {
|
|
5040
|
-
<div class="invoice-preview-modal fixed inset-0 z-
|
|
5221
|
+
<div class="invoice-preview-modal fixed inset-0 z-[100] overflow-hidden">
|
|
5041
5222
|
<!-- Backdrop -->
|
|
5042
5223
|
<div
|
|
5043
5224
|
class="invoice-preview-backdrop absolute inset-0 bg-black/50 transition-opacity"
|
|
@@ -5374,7 +5555,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
5374
5555
|
type: Component,
|
|
5375
5556
|
args: [{ selector: 'cp-invoice-preview', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
5376
5557
|
@if (show && selectedInvoice) {
|
|
5377
|
-
<div class="invoice-preview-modal fixed inset-0 z-
|
|
5558
|
+
<div class="invoice-preview-modal fixed inset-0 z-[100] overflow-hidden">
|
|
5378
5559
|
<!-- Backdrop -->
|
|
5379
5560
|
<div
|
|
5380
5561
|
class="invoice-preview-backdrop absolute inset-0 bg-black/50 transition-opacity"
|
|
@@ -5794,7 +5975,7 @@ class CustomerPortalComponent {
|
|
|
5794
5975
|
const allPriceOptions = [
|
|
5795
5976
|
...(plan.price_options || []),
|
|
5796
5977
|
...(plan.entitlement_price_options || []),
|
|
5797
|
-
...(plan.credit_attachment_price_options || [])
|
|
5978
|
+
...(plan.credit_attachment_price_options || [])
|
|
5798
5979
|
];
|
|
5799
5980
|
allPriceOptions.forEach((po) => {
|
|
5800
5981
|
if (po.price?.billing_interval) {
|
|
@@ -5808,11 +5989,25 @@ class CustomerPortalComponent {
|
|
|
5808
5989
|
cssVars = computed(() => {
|
|
5809
5990
|
const custom = this.themeSignal() ?? MetrifoxService.getTheme()?.customerPortal;
|
|
5810
5991
|
const theme = mergeCustomerPortalTheme(defaultCustomerPortalTheme, custom);
|
|
5811
|
-
|
|
5992
|
+
const vars = MetrifoxService.customerPortalThemeToCssVars(theme);
|
|
5993
|
+
const gradientVars = MetrifoxService.getBackgroundImage(theme);
|
|
5994
|
+
return {
|
|
5995
|
+
...vars,
|
|
5996
|
+
...gradientVars,
|
|
5997
|
+
'font-family': 'var(--cp-font-family)',
|
|
5998
|
+
'background-color': 'var(--cp-bg)',
|
|
5999
|
+
'border-radius': 'var(--cp-radius)'
|
|
6000
|
+
};
|
|
5812
6001
|
});
|
|
5813
6002
|
ngOnInit() {
|
|
5814
6003
|
this.loadCustomerDetails();
|
|
5815
6004
|
}
|
|
6005
|
+
ngOnChanges(changes) {
|
|
6006
|
+
if (changes['customerKey'] && !changes['customerKey'].firstChange) {
|
|
6007
|
+
this.lastLoadedCustomerKey = null;
|
|
6008
|
+
this.loadCustomerDetails();
|
|
6009
|
+
}
|
|
6010
|
+
}
|
|
5816
6011
|
ngOnDestroy() {
|
|
5817
6012
|
this.destroy$.next();
|
|
5818
6013
|
this.destroy$.complete();
|
|
@@ -5844,9 +6039,9 @@ class CustomerPortalComponent {
|
|
|
5844
6039
|
this.error.set(err.message || 'Failed to load customer data');
|
|
5845
6040
|
this.errorOccurred.emit({
|
|
5846
6041
|
message: err.message || 'Failed to load customer data',
|
|
5847
|
-
code: err.status?.toString()
|
|
6042
|
+
code: err.status?.toString()
|
|
5848
6043
|
});
|
|
5849
|
-
}
|
|
6044
|
+
}
|
|
5850
6045
|
});
|
|
5851
6046
|
}
|
|
5852
6047
|
loadAdditionalData() {
|
|
@@ -5857,7 +6052,7 @@ class CustomerPortalComponent {
|
|
|
5857
6052
|
const subscriptionId = firstSubscription?.subscription?.id;
|
|
5858
6053
|
const productKey = firstSubscription?.product_key;
|
|
5859
6054
|
const requests = {
|
|
5860
|
-
wallets: this.metrifoxService.getCustomerWallets(this.customerKey)
|
|
6055
|
+
wallets: this.metrifoxService.getCustomerWallets(this.customerKey)
|
|
5861
6056
|
};
|
|
5862
6057
|
if (subscriptionId) {
|
|
5863
6058
|
requests.history = this.metrifoxService.getBillingHistory(subscriptionId);
|
|
@@ -5901,7 +6096,7 @@ class CustomerPortalComponent {
|
|
|
5901
6096
|
this.isLoadingData = false;
|
|
5902
6097
|
this.loading.set(false);
|
|
5903
6098
|
this.dataLoaded.emit({ customerDetails: details });
|
|
5904
|
-
}
|
|
6099
|
+
}
|
|
5905
6100
|
});
|
|
5906
6101
|
}
|
|
5907
6102
|
loadDataForSubscription(sub) {
|
|
@@ -5952,7 +6147,7 @@ class CustomerPortalComponent {
|
|
|
5952
6147
|
this.entitlementSummary.set([]);
|
|
5953
6148
|
this.entitlementUsage.set([]);
|
|
5954
6149
|
this.productPlans.set(null);
|
|
5955
|
-
}
|
|
6150
|
+
}
|
|
5956
6151
|
});
|
|
5957
6152
|
}
|
|
5958
6153
|
loadCreditAllocations(walletId, tab) {
|
|
@@ -5968,7 +6163,7 @@ class CustomerPortalComponent {
|
|
|
5968
6163
|
error: () => {
|
|
5969
6164
|
this.creditAllocations.set([]);
|
|
5970
6165
|
this.allocationsLoading.set(false);
|
|
5971
|
-
}
|
|
6166
|
+
}
|
|
5972
6167
|
});
|
|
5973
6168
|
}
|
|
5974
6169
|
selectTab(index) {
|
|
@@ -6003,11 +6198,11 @@ class CustomerPortalComponent {
|
|
|
6003
6198
|
if (invoiceId) {
|
|
6004
6199
|
this.metrifoxService.getInvoiceDetails(invoiceId).pipe(takeUntil(this.destroy$)).subscribe({
|
|
6005
6200
|
next: (data) => {
|
|
6006
|
-
const inv = data?.data ?? data;
|
|
6201
|
+
const inv = (data?.data ?? data);
|
|
6007
6202
|
this.invoiceDetails.set(inv);
|
|
6008
6203
|
this.invoiceDetailsLoading.set(false);
|
|
6009
6204
|
},
|
|
6010
|
-
error: () => this.invoiceDetailsLoading.set(false)
|
|
6205
|
+
error: () => this.invoiceDetailsLoading.set(false)
|
|
6011
6206
|
});
|
|
6012
6207
|
}
|
|
6013
6208
|
else {
|
|
@@ -6029,11 +6224,11 @@ class CustomerPortalComponent {
|
|
|
6029
6224
|
}
|
|
6030
6225
|
}
|
|
6031
6226
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: CustomerPortalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6032
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: CustomerPortalComponent, isStandalone: true, selector: "metrifox-customer-portal", inputs: { customerKey: "customerKey", sectionsConfig: "sectionsConfig", theme: "theme" }, outputs: { dataLoaded: "dataLoaded", errorOccurred: "errorOccurred" }, ngImport: i0, template: `
|
|
6227
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: CustomerPortalComponent, isStandalone: true, selector: "metrifox-customer-portal", inputs: { customerKey: "customerKey", sectionsConfig: "sectionsConfig", theme: "theme" }, outputs: { dataLoaded: "dataLoaded", errorOccurred: "errorOccurred" }, usesOnChanges: true, ngImport: i0, template: `
|
|
6033
6228
|
<div class="font-sans antialiased" [ngStyle]="cssVars()">
|
|
6034
6229
|
<!-- Error State -->
|
|
6035
6230
|
@if (error()) {
|
|
6036
|
-
<div class="max-w-[60rem] mx-auto
|
|
6231
|
+
<div class="max-w-[60rem] mx-auto" [style.padding]="'var(--cp-container-padding, 40px 24px)'">
|
|
6037
6232
|
<div class="bg-red-50 p-4 rounded-lg text-red-700">
|
|
6038
6233
|
Error loading customer details: {{ error() }}
|
|
6039
6234
|
</div>
|
|
@@ -6042,7 +6237,7 @@ class CustomerPortalComponent {
|
|
|
6042
6237
|
|
|
6043
6238
|
<!-- Loading State -->
|
|
6044
6239
|
@if (loading() && !error()) {
|
|
6045
|
-
<div class="max-w-[60rem] mx-auto
|
|
6240
|
+
<div class="max-w-[60rem] mx-auto" [style.padding]="'var(--cp-container-padding, 40px 24px)'">
|
|
6046
6241
|
<div class="animate-pulse space-y-4">
|
|
6047
6242
|
<div class="h-12 bg-gray-200 rounded-lg"></div>
|
|
6048
6243
|
<div class="h-16 bg-gray-200 rounded-lg"></div>
|
|
@@ -6055,7 +6250,7 @@ class CustomerPortalComponent {
|
|
|
6055
6250
|
|
|
6056
6251
|
<!-- Content -->
|
|
6057
6252
|
@if (!loading() && !error() && customerDetails()) {
|
|
6058
|
-
<div class="max-w-[60rem] mx-auto
|
|
6253
|
+
<div class="w-full max-w-[60rem] mx-auto min-w-0 flex flex-col gap-6" [style.padding]="'var(--cp-container-padding, 40px 24px)'">
|
|
6059
6254
|
<!-- Empty Subscription State -->
|
|
6060
6255
|
@if (subscriptions().length === 0) {
|
|
6061
6256
|
<div class="w-full"
|
|
@@ -6132,7 +6327,7 @@ class CustomerPortalComponent {
|
|
|
6132
6327
|
|
|
6133
6328
|
<!-- Subscription Content Template -->
|
|
6134
6329
|
<ng-template #subscriptionContent let-subscription>
|
|
6135
|
-
<div class="
|
|
6330
|
+
<div class="flex flex-col gap-6">
|
|
6136
6331
|
<cp-subscription-section
|
|
6137
6332
|
[subscription]="subscription"
|
|
6138
6333
|
[sectionsConfig]="sectionsConfig"
|
|
@@ -6192,12 +6387,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
6192
6387
|
PaymentSectionComponent,
|
|
6193
6388
|
BillingHistorySectionComponent,
|
|
6194
6389
|
PlansSectionComponent,
|
|
6195
|
-
InvoicePreviewComponent
|
|
6390
|
+
InvoicePreviewComponent
|
|
6196
6391
|
], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
6197
6392
|
<div class="font-sans antialiased" [ngStyle]="cssVars()">
|
|
6198
6393
|
<!-- Error State -->
|
|
6199
6394
|
@if (error()) {
|
|
6200
|
-
<div class="max-w-[60rem] mx-auto
|
|
6395
|
+
<div class="max-w-[60rem] mx-auto" [style.padding]="'var(--cp-container-padding, 40px 24px)'">
|
|
6201
6396
|
<div class="bg-red-50 p-4 rounded-lg text-red-700">
|
|
6202
6397
|
Error loading customer details: {{ error() }}
|
|
6203
6398
|
</div>
|
|
@@ -6206,7 +6401,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
6206
6401
|
|
|
6207
6402
|
<!-- Loading State -->
|
|
6208
6403
|
@if (loading() && !error()) {
|
|
6209
|
-
<div class="max-w-[60rem] mx-auto
|
|
6404
|
+
<div class="max-w-[60rem] mx-auto" [style.padding]="'var(--cp-container-padding, 40px 24px)'">
|
|
6210
6405
|
<div class="animate-pulse space-y-4">
|
|
6211
6406
|
<div class="h-12 bg-gray-200 rounded-lg"></div>
|
|
6212
6407
|
<div class="h-16 bg-gray-200 rounded-lg"></div>
|
|
@@ -6219,7 +6414,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
6219
6414
|
|
|
6220
6415
|
<!-- Content -->
|
|
6221
6416
|
@if (!loading() && !error() && customerDetails()) {
|
|
6222
|
-
<div class="max-w-[60rem] mx-auto
|
|
6417
|
+
<div class="w-full max-w-[60rem] mx-auto min-w-0 flex flex-col gap-6" [style.padding]="'var(--cp-container-padding, 40px 24px)'">
|
|
6223
6418
|
<!-- Empty Subscription State -->
|
|
6224
6419
|
@if (subscriptions().length === 0) {
|
|
6225
6420
|
<div class="w-full"
|
|
@@ -6296,7 +6491,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
6296
6491
|
|
|
6297
6492
|
<!-- Subscription Content Template -->
|
|
6298
6493
|
<ng-template #subscriptionContent let-subscription>
|
|
6299
|
-
<div class="
|
|
6494
|
+
<div class="flex flex-col gap-6">
|
|
6300
6495
|
<cp-subscription-section
|
|
6301
6496
|
[subscription]="subscription"
|
|
6302
6497
|
[sectionsConfig]="sectionsConfig"
|
|
@@ -6455,6 +6650,7 @@ var ResetIntervals;
|
|
|
6455
6650
|
ResetIntervals["DAILY"] = "daily";
|
|
6456
6651
|
ResetIntervals["BILLING_PERIOD"] = "billing_period";
|
|
6457
6652
|
ResetIntervals["NEVER"] = "never";
|
|
6653
|
+
ResetIntervals["NONE"] = "none";
|
|
6458
6654
|
})(ResetIntervals || (ResetIntervals = {}));
|
|
6459
6655
|
/**
|
|
6460
6656
|
* Enforcement types
|
|
@@ -6482,6 +6678,7 @@ var BillingTimingTypes;
|
|
|
6482
6678
|
(function (BillingTimingTypes) {
|
|
6483
6679
|
BillingTimingTypes["IN_ADVANCE"] = "in_advance";
|
|
6484
6680
|
BillingTimingTypes["IN_ARREARS"] = "in_arrears";
|
|
6681
|
+
BillingTimingTypes["PAY_AS_YOU_GO"] = "pay_as_you_go";
|
|
6485
6682
|
})(BillingTimingTypes || (BillingTimingTypes = {}));
|
|
6486
6683
|
/**
|
|
6487
6684
|
* Aggregation methods
|
|
@@ -6532,56 +6729,75 @@ var LocalizationSelection;
|
|
|
6532
6729
|
LocalizationSelection["SMART_PRE_FILL"] = "smart_pre_fill";
|
|
6533
6730
|
})(LocalizationSelection || (LocalizationSelection = {}));
|
|
6534
6731
|
|
|
6535
|
-
// Default theme matching React SDK
|
|
6536
6732
|
const defaultPricingTableTheme = {
|
|
6537
6733
|
plans: {
|
|
6538
6734
|
currentPlanCard: {
|
|
6539
|
-
header: {
|
|
6540
|
-
|
|
6735
|
+
header: {
|
|
6736
|
+
background: '#e5e7eb',
|
|
6737
|
+
textColor: '#111827'
|
|
6738
|
+
},
|
|
6739
|
+
gradientColor: '#e5e7eb'
|
|
6541
6740
|
},
|
|
6542
6741
|
planCards: {
|
|
6543
6742
|
background: '#ffffff',
|
|
6544
|
-
border: {
|
|
6545
|
-
|
|
6546
|
-
|
|
6743
|
+
border: {
|
|
6744
|
+
color: '#e5e7eb',
|
|
6745
|
+
width: '1px',
|
|
6746
|
+
radius: '8px'
|
|
6747
|
+
},
|
|
6748
|
+
header: {
|
|
6749
|
+
background: '#e5e7eb',
|
|
6750
|
+
textColor: '#111827'
|
|
6751
|
+
},
|
|
6752
|
+
description: {
|
|
6753
|
+
textColor: '#6b7280',
|
|
6754
|
+
textButtonColor: '#2563eb'
|
|
6755
|
+
},
|
|
6547
6756
|
price: {
|
|
6548
6757
|
amountColor: '#111827',
|
|
6549
|
-
primaryTextColor: '#
|
|
6550
|
-
secondaryTextColor: '#
|
|
6758
|
+
primaryTextColor: '#6b7280',
|
|
6759
|
+
secondaryTextColor: '#9ca3af',
|
|
6551
6760
|
background: 'transparent',
|
|
6552
|
-
borderColor: 'transparent'
|
|
6553
|
-
}
|
|
6761
|
+
borderColor: 'transparent'
|
|
6762
|
+
}
|
|
6763
|
+
},
|
|
6764
|
+
planFeatures: {
|
|
6765
|
+
textColor: '#374151',
|
|
6766
|
+
iconColor: '#0BB02F'
|
|
6554
6767
|
},
|
|
6555
|
-
planFeatures: { textColor: '#3F3F46', iconColor: '#0BB02F' },
|
|
6556
6768
|
planButton: {
|
|
6557
6769
|
background: '#3D3D3D',
|
|
6558
6770
|
textColor: '#ffffff',
|
|
6559
6771
|
secondaryBackground: '#E4E4E7',
|
|
6560
6772
|
secondaryTextColor: '#3F3F46',
|
|
6561
|
-
textButtonColor: '#2563eb'
|
|
6773
|
+
textButtonColor: '#2563eb'
|
|
6562
6774
|
},
|
|
6563
6775
|
planToggle: {
|
|
6564
|
-
background: '#
|
|
6776
|
+
background: '#e5e7eb',
|
|
6565
6777
|
activeBackground: '#1f2937',
|
|
6566
6778
|
activeText: '#ffffff',
|
|
6567
|
-
inactiveText: '#
|
|
6779
|
+
inactiveText: '#6b7280'
|
|
6568
6780
|
},
|
|
6569
|
-
planTags: {
|
|
6781
|
+
planTags: {
|
|
6782
|
+
freeTrialBackground: '#dbeafe',
|
|
6783
|
+
freeTrialText: '#1e40af'
|
|
6784
|
+
}
|
|
6570
6785
|
},
|
|
6571
6786
|
tabs: {
|
|
6572
|
-
inactiveText: '#
|
|
6787
|
+
inactiveText: '#9ca3af',
|
|
6573
6788
|
activeText: '#2563eb',
|
|
6574
6789
|
indicator: '#2563eb',
|
|
6575
|
-
borderColor: '#
|
|
6790
|
+
borderColor: '#9ca3af'
|
|
6576
6791
|
},
|
|
6577
6792
|
checkoutBar: {
|
|
6578
|
-
background: '#
|
|
6579
|
-
borderColor: '#
|
|
6793
|
+
background: '#f9fafb',
|
|
6794
|
+
borderColor: '#e5e7eb',
|
|
6580
6795
|
textColor: '#3F3F46',
|
|
6581
6796
|
buttonBackground: '#2563eb',
|
|
6582
|
-
buttonTextColor: '#ffffff'
|
|
6583
|
-
}
|
|
6797
|
+
buttonTextColor: '#ffffff'
|
|
6798
|
+
}
|
|
6584
6799
|
};
|
|
6800
|
+
|
|
6585
6801
|
function mergePricingTableTheme(defaultTheme, custom) {
|
|
6586
6802
|
if (!custom || typeof custom !== 'object')
|
|
6587
6803
|
return defaultTheme;
|
|
@@ -6605,12 +6821,12 @@ function mergePricingTableTheme(defaultTheme, custom) {
|
|
|
6605
6821
|
}
|
|
6606
6822
|
// SVG Icons
|
|
6607
6823
|
const ICONS = {
|
|
6608
|
-
check:
|
|
6609
|
-
search:
|
|
6610
|
-
close:
|
|
6611
|
-
trash:
|
|
6612
|
-
minus:
|
|
6613
|
-
plus:
|
|
6824
|
+
check: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>',
|
|
6825
|
+
search: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.3-4.3"></path></svg>',
|
|
6826
|
+
close: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><path d="m15 9-6 6"></path><path d="m9 9 6 6"></path></svg>',
|
|
6827
|
+
trash: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"></path><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"></path></svg>',
|
|
6828
|
+
minus: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"></path></svg>',
|
|
6829
|
+
plus: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"></path><path d="M12 5v14"></path></svg>'
|
|
6614
6830
|
};
|
|
6615
6831
|
/**
|
|
6616
6832
|
* Pricing Table Component
|
|
@@ -6635,15 +6851,24 @@ class PricingTableComponent {
|
|
|
6635
6851
|
checkoutUsername;
|
|
6636
6852
|
metrifoxService = inject(MetrifoxService);
|
|
6637
6853
|
sanitizer = inject(DomSanitizer);
|
|
6854
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
6638
6855
|
constructor() { }
|
|
6639
6856
|
/** Product key to load pricing for */
|
|
6640
6857
|
productKey;
|
|
6641
6858
|
/** Show only plans (hide single purchases) */
|
|
6642
|
-
|
|
6859
|
+
plansOnlySignal = signal(false);
|
|
6860
|
+
set plansOnly(value) { this.plansOnlySignal.set(value); }
|
|
6643
6861
|
/** Show only single purchases (hide plans) */
|
|
6644
|
-
|
|
6862
|
+
singlePurchasesOnlySignal = signal(false);
|
|
6863
|
+
set singlePurchasesOnly(value) { this.singlePurchasesOnlySignal.set(value); }
|
|
6645
6864
|
/** Show tab header when both plans and purchases exist */
|
|
6646
|
-
|
|
6865
|
+
showTabHeaderSignal = signal(true);
|
|
6866
|
+
set showTabHeader(value) { this.showTabHeaderSignal.set(value); }
|
|
6867
|
+
/** Optional theme override for this instance */
|
|
6868
|
+
themeSignal = signal(undefined);
|
|
6869
|
+
set theme(value) {
|
|
6870
|
+
this.themeSignal.set(value);
|
|
6871
|
+
}
|
|
6647
6872
|
/** Emitted when a plan is selected */
|
|
6648
6873
|
planSelected = new EventEmitter();
|
|
6649
6874
|
/** Emitted when a single purchase is selected */
|
|
@@ -6661,8 +6886,8 @@ class PricingTableComponent {
|
|
|
6661
6886
|
// Computed
|
|
6662
6887
|
plans = computed(() => this.product()?.plans || []);
|
|
6663
6888
|
singlePurchases = computed(() => this.product()?.single_purchases || []);
|
|
6664
|
-
showPlans = computed(() => this.
|
|
6665
|
-
showSinglePurchases = computed(() => this.
|
|
6889
|
+
showPlans = computed(() => this.plansOnlySignal() || (!this.plansOnlySignal() && !this.singlePurchasesOnlySignal()));
|
|
6890
|
+
showSinglePurchases = computed(() => this.singlePurchasesOnlySignal() || (!this.plansOnlySignal() && !this.singlePurchasesOnlySignal()));
|
|
6666
6891
|
hasBothTypes = computed(() => this.plans().length > 0 && this.singlePurchases().length > 0);
|
|
6667
6892
|
tabOptions = computed(() => {
|
|
6668
6893
|
const options = [];
|
|
@@ -6696,11 +6921,12 @@ class PricingTableComponent {
|
|
|
6696
6921
|
return purchases.filter((p) => p.published_version?.name?.toLowerCase().includes(term));
|
|
6697
6922
|
});
|
|
6698
6923
|
cssVars = computed(() => {
|
|
6699
|
-
const
|
|
6700
|
-
const theme = mergePricingTableTheme(defaultPricingTableTheme,
|
|
6924
|
+
const custom = this.themeSignal() ?? MetrifoxService.getTheme()?.pricingTable;
|
|
6925
|
+
const theme = mergePricingTableTheme(defaultPricingTableTheme, custom);
|
|
6701
6926
|
return {
|
|
6702
6927
|
...MetrifoxService.pricingTableThemeToCssVars(theme),
|
|
6703
6928
|
...MetrifoxService.getBackgroundImage(theme),
|
|
6929
|
+
'font-family': 'var(--pt-font-family, var(--cp-font-family, inherit))'
|
|
6704
6930
|
};
|
|
6705
6931
|
});
|
|
6706
6932
|
ngOnInit() {
|
|
@@ -6738,9 +6964,9 @@ class PricingTableComponent {
|
|
|
6738
6964
|
this.error.set(err.message || 'Failed to load pricing');
|
|
6739
6965
|
this.errorOccurred.emit({
|
|
6740
6966
|
message: err.message || 'Failed to load pricing',
|
|
6741
|
-
code: err.status?.toString()
|
|
6967
|
+
code: err.status?.toString()
|
|
6742
6968
|
});
|
|
6743
|
-
}
|
|
6969
|
+
}
|
|
6744
6970
|
});
|
|
6745
6971
|
}
|
|
6746
6972
|
/**
|
|
@@ -6763,7 +6989,7 @@ class PricingTableComponent {
|
|
|
6763
6989
|
this.planSelected.emit({
|
|
6764
6990
|
plan: plan.published_version,
|
|
6765
6991
|
interval: this.selectedInterval(),
|
|
6766
|
-
checkoutUrl
|
|
6992
|
+
checkoutUrl
|
|
6767
6993
|
});
|
|
6768
6994
|
// Open checkout in new tab
|
|
6769
6995
|
window.open(checkoutUrl, '_blank');
|
|
@@ -6775,7 +7001,7 @@ class PricingTableComponent {
|
|
|
6775
7001
|
const checkoutUrl = this.metrifoxService.buildCheckoutUrl(this.checkoutUsername, purchase.offering_key);
|
|
6776
7002
|
this.purchaseSelected.emit({
|
|
6777
7003
|
purchase: purchase.published_version,
|
|
6778
|
-
checkoutUrl
|
|
7004
|
+
checkoutUrl
|
|
6779
7005
|
});
|
|
6780
7006
|
// Open checkout in new tab
|
|
6781
7007
|
window.open(checkoutUrl, '_blank');
|
|
@@ -6836,7 +7062,7 @@ class PricingTableComponent {
|
|
|
6836
7062
|
EUR: '€',
|
|
6837
7063
|
GBP: '£',
|
|
6838
7064
|
JPY: '¥',
|
|
6839
|
-
NGN: '₦'
|
|
7065
|
+
NGN: '₦'
|
|
6840
7066
|
};
|
|
6841
7067
|
return symbols[currency] || currency;
|
|
6842
7068
|
}
|
|
@@ -6879,7 +7105,7 @@ class PricingTableComponent {
|
|
|
6879
7105
|
monthly: 'Monthly',
|
|
6880
7106
|
yearly: 'Yearly',
|
|
6881
7107
|
weekly: 'Weekly',
|
|
6882
|
-
daily: 'Daily'
|
|
7108
|
+
daily: 'Daily'
|
|
6883
7109
|
};
|
|
6884
7110
|
return labels[interval] || interval;
|
|
6885
7111
|
}
|
|
@@ -6960,7 +7186,7 @@ class PricingTableComponent {
|
|
|
6960
7186
|
price: priceOption.price.price,
|
|
6961
7187
|
currency: priceOption.price.currency,
|
|
6962
7188
|
quantity,
|
|
6963
|
-
offering_key: purchase.offering_key
|
|
7189
|
+
offering_key: purchase.offering_key
|
|
6964
7190
|
};
|
|
6965
7191
|
this.cartItems.update((items) => [...items, item]);
|
|
6966
7192
|
}
|
|
@@ -6985,7 +7211,7 @@ class PricingTableComponent {
|
|
|
6985
7211
|
checkoutWindow?.postMessage({
|
|
6986
7212
|
v: 1,
|
|
6987
7213
|
type: 'INIT_CART',
|
|
6988
|
-
payload: dataToSend
|
|
7214
|
+
payload: dataToSend
|
|
6989
7215
|
}, '*');
|
|
6990
7216
|
break;
|
|
6991
7217
|
case 'ACK':
|
|
@@ -7000,7 +7226,7 @@ class PricingTableComponent {
|
|
|
7000
7226
|
}, 5000);
|
|
7001
7227
|
}
|
|
7002
7228
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: PricingTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7003
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: PricingTableComponent, isStandalone: true, selector: "metrifox-pricing-table", inputs: { checkoutUsername: "checkoutUsername", productKey: "productKey", plansOnly: "plansOnly", singlePurchasesOnly: "singlePurchasesOnly", showTabHeader: "showTabHeader" }, outputs: { planSelected: "planSelected", purchaseSelected: "purchaseSelected", errorOccurred: "errorOccurred" }, ngImport: i0, template: `
|
|
7229
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: PricingTableComponent, isStandalone: true, selector: "metrifox-pricing-table", inputs: { checkoutUsername: "checkoutUsername", productKey: "productKey", plansOnly: "plansOnly", singlePurchasesOnly: "singlePurchasesOnly", showTabHeader: "showTabHeader", theme: "theme" }, outputs: { planSelected: "planSelected", purchaseSelected: "purchaseSelected", errorOccurred: "errorOccurred" }, ngImport: i0, template: `
|
|
7004
7230
|
<div class="font-sans antialiased" [ngStyle]="cssVars()">
|
|
7005
7231
|
<!-- Loading State -->
|
|
7006
7232
|
@if (loading()) {
|
|
@@ -7032,7 +7258,7 @@ class PricingTableComponent {
|
|
|
7032
7258
|
<div class="flex justify-center">
|
|
7033
7259
|
<div class="w-full max-w-[1089px] bg-transparent h-full rounded-2xl md:px-6 py-5">
|
|
7034
7260
|
<!-- Tab Header (Listing Tabs) -->
|
|
7035
|
-
@if (
|
|
7261
|
+
@if (showTabHeaderSignal()) {
|
|
7036
7262
|
<div class="w-full flex justify-center border-b border-[var(--pt-tabs-border)] mb-6">
|
|
7037
7263
|
@for (tab of tabOptions(); track tab.value) {
|
|
7038
7264
|
<div
|
|
@@ -7054,31 +7280,36 @@ class PricingTableComponent {
|
|
|
7054
7280
|
<!-- Plans View -->
|
|
7055
7281
|
@if (showPlans() && selectedTab() === 'plan') {
|
|
7056
7282
|
<!-- Interval Toggle (Plan Tabs) -->
|
|
7057
|
-
|
|
7058
|
-
<div class="flex items-center
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
|
|
7283
|
+
<div class="flex items-center mb-4 justify-center">
|
|
7284
|
+
<div class="inline-flex items-center gap-1 bg-[var(--pt-interval-bg)] border border-[var(--pt-interval-border,var(--cp-tabs-border,var(--cp-section-content-border)))] p-1 rounded-lg shadow-sm">
|
|
7285
|
+
@for (interval of intervals(); track interval) {
|
|
7286
|
+
<div
|
|
7287
|
+
class="py-1.5 px-6 rounded-md cursor-pointer transition-all flex items-center justify-center"
|
|
7288
|
+
[class.bg-[var(--pt-interval-active-bg)]]="selectedInterval() === interval"
|
|
7289
|
+
[class.shadow-sm]="selectedInterval() === interval"
|
|
7290
|
+
[class.bg-transparent]="selectedInterval() !== interval"
|
|
7291
|
+
[class.hover:opacity-80]="selectedInterval() !== interval"
|
|
7292
|
+
(click)="selectInterval(interval)">
|
|
7293
|
+
<span
|
|
7294
|
+
class="text-sm font-medium whitespace-nowrap"
|
|
7295
|
+
[class.text-[var(--pt-interval-active-text)]]="selectedInterval() === interval"
|
|
7296
|
+
[class.text-[var(--pt-interval-inactive-text)]]="selectedInterval() !== interval">
|
|
7297
|
+
{{ formatInterval(interval) }}
|
|
7298
|
+
</span>
|
|
7299
|
+
</div>
|
|
7300
|
+
}
|
|
7074
7301
|
</div>
|
|
7075
|
-
|
|
7302
|
+
</div>
|
|
7076
7303
|
|
|
7077
7304
|
<!-- Plan Cards -->
|
|
7078
7305
|
<div class="w-full flex gap-x-4 px-4 justify-start overflow-x-auto flex-nowrap">
|
|
7079
7306
|
@for (plan of plans(); track plan.id) {
|
|
7080
7307
|
<div
|
|
7081
|
-
class="flex flex-col
|
|
7308
|
+
class="flex flex-col shrink-0 w-[330px]"
|
|
7309
|
+
[style.borderWidth]="'var(--pt-card-border-width, 1px)'"
|
|
7310
|
+
[style.borderStyle]="'solid'"
|
|
7311
|
+
[style.borderColor]="'var(--pt-card-border, #e5e7eb)'"
|
|
7312
|
+
[style.borderRadius]="'var(--pt-card-radius, 1rem)'"
|
|
7082
7313
|
[class.bg-[var(--pt-current-sub-card-header-bg)]]="plan.published_version.is_current_plan"
|
|
7083
7314
|
[class.bg-[var(--pt-card-header-bg)]]="!plan.published_version.is_current_plan">
|
|
7084
7315
|
<!-- Card Header -->
|
|
@@ -7102,7 +7333,7 @@ class PricingTableComponent {
|
|
|
7102
7333
|
[class.bg-gradient-to-b]="plan.published_version.is_current_plan"
|
|
7103
7334
|
[class.from-[var(--pt-card-gradient)]]="plan.published_version.is_current_plan"
|
|
7104
7335
|
[class.to-[var(--pt-card-bg)]]="plan.published_version.is_current_plan">
|
|
7105
|
-
|
|
7336
|
+
|
|
7106
7337
|
<!-- Description -->
|
|
7107
7338
|
@if (plan.published_version.description) {
|
|
7108
7339
|
<div class="h-[51px] mt-1 px-2">
|
|
@@ -7145,7 +7376,7 @@ class PricingTableComponent {
|
|
|
7145
7376
|
{{ getButtonText(plan.published_version) }}
|
|
7146
7377
|
</button>
|
|
7147
7378
|
|
|
7148
|
-
<!--
|
|
7379
|
+
<!-- Entitlements -->
|
|
7149
7380
|
@if (plan.published_version.entitlements?.length || plan.published_version.credit_attachments?.length) {
|
|
7150
7381
|
<div class="px-2 mt-4">
|
|
7151
7382
|
<p class="text-sm font-medium text-[var(--pt-feature-text)] mb-3">
|
|
@@ -7208,7 +7439,12 @@ class PricingTableComponent {
|
|
|
7208
7439
|
class="grid gap-4 px-4 lg:grid-cols-3 md:grid-cols-2 grid-cols-1"
|
|
7209
7440
|
[class.pb-[72px]]="cartItems().length > 0">
|
|
7210
7441
|
@for (purchase of filteredSinglePurchases(); track purchase.id) {
|
|
7211
|
-
<div class="flex flex-col bg-[var(--pt-card-header-bg)]
|
|
7442
|
+
<div class="flex flex-col bg-[var(--pt-card-header-bg)] w-full min-h-[187px]"
|
|
7443
|
+
[style.borderWidth]="'var(--pt-card-border-width, 1px)'"
|
|
7444
|
+
[style.borderStyle]="'solid'"
|
|
7445
|
+
[style.borderColor]="'var(--pt-card-border, #e5e7eb)'"
|
|
7446
|
+
[style.borderRadius]="'var(--pt-card-radius, 1rem)'"
|
|
7447
|
+
>
|
|
7212
7448
|
<!-- Card Header -->
|
|
7213
7449
|
<div class="px-4 pt-2 pb-[2px]">
|
|
7214
7450
|
<span class="text-sm font-medium text-[var(--pt-card-header-text)]">
|
|
@@ -7342,7 +7578,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
7342
7578
|
<div class="flex justify-center">
|
|
7343
7579
|
<div class="w-full max-w-[1089px] bg-transparent h-full rounded-2xl md:px-6 py-5">
|
|
7344
7580
|
<!-- Tab Header (Listing Tabs) -->
|
|
7345
|
-
@if (
|
|
7581
|
+
@if (showTabHeaderSignal()) {
|
|
7346
7582
|
<div class="w-full flex justify-center border-b border-[var(--pt-tabs-border)] mb-6">
|
|
7347
7583
|
@for (tab of tabOptions(); track tab.value) {
|
|
7348
7584
|
<div
|
|
@@ -7364,31 +7600,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
7364
7600
|
<!-- Plans View -->
|
|
7365
7601
|
@if (showPlans() && selectedTab() === 'plan') {
|
|
7366
7602
|
<!-- Interval Toggle (Plan Tabs) -->
|
|
7367
|
-
|
|
7368
|
-
<div class="flex items-center
|
|
7369
|
-
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
|
|
7381
|
-
|
|
7382
|
-
|
|
7383
|
-
|
|
7603
|
+
<div class="flex items-center mb-4 justify-center">
|
|
7604
|
+
<div class="inline-flex items-center gap-1 bg-[var(--pt-interval-bg)] border border-[var(--pt-interval-border,var(--cp-tabs-border,var(--cp-section-content-border)))] p-1 rounded-lg shadow-sm">
|
|
7605
|
+
@for (interval of intervals(); track interval) {
|
|
7606
|
+
<div
|
|
7607
|
+
class="py-1.5 px-6 rounded-md cursor-pointer transition-all flex items-center justify-center"
|
|
7608
|
+
[class.bg-[var(--pt-interval-active-bg)]]="selectedInterval() === interval"
|
|
7609
|
+
[class.shadow-sm]="selectedInterval() === interval"
|
|
7610
|
+
[class.bg-transparent]="selectedInterval() !== interval"
|
|
7611
|
+
[class.hover:opacity-80]="selectedInterval() !== interval"
|
|
7612
|
+
(click)="selectInterval(interval)">
|
|
7613
|
+
<span
|
|
7614
|
+
class="text-sm font-medium whitespace-nowrap"
|
|
7615
|
+
[class.text-[var(--pt-interval-active-text)]]="selectedInterval() === interval"
|
|
7616
|
+
[class.text-[var(--pt-interval-inactive-text)]]="selectedInterval() !== interval">
|
|
7617
|
+
{{ formatInterval(interval) }}
|
|
7618
|
+
</span>
|
|
7619
|
+
</div>
|
|
7620
|
+
}
|
|
7384
7621
|
</div>
|
|
7385
|
-
|
|
7622
|
+
</div>
|
|
7386
7623
|
|
|
7387
7624
|
<!-- Plan Cards -->
|
|
7388
7625
|
<div class="w-full flex gap-x-4 px-4 justify-start overflow-x-auto flex-nowrap">
|
|
7389
7626
|
@for (plan of plans(); track plan.id) {
|
|
7390
7627
|
<div
|
|
7391
|
-
class="flex flex-col
|
|
7628
|
+
class="flex flex-col shrink-0 w-[330px]"
|
|
7629
|
+
[style.borderWidth]="'var(--pt-card-border-width, 1px)'"
|
|
7630
|
+
[style.borderStyle]="'solid'"
|
|
7631
|
+
[style.borderColor]="'var(--pt-card-border, #e5e7eb)'"
|
|
7632
|
+
[style.borderRadius]="'var(--pt-card-radius, 1rem)'"
|
|
7392
7633
|
[class.bg-[var(--pt-current-sub-card-header-bg)]]="plan.published_version.is_current_plan"
|
|
7393
7634
|
[class.bg-[var(--pt-card-header-bg)]]="!plan.published_version.is_current_plan">
|
|
7394
7635
|
<!-- Card Header -->
|
|
@@ -7412,7 +7653,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
7412
7653
|
[class.bg-gradient-to-b]="plan.published_version.is_current_plan"
|
|
7413
7654
|
[class.from-[var(--pt-card-gradient)]]="plan.published_version.is_current_plan"
|
|
7414
7655
|
[class.to-[var(--pt-card-bg)]]="plan.published_version.is_current_plan">
|
|
7415
|
-
|
|
7656
|
+
|
|
7416
7657
|
<!-- Description -->
|
|
7417
7658
|
@if (plan.published_version.description) {
|
|
7418
7659
|
<div class="h-[51px] mt-1 px-2">
|
|
@@ -7455,7 +7696,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
7455
7696
|
{{ getButtonText(plan.published_version) }}
|
|
7456
7697
|
</button>
|
|
7457
7698
|
|
|
7458
|
-
<!--
|
|
7699
|
+
<!-- Entitlements -->
|
|
7459
7700
|
@if (plan.published_version.entitlements?.length || plan.published_version.credit_attachments?.length) {
|
|
7460
7701
|
<div class="px-2 mt-4">
|
|
7461
7702
|
<p class="text-sm font-medium text-[var(--pt-feature-text)] mb-3">
|
|
@@ -7518,7 +7759,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
7518
7759
|
class="grid gap-4 px-4 lg:grid-cols-3 md:grid-cols-2 grid-cols-1"
|
|
7519
7760
|
[class.pb-[72px]]="cartItems().length > 0">
|
|
7520
7761
|
@for (purchase of filteredSinglePurchases(); track purchase.id) {
|
|
7521
|
-
<div class="flex flex-col bg-[var(--pt-card-header-bg)]
|
|
7762
|
+
<div class="flex flex-col bg-[var(--pt-card-header-bg)] w-full min-h-[187px]"
|
|
7763
|
+
[style.borderWidth]="'var(--pt-card-border-width, 1px)'"
|
|
7764
|
+
[style.borderStyle]="'solid'"
|
|
7765
|
+
[style.borderColor]="'var(--pt-card-border, #e5e7eb)'"
|
|
7766
|
+
[style.borderRadius]="'var(--pt-card-radius, 1rem)'"
|
|
7767
|
+
>
|
|
7522
7768
|
<!-- Card Header -->
|
|
7523
7769
|
<div class="px-4 pt-2 pb-[2px]">
|
|
7524
7770
|
<span class="text-sm font-medium text-[var(--pt-card-header-text)]">
|
|
@@ -7629,6 +7875,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
7629
7875
|
type: Input
|
|
7630
7876
|
}], showTabHeader: [{
|
|
7631
7877
|
type: Input
|
|
7878
|
+
}], theme: [{
|
|
7879
|
+
type: Input
|
|
7632
7880
|
}], planSelected: [{
|
|
7633
7881
|
type: Output
|
|
7634
7882
|
}], purchaseSelected: [{
|
|
@@ -7666,8 +7914,8 @@ class MetrifoxModule {
|
|
|
7666
7914
|
ngModule: MetrifoxModule,
|
|
7667
7915
|
providers: [
|
|
7668
7916
|
provideHttpClient(withInterceptorsFromDi()),
|
|
7669
|
-
MetrifoxService
|
|
7670
|
-
]
|
|
7917
|
+
MetrifoxService
|
|
7918
|
+
]
|
|
7671
7919
|
};
|
|
7672
7920
|
}
|
|
7673
7921
|
/**
|
|
@@ -7676,7 +7924,7 @@ class MetrifoxModule {
|
|
|
7676
7924
|
static forChild() {
|
|
7677
7925
|
return {
|
|
7678
7926
|
ngModule: MetrifoxModule,
|
|
7679
|
-
providers: []
|
|
7927
|
+
providers: []
|
|
7680
7928
|
};
|
|
7681
7929
|
}
|
|
7682
7930
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: MetrifoxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
@@ -7694,12 +7942,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
7694
7942
|
imports: [
|
|
7695
7943
|
CommonModule,
|
|
7696
7944
|
CustomerPortalComponent,
|
|
7697
|
-
PricingTableComponent
|
|
7945
|
+
PricingTableComponent
|
|
7698
7946
|
],
|
|
7699
7947
|
exports: [
|
|
7700
7948
|
CustomerPortalComponent,
|
|
7701
|
-
PricingTableComponent
|
|
7702
|
-
]
|
|
7949
|
+
PricingTableComponent
|
|
7950
|
+
]
|
|
7703
7951
|
}]
|
|
7704
7952
|
}] });
|
|
7705
7953
|
/**
|
|
@@ -7722,7 +7970,7 @@ function provideMetrifox(config) {
|
|
|
7722
7970
|
}
|
|
7723
7971
|
return [
|
|
7724
7972
|
provideHttpClient(),
|
|
7725
|
-
MetrifoxService
|
|
7973
|
+
MetrifoxService
|
|
7726
7974
|
];
|
|
7727
7975
|
}
|
|
7728
7976
|
|