Add pagination
This commit is contained in:
parent
678f068c9c
commit
1f7f70a459
|
@ -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>
|
|
@ -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();
|
||||
|
|
|
@ -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>
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue