feat(installation-position): implement crud operations and ui components
- Add installation position handler, service, and schema - Update list configuration and entry form components - Enhance pagination component with configurable controls - Implement installation position list view with search and pagination
This commit is contained in:
@@ -4,6 +4,10 @@ import Pagination from './pagination.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
paginationMeta: PaginationMeta
|
||||
conf?: {
|
||||
showInfo: boolean
|
||||
showControl: boolean
|
||||
}
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -17,8 +21,10 @@ function handlePageChange(page: number) {
|
||||
|
||||
<template>
|
||||
<Pagination
|
||||
v-if="props.paginationMeta && props.paginationMeta.pageSize > 0"
|
||||
:pagination-meta="paginationMeta"
|
||||
@page-change="handlePageChange"
|
||||
v-if="props.paginationMeta && props.paginationMeta.pageSize > 0"
|
||||
:pagination-meta="paginationMeta"
|
||||
:show-info="conf?.showInfo"
|
||||
:show-control="conf?.showControl"
|
||||
@page-change="handlePageChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -15,11 +15,13 @@ interface Props {
|
||||
paginationMeta: PaginationMeta
|
||||
onPageChange?: (page: number) => void
|
||||
showInfo?: boolean
|
||||
showControl?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
onPageChange: undefined,
|
||||
showInfo: true,
|
||||
showControl: true,
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -65,7 +67,7 @@ const formattedRecordCount = computed(() => {
|
||||
})
|
||||
|
||||
const startRecord = computed(() => {
|
||||
const start = ((props.paginationMeta.page - 1) * props.paginationMeta.pageSize) + 1
|
||||
const start = (props.paginationMeta.page - 1) * props.paginationMeta.pageSize + 1
|
||||
return Number(start).toLocaleString('id-ID')
|
||||
})
|
||||
|
||||
@@ -77,53 +79,95 @@ const endRecord = computed(() => {
|
||||
function getButtonClass(pageNumber: number) {
|
||||
const digits = pageNumber.toString().length
|
||||
|
||||
if (digits >= 4) { // 1000+ (1k+)
|
||||
if (digits >= 4) {
|
||||
// 1000+ (1k+)
|
||||
return 'h-9 px-4 min-w-12'
|
||||
} else if (digits === 3) { // 100-999
|
||||
} else if (digits === 3) {
|
||||
// 100-999
|
||||
return 'h-9 px-3 min-w-10'
|
||||
} else { // 1-99
|
||||
} else {
|
||||
// 1-99
|
||||
return 'w-9 h-9 p-0'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex items-center justify-between px-2 py-2 w-full min-w-0">
|
||||
<div class="flex w-full min-w-0 items-center justify-between px-2 py-2">
|
||||
<!-- Info text -->
|
||||
<div v-if="showInfo && endRecord > 0" class="text-sm text-muted-foreground shrink-0">
|
||||
Menampilkan {{ startRecord }}
|
||||
hingga {{ Number(endRecord).toLocaleString('id-ID') }}
|
||||
dari {{ formattedRecordCount }} data
|
||||
<div
|
||||
v-if="showInfo && endRecord > 0"
|
||||
class="shrink-0 text-sm text-muted-foreground"
|
||||
>
|
||||
Menampilkan {{ startRecord }} hingga {{ Number(endRecord).toLocaleString('id-ID') }} dari
|
||||
{{ formattedRecordCount }} data
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="shrink-0"
|
||||
>
|
||||
-
|
||||
</div>
|
||||
<div v-else class="shrink-0">-</div>
|
||||
|
||||
<!-- Spacer untuk memastikan ada ruang di tengah -->
|
||||
<div class="flex-1 min-w-4"></div>
|
||||
<div class="min-w-4 flex-1"></div>
|
||||
|
||||
<!-- Pagination controls -->
|
||||
<div class="shrink-0">
|
||||
<div
|
||||
v-if="showControl"
|
||||
class="shrink-0"
|
||||
>
|
||||
<Pagination
|
||||
v-slot="{ page }" :total="paginationMeta.recordCount" :sibling-count="1" :page="paginationMeta.page"
|
||||
:items-per-page="paginationMeta.pageSize" show-edges
|
||||
>
|
||||
<PaginationList v-slot="{ items }" class="flex items-center gap-1">
|
||||
<PaginationFirst :disabled="!paginationMeta.hasPrev" @click="handleFirst" />
|
||||
<PaginationPrev :disabled="!paginationMeta.hasPrev" @click="handlePrev" />
|
||||
v-slot="{ page }"
|
||||
:total="paginationMeta.recordCount"
|
||||
:sibling-count="1"
|
||||
:page="paginationMeta.page"
|
||||
:items-per-page="paginationMeta.pageSize"
|
||||
show-edges
|
||||
>
|
||||
<PaginationList
|
||||
v-slot="{ items }"
|
||||
class="flex items-center gap-1"
|
||||
>
|
||||
<PaginationFirst
|
||||
:disabled="!paginationMeta.hasPrev"
|
||||
@click="handleFirst"
|
||||
/>
|
||||
<PaginationPrev
|
||||
:disabled="!paginationMeta.hasPrev"
|
||||
@click="handlePrev"
|
||||
/>
|
||||
|
||||
<template v-for="(item, index) in items">
|
||||
<PaginationListItem
|
||||
v-if="item.type === 'page'" :key="index" :value="item.value" as-child
|
||||
v-if="item.type === 'page'"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
as-child
|
||||
@click="handlePageChange(item.value)"
|
||||
>
|
||||
<Button :class="getButtonClass(item.value)" :variant="item.value === page ? 'default' : 'outline'">
|
||||
>
|
||||
<Button
|
||||
:class="getButtonClass(item.value)"
|
||||
:variant="item.value === page ? 'default' : 'outline'"
|
||||
>
|
||||
{{ item.value }}
|
||||
</Button>
|
||||
</PaginationListItem>
|
||||
<PaginationEllipsis v-else :key="item.type" :index="index" />
|
||||
<PaginationEllipsis
|
||||
v-else
|
||||
:key="item.type"
|
||||
:index="index"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<PaginationNext :disabled="!paginationMeta.hasNext" @click="handleNext" />
|
||||
<PaginationLast :disabled="!paginationMeta.hasNext" @click="handleLast" />
|
||||
<PaginationNext
|
||||
:disabled="!paginationMeta.hasNext"
|
||||
@click="handleNext"
|
||||
/>
|
||||
<PaginationLast
|
||||
:disabled="!paginationMeta.hasNext"
|
||||
@click="handleLast"
|
||||
/>
|
||||
</PaginationList>
|
||||
</Pagination>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user