Untitled

 avatar
unknown
plain_text
a year ago
15 kB
3
Indexable
import { Location } from '@angular/common';
import { AfterContentChecked, Component } from '@angular/core';
import { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { DisabilityTypes } from '@viarail/everest-lib-common';
import { cloneDeep, isEqual } from 'lodash';
import { BehaviorSubject, EMPTY, Observable, Subject, of } from 'rxjs';
import { catchError, finalize, map, shareReplay, switchMap, take, takeUntil, tap } from 'rxjs/operators';
import { SEATING_ARRANGEMENT } from '../../common/constants/disabilities';
import { ModalService } from '../../common/modals/modal.service';
import { SsrWarningModalComponent } from '../../common/modals/ssr-warning-modal/ssr-warning-modal/ssr-warning-modal.component';
import { BookingViewModel } from '../../common/models';
import { ThirdPartySsrDisability, ThirdPartySsrFormModel } from '../../common/models/disability.model';
import { PricingCodes } from '../../common/models/ssr/disability-codes.enum';
import { BookingService } from '../../common/services';
import { DISABILITY_CODE_TITLE, DisabilityService } from '../../common/services/disability.service';
import { PricingService } from '../../common/services/pricing.service';
import { formGroupFactory } from '../../common/utils/disability.utils';
import { QueryParameterService } from '../../create/search/services/query-parameter.service';
import { BaseSsrWizard } from '../ssr-wizard-base.container';

@Component({
  selector: 'app-manage-ssr-booking-container',
  templateUrl: './manage-ssr-booking.container.html'
})
export class ManageSsrContainer extends BaseSsrWizard implements AfterContentChecked {
  pricingCodesForm: UntypedFormArray;
  passengerDisabilityForm: UntypedFormArray;
  isPricingCodesFormLoaded$ = new BehaviorSubject<boolean>(false);
  isPassengerDisabilityFormLoaded$ = new BehaviorSubject<boolean>(false);
  booking$: Observable<BookingViewModel>;
  refreshBookingSubject = new BehaviorSubject<boolean>(true);
  refreshPricingFormSubject = new Subject();
  refreshPricingForm$ = this.refreshPricingFormSubject.asObservable();
  refreshDisabilityFormSubject = new Subject();
  refreshDisabilityForm$ = this.refreshDisabilityFormSubject.asObservable();
  numberDisabilityCodes: number;
  numberPricingCodes: number;
  removedPricingCodes: string[];
  pricingButtonEnabled: boolean;
  isSameModificationError: boolean;
  isDisabilityError: boolean;
  isStopError: boolean;
  hasError: boolean;
  ssrButtonEnabled: boolean;
  isFareMatrixOrigin: boolean;
  continueButtonEnabled: boolean;
  adjustedPassengerIndex: number[];
  pricingCodes: string[];
  isPricingFormChecked: boolean;
  isPassengerDisabilityFormChecked: boolean;

  constructor(
    private formBuilder: UntypedFormBuilder,
    private modalService: ModalService,
    private location: Location,
    private bookingService: BookingService,
    protected activatedRoute: ActivatedRoute,
    protected router: Router,
    protected pricingService: PricingService,
    protected disabilityService: DisabilityService,
    protected queryParameterService: QueryParameterService
  ) {
    super(queryParameterService, disabilityService, pricingService, router, activatedRoute);
  }

  ngOnInit(): void {
    this.initBookingType();
    super.ngOnInit();
    this.initVariables();
    this.initFareMatrixRoute();
    this.initPricingFromRefresh();
    this.initDisabilityFromRefresh();
  }

  ngAfterContentChecked(): void {
    this.refreshPricingFormSubject.next();
    this.refreshDisabilityFormSubject.next();
  }

  private initVariables(): void {
    this.numberPricingCodes = this.numberDisabilityCodes = 0;
    this.removedPricingCodes = [];
    this.adjustedPassengerIndex = [];
  }

  private initBookingType(): void {
    this.activatedRoute.queryParams.pipe(take(1)).subscribe((params) => {
      this.bookingType = params['bookingType'];
    });
  }

  private initFareMatrixRoute(): void {
    this.activatedRoute.queryParams.pipe(take(1)).subscribe((params) => {
      if (params['fareMatrixOrigin'] && !params.bookingNumber) {
        this.isFareMatrixOrigin = true;
        this.constructPassengerDisabilityFormFromLocalStorage();
        this.constructPricingFormArray();
      } else {
        this.disabilityService.clearSessionStorage();
        this.initBooking();
        this.constructDisabilityFormArray();
        this.constructPricingFormArrayFromBooking();
      }
    });
  }

  numberOfDisabilityCodesOperation(newIncrement: number): void {
    setTimeout(() => {
      this.numberDisabilityCodes += newIncrement;
    });
  }

  numberOfPricingCodesOperation(newIncrement: number): void {
    setTimeout(() => {
      this.numberPricingCodes += newIncrement;
      console.log('remaining code', this.numberPricingCodes);
      this.refreshBookingSubject.next(true);
    });
  }

  goBack(): void {
    if (this.pricingCodesForm?.touched || this.passengerDisabilityForm?.touched) {
      this.modalService.open<SsrWarningModalComponent>(SsrWarningModalComponent, {
        ariaLabelledBy: 'modal-sr-only'
      });
    } else if (this.isFareMatrixOrigin) {
      this.updateUrlWithDisabilitiesSSR(this.passengerDisabilityForm, true);
    } else {
      this.location.back();
    }
  }

  savePricingCodesInAdditionalDetails(): void {
    // save button
    this.pricingCodesForm.markAllAsTouched();
    console.log('save');
    if (this.pricingCodesForm.invalid) {
      return;
    }
    this.pricingService.savePricingAndServicesInLocalStorage(this.pricingCodesForm);
    if (this.isFareMatrixOrigin) {
      this.pricingCodesForm.markAsUntouched();
    } else {
      this.savePricingAndServicesUsingBooking();
    }
  }

  saveDisabilityCodesInAdditionalDetail(passengerWithDisabilityIndex: string): void {
    this.passengerDisabilityForm.markAllAsTouched();
    if (this.passengerDisabilityForm.invalid) {
      return;
    }
    if (this.isFareMatrixOrigin) {
      this.disabilityService.saveFormValuesInLocalStorage(this.passengerDisabilityForm);
      this.passengerDisabilityForm.markAsUntouched();
    } else {
      this.saveDisabilityCodesUsingBooking(passengerWithDisabilityIndex);
    }
  }

  constructPricingFormArray(): void {
    console.log('remove Code', this.removedPricingCodes);
    this.pricingCodesForm = this.pricingService.constructPricingFormArray(this.removedPricingCodes);
    this.refreshPricingFormSubject.next();
  }

  initPricingFromRefresh(): void {
    this.refreshPricingForm$
      .pipe(
        takeUntil(this.destroy$),
        tap(() => {
          if (this.pricingCodesForm) {
            this.isPricingCodesFormLoaded$.next(true);
            if (!this.isPricingFormChecked) {
              this.initPricingCodesFormChangeCheck();
            }
          }
        })
      )
      .subscribe();
  }

  initDisabilityFromRefresh(): void {
    this.refreshDisabilityForm$
      .pipe(
        takeUntil(this.destroy$),
        tap(() => {
          if (this.passengerDisabilityForm) {
            this.isPassengerDisabilityFormLoaded$.next(true);
            if (!this.isPassengerDisabilityFormChecked) {
              this.initPassengerDisabilityFormChangeCheck();
            }
          }
        })
      )
      .subscribe();
  }

  savePricingAndServicesUsingBooking(): void {
    this.hasError = false;
    this.isStopError = false;
    this.isSameModificationError = false;
    this.booking$
      .pipe(
        take(1),
        switchMap((booking) => {
          // console.log('validateBookingValue', this.validateBookingValue(booking, false));
          return this.validateBookingValue(booking, false);
        }),
        tap(() => {
          console.log('tap');

          this.pricingButtonEnabled = true;
          this.continueButtonEnabled = true;
        }),
        switchMap((booking) => {
          console.log('booking', booking);

          return this.bookingService.managePricingAdditionalDetails(booking, {
            isThrowError: true,
            pricingFormArray: this.pricingCodesForm
          });
        }),
        catchError((e) => {
          this.isStopError = e?.error?.error?.context?.tariff_code?.toUpperCase() === PricingCodes.Stop;
          this.hasError = true;
          return of(null);
        }),
        finalize(() => {
          this.pricingButtonEnabled = false;
          this.continueButtonEnabled = false;
          this.pricingCodesForm.markAsUntouched();
          this.refreshPricingFormSubject.next();
        })
      )
      .subscribe();
  }

  private saveDisabilityCodesUsingBooking(passengerId: string): void {
    this.isSameModificationError = false;
    this.isDisabilityError = true;

    this.booking$
      .pipe(
        switchMap((booking) => this.validateBookingValue(booking)),
        take(1),
        tap(() => {
          this.continueButtonEnabled = true;
          this.ssrButtonEnabled = true;
        }),
        switchMap((booking) => {
          const getFormGroup = this.passengerDisabilityForm.controls.find(
            (control) => control.value.passengerId === passengerId
          ) as UntypedFormGroup;
          const passenger = booking.activePassengersDummyExcluded.find((passenger) => (passenger.id = passengerId));
          return this.bookingService.manageSsrDisabilityAdditionalDetails(booking, passenger, getFormGroup, true);
        }),
        finalize(() => {
          this.ssrButtonEnabled = false;
          this.continueButtonEnabled = false;
          this.passengerDisabilityForm.markAsUntouched();
          this.refreshDisabilityFormSubject.next();
        })
      )
      .subscribe();
  }

  private validateBookingValue(booking: BookingViewModel, isDisability = true): Observable<BookingViewModel> {
    console.log('ValidateBooking', booking);

    return this.bookingService.isSameModification(booking).pipe(
      take(1),
      switchMap((isSameModification) => {
        if (!isSameModification || (booking.hasProvisionalModification && !booking.isProvisional)) {
          this.hasError = !isDisability;
          this.isDisabilityError = isDisability;
          this.isSameModificationError = true;
          return EMPTY;
        }
        return of(booking);
      })
    );
  }

  private constructPassengerDisabilityFormFromLocalStorage(): void {
    const formValues = this.disabilityService.getFormValueFromSessionStorage();
    this.pricingCodes = this.pricingService.getPricingCodesBasedOnSsrCases(null, !!formValues?.length);
    if (!formValues?.length) {
      return;
    }
    if (!this.passengerDisabilityForm) {
      this.passengerDisabilityForm = this.formBuilder.array([]);
    }
    for (const form of formValues) {
      this.passengerDisabilityForm.push(this.constructFormGroupsFromLocalStorage(form));
      this.adjustedPassengerIndex.push(form.passengerIndex);
    }
    this.refreshDisabilityFormSubject.next();
  }

  private constructFormGroupsFromLocalStorage(form: ThirdPartySsrFormModel): UntypedFormGroup {
    return this.formBuilder.group({
      passengerIndex: form.passengerIndex,
      passengerType: form.passengerType,
      passengerId: form.passengerId,
      disabledPassengers: this.formBuilder.array(this.constructDisabilityTypeFormGroup(form.disabledPassengers))
    });
  }

  private constructDisabilityTypeFormGroup(thirdPartySsrDisability: ThirdPartySsrDisability[]): UntypedFormGroup[] {
    return thirdPartySsrDisability.map((form) => {
      return this.formBuilder.group({
        disabilityType: this.mapDisabilityType(form.disabilityType as DisabilityTypes),
        disabilities: this.formBuilder.array(
          form.disabilities.map((keyValuePair) => {
            const dsbCode = keyValuePair[DISABILITY_CODE_TITLE];
            const formGroup = formGroupFactory(dsbCode, DISABILITY_CODE_TITLE, this.formBuilder);
            Object.keys(keyValuePair).forEach((key) => {
              const valueCurrent = keyValuePair[key];
              formGroup?.controls[key]?.setValue(valueCurrent);
            });
            return formGroup;
          })
        )
      });
    });
  }

  private constructDisabilityFormArray(): void {
    this.booking$
      .pipe(
        takeUntil(this.destroy$),
        map(
          (booking) =>
            (this.passengerDisabilityForm = this.disabilityService.buildDisabilityForm(
              booking,
              this.adjustedPassengerIndex
            ))
        ),
        take(1),
        tap(() => {
          this.refreshDisabilityFormSubject.next();
        })
      )
      .subscribe();
  }

  private constructPricingFormArrayFromBooking(): void {
    this.booking$
      .pipe(
        takeUntil(this.destroy$),
        take(1),
        tap((bk) => {
          [this.pricingCodesForm, this.removedPricingCodes] = this.pricingService.constructPricingFormArrayFromBooking(
            bk,
            this.removedPricingCodes
          );
          console.log('remove Code2', this.removedPricingCodes);
          this.pricingCodes = this.pricingService.getPricingCodesBasedOnSsrCases(bk);
          this.refreshPricingFormSubject.next();
        })
      )
      .subscribe();
  }

  private initBooking(): void {
    this.booking$ = this.refreshBookingSubject.pipe(
      takeUntil(this.destroy$),
      switchMap(() =>
        this.bookingService.initCurrentBooking(this.activatedRoute.params, this.destroy$).pipe(shareReplay())
      )
    );
  }

  private initPassengerDisabilityFormChangeCheck(): void {
    const passengerDisabilityFormInitialValue = cloneDeep(this.passengerDisabilityForm.value);
    this.passengerDisabilityForm?.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => {
      if (isEqual(passengerDisabilityFormInitialValue, value)) {
        this.passengerDisabilityForm.markAsUntouched();
      } else {
        this.passengerDisabilityForm.markAsTouched();
      }
    });
    this.isPassengerDisabilityFormChecked = true;
  }

  private initPricingCodesFormChangeCheck(): void {
    const pricingCodesFormInitialValue = cloneDeep(this.pricingCodesForm.value);
    this.pricingCodesForm?.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => {
      if (isEqual(pricingCodesFormInitialValue, value)) {
        this.pricingCodesForm.markAsUntouched();
      } else {
        this.pricingCodesForm.markAsTouched();
      }
    });
    this.isPricingFormChecked = true;
  }

  private mapDisabilityType(disabilityType: DisabilityTypes): DisabilityTypes {
    return SEATING_ARRANGEMENT.includes(disabilityType) ? DisabilityTypes.ReducedMobility : disabilityType;
  }
}
Editor is loading...
Leave a Comment