feat(encounter): implement encounter detail loading and update handling in entry form
This commit is contained in:
No files matched your search
@@ -18,7 +18,7 @@ import {
|
|||||||
getValueTreeItems as getSpecialistTreeItems,
|
getValueTreeItems as getSpecialistTreeItems,
|
||||||
} from '~/services/specialist.service'
|
} from '~/services/specialist.service'
|
||||||
import { getValueLabelList as getDoctorValueLabelList } from '~/services/doctor.service'
|
import { getValueLabelList as getDoctorValueLabelList } from '~/services/doctor.service'
|
||||||
import { create as createEncounter } from '~/services/encounter.service'
|
import { create as createEncounter, getDetail as getEncounterDetail, update as updateEncounter } from '~/services/encounter.service'
|
||||||
|
|
||||||
// Handlers
|
// Handlers
|
||||||
import {
|
import {
|
||||||
@@ -55,11 +55,17 @@ const specialistsData = ref<any[]>([]) // Store full specialist data with id
|
|||||||
const doctorsList = ref<Array<{ value: string; label: string }>>([])
|
const doctorsList = ref<Array<{ value: string; label: string }>>([])
|
||||||
const recSelectId = ref<number | null>(null)
|
const recSelectId = ref<number | null>(null)
|
||||||
const isSaving = ref(false)
|
const isSaving = ref(false)
|
||||||
|
const isLoadingDetail = ref(false)
|
||||||
const formRef = ref<InstanceType<typeof AppEncounterEntryForm> | null>(null)
|
const formRef = ref<InstanceType<typeof AppEncounterEntryForm> | null>(null)
|
||||||
|
const encounterData = ref<any>(null)
|
||||||
|
const formObjects = ref<any>({})
|
||||||
|
|
||||||
|
// Computed for edit mode
|
||||||
|
const isEditMode = computed(() => props.id > 0)
|
||||||
|
|
||||||
// Computed for save button disable state
|
// Computed for save button disable state
|
||||||
const isSaveDisabled = computed(() => {
|
const isSaveDisabled = computed(() => {
|
||||||
return !selectedPatient.value || !selectedPatientObject.value || isSaving.value
|
return !selectedPatient.value || !selectedPatientObject.value || isSaving.value || isLoadingDetail.value
|
||||||
})
|
})
|
||||||
|
|
||||||
function getListPath(): string {
|
function getListPath(): string {
|
||||||
@@ -186,19 +192,24 @@ async function handleSaveEncounter(formValues: any) {
|
|||||||
payload.allocatedVisitCount = 0
|
payload.allocatedVisitCount = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call encounter service
|
// Call encounter service - use update if edit mode, create otherwise
|
||||||
const result = await createEncounter(payload)
|
let result
|
||||||
|
if (isEditMode.value) {
|
||||||
|
result = await updateEncounter(props.id, payload)
|
||||||
|
} else {
|
||||||
|
result = await createEncounter(payload)
|
||||||
|
}
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
toast({
|
toast({
|
||||||
title: 'Berhasil',
|
title: 'Berhasil',
|
||||||
description: 'Kunjungan berhasil dibuat',
|
description: isEditMode.value ? 'Kunjungan berhasil diperbarui' : 'Kunjungan berhasil dibuat',
|
||||||
variant: 'default',
|
variant: 'default',
|
||||||
})
|
})
|
||||||
// Redirect to list page
|
// Redirect to list page
|
||||||
await navigateTo(getListPath())
|
await navigateTo(getListPath())
|
||||||
} else {
|
} else {
|
||||||
const errorMessage = result.body?.message || 'Gagal membuat kunjungan'
|
const errorMessage = result.body?.message || (isEditMode.value ? 'Gagal memperbarui kunjungan' : 'Gagal membuat kunjungan')
|
||||||
toast({
|
toast({
|
||||||
title: 'Gagal',
|
title: 'Gagal',
|
||||||
description: errorMessage,
|
description: errorMessage,
|
||||||
@@ -209,7 +220,7 @@ async function handleSaveEncounter(formValues: any) {
|
|||||||
console.error('Error saving encounter:', error)
|
console.error('Error saving encounter:', error)
|
||||||
toast({
|
toast({
|
||||||
title: 'Gagal',
|
title: 'Gagal',
|
||||||
description: error?.message || 'Gagal membuat kunjungan',
|
description: error?.message || (isEditMode.value ? 'Gagal memperbarui kunjungan' : 'Gagal membuat kunjungan'),
|
||||||
variant: 'destructive',
|
variant: 'destructive',
|
||||||
})
|
})
|
||||||
} finally {
|
} finally {
|
||||||
@@ -370,11 +381,149 @@ async function handleInit() {
|
|||||||
await handleFetchSpecialists()
|
await handleFetchSpecialists()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load encounter detail data for edit mode
|
||||||
|
*/
|
||||||
|
async function loadEncounterDetail() {
|
||||||
|
if (!isEditMode.value || props.id <= 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
isLoadingDetail.value = true
|
||||||
|
const result = await getEncounterDetail(props.id, {
|
||||||
|
includes: 'patient,patient-person,specialist,subspecialist,appointment_doctor,responsible_doctor,encounter_payments',
|
||||||
|
})
|
||||||
|
|
||||||
|
if (result.success && result.body?.data) {
|
||||||
|
encounterData.value = result.body.data
|
||||||
|
await mapEncounterToForm(encounterData.value)
|
||||||
|
} else {
|
||||||
|
toast({
|
||||||
|
title: 'Gagal',
|
||||||
|
description: 'Gagal memuat data kunjungan',
|
||||||
|
variant: 'destructive',
|
||||||
|
})
|
||||||
|
// Redirect to list page if encounter not found
|
||||||
|
await navigateTo(getListPath())
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('Error loading encounter detail:', error)
|
||||||
|
toast({
|
||||||
|
title: 'Gagal',
|
||||||
|
description: error?.message || 'Gagal memuat data kunjungan',
|
||||||
|
variant: 'destructive',
|
||||||
|
})
|
||||||
|
// Redirect to list page on error
|
||||||
|
await navigateTo(getListPath())
|
||||||
|
} finally {
|
||||||
|
isLoadingDetail.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map encounter data to form fields
|
||||||
|
*/
|
||||||
|
async function mapEncounterToForm(encounter: any) {
|
||||||
|
if (!encounter) return
|
||||||
|
|
||||||
|
// Set patient data and wait for it to load
|
||||||
|
if (encounter.patient) {
|
||||||
|
selectedPatient.value = String(encounter.patient.id)
|
||||||
|
selectedPatientObject.value = encounter.patient
|
||||||
|
// Fetch full patient data to ensure we have all fields
|
||||||
|
await getPatientCurrent(selectedPatient.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map form fields
|
||||||
|
const formData: any = {}
|
||||||
|
|
||||||
|
// Patient data (readonly, populated from selected patient)
|
||||||
|
// Use selectedPatientObject which now has full patient data
|
||||||
|
if (selectedPatientObject.value?.person) {
|
||||||
|
formData.patientName = selectedPatientObject.value.person.name || ''
|
||||||
|
formData.nationalIdentity = selectedPatientObject.value.person.residentIdentityNumber || ''
|
||||||
|
formData.medicalRecordNumber = selectedPatientObject.value.number || ''
|
||||||
|
} else if (encounter.patient?.person) {
|
||||||
|
// Fallback to encounter patient data if selectedPatientObject is not yet loaded
|
||||||
|
formData.patientName = encounter.patient.person.name || ''
|
||||||
|
formData.nationalIdentity = encounter.patient.person.residentIdentityNumber || ''
|
||||||
|
formData.medicalRecordNumber = encounter.patient.number || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// Doctor ID
|
||||||
|
const doctorId = encounter.appointment_doctor_id || encounter.responsible_doctor_id
|
||||||
|
if (doctorId) {
|
||||||
|
formData.doctorId = String(doctorId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specialist/Subspecialist
|
||||||
|
if (encounter.subspecialist?.code) {
|
||||||
|
formData.subSpecialistId = encounter.subspecialist.code
|
||||||
|
} else if (encounter.specialist?.code) {
|
||||||
|
formData.subSpecialistId = encounter.specialist.code
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register date
|
||||||
|
if (encounter.registeredAt) {
|
||||||
|
// Convert ISO date to local date string (YYYY-MM-DD)
|
||||||
|
const date = new Date(encounter.registeredAt)
|
||||||
|
formData.registerDate = date.toISOString().split('T')[0]
|
||||||
|
} else if (encounter.visitDate) {
|
||||||
|
const date = new Date(encounter.visitDate)
|
||||||
|
formData.registerDate = date.toISOString().split('T')[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Payment data
|
||||||
|
// Check if encounter has payment data
|
||||||
|
if (encounter.encounter_payments && Array.isArray(encounter.encounter_payments) && encounter.encounter_payments.length > 0) {
|
||||||
|
const payment = encounter.encounter_payments[0]
|
||||||
|
|
||||||
|
// Determine payment type from paymentMethod_code
|
||||||
|
if (payment.paymentMethod_code === 'insurance') {
|
||||||
|
// Check if it's JKN or JKMM based on member_number or other indicators
|
||||||
|
// For now, default to 'jkn' - this might need adjustment based on actual data structure
|
||||||
|
formData.paymentType = 'jkn'
|
||||||
|
formData.cardNumber = payment.member_number || ''
|
||||||
|
formData.sepNumber = payment.ref_number || ''
|
||||||
|
// Note: patientCategory and sepType might need to be extracted from other sources
|
||||||
|
// as they might not be directly in the payment object
|
||||||
|
} else {
|
||||||
|
// For non-insurance payments, try to determine from encounter data
|
||||||
|
// This might need adjustment based on actual API response
|
||||||
|
formData.paymentType = 'spm' // default to SPM
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fallback: try to get payment type from encounter.paymentType if available
|
||||||
|
if (encounter.paymentType) {
|
||||||
|
formData.paymentType = encounter.paymentType
|
||||||
|
}
|
||||||
|
if (encounter.cardNumber) {
|
||||||
|
formData.cardNumber = encounter.cardNumber
|
||||||
|
}
|
||||||
|
if (encounter.ref_number || encounter.sepNumber) {
|
||||||
|
formData.sepNumber = encounter.ref_number || encounter.sepNumber
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set form objects for the form component
|
||||||
|
formObjects.value = formData
|
||||||
|
|
||||||
|
// Fetch doctors based on specialist/subspecialist selection
|
||||||
|
if (formData.subSpecialistId) {
|
||||||
|
await handleFetchDoctors(formData.subSpecialistId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
provide('rec_select_id', recSelectId)
|
provide('rec_select_id', recSelectId)
|
||||||
provide('table_data_loader', isLoading)
|
provide('table_data_loader', isLoading)
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await handleInit()
|
await handleInit()
|
||||||
|
// Load encounter detail if in edit mode
|
||||||
|
if (isEditMode.value) {
|
||||||
|
await loadEncounterDetail()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -396,6 +545,8 @@ onMounted(async () => {
|
|||||||
:specialists="specialistsTree"
|
:specialists="specialistsTree"
|
||||||
:doctor="doctorsList"
|
:doctor="doctorsList"
|
||||||
:patient="selectedPatientObject"
|
:patient="selectedPatientObject"
|
||||||
|
:objects="formObjects"
|
||||||
|
:is-loading="isLoadingDetail"
|
||||||
@event="handleEvent"
|
@event="handleEvent"
|
||||||
@fetch="handleFetch"
|
@fetch="handleFetch"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -74,6 +74,25 @@ const refSearchNav: RefSearchNav = {
|
|||||||
|
|
||||||
// Loading state management
|
// Loading state management
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get base path for encounter routes based on classCode and subClassCode
|
||||||
|
*/
|
||||||
|
function getBasePath(): string {
|
||||||
|
if (props.classCode === 'ambulatory' && props.subClassCode === 'rehab') {
|
||||||
|
return '/rehab/encounter'
|
||||||
|
}
|
||||||
|
if (props.classCode === 'ambulatory' && props.subClassCode === 'reg') {
|
||||||
|
return '/outpatient/encounter'
|
||||||
|
}
|
||||||
|
if (props.classCode === 'emergency') {
|
||||||
|
return '/emergency/encounter'
|
||||||
|
}
|
||||||
|
if (props.classCode === 'inpatient') {
|
||||||
|
return '/inpatient/encounter'
|
||||||
|
}
|
||||||
|
return '/encounter' // fallback
|
||||||
|
}
|
||||||
|
|
||||||
async function getPatientList() {
|
async function getPatientList() {
|
||||||
isLoading.isTableLoading = true
|
isLoading.isTableLoading = true
|
||||||
try {
|
try {
|
||||||
@@ -81,6 +100,9 @@ async function getPatientList() {
|
|||||||
if (props.classCode) {
|
if (props.classCode) {
|
||||||
params['class-code'] = props.classCode
|
params['class-code'] = props.classCode
|
||||||
}
|
}
|
||||||
|
if (props.subClassCode) {
|
||||||
|
params['sub-class-code'] = props.subClassCode
|
||||||
|
}
|
||||||
const result = await getEncounterList(params)
|
const result = await getEncounterList(params)
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
data.value = result.body?.data || []
|
data.value = result.body?.data || []
|
||||||
@@ -144,27 +166,31 @@ watch(
|
|||||||
isRecordConfirmationOpen.value = true
|
isRecordConfirmationOpen.value = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// if (props.type === 'encounter') {
|
|
||||||
// if (recAction.value === 'showDetail') {
|
const basePath = getBasePath()
|
||||||
// navigateTo(`/rehab/encounter/${recId.value}/detail`)
|
|
||||||
// } else if (recAction.value === 'showEdit') {
|
if (props.type === 'encounter') {
|
||||||
// navigateTo(`/rehab/encounter/${recId.value}/edit`)
|
if (recAction.value === 'showDetail') {
|
||||||
// } else if (recAction.value === 'showProcess') {
|
navigateTo(`${basePath}/${recId.value}/detail`)
|
||||||
// navigateTo(`/rehab/encounter/${recId.value}/process`)
|
} else if (recAction.value === 'showEdit') {
|
||||||
// } else {
|
navigateTo(`${basePath}/${recId.value}/edit`)
|
||||||
// // handle other actions
|
} else if (recAction.value === 'showProcess') {
|
||||||
// }
|
navigateTo(`${basePath}/${recId.value}/process`)
|
||||||
// } else if (props.type === 'registration') {
|
} else {
|
||||||
// if (recAction.value === 'showDetail') {
|
// handle other actions
|
||||||
// navigateTo(`/rehab/registration/${recId.value}/detail`)
|
}
|
||||||
// } else if (recAction.value === 'showEdit') {
|
} else if (props.type === 'registration') {
|
||||||
// navigateTo(`/rehab/registration/${recId.value}/edit`)
|
// Handle registration type if needed
|
||||||
// } else if (recAction.value === 'showProcess') {
|
if (recAction.value === 'showDetail') {
|
||||||
// navigateTo(`/rehab/registration/${recId.value}/process`)
|
navigateTo(`${basePath.replace('/encounter', '/registration')}/${recId.value}/detail`)
|
||||||
// } else {
|
} else if (recAction.value === 'showEdit') {
|
||||||
// // handle other actions
|
navigateTo(`${basePath.replace('/encounter', '/registration')}/${recId.value}/edit`)
|
||||||
// }
|
} else if (recAction.value === 'showProcess') {
|
||||||
// }
|
navigateTo(`${basePath.replace('/encounter', '/registration')}/${recId.value}/process`)
|
||||||
|
} else {
|
||||||
|
// handle other actions
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -185,7 +211,10 @@ onMounted(() => {
|
|||||||
/>
|
/>
|
||||||
<Separator class="my-4 xl:my-5" />
|
<Separator class="my-4 xl:my-5" />
|
||||||
|
|
||||||
<Filter :ref-search-nav="refSearchNav" />
|
<Filter
|
||||||
|
:prep="hreaderPrep"
|
||||||
|
:ref-search-nav="refSearchNav"
|
||||||
|
/>
|
||||||
|
|
||||||
<AppEncounterList :data="data" />
|
<AppEncounterList :data="data" />
|
||||||
|
|
||||||
@@ -195,7 +224,13 @@ onMounted(() => {
|
|||||||
size="lg"
|
size="lg"
|
||||||
prevent-outside
|
prevent-outside
|
||||||
>
|
>
|
||||||
<AppEncounterFilter />
|
<AppEncounterFilter
|
||||||
|
:installation="{
|
||||||
|
msg: { placeholder: 'Pilih' },
|
||||||
|
items: [],
|
||||||
|
}"
|
||||||
|
:schema="{}"
|
||||||
|
/>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
<!-- Record Confirmation Modal -->
|
<!-- Record Confirmation Modal -->
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { PagePermission } from '~/models/role'
|
||||||
|
import Error from '~/components/pub/my-ui/error/error.vue'
|
||||||
|
import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ['rbac'],
|
||||||
|
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||||
|
title: 'Edit Kunjungan',
|
||||||
|
contentFrame: 'cf-full-width',
|
||||||
|
})
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: () => `${route.meta.title}`, // backtick to avoid the ts-plugin(2322) warning
|
||||||
|
})
|
||||||
|
|
||||||
|
const roleAccess: PagePermission = PAGE_PERMISSIONS['/emergency/encounter']
|
||||||
|
|
||||||
|
const { checkRole, hasUpdateAccess } = useRBAC()
|
||||||
|
|
||||||
|
// Check if user has access to this page
|
||||||
|
const hasAccess = checkRole(roleAccess)
|
||||||
|
if (!hasAccess) {
|
||||||
|
throw createError({
|
||||||
|
statusCode: 403,
|
||||||
|
statusMessage: 'Access denied',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define permission-based computed properties
|
||||||
|
const canUpdate = hasUpdateAccess(roleAccess)
|
||||||
|
|
||||||
|
// Get encounter ID from route params
|
||||||
|
const encounterId = computed(() => {
|
||||||
|
const id = route.params.id
|
||||||
|
return typeof id === 'string' ? parseInt(id) : 0
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="canUpdate">
|
||||||
|
<ContentEncounterEntry
|
||||||
|
:id="encounterId"
|
||||||
|
class-code="emergency"
|
||||||
|
sub-class-code="emg"
|
||||||
|
form-type="Edit"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Error
|
||||||
|
v-else
|
||||||
|
:status-code="403"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { PagePermission } from '~/models/role'
|
||||||
|
import Error from '~/components/pub/my-ui/error/error.vue'
|
||||||
|
import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ['rbac'],
|
||||||
|
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||||
|
title: 'Edit Kunjungan',
|
||||||
|
contentFrame: 'cf-full-width',
|
||||||
|
})
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: () => `${route.meta.title}`, // backtick to avoid the ts-plugin(2322) warning
|
||||||
|
})
|
||||||
|
|
||||||
|
const roleAccess: PagePermission = PAGE_PERMISSIONS['/inpatient/encounter']
|
||||||
|
|
||||||
|
const { checkRole, hasUpdateAccess } = useRBAC()
|
||||||
|
|
||||||
|
// Check if user has access to this page
|
||||||
|
const hasAccess = checkRole(roleAccess)
|
||||||
|
if (!hasAccess) {
|
||||||
|
throw createError({
|
||||||
|
statusCode: 403,
|
||||||
|
statusMessage: 'Access denied',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define permission-based computed properties
|
||||||
|
const canUpdate = hasUpdateAccess(roleAccess)
|
||||||
|
|
||||||
|
// Get encounter ID from route params
|
||||||
|
const encounterId = computed(() => {
|
||||||
|
const id = route.params.id
|
||||||
|
return typeof id === 'string' ? parseInt(id) : 0
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="canUpdate">
|
||||||
|
<ContentEncounterEntry
|
||||||
|
:id="encounterId"
|
||||||
|
class-code="inpatient"
|
||||||
|
sub-class-code="icu"
|
||||||
|
form-type="Edit"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Error
|
||||||
|
v-else
|
||||||
|
:status-code="403"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { PagePermission } from '~/models/role'
|
||||||
|
import Error from '~/components/pub/my-ui/error/error.vue'
|
||||||
|
import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ['rbac'],
|
||||||
|
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||||
|
title: 'Edit Kunjungan',
|
||||||
|
contentFrame: 'cf-full-width',
|
||||||
|
})
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: () => `${route.meta.title}`, // backtick to avoid the ts-plugin(2322) warning
|
||||||
|
})
|
||||||
|
|
||||||
|
const roleAccess: PagePermission = PAGE_PERMISSIONS['/outpatient/encounter']
|
||||||
|
|
||||||
|
const { checkRole, hasUpdateAccess } = useRBAC()
|
||||||
|
|
||||||
|
// Check if user has access to this page
|
||||||
|
const hasAccess = checkRole(roleAccess)
|
||||||
|
if (!hasAccess) {
|
||||||
|
throw createError({
|
||||||
|
statusCode: 403,
|
||||||
|
statusMessage: 'Access denied',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define permission-based computed properties
|
||||||
|
const canUpdate = hasUpdateAccess(roleAccess)
|
||||||
|
|
||||||
|
// Get encounter ID from route params
|
||||||
|
const encounterId = computed(() => {
|
||||||
|
const id = route.params.id
|
||||||
|
return typeof id === 'string' ? parseInt(id) : 0
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="canUpdate">
|
||||||
|
<ContentEncounterEntry
|
||||||
|
:id="encounterId"
|
||||||
|
class-code="ambulatory"
|
||||||
|
sub-class-code="reg"
|
||||||
|
form-type="Edit"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Error
|
||||||
|
v-else
|
||||||
|
:status-code="403"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
|||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: ['rbac'],
|
middleware: ['rbac'],
|
||||||
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||||
title: 'Tambah Kunjungan',
|
title: 'Edit Kunjungan',
|
||||||
contentFrame: 'cf-full-width',
|
contentFrame: 'cf-full-width',
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ useHead({
|
|||||||
|
|
||||||
const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/encounter']
|
const roleAccess: PagePermission = PAGE_PERMISSIONS['/rehab/encounter']
|
||||||
|
|
||||||
const { checkRole, hasCreateAccess } = useRBAC()
|
const { checkRole, hasUpdateAccess } = useRBAC()
|
||||||
|
|
||||||
// Check if user has access to this page
|
// Check if user has access to this page
|
||||||
const hasAccess = checkRole(roleAccess)
|
const hasAccess = checkRole(roleAccess)
|
||||||
@@ -30,12 +30,26 @@ if (!hasAccess) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Define permission-based computed properties
|
// Define permission-based computed properties
|
||||||
const canCreate = hasCreateAccess(roleAccess)
|
const canUpdate = hasUpdateAccess(roleAccess)
|
||||||
|
|
||||||
|
// Get encounter ID from route params
|
||||||
|
const encounterId = computed(() => {
|
||||||
|
const id = route.params.id
|
||||||
|
return typeof id === 'string' ? parseInt(id) : 0
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="canCreate">
|
<div v-if="canUpdate">
|
||||||
<ContentEncounterEntry :id="1" form-type="Edit" />
|
<ContentEncounterEntry
|
||||||
|
:id="encounterId"
|
||||||
|
class-code="ambulatory"
|
||||||
|
sub-class-code="rehab"
|
||||||
|
form-type="Edit"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Error v-else :status-code="403" />
|
<Error
|
||||||
|
v-else
|
||||||
|
:status-code="403"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
Reference in New Issue
Block a user