refactor : merge Inventory_frontend submodule into frontend/ directory
Merges the full git history of Inventory_frontend into the monorepo under frontend/. Removes the submodule in favor of a unified repo. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
128
frontend/app/components/common/Pagination.vue
Normal file
128
frontend/app/components/common/Pagination.vue
Normal file
@@ -0,0 +1,128 @@
|
||||
<template>
|
||||
<div v-if="totalPages > 1" class="flex items-center justify-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-ghost"
|
||||
:disabled="currentPage <= 1"
|
||||
@click="goToPage(1)"
|
||||
>
|
||||
<IconLucideChevronFirst class="w-4 h-4" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-ghost"
|
||||
:disabled="currentPage <= 1"
|
||||
@click="goToPage(currentPage - 1)"
|
||||
>
|
||||
<IconLucideChevronLeft class="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
<template v-for="page in visiblePages" :key="page">
|
||||
<span v-if="page === 'ellipsis-start' || page === 'ellipsis-end'" class="px-2">...</span>
|
||||
<button
|
||||
v-else
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
:class="page === currentPage ? 'btn-primary' : 'btn-ghost'"
|
||||
@click="goToPage(page)"
|
||||
>
|
||||
{{ page }}
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-ghost"
|
||||
:disabled="currentPage >= totalPages"
|
||||
@click="goToPage(currentPage + 1)"
|
||||
>
|
||||
<IconLucideChevronRight class="w-4 h-4" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-ghost"
|
||||
:disabled="currentPage >= totalPages"
|
||||
@click="goToPage(totalPages)"
|
||||
>
|
||||
<IconLucideChevronLast class="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import IconLucideChevronFirst from '~icons/lucide/chevrons-left'
|
||||
import IconLucideChevronLeft from '~icons/lucide/chevron-left'
|
||||
import IconLucideChevronRight from '~icons/lucide/chevron-right'
|
||||
import IconLucideChevronLast from '~icons/lucide/chevrons-right'
|
||||
|
||||
const props = defineProps({
|
||||
currentPage: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
totalPages: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
maxVisiblePages: {
|
||||
type: Number,
|
||||
default: 5
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:currentPage'])
|
||||
|
||||
const visiblePages = computed(() => {
|
||||
const pages = []
|
||||
const total = props.totalPages
|
||||
const current = props.currentPage
|
||||
const maxVisible = props.maxVisiblePages
|
||||
|
||||
if (total <= maxVisible + 2) {
|
||||
for (let i = 1; i <= total; i++) {
|
||||
pages.push(i)
|
||||
}
|
||||
return pages
|
||||
}
|
||||
|
||||
// Always show first page
|
||||
pages.push(1)
|
||||
|
||||
const half = Math.floor(maxVisible / 2)
|
||||
let start = Math.max(2, current - half)
|
||||
let end = Math.min(total - 1, current + half)
|
||||
|
||||
// Adjust if near start
|
||||
if (current <= half + 1) {
|
||||
end = maxVisible
|
||||
}
|
||||
// Adjust if near end
|
||||
if (current >= total - half) {
|
||||
start = total - maxVisible + 1
|
||||
}
|
||||
|
||||
if (start > 2) {
|
||||
pages.push('ellipsis-start')
|
||||
}
|
||||
|
||||
for (let i = start; i <= end; i++) {
|
||||
pages.push(i)
|
||||
}
|
||||
|
||||
if (end < total - 1) {
|
||||
pages.push('ellipsis-end')
|
||||
}
|
||||
|
||||
// Always show last page
|
||||
pages.push(total)
|
||||
|
||||
return pages
|
||||
})
|
||||
|
||||
const goToPage = (page) => {
|
||||
if (page >= 1 && page <= props.totalPages && page !== props.currentPage) {
|
||||
emit('update:currentPage', page)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user