feat(FE) : layouting dashboard,antrean,pendaftaran
This commit is contained in:
No files matched your search
@@ -151,44 +151,8 @@ const sessionInfo = computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<v-divider></v-divider>
|
||||
</div>
|
||||
|
||||
<PerfectScrollbar style="height: calc(100vh - 240px); max-height: 240px">
|
||||
<v-list class="py-0 theme-list" lines="two">
|
||||
<v-list-item
|
||||
v-for="item in profileDD"
|
||||
:key="item.title"
|
||||
class="py-4 px-8 custom-text-primary"
|
||||
:to="item.href"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<v-avatar
|
||||
size="48"
|
||||
color="lightprimary"
|
||||
class="mr-3"
|
||||
rounded="md"
|
||||
>
|
||||
<img
|
||||
:src="item.avatar"
|
||||
width="24"
|
||||
height="24"
|
||||
:alt="item.avatar"
|
||||
/>
|
||||
</v-avatar>
|
||||
</template>
|
||||
<div>
|
||||
<h6 class="text-subtitle-1 font-weight-bold mb-2 custom-title">
|
||||
{{ item.title }}
|
||||
</h6>
|
||||
</div>
|
||||
<p class="text-subtitle-1 font-weight-regular textSecondary">
|
||||
{{ item.subtitle }}
|
||||
</p>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</PerfectScrollbar>
|
||||
|
||||
<!-- **DIPERBAIKI: Logout buttons section dengan multiple options** -->
|
||||
<div class="pt-4 pb-6 px-8">
|
||||
<!-- Regular Logout Button -->
|
||||
@@ -203,24 +167,7 @@ const sessionInfo = computed(() => {
|
||||
Logout
|
||||
</v-btn>
|
||||
|
||||
<!-- **TAMBAHAN: Full Logout Button** -->
|
||||
<v-btn
|
||||
color="error"
|
||||
variant="outlined"
|
||||
block
|
||||
@click="fullLogout"
|
||||
prepend-icon="mdi-logout-variant"
|
||||
class="mb-2"
|
||||
>
|
||||
Full Logout
|
||||
</v-btn>
|
||||
|
||||
<!-- **TAMBAHAN: Quick info text** -->
|
||||
<div class="text-center mt-2">
|
||||
<span class="text-caption textSecondary">
|
||||
Full logout akan menghapus semua sesi dan data lokal
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</v-sheet>
|
||||
</v-menu>
|
||||
|
||||
@@ -44,13 +44,13 @@ watch(priority, (newPriority) => {
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Search part -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<Searchbar />
|
||||
<!-- <Searchbar /> -->
|
||||
|
||||
<!-- ---------------------------------------------- -->
|
||||
<!-- Mega menu -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<div class="hidden-sm-and-down">
|
||||
<Navigations />
|
||||
<!-- <Navigations /> -->
|
||||
</div>
|
||||
|
||||
<v-spacer class="hidden-sm-and-down" />
|
||||
@@ -85,7 +85,7 @@ watch(priority, (newPriority) => {
|
||||
<!-- Notification -->
|
||||
<!-- ---------------------------------------------- -->
|
||||
<div class="hidden-sm-and-down">
|
||||
<NotificationDD />
|
||||
<!-- <NotificationDD /> -->
|
||||
</div>
|
||||
|
||||
<!-- ---------------------------------------------- -->
|
||||
|
||||
@@ -51,60 +51,7 @@ const sidebarMenu = shallowRef(sidebarItems);
|
||||
|
||||
<template>
|
||||
<!-- Minisidebar Icons -->
|
||||
<v-navigation-drawer
|
||||
class="bg-light"
|
||||
v-model="customizer.Sidebar_drawer"
|
||||
top="0"
|
||||
rail
|
||||
rail-width="80"
|
||||
>
|
||||
<!-- <perfect-scrollbar class="miniscrollnavbar"> -->
|
||||
<v-list-item class="px-0">
|
||||
<!-- Toggle Sidebar Button -->
|
||||
<div class="px-4 mb-3">
|
||||
<v-btn
|
||||
class="hidden-md-and-down my-2"
|
||||
icon
|
||||
rounded="md"
|
||||
variant="plain"
|
||||
@click.stop="customizer.SET_MINI_SIDEBAR(!customizer.mini_sidebar)"
|
||||
>
|
||||
<Icon icon="solar:hamburger-menu-line-duotone" height="25" />
|
||||
</v-btn>
|
||||
</div>
|
||||
|
||||
<div class="miniicons mt-lg-0 mt-4">
|
||||
<!-- MiniSidebar Icons -->
|
||||
<div class="d-flex flex-column gap-2">
|
||||
<div
|
||||
class="miniicons-list px-4"
|
||||
v-for="menu in MiniSideIcons"
|
||||
:key="menu.icon"
|
||||
>
|
||||
<v-btn
|
||||
rounded="md"
|
||||
flat
|
||||
icon
|
||||
variant="plain"
|
||||
@click="showData(menu.id)"
|
||||
:class="{ 'bg-primary opacity-1': currentMenu === menu.id }"
|
||||
>
|
||||
<Icon :icon="'solar:' + menu.icon" width="25" />
|
||||
<!-- Tooltip on Hover -->
|
||||
<v-tooltip
|
||||
activator="parent"
|
||||
location="end"
|
||||
class="custom-tooltip"
|
||||
>{{ menu.tooltip }}</v-tooltip
|
||||
>
|
||||
</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</v-list-item>
|
||||
|
||||
<!-- </perfect-scrollbar> -->
|
||||
</v-navigation-drawer>
|
||||
|
||||
|
||||
<!-- LeftSidebar Items -->
|
||||
<v-navigation-drawer
|
||||
|
||||
@@ -21,209 +21,29 @@ const sidebarItem: menu[] = [
|
||||
id: 1,
|
||||
children: [
|
||||
{
|
||||
title: 'Dashboard1',
|
||||
title: 'Dashboard',
|
||||
icon: 'widget-add-line-duotone',
|
||||
to: '/dashboards/dashboard1'
|
||||
},
|
||||
{
|
||||
title: 'Dashboard2',
|
||||
icon: 'chart-line-duotone',
|
||||
to: '/dashboards/dashboard2'
|
||||
},
|
||||
{
|
||||
title: 'Dashboard3',
|
||||
icon: 'screencast-2-line-duotone',
|
||||
to: '/dashboards/dashboard3'
|
||||
},
|
||||
{
|
||||
title: 'Front Pages',
|
||||
icon: 'home-angle-linear',
|
||||
to: '/',
|
||||
children: [
|
||||
{
|
||||
title: 'Homepage',
|
||||
to: '/front-page/homepage'
|
||||
},
|
||||
{
|
||||
title: 'About Us',
|
||||
to: '/front-page/about-us'
|
||||
},
|
||||
{
|
||||
title: 'Blog',
|
||||
to: '/front-page/blog/posts'
|
||||
},
|
||||
{
|
||||
title: 'Blog Details',
|
||||
to: '/front-page/blog/early-black-friday-amazon-deals-cheap-tvs-headphones'
|
||||
},
|
||||
{
|
||||
title: 'Contact Us',
|
||||
to: '/front-page/contact-us'
|
||||
},
|
||||
{
|
||||
title: 'Portfolio',
|
||||
to: '/front-page/portfolio'
|
||||
},
|
||||
{
|
||||
title: 'Pricing',
|
||||
to: '/front-page/pricing'
|
||||
}
|
||||
]
|
||||
},
|
||||
to: '/'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
header: 'apps',
|
||||
header: 'antrean',
|
||||
id: 1,
|
||||
children: [
|
||||
{
|
||||
title: 'ECommerce',
|
||||
title: 'Semua',
|
||||
icon: 'cart-3-line-duotone',
|
||||
to: '/ecommerce/',
|
||||
children: [
|
||||
{
|
||||
title: 'Shop',
|
||||
to: '/ecommerce/products'
|
||||
},
|
||||
{
|
||||
title: 'Detail',
|
||||
to: '/ecommerce/product/detail/1'
|
||||
},
|
||||
{
|
||||
title: 'List',
|
||||
to: '/ecommerce/productlist'
|
||||
},
|
||||
{
|
||||
title: 'Checkout',
|
||||
to: '/ecommerce/checkout'
|
||||
},
|
||||
{
|
||||
title: 'Add Product',
|
||||
to: '/ecommerce/add-product'
|
||||
},
|
||||
{
|
||||
title: 'Edit Product',
|
||||
to: '/ecommerce/edit-product'
|
||||
}
|
||||
]
|
||||
to: '/antrean/all',
|
||||
},
|
||||
{
|
||||
title: 'Blog',
|
||||
title: 'Spesialis',
|
||||
icon: 'widget-4-line-duotone',
|
||||
to: '/',
|
||||
children: [
|
||||
{
|
||||
title: 'Blog Posts',
|
||||
to: '/apps/blog/posts'
|
||||
},
|
||||
{
|
||||
title: 'Blog Details',
|
||||
to: '/apps/blog/early-black-friday-amazon-deals-cheap-tvs-headphones'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'User Profile',
|
||||
icon: 'shield-user-line-duotone',
|
||||
to: '/',
|
||||
children: [
|
||||
{
|
||||
title: 'Profile',
|
||||
to: '/apps/user/profile'
|
||||
},
|
||||
{
|
||||
title: 'Followers',
|
||||
to: '/apps/user/profile/followers'
|
||||
},
|
||||
{
|
||||
title: 'Friends',
|
||||
to: '/apps/user/profile/friends'
|
||||
},
|
||||
{
|
||||
title: 'Gallery',
|
||||
to: '/apps/user/profile/gallery'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Invoice',
|
||||
icon: 'bill-check-outline',
|
||||
to: '/',
|
||||
children: [
|
||||
{
|
||||
title: 'List',
|
||||
to: '/apps/invoice'
|
||||
},
|
||||
{
|
||||
title: 'Details',
|
||||
to: '/apps/invoice/details/102'
|
||||
},
|
||||
{
|
||||
title: 'Create',
|
||||
to: '/apps/invoice/create'
|
||||
},
|
||||
{
|
||||
title: 'Edit',
|
||||
to: '/apps/invoice/edit/102'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Calendar',
|
||||
icon: 'calendar-mark-line-duotone',
|
||||
to: '/apps/calendar'
|
||||
},
|
||||
{
|
||||
title: 'Email',
|
||||
icon: 'letter-linear',
|
||||
to: '/apps/email'
|
||||
},
|
||||
{
|
||||
title: 'Chats',
|
||||
icon: 'chat-round-line-line-duotone',
|
||||
to: '/apps/chats'
|
||||
},
|
||||
{
|
||||
title: 'Notes',
|
||||
icon: 'document-text-line-duotone',
|
||||
to: '/apps/notes'
|
||||
},
|
||||
{
|
||||
title: 'Kanban',
|
||||
icon: 'airbuds-case-minimalistic-line-duotone',
|
||||
to: '/apps/kanban'
|
||||
},
|
||||
{
|
||||
title: 'Contact',
|
||||
icon: 'iphone-line-duotone',
|
||||
to: '/apps/contacts'
|
||||
},
|
||||
{
|
||||
title: 'Tickets',
|
||||
icon: 'ticker-star-outline',
|
||||
to: '/apps/tickets'
|
||||
},
|
||||
to: '/antrean/list-spesialis'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
header: 'Master',
|
||||
id: 2,
|
||||
children: [
|
||||
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
header: 'Forms',
|
||||
id: 3,
|
||||
children: [
|
||||
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
];
|
||||
|
||||
export default sidebarItem;
|
||||
@@ -0,0 +1,248 @@
|
||||
<script setup lang="ts">
|
||||
const formData = defineModel<{
|
||||
noRekamMedis: string;
|
||||
noKtp: string;
|
||||
namaPasien: string;
|
||||
jenisKelamin: string;
|
||||
tanggalLahir: string;
|
||||
umur: string;
|
||||
alamat: string;
|
||||
nomorTelepon: string[];
|
||||
}>({ required: true });
|
||||
|
||||
const rules = {
|
||||
required: (value: string) => !!value || 'Field ini wajib diisi'
|
||||
};
|
||||
|
||||
// Modal state
|
||||
const showModal = ref(false);
|
||||
const newPhoneNumber = ref('');
|
||||
const editingIndex = ref<number | null>(null);
|
||||
|
||||
// Initialize nomorTelepon as array if not already
|
||||
if (!Array.isArray(formData.value.nomorTelepon)) {
|
||||
formData.value.nomorTelepon = [];
|
||||
}
|
||||
|
||||
const openAddModal = () => {
|
||||
newPhoneNumber.value = '';
|
||||
editingIndex.value = null;
|
||||
showModal.value = true;
|
||||
};
|
||||
|
||||
const editPhoneNumber = (index: number) => {
|
||||
const phone = formData.value.nomorTelepon[index];
|
||||
// Remove +62 prefix for editing
|
||||
newPhoneNumber.value = phone.startsWith('+62') ? phone.substring(3) : phone;
|
||||
editingIndex.value = index;
|
||||
showModal.value = true;
|
||||
};
|
||||
|
||||
// Handle only numeric input
|
||||
const handlePhoneInput = (event: Event) => {
|
||||
const input = event.target as HTMLInputElement;
|
||||
const value = input.value;
|
||||
|
||||
// Only allow numbers
|
||||
const numericValue = value.replace(/\D/g, '');
|
||||
newPhoneNumber.value = numericValue;
|
||||
};
|
||||
|
||||
const savePhoneNumber = () => {
|
||||
if (!newPhoneNumber.value.trim()) return;
|
||||
|
||||
const fullPhoneNumber = `+62${newPhoneNumber.value}`;
|
||||
|
||||
if (editingIndex.value !== null) {
|
||||
formData.value.nomorTelepon[editingIndex.value] = fullPhoneNumber;
|
||||
} else {
|
||||
formData.value.nomorTelepon.push(fullPhoneNumber);
|
||||
}
|
||||
|
||||
showModal.value = false;
|
||||
newPhoneNumber.value = '';
|
||||
editingIndex.value = null;
|
||||
};
|
||||
|
||||
const deletePhoneNumber = (index: number) => {
|
||||
formData.value.nomorTelepon.splice(index, 1);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-card elevation="10">
|
||||
<v-card-item>
|
||||
<h5 class="text-h5 font-weight-bold">Data Biodata Pasien</h5>
|
||||
</v-card-item>
|
||||
<v-divider></v-divider>
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<!-- No Rekam Medis -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">No Rekam Medis <span
|
||||
class="text-error">*</span></v-label>
|
||||
<v-text-field
|
||||
v-model="formData.noRekamMedis"
|
||||
placeholder="Masukan Nomor RM / Nama Pasien"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
:rules="[rules.required]"
|
||||
hide-details="auto"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<!-- No KTP -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">No Ktp</v-label>
|
||||
<v-text-field v-model="formData.noKtp" variant="outlined" density="comfortable"
|
||||
hide-details="auto" readonly bg-color="grey-lighten-3"></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<!-- Nama Pasien -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">Nama Pasien</v-label>
|
||||
<v-text-field v-model="formData.namaPasien" variant="outlined" density="comfortable"
|
||||
hide-details="auto" readonly bg-color="grey-lighten-3"></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<!-- Jenis Kelamin -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">Jenis Kelamin</v-label>
|
||||
<v-radio-group v-model="formData.jenisKelamin" inline hide-details="auto">
|
||||
<v-radio label="Laki-Laki" value="L" color="primary"></v-radio>
|
||||
<v-radio label="Perempuan" value="P" color="primary"></v-radio>
|
||||
</v-radio-group>
|
||||
</v-col>
|
||||
|
||||
<!-- Tanggal Lahir -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">Tanggal Lahir</v-label>
|
||||
<v-text-field v-model="formData.tanggalLahir" type="date" variant="outlined"
|
||||
density="comfortable" hide-details="auto" readonly
|
||||
bg-color="grey-lighten-3"></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<!-- Umur -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">Umur</v-label>
|
||||
<v-text-field v-model="formData.umur" variant="outlined" density="comfortable"
|
||||
hide-details="auto" readonly bg-color="grey-lighten-3"></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<!-- Alamat -->
|
||||
<v-col cols="12">
|
||||
<v-label class="mb-2 font-weight-medium">Alamat</v-label>
|
||||
<v-textarea v-model="formData.alamat" variant="outlined" rows="3" hide-details="auto"
|
||||
readonly bg-color="grey-lighten-3"></v-textarea>
|
||||
</v-col>
|
||||
|
||||
<!-- Nomor Telepon -->
|
||||
<v-col cols="12">
|
||||
<v-label class="mb-2 font-weight-medium">Nomor Telepon</v-label>
|
||||
|
||||
<!-- Alert when no phone numbers -->
|
||||
<v-alert
|
||||
v-if="formData.nomorTelepon.length === 0"
|
||||
type="info"
|
||||
variant="tonal"
|
||||
class="mb-3"
|
||||
density="compact"
|
||||
>
|
||||
<div class="d-flex align-center">
|
||||
<span>No items</span>
|
||||
</div>
|
||||
</v-alert>
|
||||
|
||||
<!-- List of phone numbers -->
|
||||
<v-list v-if="formData.nomorTelepon.length > 0" class="mb-3" density="compact">
|
||||
<v-list-item
|
||||
v-for="(phone, index) in formData.nomorTelepon"
|
||||
:key="index"
|
||||
class="px-4 mb-2"
|
||||
border
|
||||
@click="editPhoneNumber(index)"
|
||||
style="cursor: pointer;"
|
||||
>
|
||||
<template #default>
|
||||
<div class="d-flex align-center justify-space-between w-100">
|
||||
<span>{{ phone }}</span>
|
||||
<v-btn
|
||||
icon
|
||||
size="small"
|
||||
variant="text"
|
||||
color="error"
|
||||
@click.stop="deletePhoneNumber(index)"
|
||||
>
|
||||
<v-icon>mdi-delete</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
<!-- Add Button -->
|
||||
<v-btn
|
||||
color="primary"
|
||||
variant="flat"
|
||||
prepend-icon="mdi-plus"
|
||||
@click="openAddModal"
|
||||
>
|
||||
Tambah Nomor Telepon
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<!-- Modal for adding phone number -->
|
||||
<v-dialog v-model="showModal" max-width="600px">
|
||||
<v-card>
|
||||
<v-card-title class="d-flex align-center justify-space-between pa-4">
|
||||
<div class="d-flex align-center">
|
||||
<v-icon class="mr-3">mdi-package-variant</v-icon>
|
||||
<span class="text-h6">{{ editingIndex !== null ? 'Edit' : 'Tambah' }} Item Data Telepon Pasien Operasi</span>
|
||||
</div>
|
||||
<v-btn
|
||||
icon
|
||||
variant="text"
|
||||
@click="showModal = false"
|
||||
>
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-card-text class="pa-6">
|
||||
<v-label class="mb-2 font-weight-medium">Nomor Telepon</v-label>
|
||||
<v-text-field
|
||||
v-model="newPhoneNumber"
|
||||
placeholder="Masukan nomor telepon lengkap"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
hide-details="auto"
|
||||
type="tel"
|
||||
@input="handlePhoneInput"
|
||||
>
|
||||
<template #prepend-inner>
|
||||
<span class="text-medium-emphasis">+62</span>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</v-card-text>
|
||||
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-card-actions class="pa-4 justify-end">
|
||||
<v-btn
|
||||
color="primary"
|
||||
variant="flat"
|
||||
@click="savePhoneNumber"
|
||||
:disabled="!newPhoneNumber.trim()"
|
||||
>
|
||||
<v-icon start>mdi-check</v-icon>
|
||||
Save
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
@@ -0,0 +1,422 @@
|
||||
<script setup lang="ts">
|
||||
import diagnosisData from '~/data/mock/diagnosa.json';
|
||||
import tindakanData from '~/data/mock/tindakan.json';
|
||||
|
||||
interface DiagnosisItem {
|
||||
kodeDiagnosa: string;
|
||||
diagnosa: string;
|
||||
jenisDiagnosa: string;
|
||||
}
|
||||
|
||||
interface TindakanItem {
|
||||
kodeTindakan: string;
|
||||
tindakan: string;
|
||||
tindakanTambahan?: string;
|
||||
}
|
||||
|
||||
const diagnosisItems = defineModel<DiagnosisItem[]>('diagnosisItems', { required: true });
|
||||
const tindakanItems = defineModel<TindakanItem[]>('tindakanItems', { required: true });
|
||||
|
||||
// Modal state for diagnosis
|
||||
const showDiagnosisModal = ref(false);
|
||||
const diagnosisForm = ref<DiagnosisItem>({
|
||||
kodeDiagnosa: '',
|
||||
diagnosa: '',
|
||||
jenisDiagnosa: 'utama'
|
||||
});
|
||||
const editingDiagnosisIndex = ref<number | null>(null);
|
||||
const diagnosisList = ref(diagnosisData);
|
||||
|
||||
// Autocomplete options for diagnosis
|
||||
const diagnosisOptions = computed(() => {
|
||||
return diagnosisList.value.map(d => ({
|
||||
title: `${d.kode} - ${d.diagnosa}`,
|
||||
value: d.kode,
|
||||
diagnosa: d.diagnosa,
|
||||
jenisDiagnosa: d.jenis_diagnosa
|
||||
}));
|
||||
});
|
||||
|
||||
// Modal state for tindakan
|
||||
const showTindakanModal = ref(false);
|
||||
const tindakanForm = ref<TindakanItem>({
|
||||
kodeTindakan: '',
|
||||
tindakan: '',
|
||||
tindakanTambahan: ''
|
||||
});
|
||||
const editingTindakanIndex = ref<number | null>(null);
|
||||
const tindakanList = ref(tindakanData);
|
||||
|
||||
// Autocomplete options for tindakan
|
||||
const tindakanOptions = computed(() => {
|
||||
return tindakanList.value.map(t => ({
|
||||
title: `${t.kode} - ${t.tindakan}`,
|
||||
value: t.kode,
|
||||
tindakan: t.tindakan,
|
||||
tindakanTambahan: t.tindakan_tambahan
|
||||
}));
|
||||
});
|
||||
|
||||
// Initialize arrays if not already
|
||||
if (!Array.isArray(diagnosisItems.value)) {
|
||||
diagnosisItems.value = [];
|
||||
}
|
||||
if (!Array.isArray(tindakanItems.value)) {
|
||||
tindakanItems.value = [];
|
||||
}
|
||||
|
||||
const openDiagnosisModal = () => {
|
||||
diagnosisForm.value = {
|
||||
kodeDiagnosa: '',
|
||||
diagnosa: '',
|
||||
jenisDiagnosa: 'utama'
|
||||
};
|
||||
editingDiagnosisIndex.value = null;
|
||||
showDiagnosisModal.value = true;
|
||||
};
|
||||
|
||||
const editDiagnosis = (index: number) => {
|
||||
diagnosisForm.value = { ...diagnosisItems.value[index] };
|
||||
editingDiagnosisIndex.value = index;
|
||||
showDiagnosisModal.value = true;
|
||||
};
|
||||
|
||||
const saveDiagnosis = () => {
|
||||
if (!diagnosisForm.value.kodeDiagnosa.trim() || !diagnosisForm.value.diagnosa.trim()) return;
|
||||
|
||||
if (editingDiagnosisIndex.value !== null) {
|
||||
diagnosisItems.value[editingDiagnosisIndex.value] = { ...diagnosisForm.value };
|
||||
} else {
|
||||
diagnosisItems.value.push({ ...diagnosisForm.value });
|
||||
}
|
||||
|
||||
showDiagnosisModal.value = false;
|
||||
diagnosisForm.value = {
|
||||
kodeDiagnosa: '',
|
||||
diagnosa: '',
|
||||
jenisDiagnosa: 'utama'
|
||||
};
|
||||
editingDiagnosisIndex.value = null;
|
||||
};
|
||||
|
||||
const deleteDiagnosis = (index: number) => {
|
||||
diagnosisItems.value.splice(index, 1);
|
||||
};
|
||||
|
||||
// Auto-fill diagnosis when code is selected
|
||||
const handleKodeDiagnosaChange = (kode: string) => {
|
||||
const found = diagnosisList.value.find(d => d.kode === kode);
|
||||
if (found) {
|
||||
diagnosisForm.value.diagnosa = found.diagnosa;
|
||||
diagnosisForm.value.jenisDiagnosa = found.jenis_diagnosa;
|
||||
}
|
||||
};
|
||||
|
||||
const openTindakanModal = () => {
|
||||
tindakanForm.value = {
|
||||
kodeTindakan: '',
|
||||
tindakan: '',
|
||||
tindakanTambahan: ''
|
||||
};
|
||||
editingTindakanIndex.value = null;
|
||||
showTindakanModal.value = true;
|
||||
};
|
||||
|
||||
const editTindakan = (index: number) => {
|
||||
tindakanForm.value = { ...tindakanItems.value[index] };
|
||||
editingTindakanIndex.value = index;
|
||||
showTindakanModal.value = true;
|
||||
};
|
||||
|
||||
const saveTindakan = () => {
|
||||
if (!tindakanForm.value.kodeTindakan.trim() || !tindakanForm.value.tindakan.trim()) return;
|
||||
|
||||
if (editingTindakanIndex.value !== null) {
|
||||
tindakanItems.value[editingTindakanIndex.value] = { ...tindakanForm.value };
|
||||
} else {
|
||||
tindakanItems.value.push({ ...tindakanForm.value });
|
||||
}
|
||||
|
||||
showTindakanModal.value = false;
|
||||
tindakanForm.value = {
|
||||
kodeTindakan: '',
|
||||
tindakan: '',
|
||||
tindakanTambahan: ''
|
||||
};
|
||||
editingTindakanIndex.value = null;
|
||||
};
|
||||
|
||||
const deleteTindakan = (index: number) => {
|
||||
tindakanItems.value.splice(index, 1);
|
||||
};
|
||||
|
||||
// Auto-fill tindakan when code is selected
|
||||
const handleKodeTindakanChange = (kode: string) => {
|
||||
const found = tindakanList.value.find(t => t.kode === kode);
|
||||
if (found) {
|
||||
tindakanForm.value.tindakan = found.tindakan;
|
||||
tindakanForm.value.tindakanTambahan = found.tindakan_tambahan || '';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-card elevation="10">
|
||||
<v-card-item>
|
||||
<h5 class="text-h5 font-weight-bold">Data Medis Pasien</h5>
|
||||
</v-card-item>
|
||||
<v-divider></v-divider>
|
||||
<v-card-text>
|
||||
<!-- Diagnosa -->
|
||||
<div class="mb-6">
|
||||
<h6 class="text-h6 font-weight-medium mb-3">Diagnosa</h6>
|
||||
<v-card variant="outlined" class="mb-3">
|
||||
<v-alert
|
||||
v-if="diagnosisItems.length === 0"
|
||||
type="info"
|
||||
variant="tonal"
|
||||
density="compact"
|
||||
>
|
||||
<div class="d-flex align-center">
|
||||
<span>No items</span>
|
||||
</div>
|
||||
</v-alert>
|
||||
<v-list v-else density="compact">
|
||||
<v-list-item
|
||||
v-for="(item, index) in diagnosisItems"
|
||||
:key="index"
|
||||
class="px-4 mb-2"
|
||||
@click="editDiagnosis(index)"
|
||||
style="cursor: pointer;"
|
||||
>
|
||||
<template #default>
|
||||
<div class="d-flex align-center justify-space-between w-100">
|
||||
<div>
|
||||
<div class="font-weight-medium">{{ item.kodeDiagnosa }} - {{ item.diagnosa }}</div>
|
||||
<div class="text-caption text-medium-emphasis">
|
||||
{{ item.jenisDiagnosa === 'utama' ? 'Diagnosa Utama' : 'Diagnosa Tambahan' }}
|
||||
</div>
|
||||
</div>
|
||||
<v-btn
|
||||
icon
|
||||
size="small"
|
||||
variant="text"
|
||||
color="error"
|
||||
@click.stop="deleteDiagnosis(index)"
|
||||
>
|
||||
<v-icon>mdi-delete</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-card>
|
||||
<v-btn color="primary" prepend-icon="mdi-plus" @click="openDiagnosisModal">
|
||||
Tambah Diagnosa
|
||||
</v-btn>
|
||||
</div>
|
||||
|
||||
<!-- Tindakan -->
|
||||
<div>
|
||||
<h6 class="text-h6 font-weight-medium mb-3">Tindakan</h6>
|
||||
<v-card variant="outlined" class="mb-3">
|
||||
<v-alert
|
||||
v-if="tindakanItems.length === 0"
|
||||
type="info"
|
||||
variant="tonal"
|
||||
density="compact"
|
||||
>
|
||||
<div class="d-flex align-center">
|
||||
<span>No items</span>
|
||||
</div>
|
||||
</v-alert>
|
||||
<v-list v-else density="compact">
|
||||
<v-list-item
|
||||
v-for="(item, index) in tindakanItems"
|
||||
:key="index"
|
||||
class="px-4 mb-2"
|
||||
@click="editTindakan(index)"
|
||||
style="cursor: pointer;"
|
||||
>
|
||||
<template #default>
|
||||
<div class="d-flex align-center justify-space-between w-100">
|
||||
<div>
|
||||
<div class="font-weight-medium">{{ item.kodeTindakan }} - {{ item.tindakan }}</div>
|
||||
<div v-if="item.tindakanTambahan" class="text-caption text-medium-emphasis">
|
||||
{{ item.tindakanTambahan }}
|
||||
</div>
|
||||
</div>
|
||||
<v-btn
|
||||
icon
|
||||
size="small"
|
||||
variant="text"
|
||||
color="error"
|
||||
@click.stop="deleteTindakan(index)"
|
||||
>
|
||||
<v-icon>mdi-delete</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-card>
|
||||
<v-btn color="primary" prepend-icon="mdi-plus" @click="openTindakanModal">
|
||||
Tambah Tindakan
|
||||
</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<!-- Modal for adding diagnosis -->
|
||||
<v-dialog v-model="showDiagnosisModal" max-width="800px">
|
||||
<v-card>
|
||||
<v-card-title class="d-flex align-center justify-space-between pa-4">
|
||||
<div class="d-flex align-center">
|
||||
<v-icon class="mr-3">mdi-package-variant</v-icon>
|
||||
<span class="text-h6">{{ editingDiagnosisIndex !== null ? 'Edit' : 'Tambah' }} Item Data Diagnosa Pasien Operasi</span>
|
||||
</div>
|
||||
<v-btn
|
||||
icon
|
||||
variant="text"
|
||||
@click="showDiagnosisModal = false"
|
||||
>
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-card-text class="pa-6">
|
||||
<v-row>
|
||||
<!-- Kode Diagnosa -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">Kode Diagnosa</v-label>
|
||||
<v-autocomplete
|
||||
v-model="diagnosisForm.kodeDiagnosa"
|
||||
:items="diagnosisOptions"
|
||||
placeholder="Kode ICD 10"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
hide-details="auto"
|
||||
@update:model-value="handleKodeDiagnosaChange"
|
||||
></v-autocomplete>
|
||||
</v-col>
|
||||
|
||||
<!-- Diagnosa -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">Diagnosa</v-label>
|
||||
<v-text-field
|
||||
v-model="diagnosisForm.diagnosa"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
readonly
|
||||
bg-color="grey-lighten-3"
|
||||
hide-details="auto"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<!-- Jenis Diagnosa -->
|
||||
<v-col cols="12">
|
||||
<v-label class="mb-2 font-weight-medium">Jenis Diagnosa</v-label>
|
||||
<v-radio-group v-model="diagnosisForm.jenisDiagnosa" inline hide-details="auto" readonly>
|
||||
<v-radio label="Diagnosa Utama" value="utama" color="primary"></v-radio>
|
||||
<v-radio label="Diagnosa Tambahan" value="tambahan" color="primary"></v-radio>
|
||||
</v-radio-group>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-card-actions class="pa-4 justify-end">
|
||||
<v-btn
|
||||
color="primary"
|
||||
variant="flat"
|
||||
@click="saveDiagnosis"
|
||||
:disabled="!diagnosisForm.kodeDiagnosa.trim() || !diagnosisForm.diagnosa.trim()"
|
||||
>
|
||||
<v-icon start>mdi-check</v-icon>
|
||||
Save
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<!-- Modal for adding tindakan -->
|
||||
<v-dialog v-model="showTindakanModal" max-width="800px">
|
||||
<v-card>
|
||||
<v-card-title class="d-flex align-center justify-space-between pa-4">
|
||||
<div class="d-flex align-center">
|
||||
<v-icon class="mr-3">mdi-package-variant</v-icon>
|
||||
<span class="text-h6">{{ editingTindakanIndex !== null ? 'Edit' : 'Tambah' }} Item Data Tindakan Pasien Operasi</span>
|
||||
</div>
|
||||
<v-btn
|
||||
icon
|
||||
variant="text"
|
||||
@click="showTindakanModal = false"
|
||||
>
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-card-text class="pa-6">
|
||||
<v-row>
|
||||
<!-- Kode Tindakan -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">Kode Tindakan</v-label>
|
||||
<v-autocomplete
|
||||
v-model="tindakanForm.kodeTindakan"
|
||||
:items="tindakanOptions"
|
||||
placeholder="Kode ICD 9"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
hide-details="auto"
|
||||
@update:model-value="handleKodeTindakanChange"
|
||||
></v-autocomplete>
|
||||
</v-col>
|
||||
|
||||
<!-- Tindakan -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">Tindakan</v-label>
|
||||
<v-text-field
|
||||
v-model="tindakanForm.tindakan"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
readonly
|
||||
bg-color="grey-lighten-3"
|
||||
hide-details="auto"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<!-- Tindakan Tambahan -->
|
||||
<v-col cols="12">
|
||||
<v-label class="mb-2 font-weight-medium">Tindakan Tambahan</v-label>
|
||||
<v-text-field
|
||||
v-model="tindakanForm.tindakanTambahan"
|
||||
placeholder="Prosedur Tindakan Tambahan"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
hide-details="auto"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-card-actions class="pa-4 justify-end">
|
||||
<v-btn
|
||||
color="primary"
|
||||
variant="flat"
|
||||
@click="saveTindakan"
|
||||
:disabled="!tindakanForm.kodeTindakan.trim() || !tindakanForm.tindakan.trim()"
|
||||
>
|
||||
<v-icon start>mdi-check</v-icon>
|
||||
Save
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
@@ -0,0 +1,365 @@
|
||||
<script setup lang="ts">
|
||||
import dokterData from '~/data/mock/dokter.json';
|
||||
import spesialisData from '~/data/mock/spesialis.json';
|
||||
import subSpesialisData from '~/data/mock/subSpesialis.json';
|
||||
import kategoriOperasiData from '~/data/mock/kategoriOperasi.json';
|
||||
|
||||
interface Dokter {
|
||||
id: number;
|
||||
nip: string;
|
||||
nama: string;
|
||||
satuan_kerja: string;
|
||||
}
|
||||
|
||||
const rencanaOperasiData = defineModel<{
|
||||
spesialis: number | null | undefined;
|
||||
subSpesialis: number | null | undefined;
|
||||
tanggalDaftar: string;
|
||||
kategoriOperasi: number | null | undefined;
|
||||
rencanaOperasi: string;
|
||||
keterangan: string;
|
||||
}>('rencanaOperasiData', { required: true });
|
||||
|
||||
const dokterPelaksanaItems = defineModel<Dokter[]>('dokterPelaksanaItems', { required: true });
|
||||
|
||||
const rules = {
|
||||
required: (value: any) => !!value || 'Field ini wajib diisi'
|
||||
};
|
||||
|
||||
// Spesialis, Sub-spesialis, dan Kategori Operasi data
|
||||
const spesialisList = ref(spesialisData);
|
||||
const subSpesialisList = ref(subSpesialisData);
|
||||
const kategoriOperasiList = ref(kategoriOperasiData);
|
||||
|
||||
// Autocomplete options
|
||||
const spesialisOptions = computed(() => {
|
||||
return spesialisList.value.map(s => ({
|
||||
title: s.spesialis,
|
||||
value: s.id
|
||||
}));
|
||||
});
|
||||
|
||||
const subSpesialisOptions = computed(() => {
|
||||
if (!rencanaOperasiData.value.spesialis) return [];
|
||||
|
||||
return subSpesialisList.value
|
||||
.filter(ss => ss.id_spesialis === rencanaOperasiData.value.spesialis)
|
||||
.map(ss => ({
|
||||
title: ss.subspesialis,
|
||||
value: ss.id
|
||||
}));
|
||||
});
|
||||
|
||||
const kategoriOperasiOptions = computed(() => {
|
||||
return kategoriOperasiList.value.map(k => ({
|
||||
title: k.kategori,
|
||||
value: k.id
|
||||
}));
|
||||
});
|
||||
|
||||
// Watch spesialis change to reset sub-spesialis
|
||||
watch(() => rencanaOperasiData.value.spesialis, () => {
|
||||
rencanaOperasiData.value.subSpesialis = null;
|
||||
});
|
||||
|
||||
// Modal state for dokter
|
||||
const showDokterModal = ref(false);
|
||||
const searchDokter = ref('');
|
||||
const selectedDokters = ref<number[]>([]);
|
||||
const dokterList = ref<Dokter[]>(dokterData);
|
||||
|
||||
// Computed filtered dokter list
|
||||
const filteredDokterList = computed(() => {
|
||||
if (!searchDokter.value) return dokterList.value;
|
||||
|
||||
const search = searchDokter.value.toLowerCase();
|
||||
return dokterList.value.filter(dokter =>
|
||||
dokter.nama.toLowerCase().includes(search) ||
|
||||
dokter.nip.includes(search) ||
|
||||
dokter.satuan_kerja.toLowerCase().includes(search)
|
||||
);
|
||||
});
|
||||
|
||||
// Initialize dokterPelaksanaItems as array if not already
|
||||
if (!Array.isArray(dokterPelaksanaItems.value)) {
|
||||
dokterPelaksanaItems.value = [];
|
||||
}
|
||||
|
||||
const openDokterModal = () => {
|
||||
// Pre-select already added doctors
|
||||
selectedDokters.value = dokterPelaksanaItems.value.map(d => d.id);
|
||||
searchDokter.value = '';
|
||||
showDokterModal.value = true;
|
||||
};
|
||||
|
||||
const saveDokterSelection = () => {
|
||||
// Get selected doctor objects
|
||||
const selected = dokterList.value.filter(d => selectedDokters.value.includes(d.id));
|
||||
dokterPelaksanaItems.value = selected;
|
||||
showDokterModal.value = false;
|
||||
};
|
||||
|
||||
const deleteDokter = (index: number) => {
|
||||
dokterPelaksanaItems.value.splice(index, 1);
|
||||
};
|
||||
|
||||
// Toggle all selection
|
||||
const toggleAllDokters = () => {
|
||||
if (selectedDokters.value.length === filteredDokterList.value.length) {
|
||||
selectedDokters.value = [];
|
||||
} else {
|
||||
selectedDokters.value = filteredDokterList.value.map(d => d.id);
|
||||
}
|
||||
};
|
||||
|
||||
const isAllSelected = computed(() => {
|
||||
return filteredDokterList.value.length > 0 &&
|
||||
selectedDokters.value.length === filteredDokterList.value.length;
|
||||
});
|
||||
|
||||
const toggleDokterSelection = (dokterId: number) => {
|
||||
const index = selectedDokters.value.indexOf(dokterId);
|
||||
if (index > -1) {
|
||||
selectedDokters.value.splice(index, 1);
|
||||
} else {
|
||||
selectedDokters.value.push(dokterId);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-card elevation="10">
|
||||
<v-card-item>
|
||||
<h5 class="text-h5 font-weight-bold">Data Rencana Operasi</h5>
|
||||
</v-card-item>
|
||||
<v-divider></v-divider>
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<!-- Spesialis -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">Spesialis <span class="text-error">*</span></v-label>
|
||||
<v-autocomplete
|
||||
v-model="rencanaOperasiData.spesialis"
|
||||
:items="spesialisOptions"
|
||||
placeholder="Select an item..."
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
:rules="[rules.required]"
|
||||
hide-details="auto"
|
||||
></v-autocomplete>
|
||||
</v-col>
|
||||
|
||||
<!-- Sub Spesialis -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">Sub Spesialis <span class="text-error">*</span></v-label>
|
||||
<v-autocomplete
|
||||
v-model="rencanaOperasiData.subSpesialis"
|
||||
:items="subSpesialisOptions"
|
||||
placeholder="Select an item..."
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
:rules="[rules.required]"
|
||||
hide-details="auto"
|
||||
:disabled="!rencanaOperasiData.spesialis"
|
||||
></v-autocomplete>
|
||||
</v-col>
|
||||
|
||||
<!-- Dokter Pelaksana -->
|
||||
<v-col cols="12">
|
||||
<v-label class="mb-2 font-weight-medium">Dokter Pelaksana</v-label>
|
||||
<v-card variant="outlined" class="mb-3">
|
||||
<v-alert
|
||||
v-if="dokterPelaksanaItems.length === 0"
|
||||
type="info"
|
||||
variant="tonal"
|
||||
density="compact"
|
||||
>
|
||||
<div class="d-flex align-center">
|
||||
<span>No items</span>
|
||||
</div>
|
||||
</v-alert>
|
||||
<v-list v-else density="compact">
|
||||
<v-list-item
|
||||
v-for="(item, index) in dokterPelaksanaItems"
|
||||
:key="index"
|
||||
@click="openDokterModal"
|
||||
class="px-4 mb-2"
|
||||
>
|
||||
<template #default>
|
||||
<div class="d-flex align-center justify-space-between w-100">
|
||||
<div>
|
||||
<div class="font-weight-medium">{{ item.nama }}</div>
|
||||
<div class="text-caption text-medium-emphasis">
|
||||
{{ item.nip }} - {{ item.satuan_kerja }}
|
||||
</div>
|
||||
</div>
|
||||
<v-btn
|
||||
icon
|
||||
size="small"
|
||||
variant="text"
|
||||
color="error"
|
||||
@click="deleteDokter(index)"
|
||||
>
|
||||
<v-icon>mdi-delete</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-card>
|
||||
<v-btn color="primary" prepend-icon="mdi-plus" @click="openDokterModal">
|
||||
Tambah Dokter Pelaksana
|
||||
</v-btn>
|
||||
</v-col>
|
||||
|
||||
<!-- Tanggal Daftar -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">Tanggal Daftar <span class="text-error">*</span></v-label>
|
||||
<v-text-field
|
||||
v-model="rencanaOperasiData.tanggalDaftar"
|
||||
type="datetime-local"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
:rules="[rules.required]"
|
||||
hide-details="auto"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<!-- Kategori Operasi -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-label class="mb-2 font-weight-medium">Kategori Operasi <span class="text-error">*</span></v-label>
|
||||
<v-autocomplete
|
||||
v-model="rencanaOperasiData.kategoriOperasi"
|
||||
:items="kategoriOperasiOptions"
|
||||
placeholder="Select an item..."
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
:rules="[rules.required]"
|
||||
hide-details="auto"
|
||||
></v-autocomplete>
|
||||
</v-col>
|
||||
|
||||
<!-- Rencana Operasi -->
|
||||
<v-col cols="12">
|
||||
<v-label class="mb-2 font-weight-medium">Rencana Operasi</v-label>
|
||||
<v-textarea
|
||||
v-model="rencanaOperasiData.rencanaOperasi"
|
||||
variant="outlined"
|
||||
rows="5"
|
||||
hide-details="auto"
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
|
||||
<!-- Keterangan -->
|
||||
<v-col cols="12">
|
||||
<v-label class="mb-2 font-weight-medium">Keterangan</v-label>
|
||||
<v-textarea
|
||||
v-model="rencanaOperasiData.keterangan"
|
||||
variant="outlined"
|
||||
rows="3"
|
||||
hide-details="auto"
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<!-- Modal for selecting dokter -->
|
||||
<v-dialog v-model="showDokterModal" max-width="900px">
|
||||
<v-card>
|
||||
<v-card-title class="d-flex align-center justify-space-between pa-4">
|
||||
<div class="d-flex align-center">
|
||||
<v-icon class="mr-3">mdi-database</v-icon>
|
||||
<span class="text-h6">Select Item</span>
|
||||
</div>
|
||||
<v-btn
|
||||
icon
|
||||
variant="text"
|
||||
@click="showDokterModal = false"
|
||||
>
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-card-text class="pa-4">
|
||||
<!-- Search Bar -->
|
||||
<v-text-field
|
||||
v-model="searchDokter"
|
||||
placeholder="Search..."
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
prepend-inner-icon="mdi-magnify"
|
||||
class="mb-4"
|
||||
></v-text-field>
|
||||
|
||||
<!-- Info Badge -->
|
||||
<div class="text-caption text-medium-emphasis mb-3">
|
||||
1-{{ filteredDokterList.length }} of {{ dokterList.length }} Items
|
||||
</div>
|
||||
|
||||
<!-- Data Table -->
|
||||
<v-table density="compact" class="border">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-left">
|
||||
<v-checkbox
|
||||
:model-value="isAllSelected"
|
||||
@click="toggleAllDokters"
|
||||
hide-details
|
||||
density="compact"
|
||||
></v-checkbox>
|
||||
</th>
|
||||
<th class="text-left">Display</th>
|
||||
<th class="text-left">Nip</th>
|
||||
<th class="text-left">Nama Lengkap</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="dokter in filteredDokterList"
|
||||
:key="dokter.id"
|
||||
@click="toggleDokterSelection(dokter.id)"
|
||||
class="cursor-pointer"
|
||||
style="cursor: pointer;"
|
||||
>
|
||||
<td @click.stop>
|
||||
<v-checkbox
|
||||
v-model="selectedDokters"
|
||||
:value="dokter.id"
|
||||
hide-details
|
||||
density="compact"
|
||||
></v-checkbox>
|
||||
</td>
|
||||
<td>Doctor</td>
|
||||
<td>{{ dokter.nip }}</td>
|
||||
<td>{{ dokter.nama }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-table>
|
||||
|
||||
<!-- Empty State -->
|
||||
<div v-if="filteredDokterList.length === 0" class="text-center py-8">
|
||||
<v-icon size="large" class="mb-2 text-medium-emphasis">mdi-information-outline</v-icon>
|
||||
<p class="text-medium-emphasis">No results found</p>
|
||||
</div>
|
||||
</v-card-text>
|
||||
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-card-actions class="pa-4 justify-end">
|
||||
<v-btn
|
||||
color="primary"
|
||||
variant="flat"
|
||||
@click="saveDokterSelection"
|
||||
:disabled="selectedDokters.length === 0"
|
||||
>
|
||||
<v-icon start>mdi-check</v-icon>
|
||||
Save ({{ selectedDokters.length }})
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
@@ -0,0 +1,98 @@
|
||||
<script setup lang="ts">
|
||||
const statusPasienData = defineModel<{
|
||||
tanggalSelesai: string;
|
||||
statusOperasi: string;
|
||||
keteranganStatus: string;
|
||||
}>({ required: true });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-card elevation="10">
|
||||
<v-card-item>
|
||||
<h5 class="text-h5 font-weight-bold">Data Status Pasien Operasi</h5>
|
||||
</v-card-item>
|
||||
<v-divider></v-divider>
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<!-- Status Operasi -->
|
||||
<v-col cols="12">
|
||||
<v-label class="mb-2 font-weight-medium">Status Operasi <span class="text-error">*</span></v-label>
|
||||
<v-row class="mt-2">
|
||||
<v-col cols="12" sm="6" md="3">
|
||||
<v-btn
|
||||
block
|
||||
size="large"
|
||||
:variant="statusPasienData.statusOperasi === 'Belum' ? 'flat' : 'outlined'"
|
||||
:color="statusPasienData.statusOperasi === 'Belum' ? 'primary' : 'default'"
|
||||
@click="statusPasienData.statusOperasi = 'Belum'"
|
||||
>
|
||||
<v-icon left class="mr-2">{{ statusPasienData.statusOperasi === 'Belum' ? 'mdi-radiobox-marked' : 'mdi-radiobox-blank' }}</v-icon>
|
||||
Belum
|
||||
</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" md="3">
|
||||
<v-btn
|
||||
block
|
||||
size="large"
|
||||
:variant="statusPasienData.statusOperasi === 'Selesai' ? 'flat' : 'outlined'"
|
||||
:color="statusPasienData.statusOperasi === 'Selesai' ? 'primary' : 'default'"
|
||||
@click="statusPasienData.statusOperasi = 'Selesai'"
|
||||
>
|
||||
<v-icon left class="mr-2">{{ statusPasienData.statusOperasi === 'Selesai' ? 'mdi-radiobox-marked' : 'mdi-radiobox-blank' }}</v-icon>
|
||||
Selesai
|
||||
</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" md="3">
|
||||
<v-btn
|
||||
block
|
||||
size="large"
|
||||
:variant="statusPasienData.statusOperasi === 'Tunda' ? 'flat' : 'outlined'"
|
||||
:color="statusPasienData.statusOperasi === 'Tunda' ? 'primary' : 'default'"
|
||||
@click="statusPasienData.statusOperasi = 'Tunda'"
|
||||
>
|
||||
<v-icon left class="mr-2">{{ statusPasienData.statusOperasi === 'Tunda' ? 'mdi-radiobox-marked' : 'mdi-radiobox-blank' }}</v-icon>
|
||||
Tunda
|
||||
</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" md="3">
|
||||
<v-btn
|
||||
block
|
||||
size="large"
|
||||
:variant="statusPasienData.statusOperasi === 'Batal' ? 'flat' : 'outlined'"
|
||||
:color="statusPasienData.statusOperasi === 'Batal' ? 'primary' : 'default'"
|
||||
@click="statusPasienData.statusOperasi = 'Batal'"
|
||||
>
|
||||
<v-icon left class="mr-2">{{ statusPasienData.statusOperasi === 'Batal' ? 'mdi-radiobox-marked' : 'mdi-radiobox-blank' }}</v-icon>
|
||||
Batal
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
|
||||
<!-- Tanggal Selesai Operasi -->
|
||||
<v-col cols="6">
|
||||
<v-label class="mb-2 font-weight-medium">Tanggal Selesai Operasi</v-label>
|
||||
<v-text-field
|
||||
v-model="statusPasienData.tanggalSelesai"
|
||||
type="date"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
hide-details="auto"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<!-- Keterangan Status Pasien -->
|
||||
<v-col cols="12">
|
||||
<v-label class="mb-2 font-weight-medium">Keterangan Status Pasien</v-label>
|
||||
<v-textarea
|
||||
v-model="statusPasienData.keteranganStatus"
|
||||
variant="outlined"
|
||||
rows="5"
|
||||
placeholder="Keterangan status tunda / batal"
|
||||
hide-details="auto"
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
@@ -11,27 +11,19 @@ const props = defineProps({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-card elevation="10" class="mb-8">
|
||||
<div class="px-6 py-4">
|
||||
<div class="d-flex justify-space-between align-center">
|
||||
<h5 class="text-h5">{{ title }}</h5>
|
||||
<v-breadcrumbs :items="breadcrumbs" class="pa-0">
|
||||
<template v-slot:prepend>
|
||||
<router-link to="/" class="textSecondary lh-0">
|
||||
<Icon icon="solar:home-2-line-duotone" height="20" />
|
||||
</router-link>
|
||||
</template>
|
||||
<template v-slot:divider>
|
||||
<div class="d-flex align-center textSecondary "></div>
|
||||
</template>
|
||||
<template v-slot:title="{ item }">
|
||||
<v-chip size="small" class="rounded-sm" color="primary" >{{ item.text }}</v-chip>
|
||||
</template>
|
||||
</v-breadcrumbs>
|
||||
|
||||
<div class="d-flex align-center ga-2">
|
||||
<router-link to="/" class="textSecondary lh-0">
|
||||
<Icon icon="solar:home-2-line-duotone" height="20" />
|
||||
</router-link>
|
||||
<v-chip size="small" class="rounded-sm" color="primary">
|
||||
{{ breadcrumbs?.map(item => item.text).join(' / ') }}
|
||||
</v-chip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
Reference in New Issue
Block a user