File

feature-libs/checkout/components/components/review-submit/review-submit.component.ts

Metadata

changeDetection ChangeDetectionStrategy.OnPush
selector cx-review-submit
templateUrl ./review-submit.component.html

Index

Properties
Methods
Accessors

Constructor

constructor(checkoutDeliveryService: CheckoutDeliveryFacade, checkoutPaymentService: CheckoutPaymentFacade, userAddressService: UserAddressService, activeCartService: ActiveCartService, translation: TranslationService, checkoutStepService: CheckoutStepService, paymentTypeService: PaymentTypeFacade, checkoutCostCenterService: CheckoutCostCenterFacade, userCostCenterService: UserCostCenterService)
Parameters :
Name Type Optional
checkoutDeliveryService CheckoutDeliveryFacade No
checkoutPaymentService CheckoutPaymentFacade No
userAddressService UserAddressService No
activeCartService ActiveCartService No
translation TranslationService No
checkoutStepService CheckoutStepService No
paymentTypeService PaymentTypeFacade No
checkoutCostCenterService CheckoutCostCenterFacade No
userCostCenterService UserCostCenterService No

Methods

getCheckoutStepUrl
getCheckoutStepUrl(stepType: CheckoutStepType)
Parameters :
Name Type Optional
stepType CheckoutStepType No
Returns : string | undefined
getCostCenterCard
getCostCenterCard(costCenter?: CostCenter)
Parameters :
Name Type Optional
costCenter CostCenter Yes
Returns : Observable<Card>
getDeliveryModeCard
getDeliveryModeCard(deliveryMode: DeliveryMode)
Parameters :
Name Type Optional
deliveryMode DeliveryMode No
Returns : Observable<Card>
getPaymentMethodCard
getPaymentMethodCard(paymentDetails: PaymentDetails)
Parameters :
Name Type Optional
paymentDetails PaymentDetails No
Returns : Observable<Card>
getPaymentTypeCard
getPaymentTypeCard(paymentType?: string)
Parameters :
Name Type Optional
paymentType string Yes
Returns : Observable<Card>
getPoNumberCard
getPoNumberCard(poNumber?: string | null)
Parameters :
Name Type Optional
poNumber string | null Yes
Returns : Observable<Card>
getShippingAddressCard
getShippingAddressCard(deliveryAddress: Address, countryName: string)
Parameters :
Name Type Optional
deliveryAddress Address No
countryName string No
Returns : Observable<Card>
paymentSteps
paymentSteps(steps: CheckoutStep[])
Parameters :
Name Type Optional
steps CheckoutStep[] No
Returns : CheckoutStep[]
shippingSteps
shippingSteps(steps: CheckoutStep[])
Parameters :
Name Type Optional
steps CheckoutStep[] No
Returns : CheckoutStep[]

Properties

checkoutStepType
Default value : CheckoutStepType
iconTypes
Default value : ICON_TYPE
promotionLocation
Type : PromotionLocation
Default value : PromotionLocation.ActiveCart

Accessors

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>
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""