feature-libs/checkout/components/components/shipping-address/shipping-address.component.ts
| changeDetection | ChangeDetectionStrategy.OnPush |
| selector | cx-shipping-address |
| templateUrl | ./shipping-address.component.html |
Properties |
Methods |
Accessors |
constructor(userAddressService: UserAddressService, checkoutDeliveryService: CheckoutDeliveryFacade, activatedRoute: ActivatedRoute, translation: TranslationService, activeCartService: ActiveCartService, checkoutStepService: CheckoutStepService, paymentTypeService?: PaymentTypeFacade, userCostCenterService?: UserCostCenterService, checkoutCostCenterService?: CheckoutCostCenterFacade)
|
||||||||||||||||||||||||||||||
|
Parameters :
|
| addAddress | ||||||
addAddress(address: Address)
|
||||||
|
Parameters :
Returns :
void
|
| back |
back()
|
|
Returns :
void
|
| getCardContent | ||||||||||||||||||
getCardContent(address: Address, selected: any, textDefaultShippingAddress: string, textShipToThisAddress: string, textSelected: string)
|
||||||||||||||||||
|
Parameters :
Returns :
Card
|
| getSupportedAddresses |
getSupportedAddresses()
|
|
Returns :
Observable<Address[]>
|
| hideNewAddressForm | ||||||||
hideNewAddressForm(goPrevious: boolean)
|
||||||||
|
Parameters :
Returns :
void
|
| next |
next()
|
|
Returns :
void
|
| ngOnDestroy |
ngOnDestroy()
|
|
Returns :
void
|
| ngOnInit |
ngOnInit()
|
|
Returns :
void
|
| selectAddress | ||||||
selectAddress(address: Address)
|
||||||
|
Parameters :
Returns :
void
|
| selectDefaultAddress | |||||||||
selectDefaultAddress(addresses: Address[], selected: Address | undefined)
|
|||||||||
|
Parameters :
Returns :
void
|
| showNewAddressForm |
showNewAddressForm()
|
|
Returns :
void
|
| addressFormOpened |
Default value : false
|
| doneAutoSelect |
Default value : false
|
| forceLoader |
Default value : false
|
| isAccountPayment |
Default value : false
|
| selectedAddress |
Type : Address
|
| Protected subscriptions |
Default value : new Subscription()
|
| isGuestCheckout |
getisGuestCheckout()
|
| backBtnText |
getbackBtnText()
|
| isLoading$ |
getisLoading$()
|
| selectedAddress$ |
getselectedAddress$()
|
| cards$ |
getcards$()
|
import {
ChangeDetectionStrategy,
Component,
OnDestroy,
OnInit,
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import {
CheckoutCostCenterFacade,
CheckoutDeliveryFacade,
PaymentTypeFacade,
} from '@spartacus/checkout/root';
import {
ActiveCartService,
Address,
TranslationService,
UserAddressService,
UserCostCenterService,
} from '@spartacus/core';
import { Card } from '@spartacus/storefront';
import { combineLatest, Observable, Subscription } from 'rxjs';
import { distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators';
import { CheckoutStepService } from '../../services/checkout-step.service';
export interface CardWithAddress {
card: Card;
address: Address;
}
@Component({
selector: 'cx-shipping-address',
templateUrl: './shipping-address.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ShippingAddressComponent implements OnInit, OnDestroy {
addressFormOpened = false;
forceLoader = false; // this helps with smoother steps transition
selectedAddress: Address;
doneAutoSelect = false;
isAccountPayment = false;
protected subscriptions = new Subscription();
constructor(
protected userAddressService: UserAddressService,
protected checkoutDeliveryService: CheckoutDeliveryFacade,
protected activatedRoute: ActivatedRoute,
protected translation: TranslationService,
protected activeCartService: ActiveCartService,
protected checkoutStepService: CheckoutStepService,
protected paymentTypeService?: PaymentTypeFacade,
protected userCostCenterService?: UserCostCenterService,
protected checkoutCostCenterService?: CheckoutCostCenterFacade
) {}
get isGuestCheckout(): boolean {
return this.activeCartService.isGuestCart();
}
get backBtnText(): string {
return this.checkoutStepService.getBackBntText(this.activatedRoute);
}
get isLoading$(): Observable<boolean> {
return this.userAddressService.getAddressesLoading();
}
get selectedAddress$(): Observable<Address> {
return this.checkoutDeliveryService.getDeliveryAddress().pipe(
tap((address) => {
if (
address &&
(this.selectedAddress === undefined ||
this.selectedAddress.id !== address.id)
) {
this.selectedAddress = address;
if (this.forceLoader) {
this.next();
}
}
})
);
}
get cards$(): Observable<CardWithAddress[]> {
return combineLatest([
this.getSupportedAddresses(),
this.selectedAddress$,
this.translation.translate('checkoutAddress.defaultShippingAddress'),
this.translation.translate('checkoutAddress.shipToThisAddress'),
this.translation.translate('addressCard.selected'),
]).pipe(
tap(([addresses, selected]) =>
this.selectDefaultAddress(addresses, selected)
),
map(([addresses, selected, textDefault, textShipTo, textSelected]) =>
(<any>addresses).map((address: Address) => ({
address,
card: this.getCardContent(
address,
selected,
textDefault,
textShipTo,
textSelected
),
}))
)
);
}
getSupportedAddresses(): Observable<Address[]> {
if (
this.isAccountPayment &&
this.checkoutCostCenterService &&
this.userCostCenterService
) {
return this.checkoutCostCenterService.getCostCenter().pipe(
distinctUntilChanged(),
switchMap((selected) => {
this.doneAutoSelect = false;
return (
this.userCostCenterService?.getCostCenterAddresses(
selected as string
) ?? []
);
})
);
}
return this.userAddressService.getAddresses();
}
selectDefaultAddress(addresses: Address[], selected: Address | undefined) {
if (
!this.doneAutoSelect &&
addresses &&
addresses.length &&
(!selected || Object.keys(selected).length === 0)
) {
if (this.isAccountPayment) {
if (addresses.length === 1) {
this.selectAddress(addresses[0]);
}
} else {
selected = addresses.find((address) => address.defaultAddress);
if (selected) {
this.selectAddress(selected);
}
}
this.doneAutoSelect = true;
}
}
ngOnInit(): void {
if (
this.paymentTypeService &&
this.userCostCenterService &&
this.checkoutCostCenterService
) {
this.subscriptions.add(
this.paymentTypeService
.isAccountPayment()
.pipe(distinctUntilChanged())
.subscribe((isAccount) => (this.isAccountPayment = isAccount))
);
}
if (!this.isGuestCheckout && !this.isAccountPayment) {
this.userAddressService.loadAddresses();
}
}
getCardContent(
address: Address,
selected: any,
textDefaultShippingAddress: string,
textShipToThisAddress: string,
textSelected: string
): Card {
let region = '';
if (address.region && address.region.isocode) {
region = address.region.isocode + ', ';
}
return {
title: address.defaultAddress ? textDefaultShippingAddress : '',
textBold: address.firstName + ' ' + address.lastName,
text: [
address.line1,
address.line2,
address.town + ', ' + region + address.country?.isocode,
address.postalCode,
address.phone,
],
actions: [{ name: textShipToThisAddress, event: 'send' }],
header: selected && selected.id === address.id ? textSelected : '',
} as Card;
}
selectAddress(address: Address): void {
this.checkoutDeliveryService.setDeliveryAddress(address);
}
addAddress(address: Address): void {
this.forceLoader = true;
if (Boolean(address)) {
this.checkoutDeliveryService.createAndSetAddress(address);
} else {
this.forceLoader = false;
this.next();
}
}
showNewAddressForm(): void {
this.addressFormOpened = true;
}
hideNewAddressForm(goPrevious: boolean = false): void {
this.addressFormOpened = false;
if (goPrevious) {
this.back();
}
}
next(): void {
this.checkoutStepService.next(this.activatedRoute);
}
back(): void {
this.checkoutStepService.back(this.activatedRoute);
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
}
<ng-container *ngIf="cards$ | async as cards">
<h2 class="cx-checkout-title d-none d-lg-block d-xl-block">
{{ 'checkoutAddress.shippingAddress' | cxTranslate }}
</h2>
<ng-container *ngIf="!forceLoader && !(isLoading$ | async); else loading">
<ng-container
*ngIf="
isAccountPayment || (cards?.length && !addressFormOpened);
else newAddressForm
"
>
<p class="cx-checkout-text">
{{ 'checkoutAddress.selectYourShippingAddress' | cxTranslate }}
</p>
<div class="cx-checkout-btns row" *ngIf="!isAccountPayment">
<div class="col-sm-12 col-md-12 col-lg-6">
<button
class="btn btn-block btn-action"
(click)="showNewAddressForm()"
>
{{ 'checkoutAddress.addNewAddress' | cxTranslate }}
</button>
</div>
</div>
<div class="cx-checkout-body row">
<div
class="cx-shipping-address-card col-md-12 col-lg-6"
*ngFor="let card of cards; let i = index"
>
<div
class="cx-shipping-address-card-inner"
(click)="selectAddress(card.address)"
>
<cx-card
[border]="true"
[fitToContainer]="true"
[content]="card.card"
(sendCard)="selectAddress(card.address)"
></cx-card>
</div>
</div>
</div>
<div class="cx-checkout-btns row">
<div class="col-md-12 col-lg-6">
<button class="cx-btn btn btn-block btn-action" (click)="back()">
{{ backBtnText | cxTranslate }}
</button>
</div>
<div class="col-md-12 col-lg-6">
<button
class="cx-btn btn btn-block btn-primary"
[disabled]="!selectedAddress?.id"
(click)="next()"
>
{{ 'common.continue' | cxTranslate }}
</button>
</div>
</div>
</ng-container>
<ng-template #newAddressForm>
<cx-address-form
*ngIf="cards.length; else initialAddressForm"
[showTitleCode]="true"
(backToAddress)="hideNewAddressForm(false)"
(submitAddress)="addAddress($event)"
></cx-address-form>
<ng-template #initialAddressForm>
<cx-address-form
[showTitleCode]="true"
[setAsDefaultField]="!isGuestCheckout"
[addressData]="selectedAddress"
cancelBtnLabel="{{ backBtnText | cxTranslate }}"
(backToAddress)="hideNewAddressForm(true)"
(submitAddress)="addAddress($event)"
></cx-address-form>
</ng-template>
</ng-template>
</ng-container>
<ng-template #loading>
<div class="cx-spinner">
<cx-spinner></cx-spinner>
</div>
</ng-template>
</ng-container>