fix : add filter dokter,kategori antrean

This commit is contained in:
Yusron alamsyah
2026-04-27 13:43:12 +07:00
parent f5db0d9066
commit 41cd9d2715
9 changed files with 505 additions and 55 deletions

No files matched your search

+102 -7
View File
@@ -10,6 +10,9 @@ import { Icon } from '@iconify/vue';
import type { AntreanOperasi } from '~/types/antrean';
import { STATUS, statusOptions } from '~/types/antrean';
import { usePendaftaranStore } from '~/store/pendaftaran';
import type { Dokter } from '~/types/pendaftaran';
import type { KategoriOperasi } from '~/types/antrean';
import api from '~/services/api';
definePageMeta({
middleware: 'auth',
@@ -17,15 +20,31 @@ definePageMeta({
});
const pendaftaranStore = usePendaftaranStore();
const search = ref('');
const route = useRoute();
const router = useRouter();
const getSearchFromRoute = () => {
const q = route.query.search;
if (Array.isArray(q)) return q[0] ?? '';
return typeof q === 'string' ? q : '';
};
const search = ref(getSearchFromRoute());
type SelectOption = { label: string; value: any };
const filterValues = ref<{
statusFilter: string | null;
sortOption: string | null;
DokterFilter: SelectOption | null;
KategoriFilter: SelectOption | null;
}>({
statusFilter: STATUS.BELUM,
sortOption: null
sortOption: null,
DokterFilter: null,
KategoriFilter: null
});
const antreanList = ref<any[]>([]);
const kategoriOptions = ref<SelectOption[]>([]);
const dokterOptions = ref<SelectOption[]>([]);
const loading = ref(false);
const currentPage = ref(1);
const itemsPerPage = ref(10);
@@ -37,8 +56,6 @@ const effectiveItemsPerPage = computed(() => {
return itemsPerPage.value;
});
const router = useRouter();
// Modal state
const showModal = ref(false);
const showEditModal = ref(false);
@@ -49,7 +66,7 @@ const selectedIdForEdit = ref<string | number | null>(null);
const selectedIdForStatus = ref<string | number | null>(null);
// Define filter options
const filterOptions = [
const filterOptions = computed(() => [
{
type: 'btn-group' as const,
label: 'Filter Status',
@@ -58,6 +75,20 @@ const filterOptions = [
options: statusOptions,
defaultValue: STATUS.BELUM
},
{
type: 'autocomplete' as const,
label: 'Filter Dokter',
modelKey: 'DokterFilter',
options: dokterOptions.value,
defaultValue: null
},
{
type: 'autocomplete' as const,
label: 'Filter Kategori',
modelKey: 'KategoriFilter',
options: kategoriOptions.value,
defaultValue: null
},
{
type: 'select' as const,
label: 'Urutkan',
@@ -69,7 +100,7 @@ const filterOptions = [
],
defaultValue: null
}
];
]);
// Fetch data from API
@@ -93,7 +124,9 @@ const fetchData = async (append: boolean = false) => {
status: filterValues.value.statusFilter || undefined,
search: search.value || undefined,
sort_by: sortBy,
sort_order: sortOrder
sort_order: sortOrder,
kategori_id: filterValues.value.KategoriFilter?.value || undefined,
dokter_id: filterValues.value.DokterFilter?.value || undefined
});
if (response.success) {
@@ -116,6 +149,35 @@ const fetchData = async (append: boolean = false) => {
}
};
const fetchKategoriOptions = async () => {
try {
const response = await api.get(`/reference/kategori`);
if (response.data.success && response.data.data) {
kategoriOptions.value = response.data.data.map((kategori: KategoriOperasi) => ({
label: kategori.kategori.split('-')[1]?.trim() || kategori.kategori,
value: kategori.id
}));
}
} catch (error) {
console.error('Error fetching kategori options:', error);
}
};
const fetchDokterOptions = async (searchQuery: string = '') => {
try {
const response = await api.get(`/reference/dokter?limit=50&offset=0&search=${searchQuery}`);
if (response.data.success && response.data.data) {
dokterOptions.value = response.data.data.map((dokter: Dokter) => ({
label: dokter.nama_lengkap,
value: dokter.id
}));
}
} catch (error) {
console.error('Error fetching dokter options:', error);
}
};
// Load more for infinite scroll
const handleLoadMore = () => {
if (hasMore.value && !loading.value) {
@@ -153,6 +215,15 @@ watch(search, () => {
}, 500); // 500ms debounce
});
// Keep input in sync if query param changes (e.g. back/forward navigation)
watch(
() => route.query.search,
() => {
const next = getSearchFromRoute();
if (next !== search.value) search.value = next;
}
);
// Watch for sort changes
watch(() => filterValues.value.sortOption, () => {
currentPage.value = 1;
@@ -161,9 +232,27 @@ watch(() => filterValues.value.sortOption, () => {
fetchData();
});
// Watch for Kategori filter changes
watch(() => filterValues.value.KategoriFilter, () => {
currentPage.value = 1;
antreanList.value = [];
hasMore.value = true;
fetchData();
});
// Watch for Dokter filter changes
watch(() => filterValues.value.DokterFilter, () => {
currentPage.value = 1;
antreanList.value = [];
hasMore.value = true;
fetchData();
});
// Initial fetch
onMounted(() => {
fetchData();
fetchKategoriOptions();
fetchDokterOptions();
});
const showSnackbar = (message: string, color: string = 'success') => {
@@ -255,6 +344,11 @@ const handleEditModalSuccess = () => {
const handleUpdateStatusSuccess = () => {
fetchData(); // Refresh the table after status update
};
const handleFilterSearch = ({ modelKey, query }: { modelKey: string, query: string }) => {
if (modelKey === 'DokterFilter') {
fetchDokterOptions(query);
}
};
</script>
<template>
<v-row>
@@ -275,6 +369,7 @@ const handleUpdateStatusSuccess = () => {
<FilterSortMenu
v-model="filterValues"
:filters="filterOptions"
@search="handleFilterSearch"
/>
</div>
+48 -4
View File
@@ -9,20 +9,25 @@ import ModalPendaftaran from '@/components/pendaftaran/ModalPendaftaranV2.vue';
import ModalDetailPendaftaran from '@/components/pendaftaran/ModalDetailPendaftaran.vue';
import ModalUpdateStatus from '@/components/pendaftaran/ModalUpdateStatus.vue';
import { usePendaftaranStore } from '~/store/pendaftaran';
import type { Dokter } from '~/types/pendaftaran';
import api from '~/services/api';
const route = useRoute();
const idKategori = route.params.id as string;
const categoryName = route.query.category as string || 'Kategori';
const pendaftaranStore = usePendaftaranStore();
type SelectOption = { label: string; value: any };
// State
const search = ref('');
const antreanList = ref<any[]>([]);
const filterValues = ref<{
statusFilter: string | null;
dokterFilter: SelectOption | null;
sortOption: string | null;
}>({
statusFilter: STATUS.BELUM,
dokterFilter: null,
sortOption: null
});
const loading = ref(false);
@@ -40,13 +45,15 @@ const showUpdateStatusModal = ref(false);
const selectedId = ref<string | number | null>(null);
const selectedIdForEdit = ref<string | number | null>(null);
const selectedIdForStatus = ref<string | number | null>(null);
const dokterOptions = ref<SelectOption[]>([]);
const showSnackbar = (message: string, color: string = 'success') => {
pendaftaranStore.showSnackbar(message, color);
};
// Define filter options
const filterOptions = [
const filterOptions = computed(() => [
{
type: 'btn-group' as const,
label: 'Filter Status',
@@ -55,6 +62,13 @@ const filterOptions = [
options: statusOptions,
defaultValue: STATUS.BELUM
},
{
type: 'autocomplete' as const,
label: 'Filter Dokter',
modelKey: 'dokterFilter',
options: dokterOptions.value,
defaultValue: null
},
{
type: 'select' as const,
label: 'Urutkan',
@@ -66,7 +80,7 @@ const filterOptions = [
],
defaultValue: null
}
];
]);
definePageMeta({
middleware: 'auth',
@@ -101,7 +115,8 @@ const fetchData = async (append: boolean = false) => {
search: search.value || undefined,
type_id: idKategori,
sort_by: sortBy,
sort_order: sortOrder
sort_order: sortOrder,
dokter_id: filterValues.value.dokterFilter?.value || undefined
});
if (response.success) {
@@ -124,6 +139,20 @@ const fetchData = async (append: boolean = false) => {
}
};
const fetchDokterOptions = async (searchQuery: string = '') => {
try {
const response = await api.get(`/reference/dokter?limit=50&offset=0&search=${searchQuery}`);
if (response.data.success && response.data.data) {
dokterOptions.value = response.data.data.map((dokter: Dokter) => ({
label: dokter.nama_lengkap,
value: dokter.id
}));
}
} catch (error) {
console.error('Error fetching dokter options:', error);
}
};
// Load more for infinite scroll
const handleLoadMore = () => {
if (hasMore.value && !loading.value) {
@@ -140,6 +169,14 @@ watch(() => filterValues.value.statusFilter, () => {
fetchData();
});
// Watch for Dokter filter changes
watch(() => filterValues.value.dokterFilter, () => {
currentPage.value = 1;
antreanList.value = [];
hasMore.value = true;
fetchData();
});
// Watch for search with debounce
let searchTimeout: NodeJS.Timeout | null = null;
watch(search, () => {
@@ -165,6 +202,7 @@ watch(() => filterValues.value.sortOption, () => {
// Initial fetch
onMounted(() => {
fetchData();
fetchDokterOptions();
});
// Function to get actions based on item status
@@ -184,6 +222,12 @@ const getActionsForItem = (item: AntreanOperasi) => {
return allActions;
};
const handleFilterSearch = ({ modelKey, query }: { modelKey: string, query: string }) => {
if (modelKey === 'dokterFilter') {
fetchDokterOptions(query);
}
};
const handleView = async (item: unknown) => {
const data = item as AntreanOperasi;
selectedId.value = data.id;
@@ -258,7 +302,7 @@ const handleUpdateStatusSuccess = () => {
<v-text-field v-model="search" placeholder="Cari..." variant="outlined" density="compact" class="bg-white"
hide-details prepend-inner-icon="mdi-magnify" style="max-width: 300px;"></v-text-field>
<FilterSortMenu v-model="filterValues" :filters="filterOptions" />
<FilterSortMenu v-model="filterValues" :filters="filterOptions" @search="handleFilterSearch" />
</div>
<v-btn color="primary" size="large" elevation="2" @click="showModal = true">
+83 -4
View File
@@ -10,11 +10,15 @@ import ModalPendaftaran from '@/components/pendaftaran/ModalPendaftaranV2.vue';
import ModalDetailPendaftaran from '@/components/pendaftaran/ModalDetailPendaftaran.vue';
import ModalUpdateStatus from '@/components/pendaftaran/ModalUpdateStatus.vue';
import { usePendaftaranStore } from '~/store/pendaftaran';
import type { Dokter } from '~/types/pendaftaran';
import type { KategoriOperasi } from '~/types/antrean';
import api from '~/services/api';
const route = useRoute();
const kodeSpesialis = route.params.kode as string;
const spesialisName = route.query.spesialis as string || 'Spesialis';
const pendaftaranStore = usePendaftaranStore();
type SelectOption = { label: string; value: any };
// State
const search = ref('');
@@ -22,15 +26,21 @@ const antreanList = ref<any[]>([]);
const filterValues = ref<{
statusFilter: string | null;
sortOption: string | null;
DokterFilter: SelectOption | null;
KategoriFilter: SelectOption | null;
}>({
statusFilter: STATUS.BELUM,
sortOption: null
sortOption: null,
DokterFilter: null,
KategoriFilter: null
});
const loading = ref(false);
const currentPage = ref(1);
const itemsPerPage = ref(12); // Set to 12 for card view
const totalItems = ref(0);
const hasMore = ref(true);
const kategoriOptions = ref<SelectOption[]>([]);
const dokterOptions = ref<SelectOption[]>([]);
// Modal state
const showModal = ref(false);
@@ -46,7 +56,7 @@ const showSnackbar = (message: string, color: string = 'success') => {
};
// Define filter options
const filterOptions = [
const filterOptions = computed(() => [
{
type: 'btn-group' as const,
label: 'Filter Status',
@@ -55,6 +65,20 @@ const filterOptions = [
options: statusOptions,
defaultValue: STATUS.BELUM
},
{
type: 'autocomplete' as const,
label: 'Filter Dokter',
modelKey: 'DokterFilter',
options: dokterOptions.value,
defaultValue: null
},
{
type: 'autocomplete' as const,
label: 'Filter Kategori',
modelKey: 'KategoriFilter',
options: kategoriOptions.value,
defaultValue: null
},
{
type: 'select' as const,
label: 'Urutkan',
@@ -66,7 +90,7 @@ const filterOptions = [
],
defaultValue: null
}
];
]);
definePageMeta({
middleware: 'auth',
@@ -101,7 +125,9 @@ const fetchData = async (append: boolean = false) => {
search: search.value || undefined,
type_id: kodeSpesialis,
sort_by: sortBy,
sort_order: sortOrder
sort_order: sortOrder,
kategori_id: filterValues.value.KategoriFilter?.value || undefined,
dokter_id: filterValues.value.DokterFilter?.value || undefined
});
if (response.success) {
@@ -124,6 +150,34 @@ const fetchData = async (append: boolean = false) => {
}
};
const fetchKategoriOptions = async () => {
try {
const response = await api.get(`/reference/kategori`);
if (response.data.success && response.data.data) {
kategoriOptions.value = response.data.data.map((kategori: KategoriOperasi) => ({
label: kategori.kategori.split('-')[1]?.trim() || kategori.kategori,
value: kategori.id
}));
}
} catch (error) {
console.error('Error fetching kategori options:', error);
}
};
const fetchDokterOptions = async (searchQuery: string = '') => {
try {
const response = await api.get(`/reference/dokter?limit=50&offset=0&search=${searchQuery}`);
if (response.data.success && response.data.data) {
dokterOptions.value = response.data.data.map((dokter: Dokter) => ({
label: dokter.nama_lengkap,
value: dokter.id
}));
}
} catch (error) {
console.error('Error fetching dokter options:', error);
}
};
// Load more for infinite scroll
const handleLoadMore = () => {
if (hasMore.value && !loading.value) {
@@ -162,9 +216,27 @@ watch(() => filterValues.value.sortOption, () => {
fetchData();
});
// Watch for Kategori filter changes
watch(() => filterValues.value.KategoriFilter, () => {
currentPage.value = 1;
antreanList.value = [];
hasMore.value = true;
fetchData();
});
// Watch for Dokter filter changes
watch(() => filterValues.value.DokterFilter, () => {
currentPage.value = 1;
antreanList.value = [];
hasMore.value = true;
fetchData();
});
// Initial fetch
onMounted(() => {
fetchData();
fetchKategoriOptions();
fetchDokterOptions();
});
@@ -185,6 +257,12 @@ const getActionsForItem = (item: AntreanOperasi) => {
return allActions;
};
const handleFilterSearch = ({ modelKey, query }: { modelKey: string, query: string }) => {
if (modelKey === 'DokterFilter') {
fetchDokterOptions(query);
}
};
const handleView = async (item: unknown) => {
const data = item as AntreanOperasi;
selectedId.value = data.id;
@@ -263,6 +341,7 @@ const handleUpdateStatusSuccess = () => {
<FilterSortMenu
v-model="filterValues"
:filters="filterOptions"
@search="handleFilterSearch"
/>
</div>
+84 -4
View File
@@ -9,12 +9,16 @@ import ModalPendaftaran from '@/components/pendaftaran/ModalPendaftaranV2.vue';
import ModalDetailPendaftaran from '@/components/pendaftaran/ModalDetailPendaftaran.vue';
import ModalUpdateStatus from '@/components/pendaftaran/ModalUpdateStatus.vue';
import { usePendaftaranStore } from '~/store/pendaftaran';
import type { Dokter } from '~/types/pendaftaran';
import type { KategoriOperasi } from '~/types/antrean';
import api from '~/services/api';
const route = useRoute();
const kodeSubSpesialis = route.params.kode as string;
const subSpesialisName = route.query.subspecialis as string || 'Sub Spesialis';
const spesialisId = route.query.spesialis_id as string || null;
const pendaftaranStore = usePendaftaranStore();
type SelectOption = { label: string; value: any };
// State
const search = ref('');
@@ -22,15 +26,21 @@ const antreanList = ref<any[]>([]);
const filterValues = ref<{
statusFilter: string | null;
sortOption: string | null;
DokterFilter: SelectOption | null;
KategoriFilter: SelectOption | null;
}>({
statusFilter: STATUS.BELUM,
sortOption: null
sortOption: null,
DokterFilter: null,
KategoriFilter: null
});
const loading = ref(false);
const currentPage = ref(1);
const itemsPerPage = ref(12); // Set to 12 for card view
const totalItems = ref(0);
const hasMore = ref(true);
const kategoriOptions = ref<SelectOption[]>([]);
const dokterOptions = ref<SelectOption[]>([]);
// Modal state
const showModal = ref(false);
@@ -46,7 +56,7 @@ const showSnackbar = (message: string, color: string = 'success') => {
};
// Define filter options
const filterOptions = [
const filterOptions = computed(() => [
{
type: 'btn-group' as const,
label: 'Filter Status',
@@ -55,6 +65,20 @@ const filterOptions = [
options: statusOptions,
defaultValue: STATUS.BELUM
},
{
type: 'autocomplete' as const,
label: 'Filter Dokter',
modelKey: 'DokterFilter',
options: dokterOptions.value,
defaultValue: null
},
{
type: 'autocomplete' as const,
label: 'Filter Kategori',
modelKey: 'KategoriFilter',
options: kategoriOptions.value,
defaultValue: null
},
{
type: 'select' as const,
label: 'Urutkan',
@@ -66,7 +90,7 @@ const filterOptions = [
],
defaultValue: null
}
];
]);
definePageMeta({
middleware: 'auth',
@@ -101,7 +125,9 @@ const fetchData = async (append: boolean = false) => {
search: search.value || undefined,
type_id: kodeSubSpesialis,
sort_by: sortBy,
sort_order: sortOrder
sort_order: sortOrder,
kategori_id: filterValues.value.KategoriFilter?.value || undefined,
dokter_id: filterValues.value.DokterFilter?.value || undefined
});
if (response.success) {
@@ -124,6 +150,35 @@ const fetchData = async (append: boolean = false) => {
}
};
const fetchKategoriOptions = async () => {
try {
const response = await api.get(`/reference/kategori`);
if (response.data.success && response.data.data) {
kategoriOptions.value = response.data.data.map((kategori: KategoriOperasi) => ({
label: kategori.kategori.split('-')[1]?.trim() || kategori.kategori,
value: kategori.id
}));
}
} catch (error) {
console.error('Error fetching kategori options:', error);
}
};
const fetchDokterOptions = async (searchQuery: string = '') => {
try {
const response = await api.get(`/reference/dokter?limit=50&offset=0&search=${searchQuery}`);
if (response.data.success && response.data.data) {
dokterOptions.value = response.data.data.map((dokter: Dokter) => ({
label: dokter.nama_lengkap,
value: dokter.id
}));
}
} catch (error) {
console.error('Error fetching dokter options:', error);
}
};
// Load more for infinite scroll
const handleLoadMore = () => {
if (hasMore.value && !loading.value) {
@@ -162,9 +217,27 @@ watch(() => filterValues.value.sortOption, () => {
fetchData();
});
// Watch for Kategori filter changes
watch(() => filterValues.value.KategoriFilter, () => {
currentPage.value = 1;
antreanList.value = [];
hasMore.value = true;
fetchData();
});
// Watch for Dokter filter changes
watch(() => filterValues.value.DokterFilter, () => {
currentPage.value = 1;
antreanList.value = [];
hasMore.value = true;
fetchData();
});
// Initial fetch
onMounted(() => {
fetchData();
fetchKategoriOptions();
fetchDokterOptions();
});
// Function to get actions based on item status
@@ -184,6 +257,12 @@ const getActionsForItem = (item: AntreanOperasi) => {
return allActions;
};
const handleFilterSearch = ({ modelKey, query }: { modelKey: string, query: string }) => {
if (modelKey === 'DokterFilter') {
fetchDokterOptions(query);
}
};
const handleView = async (item: unknown) => {
const data = item as AntreanOperasi;
selectedId.value = data.id;
@@ -263,6 +342,7 @@ const handleUpdateStatusSuccess = () => {
<FilterSortMenu
v-model="filterValues"
:filters="filterOptions"
@search="handleFilterSearch"
/>
</div>
+48 -19
View File
@@ -42,6 +42,7 @@ const hasDashboardAccess = computed(() => {
// Filter bulan
const selectedMonth = ref(new Date().getMonth());
const selectedYear = ref(new Date().getFullYear());
const useAllPeriod = ref(false);
const months = [
{ value: 0, text: 'Januari' },
@@ -62,6 +63,21 @@ const years = ref([
yearNow -3, yearNow - 2, yearNow -1,yearNow
]);
const dashboardParams = computed(() => {
if (useAllPeriod.value) return {};
return {
year: selectedYear.value,
month: selectedMonth.value + 1 // API expects 1-12, not 0-11
};
});
const periodKey = computed(() => (useAllPeriod.value ? 'all' : `${selectedYear.value}-${selectedMonth.value}`));
const periodLabel = computed(() => {
if (useAllPeriod.value) return 'Semua Periode';
return `${months[selectedMonth.value].text} ${selectedYear.value}`;
});
// Modal state
const showModal = ref(false);
@@ -83,8 +99,7 @@ const fetchStatusAntrian = async () => {
try {
const response = await api.get('/dashboard/perbandingan-status-antrian', {
params: {
year: selectedYear.value,
month: selectedMonth.value + 1 // API expects 1-12, not 0-11
...dashboardParams.value
}
});
@@ -105,8 +120,7 @@ const fetchKategoriAntrian = async () => {
try {
const response = await api.get('/dashboard/perbandingan-kategori-antrian', {
params: {
year: selectedYear.value,
month: selectedMonth.value + 1 // API expects 1-12, not 0-11
...dashboardParams.value
}
});
@@ -127,8 +141,7 @@ const fetchAntrianPerHari = async () => {
try {
const response = await api.get('/dashboard/antrian-per-hari', {
params: {
year: selectedYear.value,
month: selectedMonth.value + 1 // API expects 1-12, not 0-11
...dashboardParams.value
}
});
@@ -149,8 +162,7 @@ const fetchAntrianPerSpesialis = async () => {
try {
const response = await api.get('/dashboard/table-antrian-per-spesialis', {
params: {
year: selectedYear.value,
month: selectedMonth.value + 1 // API expects 1-12, not 0-11
...dashboardParams.value
}
});
@@ -179,8 +191,7 @@ const fetchAntrianPerSubspesialis = async () => {
try {
const response = await api.get('/dashboard/table-antrian-per-subspesialis', {
params: {
year: selectedYear.value,
month: selectedMonth.value + 1 // API expects 1-12, not 0-11
...dashboardParams.value
}
});
@@ -322,13 +333,12 @@ const pieKategoriChartSeries = computed(() => {
// Data untuk Column Chart - Antrian Per Hari dalam 1 Bulan
const lineChartOptions = computed(() => {
const monthName = months[selectedMonth.value].text.substring(0, 3);
// Get categories from API data or generate default
const categories = antrianPerHariData.value.length > 0
? antrianPerHariData.value.map(item => {
const date = new Date(item.TanggalDaftar);
return `${date.getDate()} ${monthName}`;
const shortMonth = date.toLocaleDateString('id-ID', { month: 'short' });
return `${date.getDate()} ${shortMonth}`;
})
: [];
@@ -597,6 +607,17 @@ const subspesialisChartSeries = computed(() => [
// Watch untuk refetch data saat bulan atau tahun berubah
watch([selectedMonth, selectedYear], () => {
if (hasDashboardAccess.value) {
if (useAllPeriod.value) return;
fetchStatusAntrian();
fetchKategoriAntrian();
fetchAntrianPerHari();
fetchAntrianPerSpesialis();
fetchAntrianPerSubspesialis();
}
});
watch(useAllPeriod, () => {
if (hasDashboardAccess.value) {
fetchStatusAntrian();
fetchKategoriAntrian();
@@ -710,6 +731,7 @@ definePageMeta({
density="compact"
variant="outlined"
hide-details
:disabled="useAllPeriod"
style="min-width: 140px;"
prepend-inner-icon="mdi-calendar-month"
></v-select>
@@ -719,8 +741,15 @@ definePageMeta({
density="compact"
variant="outlined"
hide-details
:disabled="useAllPeriod"
style="min-width: 100px;"
></v-select>
<v-checkbox
v-model="useAllPeriod"
label="Semua data"
density="compact"
hide-details
/>
</div>
</div>
<v-btn
@@ -850,7 +879,7 @@ definePageMeta({
</div>
<ClientOnly v-else>
<VueApexCharts
:key="`pie-status-${selectedMonth}-${selectedYear}`"
:key="`pie-status-${periodKey}`"
type="donut"
height="350"
:options="pieChartOptions"
@@ -879,7 +908,7 @@ definePageMeta({
</div>
<ClientOnly v-else>
<VueApexCharts
:key="`pie-kategori-${selectedMonth}-${selectedYear}`"
:key="`pie-kategori-${periodKey}`"
type="donut"
height="350"
:options="pieKategoriChartOptions"
@@ -895,7 +924,7 @@ definePageMeta({
<v-card elevation="10">
<v-card-item>
<div class="d-flex align-center justify-space-between mb-4">
<h5 class="text-h5 font-weight-bold">Antrean Per Hari ({{ months[selectedMonth].text }} {{ selectedYear }})</h5>
<h5 class="text-h5 font-weight-bold">Antrean Per Hari ({{ periodLabel }})</h5>
<v-avatar size="40" class="rounded-md bg-lightsecondary">
<Icon icon="solar:chart-outline" class="text-secondary" height="22" />
</v-avatar>
@@ -908,7 +937,7 @@ definePageMeta({
</div>
<ClientOnly v-else>
<VueApexCharts
:key="`column-${selectedMonth}-${selectedYear}`"
:key="`column-${periodKey}`"
type="bar"
height="350"
:options="lineChartOptions"
@@ -943,7 +972,7 @@ definePageMeta({
</div>
<ClientOnly v-else>
<VueApexCharts
:key="`spesialis-${selectedMonth}-${selectedYear}`"
:key="`spesialis-${periodKey}`"
type="bar"
height="400"
:options="spesialisChartOptions"
@@ -978,7 +1007,7 @@ definePageMeta({
</div>
<ClientOnly v-else>
<VueApexCharts
:key="`subspesialis-${selectedMonth}-${selectedYear}`"
:key="`subspesialis-${periodKey}`"
type="bar"
height="400"
:options="subspesialisChartOptions"