refactor: folders and components
This commit is contained in:
		| @@ -1,6 +1,6 @@ | |||||||
| import {Component} from "@angular/core"; | import {Component} from "@angular/core"; | ||||||
| import {MatList, MatListItem} from "@angular/material/list"; | import {MatList, MatListItem} from "@angular/material/list"; | ||||||
| import {version} from "@/../package.json"; | import {version} from "../../../../package.json"; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-footer', |   selector: 'app-footer', | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| import {Component, EventEmitter, Input, Output} from '@angular/core'; | 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 {MatIcon} from "@angular/material/icon"; | ||||||
| import {MatButton, MatFabButton} from "@angular/material/button"; | 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 {map, Observable, of} from "rxjs"; | ||||||
| import {FacultyResponse} from "@model/facultyResponse"; | import {FacultyResponse} from "@model/facultyResponse"; | ||||||
| import {GroupResponse} from "@model/groupResponse"; | 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({ | @Component({ | ||||||
|   selector: 'app-schedule-tabs-group', |   selector: 'app-group', | ||||||
|   standalone: true, |   standalone: true, | ||||||
|   imports: [ |   imports: [ | ||||||
|     MatExpansionModule, |     MatExpansionModule, | ||||||
| @@ -18,11 +18,11 @@ import {LoadingIndicatorComponent} from "@component/loading-indicator/loading-in | |||||||
|     LoadingIndicatorComponent, |     LoadingIndicatorComponent, | ||||||
|     AsyncPipe |     AsyncPipe | ||||||
|   ], |   ], | ||||||
|   templateUrl: './schedule-tabs-group.component.html', |   templateUrl: './group.component.html', | ||||||
|   styleUrl: './schedule-tabs-group.component.css' |   styleUrl: './group.component.css' | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| export class ScheduleTabsGroupComponent { | export class GroupComponent { | ||||||
|   protected facultyId: number | null = null; |   protected facultyId: number | null = null; | ||||||
|   protected courseNumber: number | null = null; |   protected courseNumber: number | null = null; | ||||||
| 
 | 
 | ||||||
| @@ -6,10 +6,10 @@ import {Observable, of} from "rxjs"; | |||||||
| import {CampusBasicInfoResponse} from "@model/campusBasicInfoResponse"; | import {CampusBasicInfoResponse} from "@model/campusBasicInfoResponse"; | ||||||
| import {FormControl, ReactiveFormsModule} from "@angular/forms"; | import {FormControl, ReactiveFormsModule} from "@angular/forms"; | ||||||
| import {LectureHallResponse} from "@model/lectureHallResponse"; | 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({ | @Component({ | ||||||
|   selector: 'app-schedule-tabs-lecture-hall', |   selector: 'app-lecture-hall', | ||||||
|   standalone: true, |   standalone: true, | ||||||
|   imports: [ |   imports: [ | ||||||
|     MatChipsModule, |     MatChipsModule, | ||||||
| @@ -19,10 +19,10 @@ import {LoadingIndicatorComponent} from "@component/loading-indicator/loading-in | |||||||
|     MatAccordion, |     MatAccordion, | ||||||
|     LoadingIndicatorComponent |     LoadingIndicatorComponent | ||||||
|   ], |   ], | ||||||
|   templateUrl: './schedule-tabs-lecture-hall.component.html', |   templateUrl: './lecture-hall.component.html', | ||||||
|   styleUrl: './schedule-tabs-lecture-hall.component.css' |   styleUrl: './lecture-hall.component.css' | ||||||
| }) | }) | ||||||
| export class ScheduleTabsLectureHallComponent { | export class LectureHallComponent { | ||||||
|   protected campusId: number | null = null; |   protected campusId: number | null = null; | ||||||
|   protected chipLecture: FormControl = new FormControl(); |   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 {ScrollingModule as ExperimentalScrollingModule} from '@angular/cdk-experimental/scrolling'; | ||||||
| import {MatDivider} from "@angular/material/divider"; | import {MatDivider} from "@angular/material/divider"; | ||||||
| import {MatInput} from "@angular/material/input"; | 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 { | export interface SelectData { | ||||||
|   id: number, |   id: number, | ||||||
| @@ -20,7 +20,7 @@ export interface SelectData { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-schedule-tabs-other', |   selector: 'app-other', | ||||||
|   standalone: true, |   standalone: true, | ||||||
|   imports: [ |   imports: [ | ||||||
|     MatMenuTrigger, |     MatMenuTrigger, | ||||||
| @@ -40,10 +40,10 @@ export interface SelectData { | |||||||
|     ExperimentalScrollingModule, |     ExperimentalScrollingModule, | ||||||
|     LoadingIndicatorComponent |     LoadingIndicatorComponent | ||||||
|   ], |   ], | ||||||
|   templateUrl: './schedule-tabs-other.component.html', |   templateUrl: './other.component.html', | ||||||
|   styleUrl: './schedule-tabs-other.component.css' |   styleUrl: './other.component.css' | ||||||
| }) | }) | ||||||
| export class ScheduleTabsOtherComponent { | export class OtherComponent { | ||||||
|   private _searchQuery: string = ''; |   private _searchQuery: string = ''; | ||||||
|   protected filteredData: BehaviorSubject<SelectData[]> = new BehaviorSubject<SelectData[]>([]); |   protected filteredData: BehaviorSubject<SelectData[]> = new BehaviorSubject<SelectData[]>([]); | ||||||
|   protected data: SelectData[] = []; |   protected data: SelectData[] = []; | ||||||
| @@ -5,10 +5,10 @@ import {MatAutocompleteModule, MatAutocompleteSelectedEvent} from "@angular/mate | |||||||
| import {AsyncPipe} from "@angular/common"; | import {AsyncPipe} from "@angular/common"; | ||||||
| import {map, Observable, startWith} from "rxjs"; | import {map, Observable, startWith} from "rxjs"; | ||||||
| import {ProfessorResponse} from "@model/professorResponse"; | 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({ | @Component({ | ||||||
|   selector: 'app-schedule-tabs-professor', |   selector: 'app-professor', | ||||||
|   standalone: true, |   standalone: true, | ||||||
|   imports: [ |   imports: [ | ||||||
|     MatAutocompleteModule, |     MatAutocompleteModule, | ||||||
| @@ -18,10 +18,10 @@ import {LoadingIndicatorComponent} from "@component/loading-indicator/loading-in | |||||||
|     MatInput, |     MatInput, | ||||||
|     LoadingIndicatorComponent |     LoadingIndicatorComponent | ||||||
|   ], |   ], | ||||||
|   templateUrl: './schedule-tabs-professor.component.html', |   templateUrl: './professor.component.html', | ||||||
|   styleUrl: './schedule-tabs-professor.component.css' |   styleUrl: './professor.component.css' | ||||||
| }) | }) | ||||||
| export class ScheduleTabsProfessorComponent implements OnInit { | export class ProfessorComponent implements OnInit { | ||||||
|   protected professorControl = new FormControl(); |   protected professorControl = new FormControl(); | ||||||
|   protected filteredProfessors!: Observable<ProfessorResponse[]>; |   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