fix betreft afspraken
All checks were successful
Docker Image CI / build-and-push (push) Successful in 1m4s
Docker Image CI / deploy (push) Successful in 30s
Docker Image CI / notify-failure (push) Has been skipped

This commit is contained in:
2025-04-18 23:30:16 +02:00
parent 781723fddf
commit 524aa879de
9 changed files with 50 additions and 33 deletions

View File

@@ -1,5 +1,4 @@
import {Component, EventEmitter, inject, Input, OnInit, Output} from '@angular/core'; import {Component, EventEmitter, inject, Input, OnInit, Output} from '@angular/core';
import {Appointment} from '../../models/appointment';
import {DateFormatter} from '../../utils/date-formatter'; import {DateFormatter} from '../../utils/date-formatter';
import {TuiAlertService, TuiButton, TuiGroup, TuiIcon} from '@taiga-ui/core'; import {TuiAlertService, TuiButton, TuiGroup, TuiIcon} from '@taiga-ui/core';
import {TuiTextareaModule} from '@taiga-ui/legacy'; import {TuiTextareaModule} from '@taiga-ui/legacy';
@@ -8,6 +7,7 @@ import {NgIf} from '@angular/common';
import {ModalComponent} from '../modal/modal.component'; import {ModalComponent} from '../modal/modal.component';
import {EditItemComponent} from '../edit-item/edit-item.component'; import {EditItemComponent} from '../edit-item/edit-item.component';
import {AppointmentService} from '../../services/appointment.service'; import {AppointmentService} from '../../services/appointment.service';
import {AppointmentDto} from '../../models/appointment-dto';
@Component({ @Component({
selector: 'app-details', selector: 'app-details',
@@ -36,9 +36,9 @@ export class DetailsComponent implements OnInit {
constructor(private appointmentService: AppointmentService) { constructor(private appointmentService: AppointmentService) {
} }
@Input() appointment: Appointment; @Input() appointment: AppointmentDto;
@Output() appointmentDeleted = new EventEmitter<Appointment>(); @Output() appointmentDeleted = new EventEmitter<AppointmentDto>();
@Output() appointmentEdited = new EventEmitter<Appointment>(); @Output() appointmentEdited = new EventEmitter<AppointmentDto>();
open: boolean = true; open: boolean = true;
readonly = true; readonly = true;
showDeleteModal = false; showDeleteModal = false;
@@ -66,7 +66,7 @@ export class DetailsComponent implements OnInit {
updateAppointment($event: any) { updateAppointment($event: any) {
this.showEditModal = false; this.showEditModal = false;
this.appointmentService.getAppointment($event).subscribe((appointment: Appointment) => { this.appointmentService.getAppointment($event).subscribe((appointment: AppointmentDto) => {
this.appointment = appointment this.appointment = appointment
this.appointmentEdited.emit(this.appointment); this.appointmentEdited.emit(this.appointment);
}) })

View File

@@ -10,7 +10,6 @@ import {
TuiTextareaModule, TuiTextareaModule,
TuiTextfieldControllerModule TuiTextfieldControllerModule
} from "@taiga-ui/legacy"; } from "@taiga-ui/legacy";
import {Appointment} from '../../models/appointment';
import {TuiDay, TuiTime} from '@taiga-ui/cdk'; import {TuiDay, TuiTime} from '@taiga-ui/cdk';
import {AppointmentService} from '../../services/appointment.service'; import {AppointmentService} from '../../services/appointment.service';
import {TuiDataListWrapperComponent, TuiFilterByInputPipe, TuiStringifyContentPipe} from '@taiga-ui/kit'; import {TuiDataListWrapperComponent, TuiFilterByInputPipe, TuiStringifyContentPipe} from '@taiga-ui/kit';
@@ -18,6 +17,7 @@ import {Customer} from '../../models/customer';
import {CustomerService} from '../../services/customer.service'; import {CustomerService} from '../../services/customer.service';
import {ModalComponent} from '../modal/modal.component'; import {ModalComponent} from '../modal/modal.component';
import {NewCustomerComponent} from '../new-customer/new-customer.component'; import {NewCustomerComponent} from '../new-customer/new-customer.component';
import {AppointmentDto} from '../../models/appointment-dto';
@Component({ @Component({
selector: 'app-edit-item', selector: 'app-edit-item',
@@ -44,7 +44,7 @@ import {NewCustomerComponent} from '../new-customer/new-customer.component';
}) })
export class EditItemComponent implements OnInit { export class EditItemComponent implements OnInit {
@Input() appointment: Appointment; @Input() appointment: AppointmentDto;
testForm: FormGroup; testForm: FormGroup;
quickActions = ['Knippen', 'Kleuren', 'Knippen + Kleuren'] quickActions = ['Knippen', 'Kleuren', 'Knippen + Kleuren']
waiting: boolean = false; waiting: boolean = false;

View File

@@ -19,6 +19,8 @@ import {CustomerService} from '../../services/customer.service';
import {ModalComponent} from '../modal/modal.component'; import {ModalComponent} from '../modal/modal.component';
import {timeAfterStartValidator} from '../../models/validators/time-after-start-validator'; import {timeAfterStartValidator} from '../../models/validators/time-after-start-validator';
import {NewCustomerComponent} from '../new-customer/new-customer.component'; import {NewCustomerComponent} from '../new-customer/new-customer.component';
import {UserService} from '../../services/user.service';
import {AppointmentDto} from '../../models/appointment-dto';
@Component({ @Component({
selector: 'app-new-item', selector: 'app-new-item',
@@ -48,7 +50,7 @@ import {NewCustomerComponent} from '../new-customer/new-customer.component';
export class NewItemComponent implements OnInit { export class NewItemComponent implements OnInit {
@Input() appointmentForm: FormGroup; @Input() appointmentForm: FormGroup;
@Input() appointments: Appointment[]; @Input() appointments: AppointmentDto[];
quickActions = ['Knippen', 'Kleuren', 'Knippen + Kleuren'] quickActions = ['Knippen', 'Kleuren', 'Knippen + Kleuren']
waiting: boolean = false; waiting: boolean = false;
protected value: TuiDay | null = null; protected value: TuiDay | null = null;
@@ -59,7 +61,7 @@ export class NewItemComponent implements OnInit {
timeError = new TuiValidationError('Begintijd moet voor de eindtijd liggen.'); timeError = new TuiValidationError('Begintijd moet voor de eindtijd liggen.');
constructor(private appointmentService: AppointmentService, private customerService: CustomerService) { constructor(private appointmentService: AppointmentService, private customerService: CustomerService, private userService: UserService,) {
} }
ngOnInit(): void { ngOnInit(): void {
@@ -89,7 +91,7 @@ export class NewItemComponent implements OnInit {
const appointment = new Appointment(title, description, startTime.hours, startTime.minutes, endTime.hours, endTime.minutes, correctDate, customer) const appointment = new Appointment(title, description, startTime.hours, startTime.minutes, endTime.hours, endTime.minutes, correctDate, customer)
this.waiting = true this.waiting = true
this.appointmentService.addAppointment(appointment).subscribe(() => { this.appointmentService.addAppointment(appointment, this.userService.currentCompany.id).subscribe(() => {
this.waiting = false this.waiting = false
this.appointmentAddedEvent.emit(title) this.appointmentAddedEvent.emit(title)
}) })

View File

@@ -0,0 +1,16 @@
import {Customer} from './customer';
import {CompanyDTO} from './app-user-dto';
export class AppointmentDto {
id: number;
title: string;
description: string;
startDate: Date; // ISO 8601 string (LocalDateTime in Java)
startHour: number;
startMinute: number;
endHour: number;
endMinute: number;
durationInMinutes: number;
customer: Customer;
company: CompanyDTO;
}

View File

@@ -1,7 +1,6 @@
import {Component, inject, OnInit} from '@angular/core'; import {Component, inject, OnInit} from '@angular/core';
import {CommonModule, NgFor, NgIf} from '@angular/common'; import {CommonModule, NgFor, NgIf} from '@angular/common';
import {TuiAlertService, TuiButton, TuiCalendar, tuiDateFormatProvider, TuiIcon} from '@taiga-ui/core'; import {TuiAlertService, TuiButton, TuiCalendar, tuiDateFormatProvider, TuiIcon} from '@taiga-ui/core';
import {Appointment} from '../../models/appointment';
import {ModalComponent} from '../../components/modal/modal.component'; import {ModalComponent} from '../../components/modal/modal.component';
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms'; import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
import { import {
@@ -19,6 +18,7 @@ import {WeekDay} from '../../models/week-day';
import {NewItemComponent} from '../../components/new-item/new-item.component'; import {NewItemComponent} from '../../components/new-item/new-item.component';
import {timeAfterStartValidator} from '../../models/validators/time-after-start-validator'; import {timeAfterStartValidator} from '../../models/validators/time-after-start-validator';
import {DropdownContentComponent} from '../../components/dropdown-content/dropdown-content.component'; import {DropdownContentComponent} from '../../components/dropdown-content/dropdown-content.component';
import {AppointmentDto} from '../../models/appointment-dto';
@Component({ @Component({
selector: 'app-agenda', selector: 'app-agenda',
@@ -40,12 +40,12 @@ export class AgendaComponent implements OnInit {
} }
timeSlots: number[] = Array.from({length: 24}, (_, i) => i); // 24 uren timeSlots: number[] = Array.from({length: 24}, (_, i) => i); // 24 uren
appointments: Appointment[] = []; appointments: AppointmentDto[] = [];
showNewItem = false showNewItem = false
today = new Date() today = new Date()
selectedDate = new Date() selectedDate = new Date()
waiting: boolean = false; waiting: boolean = false;
selectedAppointment: Appointment; selectedAppointment: AppointmentDto;
protected value: TuiDay | null = null; protected value: TuiDay | null = null;
showCalendar: boolean = false; showCalendar: boolean = false;
open = false open = false
@@ -151,7 +151,7 @@ export class AgendaComponent implements OnInit {
}) })
} }
getInlineStyles(appointment: Appointment): { [key: string]: string } { getInlineStyles(appointment: AppointmentDto): { [key: string]: string } {
return { return {
'--duration': `${appointment.durationInMinutes}`, '--duration': `${appointment.durationInMinutes}`,
'--start-minute': `${appointment.startMinute}`, '--start-minute': `${appointment.startMinute}`,
@@ -164,13 +164,13 @@ export class AgendaComponent implements OnInit {
return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`; return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
} }
getAppointmentHeight(appointment: Appointment): number { getAppointmentHeight(appointment: AppointmentDto): number {
const startInMinutes = (appointment.startHour * 60) + appointment.startMinute; const startInMinutes = (appointment.startHour * 60) + appointment.startMinute;
const endInMinutes = (appointment.endHour * 60) + appointment.endMinute; const endInMinutes = (appointment.endHour * 60) + appointment.endMinute;
return (endInMinutes - startInMinutes); // 50px per uur return (endInMinutes - startInMinutes); // 50px per uur
} }
selectAppointment(appointment: Appointment) { selectAppointment(appointment: AppointmentDto) {
this.selectedAppointment = appointment; this.selectedAppointment = appointment;
} }
@@ -193,7 +193,7 @@ export class AgendaComponent implements OnInit {
this.resetForms() this.resetForms()
} }
appointmentIsDeleted(appointment: Appointment) { appointmentIsDeleted(appointment: AppointmentDto) {
this.selectedAppointment = undefined; this.selectedAppointment = undefined;
this.alerts this.alerts
.open(`Afspraak <strong>${appointment.title}</strong> is verwijderd.`) .open(`Afspraak <strong>${appointment.title}</strong> is verwijderd.`)
@@ -201,7 +201,7 @@ export class AgendaComponent implements OnInit {
this.getAppointmentsByDate(this.selectedDate); this.getAppointmentsByDate(this.selectedDate);
} }
appointmentIsEdited($event: Appointment) { appointmentIsEdited($event: AppointmentDto) {
this.getAppointmentsByDate(this.selectedDate); this.getAppointmentsByDate(this.selectedDate);
} }

View File

@@ -28,7 +28,7 @@
<ng-template #dropdownContent> <ng-template #dropdownContent>
<div class="dropdown"> <div class="dropdown">
<h3>{{ fullName }}</h3> <h3>{{ fullName }}</h3>
<h4>{{ currentCompany.name }}</h4> <h4>{{ userService.currentCompany.name }}</h4>
<button <button
size="m" size="m"

View File

@@ -6,7 +6,6 @@ import {AuthService} from '../../services/auth.service';
import {TuiButton, TuiDropdown} from '@taiga-ui/core'; import {TuiButton, TuiDropdown} from '@taiga-ui/core';
import {TuiActiveZone, TuiObscured} from '@taiga-ui/cdk'; import {TuiActiveZone, TuiObscured} from '@taiga-ui/cdk';
import {environment} from '../../../environments/environment'; import {environment} from '../../../environments/environment';
import {Company} from '../../models/company';
import {TuiSelectModule} from '@taiga-ui/legacy'; import {TuiSelectModule} from '@taiga-ui/legacy';
import {UserService} from '../../services/user.service'; import {UserService} from '../../services/user.service';
import {AppUserDto, CompanyDTO} from '../../models/app-user-dto'; import {AppUserDto, CompanyDTO} from '../../models/app-user-dto';
@@ -21,7 +20,6 @@ export class HomeComponent implements OnInit {
user: AppUserDto; user: AppUserDto;
fullName: string fullName: string
companies: CompanyDTO[]; companies: CompanyDTO[];
currentCompany: CompanyDTO;
getInitials(): string { getInitials(): string {
this.user = this.userService.userValue this.user = this.userService.userValue
@@ -45,7 +43,7 @@ export class HomeComponent implements OnInit {
this.open = active && this.open; this.open = active && this.open;
} }
constructor(private authService: AuthService, private router: Router, private userService: UserService) { constructor(private authService: AuthService, private router: Router, protected userService: UserService) {
} }
ngOnInit(): void { ngOnInit(): void {
@@ -53,7 +51,7 @@ export class HomeComponent implements OnInit {
this.router.navigate(['login']); this.router.navigate(['login']);
} else { } else {
this.companies = this.userService.userValue.companies.map(a => a.company) this.companies = this.userService.userValue.companies.map(a => a.company)
this.currentCompany = this.companies[0]; this.userService.currentCompany = this.companies[0];
} }
} }

View File

@@ -3,6 +3,7 @@ import {HttpClient} from '@angular/common/http';
import {Appointment} from '../models/appointment'; import {Appointment} from '../models/appointment';
import {environment} from '../../environments/environment'; import {environment} from '../../environments/environment';
import {AuthService} from './auth.service'; import {AuthService} from './auth.service';
import {AppointmentDto} from '../models/appointment-dto';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
@@ -10,7 +11,7 @@ import {AuthService} from './auth.service';
export class AppointmentService { export class AppointmentService {
baseApi = `${environment.baseApi}/appointments`; baseApi = `${environment.baseApi}/appointments`;
constructor(private http: HttpClient, private authService: AuthService) { constructor(private http: HttpClient) {
} }
getAllAppointments() { getAllAppointments() {
@@ -21,24 +22,23 @@ export class AppointmentService {
const day = date.getDate().toString().padStart(2, '0') const day = date.getDate().toString().padStart(2, '0')
const month = (date.getMonth() + 1).toString().padStart(2, '0') const month = (date.getMonth() + 1).toString().padStart(2, '0')
const year = date.getFullYear(); const year = date.getFullYear();
return this.http.get<Appointment[]>(`${this.baseApi}/date?start=${year}-${month}-${day}`, {}); return this.http.get<AppointmentDto[]>(`${this.baseApi}/date?start=${year}-${month}-${day}`, {});
} }
addAppointment(appointment: Appointment) { addAppointment(appointment: Appointment, companyId: number) {
let companyId = this.authService.getCurrentCompany().id return this.http.post<AppointmentDto>(`${this.baseApi}/${companyId}`, appointment);
return this.http.post(`${this.baseApi}/${companyId}`, appointment);
} }
deleteAppointment(appointment: Appointment) { deleteAppointment(appointment: AppointmentDto) {
return this.http.delete(`${this.baseApi}?id=${appointment.id}`) return this.http.delete(`${this.baseApi}?id=${appointment.id}`)
} }
updateAppointment(appointment: Appointment) { updateAppointment(appointment: AppointmentDto) {
return this.http.put(`${this.baseApi}`, appointment); return this.http.put<AppointmentDto>(`${this.baseApi}`, appointment);
} }
getAppointment(id: string) { getAppointment(id: string) {
return this.http.get(`${this.baseApi}/${id}`); return this.http.get<AppointmentDto>(`${this.baseApi}/${id}`);
} }
getMostRecentAppointment(id: number) { getMostRecentAppointment(id: number) {

View File

@@ -1,12 +1,13 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject, Observable } from 'rxjs';
import {AppUserDto} from '../models/app-user-dto'; import {AppUserDto, CompanyDTO} from '../models/app-user-dto';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class UserService { export class UserService {
private userSubject = new BehaviorSubject<AppUserDto | null>(null); private userSubject = new BehaviorSubject<AppUserDto | null>(null);
currentCompany: CompanyDTO
get user$(): Observable<AppUserDto | null> { get user$(): Observable<AppUserDto | null> {
return this.userSubject.asObservable(); return this.userSubject.asObservable();