Add pagination

This commit is contained in:
philipp lang 2024-02-29 22:44:48 +01:00
parent 678f068c9c
commit 1f7f70a459
4 changed files with 91 additions and 5 deletions

View File

@ -0,0 +1,72 @@
<template>
<div class="flex flex-col md:flex-row justify-between items-center space-y-3 md:space-y-0">
<div class="text-sm text-gray-600" v-text="desc"></div>
<div v-if="modelValue.last_page > 1" class="items-center flex space-x-2">
<div class="hidden sm:flex text-gray-600 text-sm" v-text="pages"></div>
<button
v-if="modelValue.current_page !== 1"
href="#"
class="rounded !ml-0 sm:!ml-2 flex w-6 h-6 items-center justify-center leading-none shadow bg-blue-700 hover:bg-blue-600 items-center justify-center"
@click.prevent="goto(modelValue.current_page - 1)"
>
<chevron class="rotate-90 text-white w-2 h-2"></chevron>
</button>
<button
v-for="(button, index) in pageButtons"
:key="index"
href="#"
class="rounded text-sm w-6 h-6 text-white flex items-center justify-center leading-none shadow"
:class="{'bg-blue-500': button.current, 'bg-blue-700 hover:bg-blue-600': !button.current}"
@click.prevent="goto(button.page)"
v-text="button.page"
></button>
<button
v-if="modelValue.current_page !== modelValue.last_page"
href="#"
class="flex rounded text-sm w-6 h-6 items-center justify-center leading-none shadow bg-blue-700 hover:bg-blue-600 items-center justify-center"
@click.prevent="goto(modelValue.current_page + 1)"
>
<chevron class="-rotate-90 text-white w-2 h-2"></chevron>
</button>
</div>
</div>
</template>
<script setup>
import {computed} from 'vue';
import Chevron from './icons/Chevron.vue';
const emits = defineEmits(['reload']);
const props = defineProps({
modelValue: {
required: true,
},
});
function goto(page) {
if (page === props.modelValue.current_page) {
return;
}
emits('reload', page);
}
const pageButtons = computed(() => {
var from = Math.max(1, props.modelValue.current_page - 2);
var to = Math.min(props.modelValue.last_page, props.modelValue.current_page + 2);
return Array(to + 1)
.fill(0)
.map((index, key) => key)
.slice(from)
.map((page) => {
return {
page: page,
current: page === props.modelValue.current_page,
};
});
});
const pages = computed(() => `Seite ${props.modelValue.current_page} von ${props.modelValue.last_page}`);
const desc = computed(() => `${props.modelValue.from} - ${props.modelValue.to} von ${props.modelValue.total} Einträgen`);
</script>

View File

@ -50,10 +50,13 @@
</div>
<div class="relative min-h-48">
<div class="relative" v-for="member in searchResults" :id="member.id" v-if="!searching">
{{ member.name }}
<div class="relative grid grid-cols-[repeat(auto-fit,minmax(200px,1fr))] gap-2 mt-2">
<div v-for="member in searchResults.data" :id="member.id">
{{ member.name }}
</div>
</div>
<div class="absolute flex h-full w-full justify-center items-center opacity-80" v-if="searching">
<pagination class="mt-5" :model-value="searchResults" @reload="searchForMember($event)" v-if="searchResults.current_page"></pagination>
<div class="absolute flex h-full w-full top-0 left-0 justify-center items-center backdrop-blur-sm" v-if="searching">
<spinner class="w-20 h-20"></spinner>
</div>
</div>
@ -100,6 +103,7 @@ import VBtn from '../VBtn.vue';
import Spinner from '../Spinner.vue';
import useAdremaLogin from '../../composables/useAdremaLogin.js';
import useEventMeta from '../../composables/useEventMeta.js';
import Pagination from '../Pagination.vue';
const eventMeta = useEventMeta();
const {login, logout, user, loginData, searchData, searchForMember, resetSearchData, searchResults, searching} = useAdremaLogin();

View File

@ -0,0 +1,9 @@
<template>
<svg height="223.651" viewBox="0 0 105.911 55.913" width="423.642" xmlns="http://www.w3.org/2000/svg">
<path
d="M0 4.66a4.57 4.57 0 0 1 1.41-3.295c1.882-1.82 4.928-1.82 6.808 0l44.737 43.3 44.738-43.3c1.881-1.82 4.927-1.82 6.807 0a4.552 4.552 0 0 1 0 6.589L56.36 54.547c-1.881 1.82-4.927 1.82-6.807 0L1.41 7.954A4.57 4.57 0 0 1 0 4.66Z"
style="stroke-width: 1.18403"
fill="currentColor"
/>
</svg>
</template>

View File

@ -48,20 +48,21 @@ export default function useAdremaLogin() {
loginToken.value = null;
}
const searchForMember = debounce(async function () {
const searchForMember = debounce(async function (page = 1) {
searching.value = true;
const response = await axios.post(
'/remote/nami/search',
{
...searchData.value,
untergliederungId: searchData.value.untergliederungId ? [searchData.value.untergliederungId] : [],
page: page,
},
{
headers: {'X-Adrema-Token': loginToken.value.token},
},
);
searchResults.value = response.data.data;
searchResults.value = response.data;
searching.value = false;
}, 500);