Files
web-temp/layers/components/blocks/Pagination.vue

147 lines
4.4 KiB
Vue

<script setup lang="ts">
interface Props {
totalCount: number
currentPage: number
pageSize: number
pageBlock?: number
useMinMax?: boolean
}
const props = withDefaults(defineProps<Props>(), {
currentPage: 1,
pageBlock: 10,
useMinMax: true,
})
const emits = defineEmits(['update:page'])
const currentPage = ref(props.currentPage)
const firstPage = ref(1)
const lastPage = computed(() => Math.ceil(props.totalCount / props.pageSize))
const prevPage = computed(() => currentPage.value - 1)
const nextPage = computed(() => currentPage.value + 1)
const currentBlock = computed(() =>
isShortThanBlock.value ? 1 : Math.ceil(currentPage.value / props.pageBlock)
)
// 블럭 크기가 전체 페이지 수보다 작은지 여부
const isShortThanBlock = computed(() => lastPage.value < props.pageBlock)
// 현재 블럭이 첫 블럭인지 여부
const isFirstBlock = computed(() => currentBlock.value === 1)
// 현재 블럭이 마지막 블럭인지 여부
const isLastBlock = computed(
() => currentBlock.value === Math.ceil(lastPage.value / props.pageBlock)
)
const lastBlock = computed(() =>
isShortThanBlock.value ? 1 : Math.ceil(lastPage.value / props.pageBlock)
)
const currentBlockFirstPage = computed(() =>
isShortThanBlock.value ? 1 : (currentBlock.value - 1) * props.pageBlock + 1
)
const blocks = computed(() => {
if (props.totalCount === 0) {
return []
}
const blockSize =
currentBlock.value === lastBlock.value &&
lastPage.value % props.pageBlock !== 0
? lastPage.value - currentBlockFirstPage.value + 1
: props.pageBlock
return Array.from(
{ length: blockSize },
(_, i) => currentBlockFirstPage.value + i
)
})
const handlePagination = (page: number) => {
currentPage.value = page
emits('update:page', page)
}
</script>
<template>
<div
v-if="props.totalCount > 0"
class="relative flex items-center justify-center w-full py-[32px]"
>
<template v-if="totalCount > pageSize">
<template v-if="props.useMinMax">
<button
type="button"
class="relative inline-flex items-center justify-center w-[32px] h-[32px]"
:disabled="currentPage === firstPage"
@click="handlePagination(firstPage)"
>
<AtomsIconsArrowDoubleLeftLine
:size="11"
:color="currentPage === firstPage ? '#CCCCCC' : '#333333'"
/>
</button>
</template>
<button
type="button"
class="relative inline-flex items-center justify-center w-[32px] h-[32px]"
:disabled="currentPage === firstPage"
@click="handlePagination(prevPage)"
>
<AtomsIconsArrowRightLine
:size="16"
:color="currentPage === firstPage ? '#CCCCCC' : '#333333'"
class="rotate-180"
/>
</button>
</template>
<ol class="relative inline-flex items-center justify-center">
<template v-for="page in blocks" :key="page">
<li
class="relative inline-flex items-center justify-center w-[32px] h-[32px]"
>
<AtomsButton
type="action"
size="size-small"
background-color="transparent"
text-color="#333333"
:class="[
'!w-full !h-full p-0 rounded-full text-center text-[14px] font-[500] leading-[24px] tracking-[-0.42px]',
page === currentPage
? '!bg-[var(--primary)] !text-white cursor-default'
: '',
]"
@click="handlePagination(page)"
>
<span>{{ page }}</span>
</AtomsButton>
</li>
</template>
</ol>
<template v-if="totalCount > pageSize">
<button
type="button"
class="relative inline-flex items-center justify-center w-[32px] h-[32px]"
:disabled="currentPage === lastPage"
@click="handlePagination(nextPage)"
>
<AtomsIconsArrowRightLine
:size="16"
:color="currentPage === lastPage ? '#CCCCCC' : '#333333'"
/>
</button>
<button
type="button"
class="relative inline-flex items-center justify-center w-[32px] h-[32px]"
:disabled="currentPage === lastPage"
@click="handlePagination(lastPage)"
>
<AtomsIconsArrowDoubleLeftLine
:size="11"
:color="currentPage === lastPage ? '#CCCCCC' : '#333333'"
class="rotate-180"
/>
</button>
</template>
</div>
</template>
<style scoped></style>