Refactor date inputs in CreateEventDialog: replace VDateInput with v-text-field and consolidate validation
Build And Push Image / docker (push) Successful in 1m39s
Details
Build And Push Image / docker (push) Successful in 1m39s
Details
This commit is contained in:
parent
503d68cd2d
commit
a0e9643880
|
|
@ -80,13 +80,11 @@
|
|||
|
||||
<!-- Date and Time -->
|
||||
<v-col cols="12" md="6">
|
||||
<VDateInput
|
||||
<v-text-field
|
||||
v-model="startDate"
|
||||
label="Start Date*"
|
||||
:rules="[
|
||||
v => !!v || 'Start date is required',
|
||||
v => !v || new Date(v).getTime() >= new Date().setHours(0,0,0,0) || 'Start date cannot be in the past'
|
||||
]"
|
||||
type="date"
|
||||
:rules="dateValidationRules.startDate"
|
||||
variant="outlined"
|
||||
prepend-inner-icon="mdi-calendar"
|
||||
required
|
||||
|
|
@ -99,7 +97,7 @@
|
|||
v-model="startTime"
|
||||
label="Start Time*"
|
||||
type="time"
|
||||
:rules="[v => !!v || 'Start time is required']"
|
||||
:rules="dateValidationRules.startTime"
|
||||
variant="outlined"
|
||||
prepend-inner-icon="mdi-clock"
|
||||
required
|
||||
|
|
@ -107,14 +105,11 @@
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6">
|
||||
<VDateInput
|
||||
<v-text-field
|
||||
v-model="endDate"
|
||||
label="End Date*"
|
||||
:rules="[
|
||||
v => !!v || 'End date is required',
|
||||
v => !v || new Date(v).getTime() >= new Date().setHours(0,0,0,0) || 'End date cannot be in the past',
|
||||
v => !v || !startDate || new Date(v).getTime() >= new Date(startDate).getTime() || 'End date must be same or after start date'
|
||||
]"
|
||||
type="date"
|
||||
:rules="dateValidationRules.endDate"
|
||||
variant="outlined"
|
||||
prepend-inner-icon="mdi-calendar"
|
||||
:min="startDate || new Date().toISOString().split('T')[0]"
|
||||
|
|
@ -127,10 +122,7 @@
|
|||
v-model="endTime"
|
||||
label="End Time*"
|
||||
type="time"
|
||||
:rules="[
|
||||
v => !!v || 'End time is required',
|
||||
v => !validateEndTime() || 'End time must be after start time when on same date'
|
||||
]"
|
||||
:rules="dateValidationRules.endTime"
|
||||
variant="outlined"
|
||||
prepend-inner-icon="mdi-clock"
|
||||
required
|
||||
|
|
@ -350,12 +342,6 @@ const startTime = ref<string>('');
|
|||
const endDate = ref<string>('');
|
||||
const endTime = ref<string>('');
|
||||
|
||||
// Legacy date model refs for backward compatibility
|
||||
const startDateModel = ref<Date | null>(null);
|
||||
const endDateModel = ref<Date | null>(null);
|
||||
|
||||
// Date format for display
|
||||
const dateTimeFormat = 'dd/MM/yyyy HH:mm (Monaco)';
|
||||
|
||||
// Form data
|
||||
const eventData = reactive<EventCreateRequest>({
|
||||
|
|
@ -442,20 +428,6 @@ watch(maxGuestsPerPerson, (newValue) => {
|
|||
}
|
||||
});
|
||||
|
||||
// Fix date picker binding - ensure proper syncing
|
||||
watch(startDateModel, (newDate) => {
|
||||
if (newDate instanceof Date) {
|
||||
eventData.start_datetime = newDate.toISOString();
|
||||
console.log('[CreateEventDialog] Start date updated:', eventData.start_datetime);
|
||||
}
|
||||
});
|
||||
|
||||
watch(endDateModel, (newDate) => {
|
||||
if (newDate instanceof Date) {
|
||||
eventData.end_datetime = newDate.toISOString();
|
||||
console.log('[CreateEventDialog] End date updated:', eventData.end_datetime);
|
||||
}
|
||||
});
|
||||
|
||||
watch(isRecurring, (newValue) => {
|
||||
eventData.is_recurring = newValue ? 'true' : 'false';
|
||||
|
|
@ -489,38 +461,26 @@ watch(startDate, (newStartDate) => {
|
|||
}
|
||||
});
|
||||
|
||||
// Watch for separate date and time changes to combine them using robust parsing
|
||||
watch([startDate, startTime], ([newDate, newTime]) => {
|
||||
if (newDate && newTime) {
|
||||
console.log('[CreateEventDialog] Combining start date/time:', { date: newDate, time: newTime });
|
||||
|
||||
const combinedDateTime = createDateTimeFromParts(newDate, newTime);
|
||||
|
||||
if (!combinedDateTime) {
|
||||
console.error('[CreateEventDialog] Failed to create start datetime from parts:', { date: newDate, time: newTime });
|
||||
return;
|
||||
// Consolidated watcher for all date/time changes
|
||||
watch([startDate, startTime, endDate, endTime], ([newStartDate, newStartTime, newEndDate, newEndTime]) => {
|
||||
// Update start datetime
|
||||
if (newStartDate && newStartTime) {
|
||||
const startDateTime = createDateTime(newStartDate, newStartTime);
|
||||
if (startDateTime) {
|
||||
eventData.start_datetime = startDateTime.toISOString();
|
||||
console.log('[CreateEventDialog] Updated start datetime:', eventData.start_datetime);
|
||||
}
|
||||
|
||||
eventData.start_datetime = combinedDateTime.toISOString();
|
||||
console.log('[CreateEventDialog] Combined start datetime:', eventData.start_datetime);
|
||||
}
|
||||
});
|
||||
|
||||
watch([endDate, endTime], ([newDate, newTime]) => {
|
||||
if (newDate && newTime) {
|
||||
console.log('[CreateEventDialog] Combining end date/time:', { date: newDate, time: newTime });
|
||||
|
||||
const combinedDateTime = createDateTimeFromParts(newDate, newTime);
|
||||
|
||||
if (!combinedDateTime) {
|
||||
console.error('[CreateEventDialog] Failed to create end datetime from parts:', { date: newDate, time: newTime });
|
||||
return;
|
||||
|
||||
// Update end datetime
|
||||
if (newEndDate && newEndTime) {
|
||||
const endDateTime = createDateTime(newEndDate, newEndTime);
|
||||
if (endDateTime) {
|
||||
eventData.end_datetime = endDateTime.toISOString();
|
||||
console.log('[CreateEventDialog] Updated end datetime:', eventData.end_datetime);
|
||||
}
|
||||
|
||||
eventData.end_datetime = combinedDateTime.toISOString();
|
||||
console.log('[CreateEventDialog] Combined end datetime:', eventData.end_datetime);
|
||||
}
|
||||
});
|
||||
}, { deep: true });
|
||||
|
||||
// Watch for prefilled dates
|
||||
watch(() => props.prefilledDate, (newDate) => {
|
||||
|
|
@ -547,142 +507,48 @@ watch(() => props.prefilledEndDate, (newEndDate) => {
|
|||
}
|
||||
}, { immediate: true });
|
||||
|
||||
// Date picker handlers
|
||||
const handleStartDateUpdate = (date: Date | null) => {
|
||||
if (date) {
|
||||
eventData.start_datetime = date.toISOString();
|
||||
}
|
||||
|
||||
// Simple date/time functions
|
||||
const createDateTime = (dateStr: string, timeStr: string): Date | null => {
|
||||
if (!dateStr || !timeStr) return null;
|
||||
|
||||
const combined = new Date(`${dateStr}T${timeStr}:00`);
|
||||
return isNaN(combined.getTime()) ? null : combined;
|
||||
};
|
||||
|
||||
const handleEndDateUpdate = (date: Date | null) => {
|
||||
if (date) {
|
||||
eventData.end_datetime = date.toISOString();
|
||||
}
|
||||
const isValidDateTime = (date: Date | null): boolean => {
|
||||
return date !== null && !isNaN(date.getTime());
|
||||
};
|
||||
|
||||
const onDatePickerClosed = () => {
|
||||
console.log('[CreateEventDialog] Date picker closed');
|
||||
// This handler ensures the date picker behaves correctly on mobile and desktop
|
||||
// Simple end time validation
|
||||
const validateEndTime = (endTimeValue: string): boolean => {
|
||||
if (!startDate.value || !endDate.value || !startTime.value || !endTimeValue) return true;
|
||||
if (startDate.value !== endDate.value) return true;
|
||||
|
||||
const startDateTime = createDateTime(startDate.value, startTime.value);
|
||||
const endDateTime = createDateTime(endDate.value, endTimeValue);
|
||||
|
||||
if (!startDateTime || !endDateTime) return false;
|
||||
return endDateTime > startDateTime;
|
||||
};
|
||||
|
||||
// Helper functions
|
||||
const normalizeTimeFormat = (timeString: string): string => {
|
||||
// Ensure time is in HH:MM 24-hour format
|
||||
if (!timeString) return '';
|
||||
|
||||
// Remove any whitespace
|
||||
const cleaned = timeString.trim();
|
||||
|
||||
// If already in HH:MM format, validate and return
|
||||
if (/^\d{2}:\d{2}$/.test(cleaned)) {
|
||||
const [hours, minutes] = cleaned.split(':').map(Number);
|
||||
if (hours >= 0 && hours <= 23 && minutes >= 0 && minutes <= 59) {
|
||||
return cleaned;
|
||||
}
|
||||
}
|
||||
|
||||
// If in H:MM format, pad with zero
|
||||
if (/^\d{1}:\d{2}$/.test(cleaned)) {
|
||||
const [hours, minutes] = cleaned.split(':');
|
||||
const paddedHours = hours.padStart(2, '0');
|
||||
const numHours = Number(paddedHours);
|
||||
const numMinutes = Number(minutes);
|
||||
if (numHours >= 0 && numHours <= 23 && numMinutes >= 0 && numMinutes <= 59) {
|
||||
return `${paddedHours}:${minutes}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle seconds format HH:MM:SS by truncating
|
||||
if (/^\d{2}:\d{2}:\d{2}$/.test(cleaned)) {
|
||||
const timePart = cleaned.substring(0, 5);
|
||||
return normalizeTimeFormat(timePart);
|
||||
}
|
||||
|
||||
console.error('[CreateEventDialog] Invalid time format:', timeString);
|
||||
return '';
|
||||
};
|
||||
|
||||
const createDateTimeFromParts = (dateString: string, timeString: string): Date | null => {
|
||||
if (!dateString || !timeString) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// Normalize the time format first
|
||||
const normalizedTime = normalizeTimeFormat(timeString);
|
||||
if (!normalizedTime) {
|
||||
console.error('[CreateEventDialog] Failed to normalize time:', timeString);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Split time into parts
|
||||
const [hours, minutes] = normalizedTime.split(':').map(Number);
|
||||
|
||||
// Create date object from date string (YYYY-MM-DD format)
|
||||
const dateObj = new Date(dateString + 'T00:00:00');
|
||||
|
||||
if (isNaN(dateObj.getTime())) {
|
||||
console.error('[CreateEventDialog] Invalid date string:', dateString);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Set the time components
|
||||
dateObj.setHours(hours, minutes, 0, 0);
|
||||
|
||||
// Validate the final result
|
||||
if (isNaN(dateObj.getTime())) {
|
||||
console.error('[CreateEventDialog] Invalid combined datetime:', { dateString, timeString, normalizedTime, hours, minutes });
|
||||
return null;
|
||||
}
|
||||
|
||||
return dateObj;
|
||||
} catch (error) {
|
||||
console.error('[CreateEventDialog] Error creating datetime:', error, { dateString, timeString });
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Validation functions
|
||||
const validateEndTime = () => {
|
||||
if (!startDate.value || !endDate.value || !startTime.value || !endTime.value) {
|
||||
return false; // Return false (no error) if not all fields are filled
|
||||
}
|
||||
|
||||
console.log('[CreateEventDialog] validateEndTime called with:', {
|
||||
startDate: startDate.value,
|
||||
endDate: endDate.value,
|
||||
startTime: startTime.value,
|
||||
endTime: endTime.value
|
||||
});
|
||||
|
||||
// Only validate if start and end are on the same date
|
||||
if (startDate.value === endDate.value) {
|
||||
// Use robust parsing to create datetime objects
|
||||
const startDateTime = createDateTimeFromParts(startDate.value, startTime.value);
|
||||
const endDateTime = createDateTimeFromParts(endDate.value, endTime.value);
|
||||
|
||||
// Check if dates are valid
|
||||
if (!startDateTime || !endDateTime) {
|
||||
console.error('[CreateEventDialog] Failed to create datetime objects in validation');
|
||||
return true; // Return error if dates are invalid
|
||||
}
|
||||
|
||||
console.log('[CreateEventDialog] Time comparison:', {
|
||||
startDateTime: startDateTime.toISOString(),
|
||||
endDateTime: endDateTime.toISOString(),
|
||||
startTimestamp: startDateTime.getTime(),
|
||||
endTimestamp: endDateTime.getTime(),
|
||||
endIsAfterStart: endDateTime.getTime() > startDateTime.getTime()
|
||||
});
|
||||
|
||||
// Return true if there's an error (end is NOT after start)
|
||||
const hasError = endDateTime.getTime() <= startDateTime.getTime();
|
||||
console.log('[CreateEventDialog] Validation result - hasError:', hasError);
|
||||
|
||||
return hasError;
|
||||
}
|
||||
|
||||
return false; // No error if different dates
|
||||
// Validation rules
|
||||
const dateValidationRules = {
|
||||
startDate: [
|
||||
(v: string) => !!v || 'Start date is required',
|
||||
(v: string) => !v || new Date(v).getTime() >= new Date().setHours(0,0,0,0) || 'Start date cannot be in the past'
|
||||
],
|
||||
startTime: [
|
||||
(v: string) => !!v || 'Start time is required'
|
||||
],
|
||||
endDate: [
|
||||
(v: string) => !!v || 'End date is required',
|
||||
(v: string) => !v || !startDate.value || new Date(v).getTime() >= new Date(startDate.value).getTime() || 'End date must be same or after start date'
|
||||
],
|
||||
endTime: [
|
||||
(v: string) => !!v || 'End time is required',
|
||||
(v: string) => validateEndTime(v) || 'End time must be after start time when on same date'
|
||||
]
|
||||
};
|
||||
|
||||
// Methods
|
||||
|
|
@ -705,11 +571,7 @@ const resetForm = () => {
|
|||
eventData.is_recurring = 'false';
|
||||
eventData.recurrence_pattern = '';
|
||||
|
||||
// Reset date pickers
|
||||
startDateModel.value = null;
|
||||
endDateModel.value = null;
|
||||
|
||||
// Reset separate date/time fields
|
||||
// Reset date/time fields
|
||||
startDate.value = '';
|
||||
startTime.value = '';
|
||||
endDate.value = '';
|
||||
|
|
@ -757,30 +619,18 @@ const handleSubmit = async () => {
|
|||
loading.value = true;
|
||||
|
||||
try {
|
||||
// Combine date and time properly using robust parsing
|
||||
const startDateTime = createDateTimeFromParts(startDate.value, startTime.value);
|
||||
const endDateTime = createDateTimeFromParts(endDate.value, endTime.value);
|
||||
// Simple date validation using our new function
|
||||
const startDateTime = createDateTime(startDate.value, startTime.value);
|
||||
const endDateTime = createDateTime(endDate.value, endTime.value);
|
||||
|
||||
console.log('[CreateEventDialog] DateTime validation:', {
|
||||
startDate: startDate.value,
|
||||
startTime: startTime.value,
|
||||
endDate: endDate.value,
|
||||
endTime: endTime.value,
|
||||
startDateTime: startDateTime?.toISOString(),
|
||||
endDateTime: endDateTime?.toISOString(),
|
||||
startTimestamp: startDateTime?.getTime(),
|
||||
endTimestamp: endDateTime?.getTime()
|
||||
});
|
||||
|
||||
// Validate dates are valid
|
||||
if (!startDateTime) {
|
||||
errorMessage.value = 'Invalid start date or time format';
|
||||
errorMessage.value = 'Please enter a valid start date and time';
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!endDateTime) {
|
||||
errorMessage.value = 'Invalid end date or time format';
|
||||
errorMessage.value = 'Please enter a valid end date and time';
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue