import {Component, LOCALE_ID, ViewChild} from '@angular/core'; import {AdditionalText, TableHeaderComponent} from "@component/schedule/table-header/table-header.component"; import {addDays, weekInYear} from "@progress/kendo-date-math"; import {TabsComponent, TabsSelect} from "@component/schedule/tabs/tabs.component"; import {catchError, Observable} from "rxjs"; import {ScheduleService} from "@api/v1/schedule.service"; import {ScheduleResponse} from "@api/v1/scheduleResponse"; import {PairPeriodTime} from "@model/pairPeriodTime"; import {ActivatedRoute} from "@angular/router"; import {TabStorageService} from "@service/tab-storage.service"; import {MatDialog} from "@angular/material/dialog"; import {ConfirmDialogComponent} from "@page/schedule/confirm-dialog.component"; import {AuthRoles} from "@model/authRoles"; import {ImportService} from "@api/v1/import.service"; import {ScheduleRequest} from "@api/v1/scheduleRequest"; import {ToastrService} from "ngx-toastr"; import {MatSidenavModule} from "@angular/material/sidenav"; import {TableComponent} from "@component/schedule/table/table.component"; import {MatCheckbox} from "@angular/material/checkbox"; import {DataSpinnerComponent} from "@component/common/data-spinner/data-spinner.component"; import {MatButton} from "@angular/material/button"; import {HasRoleDirective} from "@/directives/has-role.directive"; @Component({ selector: 'app-schedule', standalone: true, imports: [ MatSidenavModule, TabsComponent, TableHeaderComponent, TableComponent, MatCheckbox, DataSpinnerComponent, MatButton, HasRoleDirective ], templateUrl: './schedule.component.html', styleUrl: './schedule.component.css', providers: [ ScheduleService, ImportService, {provide: LOCALE_ID, useValue: 'ru-RU'} ] }) export class ScheduleComponent { private lastRequest: ScheduleRequest | null = null; protected startWeek: Date; protected data: ScheduleResponse[] = []; protected startTerm: Date; protected isLoadTable: boolean = false; protected pairPeriods: PairPeriodTime | null = null; protected disciplineWithWeeks: boolean = false; protected excelImportLoader: boolean = false; @ViewChild('tableHeader') childComponent!: TableHeaderComponent; constructor(api: ScheduleService, route: ActivatedRoute, private importApi: ImportService, private notify: ToastrService, public dialog: MatDialog) { route.queryParams.subscribe(params => { TabStorageService.selectDataFromQuery(params); }); this.startTerm = new Date(1, 1, 1); this.startWeek = new Date(1, 1, 1); let disciplineWithWeeksStorage = localStorage.getItem('disciplineWithWeeks'); if (disciplineWithWeeksStorage) this.disciplineWithWeeks = disciplineWithWeeksStorage.toLowerCase() === 'true'; api.pairPeriod().subscribe(date => { this.pairPeriods = date; }); api.startTerm().subscribe(date => { this.startTerm = date.date; this.calculateCurrentWeek(); }); } protected result(data: [TabsSelect, number, Observable, ScheduleRequest]) { this.isLoadTable = true; this.lastRequest = data[3]; data[2] .pipe(catchError(error => { this.data = []; throw error; })) .subscribe(x => { if (x == undefined || x.length === 0) { this.isLoadTable = false; return; } this.data = x; switch (data[0]) { case TabsSelect.Group: this.childComponent.AdditionalText(AdditionalText.Group, this.data[0].group); break; case TabsSelect.Professor: let indexProfessor = this.data[0].professorsId.findIndex(p => p === data[1]); this.childComponent.AdditionalText(AdditionalText.Professor, this.data[0].professors[indexProfessor]); break; case TabsSelect.LectureHall: this.childComponent.AdditionalText(AdditionalText.LectureHall, `${this.data[0].lectureHalls[0]} (${this.data[0].campus[0]})`); break; case TabsSelect.Other: this.childComponent.AdditionalText(AdditionalText.Other, ''); break; } this.isLoadTable = false; }); } private calculateCurrentWeek() { let currentDate = new Date(); if (currentDate.getDate() < this.startTerm.getDate()) currentDate = this.startTerm; function startOfWeek(date: Date) { return addDays(date, -date.getDay() + 1); } this.startWeek = currentDate.getDay() === 0 ? startOfWeek(addDays(currentDate, 1)) : startOfWeek(currentDate); if (this.startWeek < this.startTerm) this.startWeek = this.startTerm; } protected handleWeekEvent(eventData: boolean | null) { if (eventData === null) { this.calculateCurrentWeek(); } else if (eventData) { this.startWeek = addDays(this.startWeek, 7); } else { this.startWeek = addDays(this.startWeek, -7); } } get currentWeek(): number { let result = (weekInYear(this.startWeek) - weekInYear(this.startTerm)) + 1; if (result <= 0) result = 1; return result; } protected changeDisciplineWeeksView(checked: boolean) { localStorage.setItem('disciplineWithWeeks', checked.toString()); this.disciplineWithWeeks = checked; } protected openDialog() { if (this.lastRequest == null) { this.notify.error("It is not possible to make an import request because the table data has not been selected", "Import error"); return; } const dialogRef = this.dialog.open(ConfirmDialogComponent); dialogRef.afterClosed().subscribe(result => { if (result && this.lastRequest != null) { this.excelImportLoader = true; this.importApi.importToExcel(this.lastRequest).subscribe({ next: (blob: Blob) => { const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'schedule.xlsx'; a.click(); window.URL.revokeObjectURL(url); this.excelImportLoader = false; }, error: _ => { this.excelImportLoader = false; this.notify.error("Failed to import Excel file"); } }); } }); } protected readonly AuthRoles = AuthRoles; }