refactor: folders and components
This commit is contained in:
		| @@ -1,6 +1,6 @@ | ||||
| import {Component} from "@angular/core"; | ||||
| import {MatList, MatListItem} from "@angular/material/list"; | ||||
| import {version} from "@/../package.json"; | ||||
| import {version} from "../../../../package.json"; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'app-footer', | ||||
| @@ -1,5 +1,5 @@ | ||||
| import {Component, EventEmitter, Input, Output} from '@angular/core'; | ||||
| import {DataSpinnerComponent} from "@component/data-spinner/data-spinner.component"; | ||||
| import {DataSpinnerComponent} from "@component/common/data-spinner/data-spinner.component"; | ||||
| import {MatIcon} from "@angular/material/icon"; | ||||
| import {MatButton, MatFabButton} from "@angular/material/button"; | ||||
| 
 | ||||
							
								
								
									
										54
									
								
								src/components/schedule/table/table.component.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/components/schedule/table/table.component.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| .schedule-table { | ||||
|   border: 1px solid white; | ||||
| } | ||||
|  | ||||
| .schedule-table td, .schedule-table th { | ||||
|   border-right: 1px solid; | ||||
|   border-right-color: var(--mat-table-row-item-outline-color, rgba(0, 0, 0, 0.12)); | ||||
|   padding-top: 8px; | ||||
|   padding-bottom: 8px; | ||||
| } | ||||
|  | ||||
| .schedule-table tr:nth-child(even) { | ||||
|   background-color: color-mix(in srgb, var(--mat-table-background-color), white 5%); | ||||
| } | ||||
|  | ||||
| .schedule-table th { | ||||
|   text-align: center; | ||||
| } | ||||
|  | ||||
| .table-element div { | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   margin-bottom: 10px; | ||||
| } | ||||
|  | ||||
| .pair-cell { | ||||
|   text-align: center; | ||||
|   width: 0; | ||||
|   min-width: fit-content; | ||||
| } | ||||
|  | ||||
| mat-icon { | ||||
|   transform: scale(0.85); | ||||
| } | ||||
|  | ||||
| .table-section { | ||||
|   overflow: auto; | ||||
|   max-height: 80vh; | ||||
|   position: relative | ||||
| } | ||||
|  | ||||
| .overlay { | ||||
|   position: absolute; | ||||
|   top: 0; | ||||
|   left: 0; | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|   background-color: rgba(0, 0, 0, 0.5); | ||||
|   z-index: 1001; | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   justify-content: center; | ||||
|   flex-direction: column; | ||||
| } | ||||
							
								
								
									
										116
									
								
								src/components/schedule/table/table.component.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/components/schedule/table/table.component.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| <section class="mat-elevation-z8 table-section" tabindex="0"> | ||||
