flaschengeist-schedule/src/components/overview/ListView.vue

188 lines
4.9 KiB
Vue

<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>
<div class="q-pa-md">
<q-card style="height: 70vh; max-width: 1800px" class="q-pa-md">
<div class="scroll" ref="scrollDiv" style="height: 100%">
<q-infinite-scroll :offset="250" @load="load">
<q-list>
<q-item id="bbb">
<q-btn label="Ältere Veranstaltungen laden" @click="load(-1)" />
</q-item>
<template v-for="(events, index) in agendas" :key="index">
<q-separator />
<q-item-label overline>{{ index }}</q-item-label>
<q-item v-for="(event, idx) in events" :key="idx"
><event-slot :model-value="event" />{{ idx }}</q-item
>
</template>
</q-list>
<template #loading>
<div class="row justify-center q-my-md">
<q-spinner-dots color="primary" size="40px" />
</div>
</template>
</q-infinite-scroll>
</div>
</q-card>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, onBeforeMount, ref } from 'vue';
import { useEventStore } from '../../store';
import { date } from 'quasar';
import EditEvent from '../management/EditEvent.vue';
import EventSlot from '../overview/slots/EventSlot.vue';
export default defineComponent({
name: 'ListView',
components: { EditEvent, EventSlot },
setup() {
interface Agendas {
[index: string]: FG.Event[];
}
const store = useEventStore();
const editor = ref<FG.Event | undefined>(undefined);
const events = ref<FG.Event[]>([]);
const scrollDiv = ref<Element>();
const agendas = computed<Agendas>(() => {
const ag = {} as Agendas;
events.value?.forEach((event) => {
const day = date.formatDate(event.start, 'YYYYMMDD');
if (!ag[day]) {
ag[day] = [];
}
ag[day].push(event);
});
return ag;
});
onBeforeMount(async () => {
//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 load(index: number, done?: (stop: boolean) => void) {
const start = new Date();
if (index < 0) {
const { result } = await store.getEvents({ to: start, limit: 5, descending: true });
events.value.unshift(...result);
if (done) done(false);
} else {
const len = events.value.length;
const { result } = await store.getEvents({
from: start,
offset: (index - 1) * 10,
limit: 10,
});
if (len == events.value.push(...result)) {
if (done) return done(true);
} else if (done) done(false);
}
if (index <= 1) {
window.setTimeout(() => {
(<Element>scrollDiv.value).scrollTop = document.getElementById('bbb')?.scrollHeight || 0;
}, 150);
}
}
async function remove(id: number) {
if (await store.removeEvent(id)) {
// Successfull removed
for (const idx in agendas.value) {
const i = agendas.value[idx].findIndex((event) => event.id === id);
if (i !== -1) {
agendas.value[idx].splice(i, 1);
break;
}
}
} else {
// Not found, this means our eventa are outdated
}
}
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 {
agendas,
asYear,
asMonth,
edit,
editor,
scrollDiv,
editDone,
load,
remove,
};
},
});
</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>