feat: enhance CalendarEventPanel and TimePicker with improved date and time selection UI

This commit is contained in:
Shariq Ansari 2025-08-05 16:39:44 +05:30
parent 27c54461de
commit 55c61cbd80
2 changed files with 52 additions and 51 deletions

View File

@ -66,47 +66,63 @@
<div <div
class="flex items-center justify-between px-4.5 py-[7px] text-ink-gray-7" class="flex items-center justify-between px-4.5 py-[7px] text-ink-gray-7"
> >
<div class="">{{ __('From') }}</div> <div class="">{{ __('Date') }}</div>
<div class="flex items-center gap-x-2"> <div class="flex items-center gap-x-2">
<DatePicker <DatePicker
:class="[_event.isFullDay ? '[&_input]:w-[216px]' : 'max-w-28']" :class="['[&_input]:w-[216px]']"
variant="outline" variant="outline"
:value="_event.fromDate" :value="_event.fromDate"
:formatter="(date) => getFormat(date, 'MMM D, YYYY')" :formatter="(date) => getFormat(date, 'MMM D, YYYY')"
:placeholder="__('Start Date')" :placeholder="__('May 1, 2025')"
@update:modelValue="(date) => updateDate(date, true)" @update:modelValue="(date) => updateDate(date, true)"
/> >
<template #suffix="{ togglePopover }">
<FeatherIcon
name="chevron-down"
class="h-4 w-4 cursor-pointer"
@click="togglePopover"
/>
</template>
</DatePicker>
</div>
</div>
<div
v-if="!_event.isFullDay"
class="flex items-center justify-between px-4.5 py-[7px] text-ink-gray-7"
>
<div class="w-20">{{ __('Time') }}</div>
<div class="flex items-center gap-x-3">
<TimePicker <TimePicker
v-if="!_event.isFullDay" v-if="!_event.isFullDay"
class="max-w-24" class="max-w-[102px]"
variant="outline" variant="outline"
:value="_event.fromTime" :value="_event.fromTime"
:placeholder="__('Start Time')" :placeholder="__('Start Time')"
@update:modelValue="(time) => updateTime(time, true)" @update:modelValue="(time) => updateTime(time, true)"
/> >
</div> <template #suffix="{ togglePopover }">
</div> <FeatherIcon
<div name="chevron-down"
class="flex items-center justify-between px-4.5 py-[7px] text-ink-gray-7" class="h-4 w-4 cursor-pointer"
> @click="togglePopover"
<div class="w-20">{{ __('To') }}</div> />
<div class="flex items-center gap-x-2"> </template>
<DatePicker </TimePicker>
:class="[_event.isFullDay ? '[&_input]:w-[216px]' : 'max-w-28']"
variant="outline"
:value="_event.toDate"
:formatter="(date) => getFormat(date, 'MMM D, YYYY')"
:placeholder="__('End Date')"
@update:modelValue="(date) => updateDate(date)"
/>
<TimePicker <TimePicker
v-if="!_event.isFullDay" class="max-w-[102px]"
class="max-w-24"
variant="outline" variant="outline"
:value="_event.toTime" :value="_event.toTime"
:placeholder="__('End Time')" :placeholder="__('End Time')"
@update:modelValue="(time) => updateTime(time)" @update:modelValue="(time) => updateTime(time)"
/> >
<template #suffix="{ togglePopover }">
<FeatherIcon
name="chevron-down"
class="h-4 w-4 cursor-pointer"
@click="togglePopover"
/>
</template>
</TimePicker>
</div> </div>
</div> </div>
<div class="mx-4.5 my-2.5 border-t" /> <div class="mx-4.5 my-2.5 border-t" />
@ -192,31 +208,9 @@ watch(
{ immediate: true }, { immediate: true },
) )
function updateDate(d, fromDate = false) { function updateDate(d) {
error.value = null _event.value.fromDate = d
let oldTo = _event.value.toDate || _event.value.fromDate _event.value.toDate = d
if (fromDate) {
_event.value.fromDate = d
if (!_event.value.toDate) {
_event.value.toDate = d
}
} else {
_event.value.toDate = d
}
if (_event.value.toDate && _event.value.fromDate) {
const diff = dayjs(_event.value.toDate).diff(
dayjs(_event.value.fromDate),
'day',
)
if (diff < 0) {
_event.value.toDate = oldTo
error.value = __('End date should be after start date')
return
}
}
} }
function updateTime(t, fromTime = false) { function updateTime(t, fromTime = false) {

View File

@ -1,6 +1,6 @@
<template> <template>
<Dropdown :options="options()"> <Dropdown :options="options()">
<template #default="{ open }"> <template #default="{ open, togglePopover }">
<slot <slot
v-bind="{ v-bind="{
emitUpdate, emitUpdate,
@ -17,7 +17,14 @@
:value="timeValue" :value="timeValue"
:placeholder="placeholder" :placeholder="placeholder"
@change="(e) => emitUpdate(e.target.value)" @change="(e) => emitUpdate(e.target.value)"
/> >
<template #prefix v-if="$slots.prefix">
<slot name="prefix" />
</template>
<template #suffix v-if="$slots.suffix">
<slot name="suffix" v-bind="{ togglePopover }" />
</template>
</TextInput>
</slot> </slot>
</template> </template>
<template #body> <template #body>