<template> <div v-if="data?.lookup.date_list" class="flex flex-row justify-between w-full max-w-4xl mx-auto"> <svg viewBox="0 0 24 24" class="h-5 w-5 cursor-pointer fill-none stroke-2 stroke-black" :class="allowLeft ? '' : 'pointer-events-none opacity-75'" @click="changeTimedData(allowLeft ?? 0)" > <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" /> </svg> <h1>{{ activeYear }}</h1> <svg viewBox="0 0 24 24" class="h-5 w-5 cursor-pointer fill-none stroke-2 stroke-black" :class="allowRight ? '' : 'pointer-events-none opacity-75'" @click="changeTimedData(allowRight ?? 0)" > <path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" /> </svg> </div> <div class="flex gap-2 w-full max-w-4xl mx-auto" :class="data?.lookup.image_item ? 'flex-row flex-wrap justify-center' : ' flex-col'" > <div v-for="(item, index) in collection" :key="item.slug" class="contents"> <p v-if="data?.lookup.date_list && data?.lookup.numbered_item == false && getDate(index) != ''" class="w-full text-center" > {{ getDate(index) }} </p> <BaseListImageItem v-if="data?.lookup.image_item" :data="item" :number-overwrite="data.lookup.numbered_item ? getNumber(index) : undefined" :allow-navigation="data.enable_detail" /> <BaseListItem v-else-if="data?.lookup" :data="item" :number-overwrite="data.lookup.numbered_item ? getNumber(index) : undefined" :allow-navigation="data.enable_detail" /> </div> </div> <div v-if="pagination.pageCount > 1" class="flex flex-row w-full max-w-4xl mx-auto justify-between items-center select-none pt-4" > <p class="text-sm font-normal text-gray-500"> Elemente <span class="font-semibold text-gray-900">{{ showingText }}</span> von <span class="font-semibold text-gray-900">{{ entryCount }}</span> </p> <ul class="flex flex-row text-sm h-8"> <li class="flex h-8 w-8 items-center justify-center text-gray-500 bg-white border border-gray-300 first:rounded-s-lg last:rounded-e-lg" :class="[ currentPage > 1 ? 'cursor-pointer hover:bg-gray-100 hover:text-gray-700' : 'opacity-50 pointer-events-none', ]" @click="changeTimedPage(currentPage - 1)" > <svg viewBox="0 0 24 24" class="h-5 w-4 cursor-pointer fill-none stroke-2 stroke-black"> <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" /> </svg> </li> <li v-for="page in displayedPagesNumbers" :key="page" class="flex h-8 w-8 items-center justify-center text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 first:rounded-s-lg last:rounded-e-lg" :class="[currentPage - 1 == page ? 'font-bold border-primary' : '', page != '.' ? ' cursor-pointer' : '']" @click="changeTimedPage(page)" > {{ typeof page == "number" ? page + 1 : "..." }} </li> <li class="flex h-8 w-8 items-center justify-center text-gray-500 bg-white border border-gray-300 first:rounded-s-lg last:rounded-e-lg" :class="[ currentPage < pagination.pageCount ? 'cursor-pointer hover:bg-gray-100 hover:text-gray-700' : 'opacity-50 pointer-events-none', ]" @click="changeTimedPage(currentPage + 1)" > <svg viewBox="0 0 24 24" class="h-4 w-4 cursor-pointer fill-none stroke-2 stroke-black"> <path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" /> </svg> </li> </ul> </div> </template> <script setup lang="ts"> import type { PropType } from "vue"; import type SharedList from "../../types/component/sharedList"; import type BaseCollection from "~/types/collection/baseCollection"; interface Meta { page: number; pageSize: number; pageCount: number; total: number; } const runtimeConfig = useRuntimeConfig(); const baseUrl = runtimeConfig.public.strapi.url; const { find } = useStrapi(); const props = defineProps({ data: Object as PropType<SharedList>, }); const collection = ref<Array<BaseCollection> | undefined>(); const years = ref<Array<number>>([]); const pagination = ref<Meta>({ page: 0, pageSize: 0, pageCount: 0, total: 0 }); const activeYear = ref<number>(0); if (props.data?.lookup.date_list) { const { data: year } = await useAsyncData<Array<number>>("distinct-years", () => $fetch(`${baseUrl}/api/custom/${props.data?.lookup.collection}/distinct-years`) ); years.value = year.value ?? []; activeYear.value = years.value[0] ?? 0; } const { data: collections } = await useAsyncData("collection", () => find<BaseCollection>(props.data?.lookup.collection ?? "", { ...(props.data?.lookup?.date_list ? { sort: "date:desc", filters: { date: { $between: [`${activeYear.value}-01-01 00:00:00.000000`, `${activeYear.value}-12-31 23:59:59.999`], }, }, pagination: { page: 1, pageSize: 10, withCount: true, }, } : { pagination: { page: 1, pageSize: 10, withCount: true, }, }), }) ); collection.value = collections.value?.data; pagination.value = (collections.value?.meta.pagination as unknown as { page: number; pageSize: number; pageCount: number; total: number; }) ?? { page: 0, pageSize: 0, pageCount: 0, total: 0, }; const numberOffset = computed(() => { return (pagination.value.page - 1) * pagination.value.pageSize; }); const allowRight = computed<number | undefined>(() => { return years.value.filter((y) => y < activeYear.value).sort((a, b) => b - a)[0]; }); const allowLeft = computed(() => { return years.value.filter((y) => y > activeYear.value).sort((a, b) => a - b)[0]; }); const currentPage = computed(() => pagination.value.page); const entryCount = computed(() => pagination.value.total); const showingStart = computed(() => (currentPage.value - 1) * pagination.value.pageSize); const showingEnd = computed(() => { let max = (currentPage.value - 1) * pagination.value.pageSize + pagination.value.pageSize; if (max > entryCount.value) max = entryCount.value; return max; }); const showingText = computed(() => `${entryCount.value != 0 ? showingStart.value + 1 : 0} - ${showingEnd.value}`); const displayedPagesNumbers = computed(() => { let stateOfPush = false; return [...new Array(pagination.value.pageCount)].reduce((acc, curr, index) => { if ( index <= 1 || index >= pagination.value.pageCount - 2 || (currentPage.value - 1 <= index && index <= currentPage.value + 1) ) { acc.push(index); stateOfPush = false; return acc; } if (stateOfPush == true) return acc; acc.push("."); stateOfPush = true; return acc; }, []); }); function getNumber(index: number): number { if (props.data?.lookup.inverse_count) { return pagination.value.total - numberOffset.value - index; } else { return numberOffset.value + index + 1; } } function getDate(index: number): string { let thisElement = collection.value?.[index]; let beforeElement = collection.value?.[index - 1]; if (thisElement && beforeElement) { let thisElementDate = new Date(thisElement.date ?? "").toLocaleDateString("de", { month: "long" }); let beforeElementDate = new Date(beforeElement.date ?? "").toLocaleDateString("de", { month: "long" }); if (thisElementDate == beforeElementDate) return ""; else return thisElementDate; } else if (thisElement) { return new Date(thisElement.date ?? "").toLocaleDateString("de", { month: "long" }); } else return ""; } async function changeTimedData(year: number) { activeYear.value = year; const data = await find<BaseCollection>(props.data?.lookup.collection ?? "", { sort: "date:desc", filters: { date: { $between: [`${activeYear.value}-01-01 00:00:00.000000`, `${activeYear.value}-12-31 23:59:59.999`], }, }, pagination: { page: 1, pageSize: 10, withCount: true, }, }); console.log(data); collection.value = data?.data; pagination.value = (data?.meta.pagination as unknown as { page: number; pageSize: number; pageCount: number; total: number; }) ?? { page: 0, pageSize: 0, pageCount: 0, total: 0, }; } async function changeTimedPage(page: number = 1) { const data = await find<BaseCollection>(props.data?.lookup.collection ?? "", { sort: "date:desc", filters: { date: { $between: [`${activeYear.value}-01-01 00:00:00.000000`, `${activeYear.value}-12-31 23:59:59.999`], }, }, pagination: { page, pageSize: 10, withCount: true, }, }); collection.value = data?.data; pagination.value = (data?.meta.pagination as unknown as { page: number; pageSize: number; pageCount: number; total: number; }) ?? { page: 0, pageSize: 0, pageCount: 0, total: 0, }; } </script>