File

projects/storefrontlib/cms-components/cart/cart-coupon/cart-coupon.component.ts

Implements

OnInit OnDestroy

Metadata

selector cx-cart-coupon
templateUrl ./cart-coupon.component.html

Index

Properties
Methods

Constructor

constructor(cartVoucherService: CartVoucherService, formBuilder: FormBuilder, customerCouponService: CustomerCouponService, activeCartService: ActiveCartService)
Parameters :
Name Type Optional
cartVoucherService CartVoucherService No
formBuilder FormBuilder No
customerCouponService CustomerCouponService No
activeCartService ActiveCartService No

Methods

applyCustomerCoupon
applyCustomerCoupon(couponId: string)
Parameters :
Name Type Optional
couponId string No
Returns : void
applyVoucher
applyVoucher()
Returns : void
close
close(event: UIEvent)
Parameters :
Name Type Optional
event UIEvent No
Returns : void
disableClose
disableClose()
Returns : void
Protected getApplicableCustomerCoupons
getApplicableCustomerCoupons(cart: Cart, coupons: CustomerCoupon[])
Parameters :
Name Type Optional
cart Cart No
coupons CustomerCoupon[] No
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
Protected onError
onError(error: boolean)
Parameters :
Name Type Optional
error boolean No
Returns : void
onSuccess
onSuccess(success: boolean)
Parameters :
Name Type Optional
success boolean No
Returns : void

Properties

applicableCoupons
Type : CustomerCoupon[]
cart$
Type : Observable<Cart>
cartId
Type : string
cartIsLoading$
Type : Observable<boolean>
couponBoxIsActive
Default value : false
couponForm
Type : FormGroup
Protected ignoreCloseEvent
Default value : false
MAX_CUSTOMER_COUPON_PAGE
Type : number
Default value : 100
Protected subscription
Default value : new Subscription()
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import {
  ActiveCartService,
  Cart,
  CartVoucherService,
  CustomerCoupon,
  CustomerCouponSearchResult,
  CustomerCouponService,
} from '@spartacus/core';
import { combineLatest, Observable, Subscription } from 'rxjs';
import { map, tap } from 'rxjs/operators';

@Component({
  selector: 'cx-cart-coupon',
  templateUrl: './cart-coupon.component.html',
})
export class CartCouponComponent implements OnInit, OnDestroy {
  MAX_CUSTOMER_COUPON_PAGE = 100;
  couponForm: FormGroup;
  cartIsLoading$: Observable<boolean>;
  cart$: Observable<Cart>;
  cartId: string;
  applicableCoupons: CustomerCoupon[];

  protected ignoreCloseEvent = false;

  protected subscription = new Subscription();

  couponBoxIsActive = false;

  constructor(
    protected cartVoucherService: CartVoucherService,
    protected formBuilder: FormBuilder,
    protected customerCouponService: CustomerCouponService,
    protected activeCartService: ActiveCartService
  ) {}

  ngOnInit() {
    if (this.customerCouponService) {
      this.customerCouponService.loadCustomerCoupons(
        this.MAX_CUSTOMER_COUPON_PAGE
      );
    }

    this.cart$ = combineLatest([
      this.activeCartService.getActive(),
      this.activeCartService.getActiveCartId(),
      this.customerCouponService.getCustomerCoupons(
        this.MAX_CUSTOMER_COUPON_PAGE
      ),
    ]).pipe(
      tap(
        ([cart, activeCardId, customerCoupons]: [
          Cart,
          string,
          CustomerCouponSearchResult
        ]) => {
          this.cartId = activeCardId;
          this.getApplicableCustomerCoupons(cart, customerCoupons.coupons);
        }
      ),
      map(([cart]: [Cart, string, CustomerCouponSearchResult]) => cart)
    );

    this.cartIsLoading$ = this.activeCartService
      .isStable()
      .pipe(map((loaded) => !loaded));

    this.cartVoucherService.resetAddVoucherProcessingState();

    this.couponForm = this.formBuilder.group({
      couponCode: ['', [Validators.required]],
    });

    // TODO(#7241): Replace process subscriptions with event listeners and drop process for ADD_VOUCHER
    this.subscription.add(
      this.cartVoucherService
        .getAddVoucherResultSuccess()
        .subscribe((success) => {
          this.onSuccess(success);
        })
    );

    // TODO(#7241): Replace process subscriptions with event listeners and drop process for ADD_VOUCHER
    this.subscription.add(
      this.cartVoucherService.getAddVoucherResultError().subscribe((error) => {
        this.onError(error);
      })
    );
  }

