224 lines
6.9 KiB
Vue
224 lines
6.9 KiB
Vue
<script setup lang="ts">
|
|
import TableAntrian from '@/components/pendaftaran/TableAntrian.vue';
|
|
import type { HakAkses } from '~/types/setting';
|
|
import { getListRole } from '~/services/access';
|
|
|
|
|
|
const router = useRouter();
|
|
const search = ref('');
|
|
const hakAksesList = ref<HakAkses[]>([]);
|
|
const loading = ref(false);
|
|
const currentPage = ref(1);
|
|
const itemsPerPage = ref(10);
|
|
const totalItems = ref(0);
|
|
|
|
// Snackbar state
|
|
const snackbar = ref(false);
|
|
const snackbarMessage = ref('');
|
|
const snackbarColor = ref('success');
|
|
|
|
const showSnackbar = (message: string, color: string = 'success') => {
|
|
snackbarMessage.value = message;
|
|
snackbarColor.value = color;
|
|
snackbar.value = true;
|
|
};
|
|
|
|
// Load data from API
|
|
const fetchData = async () => {
|
|
loading.value = true;
|
|
try {
|
|
const offset = (currentPage.value - 1) * itemsPerPage.value;
|
|
const response = await getListRole({
|
|
limit: itemsPerPage.value,
|
|
offset: offset,
|
|
search: search.value || undefined
|
|
});
|
|
|
|
if (response && response.success) {
|
|
hakAksesList.value = response.data;
|
|
totalItems.value = response.Paginate.Total;
|
|
}
|
|
} catch (error) {
|
|
console.error('Error fetching hak akses:', error);
|
|
showSnackbar('Gagal mengambil data hak akses', 'error');
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
const headers = [
|
|
{ title: 'No', key: 'no', width: '100px', align: 'center' as const },
|
|
{ title: 'Nama Hak Akses', key: 'name', sortable: true },
|
|
{ title: 'Status', key: 'is_active', sortable: true, align: 'center' as const },
|
|
{ title: 'Actions', key: 'actions', sortable: false }
|
|
];
|
|
|
|
const actions = [
|
|
{ icon: 'mdi-eye', color: 'info', tooltip: 'View', event: 'view' },
|
|
{ icon: 'mdi-pencil', color: 'primary', tooltip: 'Edit', event: 'edit' }
|
|
];
|
|
|
|
const handleView = (item: unknown) => {
|
|
const data = item as HakAkses;
|
|
router.push({
|
|
path: '/setting/hak-akses/form',
|
|
query: {
|
|
mode: 'view',
|
|
id: data.id
|
|
}
|
|
});
|
|
};
|
|
|
|
const handleEdit = (item: unknown) => {
|
|
const data = item as HakAkses;
|
|
router.push({
|
|
path: '/setting/hak-akses/form',
|
|
query: {
|
|
mode: 'edit',
|
|
id: data.id
|
|
}
|
|
});
|
|
};
|
|
|
|
const handleDelete = async (item: unknown) => {
|
|
const data = item as HakAkses;
|
|
if (confirm(`Apakah Anda yakin ingin menghapus hak akses "${data.name}"?`)) {
|
|
loading.value = true;
|
|
|
|
try {
|
|
const response = await $fetch(`/api/hak-akses/${data.id}`, {
|
|
method: 'DELETE'
|
|
});
|
|
|
|
if (response && typeof response === 'object' && 'success' in response && response.success) {
|
|
// Remove from list locally
|
|
const index = hakAksesList.value.findIndex(h => h.id === data.id);
|
|
if (index > -1) {
|
|
hakAksesList.value.splice(index, 1);
|
|
}
|
|
|
|
const message = 'message' in response && typeof response.message === 'string'
|
|
? response.message
|
|
: 'Hak akses berhasil dihapus';
|
|
showSnackbar(message, 'success');
|
|
} else {
|
|
const message = response && typeof response === 'object' && 'message' in response && typeof response.message === 'string'
|
|
? response.message
|
|
: 'Gagal menghapus hak akses';
|
|
showSnackbar(message, 'error');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error deleting hak akses:', error);
|
|
showSnackbar('Terjadi kesalahan saat menghapus data', 'error');
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
};
|
|
|
|
// Watch for page changes
|
|
watch(currentPage, () => {
|
|
fetchData();
|
|
});
|
|
|
|
watch(itemsPerPage, () => {
|
|
currentPage.value = 1;
|
|
fetchData();
|
|
});
|
|
|
|
|
|
// Watch for search with debounce
|
|
let searchTimeout: NodeJS.Timeout | null = null;
|
|
watch(search, () => {
|
|
if (searchTimeout) {
|
|
clearTimeout(searchTimeout);
|
|
}
|
|
searchTimeout = setTimeout(() => {
|
|
currentPage.value = 1;
|
|
fetchData();
|
|
}, 500); // 500ms debounce
|
|
});
|
|
|
|
// Initial fetch
|
|
onMounted(() => {
|
|
fetchData();
|
|
});
|
|
|
|
definePageMeta({
|
|
middleware: 'auth',
|
|
pageTitle: 'Hak Akses',
|
|
});
|
|
</script>
|
|
<template>
|
|
<v-row>
|
|
<v-col cols="12">
|
|
<v-card elevation="10">
|
|
<v-card-text>
|
|
<div class="d-flex justify-space-between align-center mb-4">
|
|
<v-text-field
|
|
v-model="search"
|
|
placeholder="Cari..."
|
|
variant="outlined"
|
|
density="comfortable"
|
|
hide-details
|
|
prepend-inner-icon="mdi-magnify"
|
|
style="max-width: 400px;"
|
|
></v-text-field>
|
|
|
|
<!-- <v-btn
|
|
color="primary"
|
|
prepend-icon="mdi-plus"
|
|
to="/setting/hak-akses/form"
|
|
>
|
|
Tambah Hak Akses
|
|
</v-btn> -->
|
|
</div>
|
|
|
|
<TableAntrian
|
|
:headers="headers"
|
|
:items="hakAksesList"
|
|
:server-side="true"
|
|
:total-items="totalItems"
|
|
:current-page="currentPage"
|
|
:items-per-page="itemsPerPage"
|
|
:loading="loading"
|
|
:get-actions="() => actions"
|
|
min-width="900px"
|
|
@view="handleView"
|
|
@edit="handleEdit"
|
|
>
|
|
<template #item.no="{ index }">
|
|
{{ index + 1 }}
|
|
</template>
|
|
<template #item.is_active="{ item }">
|
|
<v-chip
|
|
:color="item.is_active === true ? 'success' : 'error'"
|
|
size="small"
|
|
>
|
|
{{ item.is_active === true ? 'Aktif' : 'Nonaktif' }}
|
|
</v-chip>
|
|
</template>
|
|
</TableAntrian>
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<!-- Snackbar for notifications -->
|
|
<v-snackbar
|
|
v-model="snackbar"
|
|
:color="snackbarColor"
|
|
:timeout="3000"
|
|
location="top"
|
|
>
|
|
{{ snackbarMessage }}
|
|
<template #actions>
|
|
<v-btn
|
|
variant="text"
|
|
@click="snackbar = false"
|
|
>
|
|
Close
|
|
</v-btn>
|
|
</template>
|
|
</v-snackbar>
|
|
</template> |