348 lines
9.3 KiB
Vue
348 lines
9.3 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 [curDiseaseHistory, curDiseaseHistoryAttrs] = defineField('cur-disea-hist')
|
|
const [systolic, systolicAttrs] = defineField('syst-bp')
|
|
const [diastolic, diastolicAttrs] = defineField('diast-bp')
|
|
const [pulse, pulseAttrs] = defineField('pulse')
|
|
const [respiratoryRate, respiratoryRateAttrs] = defineField('resp-rate')
|
|
const [temperature, temperatureAttrs] = defineField('temp')
|
|
const [weight, weightAttrs] = defineField('weight')
|
|
const [height, heightAttrs] = defineField('height')
|
|
const [bloodGroup, bloodGroupAttrs] = defineField('reflect-fisio')
|
|
const [physicalExamination, physicalExaminationAttrs] = defineField('reflect-pato')
|
|
const [diagnosisMedical, diagnosisMedicalAttrs] = defineField('autonom-neuron')
|
|
const [medicalPlan, medicalPlanAttrs] = defineField('medical-act')
|
|
const [therapy, therapyAttrs] = defineField('therapy')
|
|
|
|
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 icdPreview = inject('icdPreview')
|
|
|
|
const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
|
</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>Sudah Vaksin</Label>
|
|
<Field>
|
|
<RadioGroup class="flex gap-4">
|
|
<div class="flex items-center space-x-2">
|
|
<RadioGroupItem
|
|
id="vaksin-yes"
|
|
value="yes"
|
|
/>
|
|
<Label for="vaksin-yes">Sudah</Label>
|
|
</div>
|
|
<div class="flex items-center space-x-2">
|
|
<RadioGroupItem
|
|
id="vaksin-no"
|
|
value="no"
|
|
/>
|
|
<Label for="vaksin-no">Belum</Label>
|
|
</div>
|
|
</RadioGroup>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<Cell>
|
|
<Label dynamic>Kasus</Label>
|
|
<Field>
|
|
<RadioGroup class="flex gap-4">
|
|
<div class="flex items-center space-x-2">
|
|
<RadioGroupItem
|
|
id="kasus-baru"
|
|
value="baru"
|
|
/>
|
|
<Label for="kasus-baru">Baru</Label>
|
|
</div>
|
|
<div class="flex items-center space-x-2">
|
|
<RadioGroupItem
|
|
id="kasus-lama"
|
|
value="lama"
|
|
/>
|
|
<Label for="kasus-lama">Lama</Label>
|
|
</div>
|
|
</RadioGroup>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<Cell>
|
|
<Label dynamic>Kunjungan</Label>
|
|
<Field>
|
|
<RadioGroup class="flex gap-4">
|
|
<div class="flex items-center space-x-2">
|
|
<RadioGroupItem
|
|
id="kunjungan-baru"
|
|
value="baru"
|
|
/>
|
|
<Label for="kunjungan-baru">Baru</Label>
|
|
</div>
|
|
<div class="flex items-center space-x-2">
|
|
<RadioGroupItem
|
|
id="kunjungan-lama"
|
|
value="lama"
|
|
/>
|
|
<Label for="kunjungan-lama">Lama</Label>
|
|
</div>
|
|
</RadioGroup>
|
|
</Field>
|
|
</Cell>
|
|
</Block>
|
|
|
|
<Block :colCount="2">
|
|
<Cell>
|
|
<Label dynamic>Keluhan Utama</Label>
|
|
<Field :errMessage="errors['prim-compl']">
|
|
<Textarea
|
|
placeholder="Masukkan anamnesa pasien"
|
|
v-model="primaryComplaint"
|
|
v-bind="primaryComplaintAttrs"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
<Cell>
|
|
<Label dynamic>Riwayat Penyakit</Label>
|
|
<Field>
|
|
<Textarea
|
|
placeholder=".."
|
|
v-model="curDiseaseHistory"
|
|
v-bind="curDiseaseHistoryAttrs"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
<Cell>
|
|
<Label dynamic>SpO₂</Label>
|
|
<Field>
|
|
<Input
|
|
type="number"
|
|
placeholder="%"
|
|
v-model="spo2"
|
|
v-bind="spo2Attrs"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<Cell>
|
|
<Label dynamic>Tekanan Darah Sistol</Label>
|
|
<Field>
|
|
<Input
|
|
type="number"
|
|
placeholder="mmHg"
|
|
v-model="systolic"
|
|
v-bind="systolicAttrs"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<Cell>
|
|
<Label dynamic>Tekanan Darah Diastol</Label>
|
|
<Field>
|
|
<Input
|
|
v-model="diastolic"
|
|
v-bind="diastolicAttrs"
|
|
type="number"
|
|
placeholder="mmHg"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<Cell>
|
|
<Label dynamic>Respirasi</Label>
|
|
<Field>
|
|
<Input
|
|
v-model="respiratoryRate"
|
|
v-bind="respiratoryRateAttrs"
|
|
type="number"
|
|
placeholder="kali/menit"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<Cell>
|
|
<Label dynamic>Nadi</Label>
|
|
<Field>
|
|
<Input
|
|
v-model="pulse"
|
|
v-bind="pulseAttrs"
|
|
type="number"
|
|
placeholder="kali/menit"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<Cell>
|
|
<Label dynamic>Temperatur</Label>
|
|
<Field>
|
|
<Input
|
|
v-model="temperature"
|
|
v-bind="temperatureAttrs"
|
|
type="number"
|
|
placeholder="℃"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<Cell>
|
|
<Label dynamic>Berat Badan</Label>
|
|
<Field>
|
|
<Input
|
|
v-model="weight"
|
|
v-bind="weightAttrs"
|
|
type="number"
|
|
placeholder="Kg"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<Cell>
|
|
<Label dynamic>Tinggi Badan</Label>
|
|
<Field>
|
|
<Input
|
|
v-model="height"
|
|
v-bind="heightAttrs"
|
|
type="number"
|
|
placeholder="Cm"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<Cell>
|
|
<Label dynamic>Golongan Darah</Label>
|
|
<Field>
|
|
<Select
|
|
:options="bloodGroups"
|
|
v-model="bloodGroup"
|
|
v-bind="bloodGroupAttrs"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<Cell>
|
|
<Label dynamic>Pemeriksaan Fisik (Yang Mendukung)</Label>
|
|
<Field>
|
|
<Textarea
|
|
placeholder="Masukkan pemeriksaan fisik"
|
|
v-model="physicalExamination"
|
|
v-bind="physicalExaminationAttrs"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<!-- Prosedur -->
|
|
<Cell>
|
|
<Label dynamic>Diagnosa (ICD-X)</Label>
|
|
<Field>
|
|
<Button
|
|
class="rounded bg-orange-100 px-3 py-1 text-orange-600"
|
|
type="button"
|
|
@click="emit('modal', 'diagnosa')"
|
|
>
|
|
+ Pilih Diagnosa
|
|
</Button>
|
|
</Field>
|
|
</Cell>
|
|
<!-- Diagnosa -->
|
|
<Cell>
|
|
<Label dynamic>Diagnosa (ICD-X)</Label>
|
|
<Field>
|
|
<Button
|
|
class="rounded bg-orange-100 px-3 py-1 text-orange-600"
|
|
type="button"
|
|
@click="emit('modal', 'prosedur')"
|
|
>
|
|
+ Pilih Prosedur
|
|
</Button>
|
|
</Field>
|
|
</Cell>
|
|
</Block>
|
|
|
|
<div class="mb-8 grid grid-cols-2 gap-4">
|
|
<AppIcdPreview v-model="icdPreview.diagnoses" />
|
|
<AppIcdPreview v-model="icdPreview.procedures" />
|
|
</div>
|
|
|
|
<Block :colCount="3">
|
|
<Cell>
|
|
<Label dynamic>Diagnosa Medis</Label>
|
|
<Field>
|
|
<Textarea
|
|
v-model="diagnosisMedical"
|
|
v-bind="diagnosisMedicalAttrs"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<Cell>
|
|
<Label dynamic>Rencana Awal Medis</Label>
|
|
<Field>
|
|
<Textarea
|
|
v-model="medicalPlan"
|
|
v-bind="medicalPlanAttrs"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
|
|
<Cell>
|
|
<Label dynamic>Terapi</Label>
|
|
<Field>
|
|
<Textarea
|
|
v-model="therapy"
|
|
v-bind="therapyAttrs"
|
|
/>
|
|
</Field>
|
|
</Cell>
|
|
</Block>
|
|
</div>
|
|
</form>
|
|
</template>
|