diff --git a/angular/src/app/_components/datetime-picker/datetime-picker.component.ts b/angular/src/app/_components/datetime-picker/datetime-picker.component.ts index 8e37777..a4b0e1e 100644 --- a/angular/src/app/_components/datetime-picker/datetime-picker.component.ts +++ b/angular/src/app/_components/datetime-picker/datetime-picker.component.ts @@ -25,6 +25,7 @@ export class DatetimePickerComponent implements OnInit { ngOnInit() { if (this.initialValue) { + // Datum als UTC interpretieren const date = new Date(this.initialValue); this.form.patchValue({ date: this.formatDate(date), @@ -44,19 +45,20 @@ export class DatetimePickerComponent implements OnInit { } private formatDate(date: Date): string { - return date.toLocaleDateString('en-CA'); + // ISO String verwenden und nur den Datumsteil extrahieren (YYYY-MM-DD) + return date.toISOString().split('T')[0]; } private formatTime(date: Date): string { + // Zeit aus ISO String extrahieren + const timeString = date.toISOString().split('T')[1]; + if (this.showSeconds) { - return date.toLocaleTimeString('en-GB', {hour12: false}); + // Rückgabe mit Sekunden (HH:MM:SS) + return timeString.substring(0, 8); } else { - // Nur Stunden und Minuten zurückgeben - return date.toLocaleTimeString('en-GB', { - hour12: false, - hour: '2-digit', - minute: '2-digit' - }); + // Nur Stunden und Minuten zurückgeben (HH:MM) + return timeString.substring(0, 5); } } @@ -74,21 +76,24 @@ export class DatetimePickerComponent implements OnInit { seconds = '00'; } + // Datum in UTC erstellen const dateTime = new Date( - Number(year), - Number(month) - 1, - Number(day), - Number(hours), - Number(minutes), - Number(seconds || 0) + Date.UTC( + Number(year), + Number(month) - 1, + Number(day), + Number(hours), + Number(minutes), + Number(seconds || 0) + ) ); - // Format the date to match the loaded format - const formattedDate = dateTime.toLocaleString('sv-SE', {timeZone: 'Europe/Berlin'}).replace(' ', 'T') + '+02:00'; + // Als ISO-String formatieren, der automatisch in UTC ist + const formattedDate = dateTime.toISOString(); this.dateTimeChange.emit(formattedDate); } else { this.dateTimeChange.emit(null); } } -} +} \ No newline at end of file diff --git a/angular/src/app/_components/list/list.component.ts b/angular/src/app/_components/list/list.component.ts index f727fae..43cdbcb 100644 --- a/angular/src/app/_components/list/list.component.ts +++ b/angular/src/app/_components/list/list.component.ts @@ -405,7 +405,6 @@ export class ListComponent implements OnInit, AfterViewInit, OnDestroy { } public onFilterChanged(filterData: {filters: any, activeCount: number}) { - console.log(filterData); const filterJson = JSON.stringify(filterData.filters); const currentFilterJson = JSON.stringify(this.filterObj); @@ -417,6 +416,12 @@ export class ListComponent implements OnInit, AfterViewInit, OnDestroy { } public onCreateData() { + // Important: Reset the data property to prevent using previous edit data + if (this.dataFormComponentData) { + this.dataFormComponentData = {...this.dataFormComponentData}; + delete this.dataFormComponentData.data; + } + this.appHelperService.openModal( this.dataFormComponent, this.dataFormComponentData, @@ -425,7 +430,11 @@ export class ListComponent implements OnInit, AfterViewInit, OnDestroy { } public onEditData(element: any) { - this.dataFormComponentData.data = element; + // Create a new object instead of modifying the existing one + this.dataFormComponentData = { + ...this.dataFormComponentData, + data: element + }; this.appHelperService.openModal( this.dataFormComponent, this.dataFormComponentData, diff --git a/angular/src/app/_views/trip/trip-location-form/trip-location-form.component.html b/angular/src/app/_views/trip/trip-location-form/trip-location-form.component.html index 02a1bbf..ba6566a 100644 --- a/angular/src/app/_views/trip/trip-location-form/trip-location-form.component.html +++ b/angular/src/app/_views/trip/trip-location-form/trip-location-form.component.html @@ -5,7 +5,7 @@ } @else {
-

{{ ('basic.edit') | translate }} {{ 'model.trip_location' | translate }}: {{ data?.location?.name }}

+

{{ ('basic.edit') | translate }} {{ 'model.trip_location' | translate }}

}
diff --git a/angular/src/app/_views/trip/trip-location-form/trip-location-form.component.ts b/angular/src/app/_views/trip/trip-location-form/trip-location-form.component.ts index 8b3ce07..d0d8c57 100644 --- a/angular/src/app/_views/trip/trip-location-form/trip-location-form.component.ts +++ b/angular/src/app/_views/trip/trip-location-form/trip-location-form.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {Component} from '@angular/core'; import {AbstractDataFormComponent} from "@app/_components/_abstract/abstract-data-form-component"; import { LocationService, TripJsonld, @@ -21,11 +21,13 @@ import {SearchSelectComponent} from "@app/_components/search-select/search-selec }) export class TripLocationFormComponent extends AbstractDataFormComponent { - protected trip!: TripJsonld; - protected arrivalDateTime?: string; - protected departureDateTime?: string; + protected readonly tripLocationForm = tripLocationForm; protected readonly SearchSelectComponent = SearchSelectComponent; protected locationColDefinitions: ListColDefinition[]; + protected trip!: TripJsonld; + protected newArrivalDateTime?: string; + protected newDepartureDateTime?: string; + protected tripLocationEntries: TripLocationJsonld[]; constructor( private tripLocationService: TripLocationService, @@ -49,7 +51,7 @@ export class TripLocationFormComponent extends AbstractDataFormComponent { + alert(error); + }); + return; + } + super.onSubmit(); } - protected readonly tripLocationForm = tripLocationForm; + private hasDateOverlap(formData: TripLocationJsonld): boolean { + // Wenn kein Datum gesetzt ist, kann keine Überlappung stattfinden + if (!formData.arrivalDateTime && !formData.departureDateTime) { + return false; + } + + // Wenn wir im Edit-Modus sind, entferne den aktuellen Eintrag aus der Überprüfung + const entriesToCheck = this.isEditMode() + ? this.tripLocationEntries.filter(entry => entry.id !== this.data?.id) + : this.tripLocationEntries; + + for (const entry of entriesToCheck) { + // Fall 1: Nur ein Datum ist gesetzt in formData + if (formData.arrivalDateTime && !formData.departureDateTime) { + // Arrival date darf nicht mit anderen arrival dates übereinstimmen + if (entry.arrivalDateTime === formData.arrivalDateTime) { + return true; + } + + // Überprüfe, ob arrival innerhalb eines existierenden Zeitraums liegt + // ABER: arrival darf gleich mit einem departure sein + if (entry.arrivalDateTime && entry.departureDateTime) { + const arrivalDate = new Date(formData.arrivalDateTime); + const entryArrival = new Date(entry.arrivalDateTime); + const entryDeparture = new Date(entry.departureDateTime); + + // Liegt innerhalb des Zeitraums, aber ist NICHT gleich dem departure + if (arrivalDate > entryArrival && arrivalDate < entryDeparture) { + return true; + } + } + } + else if (!formData.arrivalDateTime && formData.departureDateTime) { + // Departure date darf nicht mit anderen departure dates übereinstimmen + if (entry.departureDateTime === formData.departureDateTime) { + return true; + } + + // Überprüfe, ob departure innerhalb eines existierenden Zeitraums liegt + // ABER: departure darf gleich mit einem arrival sein + if (entry.arrivalDateTime && entry.departureDateTime) { + const departureDate = new Date(formData.departureDateTime); + const entryArrival = new Date(entry.arrivalDateTime); + const entryDeparture = new Date(entry.departureDateTime); + + // Liegt innerhalb des Zeitraums, aber ist NICHT gleich dem arrival + if (departureDate > entryArrival && departureDate < entryDeparture) { + return true; + } + } + } + // Fall 2: Beide Daten sind gesetzt in formData, überprüfe auf Überlappung + else if (formData.arrivalDateTime && formData.departureDateTime) { + const formArrival = new Date(formData.arrivalDateTime); + const formDeparture = new Date(formData.departureDateTime); + + // Wenn der andere Eintrag beide Daten hat + if (entry.arrivalDateTime && entry.departureDateTime) { + const entryArrival = new Date(entry.arrivalDateTime); + const entryDeparture = new Date(entry.departureDateTime); + + // Überprüfung auf Überlappung der Zeiträume, erlaubt grenzen zu teilen + // Formular-Zeitraum darf vor oder nach dem Entry-Zeitraum liegen, + // oder die Grenzen dürfen gleich sein (departure gleich arrival oder umgekehrt) + if ( + // Überlappung, aber nicht nur am Rand + (formArrival < entryDeparture && formDeparture > entryArrival) && + // Erlaubt: formDeparture === entryArrival ODER formArrival === entryDeparture + !(formDeparture.getTime() === entryArrival.getTime() || + formArrival.getTime() === entryDeparture.getTime()) + ) { + return true; + } + } + // Wenn der andere Eintrag nur arrival hat + else if (entry.arrivalDateTime && !entry.departureDateTime) { + const entryArrival = new Date(entry.arrivalDateTime); + + // Das arrival des anderen Eintrags darf nicht innerhalb des neuen Zeitraums liegen + // ABER: Es darf am Rand liegen (gleich mit formDeparture) + if (entryArrival > formArrival && entryArrival < formDeparture) { + return true; + } + } + // Wenn der andere Eintrag nur departure hat + else if (!entry.arrivalDateTime && entry.departureDateTime) { + const entryDeparture = new Date(entry.departureDateTime); + + // Das departure des anderen Eintrags darf nicht innerhalb des neuen Zeitraums liegen + // ABER: Es darf am Rand liegen (gleich mit formArrival) + if (entryDeparture > formArrival && entryDeparture < formDeparture) { + return true; + } + } + } + } + + return false; + } } diff --git a/angular/src/app/_views/trip/trip-location-list/trip-location-list.component.ts b/angular/src/app/_views/trip/trip-location-list/trip-location-list.component.ts index a32fe86..3531e82 100644 --- a/angular/src/app/_views/trip/trip-location-list/trip-location-list.component.ts +++ b/angular/src/app/_views/trip/trip-location-list/trip-location-list.component.ts @@ -100,7 +100,6 @@ export class TripLocationListComponent { map(response => { // Set default arrival and departure time before return let arrivalDateTime = this.appHelperService.getDateTimeWithoutTimezone(); - console.log(arrivalDateTime); let departureDateTime = this.appHelperService.getDateTimeWithoutTimezone(new Date(new Date().setHours(new Date().getHours() + 1))); if (response.member && response.member.length > 0) { const lastEntry = response.member[response.member.length - 1]; @@ -116,8 +115,9 @@ export class TripLocationListComponent { } this.dataFormComponentData = { trip: this.trip, - arrivalDateTime: arrivalDateTime, - departureDateTime: departureDateTime + newArrivalDateTime: arrivalDateTime, + newDepartureDateTime: departureDateTime, + tripLocationEntries: response.member }; return response; diff --git a/angular/src/assets/i18n/en.json b/angular/src/assets/i18n/en.json index 78d932e..b8516da 100644 --- a/angular/src/assets/i18n/en.json +++ b/angular/src/assets/i18n/en.json @@ -44,7 +44,7 @@ }, "common": { "code": "Code", - "created_at": "Created at", + "created_at": "Created at (UTC)", "date": "Date", "name": "Name", "note": "Note", @@ -107,7 +107,8 @@ }, "trip_location": { "arrival_date_time": "ETA", - "departure_date_time": "ETD" + "departure_date_time": "ETD", + "overlap_error": "These dates and times overlap with other entries, please check!!" }, "user_trip": { "approved": "Approved",