Skip to content
Snippets Groups Projects
course-details.component.ts 4.21 KiB
Newer Older
import { Component, OnInit, OnDestroy, Inject, Input } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Observable, Subscription } from 'rxjs';
import { distinctUntilChanged, map, filter } from 'rxjs/operators';
import { MatDialog } from '@angular/material';
import { Store, select } from '@ngrx/store';

import { CourseDetails } from '@app/core/models/course-details';
Scott Berg's avatar
Scott Berg committed
import * as selectors from '@app/degree-planner/store/selectors';
import * as utils from '@app/degree-planner/shared/utils';
import { TermCode } from '@app/core/models/termcode';
Scott Berg's avatar
Scott Berg committed
import { GlobalState } from '@app/core/state';
import { Course } from '@app/core/models/course';
import { PlannedTerm } from '@app/core/models/planned-term';
import { ConfirmDialogComponent } from '@app/shared/dialogs/confirm-dialog/confirm-dialog.component';
Scott Berg's avatar
Scott Berg committed

import {
  AddCourse,
  RemoveSaveForLater,
} from '@app/degree-planner/store/actions/course.actions';
const isntUndefined = <T>(thing: T | undefined): thing is T => {
  return thing !== undefined;
};

jvanboxtel@wisc.edu's avatar
jvanboxtel@wisc.edu committed
  selector: 'cse-course-details',
  templateUrl: './course-details.component.html',
  styleUrls: ['./course-details.component.scss'],
Scott Berg's avatar
Scott Berg committed
export class CourseDetailsComponent implements OnInit, OnDestroy {
Scott Berg's avatar
Scott Berg committed
  public courseDetails: CourseDetails;
  public type: 'course' | 'search' | 'saved';
  public selectedSearchTerm: string;
Scott Berg's avatar
Scott Berg committed
  public termSelector: FormGroup;
Scott Berg's avatar
Scott Berg committed
  public selectedSearchTerm$: Observable<string>;
  public droppableTermCodes$: Observable<string[]>;
  public searchTermSubscription: Subscription;
  public termSubscription: Subscription;
  public plannedCourses: ReadonlyArray<Course>;
Scott Berg's avatar
Scott Berg committed

  constructor(
    @Inject(MAT_DIALOG_DATA) public data: any,
    private store: Store<GlobalState>,
    private fb: FormBuilder,
Scott Berg's avatar
Scott Berg committed
  ) {
jvanboxtel@wisc.edu's avatar
jvanboxtel@wisc.edu committed
    this.courseDetails = data.courseDetails;
Scott Berg's avatar
Scott Berg committed
    this.type = data.courseType;
jvanboxtel@wisc.edu's avatar
jvanboxtel@wisc.edu committed
  }
Scott Berg's avatar
Scott Berg committed
  ngOnInit() {
    this.selectedSearchTerm$ = this.store.pipe(
      select(selectors.getSelectedSearchTerm),
Isaac Evavold's avatar
Isaac Evavold committed
      map(termCode => (termCode ? termCode.toString() : '0000')),
Scott Berg's avatar
Scott Berg committed
    );

    this.droppableTermCodes$ = this.store.pipe(
      select(selectors.selectAllVisibleYears),
      utils.yearsToDroppableTermCodes(),
      distinctUntilChanged(utils.compareStringArrays),
    );

    this.searchTermSubscription = this.selectedSearchTerm$.subscribe(
      termCode => {
        this.selectedSearchTerm = termCode;
      },
    );

    this.termSelector = this.fb.group({
      term: this.selectedSearchTerm,
    });
  }

  ngOnDestroy() {
    this.searchTermSubscription.unsubscribe();
  }

  addCourseToPlan($event) {
    $event.preventDefault();
    const termCode = new TermCode(this.termSelector.value.term);
Scott Berg's avatar
Scott Berg committed
    const subjectCode = this.courseDetails.subject.subjectCode;
    const courseId = this.courseDetails.courseId;
Isaac Evavold's avatar
Isaac Evavold committed
    const payload = {
      courseId,
      termCode,
      subjectCode,
      title: this.courseDetails.title,
      catalogNumber: this.courseDetails.catalogNumber,
    };
Scott Berg's avatar
Scott Berg committed

    this.term$ = this.store.pipe(
      select(selectors.selectVisibleTerm, {
        termCode: new TermCode(this.termSelector.value.term),
      }),
      filter(isntUndefined),
      distinctUntilChanged(),
    );
    this.termSubscription = this.term$.subscribe(term => {
      this.plannedCourses = term.plannedCourses;
    });

    const isCourseInPlannedCourses = this.plannedCourses.some(
      course => course.courseId === this.courseDetails.courseId,
    );

    if (isCourseInPlannedCourses) {
      this.dialog
        .open(ConfirmDialogComponent, {
          data: {
            title: "Can't add course to term",
            confirmText: 'OK',
            dialogClass: 'alertDialog',
            text: `This course already exists in selected term`,
          },
        })
        .afterClosed();
    } else {
      switch (this.type) {
        case 'search':
          this.store.dispatch(new AddCourse(payload));
          break;
Scott Berg's avatar
Scott Berg committed

        case 'saved':
          this.store.dispatch(new AddCourse(payload));
          this.store.dispatch(
            new RemoveSaveForLater({ subjectCode, courseId }),
          );
          break;
      }
Scott Berg's avatar
Scott Berg committed
    }
  }