feat(sep): add form support code
This commit is contained in:
No files matched your search
@@ -19,6 +19,7 @@ import type { PatientEntity } from '~/models/patient'
|
||||
// Helpers
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import { useForm } from 'vee-validate'
|
||||
import { se } from "date-fns/locale"
|
||||
|
||||
const props = defineProps<{
|
||||
isLoading?: boolean
|
||||
@@ -26,6 +27,12 @@ const props = defineProps<{
|
||||
doctors: any[]
|
||||
diagnoses: any[]
|
||||
facilities: any[]
|
||||
serviceTypes: any[]
|
||||
registerMethods: any[]
|
||||
accidents: any[]
|
||||
purposes: any[]
|
||||
procedures: any[]
|
||||
assessments: any[]
|
||||
supportCodes: any[]
|
||||
patient?: PatientEntity | null | undefined
|
||||
values?: any
|
||||
@@ -39,11 +46,6 @@ const emit = defineEmits<{
|
||||
const isLoading = props.isLoading !== undefined ? props.isLoading : false
|
||||
const isReadonly = props.isReadonly !== undefined ? props.isReadonly : false
|
||||
|
||||
const admissionTypes = [
|
||||
{ value: '1', label: 'Kontrol' },
|
||||
{ value: '2', label: 'Rujukan' },
|
||||
]
|
||||
|
||||
// Validation schema (moved to shared file)
|
||||
const { handleSubmit, errors, defineField, meta } = useForm<IntegrationBpjsFormData>({
|
||||
validationSchema: toTypedSchema(IntegrationBpjsSchema),
|
||||
@@ -51,6 +53,7 @@ const { handleSubmit, errors, defineField, meta } = useForm<IntegrationBpjsFormD
|
||||
|
||||
// Bind fields and extract attrs for consistent Field pattern
|
||||
const [sepDate, sepDateAttrs] = defineField('sepDate')
|
||||
const [serviceType, serviceTypeAttrs] = defineField('serviceType')
|
||||
const [admissionType, admissionTypeAttrs] = defineField('admissionType')
|
||||
const [bpjsNumber, bpjsNumberAttrs] = defineField('bpjsNumber')
|
||||
const [nationalId, nationalIdAttrs] = defineField('nationalId')
|
||||
@@ -59,6 +62,7 @@ const [patientName, patientNameAttrs] = defineField('patientName')
|
||||
const [phoneNumber, phoneNumberAttrs] = defineField('phoneNumber')
|
||||
const [referralLetterNumber, referralLetterNumberAttrs] = defineField('referralLetterNumber')
|
||||
const [referralLetterDate, referralLetterDateAttrs] = defineField('referralLetterDate')
|
||||
const [fromClinic, fromClinicAttrs] = defineField('fromClinic')
|
||||
const [destinationClinic, destinationClinicAttrs] = defineField('destinationClinic')
|
||||
const [attendingDoctor, attendingDoctorAttrs] = defineField('attendingDoctor')
|
||||
const [initialDiagnosis, initialDiagnosisAttrs] = defineField('initialDiagnosis')
|
||||
@@ -68,6 +72,13 @@ const [clinicExcecutive, clinicExcecutiveAttrs] = defineField('clinicExcecutive'
|
||||
const [procedureType, procedureTypeAttrs] = defineField('procedureType')
|
||||
const [supportCode, supportCodeAttrs] = defineField('supportCode')
|
||||
const [note, noteAttrs] = defineField('note')
|
||||
const [accident, accidentAttrs] = defineField('trafficAccident')
|
||||
const [purposeOfVisit, purposeOfVisitAttrs] = defineField('purposeOfVisit')
|
||||
const [serviceAssessment, serviceAssessmentAttrs] = defineField('serviceAssessment')
|
||||
const titleLetterNumber = computed(() => (admissionType.value === '3' ? 'Surat Kontrol' : 'Surat Rujukan'))
|
||||
const titleLetterDate = computed(() =>
|
||||
admissionType.value === '3' ? 'Tanggal Surat Kontrol' : 'Tanggal Surat Rujukan',
|
||||
)
|
||||
|
||||
// Submit handler
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
@@ -115,6 +126,23 @@ watch(props, (value) => {
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label height="compact">Pelayanan</Label>
|
||||
<Field :errMessage="errors.serviceType">
|
||||
<Select
|
||||
id="serviceType"
|
||||
icon-name="i-lucide-chevron-down"
|
||||
v-model="serviceType"
|
||||
v-bind="serviceTypeAttrs"
|
||||
:items="serviceTypes"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Pelayanan"
|
||||
@change="emit('event', 'service-type', $event)"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label height="compact">Jalur</Label>
|
||||
<Field :errMessage="errors.admissionType">
|
||||
@@ -123,7 +151,7 @@ watch(props, (value) => {
|
||||
icon-name="i-lucide-chevron-down"
|
||||
v-model="admissionType"
|
||||
v-bind="admissionTypeAttrs"
|
||||
:items="admissionTypes"
|
||||
:items="registerMethods"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih jalur"
|
||||
@change="emit('event', 'admission-type', $event)"
|
||||
@@ -171,6 +199,7 @@ watch(props, (value) => {
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label height="compact">
|
||||
No. KTP
|
||||
@@ -185,6 +214,7 @@ watch(props, (value) => {
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label height="compact">
|
||||
No. RM
|
||||
@@ -199,6 +229,7 @@ watch(props, (value) => {
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label height="compact">
|
||||
Nama Pasien
|
||||
@@ -213,6 +244,7 @@ watch(props, (value) => {
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label height="compact">
|
||||
No. Telepon
|
||||
@@ -241,7 +273,7 @@ watch(props, (value) => {
|
||||
>
|
||||
<Cell>
|
||||
<Label height="compact">
|
||||
No. Surat Kontrol
|
||||
{{ titleLetterNumber }}
|
||||
<span class="text-red-500">*</span>
|
||||
</Label>
|
||||
<Field :errMessage="errors.referralLetterNumber">
|
||||
@@ -268,9 +300,10 @@ watch(props, (value) => {
|
||||
</div>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label height="compact">
|
||||
Tanggal Surat Kontrol
|
||||
{{ titleLetterDate }}
|
||||
<span class="text-red-500">*</span>
|
||||
</Label>
|
||||
<Field :errMessage="errors.referralLetterDate">
|
||||
@@ -278,30 +311,11 @@ watch(props, (value) => {
|
||||
id="referralLetterDate"
|
||||
v-model="referralLetterDate"
|
||||
v-bind="referralLetterDateAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
:disabled="true"
|
||||
placeholder="Pilih tanggal surat kontrol"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label height="compact">
|
||||
Klinik Tujuan
|
||||
<span class="text-red-500">*</span>
|
||||
</Label>
|
||||
<Field :errMessage="errors.destinationClinic">
|
||||
<Combobox
|
||||
id="destinationClinic"
|
||||
v-model="destinationClinic"
|
||||
v-bind="destinationClinicAttrs"
|
||||
:items="facilities"
|
||||
:is-disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Klinik"
|
||||
search-placeholder="Cari Klinik"
|
||||
empty-message="Item tidak ditemukan"
|
||||
@update:searchText="emit('fetch', { menu: 'destinationClinic', value: $event })"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label height="compact">
|
||||
@@ -332,6 +346,46 @@ watch(props, (value) => {
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label height="compact">
|
||||
Faskes Asal
|
||||
<span class="text-red-500">*</span>
|
||||
</Label>
|
||||
<Field :errMessage="errors.fromClinic">
|
||||
<Combobox
|
||||
id="fromClinic"
|
||||
v-model="fromClinic"
|
||||
v-bind="fromClinicAttrs"
|
||||
:items="facilities"
|
||||
:is-disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Asal"
|
||||
search-placeholder="Cari Asal"
|
||||
empty-message="Item tidak ditemukan"
|
||||
@update:searchText="emit('fetch', { menu: 'clinic', value: $event })"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label height="compact">
|
||||
Klinik Tujuan
|
||||
<span class="text-red-500">*</span>
|
||||
</Label>
|
||||
<Field :errMessage="errors.destinationClinic">
|
||||
<Combobox
|
||||
id="destinationClinic"
|
||||
v-model="destinationClinic"
|
||||
v-bind="destinationClinicAttrs"
|
||||
:items="facilities"
|
||||
:is-disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Klinik"
|
||||
search-placeholder="Cari Klinik"
|
||||
empty-message="Item tidak ditemukan"
|
||||
@update:searchText="emit('fetch', { menu: 'clinic', value: $event })"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label height="compact">
|
||||
DPJP
|
||||
@@ -347,7 +401,7 @@ watch(props, (value) => {
|
||||
placeholder="Pilih DPJP"
|
||||
search-placeholder="Cari DPJP"
|
||||
empty-message="Item tidak ditemukan"
|
||||
@update:searchText="emit('fetch', { menu: 'attendingDoctor', value: $event })"
|
||||
@update:searchText="emit('fetch', { menu: 'doctor', value: $event })"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
@@ -367,13 +421,13 @@ watch(props, (value) => {
|
||||
placeholder="Pilih Diagnosa Awal"
|
||||
search-placeholder="Cari Diagnosa Awal"
|
||||
empty-message="Item tidak ditemukan"
|
||||
@update:searchText="emit('fetch', { menu: 'initialDiagnosis', value: $event })"
|
||||
@update:searchText="emit('fetch', { menu: 'diagnosis', value: $event })"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
|
||||
<Block
|
||||
<Block
|
||||
labelSize="thin"
|
||||
class="!pt-0"
|
||||
:colCount="1"
|
||||
@@ -392,12 +446,12 @@ watch(props, (value) => {
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
</Block>
|
||||
|
||||
<Block
|
||||
labelSize="thin"
|
||||
class="!pt-0"
|
||||
:colCount="2"
|
||||
:colCount="3"
|
||||
:cellFlex="false"
|
||||
>
|
||||
<Cell>
|
||||
@@ -457,33 +511,29 @@ watch(props, (value) => {
|
||||
</RadioGroup>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
|
||||
<Block
|
||||
labelSize="thin"
|
||||
class="!pt-0"
|
||||
:colCount="3"
|
||||
:cellFlex="false"
|
||||
>
|
||||
<Cell>
|
||||
<Label height="compact">
|
||||
Jenis Prosedur
|
||||
Status Kecelakaan
|
||||
<span class="text-red-500">*</span>
|
||||
</Label>
|
||||
<Field :errMessage="errors.procedureType">
|
||||
<RadioGroup
|
||||
v-model="procedureType"
|
||||
class="flex items-center gap-2"
|
||||
v-bind="procedureTypeAttrs"
|
||||
>
|
||||
<div class="flex items-center space-x-2">
|
||||
<RadioGroupItem
|
||||
value="0"
|
||||
id="procedure-one"
|
||||
/>
|
||||
<Label for="procedure-one">Prosedur tidak berkelanjutan</Label>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<RadioGroupItem
|
||||
value="1"
|
||||
id="procedure-two"
|
||||
/>
|
||||
<Label for="procedure-two">Prosedur dan terapi berkelanjutan</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
<Field :errMessage="errors.trafficAccident">
|
||||
<Select
|
||||
id="accident"
|
||||
icon-name="i-lucide-chevron-down"
|
||||
v-model="accident"
|
||||
v-bind="accidentAttrs"
|
||||
:items="accidents"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Status Kecelakaan"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -495,6 +545,60 @@ watch(props, (value) => {
|
||||
:cellFlex="false"
|
||||
>
|
||||
<Cell>
|
||||
<Label height="compact">
|
||||
Tujuan Kunjungan
|
||||
<span class="text-red-500">*</span>
|
||||
</Label>
|
||||
<Field :errMessage="errors.purposeOfVisit">
|
||||
<Select
|
||||
id="purposeOfVisit"
|
||||
icon-name="i-lucide-chevron-down"
|
||||
v-model="purposeOfVisit"
|
||||
v-bind="purposeOfVisitAttrs"
|
||||
:items="purposes"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Tujuan Kunjungan"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell v-if="purposeOfVisit === '1'">
|
||||
<Label height="compact">
|
||||
Jenis Prosedur
|
||||
<span class="text-red-500">*</span>
|
||||
</Label>
|
||||
<Field :errMessage="errors.procedureType">
|
||||
<Select
|
||||
id="procedureType"
|
||||
icon-name="i-lucide-chevron-down"
|
||||
v-model="procedureType"
|
||||
v-bind="procedureTypeAttrs"
|
||||
:items="procedures"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Jenis Prosedur"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell v-if="purposeOfVisit === '2'">
|
||||
<Label height="compact">
|
||||
Assemen Pelayanan
|
||||
<span class="text-red-500">*</span>
|
||||
</Label>
|
||||
<Field :errMessage="errors.serviceAssessment">
|
||||
<Select
|
||||
id="serviceAssessment"
|
||||
icon-name="i-lucide-chevron-down"
|
||||
v-model="serviceAssessment"
|
||||
v-bind="serviceAssessmentAttrs"
|
||||
:items="assessments"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Assemen Pelayanan"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell v-if="purposeOfVisit === '1'">
|
||||
<Label height="compact">
|
||||
Kode Penunjang
|
||||
<span class="text-red-500">*</span>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRoute } from "vue-router"
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
// Components
|
||||
import AppViewHistory from '~/components/app/sep/view-history.vue'
|
||||
@@ -12,7 +12,7 @@ import type { SepHistoryData } from '~/components/app/sep/list-cfg.history'
|
||||
import type { SepVisitData } from '~/components/app/sep/list-cfg.visit'
|
||||
|
||||
// Constants
|
||||
import { supportCodes } from '~/lib/constants'
|
||||
import { serviceTypes, serviceAssessments, registerMethods, trafficAccidents, supportCodes, procedureTypes, purposeOfVisits } from '~/lib/constants.vclaim'
|
||||
|
||||
// Services
|
||||
import { getPatientDetail, getPatients } from '~/services/patient.service'
|
||||
@@ -35,6 +35,7 @@ const selectedPatient = ref('')
|
||||
const selectedPatientObject = ref<PatientEntity | null>(null)
|
||||
const selectedLetter = ref('SK22334442')
|
||||
const selectedObjects = ref<any>({})
|
||||
const selectedServiceType = ref<string>('')
|
||||
const histories = ref<Array<SepHistoryData>>([])
|
||||
const visits = ref<Array<SepVisitData>>([])
|
||||
const patients = ref<Array<{ id: string; identity: string; number: string; bpjs: string; name: string }>>([])
|
||||
@@ -42,6 +43,12 @@ const doctors = ref<Array<{ value: string | number; label: string }>>([])
|
||||
const diagnoses = ref<Array<{ value: string | number; label: string }>>([])
|
||||
const facilities = ref<Array<{ value: string | number; label: string }>>([])
|
||||
const supportCodesList = ref<Array<{ value: string; label: string }>>([])
|
||||
const serviceTypesList = ref<Array<{ value: string; label: string }>>([])
|
||||
const registerMethodsList = ref<Array<{ value: string; label: string }>>([])
|
||||
const accidentsList = ref<Array<{ value: string; label: string }>>([])
|
||||
const purposeOfVisitsList = ref<Array<{ value: string; label: string }>>([])
|
||||
const proceduresList = ref<Array<{ value: string; label: string }>>([])
|
||||
const assessmentsList = ref<Array<{ value: string; label: string }>>([])
|
||||
const isPatientsLoading = ref(false)
|
||||
const paginationMeta = ref<PaginationMeta>({
|
||||
recordCount: 0,
|
||||
@@ -246,18 +253,18 @@ function handleEvent(menu: string, value: any) {
|
||||
async function handleFetch(params: any) {
|
||||
const menu = params.menu || ''
|
||||
const value = params.value || ''
|
||||
if (menu === 'initialDiagnosis') {
|
||||
if (menu === 'diagnosis') {
|
||||
diagnoses.value = await getDiagnoseLabelList({ diagnosa: value })
|
||||
}
|
||||
if (menu === 'attendingDoctor') {
|
||||
if (menu === 'doctor') {
|
||||
console.log('value:', value)
|
||||
}
|
||||
if (menu === 'destinationClinic') {
|
||||
if (menu === 'clinic') {
|
||||
facilities.value = await getHealthFacilityLabelList({ faskes: value, 'jenis-faskes': 1 })
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
async function handleInit() {
|
||||
diagnoses.value = await getDiagnoseLabelList({ diagnosa: 'paru' })
|
||||
facilities.value = await getHealthFacilityLabelList({ faskes: 'Puskesmas', 'jenis-faskes': 1 })
|
||||
doctors.value = await getDoctorLabelList({
|
||||
@@ -265,6 +272,40 @@ onMounted(async () => {
|
||||
'tgl-pelayanan': new Date().toISOString().substring(0, 10),
|
||||
'kode-spesialis': 0,
|
||||
})
|
||||
serviceTypesList.value = Object.keys(serviceTypes).map((item) => ({
|
||||
value: item.toString(),
|
||||
label: serviceTypes[item],
|
||||
})) as any
|
||||
registerMethodsList.value = Object.keys(registerMethods)
|
||||
.filter((item) => !['2', '4'].includes(item))
|
||||
.map((item) => ({
|
||||
value: item.toString(),
|
||||
label: registerMethods[item],
|
||||
})) as any
|
||||
accidentsList.value = Object.keys(trafficAccidents).map((item) => ({
|
||||
value: item.toString(),
|
||||
label: trafficAccidents[item],
|
||||
})) as any
|
||||
purposeOfVisitsList.value = Object.keys(purposeOfVisits).map((item) => ({
|
||||
value: item.toString(),
|
||||
label: purposeOfVisits[item],
|
||||
})) as any
|
||||
proceduresList.value = Object.keys(procedureTypes).map((item) => ({
|
||||
value: item.toString(),
|
||||
label: procedureTypes[item],
|
||||
})) as any
|
||||
assessmentsList.value = Object.keys(serviceAssessments).map((item) => ({
|
||||
value: item.toString(),
|
||||
label: `${item.toString()} - ${serviceAssessments[item]}`,
|
||||
})) as any
|
||||
supportCodesList.value = Object.keys(supportCodes).map((item) => ({
|
||||
value: item.toString(),
|
||||
label: `${item.toString()} - ${supportCodes[item]}`,
|
||||
})) as any
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await handleInit()
|
||||
getProvinceList().then((value) => {
|
||||
console.log('value:', value)
|
||||
})
|
||||
@@ -277,7 +318,6 @@ onMounted(async () => {
|
||||
getDiagnoseReferralList().then((value) => {
|
||||
console.log('value:', value)
|
||||
})
|
||||
supportCodesList.value = Object.keys(supportCodes).map((item) => ({ value: item.toString(), label: supportCodes[item] })) as any
|
||||
if (route.query) {
|
||||
selectedObjects.value = { ...route.query }
|
||||
}
|
||||
@@ -298,8 +338,14 @@ onMounted(async () => {
|
||||
:doctors="doctors"
|
||||
:diagnoses="diagnoses"
|
||||
:facilities="facilities"
|
||||
:patient="selectedPatientObject"
|
||||
:service-types="serviceTypesList"
|
||||
:register-methods="registerMethodsList"
|
||||
:accidents="accidentsList"
|
||||
:purposes="purposeOfVisitsList"
|
||||
:procedures="proceduresList"
|
||||
:assessments="assessmentsList"
|
||||
:support-codes="supportCodesList"
|
||||
:patient="selectedPatientObject"
|
||||
@fetch="handleFetch"
|
||||
@event="handleEvent"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user