diff --git a/Dockerfile b/Dockerfile index d02bc726..55d61877 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build Stage -FROM node:20-alpine AS build-stage +FROM node:24-alpine AS build-stage # Set the working directory inside the container WORKDIR /app diff --git a/app/components/app/encounter/entry-form.vue b/app/components/app/encounter/entry-form.vue index 56e0383b..8fd21ea6 100644 --- a/app/components/app/encounter/entry-form.vue +++ b/app/components/app/encounter/entry-form.vue @@ -9,7 +9,9 @@ import DatepickerSingle from '~/components/pub/my-ui/datepicker/datepicker-singl import FileUpload from '~/components/pub/my-ui/form/file-field.vue' // Types -import { IntegrationEncounterSchema, type IntegrationEncounterFormData } from '~/schemas/integration-encounter.schema' +import { IntegrationEncounterSchema, type IntegrationEncounterFormData} from '~/schemas/integration-encounter.schema' +// import { IntegrationEncounterSchema, IntegrationEncounterSchemaWP} from '~/schemas/integration-encounter.schema' +// import type { IntegrationEncounterFormData, IntegrationEncounterWPFormData } from '~/schemas/integration-encounter.schema' import type { PatientEntity } from '~/models/patient' // Helpers @@ -20,9 +22,21 @@ import type { Doctor } from '~/models/doctor' // References import { paymentMethodCodes } from '~/const/key-val/common' +import { getValueLabelList as getEthnicOpts } from '~/services/ethnic.service' +import { getValueLabelList as getLanguageOpts } from '~/services/language.service' // App things import { genEncounter, type Encounter } from '~/models/encounter' +import PatientForm from '~/components/app/patient/entry-form.vue' +import PersonAddressEntryForm from '~/components/app/person-address/entry-form.vue' +import PersonAddressEntryFormRelative from '~/components/app/person-address/entry-form-relative.vue' +import PersonFamilyParentsForm from '~/components/app/person/family-parents-form.vue' +import type { PersonAddress } from '~/models/person-address' +import type { PersonRelative } from '~/models/person-relative' +import type { PersonContact } from '~/models/person-contact' +import { withBase } from '~/models/_base' +import type { Person } from '~/models/person' +import type { ExposedForm } from '~/types/form' // Props const props = defineProps<{ @@ -46,9 +60,12 @@ const props = defineProps<{ // Model const model = defineModel() model.value = genEncounter() +// const patientSource = ref<'new' | 'exists'>('exists') // Common preparation const defaultCBItems = [{ label: 'Pilih', value: '' }] +const formKey = ref(0) +// const withPatientStatus = ref(false) // Emit preparation const emit = defineEmits<{ @@ -61,10 +78,13 @@ const emit = defineEmits<{ const { handleSubmit, errors, defineField, meta } = useForm({ validationSchema: toTypedSchema(IntegrationEncounterSchema), }) +// const { handleSubmit: handleSubmitWP, errors: errorsWP, defineField: defineFieldWP, meta: metaWP } = useForm({ +// validationSchema: toTypedSchema(IntegrationEncounterSchemaWP), +// }) // Bind fields and extract attrs +const [patientSource] = defineField('patientSource') const [doctorCode, doctorCodeAttrs] = defineField('doctor_code') -const [unitCode, unitCodeAttrs] = defineField('unit_code') const [registerDate, registerDateAttrs] = defineField('registerDate') const [paymentMethodCode, paymentMethodCodeAttrs] = defineField('paymentMethod_code') const [patientCategory, patientCategoryAttrs] = defineField('patientCategory') @@ -72,10 +92,11 @@ const [cardNumber, cardNumberAttrs] = defineField('cardNumber') const [sepType, sepTypeAttrs] = defineField('sepType') const [sepNumber, sepNumberAttrs] = defineField('sepNumber') const [patientName, patientNameAttrs] = defineField('patientName') -const [nationalIdentity, nationalIdentityAttrs] = defineField('nationalIdentity') +const [residentIdentiyNumber, residentIdentiyNumberAttrs] = defineField('residentIdentiyNumber') const [medicalRecordNumber, medicalRecordNumberAttrs] = defineField('medicalRecordNumber') const [sepFile, sepFileAttrs] = defineField('sepFile') const [sippFile, sippFileAttrs] = defineField('sippFile') + const patientId = ref('') const sepReference = ref('') const sepControlDate = ref('') @@ -94,10 +115,14 @@ const debouncedSepNumber = refDebounced(sepNumber, 500) const debouncedCardNumber = refDebounced(cardNumber, 500) const sepFileReview = ref(null) const sippFileReview = ref(null) -const unitFullName = ref('') // Unit, specialist, subspecialist +const specialistFullName = ref('') // Unit, specialist, subspecialist const formRef = ref(null) // Expose submit method for parent component const paymentMethodItems = CB.recStrToItem(paymentMethodCodes) +if (!patientSource.value) { + patientSource.value = 'exists' +} + if (mode === 'add') { // Set default sepDate to current date in YYYY-MM-DD format const today = new Date() @@ -107,11 +132,32 @@ if (mode === 'add') { registerDate.value = `${year}-${month}-${day}` } + +// NEW PATIENT THINGS +const ethnicOptions = ref<{ value: string; label: string }[]>([]) +const languageOptions = ref<{ value: string; label: string }[]>([]) + +const personPatientForm = ref | null>(null) +const personAddressForm = ref | null>(null) +const personAddressRelativeForm = ref | null>(null) +const personContactForm = ref | null>(null) +const personEmergencyContactRelative = ref | null>(null) +const personFamilyForm = ref | null>(null) + +// const patientDetail = ref( +// withBase({ +// person: {} as Person, +// personAddresses: [], +// personContacts: [], +// personRelatives: [], +// }), +// ) + watch( () => props.selectedDoctor, (doctor) => { - unitFullName.value = doctor.subspecialist?.name ?? doctor.specialist?.name ?? doctor.unit?.name ?? 'tidak diketahui' - model.value!.unit_code = doctor.unit_code || '' + specialistFullName.value = doctor.subspecialist?.name ?? doctor.specialist?.name ?? doctor.unit?.name ?? 'tidak diketahui' + // model.value!.unit_code = doctor.unit_code || '' model.value!.specialist_code = doctor.specialist_code || '' model.value!.subspecialist_code = doctor.subspecialist_code || '' }, @@ -123,7 +169,7 @@ watch( (objects) => { if (objects && Object.keys(objects).length > 0) { patientName.value = objects?.patientName || '' - nationalIdentity.value = objects?.nationalIdentity || '' + residentIdentiyNumber.value = objects?.residentIdentiyNumber || '' medicalRecordNumber.value = objects?.medicalRecordNumber || '' doctorCode.value = objects?.doctorCode || '' patientCategory.value = objects?.patientCategory || '' @@ -151,7 +197,7 @@ watch( if (patient && Object.keys(patient).length > 0) { patientId.value = patient?.id ? String(patient.id) : '' patientName.value = patient?.person?.name || '' - nationalIdentity.value = patient?.person?.residentIdentityNumber || '' + residentIdentiyNumber.value = patient?.person?.residentIdentityNumber || '' medicalRecordNumber.value = patient?.number || '' } }, @@ -180,6 +226,14 @@ watch(debouncedCardNumber, (newValue) => { emit('event', 'member-changed', newValue) }) +onMounted(async () => { + const optsReq = { + 'page-no-limit': true, + } + ethnicOptions.value = await getEthnicOpts(optsReq, true) + languageOptions.value = await getLanguageOpts(optsReq, true) +}) + function onAddSep() { const formValues = { patientId: patientId.value || '', @@ -200,7 +254,7 @@ function onSearchSep() { } // Submit handler -const onSubmit = handleSubmit((values) => { +const onSubmit = handleSubmit(async(values) => { let payload: any = values if (props.mode === 'edit') { payload = { @@ -209,7 +263,32 @@ const onSubmit = handleSubmit((values) => { sippFileReview: sippFileReview.value, } } - emit('event', 'save', payload) + if (patientSource.value === 'exists') { + emit('event', 'save', payload) + } else { + const [patient, address, addressRelative, families, contacts, emergencyContact] = await Promise.all([ + personPatientForm.value?.validate(), + personAddressForm.value?.validate(), + personAddressRelativeForm.value?.validate(), + personFamilyForm.value?.validate(), + personContactForm.value?.validate(), + personEmergencyContactRelative.value?.validate(), + ]) + + const results = [patient, address, addressRelative, families, contacts, emergencyContact] + const allValid = results.every((r) => r?.valid) + if (!allValid) return Promise.reject('Form validation failed') + + emit('event', 'save', { + encounter: payload, + patient: { + person: patient?.values, + personAddresses: [address?.values, addressRelative?.values], + personContacts: contacts?.values.contacts, + personRelatives: families?.values.families, + }, + }) + } }) function openFile(path: string) { @@ -234,99 +313,229 @@ function submitForm() { } } +function requestPatient() { + patientSource.value = 'exists' + emit('event', 'search') +} + +function newPatient() { + patientSource.value = 'new' + emit('event', 'add') +} + defineExpose({ submitForm, }) diff --git a/app/components/app/person/entry-form.vue b/app/components/app/person/entry-form-new.vue similarity index 100% rename from app/components/app/person/entry-form.vue rename to app/components/app/person/entry-form-new.vue diff --git a/app/components/app/person/entry-form-old.vue b/app/components/app/person/entry-form-old.vue new file mode 100644 index 00000000..0ea3757a --- /dev/null +++ b/app/components/app/person/entry-form-old.vue @@ -0,0 +1,476 @@ + + + diff --git a/app/components/content/encounter/entry.vue b/app/components/content/encounter/entry.vue index a4ffc0d8..d509338f 100644 --- a/app/components/content/encounter/entry.vue +++ b/app/components/content/encounter/entry.vue @@ -15,13 +15,14 @@ import { useIntegrationSepEntry } from '~/handlers/integration-sep-entry.handler // Props const props = defineProps<{ id: number - classCode?: 'ambulatory' | 'emergency' | 'inpatient' | 'outpatient' - subclassCode?: 'reg' | 'rehab' | 'chemo' | 'emg' | 'eon' | 'op' | 'icu' | 'hcu' | 'vk' + classCode?: 'ambulatory' | 'emergency' | 'inpatient' + subclassCode?: 'regular' | 'rehab' | 'chemo' | 'emg' | 'eon' | 'op' | 'icu' | 'hcu' | 'vk' formType: string }>() const route = useRoute() const formRef = ref | null>(null) +// const patientMode = ref<'new' | 'exists'>('exists') const { paymentsList, @@ -56,7 +57,6 @@ const { getDoctorInfo, getValidateMember, getValidateSepNumber, - handleFetchDoctors, } = useEncounterEntry(props) const { recSepId, openHistory, histories, getMonitoringHistoryMappers } = useIntegrationSepEntry() @@ -82,11 +82,13 @@ function handleFetch(value?: any) { async function handleEvent(menu: string, value?: any) { if (menu === 'search') { + // patientMode.value = 'exists' getPatientsList({ 'page-size': 10, includes: 'person' }).then(() => { openPatient.value = true }) } else if (menu === 'add') { - navigateTo('/client/patient/add') + // navigateTo('/client/patient/add') + // patientMode.value = 'new' } else if (menu === 'add-sep') { if (isSepValid.value) { return @@ -167,6 +169,7 @@ onMounted(async () => { Kunjungan + { /> Batal +