Files
antrean-operasi/components/pendaftaran/TableAntrian.vue
T

120 lines
3.5 KiB
Vue

<script setup lang="ts">
interface Header {
title: string;
key: string;
sortable?: boolean;
width?: string;
align?: 'start' | 'center' | 'end';
}
interface Action {
icon: string;
color?: string;
tooltip?: string;
event: string;
}
interface Props {
headers: Header[];
items: any[];
search?: string;
itemsPerPage?: number;
minWidth?: string;
actions?: Action[];
}
const props = withDefaults(defineProps<Props>(), {
search: '',
itemsPerPage: 10,
minWidth: '1200px',
actions: () => []
});
const emit = defineEmits<{
(e: string, item: any): void;
}>();
const handleAction = (event: string, item: any) => {
emit(event, item);
};
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>
<!-- Action slot if enabled -->
<template v-if="actions && actions.length > 0" #item.actions="{ item }">
<slot name="item.actions" :item="item">
<div class="d-flex ga-2">
<v-btn
v-for="(action, index) in actions"
:key="index"
icon
size="small"
variant="text"
:color="action.color || 'primary'"
@click="handleAction(action.event, item)"
>
<v-icon>{{ action.icon }}</v-icon>
<v-tooltip v-if="action.tooltip" activator="parent" location="top">
{{ action.tooltip }}
</v-tooltip>
</v-btn>
</div>
</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>