
ПЗ_23-ИСТ-1-1_Какушкина_Ольга_Витальевна
.pdf
6Литература
1.Angular 2 [электронный ресурс]. – Режим доступа: https://metanit.com/web/angular2/ , дата обращения 25.10.2024.
2.Angular: Getting started [электронный ресурс]. – Режим доступа: https://developer.mozilla.org/ru/docs/Learn_web_development/Core/Frame works_libraries/Angular_getting_started , дата обращения 5.11.2024
3.Overview [электронный ресурс]. – Режим доступа: https://angular.dev/overview , дата обращения 5.11.2024.
4.Angular [электронный ресурс]. – Режим доступа: https://forum.itvdn.com/c/frontend-developer/angular/216 , дата обращения
20.11.2024.
5.AngularJS – форум [электронный ресурс]. – Режим доступа: https://www.cyberforum.ru/angularjs/ , дата обращения 20.12.2024
|
Лист |
|
НГТУ-(23-ИСТ-1-1)-КР |
|
|
41 |
||
|
Изм. Лист |
№ докум. |
Подпись Дата |

7 Приложение
Section.model.ts
export interface Section {
id: string; |
// Уникальный идентификатор секции |
|
title: string; |
// Название секции |
|
imageUrl: string; |
// URL изображения секции |
|
instructor: string; |
// ID преподавателя |
|
startTime: string; |
// Время начала |
|
endTime: string; |
// Время окончания |
|
day: string; |
// День |
|
capacity: number; |
// Вместимость |
reserved?: number;
}
Student.model.ts export class Student {
constructor( public id: string,
public firstName: string, public lastName: string, public email: string, public password: string, public group: string, public section: string, public institute: string, public payment: number, public grades: number,
public attendanceCount: number,
public requiredAttendance: number, public passStatus: 'pass' | 'fail',
public photoUrl?: string // Добавлено свойство photoUrl ) {}
}
Techer.model.ts
export interface Teacher { id: string;
firstName: string; lastName: string; email: string; password: string; experience: string; university: string; sections: string[]; photoUrl?: string | null;
requiredClasses?: number; // Новое поле для требуемых занятий isEditing?: boolean;
}
НГТУ-(23-ИСТ-1-1)-КР
Изм. Лист |
№ докум. |
Подпись Дата |
Лист
42

Upload.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs';
@Injectable({ providedIn: 'root'
})
export class UploadService {
private uploadUrl = 'http://localhost:3002/upload'; // Путь к серверу
constructor(private http: HttpClient) {}
uploadFile(file: File): Observable<any> { const formData = new FormData(); formData.append('file', file);
return this.http.post(this.uploadUrl, formData);
}
uploadFile2(formData: FormData): Observable<any> { // Изменили на FormData
return this.http.post(this.uploadUrl, formData);
}
}
Section.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, catchError, throwError, tap,switchMap,map } from 'rxjs'; import { Section } from '../models/section.model';
@Injectable({ providedIn: 'root'
})
export class SectionService {
private readonly apiUrl = 'http://localhost:3000/sections';
private readonly instituteApiUrl = 'http://localhost:3000/institutes';
constructor(private http: HttpClient) {}
getSectionByTitle(title: string): Observable<Section | null> { return this.getSections().pipe(
map((sections: Section[]) => sections.find(section => section.title === title) || null), catchError((error) => {
console.error('Ошибка при получении секции по названию:', error);
return throwError(() => new Error('Не удалось получить секцию по названию.'));
})
);
НГТУ-(23-ИСТ-1-1)-КР
Изм. Лист |
№ докум. |
Подпись Дата |
Лист
43

}
getSectionById(sectionId: string): Observable<{ name: string }> {
return this.http.get<{ name: string }>(`${this.apiUrl}/${sectionId}`).pipe( catchError((error) => {
console.error('Ошибка при получении института:', error);
return throwError(() => new Error('Не удалось получить институт. Попробуйте позже.')); })
);
}
// Метод для получения института по ID getInstituteById(instituteId: string): Observable<{ name: string }> {
return this.http.get<{ name: string }>(`${this.instituteApiUrl}/${instituteId}`).pipe( catchError((error) => {
console.error('Ошибка при получении института:', error);
return throwError(() => new Error('Не удалось получить институт. Попробуйте позже.'));
})
);
}
getSections(): Observable<Section[]> {
return this.http.get<Section[]>(this.apiUrl).pipe( catchError((error) => {
console.error('Ошибка при получении секций:', error);
return throwError(() => new Error('Не удалось получить секции. Попробуйте позже.')); })
);
}
reserveSection(sectionId: number): Observable<Section> {
return this.http.get<Section>(`${this.apiUrl}/${sectionId}`).pipe( switchMap(section => {
if (section.capacity > 0) {
section.reserved = (section.reserved ?? 0) + 1; section.capacity -= 1;
return this.http.put<Section>(`${this.apiUrl}/${sectionId}`, section); } else {
return throwError(() => new Error('Недостаточно мест.'));
}
}),
catchError(error => {
console.error('Ошибка при резервировании секции:', error);
return throwError(() => new Error('Не удалось зарезервировать место. Попробуйте позже.'));
})
);
}
cancelReservation(sectionId: number): Observable<Section> {
|
Лист |
|
НГТУ-(23-ИСТ-1-1)-КР |
|
|
44 |
||
|
Изм. Лист |
№ докум. |
Подпись Дата |

return this.getSections().pipe( switchMap(sections => {
const section = sections.find(s => s.id === sectionId.toString()); // Приведение к строке if (section && (section.reserved ?? 0) > 0) {
section.reserved = (section.reserved ?? 0) - 1; section.capacity++;
return this.http.put<Section>(`${this.apiUrl}/${sectionId}`, section).pipe( tap(() => {
console.log(`Резервирование для секции ${sectionId} отменено.`); }),
catchError(error => {
console.error('Ошибка при отмене резервирования:', error);
return throwError(() => new Error('Не удалось отменить резервирование. Попробуйте позже.'));
})
);
} else {
return throwError(() => new Error('Нет резервированных мест для отмены.'));
}
})
);
}
// Метод для освобождения секции (возвращение мест) releaseSection(sectionId: string, count: number): Observable<void> {
return this.http.put<void>(`${this.apiUrl}/${sectionId}`, { count }).pipe( tap(() => {
// Не нужно управлять состоянием с BehaviorSubject
}),
catchError((error) => {
console.error('Ошибка при освобождении секции:', error);
return throwError(() => new Error('Не удалось освободить место. Попробуйте позже.')); })
);
}
addSection(section: Section): Observable<Section> { return this.http.post<Section>(this.apiUrl, section).pipe(
catchError((error) => {
console.error('Ошибка при добавлении секции:', error);
return throwError(() => new Error('Не удалось добавить секцию. Попробуйте позже.')); })
);
}
createSection(post: Omit<Section, 'id'>): Observable<Section> { return this.http.post<Section>(this.apiUrl, post).pipe(
catchError((error) => {
console.error('Ошибка при создании секции:', error);
return throwError(() => new Error('Не удалось создать секцию. Попробуйте позже.'));
|
Лист |
|
НГТУ-(23-ИСТ-1-1)-КР |
|
|
45 |
||
|
Изм. Лист |
№ докум. |
Подпись Дата |

})
);
}
updateSection(section: Section): Observable<Section> {
return this.http.put<Section>(`${this.apiUrl}/${section.id}`, section).pipe( catchError((error) => {
console.error('Ошибка при обновлении секции:', error);
return throwError(() => new Error('Не удалось обновить секцию. Попробуйте позже.')); })
);
}
deleteSection(id: string): Observable<void> {
return this.http.delete<void>(`${this.apiUrl}/${id}`).pipe( catchError((error) => {
console.error('Ошибка при удалении секции:', error);
return throwError(() => new Error('Не удалось удалить секцию. Попробуйте позже.')); })
);
}
}
Student.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'; import { Student } from '../models/student.model';
import { AbstractControl, AsyncValidatorFn, ValidationErrors } from '@angular/forms'; import { Observable, of } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
@Injectable({ providedIn: 'root',
})
export class StudentService {
private apiUrl = 'http://localhost:3000/students';
constructor(private http: HttpClient) {}
updateStudentEmail(student: Student) {
return this.http.put(`${this.apiUrl}/${student.id}/email`, { email: student.email });
}
updateStudentPassword(studentId: string, newPassword: string) {
return this.http.put(`${this.apiUrl}/${studentId}/password`, { password: newPassword });
}
// Метод для отправки данных о студенте submitStudent(student: Student): Observable<any> {
НГТУ-(23-ИСТ-1-1)-КР
Изм. Лист |
№ докум. |
Подпись Дата |
Лист
46

return this.http.post(this.apiUrl, student).pipe( catchError(err => {
console.error('Ошибка при отправке студента', err); return of(null);
})
);
}
//Получить список студентов getStudents(): Observable<Student[]> {
return this.http.get<Student[]>(this.apiUrl);
}
//Получить студентов по секциям getStudentsBySection(sections: string[]): Observable<Student[]> {
return this.http.get<Student[]>(`${this.apiUrl}?sections=${sections.join(',')}`);
}
//Получить уникальные группы студентов
getUniqueGroups(): Observable<string[]> { return this.getStudents().pipe(
map((students: Student[]) =>
[...new Set(students.map((student: Student) => student.group).filter(group => group !== undefined))]
)
);
}
// Метод для проверки существующего пользователя checkEmailExists(email: string): Observable<boolean> {
return this.http.get<Student[]>(`${this.apiUrl}?email=${email}`).pipe( map(students => students.length > 0),
catchError(() => of(false)) );
}
uniqueEmailValidator(): AsyncValidatorFn {
return (control: AbstractControl): Observable<ValidationErrors | null> => { const email = control.value;
if (!email) {
return of(null); // Если поле пустое, возвращаем null для валидации
}
return this.checkEmailExists(email).pipe(
map(exists => (exists ? { emailExists: true } : null)), catchError(() => of(null)) // Возвращаем null в случае ошибки
);
};
}
|
Лист |
|
НГТУ-(23-ИСТ-1-1)-КР |
|
|
47 |
||
|
Изм. Лист |
№ докум. |
Подпись Дата |

