328 lines
8.4 KiB
Vue
328 lines
8.4 KiB
Vue
<script setup>
|
|
import { PerfectScrollbar } from 'vue3-perfect-scrollbar'
|
|
import { VForm } from 'vuetify/components/VForm'
|
|
import { useCalendarStore } from './useCalendarStore'
|
|
import avatar1 from '@images/avatars/avatar-1.png'
|
|
import avatar2 from '@images/avatars/avatar-2.png'
|
|
import avatar3 from '@images/avatars/avatar-3.png'
|
|
import avatar5 from '@images/avatars/avatar-5.png'
|
|
import avatar6 from '@images/avatars/avatar-6.png'
|
|
import avatar7 from '@images/avatars/avatar-7.png'
|
|
|
|
// 👉 store
|
|
const props = defineProps({
|
|
isDrawerOpen: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
event: {
|
|
type: null,
|
|
required: true,
|
|
},
|
|
})
|
|
|
|
const emit = defineEmits([
|
|
'update:isDrawerOpen',
|
|
'addEvent',
|
|
'updateEvent',
|
|
'removeEvent',
|
|
])
|
|
|
|
const store = useCalendarStore()
|
|
const refForm = ref()
|
|
|
|
// 👉 Event
|
|
const event = ref(JSON.parse(JSON.stringify(props.event)))
|
|
|
|
const resetEvent = () => {
|
|
event.value = JSON.parse(JSON.stringify(props.event))
|
|
nextTick(() => {
|
|
refForm.value?.resetValidation()
|
|
})
|
|
}
|
|
|
|
watch(() => props.isDrawerOpen, resetEvent)
|
|
|
|
const removeEvent = () => {
|
|
emit('removeEvent', String(event.value.id))
|
|
|
|
// Close drawer
|
|
emit('update:isDrawerOpen', false)
|
|
}
|
|
|
|
const handleSubmit = () => {
|
|
refForm.value?.validate().then(({ valid }) => {
|
|
if (valid) {
|
|
|
|
// If id exist on id => Update event
|
|
if ('id' in event.value)
|
|
emit('updateEvent', event.value)
|
|
|
|
// Else => add new event
|
|
else
|
|
emit('addEvent', event.value)
|
|
|
|
// Close drawer
|
|
emit('update:isDrawerOpen', false)
|
|
}
|
|
})
|
|
}
|
|
|
|
const guestsOptions = [
|
|
{
|
|
avatar: avatar1,
|
|
name: 'Jane Foster',
|
|
},
|
|
{
|
|
avatar: avatar3,
|
|
name: 'Donna Frank',
|
|
},
|
|
{
|
|
avatar: avatar5,
|
|
name: 'Gabrielle Robertson',
|
|
},
|
|
{
|
|
avatar: avatar7,
|
|
name: 'Lori Spears',
|
|
},
|
|
{
|
|
avatar: avatar6,
|
|
name: 'Sandy Vega',
|
|
},
|
|
{
|
|
avatar: avatar2,
|
|
name: 'Cheryl May',
|
|
},
|
|
]
|
|
|
|
// 👉 Form
|
|
const onCancel = () => {
|
|
|
|
// Close drawer
|
|
emit('update:isDrawerOpen', false)
|
|
nextTick(() => {
|
|
refForm.value?.reset()
|
|
resetEvent()
|
|
refForm.value?.resetValidation()
|
|
})
|
|
}
|
|
|
|
const startDateTimePickerConfig = computed(() => {
|
|
const config = {
|
|
enableTime: !event.value.allDay,
|
|
dateFormat: `Y-m-d${ event.value.allDay ? '' : ' H:i' }`,
|
|
}
|
|
|
|
if (event.value.end)
|
|
config.maxDate = event.value.end
|
|
|
|
return config
|
|
})
|
|
|
|
const endDateTimePickerConfig = computed(() => {
|
|
const config = {
|
|
enableTime: !event.value.allDay,
|
|
dateFormat: `Y-m-d${ event.value.allDay ? '' : ' H:i' }`,
|
|
}
|
|
|
|
if (event.value.start)
|
|
config.minDate = event.value.start
|
|
|
|
return config
|
|
})
|
|
|
|
const dialogModelValueUpdate = val => {
|
|
emit('update:isDrawerOpen', val)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<VNavigationDrawer
|
|
temporary
|
|
location="end"
|
|
:model-value="props.isDrawerOpen"
|
|
width="420"
|
|
class="scrollable-content"
|
|
@update:model-value="dialogModelValueUpdate"
|
|
>
|
|
<!-- 👉 Header -->
|
|
<AppDrawerHeaderSection
|
|
:title="event.id ? 'Update Event' : 'Add Event'"
|
|
@cancel="$emit('update:isDrawerOpen', false)"
|
|
>
|
|
<template #beforeClose>
|
|
<IconBtn
|
|
v-show="event.id"
|
|
@click="removeEvent"
|
|
>
|
|
<VIcon
|
|
size="18"
|
|
icon="ri-delete-bin-7-line"
|
|
/>
|
|
</IconBtn>
|
|
</template>
|
|
</AppDrawerHeaderSection>
|
|
|
|
<VDivider />
|
|
|
|
<PerfectScrollbar :options="{ wheelPropagation: false }">
|
|
<VCard flat>
|
|
<VCardText>
|
|
<!-- SECTION Form -->
|
|
<VForm
|
|
ref="refForm"
|
|
@submit.prevent="handleSubmit"
|
|
>
|
|
<VRow>
|
|
<!-- 👉 Title -->
|
|
<VCol cols="12">
|
|
<VTextField
|
|
v-model="event.title"
|
|
label="Title"
|
|
placeholder="Meeting with Jane"
|
|
:rules="[requiredValidator]"
|
|
/>
|
|
</VCol>
|
|
|
|
<!-- 👉 Calendar -->
|
|
<VCol cols="12">
|
|
<VSelect
|
|
v-model="event.extendedProps.calendar"
|
|
label="Label"
|
|
placeholder="Select Event Label"
|
|
:rules="[requiredValidator]"
|
|
:items="store.availableCalendars"
|
|
:item-title="item => item.label"
|
|
:item-value="item => item.label"
|
|
>
|
|
<template #selection="{ item }">
|
|
<div
|
|
v-show="event.extendedProps.calendar"
|
|
class="align-center"
|
|
:class="event.extendedProps.calendar ? 'd-flex' : ''"
|
|
>
|
|
<VIcon
|
|
size="8"
|
|
icon="ri-circle-fill"
|
|
:color="item.raw.color"
|
|
class="me-2"
|
|
/>
|
|
<span>{{ item.raw.label }}</span>
|
|
</div>
|
|
</template>
|
|
|
|
<template #item="{ item, props: itemProps }">
|
|
<VListItem v-bind="itemProps">
|
|
<template #prepend>
|
|
<VIcon
|
|
size="8"
|
|
icon="ri-circle-fill"
|
|
:color="item.raw.color"
|
|
/>
|
|
</template>
|
|
</VListItem>
|
|
</template>
|
|
</VSelect>
|
|
</VCol>
|
|
|
|
<!-- 👉 Start date -->
|
|
<VCol cols="12">
|
|
<AppDateTimePicker
|
|
:key="JSON.stringify(startDateTimePickerConfig)"
|
|
v-model="event.start"
|
|
:rules="[requiredValidator]"
|
|
label="Start date"
|
|
placeholder="Select Date"
|
|
:config="startDateTimePickerConfig"
|
|
/>
|
|
</VCol>
|
|
|
|
<!-- 👉 End date -->
|
|
<VCol cols="12">
|
|
<AppDateTimePicker
|
|
:key="JSON.stringify(endDateTimePickerConfig)"
|
|
v-model="event.end"
|
|
:rules="[requiredValidator]"
|
|
label="End date"
|
|
placeholder="Select End Date"
|
|
:config="endDateTimePickerConfig"
|
|
/>
|
|
</VCol>
|
|
|
|
<!-- 👉 All day -->
|
|
<VCol cols="12">
|
|
<VSwitch
|
|
v-model="event.allDay"
|
|
label="All day"
|
|
/>
|
|
</VCol>
|
|
|
|
<!-- 👉 Event URL -->
|
|
<VCol cols="12">
|
|
<VTextField
|
|
v-model="event.url"
|
|
label="Event URL"
|
|
placeholder="https://event.com/meeting"
|
|
:rules="[urlValidator]"
|
|
type="url"
|
|
/>
|
|
</VCol>
|
|
|
|
<!-- 👉 Guests -->
|
|
<VCol cols="12">
|
|
<VSelect
|
|
v-model="event.extendedProps.guests"
|
|
label="Guests"
|
|
placeholder="Select guests"
|
|
:items="guestsOptions"
|
|
:item-title="item => item.name"
|
|
:item-value="item => item.name"
|
|
chips
|
|
multiple
|
|
eager
|
|
/>
|
|
</VCol>
|
|
|
|
<!-- 👉 Location -->
|
|
<VCol cols="12">
|
|
<VTextField
|
|
v-model="event.extendedProps.location"
|
|
label="Location"
|
|
placeholder="Meeting room"
|
|
/>
|
|
</VCol>
|
|
|
|
<!-- 👉 Description -->
|
|
<VCol cols="12">
|
|
<VTextarea
|
|
v-model="event.extendedProps.description"
|
|
label="Description"
|
|
placeholder="Meeting description"
|
|
/>
|
|
</VCol>
|
|
|
|
<!-- 👉 Form buttons -->
|
|
<VCol cols="12">
|
|
<VBtn
|
|
type="submit"
|
|
class="me-3"
|
|
>
|
|
Submit
|
|
</VBtn>
|
|
<VBtn
|
|
variant="outlined"
|
|
color="secondary"
|
|
@click="onCancel"
|
|
>
|
|
Cancel
|
|
</VBtn>
|
|
</VCol>
|
|
</VRow>
|
|
</VForm>
|
|
<!-- !SECTION -->
|
|
</VCardText>
|
|
</VCard>
|
|
</PerfectScrollbar>
|
|
</VNavigationDrawer>
|
|
</template>
|