Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions uniplanWeb/public/i18n/bg.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
},
"room": {
"room-number": "Номер на стая",
"no-rooms": "Няма записани стаи"
"no-rooms": "Няма записани стаи",
"add": {
"title": "Добави стая",
"failed": "Неуспешно добавяне на стаята."
}
},
"faculty": {
"delete-button": "Изтрий",
Expand All @@ -25,6 +29,9 @@
},
"edit": {
"title": "Редактирай факултет"
},
"load":{
"failed":"Неуспешно зареждане на факултети"
}
},
"major": {
Expand Down Expand Up @@ -60,7 +67,8 @@
"save-button": "Запази",
"delete-button": "Изтрий",
"option-all": "Всички",
"confirm-delete": "Потвърдете изтриването"
"confirm-delete": "Потвърдете изтриването",
"close-btn": "Затвори"
},
"home": {
"title": "Начало!"
Expand Down
12 changes: 10 additions & 2 deletions uniplanWeb/public/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
},
"room": {
"room-number": "Room number",
"no-rooms": "No rooms"
"no-rooms": "No rooms",
"add": {
"title": "Add room",
"failed": "Failed to add room."
}
},
"faculty": {
"delete-button": "Delete",
Expand All @@ -25,6 +29,9 @@
},
"edit": {
"title": "Edit faculty"
},
"load":{
"failed":"Failed to load faculties"
}
},
"major": {
Expand Down Expand Up @@ -60,7 +67,8 @@
"save-button": "Save",
"delete-button": "Delete",
"option-all": "All",
"confirm-delete": "Confirm deletion"
"confirm-delete": "Confirm deletion",
"close-btn": "Close"
},
"home": {
"title": "Main!"
Expand Down
1 change: 1 addition & 0 deletions uniplanWeb/src/app/config/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export const API_ENDPOINTS = {
courses: `${environment.baseUrl}/courses`,
faculties: `${environment.baseUrl}/faculties`,
majors: `${environment.baseUrl}/majors`,
rooms: `${environment.baseUrl}/rooms`,
};
7 changes: 7 additions & 0 deletions uniplanWeb/src/app/core/interfaces/course-elm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface CourseElm {
id: string;
majorId: string;
courseYear: number;
locaticourseTypeon: string;
courseSubtype: string;
}
22 changes: 11 additions & 11 deletions uniplanWeb/src/app/features/faculty/faculty-service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { HttpClient } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';
import { map, Observable, Subject } from 'rxjs';
import { map, Observable, Subject, tap } from 'rxjs';
import { FacultyElm } from '../../core/interfaces/faculty-elm';
import {API_ENDPOINTS} from '../../config/endpoints';
import { API_ENDPOINTS } from '../../config/endpoints';

@Injectable({
providedIn: 'root',
Expand Down Expand Up @@ -30,9 +30,9 @@ export class FacultyService {
universityId: string;
facultyName: string;
location: string;
}): Observable<any> {
return this.http.post(`${API_ENDPOINTS.faculties}`, faculty).pipe(
map((res) => {
}): Observable<void> {
return this.http.post<void>(`${API_ENDPOINTS.faculties}`, faculty).pipe(
tap((res) => {
this.refreshNeeded.next();
return res;
})
Expand All @@ -46,18 +46,18 @@ export class FacultyService {
facultyName: string;
location: string;
}
): Observable<any> {
return this.http.put(`${API_ENDPOINTS.faculties}/${id}`, updatedFaculty).pipe(
map((res) => {
): Observable<void> {
return this.http.put<void>(`${API_ENDPOINTS.faculties}/${id}`, updatedFaculty).pipe(
tap((res) => {
this.refreshNeeded.next();
return res;
})
);
}

deleteFaculty(id: string): Observable<any> {
return this.http.delete(`${API_ENDPOINTS.faculties}/${id}`).pipe(
map((res) => {
deleteFaculty(id: string): Observable<void> {
return this.http.delete<void>(`${API_ENDPOINTS.faculties}/${id}`).pipe(
tap((res) => {
this.refreshNeeded.next();
return res;
})
Expand Down
34 changes: 18 additions & 16 deletions uniplanWeb/src/app/features/major/major-service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { HttpClient } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';
import { map, Observable, Subject, switchMap } from 'rxjs';
import { map, Observable, Subject, switchMap, tap } from 'rxjs';
import { MajorElm } from '../../core/interfaces/major-elm';
import {API_ENDPOINTS} from '../../config/endpoints';
import { CourseElm } from '../../core/interfaces/course-elm';

@Injectable({
providedIn: 'root',
Expand Down Expand Up @@ -31,8 +32,8 @@ export class MajorService {
createMajor(createMajor: {
facultyId: string;
majorName: string;
}): Observable<any> {
return this.http.post(`${API_ENDPOINTS.majors}`, createMajor).pipe(
}): Observable<MajorElm> {
return this.http.post<MajorElm>(`${API_ENDPOINTS.majors}`, createMajor).pipe(
map((res) => {
this.refreshNeeded.next();
return res;
Expand All @@ -45,25 +46,26 @@ export class MajorService {
courseYear: number;
courseType: string;
courseSubtype: string;
}): Observable<any> {
return this.http.post(`${API_ENDPOINTS.courses}`, course).pipe(
}): Observable<CourseElm> {
return this.http.post<CourseElm>(`${API_ENDPOINTS.courses}`, course).pipe(
map((res) => {
this.refreshNeeded.next();
return res;
})
);
}

createMajorWithCourse(majorData: {
facultyId: string;
majorName: string;
type: string;
subtype: string;
}): Observable<any> {
}): Observable<CourseElm> {
return this.createMajor({
facultyId: majorData.facultyId,
majorName: majorData.majorName,
}).pipe(
switchMap((createdMajor: any) => {
switchMap((createdMajor) => {
return this.createCourse({
majorId: createdMajor.id,
courseType: majorData.type,
Expand All @@ -74,20 +76,20 @@ export class MajorService {
);
}

deleteMajor(id: string): Observable<any> {
return this.http.delete(`${API_ENDPOINTS.majors}/${id}`).pipe(
map((res) => {
deleteMajor(id: string): Observable<void> {
return this.http.delete<void>(`${API_ENDPOINTS.majors}/${id}`).pipe(
tap((res) => {
this.refreshNeeded.next();
return res;
})
);
}

deleteCourse(courseId: string): Observable<any> {
return this.http.delete(`${API_ENDPOINTS.courses}/${courseId}`);
deleteCourse(courseId: string): Observable<void> {
return this.http.delete<void>(`${API_ENDPOINTS.courses}/${courseId}`);
}

deleteMajorWithCourse(major: MajorElm): Observable<any> {
deleteMajorWithCourse(major: MajorElm): Observable<void> {
return this.deleteCourse(major.courseId).pipe(
switchMap(() => this.deleteMajor(major.id))
);
Expand All @@ -96,9 +98,9 @@ export class MajorService {
editMajor(
id: string,
updateMajor: { facultyId: string; majorName: string }
): Observable<any> {
return this.http.put(`${API_ENDPOINTS.majors}/${id}`, updateMajor).pipe(
map((res) => {
): Observable<MajorElm> {
return this.http.put<MajorElm>(`${API_ENDPOINTS.majors}/${id}`, updateMajor).pipe(
tap((res) => {
this.refreshNeeded.next();
return res;
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<app-add-form [title]="'major.add.title' | translate" (saveClicked)="save()">
<form [formGroup]="addForm">
<mat-form-field appearance="fill">
<mat-label>{{ 'room.room-number' | translate }}</mat-label>
<input matInput id="room-number" type="text" formControlName="roomNumber" />
</mat-form-field>

<mat-form-field appearance="fill">
<mat-label>{{ 'features.faculty-label' | translate }}</mat-label>
<mat-select formControlName="facultyId">
@for (faculty of faculties; track faculty.id) {
<mat-option [value]="faculty.id">
{{ faculty.facultyName }}
</mat-option>
}
</mat-select>
</mat-form-field>
</form>
</app-add-form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
mat-form-field {
width: 100%;
}

mat-dialog-title {
font-size: 20px;
font-weight: bold;
color: #3f51b5;
}

input {
border-radius: 10px;
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RoomAddForm } from './room-add-form';
import { translateTestingProviders } from '@testing/translate-testing';
import { MatDialogRef } from '@angular/material/dialog';

describe('RoomAddForm', () => {
let component: RoomAddForm;
let fixture: ComponentFixture<RoomAddForm>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [RoomAddForm],
providers: [
...translateTestingProviders,
{ provide: MatDialogRef, useValue: {} },
]
})
.compileComponents();

fixture = TestBed.createComponent(RoomAddForm);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
103 changes: 103 additions & 0 deletions uniplanWeb/src/app/features/room/room-add-form/room-add-form.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { Component, OnInit, ChangeDetectionStrategy, inject, DestroyRef } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Validators, FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { MatFormField, MatLabel } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { MatOptionModule } from '@angular/material/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
import { finalize } from 'rxjs';
import { AddForm } from '../../../core/shared/add-form/add-form';
import { FacultyService } from '../../faculty/faculty-service';
import { FacultyElm } from '../../../core/interfaces/faculty-elm';
import { RoomService } from '../room-service';

@Component({
selector: 'app-room-add-form',
templateUrl: './room-add-form.html',
styleUrl: './room-add-form.scss',
changeDetection: ChangeDetectionStrategy.Eager,
Comment thread
PIPetkova19 marked this conversation as resolved.
imports: [
MatDialogModule,
MatFormField,
MatLabel,
MatInputModule,
MatSelectModule,
MatOptionModule,
AddForm,
TranslatePipe,
ReactiveFormsModule
],
})

export class RoomAddForm implements OnInit {
private dialogRef = inject(MatDialogRef<AddForm>);
private facultyService = inject(FacultyService);
private roomService = inject(RoomService)
faculties: FacultyElm[] = [];
private destroyRef = inject(DestroyRef);
private translate = inject(TranslateService);
private isSubmitting = false;
private _snackBar = inject(MatSnackBar);

addForm = new FormGroup({
Comment thread
PIPetkova19 marked this conversation as resolved.
roomNumber: new FormControl<string | null>('', Validators.required),
facultyId: new FormControl<string | null>('', Validators.required),
});

ngOnInit(): void {
this.facultyService.getFaculties()
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({
next: (data) => {
this.faculties = data;
},
error: (err) => {
console.error('Failed to load faculties', err);
Comment thread
PIPetkova19 marked this conversation as resolved.
this.openSnackBar(
this.translate.instant('faculty.load.failed'),
this.translate.instant('shared.close-btn')
);
},
});
}

openSnackBar(message: string, action: string): void {
this._snackBar.open(message, action);
}

save(): void {
if (this.addForm.invalid || this.isSubmitting) {
return;
}

this.isSubmitting = true;
this.addForm.disable();

const newRoom = {
roomNumber: this.addForm.value.roomNumber ?? '',
facultyId: this.addForm.value.facultyId ?? '',
};

this.roomService.createRoom(newRoom)
.pipe(takeUntilDestroyed(this.destroyRef),
finalize(() => {
this.isSubmitting = false;
this.addForm.enable();
}))
.subscribe({
next: (response) => {
this.dialogRef.close(response);
},
error: (err) => {
console.error('Failed to add room', err);
this.openSnackBar(
this.translate.instant('room.add.failed'),
this.translate.instant('shared.close-btn')
);
},
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<app-add-button (addClicked)="openAddForm()" class="add-button"></app-add-button>
Loading