Files
simrsx-fe/app/components/app/soapi/function-entry.vue
2025-10-20 17:33:05 +07:00

659 lines
17 KiB
Vue

<script setup lang="ts">
import Block from '~/components/pub/my-ui/doc-entry/block.vue'
import Cell from '~/components/pub/my-ui/doc-entry/cell.vue'
import Field from '~/components/pub/my-ui/doc-entry/field.vue'
import Label from '~/components/pub/my-ui/doc-entry/label.vue'
// Helpers
import type z from 'zod'
import { toTypedSchema } from '@vee-validate/zod'
import { useForm } from 'vee-validate'
import { genBase } from '~/models/_base'
const props = defineProps<{
modelValue: any
schema: z.ZodSchema<any>
excludeFields?: string[]
isReadonly?: boolean
}>()
const emit = defineEmits<{
(e: 'update:modelValue', val: any): void
(e: 'submit', val: any): void
}>()
// Setup form
const {
validate: _validate,
defineField,
handleSubmit,
errors,
values,
} = useForm({
validationSchema: toTypedSchema(props.schema),
initialValues: props.modelValue,
})
watch(values, (val) => emit('update:modelValue', val), { deep: true })
const [primaryComplaint, primaryComplaintAttrs] = defineField('prim-compl')
const [pastDisease, pastDiseaseAttrs] = defineField('past-disease')
const [currentDisease, currentDiseaseAttrs] = defineField('current-disease')
const [gcs, gcsAttrs] = defineField('gcs')
const [respiratoryRate, respiratoryRateAttrs] = defineField('respiratory-rate')
const [respiratoryRateType, respiratoryRateTypeAttrs] = defineField('respiratory-rate-type')
const [pulse, pulseAttrs] = defineField('pulse')
const [pulseType, pulseTypeAttrs] = defineField('pulse-type')
const [rightArmBp, rightArmBpAttrs] = defineField('right-arm-bp')
const [leftArmBp, leftArmBpAttrs] = defineField('left-arm-bp')
const [axillaryTemp, axillaryTempAttrs] = defineField('axillary-temp')
const [rektalTemp, rektalTempAttrs] = defineField('rektal-temp')
const [skin, skinAttrs] = defineField('skin')
const [head, headAttrs] = defineField('head')
const [ear, earAttrs] = defineField('ear')
const [nose, noseAttrs] = defineField('nose')
const [oralCavity, oralCavityAttrs] = defineField('oral-cavity')
const [eye, eyeAttrs] = defineField('eye')
const [otherBodyPart, otherBodyPartAttrs] = defineField('other-body-part')
const [neck, neckAttrs] = defineField('neck')
const [thyroid, thyroidAttrs] = defineField('thyroid')
const [thorax, thoraxAttrs] = defineField('thorax')
const [heart, heartAttrs] = defineField('heart')
const [lung, lungAttrs] = defineField('lung')
const [abdomen, abdomenAttrs] = defineField('abdomen')
const [heart2, heart2Attrs] = defineField('heart2')
const [lien, lienAttrs] = defineField('lien')
const [back, backAttrs] = defineField('back')
const [extremity, extremityAttrs] = defineField('extremity')
const [gender, genderAttrs] = defineField('gender')
const [rectum, rectumAttrs] = defineField('rectum')
const [systemSyaraf, systemSyarafAttrs] = defineField('system-syaraf')
const [nervousSystem, nervousSystemAttrs] = defineField('nervous-system')
const [cardioRespiratory, cardioRespiratoryAttrs] = defineField('cardio-respiratory')
const [imaging, imagingAttrs] = defineField('imaging')
const [laboratory, laboratoryAttrs] = defineField('laboratory')
const validate = async () => {
const result = await _validate()
console.log('Component validate() result:', result)
return {
valid: true,
data: result.values,
errors: result.errors,
}
}
defineExpose({ validate })
const isExcluded = (key: string) => props.excludeFields?.includes(key)
const disorders = ref<string[]>([])
const therapies = ref<string[]>([])
const summary = ref('')
const disorderOptions = [
'Fungsi Otot',
'Fungsi Sendi',
'Fungsi Jalan',
'Fungsi Syaraf',
'Fungsi Koordinasi',
'Jantung',
'Fungsi Respirasi',
'Fungsi Menelan',
'Fungsi Bladder',
'Fungsi Bowel',
'Fungsi Luhur',
'Fungsi Kontrol Postur',
'Fungsi Eksekusi',
'Fungsi Ortosa/Protesa',
'Gangguan Aktivitas Sehari-hari',
'Lainnya',
]
const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', 'Medikamentosa', 'Lain-lain: Konsultasi']
</script>
<template>
<form id="entry-form">
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
<Block>
<Cell>
<Label dynamic>Keluhan Utama</Label>
<Field :errMessage="errors['prim-compl']">
<Textarea
v-model="primaryComplaint"
v-bind="primaryComplaintAttrs"
/>
</Field>
</Cell>
</Block>
<Block :colCount="2">
<Cell>
<Label dynamic>Riwayat Penyakit Dahulu</Label>
<Field>
<Textarea
v-model="pastDisease"
v-bind="pastDiseaseAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Riwayat Penyakit Sekarang</Label>
<Field>
<Textarea
v-model="currentDisease"
v-bind="currentDiseaseAttrs"
/>
</Field>
</Cell>
</Block>
<Separator class="mt-8" />
<div class="my-2">
<h1 class="font-semibold">Pemeriksaan Fisik</h1>
</div>
<Block>
<Cell>
<Label dynamic>Umum</Label>
<Field>
<Input placeholder="" />
</Field>
</Cell>
</Block>
<div class="my-2">
<h1 class="font-semibold">Tanda Vital</h1>
</div>
<div class="my-2 rounded-md border border-slate-300 p-4">
<Block>
<Cell>
<Label dynamic>Kesadaran (GCS)</Label>
<Field>
<Input
v-model="gcs"
v-bind="gcsAttrs"
/>
</Field>
</Cell>
</Block>
<Block :colCount="2">
<Cell>
<Label dynamic>Pernapasan</Label>
<Field>
<Input
v-model="respiratoryRate"
v-bind="respiratoryRateAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Jenis</Label>
<Field>
<Input
v-model="respiratoryRateType"
v-bind="respiratoryRateTypeAttrs"
/>
</Field>
</Cell>
</Block>
<Block :colCount="2">
<Cell>
<Label dynamic>Nadi</Label>
<Field>
<Input
v-model="pulse"
v-bind="pulseAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Jenis</Label>
<Field>
<Input
v-model="pulseType"
v-bind="pulseTypeAttrs"
/>
</Field>
</Cell>
</Block>
<Block :colCount="2">
<Cell>
<Label dynamic>Tekanan Darah Lengan Kanan</Label>
<Field>
<Input
v-model="rightArmBp"
v-bind="rightArmBpAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Tekanan Darah Lengan Kiri</Label>
<Field>
<Input
v-model="leftArmBp"
v-bind="leftArmBpAttrs"
/>
</Field>
</Cell>
</Block>
<Block :colCount="2">
<Cell>
<Label dynamic>Suhu Aksila</Label>
<Field>
<Input
v-model="axillaryTemp"
v-bind="axillaryTempAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Suhu Rektal</Label>
<Field>
<Input
v-model="rektalTemp"
v-bind="rektalTempAttrs"
/>
</Field>
</Cell>
</Block>
</div>
<div class="my-2">
<h1 class="font-semibold">Pemeriksaan Badan</h1>
</div>
<div class="my-2 rounded-md border border-slate-300 p-4">
<Block>
<Cell>
<Label dynamic>Kulit</Label>
<Field>
<Input
v-model="skin"
v-bind="skinAttrs"
/>
</Field>
</Cell>
</Block>
</div>
<div class="my-2 rounded-md border border-slate-300 p-4">
<Block :colCount="3">
<Cell>
<Label dynamic>Kepala</Label>
<Field>
<Input
v-model="head"
v-bind="headAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Telinga</Label>
<Field>
<Input
v-model="ear"
v-bind="earAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Hidung</Label>
<Field>
<Input
v-model="nose"
v-bind="noseAttrs"
/>
</Field>
</Cell>
</Block>
<Block :colCount="3">
<Cell>
<Label dynamic>Rongga Mulut/Tenggorokan</Label>
<Field>
<Input
v-model="oralCavity"
v-bind="oralCavityAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Mata</Label>
<Field>
<Input
v-model="eye"
v-bind="eyeAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Lain-Lain</Label>
<Field>
<Input
v-model="otherBodyPart"
v-bind="otherBodyPartAttrs"
/>
</Field>
</Cell>
</Block>
</div>
<div class="my-2 rounded-md border border-slate-300 p-4">
<Block :colCount="3">
<Cell>
<Label dynamic>Leher</Label>
<Field>
<Input
v-model="neck"
v-bind="neckAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Kelenjar Tiroid</Label>
<Field>
<Input
v-model="thyroid"
v-bind="thyroidAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Lain-Lain</Label>
<Field>
<Input />
</Field>
</Cell>
</Block>
</div>
<div class="my-2 rounded-md border border-slate-300 p-4">
<Block :colCount="3">
<Cell>
<Label dynamic>Thorax</Label>
<Field>
<Input
v-model="thorax"
v-bind="thoraxAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Jantung</Label>
<Field>
<Input
v-model="heart"
v-bind="heartAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Paru-Paru</Label>
<Field>
<Input
v-model="lung"
v-bind="lungAttrs"
/>
</Field>
</Cell>
</Block>
<Block>
<Cell>
<Label dynamic>Lain-Lain</Label>
<Field>
<Input />
</Field>
</Cell>
</Block>
</div>
<div class="my-2 rounded-md border border-slate-300 p-4">
<Block :colCount="3">
<Cell>
<Label dynamic>Abdomen</Label>
<Field>
<Input
v-model="abdomen"
v-bind="abdomenAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Hati</Label>
<Field>
<Input
v-model="heart2"
v-bind="heart2Attrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Lien</Label>
<Field>
<Input
v-model="lien"
v-bind="lienAttrs"
/>
</Field>
</Cell>
</Block>
<Block>
<Cell>
<Label dynamic>Lain-Lain</Label>
<Field>
<Input />
</Field>
</Cell>
</Block>
</div>
<div class="my-2 rounded-md border border-slate-300 p-4">
<Block :colCount="3">
<Cell>
<Label dynamic>Punggung</Label>
<Field>
<Input
v-model="back"
v-bind="backAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Ekstremitas</Label>
<Field>
<Input
v-model="extremity"
v-bind="extremityAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Kelamin</Label>
<Field>
<Input
v-model="gender"
v-bind="genderAttrs"
/>
</Field>
</Cell>
</Block>
<Block :colCount="2">
<Cell>
<Label dynamic>Rectum</Label>
<Field>
<Input
v-model="rectum"
v-bind="rectumAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>System Syaraf</Label>
<Field>
<Input
v-model="nervousSystem"
v-bind="nervousSystemAttrs"
/>
</Field>
</Cell>
</Block>
</div>
<Block :colCount="2">
<Cell>
<Label dynamic>Neuromoskuloskeletal</Label>
<Field>
<Textarea
v-model="neuromoskuloskeletal"
v-bind="neuromoskuloskeletalAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Kardiorespirasi</Label>
<Field>
<Textarea
v-model="cardioRespiratory"
v-bind="cardioRespiratoryAttrs"
/>
</Field>
</Cell>
</Block>
<Separator class="mt-8" />
<div class="my-2">
<h1 class="font-semibold">Pemeriksaan Penunjang</h1>
</div>
<Block :colCount="2">
<Cell>
<Label dynamic>Pencitraan</Label>
<Field>
<Textarea
v-model="imaging"
v-bind="imagingAttrs"
/>
</Field>
</Cell>
<Cell>
<Label dynamic>Laboratorium</Label>
<Field>
<Textarea
v-model="laboratory"
v-bind="laboratoryAttrs"
/>
</Field>
</Cell>
</Block>
<div class="mb-8 grid grid-cols-2 gap-4">
<div>
<span class="text-md">Diagnosa Medis (ICD-X)</span>
<Button
class="my-2 rounded bg-orange-100 px-3 py-1 text-orange-600"
type="button"
@click="emits('click', 'prosedur')"
>
+ Pilih Prosedur
</Button>
<AppIcdPreview />
</div>
<div>
<span class="text-md">Diagnosa Medis (ICD-X)</span>
<Button
class="my-2 rounded bg-orange-100 px-3 py-1 text-orange-600"
type="button"
@click="emits('click', 'prosedur')"
>
+ Pilih Prosedur
</Button>
<AppIcdPreview />
</div>
<div>
<span class="text-md">Diagnosa Medis (ICD-X)</span>
<Button
class="my-2 rounded bg-orange-100 px-3 py-1 text-orange-600"
type="button"
@click="emits('click', 'prosedur')"
>
+ Pilih Prosedur
</Button>
<AppIcdPreview />
</div>
</div>
<div class="space-y-8">
<div>
<h3 class="mb-3 text-lg font-semibold">Gangguan Fungsi</h3>
<div class="grid grid-cols-3 gap-2">
<div
v-for="opt in disorderOptions"
:key="opt"
class="flex items-center space-x-2"
>
<Checkbox
:id="opt"
:value="opt"
v-model="disorders"
/>
<Label
:for="opt"
class="text-sm"
>
{{ opt }}
</Label>
</div>
</div>
<div class="mt-4 space-y-2">
<Label
for="summary"
class="font-medium"
>
Kesimpulan Didapatkan Gangguan Fungsi
<span class="text-red-500">*</span>
</Label>
<Textarea
id="summary"
v-model="summary"
placeholder="Masukkan kesimpulan gangguan fungsi"
/>
</div>
</div>
<Separator />
<!-- REKOMENDASI TERAPI -->
<div>
<h3 class="mb-3 text-lg font-semibold">Rekomendasi Terapi Tindakan Yang Diperlukan</h3>
<div class="grid grid-cols-3 gap-2">
<div
v-for="opt in therapyOptions"
:key="opt"
class="flex items-center space-x-2"
>
<Checkbox
:id="opt"
:value="opt"
v-model="therapies"
/>
<Label
:for="opt"
class="text-sm"
>
{{ opt }}
</Label>
</div>
</div>
</div>
</div>
</div>
</form>
</template>