feat: enhance SEP entry and detail handling with new link mode and save functionality
This commit is contained in:
No files matched your search
@@ -14,7 +14,7 @@ const recSepId = inject('rec_sep_id') as Ref<string>
|
|||||||
|
|
||||||
function handleSelection() {
|
function handleSelection() {
|
||||||
recSepId.value = record.sepNumber || ''
|
recSepId.value = record.sepNumber || ''
|
||||||
const pathUrl = `/integration/bpjs-vclaim/sep/${record.sepNumber || ''}/detail`
|
const pathUrl = `/integration/bpjs-vclaim/sep/${record.sepNumber || ''}/link`
|
||||||
router.push({ path: pathUrl })
|
router.push({ path: pathUrl })
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ const props = defineProps<{
|
|||||||
cities: any[]
|
cities: any[]
|
||||||
districts: any[]
|
districts: any[]
|
||||||
specialists?: TreeItem[]
|
specialists?: TreeItem[]
|
||||||
|
sepNumber?: string
|
||||||
objects?: any
|
objects?: any
|
||||||
values?: any
|
values?: any
|
||||||
}>()
|
}>()
|
||||||
@@ -129,6 +130,14 @@ async function onFetchChildren(parentId: string): Promise<void> {
|
|||||||
console.log('onFetchChildren', parentId)
|
console.log('onFetchChildren', parentId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onBack = () => {
|
||||||
|
emit('event', 'back')
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSaveNumber = () => {
|
||||||
|
emit('event', 'save-sep-number', { sepNumber: props.sepNumber})
|
||||||
|
}
|
||||||
|
|
||||||
// Submit handler
|
// Submit handler
|
||||||
const onSubmit = handleSubmit((values) => {
|
const onSubmit = handleSubmit((values) => {
|
||||||
console.log('✅ Validated form values:', JSON.stringify(values, null, 2))
|
console.log('✅ Validated form values:', JSON.stringify(values, null, 2))
|
||||||
@@ -966,6 +975,7 @@ onMounted(() => {
|
|||||||
<!-- Actions -->
|
<!-- Actions -->
|
||||||
<div class="mt-6 flex justify-end gap-2">
|
<div class="mt-6 flex justify-end gap-2">
|
||||||
<Button
|
<Button
|
||||||
|
v-if="props.mode === 'detail'"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
type="button"
|
type="button"
|
||||||
class="h-[40px] min-w-[120px] text-orange-400 hover:bg-green-50"
|
class="h-[40px] min-w-[120px] text-orange-400 hover:bg-green-50"
|
||||||
@@ -978,6 +988,7 @@ onMounted(() => {
|
|||||||
Riwayat SEP
|
Riwayat SEP
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
|
v-if="props.mode === 'detail'"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
type="button"
|
type="button"
|
||||||
class="h-[40px] min-w-[120px] rounded-md border-orange-400 text-orange-400 hover:bg-green-50 hover:text-orange-400"
|
class="h-[40px] min-w-[120px] rounded-md border-orange-400 text-orange-400 hover:bg-green-50 hover:text-orange-400"
|
||||||
@@ -989,6 +1000,7 @@ onMounted(() => {
|
|||||||
Preview
|
Preview
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
|
v-if="props.mode === 'add'"
|
||||||
type="button"
|
type="button"
|
||||||
class="h-[40px] min-w-[120px] text-white"
|
class="h-[40px] min-w-[120px] text-white"
|
||||||
:disabled="isLoading"
|
:disabled="isLoading"
|
||||||
@@ -1000,6 +1012,32 @@ onMounted(() => {
|
|||||||
/>
|
/>
|
||||||
Simpan
|
Simpan
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
v-if="props.mode === 'detail'"
|
||||||
|
type="button"
|
||||||
|
class="h-[40px] min-w-[120px] text-white"
|
||||||
|
:disabled="isLoading"
|
||||||
|
@click="onBack"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name="i-lucide-chevron-left"
|
||||||
|
class="h-5 w-5"
|
||||||
|
/>
|
||||||
|
Kembali
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
v-if="props.mode === 'link'"
|
||||||
|
type="button"
|
||||||
|
class="h-[40px] min-w-[120px] text-white"
|
||||||
|
:disabled="isLoading"
|
||||||
|
@click="onSaveNumber"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name="i-lucide-save"
|
||||||
|
class="h-5 w-5"
|
||||||
|
/>
|
||||||
|
Terapkan
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import AppViewLetter from '~/components/app/sep/view-letter.vue'
|
|||||||
|
|
||||||
// Handler
|
// Handler
|
||||||
import { useIntegrationSepEntry } from '~/handlers/integration-sep-entry.handler'
|
import { useIntegrationSepEntry } from '~/handlers/integration-sep-entry.handler'
|
||||||
|
import { useIntegrationSepDetail } from '~/handlers/integration-sep-detail.handler'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
histories,
|
histories,
|
||||||
@@ -55,8 +56,18 @@ const {
|
|||||||
handleInit,
|
handleInit,
|
||||||
} = useIntegrationSepEntry()
|
} = useIntegrationSepEntry()
|
||||||
|
|
||||||
|
const { valueObjects, getSepDetail } = useIntegrationSepDetail()
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
mode: 'add' | 'edit' | 'detail' | 'link'
|
||||||
|
}>()
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await handleInit()
|
await handleInit()
|
||||||
|
if (['detail', 'link'].includes(props.mode)) {
|
||||||
|
await getSepDetail()
|
||||||
|
selectedObjects.value = { ...selectedObjects.value, ...valueObjects.value }
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -66,10 +77,10 @@ onMounted(async () => {
|
|||||||
name="i-lucide-panel-bottom"
|
name="i-lucide-panel-bottom"
|
||||||
class="me-2"
|
class="me-2"
|
||||||
/>
|
/>
|
||||||
<span class="font-semibold">Tambah</span>
|
<span class="font-semibold">{{ ['detail', 'link'].includes(props.mode) ? 'Detail' : 'Tambah' }} SEP</span>
|
||||||
SEP
|
|
||||||
</div>
|
</div>
|
||||||
<AppSepEntryForm
|
<AppSepEntryForm
|
||||||
|
:mode="props.mode"
|
||||||
:is-save-loading="isSaveLoading"
|
:is-save-loading="isSaveLoading"
|
||||||
:is-service="isServiceHidden"
|
:is-service="isServiceHidden"
|
||||||
:doctors="doctors"
|
:doctors="doctors"
|
||||||
|
|||||||
@@ -39,67 +39,55 @@ export function useIntegrationSepDetail() {
|
|||||||
if (result.success && result.body?.response) {
|
if (result.success && result.body?.response) {
|
||||||
const response = result.body.response
|
const response = result.body.response
|
||||||
sepData.value = response
|
sepData.value = response
|
||||||
|
|
||||||
// Map response to form objects
|
|
||||||
// patientName.value = objects?.patientName || ''
|
|
||||||
// nationalIdentity.value = objects?.nationalIdentity || ''
|
|
||||||
// medicalRecordNumber.value = objects?.medicalRecordNumber || ''
|
|
||||||
// doctorId.value = objects?.doctorId || ''
|
|
||||||
// subSpecialistId.value = objects?.subSpecialistId || ''
|
|
||||||
// registerDate.value = objects?.registerDate || ''
|
|
||||||
// paymentType.value = objects?.paymentType || ''
|
|
||||||
// patientCategory.value = objects?.patientCategory || ''
|
|
||||||
// cardNumber.value = objects?.cardNumber || ''
|
|
||||||
// sepType.value = objects?.sepType || ''
|
|
||||||
// sepNumber.value = objects?.sepNumber || ''
|
|
||||||
// sepReference.value = objects?.sepReference || ''
|
|
||||||
// sepControlDate.value = objects?.sepControlDate || ''
|
|
||||||
// sepTrafficStatus.value = objects?.sepTrafficStatus || ''
|
|
||||||
// diagnosis.value = objects?.diagnosis || ''
|
|
||||||
|
|
||||||
// if (Object.keys(response).length > 0) {
|
|
||||||
// formObjects.value.patientName = response.peserta?.nama || '-'
|
|
||||||
// formObjects.value.medicalRecordNumber = response.peserta?.noMr || '-'
|
|
||||||
// formObjects.value.cardNumber = response.peserta?.noKartu || '-'
|
|
||||||
// formObjects.value.registerDate = response.tglSep || null
|
|
||||||
// formObjects.value.sepReference = response.noSep || '-'
|
|
||||||
// formObjects.value.sepControlDate = response.tglSep || null
|
|
||||||
// formObjects.value.sepTrafficStatus = response.nmstatusKecelakaan || '-'
|
|
||||||
// formObjects.value.diagnosis = response.diagnosa || '-'
|
|
||||||
// vclaimReference.value = {
|
|
||||||
// noSep: response.noSep || sepNumberValue.trim(),
|
|
||||||
// tglRujukan: response.tglSep ? new Date(response.tglSep).toISOString() : null,
|
|
||||||
// ppkDirujuk: response.noRujukan || 'rssa',
|
|
||||||
// jnsPelayanan:
|
|
||||||
// response.jnsPelayanan === 'Rawat Jalan' ? '2' : response.jnsPelayanan === 'Rawat Inap' ? '1' : null,
|
|
||||||
// catatan: response.catatan || '',
|
|
||||||
// diagRujukan: response.diagnosa || '',
|
|
||||||
// tipeRujukan: response.tujuanKunj?.kode ?? '0',
|
|
||||||
// poliRujukan: response.poli || '',
|
|
||||||
// user: userStore.user?.user_name || '',
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
valueObjects.value = {
|
valueObjects.value = {
|
||||||
noSep: response.noSep || noSep.value,
|
sepNumber: response.noSep || noSep.value,
|
||||||
tglRujukan: response.tglSep ? new Date(response.tglSep).toISOString().split('T')[0] : '',
|
eSep: response.eSEP === 'True' ? 'yes' : 'no',
|
||||||
ppkDirujuk: response.noRujukan || '',
|
serviceType: response.jnsPelayanan === 'Rawat Jalan' ? '2' : response.jnsPelayanan === 'Rawat Inap' ? '1' : null,
|
||||||
jnsPelayanan: mapServiceCodeToLabel(response.jnsPelayanan),
|
sepDate: response.tglSep ? new Date(response.tglSep).toISOString().split('T')[0] : '',
|
||||||
catatan: response.catatan || '',
|
|
||||||
diagRujukan: response.diagnosa || '',
|
|
||||||
tipeRujukan: response.tujuanKunj?.kode ?? '0',
|
|
||||||
poliRujukan: response.poli || '',
|
|
||||||
user: response.dpjp?.kdDPJP || response.dpjp?.nmDPJP || '',
|
|
||||||
// Additional fields dari response
|
|
||||||
patientName: response.peserta?.nama || '-',
|
|
||||||
medicalRecordNumber: response.peserta?.noMr || '-',
|
|
||||||
cardNumber: response.peserta?.noKartu || '-',
|
cardNumber: response.peserta?.noKartu || '-',
|
||||||
diagnosis: response.diagnosa || '-',
|
patientName: response.peserta?.nama || '-',
|
||||||
sepReference: response.noSep || '-',
|
phoneNumber: response.peserta?.noTelp || '-',
|
||||||
sepControlDate: response.tglSep || null,
|
medicalRecordNumber: response.peserta?.noMr || '-',
|
||||||
sepTrafficStatus: response.nmstatusKecelakaan || '-',
|
memberInsurance: response.peserta?.asuransi || '-',
|
||||||
kelasRawat: response.kelasRawat || '-',
|
memberClass: response.peserta?.hakKelas || '-',
|
||||||
referralNumber: response.noRujukan || '-',
|
memberGender: response.peserta?.kelamin || '-',
|
||||||
|
memberBirthDate: response.peserta?.tglLahir || '-',
|
||||||
|
memberType: response.peserta?.jnsPeserta || '-',
|
||||||
|
referralLetterNumber: response.noRujukan || '-',
|
||||||
|
initialDiagnosis: response.diagnosa || '-',
|
||||||
|
attendingDoctor: response.dpjp?.kdDPJP || '-',
|
||||||
|
attendingDoctorName: response.dpjp?.nmDPJP || '-',
|
||||||
|
polyName: response.poli || '-',
|
||||||
|
cob: response.cob === '1' ? 'yes' : 'no',
|
||||||
|
cataract: response.katarak === '1' ? 'yes' : 'no',
|
||||||
|
clinicExcecutive: response.poliEksekutif === '1' ? 'yes' : 'no',
|
||||||
|
procedureType: response.flagProcedure?.kode || '-',
|
||||||
|
procedureTypeName: response.flagProcedure?.nama || '-',
|
||||||
|
supportCode: response.kdPenunjang?.kode || '-',
|
||||||
|
supportCodeName: response.kdPenunjang?.nama || '-',
|
||||||
|
note: response.catatan || response.informasi || '-',
|
||||||
|
classLevel: response.kelasRawat || '-',
|
||||||
|
classLevelUpgrade: response.klsRawat?.klsRawatNaik || '-',
|
||||||
|
classPaySource: response.klsRawat?.pembiayaan || '-',
|
||||||
|
responsiblePerson: response.klsRawat?.penanggungJawab || response.penjamin || '-',
|
||||||
|
purposeOfVisit: response.tujuanKunj?.kode || '-',
|
||||||
|
purposeOfVisitName: response.tujuanKunj?.nama || '-',
|
||||||
|
serviceAssessment: response.assestmenPel?.kode || '-',
|
||||||
|
serviceAssessmentName: response.assestmenPel?.nama || '-',
|
||||||
|
trafficAccident: response.nmstatusKecelakaan || '',
|
||||||
|
trafficAccidentCode: response.kdStatusKecelakaan || '',
|
||||||
|
lpNumber: response.kontrol?.noSurat || '-',
|
||||||
|
accidentDate: response.lokasiKejadian?.tglKejadian || '-',
|
||||||
|
accidentNote: response.lokasiKejadian?.ketKejadian || '-',
|
||||||
|
accidentProvince: response.lokasiKejadian?.kdProp || '-',
|
||||||
|
accidentCity: response.lokasiKejadian?.kdKab || '-',
|
||||||
|
accidentDistrict: response.lokasiKejadian?.kdKec || '-',
|
||||||
|
accidentLocation: response.lokasiKejadian?.lokasi || '-',
|
||||||
|
suplesi: response.jnsPelayanan === 'Rawat Jalan' ? 'yes' : 'no',
|
||||||
|
suplesiNumber: response.jnsPelayanan === 'Rawat Jalan' ? response.noRujukan || '-' : '-',
|
||||||
|
controlLetterNumber: response.kontrol?.noSurat || '-',
|
||||||
|
controlLetterDoctor: response.kontrol?.kdDokter || '-',
|
||||||
|
controlLetterDoctorName: response.kontrol?.nmDokter || '-',
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
toast({
|
toast({
|
||||||
|
|||||||
@@ -442,6 +442,9 @@ export function useIntegrationSepEntry() {
|
|||||||
if (menu === 'back') {
|
if (menu === 'back') {
|
||||||
navigateTo('/integration/bpjs-vclaim/sep')
|
navigateTo('/integration/bpjs-vclaim/sep')
|
||||||
}
|
}
|
||||||
|
if (menu === 'save-sep-number') {
|
||||||
|
navigateTo({ path: resourcePath.value, query: { 'sep-number': value.sepNumber || '' } })
|
||||||
|
}
|
||||||
if (menu === 'save-sep') {
|
if (menu === 'save-sep') {
|
||||||
isSaveLoading.value = true
|
isSaveLoading.value = true
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import Error from '~/components/pub/my-ui/error/error.vue'
|
||||||
|
import Content from '~/components/content/sep/entry.vue'
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
middleware: [],
|
||||||
|
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||||
|
title: 'Detail SEP',
|
||||||
|
contentFrame: 'cf-full-width',
|
||||||
|
})
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: () => route.meta.title as string,
|
||||||
|
})
|
||||||
|
|
||||||
|
const canCreate = true
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="canCreate">
|
||||||
|
<Content mode="detail" />
|
||||||
|
</div>
|
||||||
|
<Error v-else :status-code="403" />
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import Error from '~/components/pub/my-ui/error/error.vue'
|
||||||
|
import Content from '~/components/content/sep/entry.vue'
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
middleware: [],
|
||||||
|
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||||
|
title: 'Detail SEP',
|
||||||
|
contentFrame: 'cf-full-width',
|
||||||
|
})
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: () => route.meta.title as string,
|
||||||
|
})
|
||||||
|
|
||||||
|
const canCreate = true
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="canCreate">
|
||||||
|
<Content mode="link" />
|
||||||
|
</div>
|
||||||
|
<Error v-else :status-code="403" />
|
||||||
|
</template>
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { PagePermission } from '~/models/role'
|
|
||||||
import Error from '~/components/pub/my-ui/error/error.vue'
|
import Error from '~/components/pub/my-ui/error/error.vue'
|
||||||
import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
import Content from '~/components/content/sep/entry.vue'
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: [],
|
middleware: [],
|
||||||
@@ -16,26 +15,12 @@ useHead({
|
|||||||
title: () => route.meta.title as string,
|
title: () => route.meta.title as string,
|
||||||
})
|
})
|
||||||
|
|
||||||
const roleAccess: PagePermission = PAGE_PERMISSIONS['/doctor']
|
const canCreate = true
|
||||||
|
|
||||||
const { checkRole, hasCreateAccess } = 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 canCreate = true // hasCreateAccess(roleAccess)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="canCreate">
|
<div v-if="canCreate">
|
||||||
<ContentSepEntry />
|
<Content mode="add" />
|
||||||
</div>
|
</div>
|
||||||
<Error v-else :status-code="403" />
|
<Error v-else :status-code="403" />
|
||||||
</template>
|
</template>
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { PagePermission } from '~/models/role'
|
|
||||||
import Error from '~/components/pub/my-ui/error/error.vue'
|
import Error from '~/components/pub/my-ui/error/error.vue'
|
||||||
import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
import Content from '~/components/content/sep/list.vue'
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: ['rbac'],
|
middleware: ['rbac'],
|
||||||
@@ -16,24 +15,13 @@ useHead({
|
|||||||
title: () => route.meta.title as string,
|
title: () => route.meta.title as string,
|
||||||
})
|
})
|
||||||
|
|
||||||
const roleAccess: PagePermission = PAGE_PERMISSIONS['/doctor']
|
const canRead = true
|
||||||
|
|
||||||
const { checkRole, hasReadAccess } = useRBAC()
|
|
||||||
|
|
||||||
// Check if user has access to this page
|
|
||||||
const hasAccess = checkRole(roleAccess)
|
|
||||||
// if (!hasAccess) {
|
|
||||||
// navigateTo('/403')
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Define permission-based computed properties
|
|
||||||
const canRead = true // hasReadAccess(roleAccess)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="canRead">
|
<div v-if="canRead">
|
||||||
<ContentSepList />
|
<Content />
|
||||||
</div>
|
</div>
|
||||||
<Error v-else :status-code="403" />
|
<Error v-else :status-code="403" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user