vueJava/nuxt/components/data/pagination.vue

164 lines
3.5 KiB
Vue

<script setup lang="ts">
import 'tui-pagination/dist/tui-pagination.css';
import type { PaginationType } from '~/types/data/pagination';
import {
DoubleLeftOutlined,
DoubleRightOutlined,
LeftOutlined,
RightOutlined
} from '@ant-design/icons-vue';
const props = defineProps<PaginationType>();
const emit = defineEmits(['change']);
const totalPages = computed(() => Math.ceil(props.totalElements / props.size));
const rangePages = computed(() =>
Array.from({ length: totalPages.value }, (_, i) => i + 1)
);
const ranges = computed(() => {
const ranges: number[][] = [];
do {
ranges.push(rangePages.value.splice(0, props.showPaginationCount));
} while (rangePages.value.length !== 0);
if (ranges[0].length === 0) {
ranges[0][0] = 1;
}
return ranges;
});
const currentRange = computed(() => {
for (const range of ranges.value) {
if (range.some((i) => i === props.page)) {
return range;
}
}
return [];
});
const currentPeriod = computed(() => {
for (let i = 0; i < ranges.value.length; ++i) {
if (ranges.value[i].some((i) => i === props.page)) {
return i;
}
}
return -1;
});
const prevPageNumber = computed(() => {
const range = ranges.value[currentPeriod.value - 1];
if (range) {
return range[range.length - 1];
}
return props.page;
});
const nextPageNumber = computed(() => {
const range = ranges.value[currentPeriod.value + 1];
if (range) {
return range[0];
}
return props.page;
});
const firstPage = () => {
submitPage(1);
};
const prevPage = () => {
submitPage(prevPageNumber.value);
};
const nextPage = () => {
submitPage(nextPageNumber.value);
};
const lastPage = () => {
submitPage(totalPages.value ? totalPages.value : 1);
};
const change = (value) => {
if (props.size !== value) {
emit('change', props.page, value);
}
};
const movePage = (value) => {
submitPage(value);
};
const submitPage = (page: number) => {
if (props.page !== page) {
emit('change', page, props.size);
}
};
const options = [
{ label: '15', value: 15 },
{ label: '30', value: 30 },
{ label: '50', value: 50 },
{ label: '100', value: 100 }
];
</script>
<template>
<a-row justify="space-between" class="mt-5">
<a-col>
<a-space>
<a-select :options="options" :value="size" @change="change" />
<span>/페이지 ( {{ totalElements }})</span>
</a-space>
</a-col>
<a-col
><a-space>
<a-button
type="link"
:icon="h(DoubleLeftOutlined)"
size="small"
class="pagination-icon-size text-black"
@click="firstPage"
/>
<a-button
type="link"
:icon="h(LeftOutlined)"
class="pagination-icon-size text-black"
size="small"
@click="prevPage"
/>
<a-space>
<a-button
size="small"
:type="pageNo === page ? 'default' : `link`"
class="text-black"
v-for="pageNo in currentRange"
:key="`pagination-${pageNo}`"
@click="() => movePage(pageNo)"
>{{ pageNo }}</a-button
>
</a-space>
<a-button
type="link"
:icon="h(RightOutlined)"
size="small"
class="pagination-icon-size text-black"
@click="nextPage"
/>
<a-button
type="link"
:icon="h(DoubleRightOutlined)"
class="pagination-icon-size text-black"
size="small"
@click="lastPage"
/>
</a-space>
</a-col>
<a-col></a-col>
</a-row>
</template>