From d86af94ac8170fbadf2881d268a478071ba82c21 Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Wed, 15 Jan 2025 11:02:12 +0100 Subject: [PATCH] feat: add employee management and skill handling features --- src/app/app.config.ts | 34 +++---- src/app/app.routes.ts | 3 +- ...mitarbeiter-bearbeiten-view.component.html | 2 +- .../mitarbeiter-bearbeiten-view.component.ts | 22 +++++ .../mitarbeiter-form.component.html | 95 ++++++++++--------- .../mitarbeiter-form.component.ts | 64 ++++++++++++- src/app/models/mitarbeiter.ts | 47 +++++++++ src/app/models/skill.ts | 12 +++ src/app/service/employee.service.ts | 43 +++++++++ src/app/service/skill.service.ts | 20 ++++ 10 files changed, 277 insertions(+), 65 deletions(-) create mode 100644 src/app/models/mitarbeiter.ts create mode 100644 src/app/models/skill.ts create mode 100644 src/app/service/employee.service.ts create mode 100644 src/app/service/skill.service.ts diff --git a/src/app/app.config.ts b/src/app/app.config.ts index b047b4b..bd19328 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -2,7 +2,7 @@ import { APP_INITIALIZER, ApplicationConfig, provideZoneChangeDetection } from ' import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; -import {KeycloakAngularModule, KeycloakBearerInterceptor, KeycloakService} from "keycloak-angular"; +import { KeycloakAngularModule, KeycloakBearerInterceptor, KeycloakService } from "keycloak-angular"; import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; export const initializeKeycloak = (keycloak: KeycloakService) => async () => @@ -28,20 +28,20 @@ function initializeApp(keycloak: KeycloakService): () => Promise { export const appConfig: ApplicationConfig = { providers: [ - provideRouter(routes), - KeycloakAngularModule, - { - provide: APP_INITIALIZER, - useFactory: initializeApp, - multi: true, - deps: [KeycloakService] - }, - KeycloakService, - provideHttpClient(withInterceptorsFromDi()), - { - provide: HTTP_INTERCEPTORS, - useClass: KeycloakBearerInterceptor, - multi: true - } - ] + provideRouter(routes), + KeycloakAngularModule, + { + provide: APP_INITIALIZER, + useFactory: initializeApp, + multi: true, + deps: [KeycloakService] + }, + KeycloakService, + provideHttpClient(withInterceptorsFromDi()), + { + provide: HTTP_INTERCEPTORS, + useClass: KeycloakBearerInterceptor, + multi: true + } + ] }; diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 0ed7af5..93c626a 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -19,7 +19,8 @@ export const routes: Routes = [ }, { path: "mitarbeiterbearbeiten/:id", - component: MitarbeiterBearbeitenViewComponent + component: MitarbeiterBearbeitenViewComponent, + canActivate: [AuthGuard], }, { path: "mitarbeiterdetails", diff --git a/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.html b/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.html index fccd9f7..0d53245 100644 --- a/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.html +++ b/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.html @@ -1 +1 @@ - + diff --git a/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.ts b/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.ts index 2f3c3c5..a07c020 100644 --- a/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.ts +++ b/src/app/components/mitarbeiter-bearbeiten-view/mitarbeiter-bearbeiten-view.component.ts @@ -1,5 +1,8 @@ import { Component } from '@angular/core'; import { MitarbeiterFormComponent } from '../mitarbeiter-form/mitarbeiter-form.component'; +import { EmployeeResponseDTO } from '../../models/mitarbeiter'; +import { EmployeeService } from '../../service/employee.service'; +import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-mitarbeiter-bearbeiten-view', @@ -9,5 +12,24 @@ import { MitarbeiterFormComponent } from '../mitarbeiter-form/mitarbeiter-form.c styleUrl: './mitarbeiter-bearbeiten-view.component.css' }) export class MitarbeiterBearbeitenViewComponent { + public mitarbeiter!: EmployeeResponseDTO; + constructor(private employeeService: EmployeeService, private route: ActivatedRoute) { } + + ngOnInit(): void { + this.mitarbeiter = { + id: 0, + firstName: '', + lastName: '', + street: '', + phone: '', + skillSet: [], + postcode: '', + city: '', + } + this.employeeService.getEmployeeById(this.route.snapshot.params['id']).subscribe(employee => { + this.mitarbeiter = employee; + console.log(this.mitarbeiter); + }); + } } diff --git a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.html b/src/app/components/mitarbeiter-form/mitarbeiter-form.component.html index 4bc03b5..2dae44f 100644 --- a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.html +++ b/src/app/components/mitarbeiter-form/mitarbeiter-form.component.html @@ -1,49 +1,56 @@ -
- - +
-
-

