feat: add member validation and enhance encounter entry form with additional fields

This commit is contained in:
riefive
2025-11-27 14:19:58 +07:00
parent b38487e41f
commit d8f2e30bd6
3 changed files with 204 additions and 21 deletions
+174 -18
View File
@@ -23,11 +23,12 @@ import { useForm } from 'vee-validate'
import { refDebounced } from '@vueuse/core'
const props = defineProps<{
mode?: string
isLoading?: boolean
isReadonly?: boolean
isSepValid?: boolean
isMemberValid?: boolean
isCheckingSep?: boolean
mode?: string
doctor?: any[]
subSpecialist?: any[]
specialists?: TreeItem[]
@@ -61,6 +62,12 @@ const [patientName, patientNameAttrs] = defineField('patientName')
const [nationalIdentity, nationalIdentityAttrs] = defineField('nationalIdentity')
const [medicalRecordNumber, medicalRecordNumberAttrs] = defineField('medicalRecordNumber')
const patientId = ref('')
const sepReference = ref('')
const sepControlDate = ref('')
const sepTrafficStatus = ref('')
const diagnosis = ref('')
const noteReference = ref('Hanya diperlukan jika pembayaran jenis JKN')
const noteFile = ref('Gunakan file [.pdf, .jpg, .png] dengan ukuran maksimal 1MB')
const isLoading = props.isLoading !== undefined ? props.isLoading : false
const isReadonly = props.isReadonly !== undefined ? props.isReadonly : false
@@ -76,6 +83,8 @@ const doctorOpts = computed(() => {
return [...defaultOption, ...doctors]
})
const isJKNPayment = computed(() => paymentType.value === 'jkn')
const debouncedSepNumber = refDebounced(sepNumber, 500)
const debouncedCardNumber = refDebounced(cardNumber, 500)
if (mode === 'add') {
// Set default sepDate to current date in YYYY-MM-DD format
@@ -101,12 +110,14 @@ watch(subSpecialistId, async (newValue) => {
}
})
// Debounced SEP number watcher: emit change only after user stops typing
const debouncedSepNumber = refDebounced(sepNumber, 500)
watch(debouncedSepNumber, (newValue) => {
emit('event', 'sep-number-changed', newValue)
})
watch(debouncedCardNumber, (newValue) => {
emit('event', 'member-changed', newValue)
})
// Sync props to form fields
watch(
() => props.objects,
@@ -123,6 +134,10 @@ watch(
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 || ''
}
},
{ deep: true, immediate: true },
@@ -141,6 +156,20 @@ watch(
{ deep: true, immediate: true },
)
watch(
() => props.isSepValid,
(value) => {
if (!value) return
const objects = props.objects
if (objects && Object.keys(objects).length > 0) {
sepReference.value = objects?.sepReference || ''
sepControlDate.value = objects?.sepControlDate || ''
sepTrafficStatus.value = objects?.sepTrafficStatus || ''
diagnosis.value = objects?.diagnosis || ''
}
}
)
function onAddSep() {
const formValues = {
patientId: patientId.value || '',
@@ -391,6 +420,9 @@ defineExpose({
placeholder="Pilih Kelompok Peserta"
/>
</Field>
<span class="text-sm text-gray-500">
{{ noteReference }}
</span>
</Cell>
<Cell>
@@ -407,6 +439,26 @@ defineExpose({
placeholder="Masukkan nomor kartu BPJS"
/>
</Field>
<div
v-if="isMemberValid"
class="mt-1 flex items-center gap-2"
>
<Icon
name="i-lucide-badge-check"
class="h-4 w-4 bg-green-500 text-white"
/>
<span class="text-sm text-green-500">Aktif</span>
</div>
<div
v-if="!isMemberValid"
class="mt-1 flex items-center gap-2"
>
<Icon
name="i-lucide-x"
class="h-4 w-4 bg-red-500 text-white"
/>
<span class="text-sm text-red-500">Tidak aktif</span>
</div>
</Cell>
<Cell>
@@ -469,7 +521,19 @@ defineExpose({
/>
</Button>
<Button
v-else
v-if="!isSepValid"
variant="outline"
type="button"
class="bg-primary"
size="sm"
>
<Icon
name="i-lucide-search"
class="h-4 w-4"
/>
</Button>
<Button
v-if="isSepValid"
variant="outline"
type="button"
class="bg-green-500 text-white hover:bg-green-600"
@@ -483,23 +547,115 @@ defineExpose({
</Button>
</div>
</Field>
<span class="text-sm text-gray-500">
{{ noteReference }}
</span>
</Cell>
<FileUpload
field-name="sepFile"
label="Dokumen SEP"
placeholder="Unggah dokumen SEP"
:accept="['pdf', 'jpg', 'png']"
:max-size-mb="1"
/>
<Cell>
<FileUpload
field-name="sepFile"
label="Dokumen SEP"
placeholder=""
:accept="['pdf', 'jpg', 'png']"
:max-size-mb="1"
/>
<span class="mt-1 text-sm text-gray-500">
{{ noteFile }}
</span>
</Cell>
<FileUpload
field-name="sippFile"
label="Dokumen SIPP"
placeholder="Unggah dokumen SIPP"
:accept="['pdf', 'jpg', 'png']"
:max-size-mb="1"
/>
<Cell>
<FileUpload
field-name="sippFile"
label="Dokumen SIPP"
placeholder=""
:accept="['pdf', 'jpg', 'png']"
:max-size-mb="1"
/>
<span class="mt-1 text-sm text-gray-500">
{{ noteFile }}
</span>
</Cell>
</Block>
</template>
<template v-if="isSepValid">
<hr />
<!-- Data SEP -->
<h3 class="text-lg font-semibold">Data SEP</h3>
<Block
labelSize="thin"
class="!pt-0"
:colCount="3"
:cellFlex="false"
>
<Cell>
<Label height="compact">Dengan Rujukan / Surat Kontrol</Label>
<Field>
<Input
id="sepReference"
v-model="sepReference"
:disabled="true"
/>
</Field>
</Cell>
<Cell>
<Label height="compact">No. Rujukan / Surat Kontrol</Label>
<Field>
<Input
id="sepReference"
v-model="sepNumber"
:disabled="true"
/>
</Field>
</Cell>
<Cell>
<Label height="compact">
Tanggal Rujukan / Surat Kontrol
<span class="ml-1 text-red-500">*</span>
</Label>
<Field>
<DatepickerSingle
id="sepControlDate"
v-model="sepControlDate"
:disabled="true"
placeholder="Pilih tanggal sep"
/>
</Field>
</Cell>
</Block>
<Block
labelSize="thin"
class="!pt-0"
:colCount="3"
:cellFlex="false"
>
<Cell>
<Label height="compact">Diagnosis</Label>
<Field>
<Input
id="diagnosis"
v-model="diagnosis"
:disabled="true"
/>
</Field>
</Cell>
<Cell>
<Label height="compact">Status Kecelakaan</Label>
<Field>
<Input
id="sepTrafficStatus"
v-model="sepTrafficStatus"
:disabled="true"
/>
</Field>
</Cell>
</Block>
</template>
</form>
+5 -1
View File
@@ -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"