283 lines
9.1 KiB
Vue

<template>
<div>
<h2 class="chill-red">{{ $t('edit_your_calendar_range') }}</h2>
<div class="form-check">
<input type="checkbox" id="myCalendar" class="form-check-input" v-model="showMyCalendarWidget" />
<label class="form-check-label" for="myCalendar">{{ $t('show_my_calendar') }}</label>
</div>
<div class="form-check">
<input type="checkbox" id="weekends" class="form-check-input" @click="toggleWeekends" />
<label class="form-check-label" for="weekends">{{ $t('show_weekends') }}</label>
</div>
<FullCalendar ref="fullCalendar" :options="{...calendarOptions, eventSources: [this.rangeSource, this.appointmentSource]}">
<template v-slot:eventContent='arg' >
<span class='calendarRangeItems'>
<b v-if="arg.event.extendedProps.myCalendar" style="text-decoration: underline" >{{ arg.timeText }}</b>
<b v-else-if="!arg.event.extendedProps.myCalendar && arg.event.extendedProps.toDelete" style="text-decoration: line-through red" >{{ arg.timeText }}</b>
<b v-else >{{ arg.timeText }}</b>
<i>&nbsp;{{ arg.event.title }}</i>
<a v-if=!arg.event.extendedProps.myCalendar class="fa fa-fw fa-times"
@click.prevent="onClickDelete(arg.event)">
</a>
</span>
</template>
</FullCalendar>
<div id="copy-widget">
<h4 class="chill-red" style="margin-top: 2rem;">{{ $t('copy_range_from_to') }}</h4>
<div style="display: flex; justify-content: space-between; margin-top: 1rem;">
<label class="col-form-label">{{ $t('dateFrom') }}</label>
<div class="col-sm-3">
<input class="form-control" type="date" v-model="copyFrom" />
</div>
<label class="col-form-label">{{ $t('dateTo') }}</label>
<div class="col-sm-3">
<input class="form-control" type="date" v-model="copyTo" />
</div>
<button class="btn btn-action" @click="copyDay">
{{ $t('copy_range')}}
</button>
</div>
</div>
</div>
<teleport to="body">
<modal v-if="modal.showModal"
:modalDialogClass="modal.modalDialogClass"
@close="modal.showModal = false">
<template v-slot:header>
<h2 class="modal-title">{{ this.renderEventDate() }}</h2>
</template>
<template v-slot:body>
<p>{{ $t('by')}} {{this.myCalendarClickedEvent.user.username }}</p>
<p>{{ $t('main_user_concerned') }} : {{ this.myCalendarClickedEvent.mainUser.username }}</p>
<p v-if="myCalendarClickedEvent.comment.length > 0" >{{ this.myCalendarClickedEvent.comment }}</p>
</template>
<template v-slot:footer>
<ul class="record_actions">
<li>
<a
class="btn btn-show"
:href=myCalendarEventShowLink() >
</a>
</li>
<li>
<a
class="btn btn-update"
:href=myCalendarEventUpdateLink() >
</a>
</li>
<li>
<a
class="btn btn-delete"
:href=myCalendarEventDeleteLink() >
</a>
</li>
</ul>
</template>
</modal>
</teleport>
</template>
<script>
import '@fullcalendar/core/vdom'; // solves problem with Vite
import frLocale from '@fullcalendar/core/locales/fr';
import FullCalendar from '@fullcalendar/vue3';
import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction';
import timeGridPlugin from '@fullcalendar/timegrid';
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
import { fetchCalendarRangesByUser, postCalendarRange } from '../_api/api';
import { mapGetters, mapActions, mapState } from 'vuex';
import { vShow } from 'vue';
export default {
name: "App",
components: {
FullCalendar,
Modal
},
data() {
return {
errorMsg: [],
copyFrom: null,
copyTo: null,
modal: {
showModal: false,
modalDialogClass: "modal-dialog-scrollable modal-m"
},
flag: {
loading: false
},
userId: window.userId,
showMyCalendar: true,
myCalendarClickedEvent: null,
lastNewDate: null,
disableCopyDayButton: true,
calendarOptions: {
locale: frLocale,
plugins: [ dayGridPlugin, interactionPlugin, timeGridPlugin ],
initialView: 'timeGridWeek',
initialDate: window.startDate !== undefined ? window.startDate : new Date(),
selectable: true,
select: this.onDateSelect,
eventChange: this.onEventChange,
eventDrop: this.onEventDropOrResize,
eventResize: this.onEventDropOrResize,
eventClick: this.onEventClick,
selectMirror: false,
editable: true,
weekends: false,
slotDuration: '00:15:00',
slotMinTime: "08:00:00",
slotMaxTime: "19:00:00",
contentHeight: 500,
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth timeGridWeek timeGridDay'
},
},
}
},
computed: {
...mapState({
rangesToCopy: state => state.rangesToCopy
}),
...mapGetters(['rangeSource', 'appointmentSource']),
showMyCalendarWidget: {
set(value) {
this.toggleMyCalendar(value);
},
get() {
return this.showMyCalendar;
}
}
},
methods: {
...mapActions([
'fetchRanges',
'fetchAppointments',
'postRange',
'patchRange',
'deleteRange'
]),
openModal() {
this.modal.showModal = true;
},
myCalendarEventShowLink() {
return `/fr/calendar/calendar/${this.myCalendarClickedEvent.id}/show?user_id=${ this.userId }`
},
myCalendarEventUpdateLink() {
return `/fr/calendar/calendar/${this.myCalendarClickedEvent.id}/edit?user_id=${ this.userId }`
},
myCalendarEventDeleteLink() {
return `/fr/calendar/calendar/${this.myCalendarClickedEvent.id}/delete?user_id=${ this.userId }`
},
toggleMyCalendar(value) {
this.showMyCalendar = value;
},
toggleWeekends: function() {
this.calendarOptions.weekends = !this.calendarOptions.weekends;
},
replaceDate(from, to) {
const fromDate = new Date(from)
const toDate = new Date(to);
let newDate = fromDate.setDate(toDate.getDate());
newDate = new Date(newDate).setMonth(toDate.getMonth());
newDate = new Date(newDate).setFullYear(toDate.getFullYear());
newDate = `${new Date(newDate).toISOString().split('.')[0]}+0000`;
return newDate;
},
onDateSelect(payload) {
const newRange = {
user: {
type: 'user',
id: window.userId,
},
startDate: {
datetime: `${payload.start.toISOString().split('.')[0]}+0000`, //should be like "2021-08-20T15:00:00+0200",
},
endDate: {
datetime: `${payload.end.toISOString().split('.')[0]}+0000`, // TODO check if OK with time zone
},
}
this.postRange(newRange);
},
onEventClick(payload) {
if (payload.event.extendedProps.myCalendar) {
this.myCalendarClickedEvent = {
id: payload.event.extendedProps.calendarId,
start: payload.event.start,
end: payload.event.end,
user: payload.event.extendedProps.user,
mainUser: payload.event.extendedProps.mainUser,
persons: payload.event.extendedProps.persons,
professionals: payload.event.extendedProps.professionals,
comment: payload.event.extendedProps.comment
};
this.openModal();
}
},
onClickDelete(payload) {
if (payload.extendedProps.hasOwnProperty("calendarRangeId")) {
this.deleteRange(payload.extendedProps.calendarRangeId)
}
},
onEventDropOrResize(payload) {
const changedEvent = payload.event;
this.patchRange(changedEvent);
},
copyDay() {
const payload = {
userId: this.userId,
dateToCopy: new Date(this.copyFrom).toISOString()
}
this.fetchRanges(payload).then(
r => {
r.forEach((range) => {
this.postRange({
user: {
type: 'user',
id: range.user.id,
},
startDate: {
datetime: this.replaceDate(range.startDate.datetime, this.copyTo), //should be like "2021-08-20T15:00:00+0200",
},
endDate: {
datetime: this.replaceDate(range.endDate.datetime, this.copyTo),
},
})
})
}
)
},
renderEventDate() {
let start = this.myCalendarClickedEvent.start;
let end = this.myCalendarClickedEvent.end;
return start.getDate() === end.getDate() ?
`${start.toLocaleDateString()}, ${start.toLocaleTimeString()} - ${end.toLocaleTimeString()}` :
`${start.toLocaleString()} - ${end.toLocaleString()}`;
}
},
mounted() {
this.fetchRanges()
if (this.showMyCalendar) {
this.fetchAppointments(this.userId)
}
}
}
</script>