Skills

-
    -
  • - Skill 1 - + + +
    +

    Skills

    +
      + @for (skill of mitarbeiter.skillSet; track skill) { +
    • + {{skill.skill}} + -
    • -
    -
    - - +
  • + } +
+
+ + +
+
- - + + diff --git a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.ts b/src/app/components/mitarbeiter-form/mitarbeiter-form.component.ts index 59b5c0f..c242ba6 100644 --- a/src/app/components/mitarbeiter-form/mitarbeiter-form.component.ts +++ b/src/app/components/mitarbeiter-form/mitarbeiter-form.component.ts @@ -1,12 +1,72 @@ -import { Component } from '@angular/core'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { EmployeeNameAndSkillDataDTO, EmployeeRequestPutDTO, EmployeeResponseDTO } from '../../models/mitarbeiter'; +import { AbstractControl, FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; +import { HttpClient } from '@angular/common/http'; +import { Router } from '@angular/router'; +import { AsyncPipe, NgFor } from '@angular/common'; +import { SkillService } from '../../service/skill.service'; +import { QualificationGetDTO } from '../../models/skill'; +import { Observable, of } from 'rxjs'; +import { EmployeeService } from '../../service/employee.service'; @Component({ selector: 'app-mitarbeiter-form', standalone: true, - imports: [MitarbeiterFormComponent], + imports: [MitarbeiterFormComponent, ReactiveFormsModule, NgFor, AsyncPipe], templateUrl: './mitarbeiter-form.component.html', styleUrl: './mitarbeiter-form.component.css' }) export class MitarbeiterFormComponent { + @Input() mitarbeiter!: EmployeeResponseDTO; + @Output() mitarbeiterChange = new EventEmitter(); + public mitarbeiterForm!: FormGroup; + public allSkills: Observable> = of([]); + + constructor(public http: HttpClient, public router: Router, private employeeService: EmployeeService, private skillService: SkillService) { + + } + + private setupForm() { + this.mitarbeiterForm = new FormGroup({ + lastName: new FormControl(this.mitarbeiter.lastName), + firstName: new FormControl(this.mitarbeiter.firstName), + street: new FormControl(this.mitarbeiter.street), + postcode: new FormControl(this.mitarbeiter.postcode), + city: new FormControl(this.mitarbeiter.city), + phone: new FormControl(this.mitarbeiter.phone), + newSkill: new FormControl(), + }); + } + + ngOnChanges(): void { + this.setupForm(); + } + + ngOnInit(): void { + this.allSkills = this.skillService.getAllSkills(); + this.setupForm(); + } + + removeSkill(id?: number) { + this.mitarbeiter.skillSet = this.mitarbeiter.skillSet?.filter(skill => skill.id !== id); + } + + addSkill() { + const id = Number(this.mitarbeiterForm.get("newSkill")?.value); + this.employeeService.addSkillToEmployee(id, this.mitarbeiter); + } + + submit() { + this.mitarbeiter.firstName = this.mitarbeiterForm.get("firstName")?.value; + this.mitarbeiter.lastName = this.mitarbeiterForm.get("lastName")?.value; + this.mitarbeiter.street = this.mitarbeiterForm.get("street")?.value; + this.mitarbeiter.postcode = this.mitarbeiterForm.get("postcode")?.value; + this.mitarbeiter.city = this.mitarbeiterForm.get("city")?.value; + this.mitarbeiter.phone = this.mitarbeiterForm.get("phone")?.value; + + console.log(this.mitarbeiterForm); + console.log(this.mitarbeiter); + this.mitarbeiterChange.emit(this.mitarbeiter); + } } diff --git a/src/app/models/mitarbeiter.ts b/src/app/models/mitarbeiter.ts new file mode 100644 index 0000000..9b67f85 --- /dev/null +++ b/src/app/models/mitarbeiter.ts @@ -0,0 +1,47 @@ +import { QualificationGetDTO, QualificationPostDTO } from "./skill"; + +export interface EmployeeRequestPutDTO { + lastName: string, + firstName: string, + street: string, + postcode: string, + city: string, + phone: string, + skillSet: Array, +} + +export interface EmployeeResponseDTO { + id: number, + lastName: string, + firstName: string, + street: string, + postcode: string, + city: string, + phone: string, + skillSet?: Array, +} + +export interface EmployeeRequestDTO { + lastName: string, + firstName: string, + street: string, + postcode: string, + city: string, + phone: string, + skillSet?: Array, +} + +export interface EmployeeNameAndSkillDataDTO { + id: number, + lastName: string, + firstName: string, + skillSet: Array, +} + +export interface EmployeeNameDataDTO { + id: number, + lastName: string, + firstName: string, +} + + diff --git a/src/app/models/skill.ts b/src/app/models/skill.ts new file mode 100644 index 0000000..b3db681 --- /dev/null +++ b/src/app/models/skill.ts @@ -0,0 +1,12 @@ +export interface QualificationGetDTO { + id: number, + skill: string, +} + +export interface QualificationPostDTO { + skill: string, +} + +export interface EmployeesForAQualificationDTO { + qualification: QualificationGetDTO, +} diff --git a/src/app/service/employee.service.ts b/src/app/service/employee.service.ts new file mode 100644 index 0000000..3afb443 --- /dev/null +++ b/src/app/service/employee.service.ts @@ -0,0 +1,43 @@ +import { Injectable } from "@angular/core"; +import { EmployeeRequestPutDTO, EmployeeResponseDTO } from "../models/mitarbeiter"; +import { HttpClient } from "@angular/common/http"; +import { Observable } from "rxjs"; +import { SkillService } from "./skill.service"; + +@Injectable({ + providedIn: 'root' +}) +export class EmployeeService { + constructor(private http: HttpClient) {} + + + responseDtoToPutDto(employee: EmployeeResponseDTO): EmployeeRequestPutDTO { + return { + firstName: employee.firstName, + lastName: employee.lastName, + street: employee.street, + postcode: employee.postcode, + city: employee.city, + phone: employee.phone, + skillSet: employee.skillSet?.map(skill => skill.id) || [], + } + } + + + getAllEmployees(): Observable> { + return this.http.get>(`${SkillService.BASE_URL}/employees`); + } + + + getEmployeeById(id: number): Observable { + return this.http.get(`${SkillService.BASE_URL}/employees/${id}`); + } + + + addSkillToEmployee(skillId: number, employee: EmployeeResponseDTO) { + let employeePut = this.responseDtoToPutDto(employee); + employeePut.skillSet.push(skillId); + + this.http.put(`${SkillService.BASE_URL}/employees/${employee.id}`, employeePut).subscribe(); + } +} diff --git a/src/app/service/skill.service.ts b/src/app/service/skill.service.ts new file mode 100644 index 0000000..9f6764b --- /dev/null +++ b/src/app/service/skill.service.ts @@ -0,0 +1,20 @@ +import { HttpClient } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { QualificationGetDTO } from "../models/skill"; +import { Observable } from "rxjs"; + +@Injectable({ + providedIn: 'root' +}) +export class SkillService { + + public static readonly BASE_URL = "http://localhost:8089"; + + constructor(private http: HttpClient) { + + } + + getAllSkills(): Observable> { + return this.http.get>(`${SkillService.BASE_URL}/qualifications`); + } +}