|   @if (dataSource.length === 0 || isLoad) { | ||||
|     <div class="overlay"> | ||||
|       @if (isLoad) { | ||||
|         <app-data-spinner/> | ||||
|       } @else { | ||||
|         <p class="mat-h2">Нет данных.</p> | ||||
|         <p class="mat-body-2">Выберите необходимое расписание сверху</p> | ||||
|       } | ||||
|     </div> | ||||
|   } | ||||
|  | ||||
|   <table mat-table [dataSource]="tableDataSource" class="schedule-table size-icon"> | ||||
|     <!-- Pair Number --> | ||||
|     <ng-container matColumnDef="pairNumber" sticky> | ||||
|       <th mat-header-cell *matHeaderCellDef style="width: 0; min-width: fit-content;"> | ||||
|         Пара | ||||
|         <!-- Even Or Odd --> | ||||
|         <hr/> | ||||
|         @if (currentWeek % 2 === 0) { | ||||
|           Четная | ||||
|         } @else { | ||||
|           Нечетная | ||||
|         } | ||||
|       </th> | ||||
|  | ||||
|       <td mat-cell *matCellDef="let element" class="pair-cell" sticky> | ||||
|         {{ element["pairNumber"] }} | ||||
|       </td> | ||||
|     </ng-container> | ||||
|  | ||||
|     <!-- Day of Week --> | ||||
|     @for (day of daysOfWeek; track $index) { | ||||
|       <ng-container [matColumnDef]="day"> | ||||
|         <!-- Day of Week Name --> | ||||
|         <th mat-header-cell *matHeaderCellDef> | ||||
|           <span class="mat-body-1"> | ||||
|             {{ day }} | ||||
|           </span> | ||||
|           <br/> | ||||
|           <span class="mat-caption"> | ||||
|             {{ addDays(startWeek, daysOfWeek.indexOf(day)) | date:"shortDate" }} | ||||
|           </span> | ||||
|         </th> | ||||
|  | ||||
|         <!-- Info About Pairs --> | ||||
|         <td mat-cell *matCellDef="let element" class="table-element"> | ||||
|           @for (elementData of element.data[daysOfWeek.indexOf(day) + 1]; track $index) { | ||||
|             <!-- Discipline --> | ||||
|             <div class="mat-body-1">{{ elementData["discipline"] }}</div> | ||||
|             <!-- Type of Occupation --> | ||||
|             <div class="mat-body">({{ elementData["typeOfOccupation"] }})</div> | ||||
|  | ||||
|             <!-- Professors --> | ||||
|             @if (checkAvailableData(elementData["professors"])) { | ||||
|               <div class="mat-body"> | ||||
|                 <i> | ||||
|                   <mat-icon fontIcon="person"/> | ||||
|                 </i> | ||||
|                 @for (professor of elementData["professors"]; track $index) { | ||||
|                   @if ($index !== 0) { | ||||
|                     <br/> | ||||
|                   } | ||||
|                   {{ professor }} | ||||
|                 } | ||||
|               </div> | ||||
|             } | ||||
|  | ||||
|             <!-- Address (Lecture Hall & Campus) --> | ||||
|             @if (checkAvailableData(elementData["lectureHalls"]) && checkAvailableData(elementData["campus"])) { | ||||
|               <div class="mat-body"> | ||||
|                 <i> | ||||
|                   <mat-icon fontIcon="location_on"/> | ||||
|                 </i> | ||||
|                 @for (lectureHall of elementData["lectureHalls"]; track $index) { | ||||
|                   @if ($index !== 0) { | ||||
|                     <br/> | ||||
|                   } | ||||
|                   @if (lectureHall) { | ||||
|                     {{ lectureHall }} | ||||
|                   } @else { | ||||
|                     N/A | ||||
|                   } | ||||
|                   / | ||||
|                   @if (elementData["campus"][$index]) { | ||||
|                     {{ elementData["campus"][$index] }} | ||||
|                   } @else { | ||||
|                     N/A | ||||
|                   } | ||||
|                 } | ||||
|               </div> | ||||
|             } | ||||
|  | ||||
|             <!-- Group --> | ||||
|             @if (!isOneGroup) { | ||||
|               <div class="mat-body"> | ||||
|                 <i> | ||||
|                   <mat-icon fontIcon="group"/> | ||||
|                 </i> | ||||
|                 {{ elementData["group"] }} | ||||
|               </div> | ||||
|             } | ||||
|  | ||||
|             @if ($index + 1 !== element.data[daysOfWeek.indexOf(day) + 1].length) { | ||||
|               <hr style="margin: 10px 0;"/> | ||||
|             } | ||||
|           } | ||||
|  | ||||
|         </td> | ||||
|       </ng-container> | ||||
|     } | ||||
|  | ||||
|     <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr> | ||||
|     <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> | ||||
|   </table> | ||||
| </section> | ||||
							
								
								
									
										89
									
								
								src/components/schedule/table/table.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/components/schedule/table/table.component.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| import {Component, Input, OnChanges} from '@angular/core'; | ||||
