Newer
Older
import { Component, Input, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material';
import { Store, select } from '@ngrx/store';
import {
AddCourse,
AddSaveForLater,
MoveCourseBetweenTerms,
import { GlobalState } from '@app/core/state';
import * as selectors from '@app/degree-planner/store/selectors';
import { DegreePlannerApiService } from '@app/degree-planner/services/api.service';
import { ConfirmDialogComponent } from '@app/shared/dialogs/confirm-dialog/confirm-dialog.component';
import { CourseDetailsDialogComponent } from '@app/degree-planner/dialogs/course-details-dialog/course-details-dialog.component';
import { distinctUntilChanged, filter } from 'rxjs/operators';
import { TermCode } from '@app/core/models/termcode';
import { PlannedTerm, PlannedTermEra } from '@app/core/models/planned-term';
const isntUndefined = <T>(thing: T | undefined): thing is T => {
return thing !== undefined;
};
selector: 'cse-course-item',
templateUrl: './course-item.component.html',
styleUrls: ['./course-item.component.scss'],
export class CourseItemComponent implements OnInit {
@Input() isCurrentTerm: boolean;
@Input() isPastTerm: boolean;
@Input() disabled: boolean;
activeTerm: any;
status: string;
public visibleTermCodes$: Observable<string[]>;
public droppableTermCodes$: Observable<string[]>;
public term$: Observable<PlannedTerm>;
public plannedCourses: Course[];
constructor(
private api: DegreePlannerApiService,
public dialog: MatDialog,
private store: Store<GlobalState>,
) {}
ngOnInit() {
switch (true) {
case this.course.studentEnrollmentStatus === 'Enrolled' &&
this.isCurrentTerm:
this.status = 'Enrolled';
break;
case this.course.studentEnrollmentStatus === 'Waitlisted':
this.status = 'Waitlisted';
break;
case !this.course.grade && this.isPastTerm:
this.status = 'Incomplete';
break;
default:
this.status = '';
}
const isPastOrActive = this.era === 'past' || this.era === 'active';
const isNotOffered = this.course.studentEnrollmentStatus === 'NOTOFFERED';
this.isStruckthrough = isPastOrActive && isNotOffered;
this.droppableTermCodes$ = this.store.pipe(
select(selectors.selectAllVisibleYears),
utils.yearsToDroppableTermCodes(),
distinctUntilChanged(utils.compareStringArrays),
);
this.store.dispatch(
new AddSaveForLater({
courseId: course.courseId,
subjectCode: course.subjectCode,
title: course.title,
catalogNumber: course.catalogNumber,
/**
*
* Handle moving a course to different terms based on course type
*
*/
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
onMove(termCode: string) {
const toTermCode = new TermCode(termCode);
this.term$ = this.store.pipe(
select(selectors.selectVisibleTerm, { termCode: toTermCode }),
filter(isntUndefined),
distinctUntilChanged(),
);
this.term$.subscribe(term => {
this.plannedCourses = term.plannedCourses;
});
const isCourseInPlannedCourses = this.plannedCourses.some(
course => course.courseId === this.course.courseId,
);
if (isCourseInPlannedCourses) {
this.dialog
.open(ConfirmDialogComponent, {
data: {
title: "Can't add course",
confirmText: 'OK',
dialogClass: 'alertDialog',
text: `This course already exists in selected term!`,
},
})
.afterClosed();
return;
}
case 'course': {
const id = this.course.id as number;
const from = new TermCode(this.course.termCode);
new MoveCourseBetweenTerms({
to: toTermCode,
from,
id,
newIndex: 0,
}),
this.store.dispatch(new RemoveSaveForLater({ subjectCode, courseId }));
break;
}
}
/**
*
* Handle saving a course for later (This is not possible if a course is already saved)
*
*/
onSaveForLater() {
const {
courseId,
subjectCode,
title,
catalogNumber,
termCode,
} = this.course;
// Dispatch a save for later event
this.store.dispatch(
new AddSaveForLater({
courseId: courseId,
subjectCode: subjectCode,
title: title,
catalogNumber: catalogNumber,
newIndex: 0,
}),
);
// If course is in a term, we need to remove it
if (this.type === 'course') {
this.store.dispatch(
new RemoveCourse({
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
recordId: this.course.id as number,
}),
);
}
}
/**
*
* Handle removing a course (This is not possible for type 'search')
*
*/
onRemove() {
const dialogOptions = {
title: 'Remove Course?',
text: '',
confirmText: 'Remove Course',
confirmColor: 'accent',
};
switch (this.type) {
case 'saved':
dialogOptions.text = `This will remove "${
this.course.title
}" from your saved courses.`;
break;
default:
dialogOptions.text = `This will remove "${
this.course.title
}" from your degree plan and your cart.`;
}
this.dialog
.open(ConfirmDialogComponent, { data: dialogOptions })
.afterClosed()
.subscribe((result: { confirmed: boolean }) => {
// If the user confirmed the removal, remove course
if (result.confirmed) {
console.log(this.type);
console.log({
type: this.type,
fromTermCode: this.course.termCode,
recordId: this.course.id,
});
switch (this.type) {
case 'course':
this.store.dispatch(
new RemoveCourse({
recordId: this.course.id as number,
}),
);
break;
case 'saved':
const { subjectCode, courseId } = this.course;
this.store.dispatch(
new RemoveSaveForLater({ subjectCode, courseId }),
);
break;
}
}
});
}
this.store.dispatch(
new AddCourse({
courseId: this.course.courseId,
termCode: toTermCode,
subjectCode: this.course.subjectCode,
title: this.course.title,
catalogNumber: this.course.catalogNumber,
}),
);
this.api
.getCourseDetails(course.subjectCode, course.courseId)
.subscribe(courseDetails => {
const dialogRef = this.dialog.open(CourseDetailsDialogComponent, {
width: '80%',
data: { courseDetails: courseDetails, courseType: this.type },