Files
full-matdash-nuxt-stim/components/dashboards/dashboard3/Calendarcard.vue
T

400 lines
12 KiB
Vue

<script lang="ts">
import { ref } from "vue";
import { defineComponent } from "vue";
import FullCalendar from "@fullcalendar/vue3";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
import { format } from "date-fns"; // Import date-fns for formatting dates
import type { CalendarOptions } from "@fullcalendar/core";
let eventGuid = 0;
const today = new Date();
const y = today.getFullYear();
const m = today.getMonth();
const d = today.getDate();
export const INITIAL_EVENTS = [
{
id: createEventId(),
title: "Twice event For two Days",
allDay: true,
start: new Date(y, m, 3),
end: new Date(y, m, 5),
color: "#635BFF",
},
{
id: createEventId(),
title: "Learn ReactJs",
start: new Date(y, m, d + 3, 10, 30),
end: new Date(y, m, d + 3, 11, 30),
allDay: true,
color: "#13DEB9",
},
{
id: createEventId(),
title: "Launching MaterialArt Angular",
start: new Date(y, m, d + 7, 12, 0),
end: new Date(y, m, d + 7, 14, 0),
allDay: true,
color: "#ff6692",
},
{
id: createEventId(),
title: "Lunch with Mr.Raw",
start: new Date(y, m, d - 2),
end: new Date(y, m, d - 2),
allDay: true,
color: "#16CDC7",
},
{
id: createEventId(),
title: "Going For Party of Sahs",
start: new Date(y, m, d + 1, 19, 0),
end: new Date(y, m, d + 1, 22, 30),
allDay: true,
color: "#1a97f5",
},
{
id: createEventId(),
title: "Learn Ionic",
start: new Date(y, m, 23),
end: new Date(y, m, 25),
color: "#ffd648",
},
];
export function createEventId() {
return String(eventGuid++);
}
export default defineComponent({
components: {
FullCalendar,
},
data() {
return {
menu1: false, // For Start Date
menu2: false, // For End Date
updateModalShow: false,
addModalShow: false,
selectedEvent: {
id: "",
title: "",
color: "",
start: "",
end: "",
allDay: true,
},
newEvent: { title: "", color: "", start: "", end: "", allDay: true },
updatedTitle: "",
updatedColor: "",
calendarOptions: {
plugins: [dayGridPlugin, timeGridPlugin, interactionPlugin],
headerToolbar: {
left: "prev,next today",
center: "title",
right: "dayGridMonth,timeGridWeek,timeGridDay",
},
initialView: "dayGridMonth",
initialEvents: INITIAL_EVENTS,
editable: true,
selectable: true,
selectMirror: true,
dayMaxEvents: true,
weekends: true,
select: this.handleDateSelect,
eventClick: this.handleEventClick,
eventsSet: this.handleEvents,
} as CalendarOptions,
activeColor: {
newEvent: "", // Store the active color for the new event
updateEvent: "", // Store the active color for the update event
},
currentEvents: [],
colorOptions: [
{ id: 1, label: "Primary", value: "#615dff" },
{ id: 2, label: "Success", value: "#39b69a" },
{ id: 3, label: "Error", value: "#fc4b6c" },
{ id: 4, label: "Secondary", value: "#1a97f5" },
{ id: 5, label: "Warning", value: "#fdd43f" },
],
};
},
methods: {
handleDateSelect(selectInfo: any) {
this.addModalShow = true;
this.newEvent.start = selectInfo.startStr;
this.newEvent.end = selectInfo.endStr;
this.newEvent.allDay = selectInfo.allDay;
},
handleEventClick(clickInfo: any) {
this.updateModalShow = true;
const eventStart = clickInfo.event.start ? clickInfo.event.start : null;
const eventEnd = clickInfo.event.end ? clickInfo.event.end : null;
// Safely format the start and end dates if they exist
this.selectedEvent = {
id: clickInfo.event.id,
title: clickInfo.event.title,
color: clickInfo.event.backgroundColor,
start: eventStart ? format(eventStart, "yyyy-MM-dd") : "", // If the date exists, format it, otherwise use an empty string
end: eventEnd ? format(eventEnd, "yyyy-MM-dd") : "", // Handle no end date case
allDay: clickInfo.event.allDay,
};
// Set updated values for the modal fields
this.updatedTitle = this.selectedEvent.title;
this.updatedColor = this.selectedEvent.color;
this.activeColor.updateEvent = this.selectedEvent.color;
},
addEvent() {
const calendarApi = (this.$refs.fullCalendar as InstanceType<typeof FullCalendar>).getApi();
calendarApi.addEvent({
id: createEventId(),
title: this.newEvent.title,
start: this.newEvent.start,
end: this.newEvent.end,
allDay: this.newEvent.allDay,
backgroundColor: this.newEvent.color,
});
this.addModalShow = false;
this.newEvent = {
title: "",
color: "",
start: "",
end: "",
allDay: true,
};
},
updateEvent() {
const calendarApi = (this.$refs.fullCalendar as InstanceType<typeof FullCalendar>).getApi();
const event = calendarApi.getEventById(this.selectedEvent.id);
if (event) {
// Ensure updatedStart and updatedEnd are not null before calling getTime()
const updatedStart = this.selectedEvent.start ? new Date(this.selectedEvent.start) : null;
const updatedEnd = this.selectedEvent.end ? new Date(this.selectedEvent.end) : null;
if (!updatedStart || isNaN(updatedStart.getTime()) || (updatedEnd && isNaN(updatedEnd.getTime()))) {
console.error("Invalid start or end date.");
return;
}
event.setProp("title", this.updatedTitle);
event.setProp("backgroundColor", this.updatedColor);
event.setStart(updatedStart);
event.setEnd(updatedEnd);
this.updateModalShow = false;
this.updatedTitle = "";
this.updatedColor = "";
this.selectedEvent = {
id: "",
title: "",
color: "",
start: "",
end: "",
allDay: true,
};
}
},
deleteEvent() {
const calendarApi = (this.$refs.fullCalendar as InstanceType<typeof FullCalendar>).getApi();
const event = calendarApi.getEventById(this.selectedEvent.id);
if (event) {
event.remove();
this.updateModalShow = false;
}
},
selectColor(color: string, isAddModal: boolean) {
if (isAddModal) {
this.newEvent.color = color;
this.activeColor.newEvent = color; // Set the active color for add modal
} else {
this.updatedColor = color;
this.activeColor.updateEvent = color; // Set the active color for update modal
}
},
},
});
</script>
<template>
<v-card elevation="10">
<v-card-item>
<div class="demo-app">
<div class="demo-app-main">
<FullCalendar
ref="fullCalendar"
class="demo-app-calendar rounded-md"
:options="calendarOptions"
/>
<!-- Add Event Modal -->
<v-dialog v-model="addModalShow" max-width="500px">
<v-card>
<v-card-text>
<div class="mb-6 d-flex justify-space-between">
<div>
<h4 class="text-h4 mb-2">Add Event</h4>
<p class="text-muted">
Fill in the title, choose the event color, and select the
start and end dates to add an event.
</p>
</div>
<v-btn
icon="mdi-close"
variant="text"
class="mt-n2 me-n3"
@click="addModalShow = false"
></v-btn>
</div>
<!-- Event Title -->
<v-label class="mb-2 font-weight-medium">Event Title</v-label>
<v-text-field v-model="newEvent.title" outlined required />
<!-- Start Date -->
<v-label class="mb-2 font-weight-medium">Start Date</v-label>
<v-text-field
v-model="newEvent.start"
variant="outlined"
hide-details
type="date"
class="mb-5"
required
/>
<!-- End Date -->
<v-label class="mb-2 font-weight-medium">End Date</v-label>
<v-text-field
v-model="newEvent.end"
variant="outlined"
hide-details
type="date"
class="mb-5"
required
/>
<!-- Event Color -->
<v-label class="mb-2 font-weight-medium">Event Color</v-label>
<v-list class="d-flex ga-3 pa-0">
<v-list-item
class="px-0 py-0"
:ripple="false"
v-for="option in colorOptions"
:key="option.id"
@click="selectColor(option.value, true)"
>
<div
class="round-30 rounded-circle d-flex justify-center align-center"
:style="{
backgroundColor: option.value,
}"
>
<CheckIcon
size="18"
color="#fff"
v-if="activeColor.newEvent === option.value"
/>
</div>
</v-list-item>
</v-list>
<!-- Add Event Button -->
<v-btn @click="addEvent" color="primary" class="mt-6"
>Add Event</v-btn
>
</v-card-text>
</v-card>
</v-dialog>
<!-- Update Event Modal -->
<!-- Update Event Modal -->
<v-dialog v-model="updateModalShow" max-width="500px">
<v-card>
<v-card-text>
<div class="mb-6 d-flex justify-space-between">
<div>
<h4 class="text-h4 mb-2">Update Event</h4>
<p class="text-muted">
To add Event kindly fill up the title and choose the event
color and press the add button
</p>
</div>
<v-btn
icon="mdi-close"
variant="text"
class="mt-n2 me-n3"
@click="updateModalShow = false"
></v-btn>
</div>
<v-label class="mb-2 font-weight-medium">Event Title </v-label>
<v-text-field v-model="updatedTitle" outlined required />
<!-- Start Date -->
<v-label class="mb-2 font-weight-medium">Start Date</v-label>
<v-text-field
v-model="selectedEvent.start"
variant="outlined"
hide-details
type="date"
required
class="mb-5"
/>
<!-- End Date -->
<v-label class="mb-2 font-weight-medium">End Date</v-label>
<v-text-field
v-model="selectedEvent.end"
variant="outlined"
hide-details
type="date"
class="mb-5"
required
/>
<v-label class="mb-2 font-weight-medium">Event Color </v-label>
<v-list class="d-flex ga-3 pa-0">
<v-list-item
class="px-0 py-0"
:ripple="false"
v-for="option in colorOptions"
:key="option.id"
@click="selectColor(option.value, false)"
>
<div
class="round-30 rounded-circle d-flex justify-center align-center"
:style="{ backgroundColor: option.value }"
>
<CheckIcon
size="18"
color="#fff"
v-if="activeColor.updateEvent === option.value"
/>
</div>
</v-list-item>
</v-list>
<v-btn @click="updateEvent" color="primary" class="mt-6">
Update Event
</v-btn>
<v-btn @click="deleteEvent" color="error" class="mt-6 ms-4">
Delete Event
</v-btn>
</v-card-text>
</v-card>
</v-dialog>
</div>
</div>
</v-card-item>
</v-card>
</template>