From afc01c14098548ed319c05f02ae9a1e341245803 Mon Sep 17 00:00:00 2001 From: Polianin Nikita Date: Tue, 21 May 2024 02:34:23 +0300 Subject: [PATCH] refactor: folders and components --- .../data-spinner/data-spinner.component.css | 0 .../data-spinner/data-spinner.component.html | 0 .../data-spinner/data-spinner.component.ts | 0 .../{ => common}/footer/footer.component.css | 0 .../{ => common}/footer/footer.component.html | 0 .../{ => common}/footer/footer.component.ts | 2 +- .../loading-indicator.component.html | 0 .../loading-indicator.component.ts | 2 +- .../notification/notification.component.css | 0 .../notification/notification.component.html | 0 .../notification/notification.component.ts | 0 .../table-header/table-header.component.css | 0 .../table-header/table-header.component.html | 0 .../table-header/table-header.component.ts | 0 .../schedule/table/table.component.css | 54 ++++ .../schedule/table/table.component.html | 116 ++++++++ .../schedule/table/table.component.ts | 89 ++++++ .../tabs/group/group.component.css} | 0 .../tabs/group/group.component.html} | 0 .../tabs/group/group.component.ts} | 10 +- .../lecture-hall/lecture-hall.component.css} | 0 .../lecture-hall/lecture-hall.component.html} | 0 .../lecture-hall/lecture-hall.component.ts} | 10 +- .../tabs/other/other.component.css} | 0 .../tabs/other/other.component.html} | 0 .../tabs/other/other.component.ts} | 10 +- .../tabs/professor/professor.component.css} | 0 .../tabs/professor/professor.component.html} | 0 .../tabs/professor/professor.component.ts} | 10 +- .../schedule/tabs/tabs.component.css | 14 + .../schedule/tabs/tabs.component.html | 36 +++ .../schedule/tabs/tabs.component.ts | 277 ++++++++++++++++++ 32 files changed, 608 insertions(+), 22 deletions(-) rename src/components/{ => common}/data-spinner/data-spinner.component.css (100%) rename src/components/{ => common}/data-spinner/data-spinner.component.html (100%) rename src/components/{ => common}/data-spinner/data-spinner.component.ts (100%) rename src/components/{ => common}/footer/footer.component.css (100%) rename src/components/{ => common}/footer/footer.component.html (100%) rename src/components/{ => common}/footer/footer.component.ts (90%) rename src/components/{ => common}/loading-indicator/loading-indicator.component.html (100%) rename src/components/{ => common}/loading-indicator/loading-indicator.component.ts (85%) rename src/components/{ => common}/notification/notification.component.css (100%) rename src/components/{ => common}/notification/notification.component.html (100%) rename src/components/{ => common}/notification/notification.component.ts (100%) rename src/components/{ => schedule}/table-header/table-header.component.css (100%) rename src/components/{ => schedule}/table-header/table-header.component.html (100%) rename src/components/{ => schedule}/table-header/table-header.component.ts (100%) create mode 100644 src/components/schedule/table/table.component.css create mode 100644 src/components/schedule/table/table.component.html create mode 100644 src/components/schedule/table/table.component.ts rename src/components/{schedule-tabs/schedule-tabs-group/schedule-tabs-group.component.css => schedule/tabs/group/group.component.css} (100%) rename src/components/{schedule-tabs/schedule-tabs-group/schedule-tabs-group.component.html => schedule/tabs/group/group.component.html} (100%) rename src/components/{schedule-tabs/schedule-tabs-group/schedule-tabs-group.component.ts => schedule/tabs/group/group.component.ts} (91%) rename src/components/{schedule-tabs/schedule-tabs-lecture-hall/schedule-tabs-lecture-hall.component.css => schedule/tabs/lecture-hall/lecture-hall.component.css} (100%) rename src/components/{schedule-tabs/schedule-tabs-lecture-hall/schedule-tabs-lecture-hall.component.html => schedule/tabs/lecture-hall/lecture-hall.component.html} (100%) rename src/components/{schedule-tabs/schedule-tabs-lecture-hall/schedule-tabs-lecture-hall.component.ts => schedule/tabs/lecture-hall/lecture-hall.component.ts} (86%) rename src/components/{schedule-tabs/schedule-tabs-other/schedule-tabs-other.component.css => schedule/tabs/other/other.component.css} (100%) rename src/components/{schedule-tabs/schedule-tabs-other/schedule-tabs-other.component.html => schedule/tabs/other/other.component.html} (100%) rename src/components/{schedule-tabs/schedule-tabs-other/schedule-tabs-other.component.ts => schedule/tabs/other/other.component.ts} (93%) rename src/components/{schedule-tabs/schedule-tabs-professor/schedule-tabs-professor.component.css => schedule/tabs/professor/professor.component.css} (100%) rename src/components/{schedule-tabs/schedule-tabs-professor/schedule-tabs-professor.component.html => schedule/tabs/professor/professor.component.html} (100%) rename src/components/{schedule-tabs/schedule-tabs-professor/schedule-tabs-professor.component.ts => schedule/tabs/professor/professor.component.ts} (85%) create mode 100644 src/components/schedule/tabs/tabs.component.css create mode 100644 src/components/schedule/tabs/tabs.component.html create mode 100644 src/components/schedule/tabs/tabs.component.ts diff --git a/src/components/data-spinner/data-spinner.component.css b/src/components/common/data-spinner/data-spinner.component.css similarity index 100% rename from src/components/data-spinner/data-spinner.component.css rename to src/components/common/data-spinner/data-spinner.component.css diff --git a/src/components/data-spinner/data-spinner.component.html b/src/components/common/data-spinner/data-spinner.component.html similarity index 100% rename from src/components/data-spinner/data-spinner.component.html rename to src/components/common/data-spinner/data-spinner.component.html diff --git a/src/components/data-spinner/data-spinner.component.ts b/src/components/common/data-spinner/data-spinner.component.ts similarity index 100% rename from src/components/data-spinner/data-spinner.component.ts rename to src/components/common/data-spinner/data-spinner.component.ts diff --git a/src/components/footer/footer.component.css b/src/components/common/footer/footer.component.css similarity index 100% rename from src/components/footer/footer.component.css rename to src/components/common/footer/footer.component.css diff --git a/src/components/footer/footer.component.html b/src/components/common/footer/footer.component.html similarity index 100% rename from src/components/footer/footer.component.html rename to src/components/common/footer/footer.component.html diff --git a/src/components/footer/footer.component.ts b/src/components/common/footer/footer.component.ts similarity index 90% rename from src/components/footer/footer.component.ts rename to src/components/common/footer/footer.component.ts index 90706e4..e034734 100644 --- a/src/components/footer/footer.component.ts +++ b/src/components/common/footer/footer.component.ts @@ -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', diff --git a/src/components/loading-indicator/loading-indicator.component.html b/src/components/common/loading-indicator/loading-indicator.component.html similarity index 100% rename from src/components/loading-indicator/loading-indicator.component.html rename to src/components/common/loading-indicator/loading-indicator.component.html diff --git a/src/components/loading-indicator/loading-indicator.component.ts b/src/components/common/loading-indicator/loading-indicator.component.ts similarity index 85% rename from src/components/loading-indicator/loading-indicator.component.ts rename to src/components/common/loading-indicator/loading-indicator.component.ts index 8ec20ad..82342db 100644 --- a/src/components/loading-indicator/loading-indicator.component.ts +++ b/src/components/common/loading-indicator/loading-indicator.component.ts @@ -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"; diff --git a/src/components/notification/notification.component.css b/src/components/common/notification/notification.component.css similarity index 100% rename from src/components/notification/notification.component.css rename to src/components/common/notification/notification.component.css diff --git a/src/components/notification/notification.component.html b/src/components/common/notification/notification.component.html similarity index 100% rename from src/components/notification/notification.component.html rename to src/components/common/notification/notification.component.html diff --git a/src/components/notification/notification.component.ts b/src/components/common/notification/notification.component.ts similarity index 100% rename from src/components/notification/notification.component.ts rename to src/components/common/notification/notification.component.ts diff --git a/src/components/table-header/table-header.component.css b/src/components/schedule/table-header/table-header.component.css similarity index 100% rename from src/components/table-header/table-header.component.css rename to src/components/schedule/table-header/table-header.component.css diff --git a/src/components/table-header/table-header.component.html b/src/components/schedule/table-header/table-header.component.html similarity index 100% rename from src/components/table-header/table-header.component.html rename to src/components/schedule/table-header/table-header.component.html diff --git a/src/components/table-header/table-header.component.ts b/src/components/schedule/table-header/table-header.component.ts similarity index 100% rename from src/components/table-header/table-header.component.ts rename to src/components/schedule/table-header/table-header.component.ts diff --git a/src/components/schedule/table/table.component.css b/src/components/schedule/table/table.component.css new file mode 100644 index 0000000..fac2b16 --- /dev/null +++ b/src/components/schedule/table/table.component.css @@ -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; +} diff --git a/src/components/schedule/table/table.component.html b/src/components/schedule/table/table.component.html new file mode 100644 index 0000000..f2079d9 --- /dev/null +++ b/src/components/schedule/table/table.component.html @@ -0,0 +1,116 @@ +
+ @if (dataSource.length === 0 || isLoad) { +
+ @if (isLoad) { + + } @else { +

Нет данных.

+

Выберите необходимое расписание сверху

+ } +
+ } + + + + + + + + + + + @for (day of daysOfWeek; track $index) { + + + + + + + + } + + + +
+ Пара + +
+ @if (currentWeek % 2 === 0) { + Четная + } @else { + Нечетная + } +
+ {{ element["pairNumber"] }} + + + {{ day }} + +
+ + {{ addDays(startWeek, daysOfWeek.indexOf(day)) | date:"shortDate" }} + +
+ @for (elementData of element.data[daysOfWeek.indexOf(day) + 1]; track $index) { + +
{{ elementData["discipline"] }}
+ +
({{ elementData["typeOfOccupation"] }})
+ + + @if (checkAvailableData(elementData["professors"])) { +
+ + + + @for (professor of elementData["professors"]; track $index) { + @if ($index !== 0) { +
+ } + {{ professor }} + } +
+ } + + + @if (checkAvailableData(elementData["lectureHalls"]) && checkAvailableData(elementData["campus"])) { +
+ + + + @for (lectureHall of elementData["lectureHalls"]; track $index) { + @if ($index !== 0) { +
+ } + @if (lectureHall) { + {{ lectureHall }} + } @else { + N/A + } + / + @if (elementData["campus"][$index]) { + {{ elementData["campus"][$index] }} + } @else { + N/A + } + } +
+ } + + + @if (!isOneGroup) { +
+ + + + {{ elementData["group"] }} +
+ } + + @if ($index + 1 !== element.data[daysOfWeek.indexOf(day) + 1].length) { +
+ } + } + +
+
diff --git a/src/components/schedule/table/table.component.ts b/src/components/schedule/table/table.component.ts new file mode 100644 index 0000000..a9449db --- /dev/null +++ b/src/components/schedule/table/table.component.ts @@ -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 = new MatTableDataSource([]); + 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); + this.isLoad = false; + } + + protected checkAvailableData(data: any[]): boolean { + return data && data.length !== 0 && data.every(x => x !== null); + } + + protected readonly addDays = addDays; +} diff --git a/src/components/schedule-tabs/schedule-tabs-group/schedule-tabs-group.component.css b/src/components/schedule/tabs/group/group.component.css similarity index 100% rename from src/components/schedule-tabs/schedule-tabs-group/schedule-tabs-group.component.css rename to src/components/schedule/tabs/group/group.component.css diff --git a/src/components/schedule-tabs/schedule-tabs-group/schedule-tabs-group.component.html b/src/components/schedule/tabs/group/group.component.html similarity index 100% rename from src/components/schedule-tabs/schedule-tabs-group/schedule-tabs-group.component.html rename to src/components/schedule/tabs/group/group.component.html diff --git a/src/components/schedule-tabs/schedule-tabs-group/schedule-tabs-group.component.ts b/src/components/schedule/tabs/group/group.component.ts similarity index 91% rename from src/components/schedule-tabs/schedule-tabs-group/schedule-tabs-group.component.ts rename to src/components/schedule/tabs/group/group.component.ts index 6f4508d..bf7ef36 100644 --- a/src/components/schedule-tabs/schedule-tabs-group/schedule-tabs-group.component.ts +++ b/src/components/schedule/tabs/group/group.component.ts @@ -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; diff --git a/src/components/schedule-tabs/schedule-tabs-lecture-hall/schedule-tabs-lecture-hall.component.css b/src/components/schedule/tabs/lecture-hall/lecture-hall.component.css similarity index 100% rename from src/components/schedule-tabs/schedule-tabs-lecture-hall/schedule-tabs-lecture-hall.component.css rename to src/components/schedule/tabs/lecture-hall/lecture-hall.component.css diff --git a/src/components/schedule-tabs/schedule-tabs-lecture-hall/schedule-tabs-lecture-hall.component.html b/src/components/schedule/tabs/lecture-hall/lecture-hall.component.html similarity index 100% rename from src/components/schedule-tabs/schedule-tabs-lecture-hall/schedule-tabs-lecture-hall.component.html rename to src/components/schedule/tabs/lecture-hall/lecture-hall.component.html diff --git a/src/components/schedule-tabs/schedule-tabs-lecture-hall/schedule-tabs-lecture-hall.component.ts b/src/components/schedule/tabs/lecture-hall/lecture-hall.component.ts similarity index 86% rename from src/components/schedule-tabs/schedule-tabs-lecture-hall/schedule-tabs-lecture-hall.component.ts rename to src/components/schedule/tabs/lecture-hall/lecture-hall.component.ts index 3072c5a..e58d107 100644 --- a/src/components/schedule-tabs/schedule-tabs-lecture-hall/schedule-tabs-lecture-hall.component.ts +++ b/src/components/schedule/tabs/lecture-hall/lecture-hall.component.ts @@ -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(); diff --git a/src/components/schedule-tabs/schedule-tabs-other/schedule-tabs-other.component.css b/src/components/schedule/tabs/other/other.component.css similarity index 100% rename from src/components/schedule-tabs/schedule-tabs-other/schedule-tabs-other.component.css rename to src/components/schedule/tabs/other/other.component.css diff --git a/src/components/schedule-tabs/schedule-tabs-other/schedule-tabs-other.component.html b/src/components/schedule/tabs/other/other.component.html similarity index 100% rename from src/components/schedule-tabs/schedule-tabs-other/schedule-tabs-other.component.html rename to src/components/schedule/tabs/other/other.component.html diff --git a/src/components/schedule-tabs/schedule-tabs-other/schedule-tabs-other.component.ts b/src/components/schedule/tabs/other/other.component.ts similarity index 93% rename from src/components/schedule-tabs/schedule-tabs-other/schedule-tabs-other.component.ts rename to src/components/schedule/tabs/other/other.component.ts index 4e4dad8..60434aa 100644 --- a/src/components/schedule-tabs/schedule-tabs-other/schedule-tabs-other.component.ts +++ b/src/components/schedule/tabs/other/other.component.ts @@ -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 = new BehaviorSubject([]); protected data: SelectData[] = []; diff --git a/src/components/schedule-tabs/schedule-tabs-professor/schedule-tabs-professor.component.css b/src/components/schedule/tabs/professor/professor.component.css similarity index 100% rename from src/components/schedule-tabs/schedule-tabs-professor/schedule-tabs-professor.component.css rename to src/components/schedule/tabs/professor/professor.component.css diff --git a/src/components/schedule-tabs/schedule-tabs-professor/schedule-tabs-professor.component.html b/src/components/schedule/tabs/professor/professor.component.html similarity index 100% rename from src/components/schedule-tabs/schedule-tabs-professor/schedule-tabs-professor.component.html rename to src/components/schedule/tabs/professor/professor.component.html diff --git a/src/components/schedule-tabs/schedule-tabs-professor/schedule-tabs-professor.component.ts b/src/components/schedule/tabs/professor/professor.component.ts similarity index 85% rename from src/components/schedule-tabs/schedule-tabs-professor/schedule-tabs-professor.component.ts rename to src/components/schedule/tabs/professor/professor.component.ts index 798bccb..7ace8fa 100644 --- a/src/components/schedule-tabs/schedule-tabs-professor/schedule-tabs-professor.component.ts +++ b/src/components/schedule/tabs/professor/professor.component.ts @@ -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; diff --git a/src/components/schedule/tabs/tabs.component.css b/src/components/schedule/tabs/tabs.component.css new file mode 100644 index 0000000..0d14066 --- /dev/null +++ b/src/components/schedule/tabs/tabs.component.css @@ -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; +} diff --git a/src/components/schedule/tabs/tabs.component.html b/src/components/schedule/tabs/tabs.component.html new file mode 100644 index 0000000..06ee020 --- /dev/null +++ b/src/components/schedule/tabs/tabs.component.html @@ -0,0 +1,36 @@ + + +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ + + + +
+ +
+
+
+
diff --git a/src/components/schedule/tabs/tabs.component.ts b/src/components/schedule/tabs/tabs.component.ts new file mode 100644 index 0000000..857236b --- /dev/null +++ b/src/components/schedule/tabs/tabs.component.ts @@ -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 = of([]); + protected groups: Observable = of([]); + private groupsData: Observable = of([]); + + protected campuses: Observable = of([]); + protected lectureHalls: Observable = of([]); + private lectureHallsData: Observable = 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 = new EventEmitter(); + @Output() lectureHallSelected: EventEmitter = new EventEmitter(); + @Output() professorSelected: EventEmitter = new EventEmitter(); + + 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("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("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("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("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("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("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("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("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); + } +}