Compare commits
2 Commits
cb3243e524
...
eed9e30fd3
| Author | SHA1 | Date | |
|---|---|---|---|
| eed9e30fd3 | |||
| c3663e4c6e |
@@ -58,7 +58,6 @@ export class EditItemComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
console.log(this.appointment);
|
||||
let date = new Date(this.appointment.startDate);
|
||||
this.testForm = new FormGroup({
|
||||
title: new FormControl(this.appointment.title, Validators.required),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<form [formGroup]="testForm">
|
||||
<form [formGroup]="appointmentForm">
|
||||
<tui-input formControlName="title">
|
||||
Titel
|
||||
<input
|
||||
@@ -8,7 +8,7 @@
|
||||
/>
|
||||
</tui-input>
|
||||
<div
|
||||
*ngIf="testForm.get('title').value == ''"
|
||||
*ngIf="appointmentForm.get('title').value == ''"
|
||||
tuiGroup
|
||||
class="group"
|
||||
[collapsed]="true">
|
||||
@@ -25,7 +25,7 @@
|
||||
<br>
|
||||
<div class="toolbar">
|
||||
<tui-combo-box
|
||||
[formControl]="control"
|
||||
[formControl]="customerControl"
|
||||
[stringify]="stringify"
|
||||
tuiTextfieldSize="m">
|
||||
Klant
|
||||
@@ -43,18 +43,17 @@
|
||||
type="button">
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<div
|
||||
tuiGroup
|
||||
class="group"
|
||||
>
|
||||
class="group">
|
||||
<div>
|
||||
<tui-input-date
|
||||
formControlName="date"
|
||||
tuiTextfieldSize="m"
|
||||
class="tui-space_vertical-4"
|
||||
[tuiTextfieldLabelOutside]="false"
|
||||
>
|
||||
[tuiTextfieldLabelOutside]="false">
|
||||
Datum
|
||||
</tui-input-date>
|
||||
</div>
|
||||
@@ -72,12 +71,38 @@
|
||||
formControlName="endTime"
|
||||
tuiTextfieldSize="m"
|
||||
class="tui-space_top-2"
|
||||
[tuiTextfieldLabelOutside]="false"
|
||||
>
|
||||
[tuiTextfieldLabelOutside]="false">
|
||||
Tot
|
||||
</tui-input-time>
|
||||
</div>
|
||||
</div>
|
||||
<span *ngIf="appointmentForm.get('endTime')?.errors?.['endTimeInvalid']">
|
||||
<tui-error [error]="timeError"/>
|
||||
</span>
|
||||
<br>
|
||||
<ng-container *ngIf="appointments.length > 0">
|
||||
<h3>Geplande afspraken die dag:</h3>
|
||||
<div class="appointments-container">
|
||||
<div *ngFor="let appointment of appointments" class="appointment-object">
|
||||
<span class="title">{{ appointment.title }}</span>
|
||||
<span class="name">
|
||||
<tui-icon
|
||||
icon="@tui.user"
|
||||
[style.font-size.rem]="1"
|
||||
[style.color]="'var(--tui-background-accent-1)'"/>
|
||||
{{ appointment.customer.firstName }} {{ appointment.customer.lastName }}</span>
|
||||
<span class="time">
|
||||
<tui-icon
|
||||
icon="@tui.clock"
|
||||
[style.font-size.rem]="1"
|
||||
[style.color]="'var(--tui-background-accent-1)'"/>
|
||||
{{ getFormattedTime(appointment.startHour, appointment.startMinute) }} -
|
||||
{{ getFormattedTime(appointment.endHour, appointment.endMinute) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<br>
|
||||
<tui-textarea formControlName="notes">Notities</tui-textarea>
|
||||
</form>
|
||||
@@ -95,42 +120,35 @@
|
||||
<tui-input
|
||||
formControlName="firstName"
|
||||
tuiTextfieldSize="m"
|
||||
[tuiTextfieldCleaner]="true"
|
||||
>
|
||||
[tuiTextfieldCleaner]="true">
|
||||
Voornaam
|
||||
<input
|
||||
tuiTextfieldLegacy
|
||||
type="text"
|
||||
formControlName="firstName"
|
||||
/>
|
||||
formControlName="firstName"/>
|
||||
</tui-input>
|
||||
<br>
|
||||
|
||||
<tui-input
|
||||
formControlName="lastName"
|
||||
tuiTextfieldSize="m"
|
||||
[tuiTextfieldCleaner]="true"
|
||||
>
|
||||
[tuiTextfieldCleaner]="true">
|
||||
Achternaam
|
||||
<input
|
||||
tuiTextfieldLegacy
|
||||
type="text"
|
||||
formControlName="lastName"
|
||||
/>
|
||||
formControlName="lastName"/>
|
||||
</tui-input>
|
||||
<br>
|
||||
<tui-input
|
||||
formControlName="email"
|
||||
tuiTextfieldSize="m"
|
||||
[tuiTextfieldCleaner]="true"
|
||||
>
|
||||
[tuiTextfieldCleaner]="true">
|
||||
Email
|
||||
<input
|
||||
tuiTextfieldLegacy
|
||||
autocomplete="email"
|
||||
type="email"
|
||||
formControlName="email"
|
||||
/>
|
||||
formControlName="email"/>
|
||||
</tui-input>
|
||||
<br>
|
||||
<button
|
||||
@@ -142,8 +160,7 @@
|
||||
type="button">
|
||||
<tui-icon
|
||||
icon="@tui.plus"
|
||||
[style.height.rem]="1"
|
||||
/>
|
||||
[style.height.rem]="1"/>
|
||||
Klant toevoegen
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@@ -13,3 +13,48 @@
|
||||
justify-content: center;
|
||||
|
||||
}
|
||||
|
||||
[tuiAppearance][data-appearance='custom'] {
|
||||
background: #526ed3;
|
||||
color: white;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.appointments-container {
|
||||
display: flex;
|
||||
gap: 5px; /* Ruimte tussen de objecten */
|
||||
overflow-x: auto; /* Alleen horizontaal scrollen als nodig */
|
||||
white-space: nowrap; /* Voorkomt dat items naar een nieuwe regel springen */
|
||||
padding-bottom: 5px; /* Ruimte voor scrollbar */
|
||||
}
|
||||
|
||||
.appointment-object {
|
||||
background-color: #f5f5f5;
|
||||
padding: 5px;
|
||||
border-radius: 3px;
|
||||
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);
|
||||
min-width: 120px;
|
||||
text-align: left;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
flex-shrink: 0; /* Voorkomt dat items kleiner worden bij weinig ruimte */
|
||||
}
|
||||
|
||||
|
||||
/* Optioneel: Specifieke styling voor de tekstregels */
|
||||
.name {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 11px;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {NgForOf, NgIf} from "@angular/common";
|
||||
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from "@angular/forms";
|
||||
import {TuiButton, TuiGroup, TuiIcon} from "@taiga-ui/core";
|
||||
import {TuiButton, TuiError, TuiGroup, TuiIcon} from "@taiga-ui/core";
|
||||
import {
|
||||
TuiComboBoxModule,
|
||||
TuiInputDateModule,
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
TuiTextfieldControllerModule
|
||||
} from "@taiga-ui/legacy";
|
||||
import {Appointment} from '../../models/appointment';
|
||||
import {TuiDay} from '@taiga-ui/cdk';
|
||||
import {TuiDay, TuiTime, TuiValidationError} from '@taiga-ui/cdk';
|
||||
import {AppointmentService} from '../../services/appointment.service';
|
||||
import {
|
||||
TuiButtonLoading,
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
import {Customer} from '../../models/customer';
|
||||
import {CustomerService} from '../../services/customer.service';
|
||||
import {ModalComponent} from '../modal/modal.component';
|
||||
import {timeAfterStartValidator} from '../../models/validators/time-after-start-validator';
|
||||
|
||||
@Component({
|
||||
selector: 'app-new-item',
|
||||
@@ -42,42 +43,65 @@ import {ModalComponent} from '../modal/modal.component';
|
||||
TuiFilterByInputPipe,
|
||||
ModalComponent,
|
||||
TuiIcon,
|
||||
TuiButtonLoading
|
||||
TuiButtonLoading,
|
||||
TuiError
|
||||
],
|
||||
templateUrl: './new-item.component.html',
|
||||
styleUrl: './new-item.component.scss'
|
||||
})
|
||||
export class NewItemComponent implements OnInit {
|
||||
|
||||
@Input() testForm: FormGroup;
|
||||
@Input() appointmentForm: FormGroup;
|
||||
@Input() appointments: Appointment[];
|
||||
quickActions = ['Knippen', 'Kleuren', 'Knippen + Kleuren']
|
||||
waiting: boolean = false;
|
||||
protected value: TuiDay | null = null;
|
||||
@Output() appointmentAddedEvent = new EventEmitter();
|
||||
showNewCustomer = false;
|
||||
customerForm: FormGroup;
|
||||
today: Date;
|
||||
timeError = new TuiValidationError('Begintijd moet voor de eindtijd liggen.');
|
||||
|
||||
|
||||
constructor(private appointmentService: AppointmentService, private customerService: CustomerService) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getCustomers()
|
||||
this.today = new Date();
|
||||
this.customerForm = new FormGroup({
|
||||
firstName: new FormControl('', Validators.required),
|
||||
lastName: new FormControl('', Validators.required),
|
||||
email: new FormControl('', Validators.required),
|
||||
})
|
||||
this.appointmentForm.get('startTime').setValue(new TuiTime(this.today.getHours(), this.today.getMinutes()), Validators.required)
|
||||
this.appointmentForm.get('endTime').setValue(new TuiTime(this.getEndTime().getHours(), this.getEndTime().getMinutes()), [Validators.required, timeAfterStartValidator('startTime')])
|
||||
this.appointments.sort((a, b) => {
|
||||
return a.startHour - b.startHour || a.startMinute - b.startMinute;
|
||||
});
|
||||
}
|
||||
|
||||
getEndTime(): Date {
|
||||
const endTime = new Date(this.today); // Kopieer startTime
|
||||
endTime.setMinutes(endTime.getMinutes() + 30); // 30 minuten toevoegen
|
||||
|
||||
// Controleer of de dag nog steeds hetzelfde is
|
||||
if (endTime.getDate() !== this.today.getDate()) {
|
||||
endTime.setHours(23, 59, 59, 999); // Zet naar 23:59:59 als het overloopt
|
||||
}
|
||||
|
||||
return endTime;
|
||||
}
|
||||
|
||||
registerAppointment() {
|
||||
const title = this.testForm.get('title').value
|
||||
const description = this.testForm.get('notes').value
|
||||
const startTime = this.testForm.get('startTime').value
|
||||
const endTime = this.testForm.get('endTime').value
|
||||
let date = this.testForm.get('date').value
|
||||
const title = this.appointmentForm.get('title').value
|
||||
const description = this.appointmentForm.get('notes').value
|
||||
const startTime = this.appointmentForm.get('startTime').value
|
||||
const endTime = this.appointmentForm.get('endTime').value
|
||||
let date = this.appointmentForm.get('date').value
|
||||
let correctDate = new Date(date.year, date.month, date.day, startTime.hours, startTime.minutes);
|
||||
|
||||
const customer = this.control.value;
|
||||
const customer = this.customerControl.value;
|
||||
|
||||
const appointment = new Appointment(title, description, startTime.hours, startTime.minutes, endTime.hours, endTime.minutes, correctDate, customer)
|
||||
this.waiting = true
|
||||
@@ -88,15 +112,15 @@ export class NewItemComponent implements OnInit {
|
||||
}
|
||||
|
||||
formIsValid() {
|
||||
return this.testForm.valid ? 'active' : 'disabled'
|
||||
return this.appointmentForm.valid && this.customerControl.valid ? 'active' : 'disabled'
|
||||
}
|
||||
|
||||
addAction(action: string) {
|
||||
this.testForm.get('title').setValue(`${action} `)
|
||||
this.appointmentForm.get('title').setValue(`${action} `)
|
||||
}
|
||||
|
||||
protected readonly control = new FormControl<Customer | null>(
|
||||
null,
|
||||
protected readonly customerControl = new FormControl<Customer | null>(
|
||||
null, Validators.required
|
||||
);
|
||||
|
||||
toggleCustomerModal() {
|
||||
@@ -125,4 +149,8 @@ export class NewItemComponent implements OnInit {
|
||||
this.items = response;
|
||||
})
|
||||
}
|
||||
|
||||
getFormattedTime(hour: number, minute: number): string {
|
||||
return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { HttpInterceptorFn } from '@angular/common/http';
|
||||
import { inject } from '@angular/core';
|
||||
import {HttpInterceptorFn} from '@angular/common/http';
|
||||
import {inject} from '@angular/core';
|
||||
import {AuthService} from '../services/auth.service';
|
||||
|
||||
const excludedUrls = ['/auth/login'];
|
||||
|
||||
@@ -22,8 +22,6 @@ export class Appointment {
|
||||
this.startDate = date;
|
||||
this.customer = customer;
|
||||
|
||||
console.log(this)
|
||||
|
||||
// Bereken de totale duur in minuten
|
||||
this.durationInMinutes = (endHour * 60 + endMinute) - (startHour * 60 + startMinute);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export class UserDto {
|
||||
username:string
|
||||
fullName:string
|
||||
email:string
|
||||
token:string
|
||||
username: string
|
||||
fullName: string
|
||||
email: string
|
||||
token: string
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
18
src/app/models/validators/time-after-start-validator.ts
Normal file
18
src/app/models/validators/time-after-start-validator.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import {AbstractControl, ValidationErrors, ValidatorFn} from '@angular/forms';
|
||||
|
||||
export function timeAfterStartValidator(startTimeField: string): ValidatorFn {
|
||||
return (control: AbstractControl): ValidationErrors | null => {
|
||||
const startTime = control.parent?.get(startTimeField)?.value;
|
||||
const endTime = control.value;
|
||||
|
||||
if (!startTime || !endTime) {
|
||||
return null; // Niet valideren als een van beide leeg is
|
||||
}
|
||||
|
||||
// Omzetten naar Date-objecten voor vergelijking
|
||||
const start = new Date(`1970-01-01T${startTime}:00`);
|
||||
const end = new Date(`1970-01-01T${endTime}:00`);
|
||||
|
||||
return end > start ? null : {endTimeInvalid: true};
|
||||
};
|
||||
}
|
||||
@@ -74,7 +74,8 @@
|
||||
</div>
|
||||
|
||||
<app-modal title="Nieuwe afspraak" (close)="closeNewItemModal()" *ngIf="isModalOpen">
|
||||
<app-new-item [testForm]="appointmentForm" (appointmentAddedEvent)="registerAppointment($event)"></app-new-item>
|
||||
<app-new-item [appointments]="appointments" [appointmentForm]="appointmentForm"
|
||||
(appointmentAddedEvent)="registerAppointment($event)"></app-new-item>
|
||||
</app-modal>
|
||||
|
||||
<app-modal title="{{selectedAppointment.title}}" (close)="selectedAppointment = undefined"
|
||||
|
||||
@@ -17,6 +17,7 @@ import {DetailsComponent} from '../../components/details/details.component';
|
||||
import {DateFormatter} from '../../utils/date-formatter';
|
||||
import {WeekDay} from '../../models/week-day';
|
||||
import {NewItemComponent} from '../../components/new-item/new-item.component';
|
||||
import {timeAfterStartValidator} from '../../models/validators/time-after-start-validator';
|
||||
|
||||
@Component({
|
||||
selector: 'app-agenda',
|
||||
@@ -52,7 +53,7 @@ export class AgendaComponent implements OnInit {
|
||||
title: new FormControl('', Validators.required),
|
||||
notes: new FormControl(''),
|
||||
startTime: new FormControl(new TuiTime(this.today.getHours(), this.today.getMinutes()), Validators.required),
|
||||
endTime: new FormControl(new TuiTime(this.getHours(), this.getMinutes()), Validators.required),
|
||||
endTime: new FormControl(new TuiTime(this.getHours(), this.getMinutes()), [Validators.required, timeAfterStartValidator('startTime')]),
|
||||
date: new FormControl(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()), Validators.required),
|
||||
});
|
||||
|
||||
@@ -90,7 +91,7 @@ export class AgendaComponent implements OnInit {
|
||||
title: new FormControl('', Validators.required),
|
||||
notes: new FormControl(''),
|
||||
startTime: new FormControl(new TuiTime(this.today.getHours(), this.today.getMinutes()), Validators.required),
|
||||
endTime: new FormControl(new TuiTime(this.getEndTime().getHours(), this.getEndTime().getMinutes()), Validators.required),
|
||||
endTime: new FormControl(new TuiTime(this.getEndTime().getHours(), this.getEndTime().getMinutes()), [Validators.required, timeAfterStartValidator('startTime')]),
|
||||
date: new FormControl(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()), Validators.required),
|
||||
});
|
||||
}
|
||||
@@ -109,7 +110,6 @@ export class AgendaComponent implements OnInit {
|
||||
|
||||
getHours() {
|
||||
let hours = this.today.getHours()
|
||||
console.log(hours)
|
||||
if (hours > 23) {
|
||||
return 23
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<tui-avatar src="{{getInitials()}}"/>
|
||||
<ng-template #dropdownContent>
|
||||
<div class="dropdown">
|
||||
<h3>{{fullName}}</h3>
|
||||
<h3>{{ fullName }}</h3>
|
||||
<button
|
||||
size="m"
|
||||
tuiButton
|
||||
|
||||
@@ -52,11 +52,11 @@ tui-avatar {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.t-content{
|
||||
.t-content {
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
button{
|
||||
button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<label tuiLabel>Wachtwoord</label>
|
||||
<input formControlName="password" type="password" placeholder="Voer je wachtwoord in" tuiTextfield/>
|
||||
</tui-textfield>
|
||||
<tui-error [error]="computedError" />
|
||||
<tui-error [error]="computedError"/>
|
||||
<footer>
|
||||
<button tuiButton class="custom-button" type="submit" [disabled]="form.invalid" (click)="login()">
|
||||
Inloggen
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* Adjust as needed */
|
||||
}
|
||||
|
||||
tui-error{
|
||||
tui-error {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { JwtHelperService } from '@auth0/angular-jwt';
|
||||
import { Observable } from 'rxjs';
|
||||
import {Injectable} from '@angular/core';
|
||||
import {HttpClient} from '@angular/common/http';
|
||||
import {JwtHelperService} from '@auth0/angular-jwt';
|
||||
import {Observable} from 'rxjs';
|
||||
import {jwtDecode} from 'jwt-decode';
|
||||
|
||||
@Injectable({
|
||||
@@ -12,10 +12,11 @@ export class AuthService {
|
||||
baseApi = "https://api.melvanveen.nl/api/auth/login";
|
||||
jwtHelper = new JwtHelperService();
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
constructor(private http: HttpClient) {
|
||||
}
|
||||
|
||||
login(username: string, password: string): Observable<any> {
|
||||
return this.http.post(this.baseApi, { username, password });
|
||||
return this.http.post(this.baseApi, {username, password});
|
||||
}
|
||||
|
||||
isAuthenticated(): boolean {
|
||||
|
||||
@@ -7,7 +7,6 @@ export class DateFormatter {
|
||||
|
||||
static getHours(date: Date) {
|
||||
let hours = date.getHours()
|
||||
console.log(hours)
|
||||
if (hours > 23) {
|
||||
return 23
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user