Files
antrean-operasi/pages/antrean/list-spesialis.vue
2026-02-23 10:09:13 +07:00

145 lines
5.7 KiB
Vue

<script setup lang="ts">
import { getAntrianPerSpesialis } from '~/services/antrean';
import LoadingState from '@/components/shared/LoadingState.vue';
import { numberFormat } from '~/utils/helpers';
definePageMeta({
middleware: 'auth',
pageTitle: 'Antrean Operasi per Spesialis'
});
interface SubSpesialisData {
IdSubSpesialis: number;
SubSpesialis: string;
JmlAntrian: number;
}
interface SpesialisData {
IdSpesialis: number;
Spesialis: string;
JmlAntrian: number;
SubSpesialis: SubSpesialisData[];
}
const loading = ref(true);
const spesialisList = ref<SpesialisData[]>([]);
const expandedItems = ref<Set<number>>(new Set());
// Toggle expand/collapse for subspecialist details
const toggleExpand = (idSpesialis: number) => {
if (expandedItems.value.has(idSpesialis)) {
expandedItems.value.delete(idSpesialis);
} else {
expandedItems.value.add(idSpesialis);
}
};
const isExpanded = (idSpesialis: number) => {
return expandedItems.value.has(idSpesialis);
};
// Fetch data from API
const fetchData = async () => {
try {
loading.value = true;
const response = await getAntrianPerSpesialis();
if (response.success && response.data) {
spesialisList.value = response.data;
}
} catch (error) {
console.error('Error fetching antrian per spesialis:', error);
} finally {
loading.value = false;
}
};
// Load data on mount
onMounted(() => {
fetchData();
});
</script>
<template>
<LoadingState
:loading="loading"
:empty="spesialisList.length === 0 && !loading"
loading-text="Memuat data spesialis..."
empty-text="Tidak ada data antrian per spesialis"
>
<v-row>
<v-col
v-for="spesialis in spesialisList"
:key="spesialis.IdSpesialis"
cols="12"
md="4"
>
<v-card elevation="10" class="h-100">
<NuxtLink :to="`/antrean/spesialis/${spesialis.IdSpesialis}?spesialis=${encodeURIComponent(spesialis.Spesialis)}`" style="text-decoration: none; color: inherit;">
<v-card-item style="cursor: pointer;" class="v-card-item--link pa-5">
<div class="d-flex align-center justify-space-between">
<h5 class="text-h6 font-weight-bold">{{ spesialis.Spesialis }}</h5>
<v-icon size="large" color="primary">mdi-chevron-right</v-icon>
</div>
<v-chip class="mt-3 mb-0" color="primary" size="small">
{{ numberFormat(spesialis.JmlAntrian) }} Antrean
</v-chip>
</v-card-item>
</NuxtLink>
<v-divider></v-divider>
<!-- Collapsible Header -->
<div
@click="toggleExpand(spesialis.IdSpesialis)"
style="cursor: pointer;"
class="pa-5 d-flex align-center justify-space-between"
>
<v-label class="font-weight-medium text-subtitle-2">Sub Spesialis:</v-label>
<v-icon :class="{ 'rotate-180': isExpanded(spesialis.IdSpesialis) }" style="transition: transform 0.3s;">
mdi-chevron-down
</v-icon>
</div>
<!-- Collapsible Content -->
<v-expand-transition>
<v-card-text v-show="isExpanded(spesialis.IdSpesialis)" class="pa-5 pt-0 ">
<v-list density="compact" class="py-0">
<v-list-item
v-for="subSpesialis in spesialis.SubSpesialis"
:key="subSpesialis.IdSubSpesialis"
class="px-0"
:to="`/antrean/subspesialis/${subSpesialis.IdSubSpesialis}?subspecialis=${encodeURIComponent(subSpesialis.SubSpesialis || '')}&spesialis_id=${spesialis.IdSpesialis}`"
style="text-decoration: none; color: inherit;"
>
<template #prepend>
<v-icon size="small" color="primary">mdi-chevron-right</v-icon>
</template>
<v-list-item-title class="text-body-2">
{{ subSpesialis.SubSpesialis }}
</v-list-item-title>
<template #append>
<v-chip size="x-small" variant="outlined" color="primary">
{{ numberFormat(subSpesialis.JmlAntrian) }} Antrean
</v-chip>
</template>
</v-list-item>
<v-list-item v-if="!spesialis.SubSpesialis || spesialis.SubSpesialis.length === 0" class="px-0">
<v-list-item-title class="text-body-2 text-medium-emphasis">
Tidak ada sub spesialis
</v-list-item-title>
</v-list-item>
</v-list>
</v-card-text>
</v-expand-transition>
</v-card>
</v-col>
</v-row>
</LoadingState>
</template>
<style scoped>
.rotate-180 {
transform: rotate(180deg);
}
</style>