diff --git a/package-lock.json b/package-lock.json
index 699a5c2..01dff96 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "pay-point",
- "version": "0.0.21",
+ "version": "0.0.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "pay-point",
- "version": "0.0.21",
+ "version": "0.0.3",
"dependencies": {
"@angular/animations": "^19.0.0",
"@angular/cdk": "^19.0.0",
@@ -5974,6 +5974,20 @@
"@angular/core": ">=15.0.0"
}
},
+ "node_modules/angularx-flatpickr": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/angularx-flatpickr/-/angularx-flatpickr-8.1.0.tgz",
+ "integrity": "sha512-U+WXMUXGEiQbdMGSPk7T+HehmAFdVWKu3XlCXFM8mYCCB/fWHW8sbHstxxZgOymD5Q1kfLaHNob1MxhWUgv1hg==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.3.0"
+ },
+ "peerDependencies": {
+ "@angular/core": ">=17.0.0",
+ "@angular/forms": ">=17.0.0",
+ "flatpickr": "^4.5.0"
+ }
+ },
"node_modules/ansi-colors": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
@@ -8343,6 +8357,12 @@
"flat": "cli.js"
}
},
+ "node_modules/flatpickr": {
+ "version": "4.6.13",
+ "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz",
+ "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==",
+ "license": "MIT"
+ },
"node_modules/flatted": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
diff --git a/src/app/components/appointment/appointment.component.html b/src/app/components/appointment/appointment.component.html
new file mode 100644
index 0000000..815a808
--- /dev/null
+++ b/src/app/components/appointment/appointment.component.html
@@ -0,0 +1,28 @@
+
50) }"
+ [ngStyle]="getInlineStyles(appointment)">
+
+ {{ appointment.title }}
+
+
+ {{ appointment.customer.firstName }} {{ appointment.customer.lastName }}
+
+
+ {{ getFormattedTime(appointment.startHour, appointment.startMinute) }}
+ - {{ getFormattedTime(appointment.endHour, appointment.endMinute) }}
+
+
+ 50) }"
+ [ngStyle]="getInlineStyles(appointment)">
+
+ {{ appointment.title }}
+
diff --git a/src/app/components/appointment/appointment.component.scss b/src/app/components/appointment/appointment.component.scss
new file mode 100644
index 0000000..37abd17
--- /dev/null
+++ b/src/app/components/appointment/appointment.component.scss
@@ -0,0 +1,38 @@
+.appointment {
+ position: absolute;
+ //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;
+ min-height: 20px;
+}
+
+.appointment.large {
+ grid-auto-flow: row;
+ align-items: flex-start;
+}
+
+.appointment-time {
+ margin-left: 8px;
+}
+
+@media (max-width: 600px) {
+ .appointment {
+ //width: calc(100% - 80px);
+ font-size: 14px;
+ }
+
+ .appointment-time {
+ font-size: 12px;
+ display: block;
+ }
+}
+
diff --git a/src/app/components/appointment/appointment.component.ts b/src/app/components/appointment/appointment.component.ts
new file mode 100644
index 0000000..e2e6226
--- /dev/null
+++ b/src/app/components/appointment/appointment.component.ts
@@ -0,0 +1,46 @@
+import {Component, EventEmitter, Input, Output} from '@angular/core';
+import {NgClass, NgIf, NgStyle} from '@angular/common';
+import {AppointmentDto} from '../../models/appointment-dto';
+import {TuiIcon} from '@taiga-ui/core';
+
+@Component({
+ selector: 'component-appointment',
+ imports: [
+ NgClass,
+ NgStyle,
+ TuiIcon,
+ NgIf
+ ],
+ templateUrl: './appointment.component.html',
+ styleUrl: './appointment.component.scss'
+})
+export class AppointmentComponent {
+ @Input() appointment: AppointmentDto;
+ @Input() size: 'large' | 'medium' | 'small' = 'medium';
+ @Input() width: 'normal' | 'small' = 'normal';
+ @Output() onClick = new EventEmitter();
+
+ selectAppointment(appointment: AppointmentDto) {
+ this.onClick.emit(appointment);
+ }
+
+ getInlineStyles(appointment: AppointmentDto): { [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
+ 'width': this.width == "normal"? '100px' : '50px',
+ };
+ }
+
+ getFormattedTime(hour: number, minute: number): string {
+ return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
+ }
+
+ getAppointmentHeight(appointment: AppointmentDto): number {
+ const startInMinutes = (appointment.startHour * 60) + appointment.startMinute;
+ const endInMinutes = (appointment.endHour * 60) + appointment.endMinute;
+ return (endInMinutes - startInMinutes); // 50px per uur
+ }
+}
diff --git a/src/app/components/datepicker/datepicker.component.html b/src/app/components/datepicker/datepicker.component.html
new file mode 100644
index 0000000..f691069
--- /dev/null
+++ b/src/app/components/datepicker/datepicker.component.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
Wk
+
+
+
+ {{ week.number }}
+
+ {{ day.getDate() }}
+
+
+
+
+
diff --git a/src/app/components/datepicker/datepicker.component.scss b/src/app/components/datepicker/datepicker.component.scss
new file mode 100644
index 0000000..989672f
--- /dev/null
+++ b/src/app/components/datepicker/datepicker.component.scss
@@ -0,0 +1,99 @@
+$primary: #1976d2;
+$hover-bg: #e3f2fd;
+$selected-bg: #1565c0;
+$bg-light: #f5f5f5;
+$border-radius: 8px;
+
+.calendar {
+ max-width: 900px;
+ margin: 2rem auto;
+ padding: 1rem;
+ background: #fff;
+ border-radius: $border-radius;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ font-family: 'Segoe UI', sans-serif;
+
+ .calendar-header {
+ display: flex;
+ justify-content: space-between;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 1.5rem;
+
+ h3 {
+ margin: 0;
+ font-size: 1.3rem;
+ text-align: center;
+ }
+
+ .nav-button {
+ background: none;
+ border: none;
+ font-size: 1.6rem;
+ color: $primary;
+ cursor: pointer;
+ padding: 0.4rem 0.6rem;
+ border-radius: 4px;
+
+ &:hover {
+ background: $hover-bg;
+ }
+ }
+ }
+
+ .calendar-pair {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 2rem;
+ }
+
+ .calendar-grid {
+ display: grid;
+ grid-template-columns: repeat(8, 1fr);
+ gap: 6px;
+
+ .day-header,
+ .week-label,
+ .week-number {
+ font-weight: bold;
+ background: $bg-light;
+ padding: 6px 0;
+ border-radius: $border-radius;
+ font-size: 0.9rem;
+ text-align: center;
+ height: 20px;
+ width: 28px;
+ }
+
+ .day-cell {
+ padding: 8px 0;
+ text-align: center;
+ cursor: pointer;
+ border-radius: $border-radius;
+ transition: background-color 0.2s;
+ height: 20px;
+ width: 28px;
+
+ &:hover {
+ background: $hover-bg;
+ }
+
+ &.today {
+ background: $hover-bg;
+ font-weight: bold;
+ }
+
+ &.selected {
+ background: $selected-bg;
+ color: #fff;
+ }
+ }
+ }
+
+ .calendar-footer {
+ text-align: center;
+ margin-top: 1.5rem;
+ font-size: 0.95rem;
+ color: #555;
+ }
+}
diff --git a/src/app/components/datepicker/datepicker.component.ts b/src/app/components/datepicker/datepicker.component.ts
new file mode 100644
index 0000000..f839c59
--- /dev/null
+++ b/src/app/components/datepicker/datepicker.component.ts
@@ -0,0 +1,98 @@
+import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
+import {DatePipe, NgForOf, NgIf} from '@angular/common';
+
+@Component({
+ selector: 'datepicker',
+ imports: [
+ NgForOf,
+ DatePipe,
+ NgIf
+ ],
+ templateUrl: './datepicker.component.html',
+ styleUrl: './datepicker.component.scss'
+})
+export class DatepickerComponent implements OnInit {
+ @Input() currentDate = new Date(); // startmaand
+ secondDate = new Date(); // tweede maand
+
+ calendars: any[][] = [[], []];
+ selectedDate: Date | null = null;
+ @Output() onSelectedDate: EventEmitter = new EventEmitter();
+
+ ngOnInit() {
+ this.updateSecondDate();
+ this.generateCalendars();
+ }
+
+ updateSecondDate() {
+ this.secondDate = new Date(this.currentDate.getFullYear(), this.currentDate.getMonth() + 1, 1);
+ }
+
+ generateCalendars() {
+ this.calendars[0] = this.generateCalendar(this.currentDate);
+ this.calendars[1] = this.generateCalendar(this.secondDate);
+ }
+
+ generateCalendar(date: Date) {
+ const year = date.getFullYear();
+ const month = date.getMonth();
+
+ const firstDay = new Date(year, month, 1);
+ const lastDay = new Date(year, month + 1, 0);
+
+ let day = new Date(firstDay);
+ day.setDate(day.getDate() - ((day.getDay() + 6) % 7)); // maandag starten
+
+ const calendar: any[] = [];
+
+ while (day <= lastDay || day.getDay() !== 1) {
+ const week = {
+ number: this.getWeekNumber(day),
+ days: []
+ };
+
+ for (let i = 0; i < 7; i++) {
+ week.days.push(new Date(day));
+ day.setDate(day.getDate() + 1);
+ }
+
+ calendar.push(week);
+ }
+
+ return calendar;
+ }
+
+ getWeekNumber(d: Date): number {
+ const date = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
+ const dayNum = date.getUTCDay() || 7;
+ date.setUTCDate(date.getUTCDate() + 4 - dayNum);
+ const yearStart = new Date(Date.UTC(date.getUTCFullYear(), 0, 1));
+ return Math.ceil((((+date - +yearStart) / 86400000) + 1) / 7);
+ }
+
+ selectDate(date: Date) {
+ this.selectedDate = date;
+ this.onSelectedDate.emit(date);
+ }
+
+ isToday(date: Date): boolean {
+ const today = new Date();
+ return date.toDateString() === today.toDateString();
+ }
+
+ isSelected(date: Date): boolean {
+ return this.selectedDate?.toDateString() === date.toDateString();
+ }
+
+ goToPreviousMonth() {
+ this.currentDate = new Date(this.currentDate.getFullYear(), this.currentDate.getMonth() - 1, 1);
+ this.updateSecondDate();
+ this.generateCalendars();
+ }
+
+ goToNextMonth() {
+ this.currentDate = new Date(this.currentDate.getFullYear(), this.currentDate.getMonth() + 1, 1);
+ this.updateSecondDate();
+ this.generateCalendars();
+ }
+}
diff --git a/src/app/components/dropdown-content/dropdown-content.component.html b/src/app/components/dropdown-content/dropdown-content.component.html
index 9f8cb10..29005ef 100644
--- a/src/app/components/dropdown-content/dropdown-content.component.html
+++ b/src/app/components/dropdown-content/dropdown-content.component.html
@@ -8,7 +8,7 @@
[style.color]="'var(--tui-background-accent-1)'"/>
Agenda delen
-