Fix Calendar View style and add features

- create ICSCalendar component
- create ICSAgenda component (for mobile view)
- temporary add rotes.potsda.mn ics feed for testing
This commit is contained in:
summersamara 2023-12-19 01:23:41 +01:00
parent 69717f26f3
commit 4ceee2efc7
3 changed files with 155 additions and 3 deletions

View file

@ -0,0 +1,137 @@
<template>
<FullCalendar :options="calendarOptions" class="agenda-view" />
<div v-if="listOfEventsByDate.date" class="my-4">
<b v-text="formatDateString(listOfEventsByDate.date)" />
<div v-for="(event, index) in listOfEventsByDate.events" v-bind:key="index">
<a :href="event.event.url">
<div
class="text-violet-3 dark:text-white bg-mbz-yellow dark:bg-mbz-purple my-2 p-2 rounded"
>
<div class="mb-1">
<Clock class="clock-icon" />
<b class="ml-1 time">
{{ formatTimeString(event.event.startStr, undefined) }}
{{
event.event.endStr
? "- " + formatTimeString(event.event.endStr, undefined)
: ""
}}
</b>
</div>
<span class="font-bold line-clamp-4">
{{ event.event.title }}
</span>
<div class="mt-1">
<small>
{{
t("Organized by {name}", {
name: event.event.extendedProps.organizer,
})
}}
</small>
</div>
</div>
</a>
</div>
</div>
</template>
<script lang="ts" setup>
import { useI18n } from "vue-i18n";
import { locale } from "@/utils/i18n";
import { computed, ref } from "vue";
import Clock from "vue-material-design-icons/ClockTimeTenOutline.vue";
import FullCalendar from "@fullcalendar/vue3";
import dayGridPlugin from "@fullcalendar/daygrid";
import iCalendarPlugin from "@fullcalendar/icalendar";
import interactionPlugin from "@fullcalendar/interaction";
import { formatDateString, formatTimeString } from "@/filters/datetime";
const props = defineProps<{
icsFeedUrl: string;
}>();
const { t } = useI18n({ useScope: "global" });
const listOfEventsByDate = ref<{ events: object[]; date?: string }>({
events: [],
date: undefined,
});
const calendarOptions = computed((): object => {
return {
plugins: [dayGridPlugin, iCalendarPlugin, interactionPlugin],
initialView: "dayGridMonth",
events: {
url: props.icsFeedUrl,
format: "ics",
},
nextDayThreshold: "09:00:00",
dayMaxEventRows: 0,
moreLinkClassNames: "bg-mbz-yellow dark:bg-mbz-purple dark:text-white p-2",
moreLinkContent: (arg: { num: number; text: string }) => {
return "+" + arg.num.toString();
},
moreLinkClick: (info: {
date: Date;
allSegs: object[];
hiddenSegs: [];
jsEvent: object;
}) => {
listOfEventsByDate.value = {
events: info.allSegs,
date: info.date.toISOString(),
};
return "none";
},
dateClick: (info: { dateStr: string }) => {
const moreLinkElement = document.querySelectorAll(
`td[data-date='${info.dateStr}'] a.fc-more-link`
)[0] as undefined | HTMLElement;
moreLinkElement?.click();
},
contentHeight: 350,
eventClassNames: "line-clamp-3 bg-mbz-yellow dark:bg-mbz-purple",
headerToolbar: {
left: "prev,next,today",
center: "",
right: "title",
},
locale: locale,
firstDay: 1,
buttonText: {
today: t("Today"),
month: t("Month"),
week: t("Week"),
day: t("Day"),
list: t("List"),
},
};
});
</script>
<style>
.agenda-view .fc-button {
font-size: 0.8rem !important;
}
.agenda-view .fc-toolbar-title {
font-size: 1rem !important;
}
.agenda-view .fc-daygrid-day-events {
min-height: 1.1rem !important;
}
.clock-icon {
display: inline-block;
vertical-align: middle;
}
.time {
font-size: 0.95rem !important;
}
</style>

View file

@ -31,6 +31,11 @@ const calendarOptions = computed((): object => {
url: props.icsFeedUrl, url: props.icsFeedUrl,
format: "ics", format: "ics",
}, },
nextDayThreshold: "09:00:00",
moreLinkClassNames: "bg-mbz-yellow dark:bg-mbz-purple dark:text-white p-2",
moreLinkContent: (arg: { num: number; text: string }) => {
return "+" + arg.num.toString();
},
eventClassNames: "line-clamp-3 bg-mbz-yellow dark:bg-mbz-purple", eventClassNames: "line-clamp-3 bg-mbz-yellow dark:bg-mbz-purple",
headerToolbar: { headerToolbar: {
left: "prev,next,today", left: "prev,next,today",

View file

@ -1,17 +1,27 @@
<template> <template>
<div class="container mx-auto px-1 mb-6"> <div class="container mx-auto px-1 mb-6">
<h1> <h1 v-if="!isMobile">
{{ t("Calendar") }} {{ t("Calendar") }}
</h1> </h1>
<div class="p-2"> <div class="p-2">
<FullCalendar ics-feed-url="/feed/instance/ics" /> <ICSCalendar
v-if="!isMobile"
ics-feed-url="https://rotes.potsda.mn/feed/instance/ics"
/>
<ICSAgenda
v-else
ics-feed-url="https://rotes.potsda.mn/feed/instance/ics"
/>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import FullCalendar from "@/components/FullCalendar.vue"; import ICSCalendar from "@/components/FullCalendar/ICSCalendar.vue";
import ICSAgenda from "@/components/FullCalendar/ICSAgenda.vue";
const { t } = useI18n({ useScope: "global" }); const { t } = useI18n({ useScope: "global" });
const isMobile = window.innerWidth < 760;
</script> </script>