update komponen tabel

This commit is contained in:
bagus-arie05
2025-09-19 14:55:32 +07:00
parent 28822718de
commit a66f883372
3 changed files with 989 additions and 489 deletions

View File

@@ -4,7 +4,10 @@
<!-- Title Section --> <!-- Title Section -->
<v-row no-gutters class="mb-3" v-if="title"> <v-row no-gutters class="mb-3" v-if="title">
<v-col cols="12"> <v-col cols="12">
<v-card-title class="text-subtitle-1 font-weight-bold pa-0" :class="{ 'red--text': title.includes('TERLAMBAT') }"> <v-card-title
class="text-subtitle-1 font-weight-bold pa-0"
:class="getTitleClass(title)"
>
{{ title }} {{ title }}
</v-card-title> </v-card-title>
</v-col> </v-col>
@@ -44,19 +47,25 @@
<v-data-table <v-data-table
:headers="headers" :headers="headers"
:items="filteredItems" :items="paginatedItems"
:items-per-page="itemsPerPage"
:search="search" :search="search"
no-data-text="No data available in table" no-data-text="No data available in table"
hide-default-footer hide-default-footer
class="elevation-1" class="elevation-1"
item-value="id" item-value="no"
> >
<!-- Custom slot untuk nomor urut --> <!-- Custom slot untuk nomor urut -->
<template v-slot:item.no="{ index }"> <template v-slot:item.no="{ index }">
{{ (currentPage - 1) * itemsPerPage + index + 1 }} {{ (currentPage - 1) * itemsPerPage + index + 1 }}
</template> </template>
<!-- Custom slot untuk jam panggil dengan highlighting -->
<template v-slot:item.jamPanggil="{ item }">
<slot name="item.jamPanggil" :item="item">
<span>{{ item.jamPanggil }}</span>
</slot>
</template>
<!-- Custom slot untuk status --> <!-- Custom slot untuk status -->
<template v-slot:item.status="{ item }"> <template v-slot:item.status="{ item }">
<v-chip <v-chip
@@ -68,6 +77,53 @@
</v-chip> </v-chip>
</template> </template>
<!-- Custom slot untuk barcode dengan formatting -->
<template v-slot:item.barcode="{ item }">
<span class="font-mono">{{ item.barcode }}</span>
</template>
<!-- Custom slot untuk no antrian dengan highlighting -->
<template v-slot:item.noAntrian="{ item }">
<div>
<span class="font-weight-medium">{{ item.noAntrian.split(' |')[0] }}</span>
<br>
<small class="text-grey-darken-1">{{ item.noAntrian.split(' |')[1] }}</small>
</div>
</template>
<!-- Custom slot untuk klinik dengan chip styling -->
<template v-slot:item.klinik="{ item }">
<v-chip
size="small"
variant="outlined"
:color="getKlinikColor(item.klinik)"
>
{{ item.klinik }}
</v-chip>
</template>
<!-- Custom slot untuk fast track -->
<template v-slot:item.fastTrack="{ item }">
<v-chip
size="small"
color="info"
variant="tonal"
>
{{ item.fastTrack }}
</v-chip>
</template>
<!-- Custom slot untuk pembayaran -->
<template v-slot:item.pembayaran="{ item }">
<v-chip
size="small"
color="success"
variant="tonal"
>
{{ item.pembayaran }}
</v-chip>
</template>
<!-- Custom slot untuk keterangan --> <!-- Custom slot untuk keterangan -->
<template v-slot:item.keterangan="{ item }"> <template v-slot:item.keterangan="{ item }">
<span v-if="item.keterangan" class="text-green font-weight-medium"> <span v-if="item.keterangan" class="text-green font-weight-medium">
@@ -89,7 +145,7 @@
<!-- Footer Pagination --> <!-- Footer Pagination -->
<div class="d-flex justify-space-between align-center mt-4"> <div class="d-flex justify-space-between align-center mt-4">
<div class="text-body-2 text-grey-darken-1"> <div class="text-body-2 text-grey-darken-1">
Showing {{ currentPageStart }} to {{ currentPageEnd }} of {{ totalEntries }} entries Showing {{ currentPageStart }} to {{ currentPageEnd }} of {{ filteredTotal }} entries
</div> </div>
<v-pagination <v-pagination
@@ -127,35 +183,38 @@ const search = ref("");
const itemsPerPage = ref(10); const itemsPerPage = ref(10);
const currentPage = ref(1); const currentPage = ref(1);
const totalEntries = computed(() => props.items.length); // Filter items based on search
const totalPages = computed(() => Math.ceil(totalEntries.value / itemsPerPage.value));
// Filter items based on search and pagination
const filteredItems = computed(() => { const filteredItems = computed(() => {
let filtered = props.items; if (!search.value) {
return props.items;
if (search.value) {
const searchLower = search.value.toLowerCase();
filtered = props.items.filter(item => {
return Object.values(item).some(value =>
String(value).toLowerCase().includes(searchLower)
);
});
} }
const searchLower = search.value.toLowerCase();
return props.items.filter(item => {
return Object.values(item).some(value =>
String(value).toLowerCase().includes(searchLower)
);
});
});
const filteredTotal = computed(() => filteredItems.value.length);
const totalPages = computed(() => Math.ceil(filteredTotal.value / itemsPerPage.value));
// Paginate the filtered items
const paginatedItems = computed(() => {
const start = (currentPage.value - 1) * itemsPerPage.value; const start = (currentPage.value - 1) * itemsPerPage.value;
const end = start + itemsPerPage.value; const end = start + itemsPerPage.value;
return filtered.slice(start, end); return filteredItems.value.slice(start, end);
}); });
const currentPageStart = computed(() => { const currentPageStart = computed(() => {
if (totalEntries.value === 0) return 0; if (filteredTotal.value === 0) return 0;
return (currentPage.value - 1) * itemsPerPage.value + 1; return (currentPage.value - 1) * itemsPerPage.value + 1;
}); });
const currentPageEnd = computed(() => { const currentPageEnd = computed(() => {
const end = currentPage.value * itemsPerPage.value; const end = currentPage.value * itemsPerPage.value;
return Math.min(end, totalEntries.value); return Math.min(end, filteredTotal.value);
}); });
// Method untuk mendapatkan warna status // Method untuk mendapatkan warna status
@@ -169,11 +228,43 @@ const getStatusColor = (status) => {
return 'green'; return 'green';
case 'Batal': case 'Batal':
return 'red'; return 'red';
case 'Aktif':
return 'success';
case 'Menunggu':
return 'warning';
default: default:
return 'grey'; return 'grey';
} }
}; };
// Method untuk mendapatkan warna klinik
const getKlinikColor = (klinik) => {
switch (klinik) {
case 'KANDUNGAN':
return 'pink';
case 'IPD':
return 'blue';
case 'THT':
return 'orange';
case 'SARAF':
return 'purple';
default:
return 'grey';
}
};
// Method untuk mendapatkan class title
const getTitleClass = (title) => {
if (title.includes('TERLAMBAT')) {
return 'text-warning';
} else if (title.includes('PENDING')) {
return 'text-info';
} else if (title.includes('DI LOKET')) {
return 'text-success';
}
return 'text-primary';
};
// Watch untuk reset halaman ketika items per page berubah // Watch untuk reset halaman ketika items per page berubah
watch(itemsPerPage, () => { watch(itemsPerPage, () => {
currentPage.value = 1; currentPage.value = 1;
@@ -192,6 +283,65 @@ watch(search, () => {
<style scoped> <style scoped>
.text-red { .text-red {
color: #383838; color: #f44336 !important;
}
.text-warning {
color: #ff9800 !important;
}
.text-info {
color: #2196f3 !important;
}
.text-success {
color: #4caf50 !important;
}
.text-primary {
color: #1976d2 !important;
}
.font-mono {
font-family: 'Courier New', monospace;
font-size: 0.875rem;
}
/* Table enhancements */
:deep(.v-data-table) {
border-radius: 8px;
overflow: hidden;
}
:deep(.v-data-table tbody tr) {
transition: background-color 0.2s ease;
}
:deep(.v-data-table tbody tr:hover) {
background: rgba(25, 118, 210, 0.04) !important;
}
:deep(.v-data-table th) {
font-weight: 600 !important;
background: #fafafa !important;
color: #424242 !important;
}
:deep(.v-data-table td) {
border-bottom: 1px solid #e0e0e0 !important;
}
/* Responsive adjustments */
@media (max-width: 768px) {
:deep(.v-data-table) {
font-size: 0.875rem;
}
.v-pagination {
:deep(.v-pagination__item) {
min-width: 32px;
height: 32px;
}
}
} }
</style> </style>

View File

@@ -9,145 +9,208 @@
<v-icon size="32" color="white">mdi-view-dashboard</v-icon> <v-icon size="32" color="white">mdi-view-dashboard</v-icon>
</div> </div>
<div class="header-text"> <div class="header-text">
<h1 class="page-title">Loket 12</h1> <h1 class="page-title">Loket Admin</h1>
<p class="page-subtitle">Rabu, 13 Agustus 2025 - Pelayanan</p> <p class="page-subtitle">Rabu, 13 Agustus 2025 - Pelayanan</p>
</div> </div>
</div> </div>
<div class="header-right"> <div class="header-right">
<v-chip <v-chip color="success" variant="flat" class="mr-2">
color="success" Total {{ totalPasien }} Pasien
variant="flat"
class="mr-2"
>
Total 2 Pasien
</v-chip> </v-chip>
<v-chip <v-chip color="white" variant="flat" class="text-primary">
color="white"
variant="flat"
class="text-primary"
>
Max 150 Pasien Max 150 Pasien
</v-chip> </v-chip>
</div> </div>
</div> </div>
</div> </div>
<div>
<!-- Call Controls --> <v-card class="next-patient-card mb-4" elevation="2">
<v-card class="call-controls-card mb-4" elevation="2"> <v-card-text class="text-center pa-6">
<v-card-text class="py-4"> <v-chip color="success" variant="flat" class="mb-3" size="large">
<v-row align="center"> <v-icon start>mdi-account-arrow-right</v-icon>
<v-col cols="12" md="8"> PASIEN SELANJUTNYA
<div class="d-flex align-center flex-wrap gap-3"> </v-chip>
<span class="text-subtitle-1 font-weight-medium">Panggil Pasien:</span> <div class="text-h4 font-weight-bold mb-2 text-success">
<v-btn {{ nextPatient ? nextPatient.noAntrian.split(" |")[0] : "UM1004" }}
color="success" </div>
variant="flat" <div class="text-body-1 mb-4 text-grey-darken-1">
size="large" Klik tombol hijau untuk memanggil
class="px-6" </div>
@click="callPatient(1)" <v-btn
> color="success"
<span class="text-h6 font-weight-bold">1</span> variant="flat"
</v-btn> size="large"
<v-btn class="px-8"
color="info" @click="callNext"
variant="flat" :disabled="!nextPatient"
size="large" >
class="px-6" <v-icon start>mdi-microphone</v-icon>
@click="callPatient(5)" PANGGIL NEXT
> </v-btn>
<span class="text-h6 font-weight-bold">5</span> </v-card-text>
</v-btn> </v-card>
<v-btn </div>
color="warning" <!-- Combined Control Section -->
variant="flat" <v-row class="mb-4">
size="large" <!-- Left Side: Call Controls and Current Processing -->
class="px-6" <v-col cols="12" lg="6">
@click="callPatient(10)" <!-- Current Patient Processing Card -->
> <v-card
<span class="text-h6 font-weight-bold">10</span> v-if="currentProcessingPatient"
</v-btn> class="current-processing-card"
<v-btn elevation="2"
color="error"
variant="flat"
size="large"
class="px-6"
@click="callPatient(20)"
>
<span class="text-h6 font-weight-bold">20</span>
</v-btn>
</div>
</v-col>
<v-col cols="12" md="4">
<v-chip
color="info"
variant="flat"
class="float-right"
>
Total Quota Terpakai: 5
</v-chip>
</v-col>
</v-row>
</v-card-text>
</v-card>
<!-- Next Patient Card -->
<v-card class="next-patient-card mb-4" elevation="2">
<v-card-text class="text-center pa-8">
<v-chip color="success" variant="flat" class="mb-4" size="large">
<v-icon start>mdi-account-arrow-right</v-icon>
PASIEN SELANJUTNYA
</v-chip>
<div class="text-h3 font-weight-bold mb-2 text-success">
UM1004
</div>
<div class="text-h6 mb-4 text-grey-darken-1">
Klik tombol hijau untuk memanggil
</div>
<v-btn
color="success"
variant="flat"
size="x-large"
class="px-12"
@click="callNext"
> >
<v-icon start>mdi-microphone</v-icon> <v-card-text class="pa-4">
PANGGIL NEXT <div class="d-flex align-center justify-space-between">
</v-btn> <div class="patient-info">
</v-card-text> <v-chip color="primary" variant="flat" class="mb-2">
</v-card> <v-icon start>mdi-account-clock</v-icon>
SEDANG DIPROSES
</v-chip>
<div class="text-h5 font-weight-bold mb-1">
{{ currentProcessingPatient.noAntrian.split(" |")[0] }}
</div>
<div class="text-subtitle-1 text-grey-darken-1">
{{ currentProcessingPatient.barcode }} |
{{ currentProcessingPatient.klinik }}
</div>
</div>
<div class="action-buttons">
<v-btn
color="success"
variant="flat"
class="mr-2"
@click="processPatient(currentProcessingPatient, 'check-in')"
>
<v-icon start>mdi-check-circle</v-icon>
Check In
</v-btn>
<v-btn
color="warning"
variant="flat"
class="mr-2"
@click="processPatient(currentProcessingPatient, 'terlambat')"
>
<v-icon start>mdi-clock-alert</v-icon>
Terlambat
</v-btn>
<v-btn
color="error"
variant="flat"
@click="processPatient(currentProcessingPatient, 'pending')"
>
<v-icon start>mdi-pause-circle</v-icon>
Pending
</v-btn>
</div>
</div>
</v-card-text>
</v-card>
</v-col>
<!-- Main Patients Table --> <!-- Right Side: Patient Queue Info -->
<v-col cols="12" lg="6">
<!-- Next Patient Card -->
<!-- Quota Info Card -->
<v-card class="quota-info-card" elevation="2">
<v-card-text class="pa-4">
<div class="text-center">
<div class="text-h6 font-weight-medium mb-3">
Panggil Antrean Anjungan
</div>
<v-row class="mb-3">
<v-col cols="6" class="text-center">
<div class="text-caption text-grey-darken-1">Kuota</div>
<div class="text-h4 font-weight-bold">150</div>
</v-col>
<v-col cols="6" class="text-center">
<div class="text-caption text-grey-darken-1">Tersedia</div>
<div class="text-h4 font-weight-bold text-success">
{{ 150 - quotaUsed }}
</div>
</v-col>
</v-row>
<div class="text-body-2 text-grey-darken-1 mb-2">
Total Quota Terpakai: {{ quotaUsed }}
</div>
<v-progress-linear
:model-value="(quotaUsed / 150) * 100"
color="success"
height="8"
rounded
></v-progress-linear>
<v-card-text class="call-controls-card align-center py-4">
<div> <span class="text-subtitle-1 font-weight-medium"
>Panggil Pasien:</span> </div>
<div class="d-flex align-center flex-wrap mb-3">
<v-btn
color="success"
variant="flat"
size="large"
class="px-6 ma-4"
@click="callMultiplePatients(1)"
>
<span class="text-h6 font-weight-bold">1</span>
</v-btn>
<v-btn
color="info"
variant="flat"
size="large"
class="px-6 ma-4"
@click="callMultiplePatients(5)"
>
<span class="text-h6 font-weight-bold">5</span>
</v-btn>
<v-btn
color="warning"
variant="flat"
size="large"
class="px-6 ma-4"
@click="callMultiplePatients(10)"
>
<span class="text-h6 font-weight-bold">10</span>
</v-btn>
<v-btn
color="error"
variant="flat"
size="large"
class="px-6 ma-4"
@click="callMultiplePatients(20)"
>
<span class="text-h6 font-weight-bold">20</span>
</v-btn>
</div>
</v-card-text>
</div>
</v-card-text>
</v-card>
</v-col>
</v-row>
<!-- Di Loket Patients Table -->
<v-card class="main-table-card mb-4" elevation="2"> <v-card class="main-table-card mb-4" elevation="2">
<TabelData <TabelData
:headers="mainHeaders" :headers="diLoketHeaders"
:items="mainPatients" :items="diLoketPatients"
title="DATA PASIEN" title="DATA PASIEN - DI LOKET"
> >
<template #actions="{ item }"> <template #actions="{ item }">
<div class="d-flex gap-1"> <div class="d-flex gap-1">
<v-btn
size="small"
color="info"
variant="flat"
@click="processPatient(item, 'aktifkan')"
>
Aktifkan
</v-btn>
<v-btn <v-btn
size="small" size="small"
color="success" color="success"
variant="flat" variant="flat"
@click="callPatient(item.no)" @click="processPatient(item, 'proses')"
> >
Panggil Proses
</v-btn>
<v-btn
size="small"
color="warning"
variant="flat"
@click="cancelPatient(item)"
>
Cancel
</v-btn>
<v-btn
size="small"
color="primary"
variant="flat"
@click="finishPatient(item)"
>
Selesai
</v-btn> </v-btn>
</div> </div>
</template> </template>
@@ -157,23 +220,56 @@
</TabelData> </TabelData>
</v-card> </v-card>
<!-- Late Patients Table --> <!-- Terlambat Patients Table -->
<v-card class="late-table-card mb-4" elevation="2" v-if="latePatients.length > 0"> <v-card
class="late-table-card mb-4"
elevation="2"
v-if="terlambatPatients.length > 0"
>
<TabelData <TabelData
:headers="lateHeaders" :headers="terlambatHeaders"
:items="latePatients" :items="terlambatPatients"
title="INFO PASIEN LAPOR TERLAMBAT" title="INFO PASIEN LAPOR TERLAMBAT"
:show-search="false" >
/> <template #actions="{ item }">
<div class="d-flex gap-1">
<v-btn
size="small"
color="success"
variant="flat"
@click="processPatient(item, 'aktifkan')"
>
Aktifkan
</v-btn>
</div>
</template>
</TabelData>
</v-card> </v-card>
<!-- Clinic Patients Table --> <!-- Pending Patients Table -->
<v-card class="clinic-table-card mb-4" elevation="2" v-if="clinicPatients.length > 0"> <v-card
class="pending-table-card mb-4"
elevation="2"
v-if="pendingPatients.length > 0"
>
<TabelData <TabelData
:headers="clinicHeaders" :headers="pendingHeaders"
:items="clinicPatients" :items="pendingPatients"
title="INFO PASIEN MASUK KLINIK" title="INFO PASIEN PENDING"
/> >
<template #actions="{ item }">
<div class="d-flex gap-1">
<v-btn
size="small"
color="success"
variant="flat"
@click="processPatient(item, 'proses')"
>
Proses
</v-btn>
</div>
</template>
</TabelData>
</v-card> </v-card>
<!-- Snackbar --> <!-- Snackbar -->
@@ -195,29 +291,18 @@
</template> </template>
<script setup> <script setup>
import { ref } from "vue"; import { ref, computed } from "vue";
import TabelData from "../components/TabelData.vue"; import TabelData from "../components/TabelData.vue";
// Reactive data // Reactive data
const snackbar = ref(false) const snackbar = ref(false);
const snackbarText = ref('') const snackbarText = ref("");
const snackbarColor = ref('success') const snackbarColor = ref("success");
const quotaUsed = ref(5);
const currentProcessingPatient = ref(null);
// Data and Headers // Base patient data - semua pasien yang belum dipanggil
const mainHeaders = ref([ const allPatients = ref([
{ title: "No", value: "no", sortable: false, width: "60px" },
{ title: "Jam Panggil", value: "jamPanggil", sortable: true, width: "100px" },
{ title: "Barcode", value: "barcode", sortable: true, width: "140px" },
{ title: "No Antrian", value: "noAntrian", sortable: true, width: "200px" },
{ title: "Shift", value: "shift", sortable: true, width: "80px" },
{ title: "Klinik", value: "klinik", sortable: true, width: "120px" },
{ title: "Fast Track", value: "fastTrack", sortable: true, width: "100px" },
{ title: "Pembayaran", value: "pembayaran", sortable: true, width: "100px" },
{ title: "Status", value: "panggil", sortable: true, width: "80px" },
{ title: "Aksi", value: "aksi", sortable: false, width: "200px" },
]);
const mainPatients = ref([
{ {
no: 1, no: 1,
jamPanggil: "12:49", jamPanggil: "12:49",
@@ -227,8 +312,7 @@ const mainPatients = ref([
klinik: "KANDUNGAN", klinik: "KANDUNGAN",
fastTrack: "UMUM", fastTrack: "UMUM",
pembayaran: "UMUM", pembayaran: "UMUM",
panggil: "Aktif", status: "waiting", // waiting, di-loket, terlambat, pending, processed
status: "current",
}, },
{ {
no: 2, no: 2,
@@ -239,24 +323,76 @@ const mainPatients = ref([
klinik: "IPD", klinik: "IPD",
fastTrack: "UMUM", fastTrack: "UMUM",
pembayaran: "UMUM", pembayaran: "UMUM",
panggil: "Menunggu", status: "waiting",
status: "normal",
}, },
...Array.from({ length: 20 }, (_, i) => ({ {
no: i + 3, no: 3,
jamPanggil: "09:30",
barcode: "250811100200",
noAntrian: "UM1003 | Online - 250811100200",
shift: "Shift 1",
klinik: "SARAF",
fastTrack: "UMUM",
pembayaran: "UMUM",
status: "waiting",
},
{
no: 4,
jamPanggil: "14:15",
barcode: "250811100210",
noAntrian: "UM1004 | Online - 250811100210",
shift: "Shift 1",
klinik: "THT",
fastTrack: "UMUM",
pembayaran: "UMUM",
status: "waiting",
},
...Array.from({ length: 16 }, (_, i) => ({
no: i + 5,
jamPanggil: `${String(Math.floor(Math.random() * 12) + 1).padStart(2, "0")}:${String(Math.floor(Math.random() * 60)).padStart(2, "0")}`, jamPanggil: `${String(Math.floor(Math.random() * 12) + 1).padStart(2, "0")}:${String(Math.floor(Math.random() * 60)).padStart(2, "0")}`,
barcode: `25081110${String(i + 200).padStart(4, "0")}`, barcode: `25081110${String(i + 300).padStart(4, "0")}`,
noAntrian: `UM100${i + 3} | Online - 25081110${String(i + 200).padStart(4, "0")}`, noAntrian: `UM100${i + 5} | Online - 25081110${String(i + 300).padStart(4, "0")}`,
shift: "Shift 1", shift: "Shift 1",
klinik: ["KANDUNGAN", "IPD", "THT", "SARAF"][Math.floor(Math.random() * 4)], klinik: ["KANDUNGAN", "IPD", "THT", "SARAF"][Math.floor(Math.random() * 4)],
fastTrack: "UMUM", fastTrack: "UMUM",
pembayaran: "UMUM", pembayaran: "UMUM",
panggil: "Menunggu", status: "waiting",
status: "normal",
})), })),
]); ]);
const lateHeaders = ref([ // Computed properties for different status tables
const diLoketPatients = computed(() =>
allPatients.value.filter((patient) => patient.status === "di-loket")
);
const terlambatPatients = computed(() =>
allPatients.value.filter((patient) => patient.status === "terlambat")
);
const pendingPatients = computed(() =>
allPatients.value.filter((patient) => patient.status === "pending")
);
const nextPatient = computed(() => {
return allPatients.value.find((patient) => patient.status === "waiting");
});
const totalPasien = computed(() => allPatients.value.length);
// Headers for different tables
const diLoketHeaders = ref([
{ title: "No", value: "no", sortable: false, width: "60px" },
{ title: "Jam Panggil", value: "jamPanggil", sortable: true, width: "100px" },
{ title: "Barcode", value: "barcode", sortable: true, width: "140px" },
{ title: "No Antrian", value: "noAntrian", sortable: true, width: "200px" },
{ title: "Shift", value: "shift", sortable: true, width: "80px" },
{ title: "Klinik", value: "klinik", sortable: true, width: "120px" },
{ title: "Fast Track", value: "fastTrack", sortable: true, width: "100px" },
{ title: "Pembayaran", value: "pembayaran", sortable: true, width: "100px" },
{ title: "Aksi", value: "aksi", sortable: false, width: "200px" },
]);
const terlambatHeaders = ref([
{ title: "No", value: "no", sortable: false, width: "60px" }, { title: "No", value: "no", sortable: false, width: "60px" },
{ title: "Barcode", value: "barcode", sortable: true, width: "140px" }, { title: "Barcode", value: "barcode", sortable: true, width: "140px" },
{ title: "No Antrian", value: "noAntrian", sortable: true, width: "200px" }, { title: "No Antrian", value: "noAntrian", sortable: true, width: "200px" },
@@ -265,13 +401,10 @@ const lateHeaders = ref([
{ title: "Aksi", value: "aksi", sortable: false, width: "100px" }, { title: "Aksi", value: "aksi", sortable: false, width: "100px" },
]); ]);
const latePatients = ref([]); const pendingHeaders = ref([
const clinicHeaders = ref([
{ title: "#", value: "no", sortable: false, width: "60px" }, { title: "#", value: "no", sortable: false, width: "60px" },
{ title: "Barcode", value: "barcode", sortable: true, width: "140px" }, { title: "Barcode", value: "barcode", sortable: true, width: "140px" },
{ title: "No Antrian", value: "noAntrian", sortable: true, width: "200px" }, { title: "No Antrian", value: "noAntrian", sortable: true, width: "200px" },
{ title: "No RM", value: "noRM", sortable: true, width: "100px" },
{ title: "Shift", value: "shift", sortable: true, width: "80px" }, { title: "Shift", value: "shift", sortable: true, width: "80px" },
{ title: "Klinik", value: "klinik", sortable: true, width: "120px" }, { title: "Klinik", value: "klinik", sortable: true, width: "120px" },
{ title: "Fast Track", value: "fastTrack", sortable: true, width: "100px" }, { title: "Fast Track", value: "fastTrack", sortable: true, width: "100px" },
@@ -279,30 +412,102 @@ const clinicHeaders = ref([
{ title: "Aksi", value: "aksi", sortable: false, width: "100px" }, { title: "Aksi", value: "aksi", sortable: false, width: "100px" },
]); ]);
const clinicPatients = ref([]);
// Methods // Methods
const showSnackbar = (text, color = 'success') => { const showSnackbar = (text, color = "success") => {
snackbarText.value = text snackbarText.value = text;
snackbarColor.value = color snackbarColor.value = color;
snackbar.value = true snackbar.value = true;
} };
const callPatient = (number) => { const callMultiplePatients = (count) => {
showSnackbar(`Memanggil pasien nomor ${number}`, 'success') const waitingPatients = allPatients.value.filter(
} (patient) => patient.status === "waiting"
);
const patientsToCall = waitingPatients.slice(0, count);
if (patientsToCall.length === 0) {
showSnackbar("Tidak ada pasien yang menunggu", "warning");
return;
}
// Check quota
if (quotaUsed.value + patientsToCall.length > 150) {
showSnackbar("Quota tidak mencukupi", "error");
return;
}
// Move patients to "di-loket" status
patientsToCall.forEach((patient) => {
patient.status = "di-loket";
});
quotaUsed.value += patientsToCall.length;
showSnackbar(`Memanggil ${patientsToCall.length} pasien ke loket`, "success");
};
const callNext = () => { const callNext = () => {
showSnackbar('Memanggil pasien selanjutnya: UM1004', 'success') if (!nextPatient.value) {
} showSnackbar("Tidak ada pasien selanjutnya", "warning");
return;
}
const cancelPatient = (patient) => { if (quotaUsed.value >= 150) {
showSnackbar(`Membatalkan pasien ${patient.noAntrian.split(' |')[0]}`, 'warning') showSnackbar("Quota sudah penuh", "error");
} return;
}
const finishPatient = (patient) => { // Move next patient to processing
showSnackbar(`Menyelesaikan pasien ${patient.noAntrian.split(' |')[0]}`, 'success') nextPatient.value.status = "di-loket";
} currentProcessingPatient.value = nextPatient.value;
quotaUsed.value++;
showSnackbar(
`Memanggil pasien ${nextPatient.value.noAntrian.split(" |")[0]}`,
"success"
);
};
const processPatient = (patient, action) => {
const patientCode = patient.noAntrian.split(" |")[0];
switch (action) {
case "check-in":
patient.status = "processed";
if (currentProcessingPatient.value?.no === patient.no) {
currentProcessingPatient.value = null;
}
showSnackbar(`Pasien ${patientCode} berhasil check in`, "success");
break;
case "terlambat":
patient.status = "terlambat";
if (currentProcessingPatient.value?.no === patient.no) {
currentProcessingPatient.value = null;
}
showSnackbar(`Pasien ${patientCode} ditandai terlambat`, "warning");
break;
case "pending":
patient.status = "pending";
if (currentProcessingPatient.value?.no === patient.no) {
currentProcessingPatient.value = null;
}
showSnackbar(`Pasien ${patientCode} di-pending`, "info");
break;
case "aktifkan":
if (patient.status === "terlambat") {
patient.status = "di-loket";
showSnackbar(`Pasien ${patientCode} diaktifkan kembali`, "success");
}
break;
case "proses":
currentProcessingPatient.value = patient;
showSnackbar(`Memproses pasien ${patientCode}`, "info");
break;
}
};
const getRowClass = (item) => { const getRowClass = (item) => {
if (item.status === "current") { if (item.status === "current") {
@@ -367,9 +572,11 @@ const getRowClass = (item) => {
.call-controls-card, .call-controls-card,
.next-patient-card, .next-patient-card,
.current-processing-card,
.quota-info-card,
.main-table-card, .main-table-card,
.late-table-card, .late-table-card,
.clinic-table-card { .pending-table-card {
border-radius: 16px; border-radius: 16px;
border: 1px solid rgba(0, 0, 0, 0.05); border: 1px solid rgba(0, 0, 0, 0.05);
} }
@@ -379,8 +586,29 @@ const getRowClass = (item) => {
border: 2px solid rgba(76, 175, 80, 0.2); border: 2px solid rgba(76, 175, 80, 0.2);
} }
.current-processing-card {
background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%);
border: 2px solid rgba(255, 152, 0, 0.2);
}
.quota-info-card {
background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
border: 2px solid rgba(33, 150, 243, 0.2);
}
.patient-info .text-h5 {
color: #1976d2;
}
.action-buttons {
display: flex;
align-items: center;
}
/* Enhanced table styling */ /* Enhanced table styling */
.main-table-card :deep(.v-data-table th) { .main-table-card :deep(.v-data-table th),
.late-table-card :deep(.v-data-table th),
.pending-table-card :deep(.v-data-table th) {
background: #fafbfc; background: #fafbfc;
font-weight: 600; font-weight: 600;
font-size: 13px; font-size: 13px;
@@ -388,15 +616,15 @@ const getRowClass = (item) => {
border-bottom: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb;
} }
.main-table-card :deep(.v-data-table tbody tr:nth-child(1)) { .main-table-card :deep(.v-data-table tbody tr:hover),
background-color: #fff3cd !important; .late-table-card :deep(.v-data-table tbody tr:hover),
} .pending-table-card :deep(.v-data-table tbody tr:hover) {
.main-table-card :deep(.v-data-table tbody tr:hover) {
background: #f8fafc !important; background: #f8fafc !important;
} }
.main-table-card :deep(.v-data-table tbody td) { .main-table-card :deep(.v-data-table tbody td),
.late-table-card :deep(.v-data-table tbody td),
.pending-table-card :deep(.v-data-table tbody td) {
padding: 12px 16px; padding: 12px 16px;
border-bottom: 1px solid #f1f5f9; border-bottom: 1px solid #f1f5f9;
} }
@@ -432,6 +660,29 @@ const getRowClass = (item) => {
.page-title { .page-title {
font-size: 28px; font-size: 28px;
} }
.current-processing-card .d-flex {
flex-direction: column;
gap: 20px;
align-items: flex-start;
}
.action-buttons {
flex-direction: row;
flex-wrap: wrap;
gap: 8px;
width: 100%;
}
.action-buttons .v-btn {
flex: 1;
min-width: 120px;
}
/* Stack layout vertically on medium screens */
.call-controls-card .d-flex {
justify-content: center;
}
} }
@media (max-width: 768px) { @media (max-width: 768px) {
@@ -453,13 +704,34 @@ const getRowClass = (item) => {
.call-controls-card .d-flex { .call-controls-card .d-flex {
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: center;
gap: 16px; gap: 16px;
} }
.call-controls-card .v-btn { .call-controls-card .v-btn {
min-width: 80px; min-width: 80px;
} }
/* Stack all control buttons vertically on mobile */
.call-controls-card .d-flex.flex-wrap {
flex-direction: column;
align-items: stretch;
}
.call-controls-card .v-btn {
width: 100%;
margin: 4px 0;
}
.action-buttons {
flex-direction: column;
width: 100%;
}
.action-buttons .v-btn {
width: 100%;
margin: 4px 0;
}
} }
@media (max-width: 600px) { @media (max-width: 600px) {
@@ -467,12 +739,16 @@ const getRowClass = (item) => {
font-size: 20px; font-size: 20px;
} }
.next-patient-card .text-h3 { .next-patient-card .text-h4 {
font-size: 2rem !important; font-size: 1.75rem !important;
} }
.call-controls-card .d-flex.flex-wrap { .current-processing-card .patient-info .text-h5 {
justify-content: center; font-size: 1.25rem !important;
}
.quota-info-card .text-h4 {
font-size: 1.5rem !important;
} }
} }
</style> </style>

View File

@@ -1,64 +1,93 @@
<!-- pages/data-pasien.vue --> <!-- pages/data-pasien.vue -->
<template> <template>
<div class="data-pasien"> <div class="data-pasien-container">
<!-- Header --> <div class="data-pasien">
<div class="d-flex justify-space-between align-center mb-4"> <!-- Header -->
<h2>Data Pasien</h2> <!-- <div class="d-flex justify-space-between align-center mb-4">
<div class="d-flex gap-2"> <h2>Data Pasien</h2>
<v-btn color=#ff9248 prepend-icon="mdi-plus" @click="addPatient" style="color:white"> <div class="d-flex gap-2">
Tambah Pasien
</v-btn>
</div>
</div>
<!-- Menggunakan komponen TabelData -->
<TabelData
:headers="headers"
:items="pasienItems"
title="Daftar Data Pasien"
:show-search="true"
>
<template #actions="{ item }">
<div class="d-flex gap-1">
<v-btn <v-btn
color="#ff9248"
size="small" prepend-icon="mdi-plus"
color=#ff9248 @click="addPatient"
variant="flat" style="color: white"
@click="viewPasien(item)" >
style="color:white;" Tambah Pasien
>VIEW</v-btn> </v-btn>
<v-btn
size="small"
color="grey-lighten-4"
variant="flat"
@click="editPasien(item)"
>EDIT</v-btn>
</div> </div>
</template> </div> -->
</TabelData> <div class="page-header">
<div class="header-content">
<div class="header-left">
<div class="header-icon">
<v-icon size="32" color="white">mdi-view-dashboard</v-icon>
</div>
<div class="header-text">
<h1 class="page-title">Data Pasien</h1>
</div>
</div>
<div class="header-right">
<v-btn
color="#ff9248"
prepend-icon="mdi-plus"
@click="addPatient"
style="color: white"
>
Tambah Pasien
</v-btn>
</div>
</div>
</div>
<!-- Menggunakan komponen TabelData -->
<TabelData
:headers="headers"
:items="pasienItems"
title="Daftar Data Pasien"
:show-search="true"
>
<template #actions="{ item }">
<div class="d-flex gap-1">
<v-btn
size="small"
color="#ff9248"
variant="flat"
@click="viewPasien(item)"
style="color: white"
>VIEW</v-btn
>
<v-btn
size="small"
color="grey-lighten-4"
variant="flat"
@click="editPasien(item)"
>EDIT</v-btn
>
</div>
</template>
</TabelData>
</div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, computed } from 'vue'; import { ref, computed } from "vue";
import TabelData from '@/components/TabelData.vue'; import TabelData from "@/components/TabelData.vue";
// Headers untuk tabel // Headers untuk tabel
const headers = [ const headers = [
{ title: 'No', key: 'no', sortable: false, width: '60px' }, { title: "No", key: "no", sortable: false, width: "60px" },
{ title: 'Tgl Daftar', key: 'tgl_daftar', sortable: true, width: '140px' }, { title: "Tgl Daftar", key: "tgl_daftar", sortable: true, width: "140px" },
{ title: 'No Barcode', key: 'no_barcode', sortable: true, width: '120px' }, { title: "No Barcode", key: "no_barcode", sortable: true, width: "120px" },
{ title: 'No Antrian', key: 'no_antrian', sortable: true, width: '100px' }, { title: "No Antrian", key: "no_antrian", sortable: true, width: "100px" },
{ title: 'No Klinik', key: 'no_klinik', sortable: true, width: '100px' }, { title: "No Klinik", key: "no_klinik", sortable: true, width: "100px" },
{ title: 'RM', key: 'rm', sortable: true, width: '100px' }, { title: "RM", key: "rm", sortable: true, width: "100px" },
{ title: 'Klinik', key: 'klinik', sortable: true, width: '120px' }, { title: "Klinik", key: "klinik", sortable: true, width: "120px" },
{ title: 'Shift', key: 'shift', sortable: true, width: '80px' }, { title: "Shift", key: "shift", sortable: true, width: "80px" },
{ title: 'Ket', key: 'keterangan', sortable: false, width: '150px' }, { title: "Ket", key: "keterangan", sortable: false, width: "150px" },
{ title: 'Pembayaran', key: 'pembayaran', sortable: true, width: '100px' }, { title: "Pembayaran", key: "pembayaran", sortable: true, width: "100px" },
{ title: 'Status', key: 'status', sortable: true, width: '120px' }, { title: "Status", key: "status", sortable: true, width: "120px" },
{ title: 'Aksi', key: 'aksi', sortable: false, width: '100px' } { title: "Aksi", key: "aksi", sortable: false, width: "100px" },
]; ];
// Data pasien dengan informasi lengkap untuk edit // Data pasien dengan informasi lengkap untuk edit
@@ -66,275 +95,275 @@ const pasienItems = ref([
{ {
id: 1, id: 1,
no: 1, no: 1,
tgl_daftar: '2025-07-15 13:47:33', tgl_daftar: "2025-07-15 13:47:33",
no_barcode: '25027100001', no_barcode: "25027100001",
no_antrian: 'HO1001', no_antrian: "HO1001",
no_klinik: '', no_klinik: "",
rm: '', rm: "",
klinik: 'HOM', klinik: "HOM",
shift: 'Shift 1', shift: "Shift 1",
keterangan: '', keterangan: "",
pembayaran: 'JKN', pembayaran: "JKN",
status: 'Tunggu Daftar', status: "Tunggu Daftar",
// Data tambahan untuk form edit // Data tambahan untuk form edit
editData: { editData: {
tanggal_daftar: '2025-07-15 13:47:33', tanggal_daftar: "2025-07-15 13:47:33",
tanggal_periksa: '2025-08-27', tanggal_periksa: "2025-08-27",
no_barcode: '25027100001', no_barcode: "25027100001",
no_antrian: 'HO1001', no_antrian: "HO1001",
no_klinik: 'Belum Mendapatkan Antrian Klinik', no_klinik: "Belum Mendapatkan Antrian Klinik",
no_rekammedik: '', no_rekammedik: "",
klinik: 'HOM', klinik: "HOM",
shift: 'Shift 1 = Mulai Pukul 07:00', shift: "Shift 1 = Mulai Pukul 07:00",
keterangan: '', keterangan: "",
pembayaran: 'JKN' pembayaran: "JKN",
} },
}, },
{ {
id: 2, id: 2,
no: 2, no: 2,
tgl_daftar: '2025-07-24 13:50:01', tgl_daftar: "2025-07-24 13:50:01",
no_barcode: '25027100002', no_barcode: "25027100002",
no_antrian: 'OB1001', no_antrian: "OB1001",
no_klinik: '', no_klinik: "",
rm: '', rm: "",
klinik: 'KANDUNGAN', klinik: "KANDUNGAN",
shift: 'Shift 1', shift: "Shift 1",
keterangan: '', keterangan: "",
pembayaran: 'JKN', pembayaran: "JKN",
status: 'Barcode', status: "Barcode",
editData: { editData: {
tanggal_daftar: '2025-07-24 13:50:01', tanggal_daftar: "2025-07-24 13:50:01",
tanggal_periksa: '2025-08-27', tanggal_periksa: "2025-08-27",
no_barcode: '25027100002', no_barcode: "25027100002",
no_antrian: 'OB1001', no_antrian: "OB1001",
no_klinik: '', no_klinik: "",
no_rekammedik: '', no_rekammedik: "",
klinik: 'KANDUNGAN', klinik: "KANDUNGAN",
shift: 'Shift 1 = Mulai Pukul 07:00', shift: "Shift 1 = Mulai Pukul 07:00",
keterangan: '', keterangan: "",
pembayaran: 'JKN' pembayaran: "JKN",
} },
}, },
{ {
id: 3, id: 3,
no: 3, no: 3,
tgl_daftar: '2025-07-24 13:50:37', tgl_daftar: "2025-07-24 13:50:37",
no_barcode: '25027100003', no_barcode: "25027100003",
no_antrian: 'OB1002', no_antrian: "OB1002",
no_klinik: '', no_klinik: "",
rm: '', rm: "",
klinik: 'KANDUNGAN', klinik: "KANDUNGAN",
shift: 'Shift 1', shift: "Shift 1",
keterangan: '', keterangan: "",
pembayaran: 'JKN', pembayaran: "JKN",
status: 'Barcode', status: "Barcode",
editData: { editData: {
tanggal_daftar: '2025-07-24 13:50:37', tanggal_daftar: "2025-07-24 13:50:37",
tanggal_periksa: '2025-08-27', tanggal_periksa: "2025-08-27",
no_barcode: '25027100003', no_barcode: "25027100003",
no_antrian: 'OB1002', no_antrian: "OB1002",
no_klinik: '', no_klinik: "",
no_rekammedik: '', no_rekammedik: "",
klinik: 'KANDUNGAN', klinik: "KANDUNGAN",
shift: 'Shift 1 = Mulai Pukul 07:00', shift: "Shift 1 = Mulai Pukul 07:00",
keterangan: '', keterangan: "",
pembayaran: 'JKN' pembayaran: "JKN",
} },
}, },
{ {
id: 4, id: 4,
no: 4, no: 4,
tgl_daftar: '2025-07-28 08:18:20', tgl_daftar: "2025-07-28 08:18:20",
no_barcode: '25027100004', no_barcode: "25027100004",
no_antrian: 'AN1001', no_antrian: "AN1001",
no_klinik: '', no_klinik: "",
rm: '', rm: "",
klinik: 'ANAK', klinik: "ANAK",
shift: 'Shift 1', shift: "Shift 1",
keterangan: '', keterangan: "",
pembayaran: 'JKN', pembayaran: "JKN",
status: 'Barcode', status: "Barcode",
editData: { editData: {
tanggal_daftar: '2025-07-28 08:18:20', tanggal_daftar: "2025-07-28 08:18:20",
tanggal_periksa: '2025-08-27', tanggal_periksa: "2025-08-27",
no_barcode: '25027100004', no_barcode: "25027100004",
no_antrian: 'AN1001', no_antrian: "AN1001",
no_klinik: '', no_klinik: "",
no_rekammedik: '', no_rekammedik: "",
klinik: 'ANAK', klinik: "ANAK",
shift: 'Shift 1 = Mulai Pukul 07:00', shift: "Shift 1 = Mulai Pukul 07:00",
keterangan: '', keterangan: "",
pembayaran: 'JKN' pembayaran: "JKN",
} },
}, },
{ {
id: 5, id: 5,
no: 5, no: 5,
tgl_daftar: '2025-08-13 00:00:02', tgl_daftar: "2025-08-13 00:00:02",
no_barcode: '25027100005', no_barcode: "25027100005",
no_antrian: 'HO1002', no_antrian: "HO1002",
no_klinik: '', no_klinik: "",
rm: '11412684', rm: "11412684",
klinik: 'HOM', klinik: "HOM",
shift: 'Shift 1', shift: "Shift 1",
keterangan: 'Online 25#27100005', keterangan: "Online 25#27100005",
pembayaran: 'JKN', pembayaran: "JKN",
status: 'Tunggu Daftar', status: "Tunggu Daftar",
editData: { editData: {
tanggal_daftar: '2025-08-13 00:00:02', tanggal_daftar: "2025-08-13 00:00:02",
tanggal_periksa: '2025-08-27', tanggal_periksa: "2025-08-27",
no_barcode: '25027100005', no_barcode: "25027100005",
no_antrian: 'HO1002', no_antrian: "HO1002",
no_klinik: 'Belum Mendapatkan Antrian Klinik', no_klinik: "Belum Mendapatkan Antrian Klinik",
no_rekammedik: '11412684', no_rekammedik: "11412684",
klinik: 'HOM', klinik: "HOM",
shift: 'Shift 1 = Mulai Pukul 07:00', shift: "Shift 1 = Mulai Pukul 07:00",
keterangan: 'Online 25#27100005', keterangan: "Online 25#27100005",
pembayaran: 'JKN' pembayaran: "JKN",
} },
}, },
{ {
id: 6, id: 6,
no: 6, no: 6,
tgl_daftar: '2025-08-13 00:00:03', tgl_daftar: "2025-08-13 00:00:03",
no_barcode: '25027100006', no_barcode: "25027100006",
no_antrian: 'HO1003', no_antrian: "HO1003",
no_klinik: '', no_klinik: "",
rm: '', rm: "",
klinik: 'HOM', klinik: "HOM",
shift: 'Shift 1', shift: "Shift 1",
keterangan: 'Online 25#27100006', keterangan: "Online 25#27100006",
pembayaran: 'JKN', pembayaran: "JKN",
status: 'Tunggu Daftar', status: "Tunggu Daftar",
editData: { editData: {
tanggal_daftar: '2025-08-13 00:00:03', tanggal_daftar: "2025-08-13 00:00:03",
tanggal_periksa: '2025-08-27', tanggal_periksa: "2025-08-27",
no_barcode: '25027100006', no_barcode: "25027100006",
no_antrian: 'HO1003', no_antrian: "HO1003",
no_klinik: 'Belum Mendapatkan Antrian Klinik', no_klinik: "Belum Mendapatkan Antrian Klinik",
no_rekammedik: '', no_rekammedik: "",
klinik: 'HOM', klinik: "HOM",
shift: 'Shift 1 = Mulai Pukul 07:00', shift: "Shift 1 = Mulai Pukul 07:00",
keterangan: 'Online 25#27100006', keterangan: "Online 25#27100006",
pembayaran: 'JKN' pembayaran: "JKN",
} },
}, },
{ {
id: 7, id: 7,
no: 7, no: 7,
tgl_daftar: '2025-08-13 00:00:03', tgl_daftar: "2025-08-13 00:00:03",
no_barcode: '25027100007', no_barcode: "25027100007",
no_antrian: 'IP1001', no_antrian: "IP1001",
no_klinik: '', no_klinik: "",
rm: '11555500', rm: "11555500",
klinik: 'IPD', klinik: "IPD",
shift: 'Shift 1', shift: "Shift 1",
keterangan: 'Online 25#27100007', keterangan: "Online 25#27100007",
pembayaran: 'JKN', pembayaran: "JKN",
status: 'Tunggu Daftar', status: "Tunggu Daftar",
editData: { editData: {
tanggal_daftar: '2025-08-13 00:00:03', tanggal_daftar: "2025-08-13 00:00:03",
tanggal_periksa: '2025-08-27', tanggal_periksa: "2025-08-27",
no_barcode: '25027100007', no_barcode: "25027100007",
no_antrian: 'IP1001', no_antrian: "IP1001",
no_klinik: 'Belum Mendapatkan Antrian Klinik', no_klinik: "Belum Mendapatkan Antrian Klinik",
no_rekammedik: '11555500', no_rekammedik: "11555500",
klinik: 'IPD', klinik: "IPD",
shift: 'Shift 1 = Mulai Pukul 07:00', shift: "Shift 1 = Mulai Pukul 07:00",
keterangan: 'FINGATMANA ONLINE', keterangan: "FINGATMANA ONLINE",
pembayaran: 'JKN' pembayaran: "JKN",
} },
}, },
{ {
id: 8, id: 8,
no: 8, no: 8,
tgl_daftar: '2025-08-13 00:00:04', tgl_daftar: "2025-08-13 00:00:04",
no_barcode: '25027100008', no_barcode: "25027100008",
no_antrian: 'IP1001', no_antrian: "IP1001",
no_klinik: '', no_klinik: "",
rm: '11333855', rm: "11333855",
klinik: 'IPD', klinik: "IPD",
shift: 'Shift 1', shift: "Shift 1",
keterangan: 'Online 25#27100008', keterangan: "Online 25#27100008",
pembayaran: 'JKN', pembayaran: "JKN",
status: 'Tunggu Daftar', status: "Tunggu Daftar",
editData: { editData: {
tanggal_daftar: '2025-08-13 00:00:04', tanggal_daftar: "2025-08-13 00:00:04",
tanggal_periksa: '2025-08-27', tanggal_periksa: "2025-08-27",
no_barcode: '25027100008', no_barcode: "25027100008",
no_antrian: 'IP1001', no_antrian: "IP1001",
no_klinik: 'Belum Mendapatkan Antrian Klinik', no_klinik: "Belum Mendapatkan Antrian Klinik",
no_rekammedik: '11333855', no_rekammedik: "11333855",
klinik: 'IPD', klinik: "IPD",
shift: 'Shift 1 = Mulai Pukul 07:00', shift: "Shift 1 = Mulai Pukul 07:00",
keterangan: 'Online 25#27100008', keterangan: "Online 25#27100008",
pembayaran: 'JKN' pembayaran: "JKN",
} },
}, },
{ {
id: 9, id: 9,
no: 9, no: 9,
tgl_daftar: '2025-08-13 00:00:04', tgl_daftar: "2025-08-13 00:00:04",
no_barcode: '25027100009', no_barcode: "25027100009",
no_antrian: 'IP1001', no_antrian: "IP1001",
no_klinik: '', no_klinik: "",
rm: '11565554', rm: "11565554",
klinik: 'IPD', klinik: "IPD",
shift: 'Shift 1', shift: "Shift 1",
keterangan: 'Online 25#27100009', keterangan: "Online 25#27100009",
pembayaran: 'JKN', pembayaran: "JKN",
status: 'Tunggu Daftar', status: "Tunggu Daftar",
editData: { editData: {
tanggal_daftar: '2025-08-13 00:00:04', tanggal_daftar: "2025-08-13 00:00:04",
tanggal_periksa: '2025-08-27', tanggal_periksa: "2025-08-27",
no_barcode: '25027100009', no_barcode: "25027100009",
no_antrian: 'IP1001', no_antrian: "IP1001",
no_klinik: 'Belum Mendapatkan Antrian Klinik', no_klinik: "Belum Mendapatkan Antrian Klinik",
no_rekammedik: '11565554', no_rekammedik: "11565554",
klinik: 'IPD', klinik: "IPD",
shift: 'Shift 1 = Mulai Pukul 07:00', shift: "Shift 1 = Mulai Pukul 07:00",
keterangan: 'Online 25#27100009', keterangan: "Online 25#27100009",
pembayaran: 'JKN' pembayaran: "JKN",
} },
}, },
{ {
id: 10, id: 10,
no: 10, no: 10,
tgl_daftar: '2025-08-13 00:00:04', tgl_daftar: "2025-08-13 00:00:04",
no_barcode: '25027100010', no_barcode: "25027100010",
no_antrian: 'IP1001', no_antrian: "IP1001",
no_klinik: '', no_klinik: "",
rm: '11627608', rm: "11627608",
klinik: 'IPD', klinik: "IPD",
shift: 'Shift 1', shift: "Shift 1",
keterangan: 'Online 25#27100010', keterangan: "Online 25#27100010",
pembayaran: 'JKN', pembayaran: "JKN",
status: 'Tunggu Daftar', status: "Tunggu Daftar",
editData: { editData: {
tanggal_daftar: '2025-08-13 00:00:04', tanggal_daftar: "2025-08-13 00:00:04",
tanggal_periksa: '2025-08-27', tanggal_periksa: "2025-08-27",
no_barcode: '25027100010', no_barcode: "25027100010",
no_antrian: 'IP1001', no_antrian: "IP1001",
no_klinik: 'Belum Mendapatkan Antrian Klinik', no_klinik: "Belum Mendapatkan Antrian Klinik",
no_rekammedik: '11627608', no_rekammedik: "11627608",
klinik: 'IPD', klinik: "IPD",
shift: 'Shift 1 = Mulai Pukul 07:00', shift: "Shift 1 = Mulai Pukul 07:00",
keterangan: 'Online 25#27100010', keterangan: "Online 25#27100010",
pembayaran: 'JKN' pembayaran: "JKN",
} },
} },
]); ]);
// Methods // Methods
const addPatient = () => { const addPatient = () => {
// Navigate to add patient page // Navigate to add patient page
navigateTo('/data-pasien/add'); navigateTo("/data-pasien/add");
}; };
const viewPasien = (item) => { const viewPasien = (item) => {
// Implement view functionality // Implement view functionality
console.log('View pasien:', item); console.log("View pasien:", item);
// You can navigate to a view page or open a modal // You can navigate to a view page or open a modal
// navigateTo(`/data-pasien/view/${item.id}`); // navigateTo(`/data-pasien/view/${item.id}`);
}; };
@@ -345,10 +374,55 @@ const editPasien = (item) => {
}; };
// Provide data globally untuk diakses oleh halaman edit // Provide data globally untuk diakses oleh halaman edit
provide('pasienData', pasienItems); provide("pasienData", pasienItems);
</script> </script>
<style scoped> <style scoped>
.data-pasien-container {
background: #f5f7fa;
min-height: 100vh;
padding: 20px;
}
.page-header {
background: linear-gradient(135deg, #1976d2 0%, #1565c0 100%);
border-radius: 16px;
margin-bottom: 24px;
box-shadow: 0 8px 32px rgba(25, 118, 210, 0.3);
}
.header-content {
display: flex;
align-items: center;
justify-content: space-between;
padding: 32px;
color: rgb(255, 255, 255);
}
.header-left {
display: flex;
align-items: center;
}
.header-icon {
background: rgba(255, 255, 255, 0.2);
border-radius: 16px;
padding: 16px;
margin-right: 20px;
backdrop-filter: blur(10px);
}
.page-title {
font-size: 32px;
font-weight: 700;
margin: 0;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.header-right {
display: flex;
align-items: center;
}
.data-pasien { .data-pasien {
padding: 20px; padding: 20px;
} }