| import {MatTableDataSource, MatTableModule} from "@angular/material/table"; | ||||
| import {MatIcon} from "@angular/material/icon"; | ||||
| import {DatePipe} from "@angular/common"; | ||||
| import {addDays} from "@progress/kendo-date-math"; | ||||
| import {MatDivider} from "@angular/material/divider"; | ||||
| import {Schedule} from "@page/schedule/schedule.component"; | ||||
| import {DataSpinnerComponent} from "@component/common/data-spinner/data-spinner.component"; | ||||
|  | ||||
| interface TableData { | ||||
|   pairNumber: number; | ||||
|   data: Dictionary; | ||||
| } | ||||
|  | ||||
| interface Dictionary { | ||||
|   [key: string]: any; | ||||
| } | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-table', | ||||
|   standalone: true, | ||||
|   imports: [ | ||||
|     MatTableModule, | ||||
|     MatIcon, | ||||
|     DatePipe, | ||||
|     MatDivider, | ||||
|     DataSpinnerComponent | ||||
|   ], | ||||
|   templateUrl: './table.component.html', | ||||
|   styleUrl: './table.component.css', | ||||
| }) | ||||
|  | ||||
| export class TableComponent implements OnChanges { | ||||
|   protected tableDataSource: MatTableDataSource<TableData> = new MatTableDataSource<TableData>([]); | ||||
|   protected daysOfWeek: string[] = ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота']; | ||||
|   protected displayedColumns: string[] = ['pairNumber']; | ||||
|   protected dataSource: Schedule[] = []; | ||||
|   protected isOneGroup: boolean = false; | ||||
|  | ||||
|   @Input() currentWeek!: number; | ||||
|   @Input() startWeek!: Date; | ||||
|   @Input() isLoad: boolean = false; | ||||
|  | ||||
|   @Input() set data(schedule: Schedule[]) { | ||||
|     this.dataSource = schedule; | ||||
|     this.convertData(); | ||||
|     this.isOneGroup = schedule.every((item, _, array) => item.group === array[0].group); | ||||
|   } | ||||
|  | ||||
|   ngOnChanges(changes: any) { | ||||
|     if (changes.startWeek && !changes.startWeek.firstChange) { | ||||
|       this.convertData(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   constructor() { | ||||
|     this.displayedColumns = this.displayedColumns.concat(this.daysOfWeek); | ||||
|   } | ||||
|  | ||||
|   private convertData() { | ||||
|     this.isLoad = true; | ||||
|     let tableData: TableData[] = []; | ||||
|  | ||||
|     for (let i: number = 1; i <= 7; i++) { | ||||
|       let convertedData: TableData = { | ||||
|         pairNumber: i, | ||||
|         data: {} | ||||
|       }; | ||||
|  | ||||
|       for (let k: number = 1; k < 7; k++) { | ||||
|         convertedData.data[k.toString()] = this.dataSource.filter(x => | ||||
|           x.pairNumber === i | ||||
|           && x.dayOfWeek === k | ||||
|           && x.isEven === (this.currentWeek % 2 === 0)); | ||||
|       } | ||||
|  | ||||
|       tableData.push(convertedData); | ||||
|     } | ||||
|  | ||||
|     this.tableDataSource = new MatTableDataSource<TableData>(tableData); | ||||
|     this.isLoad = false; | ||||
|   } | ||||
|  | ||||
|   protected checkAvailableData(data: any[]): boolean { | ||||
|     return data && data.length !== 0 && data.every(x => x !== null); | ||||
|   } | ||||
|  | ||||
|   protected readonly addDays = addDays; | ||||
| } | ||||
| @@ -6,10 +6,10 @@ import {AsyncPipe} from "@angular/common"; | ||||
| import {map, Observable, of} from "rxjs"; | ||||
| import {FacultyResponse} from "@model/facultyResponse"; | ||||
| import {GroupResponse} from "@model/groupResponse"; | ||||
| import {LoadingIndicatorComponent} from "@component/loading-indicator/loading-indicator.component"; | ||||
| import {LoadingIndicatorComponent} from "@component/common/loading-indicator/loading-indicator.component"; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'app-schedule-tabs-group', | ||||
|   selector: 'app-group', | ||||
|   standalone: true, | ||||
|   imports: [ | ||||
|     MatExpansionModule, | ||||
| @@ -18,11 +18,11 @@ import {LoadingIndicatorComponent} from "@component/loading-indicator/loading-in | ||||
|     LoadingIndicatorComponent, | ||||
|     AsyncPipe | ||||
|   ], | ||||
|   templateUrl: './schedule-tabs-group.component.html', | ||||
|   styleUrl: './schedule-tabs-group.component.css' | ||||
|   templateUrl: './group.component.html', | ||||
|   styleUrl: './group.component.css' | ||||
| }) | ||||
| 
 | ||||
| export class ScheduleTabsGroupComponent { | ||||
| export class GroupComponent { | ||||
|   protected facultyId: number | null = null; | ||||
|   protected courseNumber: number | null = null; | ||||
| 
 | ||||
| @@ -6,10 +6,10 @@ import {Observable, of} from "rxjs"; | ||||
| import {CampusBasicInfoResponse} from "@model/campusBasicInfoResponse"; | ||||
| import {FormControl, ReactiveFormsModule} from "@angular/forms"; | ||||
| import {LectureHallResponse} from "@model/lectureHallResponse"; | ||||
| import {LoadingIndicatorComponent} from "@component/loading-indicator/loading-indicator.component"; | ||||
| import {LoadingIndicatorComponent} from "@component/common/loading-indicator/loading-indicator.component"; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'app-schedule-tabs-lecture-hall', | ||||
|   selector: 'app-lecture-hall', | ||||
|   standalone: true, | ||||
|   imports: [ | ||||
|     MatChipsModule, | ||||
| @@ -19,10 +19,10 @@ import {LoadingIndicatorComponent} from "@component/loading-indicator/loading-in | ||||
|     MatAccordion, | ||||
|     LoadingIndicatorComponent | ||||
|   ], | ||||
|   templateUrl: './schedule-tabs-lecture-hall.component.html', | ||||
|   styleUrl: './schedule-tabs-lecture-hall.component.css' | ||||
|   templateUrl: './lecture-hall.component.html', | ||||
|   styleUrl: './lecture-hall.component.css' | ||||
| }) | ||||
| export class ScheduleTabsLectureHallComponent { | ||||
| export class LectureHallComponent { | ||||
|   protected campusId: number | null = null; | ||||
|   protected chipLecture: FormControl = new FormControl(); | ||||
| 
 | ||||
| @@ -11,7 +11,7 @@ import {ScrollingModule} from "@angular/cdk/scrolling"; | ||||
| import {ScrollingModule as ExperimentalScrollingModule} from '@angular/cdk-experimental/scrolling'; | ||||
| import {MatDivider} from "@angular/material/divider"; | ||||
| import {MatInput} from "@angular/material/input"; | ||||
| import {LoadingIndicatorComponent} from "@component/loading-indicator/loading-indicator.component"; | ||||
| import {LoadingIndicatorComponent} from "@component/common/loading-indicator/loading-indicator.component"; | ||||
| 
 | ||||
| export interface SelectData { | ||||
|   id: number, | ||||
| @@ -20,7 +20,7 @@ export interface SelectData { | ||||
| } | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'app-schedule-tabs-other', | ||||
|   selector: 'app-other', | ||||
|   standalone: true, | ||||
|   imports: [ | ||||
|     MatMenuTrigger, | ||||
| @@ -40,10 +40,10 @@ export interface SelectData { | ||||
|     ExperimentalScrollingModule, | ||||
|     LoadingIndicatorComponent | ||||
|   ], | ||||
|   templateUrl: './schedule-tabs-other.component.html', | ||||
|   styleUrl: './schedule-tabs-other.component.css' | ||||
|   templateUrl: './other.component.html', | ||||
|   styleUrl: './other.component.css' | ||||
| }) | ||||
| export class ScheduleTabsOtherComponent { | ||||
| export class OtherComponent { | ||||
|   private _searchQuery: string = ''; | ||||
|   protected filteredData: BehaviorSubject<SelectData[]> = new BehaviorSubject<SelectData[]>([]); | ||||
|   protected data: SelectData[] = []; | ||||
| @@ -5,10 +5,10 @@ import {MatAutocompleteModule, MatAutocompleteSelectedEvent} from "@angular/mate | ||||
| import {AsyncPipe} from "@angular/common"; | ||||
| import {map, Observable, startWith} from "rxjs"; | ||||
| import {ProfessorResponse} from "@model/professorResponse"; | ||||
| import {LoadingIndicatorComponent} from "@component/loading-indicator/loading-indicator.component"; | ||||
| import {LoadingIndicatorComponent} from "@component/common/loading-indicator/loading-indicator.component"; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'app-schedule-tabs-professor', | ||||
|   selector: 'app-professor', | ||||
|   standalone: true, | ||||
|   imports: [ | ||||
|     MatAutocompleteModule, | ||||
| @@ -18,10 +18,10 @@ import {LoadingIndicatorComponent} from "@component/loading-indicator/loading-in | ||||
|     MatInput, | ||||
|     LoadingIndicatorComponent | ||||
|   ], | ||||
|   templateUrl: './schedule-tabs-professor.component.html', | ||||
|   styleUrl: './schedule-tabs-professor.component.css' | ||||
|   templateUrl: './professor.component.html', | ||||
|   styleUrl: './professor.component.css' | ||||
| }) | ||||
| export class ScheduleTabsProfessorComponent implements OnInit { | ||||
| export class ProfessorComponent implements OnInit { | ||||
|   protected professorControl = new FormControl(); | ||||
|   protected filteredProfessors!: Observable<ProfessorResponse[]>; | ||||
| 
 | ||||
							
								
								
									
										14
									
								
								src/components/schedule/tabs/tabs.component.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/components/schedule/tabs/tabs.component.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| .padding-content div { | ||||
|   padding: 30px 15px; | ||||
| } | ||||
|  | ||||
| .margin-other-button { | ||||
|   display: flex; | ||||
|   align-items: stretch; | ||||
|   justify-content: space-around; | ||||
|   flex-wrap: wrap; | ||||
| } | ||||
|  | ||||
| .margin-other-button app-schedule-tabs-other { | ||||
|   margin-right: 15px; | ||||
| } | ||||
							
								
								
									
										36
									
								
								src/components/schedule/tabs/tabs.component.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/components/schedule/tabs/tabs.component.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| <mat-tab-group dynamicHeight mat-stretch-tabs="false" mat-align-tabs="start" color="accent" class="padding-content" | ||||
|                (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()"/> | ||||
|     </div> | ||||
|   </mat-tab> | ||||
|   <mat-tab label="Преподаватель"> | ||||
|     <div> | ||||
|       <app-professor (professorSelected)="professorSelected.emit($event)" [professors]="professorsData" [professorsLoaded]="professorsLoaded" (professorsLoadRetry)="professorsLoad()"/> | ||||
|     </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)"/> | ||||
|     </div> | ||||
|   </mat-tab> | ||||
|   <mat-tab label="Другое"> | ||||
|     <div class="margin-other-button"> | ||||
|       <app-other idButton="disciplines-button" textButton="Дисциплины" #discipline [dataLoaded]="disciplinesLoaded" (retryLoadData)="loadDisciplines()"/> | ||||
|       <app-other idButton="lecture-button" textButton="Кабинеты" #lecture [dataLoaded]="campusesLoaded && lectureHallsLoaded" (retryLoadData)="loadLectureHalls()"/> | ||||
|       <app-other idButton="group-button" textButton="Группы" #group [dataLoaded]="facultiesLoaded && groupLoaded" (retryLoadData)="loadGroups()"/> | ||||
|       <app-other idButton="professor-button" textButton="Профессоры" #professor [dataLoaded]="professorsLoaded" (retryLoadData)="professorsLoad()"/> | ||||
|       <section> | ||||
|         <button mat-flat-button (click)="onClickNagmi()">Отфильтровать</button> | ||||
|       </section> | ||||
|     </div> | ||||
|   </mat-tab> | ||||
| </mat-tab-group> | ||||
							
								
								
									
										277
									
								
								src/components/schedule/tabs/tabs.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										277
									
								
								src/components/schedule/tabs/tabs.component.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,277 @@ | ||||
| import {Component, EventEmitter, Output, ViewChild} from '@angular/core'; | ||||
| import {HttpClientModule} from "@angular/common/http"; | ||||
| import {ApiService} from '@service/api.service'; | ||||
| import {OtherComponent} from "@component/schedule/tabs/other/other.component"; | ||||
| import {MatTab, MatTabChangeEvent, MatTabGroup} from "@angular/material/tabs"; | ||||
| import { | ||||
|   ProfessorComponent | ||||
| } from "@component/schedule/tabs/professor/professor.component"; | ||||
| import {GroupComponent} from "@component/schedule/tabs/group/group.component"; | ||||
| import { | ||||
|   LectureHallComponent | ||||
| } from "@component/schedule/tabs/lecture-hall/lecture-hall.component"; | ||||
| import {ProfessorResponse} from "@model/professorResponse"; | ||||
| import {catchError, map, Observable, of, switchMap, tap} from "rxjs"; | ||||
| import {GroupResponse} from "@model/groupResponse"; | ||||
| import {FacultyResponse} from "@model/facultyResponse"; | ||||
| import {CampusBasicInfoResponse} from "@model/campusBasicInfoResponse"; | ||||
| import {LectureHallResponse} from "@model/lectureHallResponse"; | ||||
| import {ReactiveFormsModule} from "@angular/forms"; | ||||
| import {AsyncPipe, NgIf} from "@angular/common"; | ||||
| import {DisciplineResponse} from "@model/disciplineResponse"; | ||||
| import {MatButton} from "@angular/material/button"; | ||||
| import {DataSpinnerComponent} from "@component/common/data-spinner/data-spinner.component"; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-tabs', | ||||
|   standalone: true, | ||||
|   imports: [ | ||||
|     HttpClientModule, | ||||
|     OtherComponent, | ||||
|     MatTabGroup, | ||||
|     MatTab, | ||||
|     ProfessorComponent, | ||||
|     GroupComponent, | ||||
|     LectureHallComponent, | ||||
|     ReactiveFormsModule, | ||||
|     AsyncPipe, | ||||
|     NgIf, | ||||
|     MatButton, | ||||
|     DataSpinnerComponent | ||||
|   ], | ||||
|   templateUrl: './tabs.component.html', | ||||
|   styleUrl: './tabs.component.css' | ||||
| }) | ||||
|  | ||||
| export class TabsComponent { | ||||
|   protected professorsData: ProfessorResponse[] = []; | ||||
|  | ||||
|   protected faculties: Observable<FacultyResponse[]> = of([]); | ||||
|   protected groups: Observable<GroupResponse[]> = of([]); | ||||
|   private groupsData: Observable<GroupResponse[]> = of([]); | ||||
|  | ||||
|   protected campuses: Observable<CampusBasicInfoResponse[]> = of([]); | ||||
|   protected lectureHalls: Observable<LectureHallResponse[]> = of([]); | ||||
|   private lectureHallsData: Observable<LectureHallResponse[]> = of([]); | ||||
|  | ||||
|   // 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; | ||||
|  | ||||
|   @Output() groupSelected: EventEmitter<number> = new EventEmitter<number>(); | ||||
|   @Output() lectureHallSelected: EventEmitter<number> = new EventEmitter<number>(); | ||||
|   @Output() professorSelected: EventEmitter<number> = new EventEmitter<number>(); | ||||
|  | ||||
|   constructor(private api: ApiService) { | ||||
|     this.facultyLoad().then(); | ||||
|   } | ||||
|  | ||||
|   protected async chooseTabs(event: MatTabChangeEvent) { | ||||
|     console.log(event); | ||||
|     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.api.get<FacultyResponse[]>("Faculty/Get").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.api.get<GroupResponse[]>("Group/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.api.get<ProfessorResponse[]>("Professor/Get").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.api.get<CampusBasicInfoResponse[]>("Campus/Get").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.api.get<LectureHallResponse[]>("LectureHall/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.api.get<LectureHallResponse[]>("LectureHall/Get"); | ||||
|       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; | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   protected async loadDisciplines() { | ||||
|     if (!this.disciplinesLoaded) { | ||||
|       this.api.get<DisciplineResponse[]>("Discipline/Get").pipe( | ||||
|         catchError((error) => { | ||||
|           this.disciplinesLoaded = null; | ||||
|           throw error; | ||||
|         })).subscribe(data => { | ||||
|         this.disciplineEx.Data = data.map(x => | ||||
|           ({ | ||||
|             id: x.id, | ||||
|             name: x.name, | ||||
|             selected: false | ||||
|           })); | ||||
|         this.disciplinesLoaded = true; | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   protected async loadGroups() { | ||||
|     if (!this.facultiesLoaded) | ||||
|       await this.facultyLoad(); | ||||
|  | ||||
|     if (!this.groupLoaded) { | ||||
|       this.groupsData = this.api.get<GroupResponse[]>("Group/Get"); | ||||
|       this.groupsData.pipe( | ||||
|         switchMap(groups => this.faculties.pipe( | ||||
|           map(campuses => { | ||||
|             return groups.map(x => { | ||||
|               const faculties = campuses.find(c => c.id === x.facultyId); | ||||
|               const name = faculties ? faculties.name : ''; | ||||
|               return { | ||||
|                 id: x.id, | ||||
|                 name: `${x.name} (${name})`, | ||||
|                 selected: false | ||||
|               }; | ||||
|             }); | ||||
|           }) | ||||
|         )) | ||||
|       ).subscribe(data => { | ||||
|         this.groupEx.Data = data; | ||||
|         this.groupLoaded = true; | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   protected async extensionLoad() { | ||||
|     // Lecture Hall | ||||
|     await this.loadLectureHalls(); | ||||
|  | ||||
|     // Disciplines | ||||
|     await this.loadDisciplines(); | ||||
|  | ||||
|     // Groups | ||||
|     await this.loadGroups(); | ||||
|  | ||||
|     // Professors | ||||
|     if (this.professorsData.length === 0) | ||||
|       this.professorsLoad(); | ||||
|   } | ||||
|  | ||||
|   @ViewChild('discipline') disciplineEx!: OtherComponent; | ||||
|   @ViewChild('lecture') lectureHallEx!: OtherComponent; | ||||
|   @ViewChild('group') groupEx!: OtherComponent; | ||||
|   @ViewChild('professor') professorEx!: OtherComponent; | ||||
|  | ||||
|   onClickNagmi() { | ||||
|     console.log('huy  = ' + this.disciplineEx.selectedIds); | ||||
|     console.log('huy2 = ' + this.lectureHallEx.selectedIds); | ||||
|     console.log('huy3 = ' + this.groupEx.selectedIds); | ||||
|     console.log('huy3 = ' + this.professorEx.selectedIds); | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user