Skip to content

Instantly share code, notes, and snippets.

@alimuradov
Created November 10, 2022 11:51
Show Gist options
  • Save alimuradov/8f3619fe97f0a294e406ca76cfca31df to your computer and use it in GitHub Desktop.
Save alimuradov/8f3619fe97f0a294e406ca76cfca31df to your computer and use it in GitHub Desktop.
<template>
<div>
<div class="flex flex-row justify-end mb-4">
<div class="flex-1"></div>
<ClinicDropdown
@set-clinic="setClinicCalendar"
:clinic_id="clinicId"
:inputId="clinicId"
class="basis-1/5 justify-end"
/>
</div>
<FullCalendar :options="calendarOptions" ref="calendar" />
<AppointmentDropdown ref="appointmentMenuRef" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, h } from "vue";
import "@fullcalendar/core/vdom"; // solves problem with Vite
import FullCalendar from "@fullcalendar/vue3";
import type {
DateSelectArg,
EventApi,
CalendarOptions,
} from "@fullcalendar/vue3";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import resourceTimeGridPlugin from "@fullcalendar/resource-timegrid";
import resourceDayGridPlugin from "@fullcalendar/resource-daygrid";
import interactionPlugin from "@fullcalendar/interaction";
import ruLocale from "@fullcalendar/core/locales/ru";
import fetchApi from "@/api/appointment";
import fetchUser from "@/api/user";
import { useUserStore } from "@/stores/modules/user";
import { $vfm } from "vue-final-modal";
import AppointmentAddForm from "@/components/Forms/appointment/AppointmentAddForm.vue";
import ClinicDropdown from "@/components/Dropdowns/ClinicDropdown.vue";
import type { AppointmentCreateModal } from "@/api/appointment/model";
import { useToast } from "vue-toastification";
import { createPopper } from '@popperjs/core';
import AppointmentDropdown from "@/components/Dropdowns/appointment/AppointmentDropdown.vue";
const toast = useToast();
const userStore = useUserStore();
const clinicId = ref(userStore.getClinicId);
const uniodId = ref<string>();
const appointmentMenuRef = ref(null);
const calendar = ref(null);
interface DoctorResource {
id: string;
title: string;
eventBackgroundColor: string;
}
const doctorsResources = ref<DoctorResource[]>([]);
const handleAddAppointment = async (value: AppointmentCreateModal) => {
await fetchApi
.createAppointment(value)
.then((res) => {
if (res) {
calendar.value.calendar.addEvent({
id: res.id,
title: "dggfgf",
start: res.start,
end: res.end,
allDay: false,
resourceId: res.doctor_id,
});
}
toast.success("Запись на прием добавлена");
calendar.value.calendar.getEvents();
})
.catch(() => {
toast.error("Не удалось добавить запись на прием");
});
};
const handleDateSelect = (selectInfo: DateSelectArg) => {
$vfm.show({
component: AppointmentAddForm,
bind: {
start: selectInfo.start,
end: selectInfo.end,
clinic_id: clinicId.value,
doctor_id: selectInfo.resource?._resource.id,
},
on: {
"add-appointment": handleAddAppointment,
},
});
const calendarApi = selectInfo.view.calendar;
calendarApi.unselect(); // clear date selection
};
const setClinicCalendar = (clinic_Id: string, union_id: string) => {
if (clinic_Id) {
clinicId.value = clinic_Id;
calendar.value.calendar.refetchEvents();
}
if (union_id) {
uniodId.value = union_id;
calendar.value.calendar.refetchEvents();
}
};
function isNotEmpty(str: string | undefined) {
if (str == undefined) return false;
if (str.trim() == "") return false;
return true;
}
function getIconFromstatus(status: number) {
if (status == 0) {
return "<i class='fa-regular fa-clock'></i>";
} else if (status == 1) {
return "<i class='fa-solid fa-check'></i>";
} else if (status == 2) {
return "<i class='fa-solid fa-ban'></i>";
}
}
onMounted(async () => {
const params = {
role: "doctor",
clinic_id: clinicId.value,
};
await fetchUser
.getUsers(params)
.then((res) => {
if (res.status == 200 && res.data.items.length > 0) {
Array.prototype.forEach.call(res.data.items, function (ell) {
doctorsResources.value.push({
id: ell.id,
title: ell.first_name + " " + ell.last_name,
eventBackgroundColor: ell.color,
});
});
}
})
.catch((er) => {
console.log(er);
});
});
const calendarOptions = {
locale: ruLocale,
schedulerLicenseKey: "CC-Attribution-NonCommercial-NoDerivatives",
allDaySlot: false,
plugins: [
dayGridPlugin,
interactionPlugin,
timeGridPlugin,
resourceTimeGridPlugin,
],
headerToolbar: {
left: "prev,next today addAppointment",
center: "title",
right: "dayGridMonth,timeGridWeek,timeGridDay,resourceTimeGridPlugin",
},
views: {
resourceTimeGridPlugin: {
type: "resourceTimeGridDay",
duration: { days: 1 },
buttonText: "По врачам",
},
},
resources: doctorsResources.value,
initialView: "timeGridWeek",
slotMinTime: "08:00:00",
slotMaxTime: "21:00:00",
editable: true,
selectable: true,
select: handleDateSelect,
customButtons: {
addAppointment: {
text: "Добавить прием",
click: function () {
$vfm.show({ component: AppointmentAddForm });
},
},
},
events: function (info, successCallback, failureCallback) {
// const userStore = useUserStore();
fetchApi
.eventsFeed({
start: info.start,
end: info.end,
clinic_id: clinicId.value,
})
.then((res) => {
successCallback(
Array.prototype.slice.call(res.data).map(function (eventEl) {
return {
resourceId: eventEl["doctor_id"],
title:
(isNotEmpty(eventEl["patient"]["last_name"])
? eventEl["patient"]["last_name"]
: "") +
" " +
(isNotEmpty(eventEl["patient"]["first_name"])
? eventEl["patient"]["first_name"]
: "") +
(isNotEmpty(eventEl["patient"]["patronymic"])
? " " + eventEl["patient"]["patronymic"][0] + "."
: ""),
start: eventEl["start"],
end: eventEl["end"],
extendedProps: {
id: eventEl["id"],
status: eventEl["status"],
},
};
})
);
})
.catch((err) => failureCallback(err));
},
eventResize: async function (info) {
await fetchApi
.updateAppointment({
id: info.event.extendedProps["id"],
start: info.event.start.toISOString(),
end: info.event.end.toISOString(),
})
.catch(() => {
toast.warning("Не удалось изменить диапазон");
});
},
eventDrop: async (info) => {
await fetchApi
.updateAppointment({
id: info.event.extendedProps["id"],
start: info.event.start.toISOString(),
end: info.event.end.toISOString(),
})
.catch(() => {
toast.warning("Не удалось изменить диапазон");
});
},
eventClick: function(info) {
info.jsEvent.preventDefault();
console.log(this);
createPopper(info.el, this.$refs.appointmentMenuRef, {
placement: 'bottom',
});
},
eventContent: function (args) {
const status = args.event._def.extendedProps.status;
let text = getIconFromstatus(status) + " ";
text = text + args.event.title + "</br>";
text = text + args.timeText;
return {
html: text,
};
},
} as CalendarOptions;
</script>
<style>
.fc-license-message {
display: none !important;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment