extend calendar by list
This commit is contained in:
parent
303ce7a58d
commit
1296331796
6 changed files with 198 additions and 152 deletions
170
src/components/CustomCalendar.vue
Normal file
170
src/components/CustomCalendar.vue
Normal file
|
@ -0,0 +1,170 @@
|
|||
<template>
|
||||
<div class="flex flex-col w-full h-full gap-2 justify-between overflow-hidden">
|
||||
<div class="flex flex-row gap-2 max-xl:flex-wrap justify-between max-sm:justify-center">
|
||||
<div class="flex flex-row max-xl:order-2">
|
||||
<button
|
||||
:primary="view == 'dayGridMonth'"
|
||||
:primary-outline="view != 'dayGridMonth'"
|
||||
class="rounded-r-none!"
|
||||
@click="setView('dayGridMonth')"
|
||||
>
|
||||
Monat
|
||||
</button>
|
||||
<button
|
||||
:primary="view == 'timeGridWeek'"
|
||||
:primary-outline="view != 'timeGridWeek'"
|
||||
class="rounded-none! border-x-0!"
|
||||
@click="setView('timeGridWeek')"
|
||||
>
|
||||
Woche
|
||||
</button>
|
||||
<button
|
||||
:primary="view == 'listMonth'"
|
||||
:primary-outline="view != 'listMonth'"
|
||||
class="rounded-l-none!"
|
||||
@click="setView('listMonth')"
|
||||
>
|
||||
Liste
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-3xl w-full max-xl:order-1 text-center">{{ currentTitle }}</p>
|
||||
<div class="flex flex-row max-xl:order-3">
|
||||
<button primary-outline class="rounded-r-none!" @click="navigateView('prev')">
|
||||
<ChevronLeftIcon />
|
||||
</button>
|
||||
<button
|
||||
:primary="containsToday"
|
||||
:primary-outline="!containsToday"
|
||||
class="rounded-none! border-x-0!"
|
||||
@click="
|
||||
calendarApi?.today();
|
||||
containsToday = true;
|
||||
"
|
||||
>
|
||||
heute
|
||||
</button>
|
||||
<button primary-outline class="rounded-l-none!" @click="navigateView('next')">
|
||||
<ChevronRightIcon />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<FullCalendar ref="fullCalendar" :options="calendarOptions" class="max-h-full h-full" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineComponent, type PropType } from "vue";
|
||||
import FullCalendar from "@fullcalendar/vue3";
|
||||
import deLocale from "@fullcalendar/core/locales/de";
|
||||
import dayGridPlugin from "@fullcalendar/daygrid";
|
||||
import timeGridPlugin from "@fullcalendar/timegrid";
|
||||
import listPlugin from "@fullcalendar/list";
|
||||
import interactionPlugin from "@fullcalendar/interaction";
|
||||
import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/vue/24/outline";
|
||||
import type { CalendarOptions } from "@fullcalendar/core/index.js";
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineComponent({
|
||||
props: {
|
||||
items: {
|
||||
type: Array as PropType<
|
||||
{
|
||||
id: string;
|
||||
title: string;
|
||||
start: string;
|
||||
end: string;
|
||||
backgroundColor: string;
|
||||
}[]
|
||||
>,
|
||||
default: [],
|
||||
},
|
||||
allowInteraction: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
emits: {
|
||||
dateSelect: ({ start, end, allDay }: { start: string; end: string; allDay: boolean }) => {
|
||||
return typeof start == "string" && typeof end == "string" && typeof allDay === "boolean";
|
||||
},
|
||||
eventSelect: (id: string) => {
|
||||
return typeof id == "string";
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
view: "dayGridMonth" as "dayGridMonth" | "timeGridWeek" | "listMonth",
|
||||
calendarApi: null as null | typeof FullCalendar,
|
||||
currentTitle: "" as string,
|
||||
containsToday: false as boolean,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
calendarOptions() {
|
||||
return {
|
||||
timeZone: "local",
|
||||
locale: deLocale,
|
||||
plugins: [dayGridPlugin, timeGridPlugin, listPlugin, interactionPlugin],
|
||||
initialView: "dayGridMonth",
|
||||
eventDisplay: "block",
|
||||
headerToolbar: false,
|
||||
weekends: true,
|
||||
editable: this.allowInteraction,
|
||||
selectable: this.allowInteraction,
|
||||
selectMirror: false,
|
||||
dayMaxEvents: true,
|
||||
weekNumbers: true,
|
||||
displayEventTime: true,
|
||||
nowIndicator: true,
|
||||
weekText: "KW",
|
||||
allDaySlot: false,
|
||||
events: this.items,
|
||||
select: this.select,
|
||||
eventClick: this.eventClick,
|
||||
} as CalendarOptions;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.calendarApi = (this.$refs.fullCalendar as typeof FullCalendar).getApi();
|
||||
this.setTitle();
|
||||
this.setContainsToday();
|
||||
},
|
||||
methods: {
|
||||
setTitle() {
|
||||
this.currentTitle = this.calendarApi?.view.title ?? "";
|
||||
},
|
||||
setView(view: "dayGridMonth" | "timeGridWeek" | "listMonth") {
|
||||
this.calendarApi?.changeView(view);
|
||||
this.view = view;
|
||||
this.setTitle();
|
||||
this.setContainsToday();
|
||||
},
|
||||
navigateView(change: "prev" | "next") {
|
||||
if (change == "prev") {
|
||||
this.calendarApi?.prev();
|
||||
} else {
|
||||
this.calendarApi?.next();
|
||||
}
|
||||
this.setTitle();
|
||||
this.setContainsToday();
|
||||
},
|
||||
setContainsToday() {
|
||||
const start = this.calendarApi?.view.currentStart;
|
||||
const end = this.calendarApi?.view.currentEnd;
|
||||
const today = new Date();
|
||||
this.containsToday = today >= start && today < end;
|
||||
},
|
||||
select(e: any) {
|
||||
this.$emit("dateSelect", {
|
||||
start: e?.startStr ?? new Date().toISOString(),
|
||||
end: e?.endStr ?? new Date().toISOString(),
|
||||
allDay: e?.allDay ?? false,
|
||||
});
|
||||
},
|
||||
eventClick(e: any) {
|
||||
this.$emit("eventSelect", e.event.id);
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue