From 0386df262e6c7a6c42555450a714a22008197d0c Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Wed, 27 Aug 2025 20:36:04 +0530 Subject: [PATCH] feat: refactor TimePicker and CalendarEventPanel for improved time selection and validation --- .../Calendar/CalendarEventPanel.vue | 48 +- .../src/components/Calendar/TimePicker.vue | 644 ++++++++++++------ 2 files changed, 471 insertions(+), 221 deletions(-) diff --git a/frontend/src/components/Calendar/CalendarEventPanel.vue b/frontend/src/components/Calendar/CalendarEventPanel.vue index e680a4d0..d384c8bf 100644 --- a/frontend/src/components/Calendar/CalendarEventPanel.vue +++ b/frontend/src/components/Calendar/CalendarEventPanel.vue @@ -224,34 +224,19 @@ v-if="!_event.isFullDay" class="max-w-[105px]" variant="outline" - :value="_event.fromTime" + v-model="_event.fromTime" :placeholder="__('Start Time')" @update:modelValue="(time) => updateTime(time, true)" - > - - + /> - - + />
@@ -363,7 +348,7 @@ import DealsIcon from '@/components/Icons/DealsIcon.vue' import Link from '@/components/Controls/Link.vue' import EditIcon from '@/components/Icons/EditIcon.vue' import DescriptionIcon from '@/components/Icons/DescriptionIcon.vue' -import TimePicker from './TimePicker.vue' +import TimePicker from '@/components/Calendar/TimePicker.vue' import { globalStore } from '@/stores/global' import { usersStore } from '@/stores/users' import { getFormat, validateEmail } from '@/utils' @@ -394,7 +379,15 @@ const props = defineProps({ }, }) -const emit = defineEmits(['save', 'edit', 'delete', 'details', 'close']) +const emit = defineEmits([ + 'save', + 'edit', + 'delete', + 'details', + 'close', + 'sync', + 'duplicate', +]) const router = useRouter() const { $dialog } = globalStore() @@ -409,7 +402,6 @@ const peoples = computed({ return _event.value.event_participants || [] }, set(list) { - // Deduplicate by email while preserving first occurrence meta const seen = new Set() const out = [] for (const a of list || []) { @@ -723,7 +715,13 @@ function getTooltip(m) { function formatDuration(mins) { // For < 1 hour show minutes, else show hours (with decimal for 15/30/45 mins) if (mins < 60) return __('{0} mins', [mins]) - const hours = mins / 60 + let hours = mins / 60 + + // keep hours decimal to 2 only if decimal is not 0 + if (hours % 1 !== 0) { + hours = hours.toFixed(2) + } + if (Number.isInteger(hours)) { return hours === 1 ? __('1 hr') : __('{0} hrs', [hours]) } diff --git a/frontend/src/components/Calendar/TimePicker.vue b/frontend/src/components/Calendar/TimePicker.vue index 907e6e48..95029682 100644 --- a/frontend/src/components/Calendar/TimePicker.vue +++ b/frontend/src/components/Calendar/TimePicker.vue @@ -1,243 +1,495 @@