<template> <q-dialog :model-value="editor !== undefined" persistent transition-show="scale" transition-hide="scale" > <q-card> <div class="column"> <div class="col" align="right" style="position: sticky; top: 0; z-index: 999"> <q-btn round color="negative" icon="close" dense rounded @click="editDone(false)" /> </div> <div class="col" style="margin: 0; padding: 0; margin-top: -2.4em"> <edit-event v-model="editor" @done="editDone" /> </div> </div> </q-card> </q-dialog> <q-page padding> <q-card> <div style="max-width: 1800px; width: 100%"> <div class="bg-primary text-white q-my-sm shadow-2 row justify-center"> <div class="col-xs-12 col-sm-9 row justify-center items-center"> <q-btn flat dense icon="mdi-chevron-left" title="previous" @click="calendarPrev" /> <q-separator vertical /> <q-btn flat dense >{{ asMonth(selectedDate) }} {{ asYear(selectedDate) }} <q-popup-proxy transition-show="scale" transition-hide="scale" @before-show="updateProxy" > <q-date v-model="proxyDate"> <div class="row items-center justify-end q-gutter-sm"> <q-btn v-close-popup label="Cancel" color="primary" flat /> <q-btn v-close-popup label="OK" color="primary" flat @click="saveNewSelectedDate" /> </div> </q-date> </q-popup-proxy> </q-btn> <q-separator vertical /> <q-btn flat dense icon="mdi-chevron-right" title="next" @click="calendarNext" /> </div> <div class="col-xs-12 col-sm-3 text-center"> <q-btn-toggle v-model="calendarView" flat stretch toggle-color="black" :options="[ { label: 'Tag', value: 'day' }, { label: 'Woche', value: 'week' }, ]" /> </div> </div> <q-calendar-agenda v-model="selectedDate" :view="calendarRealView" :max-days="calendarDays" :weekdays="[1, 2, 3, 4, 5, 6, 0]" locale="de-de" style="height: 100%; min-height: 400px" > <template #head-day-label="{scope: {timestamp}}"> {{timestamp.day}} <q-menu> <q-list style="min-width: 100px"> <q-item exact :to="{name: 'new-event', query: {date: timestamp.date}}"> <q-item-section>Neue Veranstaltung</q-item-section> </q-item> </q-list> </q-menu> </template> <template #day="{ scope: { timestamp } }"> <div itemref="" class="q-pb-sm" style="min-height: 200px"> <eventslot v-for="(agenda, index) in events[timestamp.weekday]" :key="index" v-model="events[timestamp.weekday][index]" @remove-event="remove" @edit-event="edit" /> </div> </template> </q-calendar-agenda> </div> </q-card> </q-page> </template> <script lang="ts"> import { ComponentPublicInstance, computed, defineComponent, onBeforeMount, ref } from 'vue'; import { useScheduleStore } from '../../store'; import Eventslot from './slots/EventSlot.vue'; import { date } from 'quasar'; import { startOfWeek } from '@flaschengeist/api'; import EditEvent from '../management/EditEvent.vue'; import { QCalendarAgenda } from '@quasar/quasar-ui-qcalendar'; export default defineComponent({ name: 'AgendaView', components: { Eventslot, EditEvent, QCalendarAgenda: <ComponentPublicInstance>QCalendarAgenda }, setup() { const store = useScheduleStore(); const windowWidth = ref(window.innerWidth); const selectedDate = ref(date.formatDate(new Date(), 'YYYY-MM-DD')); const proxyDate = ref(''); const calendarView = ref('week'); const calendarRealView = computed(() => (calendarDays.value != 7 ? 'day' : 'week')); const calendarDays = computed(() => // <= 1023 is the breakpoint for sm to md calendarView.value == 'day' ? 1 : windowWidth.value <= 1023 ? 3 : 7 ); const events = ref<Agendas>({}); const editor = ref<FG.Event | undefined>(undefined); interface Agendas { [index: number]: FG.Event[]; } onBeforeMount(async () => { window.addEventListener('resize', () => { windowWidth.value = window.innerWidth; }); await loadAgendas(); }); async function edit(id: number) { editor.value = await store.getEvent(id); } function editDone(changed: boolean) { if (changed) void loadAgendas(); editor.value = undefined; } async function remove(id: number) { if (await store.removeEvent(id)) { // Successfull removed for (const idx in events.value) { const i = events.value[idx].findIndex((event) => event.id === id); if (i !== -1) { events.value[idx].splice(i, 1); break; } } } else { // Not found, this means our eventa are outdated await loadAgendas(); } } async function loadAgendas() { const selected = new Date(selectedDate.value); console.log(selected); const start = calendarRealView.value === 'day' ? selected : startOfWeek(selected); const end = date.addToDate(start, { days: calendarDays.value }); events.value = {}; const list = await store.getEvents({ from: start, to: end }); list.forEach((event) => { const day = event.start.getDay(); if (!events.value[day]) { events.value[day] = []; } events.value[day].push(event); }); } function calendarNext() { selectedDate.value = date.formatDate( date.addToDate(selectedDate.value, { days: calendarDays.value }), 'YYYY-MM-DD' ); void loadAgendas(); } function calendarPrev() { selectedDate.value = date.formatDate( date.subtractFromDate(selectedDate.value, { days: calendarDays.value }), 'YYYY-MM-DD' ); void loadAgendas(); } function updateProxy() { proxyDate.value = selectedDate.value; } function saveNewSelectedDate() { proxyDate.value = date.formatDate(proxyDate.value, 'YYYY-MM-DD'); selectedDate.value = proxyDate.value; } function asMonth(value: string) { if (value) { return date.formatDate(new Date(value), 'MMMM', { months: [ 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember', ], }); } } function asYear(value: string) { if (value) { return date.formatDate(new Date(value), 'YYYY'); } } return { asYear, asMonth, selectedDate, edit, editor, editDone, events, calendarNext, calendarPrev, updateProxy, saveNewSelectedDate, proxyDate, remove, calendarDays, calendarView, calendarRealView, }; }, }); </script> <style> @import '@quasar/quasar-ui-qcalendar/dist/index.css'; /* Fill full height of card */ .q-calendar-agenda__pane { height: 100%; } /* Same as Qcard */ .q-calendar { --calendar-background-dark: --q-dark; } </style>