refactor: bind components to api
This commit is contained in:
		| @@ -6,12 +6,13 @@ | ||||
|       </mat-panel-title> | ||||
|     </mat-expansion-panel-header> | ||||
|     <mat-chip-listbox hideSingleSelectionIndicator (change)="chooseFaculty($event)"> | ||||
|       @for (faculty of faculties | async; track $index) { | ||||
|       @for (faculty of faculties; track $index) { | ||||
|         <mat-chip-option [value]="faculty.id" color="accent"> | ||||
|           {{ faculty.name }} | ||||
|         </mat-chip-option> | ||||
|       } @empty { | ||||
|         <app-loading-indicator [loading]="facultiesLoaded !== null" (retryFunction)="facultiesLoadRetry.emit()"/> | ||||
|         <app-loading-indicator [loading]="facultiesLoaded !== null" | ||||
|                                (retryFunction)="loadFaculties()"/> | ||||
|       } | ||||
|     </mat-chip-listbox> | ||||
|   </mat-expansion-panel> | ||||
| @@ -22,14 +23,14 @@ | ||||
|         Курс | ||||
|       </mat-panel-title> | ||||
|     </mat-expansion-panel-header> | ||||
|     <mat-chip-listbox hideSingleSelectionIndicator (change)="chooseCourseNumber($event)" [formControl]="chipCourse"> | ||||
|       @for (course of courseNumbers | async; track $index) { | ||||
|     <mat-chip-listbox hideSingleSelectionIndicator (change)="chooseCourseNumber($event)" [formControl]="formChipCourse"> | ||||
|       @for (course of courseNumbers; track $index) { | ||||
|         <mat-chip-option [value]="course" color="accent"> | ||||
|           {{ course }} | ||||
|         </mat-chip-option> | ||||
|       } @empty { | ||||
|         <app-loading-indicator [loading]="groupsLoaded !== null" | ||||
|                                (retryFunction)="groupsLoadRetry.emit(this.facultyId!)"/> | ||||
|                                (retryFunction)="loadCourseGroup()"/> | ||||
|       } | ||||
|     </mat-chip-listbox> | ||||
|   </mat-expansion-panel> | ||||
| @@ -40,14 +41,14 @@ | ||||
|         Группа | ||||
|       </mat-panel-title> | ||||
|     </mat-expansion-panel-header> | ||||
|     <mat-chip-listbox hideSingleSelectionIndicator (change)="chooseGroup($event)" [formControl]="chipGroup"> | ||||
|       @for (group of filteredGroups | async; track $index) { | ||||
|     <mat-chip-listbox hideSingleSelectionIndicator (change)="chooseGroup($event)" [formControl]="formChipGroup"> | ||||
|       @for (group of filteredGroups; track $index) { | ||||
|         <mat-chip-option [value]="group.id" color="accent"> | ||||
|           {{ group.name }} | ||||
|         </mat-chip-option> | ||||
|       } @empty { | ||||
|         <app-loading-indicator [loading]="groupsLoaded !== null" | ||||
|                                (retryFunction)="groupsLoadRetry.emit(this.facultyId!)"/> | ||||
|                                (retryFunction)="loadCourseGroup()"/> | ||||
|       } | ||||
|     </mat-chip-listbox> | ||||
|   </mat-expansion-panel> | ||||
|   | ||||
| @@ -1,12 +1,13 @@ | ||||
| import {Component, EventEmitter, Input, Output, ViewChild} from '@angular/core'; | ||||
| import {Component, EventEmitter, Output, ViewChild} from '@angular/core'; | ||||
| import {MatExpansionModule, MatExpansionPanel} from "@angular/material/expansion"; | ||||
| import {MatChipListboxChange, MatChipsModule} from '@angular/material/chips'; | ||||
| import {FormControl, ReactiveFormsModule} from "@angular/forms"; | ||||
| import {AsyncPipe} from "@angular/common"; | ||||
| import {map, Observable, of} from "rxjs"; | ||||
| import {FormControl, FormsModule, ReactiveFormsModule} from "@angular/forms"; | ||||
| import {catchError} from "rxjs"; | ||||
| import {LoadingIndicatorComponent} from "@component/common/loading-indicator/loading-indicator.component"; | ||||
| import {GroupResponse} from "@api/v1/groupResponse"; | ||||
| import {FacultyResponse} from "@api/v1/facultyResponse"; | ||||
| import {FacultyService} from "@api/v1/faculty.service"; | ||||
| import {GroupService} from "@api/v1/group.service"; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-group', | ||||
| @@ -16,49 +17,98 @@ import {FacultyResponse} from "@api/v1/facultyResponse"; | ||||
|     MatChipsModule, | ||||
|     ReactiveFormsModule, | ||||
|     LoadingIndicatorComponent, | ||||
|     AsyncPipe | ||||
|     FormsModule | ||||
|   ], | ||||
|   templateUrl: './group.component.html', | ||||
|   styleUrl: './group.component.css' | ||||
|   styleUrl: './group.component.css', | ||||
|   providers: [FacultyService, GroupService] | ||||
| }) | ||||
|  | ||||
| export class GroupComponent { | ||||
|   protected facultyId: number | null = null; | ||||
|   protected courseNumber: number | null = null; | ||||
|  | ||||
|   protected filteredGroups: Observable<GroupResponse[]> = of([]); | ||||
|   protected courseNumbers: Observable<number[]> = of([]); | ||||
|   protected groups: Observable<GroupResponse[]> = of([]); | ||||
|   protected filteredGroups: GroupResponse[] = []; | ||||
|   protected courseNumbers: number[] = []; | ||||
|   private groups: GroupResponse[] = []; | ||||
|  | ||||
|   protected chipCourse: FormControl = new FormControl(); | ||||
|   protected chipGroup: FormControl = new FormControl(); | ||||
|   protected formChipCourse: FormControl = new FormControl(); | ||||
|   protected formChipGroup: FormControl = new FormControl(); | ||||
|  | ||||
|   protected faculties: FacultyResponse[] = []; | ||||
|  | ||||
|   @ViewChild('courseNumberPanel') courseNumberPanel!: MatExpansionPanel; | ||||
|   @ViewChild('groupPanel') groupPanel!: MatExpansionPanel; | ||||
|  | ||||
|   @Input() faculties: Observable<FacultyResponse[]> = of([]); | ||||
|   @Input() facultiesLoaded: boolean | null = false; | ||||
|   @Output() facultiesLoadRetry: EventEmitter<void> = new EventEmitter<void>(); | ||||
|   @Input() groupsLoaded: boolean | null = false; | ||||
|   @Output() groupsLoadRetry: EventEmitter<number> = new EventEmitter<number>(); | ||||
|   protected facultiesLoaded: boolean | null = false; | ||||
|   protected groupsLoaded: boolean | null = false; | ||||
|  | ||||
|   @Input() set setGroups(data: Observable<GroupResponse[]>) { | ||||
|     this.groups = data; | ||||
|     this.courseNumbers = this.groups.pipe( | ||||
|       map(data => data.map(g => g.courseNumber)), | ||||
|       map(courseNumbersArray => courseNumbersArray.filter((value, index, self) => self.indexOf(value) === index)), | ||||
|       map(uniqueCourseNumbers => uniqueCourseNumbers.sort((a, b) => a - b)) | ||||
|     ); | ||||
|   @Output() eventResult = new EventEmitter<number>(); | ||||
|  | ||||
|   constructor(private facultyApi: FacultyService, private groupApi: GroupService) { | ||||
|     this.loadFaculties(); | ||||
|   } | ||||
|  | ||||
|   @Output() groupSelected = new EventEmitter<number>(); | ||||
|   @Output() facultySelected = new EventEmitter<number>(); | ||||
|   protected loadFaculties() { | ||||
|     this.facultiesLoaded = false; | ||||
|     this.facultyApi.getFaculties() | ||||
|       .pipe(catchError(error => { | ||||
|         this.facultiesLoaded = null; | ||||
|         throw error; | ||||
|       })) | ||||
|       .subscribe(data => { | ||||
|         this.faculties = data; | ||||
|         this.facultiesLoaded = true; | ||||
|       }); | ||||
|   } | ||||
|  | ||||
|   private filteringCourseNumber() { | ||||
|     this.courseNumbers = Array.from( | ||||
|       new Set( | ||||
|         this.groups | ||||
|           .filter(x => x.facultyId === this.facultyId) | ||||
|           .map(x => x.courseNumber) | ||||
|       ) | ||||
|     ).sort((a, b) => a - b); | ||||
|   } | ||||
|  | ||||
|   private filteringGroup() { | ||||
|     this.filteredGroups = this.groups.filter(x => x.facultyId === this.facultyId && x.courseNumber === this.courseNumber); | ||||
|   } | ||||
|  | ||||
|   protected loadCourseGroup() { | ||||
|     if (this.groups.length === 0) { | ||||
|       this.groupsLoaded = false; | ||||
|  | ||||
|       this.groupApi.getGroups().pipe( | ||||
|         catchError(error => { | ||||
|           this.groupsLoaded = null; | ||||
|           throw error; | ||||
|         }) | ||||
|       ).subscribe(data => { | ||||
|         this.groups = data; | ||||
|         if (this.courseNumber === null) | ||||
|           this.filteringCourseNumber(); | ||||
|         else | ||||
|           this.filteringGroup(); | ||||
|  | ||||
|         this.groupsLoaded = true; | ||||
|       }); | ||||
|  | ||||
|       return | ||||
|     } | ||||
|  | ||||
|     if (this.courseNumber === null) | ||||
|       this.filteringCourseNumber(); | ||||
|     else | ||||
|       this.filteringGroup(); | ||||
|   } | ||||
|  | ||||
|   protected chooseFaculty(event: MatChipListboxChange) { | ||||
|     this.courseNumber = null; | ||||
|     this.groups = of([]); | ||||
|     this.chipGroup.reset(); | ||||
|     this.chipCourse.reset(); | ||||
|     this.groups = []; | ||||
|     this.formChipGroup.reset(); | ||||
|     this.formChipCourse.reset(); | ||||
|  | ||||
|     if (event.value === undefined || event.value === null) { | ||||
|       this.facultyId = null; | ||||
| @@ -67,12 +117,12 @@ export class GroupComponent { | ||||
|     this.facultyId = event.value; | ||||
|     this.courseNumberPanel.open(); | ||||
|  | ||||
|     this.facultySelected.emit(this.facultyId!); | ||||
|     this.loadCourseGroup(); | ||||
|   } | ||||
|  | ||||
|   protected chooseCourseNumber(event: MatChipListboxChange) { | ||||
|     this.filteredGroups = of([]); | ||||
|     this.chipGroup.reset(); | ||||
|     this.filteredGroups = []; | ||||
|     this.formChipGroup.reset(); | ||||
|  | ||||
|     if (event.value === undefined || event.value === null) { | ||||
|       this.courseNumber = null; | ||||
| @@ -81,8 +131,7 @@ export class GroupComponent { | ||||
|  | ||||
|     this.courseNumber = event.value; | ||||
|     this.groupPanel.open(); | ||||
|     this.groups.subscribe(data => | ||||
|       this.filteredGroups = of(data.filter(g => g.courseNumber === this.courseNumber))); | ||||
|     this.loadCourseGroup(); | ||||
|   } | ||||
|  | ||||
|   protected chooseGroup(event: MatChipListboxChange) { | ||||
| @@ -90,6 +139,6 @@ export class GroupComponent { | ||||
|       return; | ||||
|  | ||||
|     this.groupPanel.close(); | ||||
|     this.groupSelected.emit(event.value); | ||||
|     this.eventResult.emit(event.value); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -6,12 +6,12 @@ | ||||
|       </mat-panel-title> | ||||
|     </mat-expansion-panel-header> | ||||
|     <mat-chip-listbox hideSingleSelectionIndicator (change)="chooseCampus($event)"> | ||||
|       @for (campus of campuses | async; track $index) { | ||||
|       @for (campus of campuses; track $index) { | ||||
|         <mat-chip-option [value]="campus.id" color="accent"> | ||||
|           {{ campus.codeName }} | ||||
|         </mat-chip-option> | ||||
|       } @empty { | ||||
|         <app-loading-indicator [loading]="campusesLoaded !== null" (retryFunction)="campusesLoadRetry.emit()"/> | ||||
|         <app-loading-indicator [loading]="campusesLoaded !== null" (retryFunction)="loadCampuses()"/> | ||||
|       } | ||||
|     </mat-chip-listbox> | ||||
|   </mat-expansion-panel> | ||||
| @@ -23,12 +23,12 @@ | ||||
|       </mat-panel-title> | ||||
|     </mat-expansion-panel-header> | ||||
|     <mat-chip-listbox hideSingleSelectionIndicator (change)="chooseLectureHall($event)" [formControl]="chipLecture"> | ||||
|       @for (lectureHall of lectureHalls | async; track $index) { | ||||
|       @for (lectureHall of lectureHallsFiltered; track $index) { | ||||
|         <mat-chip-option [value]="lectureHall.id" color="accent"> | ||||
|           {{ lectureHall.name }} | ||||
|         </mat-chip-option> | ||||
|       } @empty { | ||||
|         <app-loading-indicator [loading]="lectureHallsLoaded !== null" (retryFunction)="lectureHallsLoadRetry.emit()"/> | ||||
|         <app-loading-indicator [loading]="lectureHallsLoaded !== null" (retryFunction)="loadLectureHalls()"/> | ||||
|       } | ||||
|     </mat-chip-listbox> | ||||
|   </mat-expansion-panel> | ||||
|   | ||||
| @@ -2,11 +2,13 @@ import {Component, EventEmitter, Input, Output, ViewChild} from '@angular/core'; | ||||
| import {AsyncPipe} from "@angular/common"; | ||||
| import {MatAccordion, MatExpansionModule, MatExpansionPanel} from "@angular/material/expansion"; | ||||
| import {MatChipListboxChange, MatChipsModule} from "@angular/material/chips"; | ||||
| import {Observable, of} from "rxjs"; | ||||
| import {catchError, Observable, of} from "rxjs"; | ||||
| import {FormControl, ReactiveFormsModule} from "@angular/forms"; | ||||
| import {LoadingIndicatorComponent} from "@component/common/loading-indicator/loading-indicator.component"; | ||||
| import {CampusBasicInfoResponse} from "@api/v1/campusBasicInfoResponse"; | ||||
| import {LectureHallResponse} from "@api/v1/lectureHallResponse"; | ||||
| import {CampusService} from "@api/v1/campus.service"; | ||||
| import {LectureHallService} from "@api/v1/lectureHall.service"; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-lecture-hall', | ||||
| @@ -20,7 +22,8 @@ import {LectureHallResponse} from "@api/v1/lectureHallResponse"; | ||||
|     LoadingIndicatorComponent | ||||
|   ], | ||||
|   templateUrl: './lecture-hall.component.html', | ||||
|   styleUrl: './lecture-hall.component.css' | ||||
|   styleUrl: './lecture-hall.component.css', | ||||
|   providers: [CampusService, LectureHallService] | ||||
| }) | ||||
|  | ||||
| export class LectureHallComponent { | ||||
| @@ -29,29 +32,66 @@ export class LectureHallComponent { | ||||
|  | ||||
|   @ViewChild('lecturePanel') lecturePanel!: MatExpansionPanel; | ||||
|  | ||||
|   @Input() campuses: Observable<CampusBasicInfoResponse[]> = of([]); | ||||
|   @Input() campusesLoaded: boolean | null = false; | ||||
|   @Output() campusesLoadRetry: EventEmitter<void> = new EventEmitter<void>(); | ||||
|   @Input() lectureHalls: Observable<LectureHallResponse[]> = of([]); | ||||
|   @Input() lectureHallsLoaded: boolean | null = false; | ||||
|   @Output() lectureHallsLoadRetry: EventEmitter<number> = new EventEmitter<number>(); | ||||
|   protected campuses: CampusBasicInfoResponse[] = []; | ||||
|   protected campusesLoaded: boolean | null = false; | ||||
|  | ||||
|   @Output() campusSelected = new EventEmitter<number>(); | ||||
|   @Output() lectureHallSelected = new EventEmitter<number>(); | ||||
|   private lectureHalls: LectureHallResponse[] = []; | ||||
|   protected lectureHallsFiltered: LectureHallResponse[] = []; | ||||
|   protected lectureHallsLoaded: boolean | null = false; | ||||
|  | ||||
|   @Output() eventResult = new EventEmitter<number>(); | ||||
|  | ||||
|   constructor(private campusApi: CampusService, private lectureHallApi: LectureHallService) { | ||||
|     this.loadCampuses(); | ||||
|   } | ||||
|  | ||||
|   protected loadCampuses() { | ||||
|     this.campusesLoaded = false; | ||||
|     this.campusApi.getCampus() | ||||
|       .pipe(catchError(error => { | ||||
|         this.campusesLoaded = null; | ||||
|         throw error; | ||||
|       })) | ||||
|       .subscribe(data => { | ||||
|         this.campuses = data; | ||||
|         this.campusesLoaded = true; | ||||
|       }); | ||||
|   } | ||||
|  | ||||
|   private filteringLectureHalls() { | ||||
|     this.lectureHallsFiltered = this.lectureHalls.filter(x => x.campusId === this.campusId); | ||||
|   } | ||||
|  | ||||
|   protected chooseCampus(event: MatChipListboxChange) { | ||||
|     this.chipLecture.reset(); | ||||
|  | ||||
|     if (event.value === undefined || event.value === null) { | ||||
|       this.campusId = null; | ||||
|       this.lectureHalls = of([]); | ||||
|       this.lectureHalls = []; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     this.campusId = event.value; | ||||
|     this.lecturePanel.open(); | ||||
|  | ||||
|     this.campusSelected.emit(this.campusId!); | ||||
|     if (this.lectureHalls.length === 0) | ||||
|       this.loadLectureHalls(); | ||||
|     else | ||||
|       this.filteringLectureHalls(); | ||||
|   } | ||||
|  | ||||
|   protected loadLectureHalls() { | ||||
|     this.lectureHallsLoaded = false; | ||||
|     this.lectureHallApi.getLectureHalls() | ||||
|       .pipe(catchError(error => { | ||||
|         this.lectureHallsLoaded = null; | ||||
|         throw error; | ||||
|       })) | ||||
|       .subscribe(data => { | ||||
|         this.lectureHalls = data; | ||||
|         this.filteringLectureHalls(); | ||||
|         this.lectureHallsLoaded = true; | ||||
|       }); | ||||
|   } | ||||
|  | ||||
|   protected chooseLectureHall(event: MatChipListboxChange) { | ||||
| @@ -59,6 +99,6 @@ export class LectureHallComponent { | ||||
|       return; | ||||
|  | ||||
|     this.lecturePanel.close(); | ||||
|     this.lectureHallSelected.emit(event.value); | ||||
|     this.eventResult.emit(event.value); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <div class="search-content"> | ||||
|   @if (professors.length === 0) { | ||||
|     <app-loading-indicator [loading]="professorsLoaded !== null" (retryFunction)="professorsLoadRetry.emit()"/> | ||||
|     <app-loading-indicator [loading]="professorsLoaded !== null" (retryFunction)="loadProfessors()"/> | ||||
|   } @else { | ||||
|     <mat-form-field color="accent" style="width: 100%;"> | ||||
|       <input type="text" placeholder="Поиск..." matInput [formControl]="professorControl" [matAutocomplete]="auto"> | ||||
|   | ||||
| @@ -3,9 +3,10 @@ import {MatFormField, MatInput} from "@angular/material/input"; | ||||
| import {FormControl, ReactiveFormsModule} from "@angular/forms"; | ||||
| import {MatAutocompleteModule, MatAutocompleteSelectedEvent} from "@angular/material/autocomplete"; | ||||
| import {AsyncPipe} from "@angular/common"; | ||||
| import {map, Observable, startWith} from "rxjs"; | ||||
| import {catchError, map, Observable, startWith} from "rxjs"; | ||||
| import {LoadingIndicatorComponent} from "@component/common/loading-indicator/loading-indicator.component"; | ||||
| import {ProfessorResponse} from "@api/v1/professorResponse"; | ||||
| import {ProfessorService} from "@api/v1/professor.service"; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-professor', | ||||
| @@ -19,17 +20,37 @@ import {ProfessorResponse} from "@api/v1/professorResponse"; | ||||
|     LoadingIndicatorComponent | ||||
|   ], | ||||
|   templateUrl: './professor.component.html', | ||||
|   styleUrl: './professor.component.css' | ||||
|   styleUrl: './professor.component.css', | ||||
|   providers: [ProfessorService] | ||||
| }) | ||||
| export class ProfessorComponent implements OnInit { | ||||
|   protected professorControl = new FormControl(); | ||||
|   protected filteredProfessors!: Observable<ProfessorResponse[]>; | ||||
|  | ||||
|   @Input() professors: ProfessorResponse[] = []; | ||||
|   @Output() professorSelected = new EventEmitter<number>(); | ||||
|   protected professors: ProfessorResponse[] = []; | ||||
|   protected professorsLoaded: boolean | null = false; | ||||
|  | ||||
|   @Input() professorsLoaded: boolean | null = false; | ||||
|   @Output() professorsLoadRetry: EventEmitter<void> = new EventEmitter<void>(); | ||||
|   @Output() eventResult = new EventEmitter<number>(); | ||||
|  | ||||
|   constructor(private api: ProfessorService) { | ||||
|     this.loadProfessors(); | ||||
|   } | ||||
|  | ||||
|   protected loadProfessors() { | ||||
|     if (this.professors.length === 0) { | ||||
|       this.professorsLoaded = false; | ||||
|  | ||||
|       this.api.getProfessors() | ||||
|         .pipe(catchError(error => { | ||||
|           this.professorsLoaded = null; | ||||
|           throw error; | ||||
|         })) | ||||
|         .subscribe(data => { | ||||
|           this.professors = data; | ||||
|           this.professorsLoaded = true; | ||||
|         }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ngOnInit(): void { | ||||
|     this.filteredProfessors = this.professorControl.valueChanges.pipe( | ||||
| @@ -53,7 +74,7 @@ export class ProfessorComponent implements OnInit { | ||||
|     const selectedOption = this.professors.find(teacher => teacher.id === event.option.value); | ||||
|     if (selectedOption) { | ||||
|       this.professorControl.setValue(selectedOption.name); | ||||
|       this.professorSelected.emit(selectedOption.id); | ||||
|       this.eventResult.emit(selectedOption.id); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -2,24 +2,17 @@ | ||||
|                (selectedTabChange)="chooseTabs($event)"> | ||||
|   <mat-tab label="Группа"> | ||||
|     <div> | ||||
|       <app-group (groupSelected)="groupSelected.emit($event)" (facultySelected)="groupLoad($event)" | ||||
|                                [setGroups]="groups" [faculties]="faculties" [facultiesLoaded]="facultiesLoaded" | ||||
|                                [groupsLoaded]="groupLoaded" (groupsLoadRetry)="groupLoad($event)" | ||||
|                                (facultiesLoadRetry)="facultyLoad()"/> | ||||
|       <app-group (eventResult)="groupSelected($event)"/> | ||||
|     </div> | ||||
|   </mat-tab> | ||||
|   <mat-tab label="Преподаватель"> | ||||
|     <div> | ||||
|       <app-professor (professorSelected)="professorSelected.emit($event)" [professors]="professorsData" [professorsLoaded]="professorsLoaded" (professorsLoadRetry)="professorsLoad()"/> | ||||
|       <app-professor (eventResult)="professorSelected($event)"/> | ||||
|     </div> | ||||
|   </mat-tab> | ||||
|   <mat-tab label="Кабинет"> | ||||
|     <div> | ||||
|       <app-lecture-hall (lectureHallSelected)="lectureHallSelected.emit($event)" [campuses]="campuses" | ||||
|                                       (campusSelected)="lectureHallLoad($event)" [lectureHalls]="lectureHalls" | ||||
|                                       [campusesLoaded]="campusesLoaded" [lectureHallsLoaded]="lectureHallsLoaded" | ||||
|                                       (campusesLoadRetry)="campusLoad()" | ||||
|                                       (lectureHallsLoadRetry)="lectureHallLoad($event)"/> | ||||
|       <app-lecture-hall (eventResult)="lectureHallSelected($event)"/> | ||||
|     </div> | ||||
|   </mat-tab> | ||||
|   <mat-tab label="Другое"> | ||||
|   | ||||
| @@ -1,38 +1,31 @@ | ||||
| import {Component, EventEmitter, Output, ViewChild} from '@angular/core'; | ||||
| import {HttpClientModule} from "@angular/common/http"; | ||||
| import {Component, EventEmitter, Output} from '@angular/core'; | ||||
| import {OtherComponent} from "@component/schedule/tabs/other/other.component"; | ||||
| import {MatTab, MatTabChangeEvent, MatTabGroup} from "@angular/material/tabs"; | ||||
| import {catchError, map, Observable, of, switchMap, tap} from "rxjs"; | ||||
| import {map, Observable} from "rxjs"; | ||||
| import {ReactiveFormsModule} from "@angular/forms"; | ||||
| import {AsyncPipe, NgIf} from "@angular/common"; | ||||
| import {MatButton} from "@angular/material/button"; | ||||
| import {DataSpinnerComponent} from "@component/common/data-spinner/data-spinner.component"; | ||||
| import {ProfessorResponse} from "@api/v1/professorResponse"; | ||||
| import {FacultyResponse} from "@api/v1/facultyResponse"; | ||||
| import {GroupResponse} from "@api/v1/groupResponse"; | ||||
| import {CampusBasicInfoResponse} from "@api/v1/campusBasicInfoResponse"; | ||||
| import {LectureHallResponse} from "@api/v1/lectureHallResponse"; | ||||
| import {DisciplineService} from "@api/v1/discipline.service"; | ||||
| import {GroupComponent} from "@component/schedule/tabs/group/group.component"; | ||||
| import {ProfessorComponent} from "@component/schedule/tabs/professor/professor.component"; | ||||
| import {LectureHallComponent} from "@component/schedule/tabs/lecture-hall/lecture-hall.component"; | ||||
| import {FacultyService} from "@api/v1/faculty.service"; | ||||
| import {GroupService} from "@api/v1/group.service"; | ||||
| import {ProfessorService} from "@api/v1/professor.service"; | ||||
| import {CampusService} from "@api/v1/campus.service"; | ||||
| import {LectureHallService} from "@api/v1/lectureHall.service"; | ||||
| import {ScheduleService} from "@api/v1/schedule.service"; | ||||
| import {ScheduleResponse} from "@api/v1/scheduleResponse"; | ||||
|  | ||||
| export enum TabsSelect { | ||||
|   Group, | ||||
|   Professor, | ||||
|   LectureHall, | ||||
|   Other | ||||
| } | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-tabs', | ||||
|   standalone: true, | ||||
|   imports: [ | ||||
|     HttpClientModule, | ||||
|     OtherComponent, | ||||
|     MatTabGroup, | ||||
|     MatTab, | ||||
|     ReactiveFormsModule, | ||||
|     AsyncPipe, | ||||
|     NgIf, | ||||
|     MatButton, | ||||
|     DataSpinnerComponent, | ||||
|     GroupComponent, | ||||
| @@ -41,171 +34,122 @@ import {LectureHallService} from "@api/v1/lectureHall.service"; | ||||
|   ], | ||||
|   templateUrl: './tabs.component.html', | ||||
|   styleUrl: './tabs.component.css', | ||||
|   providers: [FacultyService, GroupService, ProfessorService, CampusService, LectureHallService, DisciplineService ] | ||||
|   providers: [ScheduleService] | ||||
| }) | ||||
|  | ||||
| export class TabsComponent { | ||||
|   protected professorsData: ProfessorResponse[] = []; | ||||
|   @Output() eventResult = new EventEmitter<[TabsSelect, number, Observable<ScheduleResponse[]>]>(); | ||||
|  | ||||
|   protected faculties: Observable<FacultyResponse[]> = of([]); | ||||
|   protected groups: Observable<GroupResponse[]> = of([]); | ||||
|   private groupsData: Observable<GroupResponse[]> = of([]); | ||||
|   constructor(private scheduleApi: ScheduleService) { | ||||
|   } | ||||
|  | ||||
|   protected campuses: Observable<CampusBasicInfoResponse[]> = of([]); | ||||
|   protected lectureHalls: Observable<LectureHallResponse[]> = of([]); | ||||
|   private lectureHallsData: Observable<LectureHallResponse[]> = of([]); | ||||
|   protected groupSelected(id: number) { | ||||
|     this.eventResult.emit( | ||||
|       [ | ||||
|         TabsSelect.Group, | ||||
|         id, | ||||
|         this.scheduleApi.getByGroup(id) | ||||
|           .pipe( | ||||
|             map(g => | ||||
|               g.map(data => | ||||
|                 ({ | ||||
|                   dayOfWeek: data.dayOfWeek, | ||||
|                   pairNumber: data.pairNumber, | ||||
|                   isEven: data.isEven, | ||||
|                   discipline: data.discipline, | ||||
|                   disciplineId: data.disciplineId, | ||||
|                   isExcludedWeeks: data.isExcludedWeeks, | ||||
|                   weeks: data.weeks, | ||||
|                   typeOfOccupations: data.typeOfOccupations, | ||||
|                   group: data.group, | ||||
|                   groupId: data.groupId, | ||||
|                   lectureHalls: data.lectureHalls, | ||||
|                   lectureHallsId: data.lectureHallsId, | ||||
|                   professors: data.professors, | ||||
|                   professorsId: data.professorsId, | ||||
|                   campus: data.campus, | ||||
|                   campusId: data.campusId, | ||||
|                   linkToMeet: data.linkToMeet | ||||
|                 })) | ||||
|             ) | ||||
|           ) | ||||
|       ] | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   // States | ||||
|   protected facultiesLoaded: boolean | null = false; | ||||
|   protected groupLoaded: boolean | null = false; | ||||
|   protected campusesLoaded: boolean | null = false; | ||||
|   protected lectureHallsLoaded: boolean | null = false; | ||||
|   protected disciplinesLoaded: boolean | null = false; | ||||
|   protected professorsLoaded: boolean | null = false; | ||||
|   protected professorSelected(id: number) { | ||||
|     this.eventResult.emit( | ||||
|       [ | ||||
|         TabsSelect.Professor, | ||||
|         id, | ||||
|         this.scheduleApi.getByProfessor(id) | ||||
|           .pipe( | ||||
|             map(p => | ||||
|               p.map(data => | ||||
|                 ({ | ||||
|                   dayOfWeek: data.dayOfWeek, | ||||
|                   pairNumber: data.pairNumber, | ||||
|                   isEven: data.isEven, | ||||
|                   discipline: data.discipline, | ||||
|                   disciplineId: data.disciplineId, | ||||
|                   isExcludedWeeks: data.isExcludedWeeks, | ||||
|                   weeks: data.weeks, | ||||
|                   typeOfOccupations: data.typeOfOccupations, | ||||
|                   group: data.group, | ||||
|                   groupId: data.groupId, | ||||
|                   lectureHalls: data.lectureHalls, | ||||
|                   lectureHallsId: data.lectureHallsId, | ||||
|                   professors: data.professors, | ||||
|                   professorsId: data.professorsId, | ||||
|                   campus: data.campus, | ||||
|                   campusId: data.campusId, | ||||
|                   linkToMeet: data.linkToMeet | ||||
|                 })) | ||||
|             ) | ||||
|           ) | ||||
|       ] | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   @Output() groupSelected: EventEmitter<number> = new EventEmitter<number>(); | ||||
|   @Output() lectureHallSelected: EventEmitter<number> = new EventEmitter<number>(); | ||||
|   @Output() professorSelected: EventEmitter<number> = new EventEmitter<number>(); | ||||
|  | ||||
|   constructor( | ||||
|     private facultyApi: FacultyService, | ||||
|     private groupApi: GroupService, | ||||
|     private professorApi: ProfessorService, | ||||
|     private campusApi: CampusService, | ||||
|     private lectureHallApi: LectureHallService, | ||||
|     private disciplineApi: DisciplineService) { | ||||
|     this.facultyLoad().then(); | ||||
|   protected lectureHallSelected(id: number) { | ||||
|     this.eventResult.emit( | ||||
|       [ | ||||
|         TabsSelect.LectureHall, | ||||
|         id, | ||||
|         this.scheduleApi.getByLectureHall(id) | ||||
|           .pipe( | ||||
|             map(lh => | ||||
|               lh.map(data => | ||||
|                 ({ | ||||
|                   dayOfWeek: data.dayOfWeek, | ||||
|                   pairNumber: data.pairNumber, | ||||
|                   isEven: data.isEven, | ||||
|                   discipline: data.discipline, | ||||
|                   disciplineId: data.disciplineId, | ||||
|                   isExcludedWeeks: data.isExcludedWeeks, | ||||
|                   weeks: data.weeks, | ||||
|                   typeOfOccupations: data.typeOfOccupations, | ||||
|                   group: data.group, | ||||
|                   groupId: data.groupId, | ||||
|                   lectureHalls: data.lectureHalls, | ||||
|                   lectureHallsId: data.lectureHallsId, | ||||
|                   professors: data.professors, | ||||
|                   professorsId: data.professorsId, | ||||
|                   campus: data.campus, | ||||
|                   campusId: data.campusId, | ||||
|                   linkToMeet: data.linkToMeet | ||||
|                 })) | ||||
|             ) | ||||
|           ) | ||||
|       ] | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   protected async chooseTabs(event: MatTabChangeEvent) { | ||||
|     switch (event.index) { | ||||
|       case 0: | ||||
|         await this.facultyLoad(); | ||||
|         break; | ||||
|       case 1: | ||||
|         this.professorsLoad(); | ||||
|         break; | ||||
|       case 2: | ||||
|         await this.campusLoad(); | ||||
|         break; | ||||
|       case 3: | ||||
|         await this.extensionLoad(); | ||||
|         break; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   protected async facultyLoad() { | ||||
|     if (this.facultiesLoaded === null) this.facultiesLoaded = false; | ||||
|     if (this.facultiesLoaded) return; | ||||
|  | ||||
|     this.faculties = this.facultyApi.getFaculties().pipe( | ||||
|       tap(() => { | ||||
|         this.facultiesLoaded = true; | ||||
|       }), | ||||
|       catchError((error) => { | ||||
|         this.facultiesLoaded = null; | ||||
|         throw error; | ||||
|       }) | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   protected groupLoad(id: number) { | ||||
|     if (this.groupLoaded === null) this.groupLoaded = false; | ||||
|  | ||||
|     if (this.groupLoaded) | ||||
|       this.groups = this.groupsData.pipe(map(data => data.filter(x => x.facultyId === id))); | ||||
|     else | ||||
|       this.groups = this.groupApi.getByFaculty(id).pipe( | ||||
|         tap(() => { | ||||
|           this.groupLoaded = false; | ||||
|         }), | ||||
|         catchError((error) => { | ||||
|           this.groupLoaded = null; | ||||
|           throw error; | ||||
|         }) | ||||
|       ); | ||||
|   } | ||||
|  | ||||
|   protected professorsLoad() { | ||||
|     if (this.professorsLoaded === null) this.professorsLoaded = false; | ||||
|  | ||||
|     if (this.professorsLoaded) return; | ||||
|  | ||||
|     this.professorApi.getProfessors().pipe( | ||||
|       catchError((error) => { | ||||
|         this.professorsLoaded = null; | ||||
|         throw error; | ||||
|       }) | ||||
|     ).subscribe(data => { | ||||
|       this.professorsData = data; | ||||
|       this.professorEx.Data = data.map(x => | ||||
|         ({ | ||||
|           id: x.id, | ||||
|           name: x.altName ? x.altName : x.name, | ||||
|           selected: false | ||||
|         })); | ||||
|     }); | ||||
|  | ||||
|   } | ||||
|  | ||||
|   protected async campusLoad() { | ||||
|     if (this.campusesLoaded === null) this.campusesLoaded = false; | ||||
|  | ||||
|     if (this.campusesLoaded) return; | ||||
|  | ||||
|     this.campuses = this.campusApi.getCampus().pipe( | ||||
|       tap(() => { | ||||
|         this.campusesLoaded = true; | ||||
|       }), | ||||
|       catchError((error) => { | ||||
|         this.campusesLoaded = null; | ||||
|         throw error; | ||||
|       }) | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   protected lectureHallLoad(id: number) { | ||||
|     if (this.lectureHallsLoaded === null) this.lectureHallsLoaded = false; | ||||
|  | ||||
|     if (this.lectureHallsLoaded) | ||||
|       this.lectureHalls = this.lectureHallsData.pipe(map(data => data.filter(x => x.campusId === id))); | ||||
|     else | ||||
|       this.lectureHalls = this.lectureHallApi.getByCampus(id).pipe( | ||||
|         tap(() => { | ||||
|           this.lectureHallsLoaded = false; | ||||
|         }), | ||||
|         catchError((error) => { | ||||
|           this.lectureHallsLoaded = null; | ||||
|           throw error; | ||||
|         }) | ||||
|       ); | ||||
|   } | ||||
|  | ||||
|   protected async loadLectureHalls() { | ||||
|     if (!this.campusesLoaded) | ||||
|       await this.campusLoad(); | ||||
|  | ||||
|     if (!this.lectureHallsLoaded) { | ||||
|       this.lectureHallsData = this.lectureHallApi.getLectureHalls(); | ||||
|       this.lectureHallsData.pipe( | ||||
|         switchMap(lectureHalls => this.campuses.pipe( | ||||
|           map(campuses => { | ||||
|             return lectureHalls.map(x => { | ||||
|               const campus = campuses.find(c => c.id === x.campusId); | ||||
|               const codeName = campus ? campus.codeName : ''; | ||||
|               return { | ||||
|                 id: x.id, | ||||
|                 name: `${x.name} (${codeName})`, | ||||
|                 selected: false | ||||
|               }; | ||||
|             }); | ||||
|           }) | ||||
|         )), | ||||
|       ).subscribe(data => { | ||||
|         this.lectureHallEx.Data = data; | ||||
|         this.lectureHallsLoaded = true; | ||||
|         this.campusesLoaded = true; | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user