// Обновить посещаемость студента updateStudentAttendance(student: Student) {
return this.http.put(`${this.apiUrl}/${student.id}`, student).pipe( catchError(err => {
console.error('Ошибка при обновлении посещаемости', err); return of(null);
})
);
}
}
Teacher.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Teacher } from '../models/teacher.model'; import { Student } from '../models/student.model'; import { Section } from '../models/section.model';
@Injectable({ providedIn: 'root'
})
export class TeacherService {
private apiUrl = 'http://localhost:3000/teachers'; // URL для JSON Server private apiUrl2 = 'http://localhost:3000'; // Основной URL для работы с API
constructor(private http: HttpClient) {}
getStudents(): Observable<Student[]> {
return this.http.get<Student[]>(`${this.apiUrl2}/students`);
}
updateStudent(studentId: string, updateData: any): Observable<any> { return this.http.put(`${this.apiUrl2}/students/${studentId}`, updateData);
}
// Получение уникальных групп студентов по секции getUniqueStudentGroupsBySection(sectionId: string): Observable<string[]> {
return this.getStudentsBySection(sectionId).pipe(
map(students => Array.from(new Set(students.map(student => student.group).filter((group): group is string => group !== undefined))))
);
}
// Получение секций
getSections(): Observable<Section[]> {
|
Лист |
|
НГТУ-(23-ИСТ-1-1)-КР |
|
|
48 |
||
|
Изм. Лист |
№ докум. |
Подпись Дата |

return this.http.get<Section[]>(`${this.apiUrl2}/sections`);
}
//Получение всех преподавателей getTeachers(): Observable<Teacher[]> {
return this.http.get<Teacher[]>(this.apiUrl);
}
//Получение групп студентов getStudentGroups(): Observable<string[]> {
return this.getStudents().pipe(
map(students => Array.from(new Set(students.map(student => student.group).filter((group):
group is string => group !== undefined)))) );
}
//Получение студентов по секции getStudentsBySection(sectionId: string): Observable<Student[]> {
return this.http.get<Student[]>(`${this.apiUrl2}/students?section=${sectionId}`);
}
//Получение секций для конкретного преподавателя
getTeacherSections(): Observable<Section[]> {
const teacherId = JSON.parse(localStorage.getItem('teacher') || '{}').id; return this.http.get<Section[]>(`${this.apiUrl2}/sections`).pipe(
map(sections => sections.filter(section => section.instructor === teacherId)) );
}
//Получение расписания по ID секции getScheduleBySectionId(sectionId: string): Observable<any> {
return this.http.get<any>(`${this.apiUrl2}/sections/${sectionId}`);
}
//Добавление нового преподавателя
addTeacher(teacher: Teacher): Observable<Teacher> { return this.http.post<Teacher>(this.apiUrl, teacher);
}
//Обновление информации о преподавателе updateTeacher(teacher: Teacher): Observable<Teacher> {
return this.http.put<Teacher>(`${this.apiUrl}/${teacher.id}`, teacher);
}
//Удаление преподавателя
deleteTeacher(id: string): Observable<void> {
return this.http.delete<void>(`${this.apiUrl}/${id}`);
}
// Получение информации о преподавателе по ID getTeacherById(id: string): Observable<Teacher> {
НГТУ-(23-ИСТ-1-1)-КР
Изм. Лист |
№ докум. |
Подпись Дата |
Лист
49

