feature-libs/checkout/components/components/review-submit/review-submit.component.ts
| changeDetection | ChangeDetectionStrategy.OnPush |
| selector | cx-review-submit |
| templateUrl | ./review-submit.component.html |
Properties |
Methods |
Accessors |
constructor(checkoutDeliveryService: CheckoutDeliveryFacade, checkoutPaymentService: CheckoutPaymentFacade, userAddressService: UserAddressService, activeCartService: ActiveCartService, translation: TranslationService, checkoutStepService: CheckoutStepService, paymentTypeService: PaymentTypeFacade, checkoutCostCenterService: CheckoutCostCenterFacade, userCostCenterService: UserCostCenterService)
|
||||||||||||||||||||||||||||||
|
Parameters :
|
| getCheckoutStepUrl | ||||||
getCheckoutStepUrl(stepType: CheckoutStepType)
|
||||||
|
Parameters :
Returns :
string | undefined
|
| getCostCenterCard | ||||||
getCostCenterCard(costCenter?: CostCenter)
|
||||||
|
Parameters :
Returns :
Observable<Card>
|
| getDeliveryModeCard | ||||||
getDeliveryModeCard(deliveryMode: DeliveryMode)
|
||||||
|
Parameters :
Returns :
Observable<Card>
|
| getPaymentMethodCard | ||||||
getPaymentMethodCard(paymentDetails: PaymentDetails)
|
||||||
|
Parameters :
Returns :
Observable<Card>
|
| getPaymentTypeCard | ||||||
getPaymentTypeCard(paymentType?: string)
|
||||||
|
Parameters :
Returns :
Observable<Card>
|
| getPoNumberCard | ||||||
getPoNumberCard(poNumber?: string | null)
|
||||||
|
Parameters :
Returns :
Observable<Card>
|
| getShippingAddressCard |
getShippingAddressCard(deliveryAddress: Address, countryName: string)
|
|
Returns :
Observable<Card>
|
| paymentSteps | ||||||
paymentSteps(steps: CheckoutStep[])
|
||||||
|
Parameters :
Returns :
CheckoutStep[]
|
| shippingSteps | ||||||
shippingSteps(steps: CheckoutStep[])
|
||||||
|
Parameters :
Returns :
CheckoutStep[]
|
| checkoutStepType |
Default value : CheckoutStepType
|
| iconTypes |
Default value : ICON_TYPE
|
| promotionLocation |
Type : PromotionLocation
|
Default value : PromotionLocation.ActiveCart
|
| cart$ |
getcart$()
|
| entries$ |
getentries$()
|
| steps$ |
getsteps$()
|
| deliveryAddress$ |
getdeliveryAddress$()
|
| deliveryMode$ |
getdeliveryMode$()
|
| paymentDetails$ |
getpaymentDetails$()
|
| countryName$ |
getcountryName$()
|
| poNumber$ |
getpoNumber$()
|
| paymentType$ |
getpaymentType$()
|
| isAccountPayment$ |
getisAccountPayment$()
|
| costCenter$ |
getcostCenter$()
|
import { ChangeDetectionStrategy, Component } from '@angular/core';
import {
CheckoutCostCenterFacade,
CheckoutDeliveryFacade,
CheckoutPaymentFacade,
checkoutPaymentSteps,
checkoutShippingSteps,
CheckoutStep,
CheckoutStepType,
PaymentTypeFacade,
} from '@spartacus/checkout/root';
import {
ActiveCartService,
Address,
Cart,
CostCenter,
Country,
DeliveryMode,
OrderEntry,
PaymentDetails,
PromotionLocation,
TranslationService,
UserAddressService,
UserCostCenterService,
} from '@spartacus/core';
import { Card, ICON_TYPE } from '@spartacus/storefront';
import { combineLatest, Observable } from 'rxjs';
import { filter, map, switchMap, tap } from 'rxjs/operators';
import { CheckoutStepService } from '../../services/index';
@Component({
selector: 'cx-review-submit',
templateUrl: './review-submit.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ReviewSubmitComponent {
iconTypes = ICON_TYPE;
checkoutStepType = CheckoutStepType;
promotionLocation: PromotionLocation = PromotionLocation.ActiveCart;
constructor(
protected checkoutDeliveryService: CheckoutDeliveryFacade,
protected checkoutPaymentService: CheckoutPaymentFacade,
protected userAddressService: UserAddressService,
protected activeCartService: ActiveCartService,
protected translation: TranslationService,
protected checkoutStepService: CheckoutStepService,
protected paymentTypeService: PaymentTypeFacade,
protected checkoutCostCenterService: CheckoutCostCenterFacade,
protected userCostCenterService: UserCostCenterService
) {}
get cart$(): Observable<Cart> {
return this.activeCartService.getActive();
}
get entries$(): Observable<OrderEntry[]> {
return this.activeCartService.getEntries();
}
get steps$(): Observable<CheckoutStep[]> {
return this.checkoutStepService.steps$;
}
get deliveryAddress$(): Observable<Address> {
return this.checkoutDeliveryService.getDeliveryAddress();
}
get deliveryMode$(): Observable<DeliveryMode | null | undefined> {
return this.checkoutDeliveryService.getSelectedDeliveryMode().pipe(
tap((selected: DeliveryMode | null | undefined) => {
if (selected === null) {
this.checkoutDeliveryService.loadSupportedDeliveryModes();
}
})
);
}
get paymentDetails$(): Observable<PaymentDetails> {
return this.checkoutPaymentService.getPaymentDetails();
}
get countryName$(): Observable<string | undefined> {
return this.deliveryAddress$.pipe(
switchMap((address: Address) =>
this.userAddressService.getCountry(address?.country?.isocode as string)
),
tap((country: Country) => {
if (country === null) {
this.userAddressService.loadDeliveryCountries();
}
}),
map((country: Country) => country && country.name)
);
}
get poNumber$(): Observable<string | undefined> {
return this.paymentTypeService.getPoNumber();
}
get paymentType$(): Observable<string | undefined> {
return this.paymentTypeService.getSelectedPaymentType();
}
get isAccountPayment$(): Observable<boolean> {
return this.paymentTypeService.isAccountPayment();
}
get costCenter$(): Observable<CostCenter | undefined> {
return this.userCostCenterService.getActiveCostCenters().pipe(
filter((costCenters) => Boolean(costCenters)),
switchMap((costCenters) => {
return this.checkoutCostCenterService.getCostCenter().pipe(
map((code) => {
return costCenters.find((cc) => cc.code === code);
})
);
})
);
}
getShippingAddressCard(
deliveryAddress: Address,
countryName: string
): Observable<Card> {
return combineLatest([
this.translation.translate('addressCard.shipTo'),
]).pipe(
map(([textTitle]) => {
if (!countryName) {
countryName = deliveryAddress?.country?.isocode as string;
}
let region = '';
if (
deliveryAddress &&
deliveryAddress.region &&
deliveryAddress.region.isocode
) {
region = deliveryAddress.region.isocode + ', ';
}
return {
title: textTitle,
textBold: deliveryAddress.firstName + ' ' + deliveryAddress.lastName,
text: [
deliveryAddress.line1,
deliveryAddress.line2,
deliveryAddress.town + ', ' + region + countryName,
deliveryAddress.postalCode,
deliveryAddress.phone,
],
} as Card;
})
);
}
getCostCenterCard(costCenter?: CostCenter): Observable<Card> {
return combineLatest([
this.translation.translate('checkoutPO.costCenter'),
]).pipe(
map(([textTitle]) => {
return {
title: textTitle,
textBold: costCenter?.name,
text: ['(' + costCenter?.unit?.name + ')'],
};
})
);
}
getDeliveryModeCard(deliveryMode: DeliveryMode): Observable<Card> {
return combineLatest([
this.translation.translate('checkoutShipping.shippingMethod'),
]).pipe(
map(([textTitle]) => {
return {
title: textTitle,
textBold: deliveryMode.name,
text: [
deliveryMode.description,
deliveryMode.deliveryCost?.formattedValue
? deliveryMode.deliveryCost?.formattedValue
: '',
],
} as Card;
})
);
}
getPaymentMethodCard(paymentDetails: PaymentDetails): Observable<Card> {
return combineLatest([
this.translation.translate('paymentForm.payment'),
this.translation.translate('paymentCard.expires', {
month: paymentDetails.expiryMonth,
year: paymentDetails.expiryYear,
}),
this.translation.translate('paymentForm.billingAddress'),
]).pipe(
map(([textTitle, textExpires, billingAddress]) => {
const region = paymentDetails.billingAddress?.region?.isocode
? paymentDetails.billingAddress?.region?.isocode + ', '
: '';
return {
title: textTitle,
textBold: paymentDetails.accountHolderName,
text: [paymentDetails.cardNumber, textExpires],
paragraphs: [
{
title: billingAddress + ':',
text: [
paymentDetails.billingAddress?.firstName +
' ' +
paymentDetails.billingAddress?.lastName,
paymentDetails.billingAddress?.line1,
paymentDetails.billingAddress?.town +
', ' +
region +
paymentDetails.billingAddress?.country?.isocode,
paymentDetails.billingAddress?.postalCode,
],
},
],
} as Card;
})
);
}
getPoNumberCard(poNumber?: string | null): Observable<Card> {
return combineLatest([
this.translation.translate('checkoutReview.poNumber'),
this.translation.translate('checkoutPO.noPoNumber'),
]).pipe(
map(([textTitle, noneTextTitle]) => {
return {
title: textTitle,
textBold: poNumber ? poNumber : noneTextTitle,
};
})
);
}
getPaymentTypeCard(paymentType?: string): Observable<Card> {
return combineLatest([
this.translation.translate('checkoutProgress.methodOfPayment'),
this.translation.translate('paymentTypes.paymentType_' + paymentType),
]).pipe(
map(([textTitle, paymentTypeTranslation]) => {
return {
title: textTitle,
textBold: paymentTypeTranslation,
};
})
);
}
getCheckoutStepUrl(stepType: CheckoutStepType): string | undefined {
const step = this.checkoutStepService.getCheckoutStep(stepType);
return step && step.routeName;
}
shippingSteps(steps: CheckoutStep[]): CheckoutStep[] {
return steps.filter((step) => checkoutShippingSteps.includes(step.type[0]));
}
paymentSteps(steps: CheckoutStep[]): CheckoutStep[] {
return steps.filter((step) => checkoutPaymentSteps.includes(step.type[0]));
}
}
<div class="cx-review">
<!-- TITLE -->
<h2 class="cx-review-title d-none d-lg-block d-xl-block">
{{ 'checkoutReview.review' | cxTranslate }}
</h2>
<div class="cx-review-summary row">
<ng-container *ngIf="(steps$ | async)?.slice(0, -1) as steps">
<div class="col-md-12 col-lg-6 col-xl-6 cx-review-payment-col">
<ng-container *ngFor="let step of paymentSteps(steps)">
<ng-container [ngSwitch]="step.type[0]">
<ng-container *ngSwitchCase="checkoutStepType.PAYMENT_TYPE">
<ng-container *ngTemplateOutlet="poNumber"></ng-container>
</ng-container>
<ng-container *ngSwitchCase="checkoutStepType.PAYMENT_TYPE">
<ng-container *ngTemplateOutlet="paymentType"></ng-container>
</ng-container>
<ng-container *ngSwitchCase="checkoutStepType.PAYMENT_DETAILS">
<ng-container *ngTemplateOutlet="paymentMethod"></ng-container>
</ng-container>
<ng-container *ngSwitchCase="checkoutStepType.SHIPPING_ADDRESS">
<ng-container *ngTemplateOutlet="costCenter"></ng-container>
</ng-container>
</ng-container>
</ng-container>
</div>
<div class="col-md-12 col-lg-6 col-xl-6 cx-review-shipping-col">
<ng-container *ngFor="let step of shippingSteps(steps)">
<ng-container [ngSwitch]="step.type[0]">
<ng-container *ngSwitchCase="checkoutStepType.SHIPPING_ADDRESS">
<ng-container *ngTemplateOutlet="shippingAddress"></ng-container>
</ng-container>
<ng-container *ngSwitchCase="checkoutStepType.DELIVERY_MODE">
<ng-container *ngTemplateOutlet="deliveryMode"></ng-container>
</ng-container>
</ng-container>
</ng-container>
</div>
</ng-container>
</div>
<!-- PO NUMBER SECTION -->
<ng-template #poNumber>
<div class="cx-review-summary-card">
<cx-card [content]="getPoNumberCard(poNumber$ | async) | async"></cx-card>
<div class="cx-review-summary-edit-step">
<a
[attr.aria-label]="'checkoutReview.editPaymentType' | cxTranslate"
[routerLink]="
{
cxRoute: getCheckoutStepUrl(checkoutStepType.PAYMENT_TYPE)
} | cxUrl
"
><cx-icon aria-hidden="true" [type]="iconTypes.PENCIL"></cx-icon
></a>
</div>
</div>
</ng-template>
<!-- PAYMENT TYPE SECTION -->
<ng-template #paymentType>
<div class="cx-review-summary-card">
<cx-card
*ngIf="paymentType$ | async as paymentType"
[content]="getPaymentTypeCard(paymentType) | async"
></cx-card>
<div class="cx-review-summary-edit-step">
<a
[attr.aria-label]="'checkoutReview.editPaymentType' | cxTranslate"
[routerLink]="
{
cxRoute: getCheckoutStepUrl(checkoutStepType.PAYMENT_TYPE)
} | cxUrl
"
><cx-icon aria-hidden="true" [type]="iconTypes.PENCIL"></cx-icon
></a>
</div>
</div>
</ng-template>
<!-- COST CENTER SECTION -->
<ng-template #costCenter>
<ng-container *ngIf="isAccountPayment$ | async">
<div class="cx-review-summary-card">
<cx-card
*ngIf="costCenter$ | async as costCenter"
[content]="getCostCenterCard(costCenter) | async"
></cx-card>
<div class="cx-review-summary-edit-step">
<a
[attr.aria-label]="
'checkoutReview.editShippingAddressDetails' | cxTranslate
"
[routerLink]="
{
cxRoute: getCheckoutStepUrl(checkoutStepType.SHIPPING_ADDRESS)
} | cxUrl
"
><cx-icon aria-hidden="true" [type]="iconTypes.PENCIL"></cx-icon
></a>
</div>
</div>
</ng-container>
</ng-template>
<!-- SHIPPING ADDRESS SECTION -->
<ng-template #shippingAddress>
<div
*ngIf="deliveryAddress$ | async as deliveryAddress"
class="cx-review-summary-card cx-review-card-address"
>
<cx-card
*ngIf="countryName$ | async as countryName"
[content]="getShippingAddressCard(deliveryAddress, countryName) | async"
></cx-card>
<div class="cx-review-summary-edit-step">
<a
[attr.aria-label]="
'checkoutReview.editShippingAddressDetails' | cxTranslate
"
[routerLink]="
{
cxRoute: getCheckoutStepUrl(checkoutStepType.SHIPPING_ADDRESS)
} | cxUrl
"
><cx-icon aria-hidden="true" [type]="iconTypes.PENCIL"></cx-icon
></a>
</div>
</div>
</ng-template>
<!-- DELIVERY MODE SECTION -->
<ng-template #deliveryMode>
<div class="cx-review-summary-card cx-review-card-shipping">
<cx-card
*ngIf="deliveryMode$ | async as deliveryMode"
[content]="getDeliveryModeCard(deliveryMode) | async"
></cx-card>
<div class="cx-review-summary-edit-step">
<a
[attr.aria-label]="'checkoutReview.editDeliveryMode' | cxTranslate"
[routerLink]="
{ cxRoute: getCheckoutStepUrl(checkoutStepType.DELIVERY_MODE) }
| cxUrl
"
>
<cx-icon aria-hidden="true" [type]="iconTypes.PENCIL"></cx-icon>
</a>
</div>
</div>
</ng-template>
<!-- PAYMENT METHOD SECTION -->
<ng-template #paymentMethod>
<div class="cx-review-summary-card cx-review-card-payment">
<div>
<cx-card
*ngIf="paymentDetails$ | async as paymentDetails"
[content]="getPaymentMethodCard(paymentDetails) | async"
></cx-card>
</div>
<div class="cx-review-summary-edit-step">
<a
[attr.aria-label]="'checkoutReview.editPaymentDetails' | cxTranslate"
[routerLink]="
{ cxRoute: getCheckoutStepUrl(checkoutStepType.PAYMENT_DETAILS) }
| cxUrl
"
>
<cx-icon aria-hidden="true" [type]="iconTypes.PENCIL"></cx-icon>
</a>
</div>
</div>
</ng-template>
<!-- CART ITEM SECTION -->
<ng-container *ngIf="cart$ | async as cart">
<h4 class="cx-review-cart-total d-none d-lg-block d-xl-block">
{{
'cartItems.cartTotal'
| cxTranslate: { count: cart.deliveryItemsQuantity }
}}:
{{ cart.totalPrice?.formattedValue }}
</h4>
<h4 class="cx-review-cart-heading d-block d-lg-none d-xl-none">
{{ 'checkoutReview.placeOrder' | cxTranslate }}
</h4>
<div
class="cx-review-cart-item col-md-12"
*ngIf="entries$ | async as entries"
>
<cx-promotions
[promotions]="
(cart.appliedOrderPromotions || []).concat(
cart.potentialOrderPromotions || []
)
"
></cx-promotions>
<cx-cart-item-list
[items]="entries"
[readonly]="true"
[promotionLocation]="promotionLocation"
></cx-cart-item-list>
</div>
</ng-container>
</div>