  protected onError(error: boolean) {
    if (error) {
      this.customerCouponService.loadCustomerCoupons(
        this.MAX_CUSTOMER_COUPON_PAGE
      );
      this.cartVoucherService.resetAddVoucherProcessingState();
    }
  }

  onSuccess(success: boolean) {
    if (success) {
      this.couponForm.reset();
      this.cartVoucherService.resetAddVoucherProcessingState();
    }
  }

  protected getApplicableCustomerCoupons(
    cart: Cart,
    coupons: CustomerCoupon[]
  ): void {
    this.applicableCoupons = coupons || [];
    if (cart.appliedVouchers) {
      cart.appliedVouchers.forEach((appliedVoucher) => {
        this.applicableCoupons = this.applicableCoupons.filter(
          (coupon) => coupon.couponId !== appliedVoucher.code
        );
      });
    }
  }

  applyVoucher(): void {
    if (this.couponForm.valid) {
      this.cartVoucherService.addVoucher(
        this.couponForm.value.couponCode,
        this.cartId
      );
    } else {
      this.couponForm.markAllAsTouched();
    }
  }

  applyCustomerCoupon(couponId: string): void {
    this.cartVoucherService.addVoucher(couponId, this.cartId);
    this.couponBoxIsActive = false;
  }

  close(event: UIEvent): void {
    if (!this.ignoreCloseEvent) {
      this.couponBoxIsActive = false;
      if (event && event.target) {
        (<HTMLElement>event.target).blur();
      }
    }
    this.ignoreCloseEvent = false;
  }

  disableClose(): void {
    this.ignoreCloseEvent = true;
  }

  ngOnDestroy(): void {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
    this.cartVoucherService.resetAddVoucherProcessingState();
  }
}
<ng-container *ngIf="cart$ | async as cart">
  <div class="cx-cart-coupon-title">
    {{ 'voucher.coupon' | cxTranslate }}
  </div>
  <div class="form-group">
    <form (ngSubmit)="applyVoucher()" [formGroup]="couponForm">
      <div class="cx-cart-coupon-container">
        <input
          aria-required="true"
          type="text"
          class="form-control input-coupon-code"
          formControlName="couponCode"
          placeholder="{{ 'voucher.placeholder' | cxTranslate }} "
        />
        <button
          class="btn btn-block btn-action apply-coupon-button"
          type="submit"
          [disabled]="cartIsLoading$ | async"
          [class.disabled]="cartIsLoading$ | async"
        >
          {{ 'voucher.apply' | cxTranslate }}
        </button>
        <cx-form-errors
          aria-live="assertive"
          aria-atomic="true"
          [control]="couponForm.get('couponCode')"
        ></cx-form-errors>
      </div>
    </form>
  </div>

  <cx-applied-coupons
    [vouchers]="cart.appliedVouchers"
    [cartIsLoading]="cartIsLoading$ | async"
    [isReadOnly]="false"
  >
  </cx-applied-coupons>

  <ng-container *ngIf="applicableCoupons && applicableCoupons.length > 0">
    <div class="cx-available-coupon">
      <div class="title cx-cart-coupon-title">
        {{ 'voucher.availableCoupons' | cxTranslate }}
      </div>
      <div class="message">
        {{ 'voucher.availableCouponsLabel' | cxTranslate }}
      </div>
      <div class="scroll">
        <div class="coupons card" *ngFor="let coupon of applicableCoupons">
          <button
            (click)="applyCustomerCoupon(coupon.couponId)"
            class="coupon-id link"
            [disabled]="cartIsLoading$ | async"
            [class.disabled]="cartIsLoading$ | async"
          >
            {{ coupon.couponId }}
          </button>
        </div>
      </div>
    </div>
  </ng-container>
</ng-container>
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""