All files / src/app/pages/product/product-images product-images.component.ts

73.33% Statements 22/30
73.33% Branches 11/15
69.23% Functions 9/13
72.41% Lines 21/29

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 1222x                   2x 2x 2x   2x   2x 2x                                     2x       5x 5x 5x                                     5x 5x       5x       5x           5x       15x 15x 15x                                       18x                               5x      
import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  ElementRef,
  OnDestroy,
  OnInit,
  ViewChild,
} from '@angular/core';
import { Observable } from 'rxjs';
import { distinctUntilKeyChanged, map, shareReplay, tap } from 'rxjs/operators';
import Swiper from 'swiper';
import { A11y, Navigation } from 'swiper/modules';
 
import { ProductContextFacade } from 'ish-core/facades/product-context.facade';
import { ProductView } from 'ish-core/models/product-view/product-view.model';
import { ProductHelper } from 'ish-core/models/product/product.model';
import { whenTruthy } from 'ish-core/utils/operators';
import { ModalDialogComponent } from 'ish-shared/components/common/modal-dialog/modal-dialog.component';
 
/**
 * The Product Images Component
 *
 * Displays carousel slides for all images of the product and a thumbnails list as carousel indicator.
 * If zoom images are available and the user clicks on the image a zoom images dialog opens up.
 * It uses the {@link ProductImageComponent} for the rendering of product images.
 *
 * @example
 * <ish-product-images />
 */
@Component({
  selector: 'ish-product-images',
  templateUrl: './product-images.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: { ngSkipHydration: 'true' },
})
export class ProductImagesComponent implements OnInit, OnDestroy {
  private swiper: Swiper;
 
  @ViewChild('swiper') set swiperRef(ref: ElementRef) {
    Eif (ref && !this.swiper && !SSR) {
      const swiperEl = ref.nativeElement;
      this.swiper = new Swiper(swiperEl, {
        modules: [A11y, Navigation],
        navigation: {
          nextEl: swiperEl.querySelector('.swiper-button-next'),
          prevEl: swiperEl.querySelector('.swiper-button-prev'),
        },
        on: {
          slideChange: () => this.cdRef.markForCheck(),
        },
      });
    }
  }
 
  @ViewChild('zoomDialog') zoomDialog: ModalDialogComponent<unknown>;
 
  product$: Observable<ProductView>;
  zoomImageIds$: Observable<string[]>;
 
  constructor(
    private context: ProductContextFacade,
    private cdRef: ChangeDetectorRef
  ) {}
 
  ngOnInit() {
    this.product$ = this.context.select('product').pipe(
      whenTruthy(),
      distinctUntilKeyChanged('sku'),
      tap(() => {
        Iif (this.swiper?.activeIndex) {
          this.setActiveSlide(0);
        }
      }),
      shareReplay(1)
    );
    this.zoomImageIds$ = this.getImageViewIDs$('ZOOM').pipe(shareReplay(1));
  }
 
  getImageViewIDs$(imageType: string): Observable<string[]> {
    return this.product$.pipe(
      map(p => ProductHelper.getImageViewIDs(p, imageType)),
      map(ids => (ids?.length ? ids : imageType === 'ZOOM' ? undefined : ['default']))
    );
  }
 
  /**
   * Set the active slide via index (used by the thumbnail indicator)
   *
   * @param slideIndex The slide index to set the active slide
   */
  setActiveSlide(slideIndex: number) {
    this.swiper?.slideTo(slideIndex);
  }
 
  /**
   * Check if the given slide index equals the active slide
   *
   * @param slideIndex The slide index to be checked if it is the active slide
   * @returns True if the given slide index is the active slide, false otherwise
   */
  isActiveSlide(slideIndex: number): boolean {
    return (this.swiper?.activeIndex ?? 0) === slideIndex;
  }
 
  getZoomImageAnchorId(i: number) {
    return `zoom-image-${i}`;
  }
 
  openZoomModal(i: number) {
    if (this.zoomDialog) {
      this.zoomDialog.show();
      this.zoomDialog.scrollToAnchor(this.getZoomImageAnchorId(i));
    }
    return false;
  }
 
  ngOnDestroy(): void {
    this.swiper?.destroy();
  }
}