return this.http.get<Teacher>(`${this.apiUrl}/${id}`);
}
// Получение настроек посещаемости для конкретного преподавателя getAttendanceSettings(teacherId: string): Observable<{ requiredAttendance: number }> {
return this.http.get<{ requiredAttendance: number }>(`${this.apiUrl}/${teacherId}/attendance-settings`);
}
// Загрузка фото
uploadPhoto(formData: FormData): Observable<{ imageUrl: string }> {
return this.http.post<{ imageUrl: string }>('http://localhost:3002/upload', formData);
}
//Обновление информации о преподавателе updateTeacherInfo(id: string, data: Teacher): Observable<Teacher> {
return this.http.put<Teacher>(`${this.apiUrl}/${id}`, data);
}
//Удаление фото
deletePhoto(id: string): Observable<void> {
return this.http.delete<void>(`http://localhost:3002/teachers/${id}/photoUrl`);
}
//Получение информации о секции по ID getSectionById(sectionId: number): Observable<any> {
return this.http.get(`${this.apiUrl2}/sections/${sectionId}`);
}
//Загрузка изображения, например, для профиля преподавателя uploadImage(file: File): Observable<string> {
const imagePath = `assets/img/teacher_page/${file.name}`; return new Observable(observer => {
observer.next(imagePath);
observer.complete();
});
}
//Получение названий секций для конкретного преподавателя getSectionNames(teacherId: string): Observable<string[]> {
return new Observable<string[]>((observer) => { this.getTeachers().subscribe((teachers) => {
const teacher = teachers.find(t => t.id === teacherId);
if (teacher && teacher.sections) { observer.next(teacher.sections); // Возвращаем массив секций
} else {
observer.next([]); // Возвращаем пустой массив, если секций нет
}
observer.complete();
});
})}}
НГТУ-(23-ИСТ-1-1)-КР
Изм. Лист |
№ докум. |
Подпись Дата |
Лист
50