git init v2

This commit is contained in:
2025-03-11 23:13:19 +01:00
parent 4d4c8a362a
commit abae328d8f
62 changed files with 3461 additions and 421 deletions

View File

@@ -0,0 +1,84 @@
<div class="container">
<div class="heading">
<button
appearance="primary"
iconStart="@tui.chevron-left"
size="m"
tuiIconButton
(click)="previousDay()"
type="button">
</button>
<h1 class="date" (click)="toggleCalendar()">{{ getDate() }}</h1>
<button
appearance="primary"
iconStart="@tui.chevron-right"
size="m"
tuiIconButton
(click)="nextDay()"
type="button">
</button>
</div>
<div class="calendar" *ngIf="showCalendar">
<tui-calendar
[value]="value"
(dayClick)="onDayClick($event)"
/>
</div>
<div class="toolbar">
<button
*ngIf="today.getDate() != selectedDate.getDate()"
appearance="secondary"
size="m"
tuiButton
(click)="setToday()"
type="button">
Vandaag
</button>
<button
appearance="secondary"
size="m"
tuiButton
(click)="isModalOpen = true"
type="button">
<tui-icon
icon="@tui.plus"
[style.height.rem]="1"
/>
Afspraak maken
</button>
</div>
<div class="content">
<div class="agenda-container">
<div *ngFor="let hour of timeSlots" class="time-slot">
<span class="time">{{ hour.toString().padStart(2, '0') }}:00</span>
<div *ngFor="let appointment of getAppointmentsForHour(hour)"
class="appointment"
(click)="selectAppointment(appointment)"
[ngClass]="{ 'large': (getAppointmentHeight(appointment) > 50) }"
[ngStyle]="getInlineStyles(appointment)">
<strong>{{ appointment.title }}</strong>
<span class="appointment-time" *ngIf="appointment.customer">
<tui-icon icon="@tui.user" [style.font-size.rem]="1"></tui-icon>
{{ appointment.customer.firstName }} {{ appointment.customer.lastName }}</span>
<span class="appointment-time">
<tui-icon icon="@tui.clock" [style.font-size.rem]="1"></tui-icon>
{{ getFormattedTime(appointment.startHour, appointment.startMinute) }}
- {{ getFormattedTime(appointment.endHour, appointment.endMinute) }}
</span>
</div>
</div>
</div>
</div>
</div>
<app-modal title="Nieuwe afspraak" (close)="closeNewItemModal()" *ngIf="isModalOpen">
<app-new-item [testForm]="appointmentForm" (appointmentAddedEvent)="registerAppointment($event)"></app-new-item>
</app-modal>
<app-modal title="{{selectedAppointment.title}}" (close)="selectedAppointment = undefined"
*ngIf="selectedAppointment != undefined">
<app-details [appointment]="selectedAppointment" (appointmentDeleted)="appointmentIsDeleted($event)"
(appointmentEdited)="appointmentIsEdited($event)"></app-details>
</app-modal>

View File

