From e3fc1e4ab9014e0948dda6c412433509b03310de Mon Sep 17 00:00:00 2001 From: Andrian Roshandy Date: Sat, 15 Nov 2025 20:14:38 +0700 Subject: [PATCH 01/73] feat/radiology-order-54: adjust wip --- app/components/content/radiology-order/list.vue | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/components/content/radiology-order/list.vue b/app/components/content/radiology-order/list.vue index b2c8571d..47c822e9 100644 --- a/app/components/content/radiology-order/list.vue +++ b/app/components/content/radiology-order/list.vue @@ -13,7 +13,6 @@ import { recAction, recItem, isReadonly, - isFormEntryDialogOpen, isRecordConfirmationOpen, handleActionSave, handleActionRemove, @@ -28,6 +27,7 @@ const route = useRoute() const { setQueryParams } = useQueryParam() const title = ref('') +const addTrigger = ref(false) const plainEid = route.params.id const encounter_id = (plainEid && typeof plainEid == 'string') ? parseInt(plainEid) : 0 // here the @@ -74,7 +74,7 @@ const headerPrep: HeaderPrep = { onClick: () => { recItem.value = null recId.value = 0 - isFormEntryDialogOpen.value = true + addTrigger.value = true isReadonly.value = false }, }, @@ -90,7 +90,7 @@ const getMyDetail = async (id: number | string) => { if (result.success) { const currentValue = result.body?.data || {} recItem.value = currentValue - isFormEntryDialogOpen.value = true + addTrigger.value = true } } @@ -113,10 +113,10 @@ watch([recId, recAction], () => { } }) -watch([isFormEntryDialogOpen], async () => { - if (isFormEntryDialogOpen.value) { - isFormEntryDialogOpen.value = false; - const saveResp = await handleActionSave({ encounter_id }, getMyList, () =>{}, toast) +watch([addTrigger], async () => { + if (addTrigger.value) { + addTrigger.value = false; + const saveResp = await handleActionSave({ encounter_id, "scope_code": "rad" }, getMyList, () =>{}, toast) if (saveResp.success) { setQueryParams({ 'mode': 'entry', From cf5789549e7e86b6e93f9d784e3ccb433e22619f Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Sun, 23 Nov 2025 15:56:31 +0700 Subject: [PATCH 02/73] feat/mcu: improved wip --- .../app/mcu-order-item/list-entry.cfg.ts | 24 ++++---- .../app/mcu-order-item/list-entry.vue | 4 +- app/components/app/mcu-order-item/list.cfg.ts | 2 +- .../pub/my-ui/data/camuflage-input.vue | 59 +++++++++++++++++++ app/models/mcu-order-item.ts | 1 + app/services/mcu-order.service.ts | 13 ++++ 6 files changed, 90 insertions(+), 13 deletions(-) create mode 100644 app/components/pub/my-ui/data/camuflage-input.vue diff --git a/app/components/app/mcu-order-item/list-entry.cfg.ts b/app/components/app/mcu-order-item/list-entry.cfg.ts index 89d85dce..8bf2fb18 100644 --- a/app/components/app/mcu-order-item/list-entry.cfg.ts +++ b/app/components/app/mcu-order-item/list-entry.cfg.ts @@ -1,18 +1,19 @@ import type { Config } from '~/components/pub/my-ui/data-table' import { defineAsyncComponent } from 'vue' +import type { McuOrderItem } from '~/models/mcu-order-item' const action = defineAsyncComponent(() => import('~/components/pub/my-ui/data/dropdown-action-dud.vue')) -const input = defineAsyncComponent(() => import('~/components/pub/ui/input/Input.vue')) +const input = defineAsyncComponent(() => import('~/components/pub/my-ui/data/editable-div.vue')) export const config: Config = { - cols: [{}, {}, { classVal: '!p-0.5' }, { width: 50 }], + cols: [{}, {}, { classVal: '!p-0.5' }], headers: [ [ { label: 'Nama' }, { label: 'Jenis' }, - { label: 'Catatan' }, - { label: '' }, + { label: 'Catatan', classVal: '!w-[40%]' }, + // { label: '' }, ], ], @@ -27,16 +28,17 @@ export const config: Config = { return { idx, rec: rec as object, + props: { data: (rec as McuOrderItem).note }, component: input, } }, - action(rec, idx) { - return { - idx, - rec: rec as object, - component: action, - } - }, + // action(rec, idx) { + // return { + // idx, + // rec: rec as object, + // component: action, + // } + // }, }, htmls: {}, diff --git a/app/components/app/mcu-order-item/list-entry.vue b/app/components/app/mcu-order-item/list-entry.vue index 6c93c5ac..4fd8edb8 100644 --- a/app/components/app/mcu-order-item/list-entry.vue +++ b/app/components/app/mcu-order-item/list-entry.vue @@ -1,4 +1,6 @@ + + diff --git a/app/components/content/encounter/entry.vue b/app/components/content/encounter/entry.vue index 2a4730ad..eff0cb6d 100644 --- a/app/components/content/encounter/entry.vue +++ b/app/components/content/encounter/entry.vue @@ -31,10 +31,10 @@ const { isLoadingDetail, formObjects, openPatient, + isMemberValid, isSepValid, isCheckingSep, isSaveDisabled, - isSaving, isLoading, patients, selectedPatient, @@ -49,6 +49,7 @@ const { getPatientCurrent, getPatientByIdentifierSearch, getIsSubspecialist, + getValidateMember, getValidateSepNumber, handleFetchDoctors, } = useEncounterEntry(props) @@ -93,6 +94,8 @@ async function handleEvent(menu: string, value?: any) { }) } else if (menu === 'sep-number-changed') { await getValidateSepNumber(String(value || '')) + } else if (menu === 'member-changed') { + await getValidateMember(String(value || '')) } else if (menu === 'save') { await handleSaveEncounter(value) } else if (menu === 'cancel') { @@ -139,6 +142,7 @@ onMounted(async () => { ref="formRef" :mode="props.formType" :is-loading="isLoadingDetail" + :is-member-valid="isMemberValid" :is-sep-valid="isSepValid" :is-checking-sep="isCheckingSep" :payments="paymentsList" diff --git a/app/handlers/encounter-entry.handler.ts b/app/handlers/encounter-entry.handler.ts index 0b087d7f..b23e6409 100644 --- a/app/handlers/encounter-entry.handler.ts +++ b/app/handlers/encounter-entry.handler.ts @@ -23,6 +23,7 @@ import { getDetail as getEncounterDetail, update as updateEncounter, } from '~/services/encounter.service' +import { getList as getMemberList } from '~/services/vclaim-member.service' import { getList as getSepList } from '~/services/vclaim-sep.service' // Handlers @@ -59,6 +60,7 @@ export function useEncounterEntry(props: { const encounterData = ref(null) const formObjects = ref({}) const isSepValid = ref(false) + const isMemberValid = ref(false) const isCheckingSep = ref(false) const sepNumber = ref('') const vclaimReference = ref(null) @@ -201,6 +203,19 @@ export function useEncounterEntry(props: { return { specialist_id: null, subspecialist_id: null } } + async function getValidateMember(member: string) { + if (isCheckingSep.value) return + isMemberValid.value = false + try { + const result = await getMemberList({ mode: 'by-card', number: member, date: new Date().toISOString().split('T')[0] }) + if (result.success && result.body?.response !== null) { + isMemberValid.value = result.body?.metaData?.code === '200' + } + } catch (error) { + console.error('Error checking member:', error) + } + } + async function getValidateSepNumber(sepNumberValue: string) { vclaimReference.value = null if (!sepNumberValue || sepNumberValue.trim() === '') { @@ -220,11 +235,16 @@ export function useEncounterEntry(props: { 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, + jnsPelayanan: + response.jnsPelayanan === 'Rawat Jalan' ? '2' : response.jnsPelayanan === 'Rawat Inap' ? '1' : null, catatan: response.catatan || '', diagRujukan: response.diagnosa || '', tipeRujukan: response.tujuanKunj?.kode ?? '0', @@ -233,6 +253,7 @@ export function useEncounterEntry(props: { } } isSepValid.value = result.body?.metaData?.code === '200' + isMemberValid.value = isSepValid.value } } catch (error) { console.error('Error checking SEP:', error) @@ -497,7 +518,7 @@ export function useEncounterEntry(props: { if (paymentMethodCode) { payload.paymentMethod_code = paymentMethodCode } - + if (paymentMethodCode === 'insurance') { payload.insuranceCompany_id = formValues.insuranceCompany_id ?? null if (memberNumber) payload.member_number = memberNumber @@ -565,6 +586,7 @@ export function useEncounterEntry(props: { encounterData, formObjects, openPatient, + isMemberValid, isSepValid, isCheckingSep, isEditMode, @@ -585,6 +607,7 @@ export function useEncounterEntry(props: { getPatientsList, getPatientCurrent, getPatientByIdentifierSearch, + getValidateMember, getValidateSepNumber, handleFetchSpecialists, handleFetchDoctors, From 7605493d09b32d6e22903bb63f201d2738a1079a Mon Sep 17 00:00:00 2001 From: riefive Date: Thu, 27 Nov 2025 16:09:37 +0700 Subject: [PATCH 05/73] feat: create integration-sep file --- app/components/content/encounter/entry.vue | 2 - .../integration-sep-detail.handler.ts | 132 ++++++++++++++++++ 2 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 app/handlers/integration-sep-detail.handler.ts diff --git a/app/components/content/encounter/entry.vue b/app/components/content/encounter/entry.vue index eff0cb6d..c48e16e2 100644 --- a/app/components/content/encounter/entry.vue +++ b/app/components/content/encounter/entry.vue @@ -155,7 +155,6 @@ onMounted(async () => { @event="handleEvent" @fetch="handleFetch" /> - { " @save="handleSavePatient" /> -
-
+
+ + Aktif +
{{ noteReference }} diff --git a/app/components/content/encounter/entry.vue b/app/components/content/encounter/entry.vue index c48e16e2..8d11d0fb 100644 --- a/app/components/content/encounter/entry.vue +++ b/app/components/content/encounter/entry.vue @@ -93,9 +93,15 @@ async function handleEvent(menu: string, value?: any) { ...value, }) } else if (menu === 'sep-number-changed') { - await getValidateSepNumber(String(value || '')) + const sepNumberText = String(value || '').trim() + if (sepNumberText.length > 5) { + await getValidateSepNumber(sepNumberText) + } } else if (menu === 'member-changed') { - await getValidateMember(String(value || '')) + const memberText = String(value || '').trim() + if (memberText.length > 5) { + await getValidateMember(memberText) + } } else if (menu === 'save') { await handleSaveEncounter(value) } else if (menu === 'cancel') { diff --git a/app/handlers/encounter-entry.handler.ts b/app/handlers/encounter-entry.handler.ts index b23e6409..3d418991 100644 --- a/app/handlers/encounter-entry.handler.ts +++ b/app/handlers/encounter-entry.handler.ts @@ -209,6 +209,10 @@ export function useEncounterEntry(props: { try { const result = await getMemberList({ mode: 'by-card', number: member, date: new Date().toISOString().split('T')[0] }) if (result.success && result.body?.response !== null) { + const response = result.body?.response || {} + if (Object.keys(response).length > 0) { + formObjects.value.nationalIdentity = response.peserta?.nik || '' + } isMemberValid.value = result.body?.metaData?.code === '200' } } catch (error) { From e9ed2a3715889cedecfd4d25166085816c7a80f0 Mon Sep 17 00:00:00 2001 From: riefive Date: Fri, 28 Nov 2025 14:48:29 +0700 Subject: [PATCH 07/73] feat: implement SEP search functionality and enhance history management --- app/components/app/encounter/entry-form.vue | 24 +++------ app/components/app/sep/action-history.vue | 31 +++++++++++ app/components/app/sep/list-cfg.history.ts | 52 ++++++++++++++----- app/components/app/sep/list-history.vue | 5 +- app/components/app/sep/view-history.vue | 3 +- app/components/content/encounter/entry.vue | 16 ++++++ app/components/content/sep/entry.vue | 2 +- app/handlers/integration-sep-entry.handler.ts | 14 ++--- 8 files changed, 108 insertions(+), 39 deletions(-) create mode 100644 app/components/app/sep/action-history.vue diff --git a/app/components/app/encounter/entry-form.vue b/app/components/app/encounter/entry-form.vue index 43a7a48c..961b105c 100644 --- a/app/components/app/encounter/entry-form.vue +++ b/app/components/app/encounter/entry-form.vue @@ -183,6 +183,10 @@ function onAddSep() { emit('event', 'add-sep', formValues) } +function onSearchSep() { + emit('event', 'search-sep', { cardNumber: cardNumber.value }) +} + // Submit handler const onSubmit = handleSubmit((values) => { console.log('✅ Validated form values:', JSON.stringify(values, null, 2)) @@ -193,23 +197,11 @@ const onSubmit = handleSubmit((values) => { const formRef = ref(null) function submitForm() { - console.log('🔵 submitForm called, formRef:', formRef.value) - console.log('🔵 Form values:', { - doctorId: doctorId.value, - subSpecialistId: subSpecialistId.value, - registerDate: registerDate.value, - paymentType: paymentType.value, - }) - console.log('🔵 Form errors:', errors.value) - console.log('🔵 Form meta:', meta.value) - // Trigger form submit using native form submit // This will trigger validation and onSubmit handler if (formRef.value) { - console.log('🔵 Calling formRef.value.requestSubmit()') formRef.value.requestSubmit() } else { - console.warn('⚠️ formRef.value is null, cannot submit form') // Fallback: directly call onSubmit handler // Create a mock event object const mockEvent = { @@ -218,7 +210,6 @@ function submitForm() { } as SubmitEvent // Call onSubmit directly - console.log('🔵 Calling onSubmit with mock event') onSubmit(mockEvent) } } @@ -498,7 +489,7 @@ defineExpose({ v-bind="sepNumberAttrs" placeholder="Tambah SEP terlebih dahulu" class="flex-1" - :disabled="isLoading || isReadonly" + :disabled="isLoading || isReadonly || isSepValid" />