81 lines
2.2 KiB
Vue
81 lines
2.2 KiB
Vue
<script setup lang="ts">
|
|
interface Header {
|
|
title: string;
|
|
key: string;
|
|
sortable?: boolean;
|
|
width?: string;
|
|
align?: 'start' | 'center' | 'end';
|
|
}
|
|
|
|
interface Props {
|
|
headers: Header[];
|
|
items: any[];
|
|
search?: string;
|
|
itemsPerPage?: number;
|
|
minWidth?: string;
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
search: '',
|
|
itemsPerPage: 10,
|
|
minWidth: '1200px'
|
|
});
|
|
|
|
const currentPage = ref(1);
|
|
const itemsPerPageLocal = ref(props.itemsPerPage);
|
|
</script>
|
|
|
|
<template>
|
|
<div class="table-wrapper">
|
|
<v-data-table
|
|
:headers="headers"
|
|
:items="items"
|
|
:search="search"
|
|
class="elevation-1"
|
|
item-value="id"
|
|
v-model:page="currentPage"
|
|
v-model:items-per-page="itemsPerPageLocal"
|
|
>
|
|
<!-- Pass through all slots to parent -->
|
|
<template v-for="(_, name) in $slots" v-slot:[name]="slotData">
|
|
<slot :name="name" v-bind="slotData" />
|
|
</template>
|
|
|
|
<!-- Default slot for Jenis Kelamin if not provided -->
|
|
<template #item.jenisKelamin="{ item }">
|
|
<slot name="item.jenisKelamin" :item="item">
|
|
<v-chip
|
|
:color="item.jenisKelamin === 'L' ? 'primary' : 'pink'"
|
|
size="small"
|
|
>
|
|
{{ item.jenisKelamin }}
|
|
</v-chip>
|
|
</slot>
|
|
</template>
|
|
|
|
<!-- Default slot for Status if not provided -->
|
|
<template #item.status="{ item }">
|
|
<slot name="item.status" :item="item">
|
|
<v-chip
|
|
:color="item.status === 'selesai' ? 'success' : item.status === 'batal' ? 'error' : item.status === 'tunda' ? 'warning' : 'info'"
|
|
size="small"
|
|
>
|
|
{{ item.status }}
|
|
</v-chip>
|
|
</slot>
|
|
</template>
|
|
</v-data-table>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.table-wrapper {
|
|
overflow-x: auto;
|
|
width: 100%;
|
|
}
|
|
|
|
.table-wrapper :deep(.v-data-table) {
|
|
min-width: v-bind(minWidth);
|
|
}
|
|
</style>
|