@@ -0,0 +1,141 @@
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
ul {
list-style-type: none;
padding: 0;
}
li {
background-color: #f9f9f9;
margin: 10px 0;
padding: 10px;
border-radius: 5px;
}
h2 {
margin: 0;
}
p {
margin: 5px 0 0;
}
.heading {
margin-bottom: 12px;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.calendar {
margin-bottom: 12px;
display: flex;
flex-direction: row;
justify-content: center;
}
.time-slot {
height: 25px;
display: flex;
align-items: center;
font-size: 14px;
background: #f9f9f9;
transition: background 0.3s ease;
}
.time-slot.claimed {
background: #d1e7dd; /* Lichtgroene achtergrond voor gereserveerde blokken */
color: #155724;
font-weight: bold;
}
.time-slot:nth-child(odd) {
background: #ececec;
}
.time {
width: 50px;
font-weight: bold;
margin-top: 20px;
margin-left: 8px;
}
.content {
overflow-y: scroll;
max-height: 70vh;
}
.agenda-container {
display: flex;
flex-direction: column;
border: 1px solid #ddd;
position: relative;
}
.time-slot {
position: relative;
border-bottom: 1px solid #ccc;
height: 59px;
display: flex;
flex-direction: column;
align-items: flex-start;
font-size: 16px;
background: #f9f9f9;
}
.appointment {
position: absolute;
left: 80px;
width: calc(100% - 100px);
background: #1e88e5;
color: white;
border-radius: 4px;
border-left: 5px solid #1565c0;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
z-index: 10;
cursor: pointer;
display: grid;
grid-auto-flow: column;
align-items: center;
//gap: 5px;
min-height: 20px;
}
.appointment.large {
grid-auto-flow: row;
align-items: flex-start;
}
strong, p {
margin-left: 8px;
}
.appointment-time {
margin-left: 8px;
}
.toolbar {
button {
margin-left: 8px;
}
margin-bottom: 12px;
display: flex;
flex-direction: row;
justify-content: center;
}
.date {
cursor: pointer;
}
.date:hover {
text-decoration: underline;
}

View File

@@ -0,0 +1,206 @@
import {Component, inject, OnInit} from '@angular/core';
import {CommonModule, NgFor, NgIf} from '@angular/common';
import {TuiAlertService, TuiButton, TuiCalendar, tuiDateFormatProvider, TuiIcon} from '@taiga-ui/core';
import {Appointment} from '../../models/appointment';
import {ModalComponent} from '../../components/modal/modal.component';
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
import {
TuiInputDateModule,
TuiInputModule,
TuiInputTimeModule,
TuiTextareaModule,
TuiTextfieldControllerModule
} from '@taiga-ui/legacy';
import {TuiDay, TuiTime} from '@taiga-ui/cdk';
import {AppointmentService} from '../../services/appointment.service';
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';
@Component({
selector: 'app-agenda',
imports: [NgFor,
TuiButton, CommonModule, NgIf, ModalComponent, ReactiveFormsModule,
TuiInputTimeModule, TuiTextfieldControllerModule,
TuiInputModule, TuiTextareaModule, TuiInputDateModule, TuiIcon, DetailsComponent, TuiCalendar, NewItemComponent],
templateUrl: './agenda.component.html',
providers: [tuiDateFormatProvider({separator: '-'}), AppointmentService],
styleUrl: './agenda.component.scss'
})
export class AgendaComponent implements OnInit {
constructor(private appointmentService: AppointmentService) {
}
ngOnInit(): void {
this.getAppointmentsByDate(this.selectedDate);
}
timeSlots: number[] = Array.from({length: 24}, (_, i) => i); // 24 uren
appointments: Appointment[] = [];
isModalOpen = false
today = new Date()
selectedDate = new Date()
waiting: boolean = false;
selectedAppointment: Appointment;
protected value: TuiDay | null = null;
showCalendar: boolean = false;
private readonly alerts = inject(TuiAlertService);
protected appointmentForm = new FormGroup({
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),
date: new FormControl(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()), Validators.required),
});
registerAppointment(title: string): void {
this.getAppointmentsByDate(this.selectedDate);
this.waiting = false
this.isModalOpen = false
this.showNotification(title)
this.resetForms()
}
protected showNotification(message: string): void {
this.alerts
.open(`Afspraak <strong>${message}</strong> is aangemaakt.`)
.subscribe();
}
getAppointmentsForHour(hour: number) {
return this.appointments.filter(appointment => appointment.startHour === hour);
}
getDate(): string {
const date = this.selectedDate
const weekDay = WeekDay[date.getDay()];
const day = date.getDate().toString().padStart(2, '0'); // Dag met leading zero (01, 02, ..., 31)
const monthName = date.toLocaleString('nl-NL', {month: 'long'});
const year = date.getFullYear().toString(); // Volledig jaar
return `${weekDay} ${day} ${monthName} ${year}`;
}
resetForms() {
this.appointmentForm = new FormGroup({
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),
date: new FormControl(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()), Validators.required),
});
}
nextDay() {
this.selectedDate.setDate(this.selectedDate.getDate() + 1);
this.getAppointmentsByDate(this.selectedDate);
this.appointmentForm.get('date').setValue(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()))
}
previousDay() {
this.selectedDate.setDate(this.selectedDate.getDate() - 1);
this.getAppointmentsByDate(this.selectedDate);
this.appointmentForm.get('date').setValue(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()))
}
getHours() {
let hours = this.today.getHours()
console.log(hours)
if (hours > 23) {
return 23
}
return hours
}
getMinutes() {
let minutes = this.today.getMinutes() + 30
if (minutes > 59) {
return 59
}
return minutes
}
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;
}
setToday() {
this.selectedDate = new Date()
this.getAppointmentsByDate(this.selectedDate);
this.appointmentForm.get('date').setValue(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()))
}
getAppointmentsByDate(date: Date) {
this.appointmentService.getAppointmentsByDate(date).subscribe(appointments => {
this.appointments = appointments;
})
}
getInlineStyles(appointment: Appointment): { [key: string]: string } {
return {
'--duration': `${appointment.durationInMinutes}`,
'--start-minute': `${appointment.startMinute}`,
'top': `${appointment.startMinute}px`, // Startpositie binnen het uur
'height': `${appointment.durationInMinutes}px`, // Hoogte over meerdere uren
};
}
getFormattedTime(hour: number, minute: number): string {
return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
}
getAppointmentHeight(appointment: Appointment): number {
const startInMinutes = (appointment.startHour * 60) + appointment.startMinute;
const endInMinutes = (appointment.endHour * 60) + appointment.endMinute;
return (endInMinutes - startInMinutes); // 50px per uur
}
selectAppointment(appointment: Appointment) {
this.selectedAppointment = appointment;
}
protected readonly DateFormatter = DateFormatter;
onDayClick(day: TuiDay) {
this.value = day;
this.selectedDate = new Date(day.year, day.month, day.day);
this.getAppointmentsByDate(this.selectedDate);
this.appointmentForm.get('date').setValue(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()))
this.toggleCalendar()
}
toggleCalendar() {
this.showCalendar = !this.showCalendar
}
closeNewItemModal() {
this.isModalOpen = false
this.resetForms()
}
appointmentIsDeleted(appointment: Appointment) {
this.selectedAppointment = undefined;
this.alerts
.open(`Afspraak <strong>${appointment.title}</strong> is verwijderd.`)
.subscribe();
this.getAppointmentsByDate(this.selectedDate);
}
appointmentIsEdited($event: Appointment) {
this.getAppointmentsByDate(this.selectedDate);
}
}