2
0
mirror of https://github.com/frappe/books.git synced 2025-02-03 12:38:34 +00:00
books/src/components/Paginator.vue
2022-05-23 16:18:23 +05:30

136 lines
3.3 KiB
Vue

<template>
<div class="my-3 grid grid-cols-3 text-gray-800 text-sm select-none">
<!-- Length Display -->
<div class="justify-self-start">
{{
`${(pageNo - 1) * count + 1} - ${Math.min(pageNo * count, itemCount)}`
}}
</div>
<!-- Pagination Selector -->
<div class="flex gap-1 items-center justify-self-center">
<feather-icon
name="chevron-left"
class="w-4 h-4"
:class="
pageNo > 1 ? 'text-gray-600 cursor-pointer' : 'text-transparent'
"
@click="() => setPageNo(Math.max(1, pageNo - 1))"
/>
<div class="flex gap-1 bg-gray-100 rounded">
<input
type="number"
class="w-7 text-right outline-none bg-transparent focus:text-gray-900"
:value="pageNo"
@change="(e) => setPageNo(e.target.value)"
@input="(e) => setPageNo(e.target.value)"
min="1"
:max="maxPages"
/>
<p class="text-gray-600">/</p>
<p class="w-7">
{{ maxPages }}
</p>
</div>
<feather-icon
name="chevron-right"
class="w-4 h-4"
:class="
pageNo < maxPages
? 'text-gray-600 cursor-pointer'
: 'text-transparent'
"
@click="() => setPageNo(Math.min(maxPages, pageNo + 1))"
/>
</div>
<!-- Count Selector -->
<div
class="border border-gray-100 rounded flex justify-self-end"
v-if="filteredCounts.length"
>
<template v-for="c in filteredCounts" :key="c + '-count'">
<button
@click="setCount(c)"
class="w-9"
:class="
count === c || (count === itemCount && c === -1)
? 'bg-gray-100'
: ''
"
>
{{ c === -1 ? t`All` : c }}
</button>
</template>
</div>
</div>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
emits: ['index-change'],
props: {
itemCount: { type: Number, default: 0 },
allowedCounts: { type: Array, default: () => [20, 100, 500, -1] },
},
data() {
return {
pageNo: 1,
count: 0,
};
},
mounted() {
this.count = this.allowedCounts[0];
this.emitIndices();
},
computed: {
maxPages() {
return Math.ceil(this.itemCount / this.count);
},
filteredCounts() {
return this.allowedCounts.filter(this.filterCount);
},
},
methods: {
filterCount(count) {
if (count !== -1 && this.itemCount < count) {
return false;
}
if (count === -1 && this.itemCount < this.allowedCounts[0]) {
return false;
}
return true;
},
setPageNo(value) {
value = parseInt(value);
if (isNaN(value)) {
return;
}
this.pageNo = Math.min(Math.max(1, value), this.maxPages);
this.emitIndices();
},
setCount(count) {
this.pageNo = 1;
if (count === -1) {
count = this.itemCount;
}
this.count = count;
this.emitIndices();
},
emitIndices() {
const indices = this.getSliceIndices();
this.$emit('index-change', indices);
},
getSliceIndices() {
const start = (this.pageNo - 1) * this.count;
const end = this.pageNo * this.count;
return { start, end };
},
},
});
</script>