fix: resolve conflict on nuxt setting
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
NUXT_MAIN_API_ORIGIN=
|
||||
NUXT_BPJS_API_ORIGIN=
|
||||
NUXT_SYNC_API_ORIGIN=
|
||||
NUXT_API_ORIGIN=
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
--primary-hover: 26, 92%, 65%;
|
||||
|
||||
/* Secondary - Clean Blue */
|
||||
--secondary: 210 50% 96%;
|
||||
--secondary-foreground: 210 20% 20%;
|
||||
--secondary: 40 70% 60%;
|
||||
--secondary-foreground: 210 20% 100%;
|
||||
--muted: 210 25% 95%;
|
||||
--muted-foreground: 210 15% 50%;
|
||||
|
||||
|
||||
@@ -27,19 +27,31 @@ const data = computed({
|
||||
<FieldGroup :column="2">
|
||||
<Label>Status</Label>
|
||||
<Field>
|
||||
<Select v-model="data.type" :items="items" placeholder="Pilih jenis" />
|
||||
<Select
|
||||
v-model="data.type"
|
||||
:items="items"
|
||||
placeholder="Pilih jenis"
|
||||
/>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Position</Label>
|
||||
<Field>
|
||||
<Select v-model="data.type" :items="items" placeholder="Pilih jenis" />
|
||||
<Select
|
||||
v-model="data.type"
|
||||
:items="items"
|
||||
placeholder="Pilih jenis"
|
||||
/>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Divisi</Label>
|
||||
<Field>
|
||||
<Select v-model="data.type" :items="items" placeholder="Pilih jenis" />
|
||||
<Select
|
||||
v-model="data.type"
|
||||
:items="items"
|
||||
placeholder="Pilih jenis"
|
||||
/>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
<script lang="ts" setup>
|
||||
//
|
||||
import { LucideCheck } from 'lucide-vue-next';
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
|
||||
// Components
|
||||
import type z from 'zod'
|
||||
import ComboBox from '~/components/pub/my-ui/combobox/combobox.vue'
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
import type { CheckInFormData } from '~/schemas/encounter.schema'
|
||||
import type { Encounter } from '~/models/encounter'
|
||||
|
||||
interface Props {
|
||||
schema: z.ZodSchema<any>
|
||||
values: any
|
||||
doctors: { value: string; label: string }[]
|
||||
employees: { value: string; label: string }[]
|
||||
encounter: Encounter
|
||||
isLoading?: boolean
|
||||
isReadonly?: boolean
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
submit: [values: CheckInFormData]
|
||||
cancel: [resetForm: () => void]
|
||||
}>()
|
||||
|
||||
const { defineField, errors, meta } = useForm({
|
||||
validationSchema: toTypedSchema(props.schema),
|
||||
initialValues: {
|
||||
responsible_doctor_id: 0,
|
||||
adm_employee_id: 0,
|
||||
registeredAt: props.values.values?.registeredAt || '',
|
||||
} as Partial<CheckInFormData>,
|
||||
})
|
||||
|
||||
const [responsible_doctor_id, responsible_doctor_idAttrs] = defineField('responsible_doctor_id')
|
||||
const [adm_employee_id, adm_employee_idAttrs] = defineField('discharge_method_code')
|
||||
const [registeredAt, registeredAtAttrs] = defineField('registeredAt')
|
||||
|
||||
function submitForm() {
|
||||
const formData: CheckInFormData = {
|
||||
responsible_doctor_id: responsible_doctor_id.value,
|
||||
adm_employee_id: adm_employee_id.value,
|
||||
// registeredAt: registeredAt.value || '',
|
||||
}
|
||||
emit('submit', formData)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DE.Block :cell-flex="false">
|
||||
<DE.Cell>
|
||||
<DE.Label>Dokter</DE.Label>
|
||||
<DE.Field>
|
||||
<ComboBox
|
||||
id="doctor"
|
||||
v-model="responsible_doctor_id"
|
||||
v-bind="responsible_doctor_idAttrs"
|
||||
:items="doctors"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Dokter DPJP"
|
||||
search-placeholder="Pilih DPJP"
|
||||
empty-message="DPJP tidak ditemukan"
|
||||
/>
|
||||
</DE.Field>
|
||||
</DE.Cell>
|
||||
<DE.Cell>
|
||||
<DE.Label>PJ Berkas</DE.Label>
|
||||
<DE.Field>
|
||||
<ComboBox
|
||||
id="doctor"
|
||||
v-model="adm_employee_id"
|
||||
v-bind="adm_employee_idAttrs"
|
||||
:items="employees"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Dokter DPJP"
|
||||
search-placeholder="Pilih petugas"
|
||||
empty-message="Petugas tidak ditemukan"
|
||||
/>
|
||||
</DE.Field>
|
||||
</DE.Cell>
|
||||
<DE.Cell>
|
||||
<DE.Label>Waktu Masuk</DE.Label>
|
||||
<DE.Field>
|
||||
<Input
|
||||
id="name"
|
||||
v-model="registeredAt"
|
||||
v-bind="registeredAtAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
/>
|
||||
</DE.Field>
|
||||
</DE.Cell>
|
||||
</DE.Block>
|
||||
<div class="text-center">
|
||||
<Button @click="submitForm">
|
||||
<LucideCheck />
|
||||
Simpan
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,56 @@
|
||||
<script lang="ts" setup>
|
||||
// Components
|
||||
import { LucidePen } from 'lucide-vue-next';
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
import Input from '~/components/pub/ui/input/Input.vue';
|
||||
import type { Encounter } from '~/models/encounter'
|
||||
|
||||
interface Props {
|
||||
encounter: Encounter
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
const doctor = ref('-belum dipilih-')
|
||||
const adm = ref('-belum dipilih-')
|
||||
|
||||
const emit = defineEmits<{
|
||||
edit: []
|
||||
}>()
|
||||
|
||||
watch(props.encounter, () => {
|
||||
doctor.value = props.encounter.responsible_doctor?.employee?.person?.name ?? props.encounter.appointment_doctor?.employee?.person?.name ?? '-belum dipilih-'
|
||||
adm.value = props.encounter.adm_employee?.person?.name ?? '-belum dipilih-'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DE.Block :cell-flex="false">
|
||||
<DE.Cell>
|
||||
<DE.Label class="font-semibold">Dokter</DE.Label>
|
||||
<DE.Field>
|
||||
<div class="py-2 border-b border-b-slate-300">{{ doctor }}</div>
|
||||
</DE.Field>
|
||||
</DE.Cell>
|
||||
<DE.Cell>
|
||||
<DE.Label class="font-semibold">PJ Berkas</DE.Label>
|
||||
<DE.Field>
|
||||
<div class="py-2 border-b border-b-slate-300">{{ adm }}</div>
|
||||
</DE.Field>
|
||||
</DE.Cell>
|
||||
<DE.Cell>
|
||||
<DE.Label class="font-semibold">Waktu Masuk</DE.Label>
|
||||
<DE.Field>
|
||||
<div class="py-2 border-b border-b-slate-300">{{ encounter?.registeredAt || '-' }}</div>
|
||||
</DE.Field>
|
||||
</DE.Cell>
|
||||
</DE.Block>
|
||||
<div class="text-center">
|
||||
<Button @click="() => emit('edit')">
|
||||
<LucidePen />
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,187 @@
|
||||
<script lang="ts" setup>
|
||||
//
|
||||
import { LucideCheck } from 'lucide-vue-next';
|
||||
import { useForm, useFieldArray } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
|
||||
//
|
||||
import type z from 'zod'
|
||||
import * as CB from '~/components/pub/my-ui/combobox'
|
||||
import { dischargeMethodCodes } from '~/lib/constants';
|
||||
import type {
|
||||
CheckOutFormData,
|
||||
CheckOutDeathFormData,
|
||||
CheckOutInternalReferenceFormData
|
||||
} from '~/schemas/encounter.schema'
|
||||
|
||||
import * as Table from '~/components/pub/ui/table'
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
import type { InternalReference, CreateDto as InternalReferenceCreateDto } from '~/models/internal-reference';
|
||||
|
||||
interface Props {
|
||||
schema: z.ZodSchema<any>
|
||||
values: any
|
||||
units: any[]
|
||||
doctors: any[]
|
||||
isLoading?: boolean
|
||||
isReadonly?: boolean
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const dischargeMethodItems = CB.recStrToItem(dischargeMethodCodes)
|
||||
|
||||
const emit = defineEmits<{
|
||||
submit: [values: CheckOutFormData]
|
||||
cancel: [resetForm: () => void]
|
||||
}>()
|
||||
|
||||
const { defineField, errors, meta } = useForm({
|
||||
validationSchema: toTypedSchema(props.schema),
|
||||
initialValues: {
|
||||
discharge_method_code: '',
|
||||
discharge_date: '',
|
||||
internalReferences: [{ unit_id: 0, doctor_id: 0 }],
|
||||
deathCauses: [""],
|
||||
} as Partial<CheckOutFormData>,
|
||||
})
|
||||
const [ discharge_method_code, discharge_method_codeAttrs ] = defineField('discharge_method_code')
|
||||
const [ discharge_date, discharge_dateAttrs ] = defineField('discharge_date')
|
||||
const { fields, push, remove } = useFieldArray<InternalReferenceCreateDto>('internalReferences');
|
||||
|
||||
function submitForm(values: any) {
|
||||
if (['consul-poly', 'consul-executive'].includes(discharge_method_code.value)) {
|
||||
const formData: CheckOutInternalReferenceFormData = {
|
||||
discharge_method_code: discharge_method_code.value,
|
||||
discharge_date: discharge_date.value,
|
||||
internalReferences: [{ unit_id: 0, doctor_id: 0 }],
|
||||
}
|
||||
emit('submit', formData)
|
||||
} else if (discharge_method_code.value === 'death') {
|
||||
const formData: CheckOutDeathFormData = {
|
||||
discharge_method_code: discharge_method_code.value,
|
||||
discharge_date: discharge_date.value,
|
||||
death_cause: [""],
|
||||
}
|
||||
emit('submit', formData)
|
||||
} else {
|
||||
const formData: CheckOutFormData = {
|
||||
discharge_method_code: discharge_method_code.value,
|
||||
discharge_date: discharge_date.value,
|
||||
}
|
||||
emit('submit', formData)
|
||||
}
|
||||
}
|
||||
|
||||
const resetForm = () => {
|
||||
discharge_method_code.value = ''
|
||||
discharge_date.value = ''
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DE.Block :cellFlex="false">
|
||||
<DE.Cell>
|
||||
<DE.Label>Alasan Keluar</DE.Label>
|
||||
<DE.Field>
|
||||
<CB.Combobox
|
||||
id="dischargeMethodItems"
|
||||
v-model="discharge_method_code"
|
||||
v-bind="discharge_method_codeAttrs"
|
||||
:items="dischargeMethodItems"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Cara Keluar"
|
||||
search-placeholder="Cari Cara Keluar"
|
||||
empty-message="Cara Keluar tidak ditemukan"
|
||||
/>
|
||||
</DE.Field>
|
||||
</DE.Cell>
|
||||
|
||||
<DE.Cell>
|
||||
<DE.Label>Waktu Keluar</DE.Label>
|
||||
<DE.Cell>
|
||||
<Input
|
||||
id="discharge_date"
|
||||
v-model="discharge_date"
|
||||
v-bind="discharge_dateAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
/>
|
||||
</DE.Cell>
|
||||
</DE.Cell>
|
||||
|
||||
<DE.Cell v-if="'death' == discharge_method_code">
|
||||
<DE.Label>Sebab Meninggal</DE.Label>
|
||||
<DE.Cell>
|
||||
<div class="mb-3">
|
||||
<Input />
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
v-if="!isReadonly"
|
||||
type="button"
|
||||
:disabled="isLoading || !meta.valid"
|
||||
@click="submitForm"
|
||||
>
|
||||
Tambah Sebab meninggal
|
||||
</Button>
|
||||
</div>
|
||||
</DE.Cell>
|
||||
</DE.Cell>
|
||||
|
||||
<DE.Cell v-if="['consul-poly', 'consul-executive'].includes(discharge_method_code)">
|
||||
<DE.Label>Tujuan</DE.Label>
|
||||
<DE.Field>
|
||||
<Table.Table class="border mb-3">
|
||||
<Table.TableHeader class="bg-neutral-100 dark:bg-slate-800">
|
||||
<Table.TableCell class="text-center">Poly</Table.TableCell>
|
||||
<Table.TableCell class="text-center">DPJP</Table.TableCell>
|
||||
<Table.TableCell class="text-center !w-10"></Table.TableCell>
|
||||
</Table.TableHeader>
|
||||
<Table.TableBody>
|
||||
<Table.TableRow v-for="(item, index) in fields" :key="index">
|
||||
<Table.TableCell class="!p-0.5">
|
||||
<CB.Combobox
|
||||
id="dischargeMethodItems"
|
||||
:v-model.number="item.value.unit_id"
|
||||
:items="units"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Poly"
|
||||
search-placeholder="Cari Poly"
|
||||
empty-message="Poly tidak ditemukan"
|
||||
/>
|
||||
</Table.TableCell>
|
||||
<Table.TableCell class="!p-0.5">
|
||||
<CB.Combobox
|
||||
id="dischargeMethodItems"
|
||||
:v-model.number="item.value.doctor_id"
|
||||
:items="units"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Dokter"
|
||||
search-placeholder="Pilih Dokter"
|
||||
empty-message="Dokter tidak ditemukan"
|
||||
/>
|
||||
</Table.TableCell>
|
||||
<Table.TableCell>
|
||||
<Button variant="destructive" size="xs" @click="remove(index)" class="w-6 h-6 rounded-full">
|
||||
X
|
||||
</Button>
|
||||
</Table.TableCell>
|
||||
</Table.TableRow>
|
||||
</Table.TableBody>
|
||||
</Table.Table>
|
||||
<div>
|
||||
<Button @click="push({ encounter_id: 0, unit_id: 0, doctor_id: 0 })">Tambah</Button>
|
||||
</div>
|
||||
</DE.Field>
|
||||
</DE.Cell>
|
||||
</DE.Block>
|
||||
<div class="text-center">
|
||||
<Button @click="submitForm">>
|
||||
<LucideCheck />
|
||||
Simpan
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,90 @@
|
||||
<script lang="ts" setup>
|
||||
//
|
||||
import { LucidePen, LucideCheck } from 'lucide-vue-next';
|
||||
|
||||
//
|
||||
import * as CB from '~/components/pub/my-ui/combobox'
|
||||
import { dischargeMethodCodes } from '~/lib/constants';
|
||||
|
||||
import * as Table from '~/components/pub/ui/table'
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
import type { Encounter } from '~/models/encounter';
|
||||
|
||||
interface Props {
|
||||
encounter: Encounter
|
||||
isLoading?: boolean
|
||||
isReadonly?: boolean
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const dischargeMethodItems = CB.recStrToItem(dischargeMethodCodes)
|
||||
|
||||
const emit = defineEmits<{
|
||||
edit: [],
|
||||
finish: []
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DE.Block :cellFlex="false">
|
||||
<DE.Cell>
|
||||
<DE.Label class="font-semibold">Alasan Keluar</DE.Label>
|
||||
<DE.Field>
|
||||
<div class="py-2 border-b border-b-slate-300">{{ encounter.discharge_method_code || '-belum ditentukan-' }}</div>
|
||||
</DE.Field>
|
||||
</DE.Cell>
|
||||
|
||||
<DE.Cell>
|
||||
<DE.Label class="font-semibold">Waktu Keluar</DE.Label>
|
||||
<DE.Cell>
|
||||
<div class="py-2 border-b border-b-slate-300">{{ encounter.discharge_date || '-belum ditentukan-' }}</div>
|
||||
</DE.Cell>
|
||||
</DE.Cell>
|
||||
|
||||
<DE.Cell v-if="'death' == encounter.discharge_method_code">
|
||||
<DE.Label class="font-semibold">Sebab Meninggal</DE.Label>
|
||||
<DE.Cell>
|
||||
<div class="mb-3">
|
||||
<div class="py-2 border-b border-b-slate-300">{{ encounter.discharge_date }}</div>
|
||||
</div>
|
||||
</DE.Cell>
|
||||
</DE.Cell>
|
||||
|
||||
<DE.Cell v-if="['consul-poly', 'consul-executive'].includes(encounter.discharge_method_code || '')">
|
||||
<DE.Label class="font-semibold">Tujuan</DE.Label>
|
||||
<DE.Field>
|
||||
<Table.Table class="border mb-3">
|
||||
<Table.TableHeader class="bg-neutral-100 dark:bg-slate-800">
|
||||
<Table.TableCell class="text-center">Poly</Table.TableCell>
|
||||
<Table.TableCell class="text-center">DPJP</Table.TableCell>
|
||||
<Table.TableCell class="text-center !w-10"></Table.TableCell>
|
||||
</Table.TableHeader>
|
||||
<Table.TableBody>
|
||||
<Table.TableRow v-for="(item, index) in encounter.internalReferences" :key="index">
|
||||
<Table.TableCell class="!p-0.5">
|
||||
</Table.TableCell>
|
||||
<Table.TableCell class="!p-0.5">
|
||||
</Table.TableCell>
|
||||
<Table.TableCell>
|
||||
</Table.TableCell>
|
||||
</Table.TableRow>
|
||||
</Table.TableBody>
|
||||
</Table.Table>
|
||||
</DE.Field>
|
||||
</DE.Cell>
|
||||
</DE.Block>
|
||||
<div class="text-center [&>*]:mx-1">
|
||||
<Button @click="() => emit('edit')">
|
||||
<LucidePen />
|
||||
Edit
|
||||
</Button>
|
||||
<Button @click="() => emit('finish')">
|
||||
<LucideCheck />
|
||||
Selesai
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry';
|
||||
import type { Encounter } from '~/models/encounter';
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
import type { Encounter } from '~/models/encounter'
|
||||
|
||||
const props = defineProps<{
|
||||
data: Encounter
|
||||
@@ -8,27 +8,31 @@ const props = defineProps<{
|
||||
|
||||
let address = ''
|
||||
if (props.data.patient.person.addresses) {
|
||||
address = props.data.patient.person.addresses.map(a => a.address).join(', ')
|
||||
address = props.data.patient.person.addresses.map((a) => a.address).join(', ')
|
||||
}
|
||||
|
||||
let dpjp = '';
|
||||
let dpjp = ''
|
||||
if (props.data.responsible_doctor) {
|
||||
const dp = props.data.responsible_doctor.employee.person
|
||||
dpjp = `${dp.frontTitle} ${dp.name} ${dp.endTitle}`
|
||||
} else if (props.data.appointment_doctor) {
|
||||
dpjp = props.data.appointment_doctor.employee.person.name
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full rounded-md border bg-white dark:bg-neutral-950 p-4 shadow-sm">
|
||||
<div class="w-full rounded-md border bg-white p-4 shadow-sm dark:bg-neutral-950">
|
||||
<!-- Data Pasien -->
|
||||
<h2 class="mb-2 md:text-base 2xl:text-lg font-semibold">{{ data.patient.person.name }} - {{ data.patient.number }}</h2>
|
||||
<h2 class="mb-2 font-semibold md:text-base 2xl:text-lg">
|
||||
{{ data.patient.person.name }} - {{ data.patient.number }}
|
||||
</h2>
|
||||
|
||||
<div class="grid grid-cols-3" >
|
||||
<div class="grid grid-cols-3">
|
||||
<div>
|
||||
<DE.Block mode="preview" labelSize="large">
|
||||
<DE.Block
|
||||
mode="preview"
|
||||
labelSize="large"
|
||||
>
|
||||
<DE.Cell>
|
||||
<DE.Label class="font-semibold">No. RM</DE.Label>
|
||||
<DE.Field>
|
||||
@@ -50,7 +54,10 @@ if (props.data.responsible_doctor) {
|
||||
</DE.Block>
|
||||
</div>
|
||||
<div>
|
||||
<DE.Block mode="preview" labelSize="large">
|
||||
<DE.Block
|
||||
mode="preview"
|
||||
labelSize="large"
|
||||
>
|
||||
<DE.Cell>
|
||||
<DE.Label class="font-semibold">Tgl. Kunjungan</DE.Label>
|
||||
<DE.Field>
|
||||
@@ -72,9 +79,17 @@ if (props.data.responsible_doctor) {
|
||||
</DE.Block>
|
||||
</div>
|
||||
<div>
|
||||
<DE.Block mode="preview" labelSize="large">
|
||||
<DE.Block
|
||||
mode="preview"
|
||||
labelSize="large"
|
||||
>
|
||||
<DE.Cell>
|
||||
<DE.Label position="dynamic" class="!text-base 2xl:!text-lg font-semibold">Billing</DE.Label>
|
||||
<DE.Label
|
||||
position="dynamic"
|
||||
class="!text-base font-semibold 2xl:!text-lg"
|
||||
>
|
||||
Billing
|
||||
</DE.Label>
|
||||
<DE.Field class="text-base 2xl:text-lg">
|
||||
Rp. 000.000
|
||||
<!-- {{ data }} -->
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="p-10 text-center">Hello World!!!</div>
|
||||
</template>
|
||||
@@ -4,29 +4,72 @@ 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 emits = defineEmits(['click'])
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', val: any): void
|
||||
(e: 'submit', val: any): void
|
||||
}>()
|
||||
|
||||
const subject = ref({
|
||||
'prim-compl': '',
|
||||
'sec-compl': '',
|
||||
'cur-disea-hist': '',
|
||||
'pas-disea-hist': '',
|
||||
'fam-disea-hist': '',
|
||||
'alg-hist': '',
|
||||
'alg-react': '',
|
||||
'med-hist': '',
|
||||
'blood-type': '',
|
||||
// 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 isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
{{ errors }}
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<Block>
|
||||
<Cell>
|
||||
@@ -34,11 +77,17 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Field>
|
||||
<RadioGroup class="flex gap-4">
|
||||
<div class="flex items-center space-x-2">
|
||||
<RadioGroupItem id="vaksin-yes" value="yes" />
|
||||
<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" />
|
||||
<RadioGroupItem
|
||||
id="vaksin-no"
|
||||
value="no"
|
||||
/>
|
||||
<Label for="vaksin-no">Belum</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
@@ -50,11 +99,17 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Field>
|
||||
<RadioGroup class="flex gap-4">
|
||||
<div class="flex items-center space-x-2">
|
||||
<RadioGroupItem id="kasus-baru" value="baru" />
|
||||
<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" />
|
||||
<RadioGroupItem
|
||||
id="kasus-lama"
|
||||
value="lama"
|
||||
/>
|
||||
<Label for="kasus-lama">Lama</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
@@ -66,11 +121,17 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Field>
|
||||
<RadioGroup class="flex gap-4">
|
||||
<div class="flex items-center space-x-2">
|
||||
<RadioGroupItem id="kunjungan-baru" value="baru" />
|
||||
<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" />
|
||||
<RadioGroupItem
|
||||
id="kunjungan-lama"
|
||||
value="lama"
|
||||
/>
|
||||
<Label for="kunjungan-lama">Lama</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
@@ -79,88 +140,141 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
</Block>
|
||||
|
||||
<Block :colCount="2">
|
||||
<!-- Riwayat Penyakit -->
|
||||
<Cell>
|
||||
<Label dynamic>Keluhan Utama</Label>
|
||||
<Field>
|
||||
<Textarea placeholder="Masukkan anamnesa pasien" />
|
||||
<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="Masukkan anamnesa pasien (Riwayat Penyakit Sekarang, Dahulu, Pengobatan, Keluarga, dll)"
|
||||
placeholder=".."
|
||||
v-model="curDiseaseHistory"
|
||||
v-bind="curDiseaseHistoryAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>SpO₂</Label>
|
||||
<Field>
|
||||
<Input type="number" placeholder="%" />
|
||||
<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" />
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="mmHg"
|
||||
v-model="systolic"
|
||||
v-bind="systolicAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Tekanan Darah Diastol</Label>
|
||||
<Field>
|
||||
<Input type="number" placeholder="mmHg" />
|
||||
<Input
|
||||
v-model="diastolic"
|
||||
v-bind="diastolicAttrs"
|
||||
type="number"
|
||||
placeholder="mmHg"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Respirasi</Label>
|
||||
<Field>
|
||||
<Input type="number" placeholder="kali/menit" />
|
||||
<Input
|
||||
v-model="respiratoryRate"
|
||||
v-bind="respiratoryRateAttrs"
|
||||
type="number"
|
||||
placeholder="kali/menit"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Nadi</Label>
|
||||
<Field>
|
||||
<Input type="number" placeholder="kali/menit" />
|
||||
<Input
|
||||
v-model="pulse"
|
||||
v-bind="pulseAttrs"
|
||||
type="number"
|
||||
placeholder="kali/menit"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Temperatur</Label>
|
||||
<Field>
|
||||
<Input type="number" placeholder="℃" />
|
||||
<Input
|
||||
v-model="temperature"
|
||||
v-bind="temperatureAttrs"
|
||||
type="number"
|
||||
placeholder="℃"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Berat Badan</Label>
|
||||
<Field>
|
||||
<Input type="number" placeholder="Kg" />
|
||||
<Input
|
||||
v-model="weight"
|
||||
v-bind="weightAttrs"
|
||||
type="number"
|
||||
placeholder="Kg"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Tinggi Badan</Label>
|
||||
<Field>
|
||||
<Input type="number" placeholder="Cm" />
|
||||
<Input
|
||||
v-model="height"
|
||||
v-bind="heightAttrs"
|
||||
type="number"
|
||||
placeholder="Cm"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Golongan Darah</Label>
|
||||
<Field>
|
||||
<Select :options="bloodGroups" />
|
||||
<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" />
|
||||
<Textarea
|
||||
placeholder="Masukkan pemeriksaan fisik"
|
||||
v-model="physicalExamination"
|
||||
v-bind="physicalExaminationAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
@@ -171,9 +285,10 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Button
|
||||
class="rounded bg-orange-100 px-3 py-1 text-orange-600"
|
||||
type="button"
|
||||
@click="emits('click', 'diagnosa')"
|
||||
>+ Pilih Diagnosa</Button
|
||||
@click="emits('modal', 'diagnosa')"
|
||||
>
|
||||
+ Pilih Diagnosa
|
||||
</Button>
|
||||
</Field>
|
||||
</Cell>
|
||||
<!-- Diagnosa -->
|
||||
@@ -183,9 +298,10 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Button
|
||||
class="rounded bg-orange-100 px-3 py-1 text-orange-600"
|
||||
type="button"
|
||||
@click="emits('click', 'prosedur')"
|
||||
>+ Pilih Prosedur</Button
|
||||
@click="emits('modal', 'prosedur')"
|
||||
>
|
||||
+ Pilih Prosedur
|
||||
</Button>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -199,21 +315,30 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>Diagnosa Medis</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="diagnosisMedical"
|
||||
v-bind="diagnosisMedicalAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Rencana Awal Medis</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="medicalPlan"
|
||||
v-bind="medicalPlanAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Terapi</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="therapy"
|
||||
v-bind="therapyAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
|
||||
@@ -4,24 +4,88 @@ 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 emits = defineEmits(['click'])
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', val: any): void
|
||||
(e: 'submit', val: any): void
|
||||
}>()
|
||||
|
||||
const subject = ref({
|
||||
'prim-compl': '',
|
||||
'sec-compl': '',
|
||||
'cur-disea-hist': '',
|
||||
'pas-disea-hist': '',
|
||||
'fam-disea-hist': '',
|
||||
'alg-hist': '',
|
||||
'alg-react': '',
|
||||
'med-hist': '',
|
||||
'blood-type': '',
|
||||
// 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 [medicalPlan, medicalPlanAttrs] = defineField('medical-plan')
|
||||
const [diagnosisMedical, diagnosisMedicalAttrs] = defineField('diagnosis-medical')
|
||||
const [rehabTrouble, rehabTroubleAttrs] = defineField('rehab-trouble')
|
||||
const [medicalTrouble, medicalTroubleAttrs] = defineField('medical-trouble')
|
||||
const [physicModal, physicModalAttrs] = defineField('physic-modal')
|
||||
const [exercise, exerciseAttrs] = defineField('exercise')
|
||||
const [orthoPesa, orthoPesaAttrs] = defineField('ortho-pesa')
|
||||
const [education, educationAttrs] = defineField('education')
|
||||
const [other, otherAttrs] = defineField('other')
|
||||
const [cranialis, cranialisAttrs] = defineField('cranialis')
|
||||
const [sensoris, sensorisAttrs] = defineField('sensoris')
|
||||
const [reflectFisio, reflectFisioAttrs] = defineField('reflect-fisio')
|
||||
const [reflectPato, reflectPatoAttrs] = defineField('reflect-pato')
|
||||
const [otonom, otonomAttrs] = defineField('otonom')
|
||||
const [localis, localisAttrs] = defineField('localis')
|
||||
const [medicalTrial, medicalTrialAttrs] = defineField('medical-trial')
|
||||
const [therapy, therapyAttrs] = defineField('therapy')
|
||||
const [systolic, systolicAttrs] = defineField('syst-bp')
|
||||
const [diastolic, diastolicAttrs] = defineField('diast-bp')
|
||||
const [pulse, pulseAttrs] = defineField('pulse')
|
||||
const [gcs, gcsAttrs] = defineField('gcs')
|
||||
const [respiratoryRate, respiratoryRateAttrs] = defineField('respiratory-rate')
|
||||
const [temperature, temperatureAttrs] = defineField('temperature')
|
||||
const [weight, weightAttrs] = defineField('weight')
|
||||
const [height, heightAttrs] = defineField('height')
|
||||
const [ambulance, ambulanceAttrs] = defineField('ambulance')
|
||||
const [gait, gaitAttrs] = defineField('gait')
|
||||
const [neckRom, neckRomAttrs] = defineField('neck-rom')
|
||||
const [bodyRom, bodyRomAttrs] = defineField('body-rom')
|
||||
const [agaRom, agaRomAttrs] = defineField('aga-rom')
|
||||
const [agbRom, agbRomAttrs] = defineField('agb-rom')
|
||||
const [neckMmt, neckMmtAttrs] = defineField('neck-mmt')
|
||||
const [bodyMmt, bodyMmtAttrs] = defineField('body-mmt')
|
||||
const [agaMmt, agaMmtAttrs] = defineField('aga-mmt')
|
||||
const [agbMmt, agbMmtAttrs] = defineField('agb-mmt')
|
||||
|
||||
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)
|
||||
</script>
|
||||
|
||||
@@ -36,8 +100,11 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Block>
|
||||
<Cell>
|
||||
<Label dynamic>Keluhan Utama</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Field :errMessage="errors['prim-compl']">
|
||||
<Textarea
|
||||
v-model="primaryComplaint"
|
||||
v-bind="primaryComplaintAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -46,21 +113,30 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>Diagnosa Medis</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="diagnosisMedical"
|
||||
v-bind="diagnosisMedicalAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Rencana Awal Medis</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="medicalPlan"
|
||||
v-bind="medicalPlanAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Terapi</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="therapy"
|
||||
v-bind="therapyAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -77,22 +153,36 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>Tekanan Darah</Label>
|
||||
<Field>
|
||||
<Input placeholder="Sistolik" />
|
||||
<Input placeholder="Diastolik" />
|
||||
<Input
|
||||
placeholder="Sistolik"
|
||||
v-model="systolic"
|
||||
v-bind="systolicAttrs"
|
||||
/>
|
||||
<Input
|
||||
placeholder="Diastolik"
|
||||
v-model="diastolic"
|
||||
v-bind="diastolicAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Nadi</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="pulse"
|
||||
v-bind="pulseAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>GCS</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="gcs"
|
||||
v-bind="gcsAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -100,14 +190,21 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>RR</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="respiratoryRate"
|
||||
v-bind="respiratoryRateAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Ambulasi</Label>
|
||||
<Field>
|
||||
<RadioGroup class="flex gap-4">
|
||||
<RadioGroup
|
||||
class="flex gap-4"
|
||||
v-model="ambulance"
|
||||
v-bind="ambulanceAttrs"
|
||||
>
|
||||
<div class="flex items-center space-x-2">
|
||||
<RadioGroupItem
|
||||
id="vaksin-yes"
|
||||
@@ -129,7 +226,10 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>Gait</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="gait"
|
||||
v-bind="gaitAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -144,21 +244,30 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>N. Cranialis</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="cranialis"
|
||||
v-bind="cranialisAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Sensoris</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="sensoris"
|
||||
v-bind="sensorisAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Reflek Fisilogis</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="reflectFisio"
|
||||
v-bind="reflectFisioAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -166,13 +275,19 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>Reflek Patologis</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="reflectPato"
|
||||
v-bind="reflectPatoAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Saraf Otonom</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="otonom"
|
||||
v-bind="otonomAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -187,13 +302,19 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>Leher</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="neckRom"
|
||||
v-bind="neckRomAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Batang Tubuh</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="bodyRom"
|
||||
v-bind="bodyRomAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -201,13 +322,19 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>AGA</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="agaRom"
|
||||
v-bind="agaRomAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>AGB</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="agbRom"
|
||||
v-bind="agbRomAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -222,13 +349,19 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>Leher</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="neckMmt"
|
||||
v-bind="neckMmtAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Batang Tubuh</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="bodyMmt"
|
||||
v-bind="bodyMmtAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -236,13 +369,19 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>AGA</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="agaMmt"
|
||||
v-bind="agaMmtAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>AGB</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="agbMmt"
|
||||
v-bind="agbMmtAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -256,7 +395,10 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>Deskripsi Temuan Fisik</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="localis"
|
||||
v-bind="localisAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -271,7 +413,10 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>Catatan Pemeriksaan Penunjang</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="medicalTrial"
|
||||
v-bind="medicalTrialAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -286,13 +431,19 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>Masalah Medik</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="medicalTrouble"
|
||||
v-bind="medicalTroubleAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Masalah Rehabilitasi Medik</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="rehabTrouble"
|
||||
v-bind="rehabTroubleAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -316,21 +467,30 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>Modalitas Fisik</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="physicModal"
|
||||
v-bind="physicModalAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Latihan</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="exercise"
|
||||
v-bind="exerciseAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Ortesa Protesa</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="orthoPesa"
|
||||
v-bind="orthoPesaAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -338,13 +498,19 @@ const isExcluded = (key: string) => props.excludeFields?.includes(key)
|
||||
<Cell>
|
||||
<Label dynamic>Edukasi</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="education"
|
||||
v-bind="educationAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Lain-Lain</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="other"
|
||||
v-bind="otherAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
|
||||
@@ -1,28 +1,47 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import EarlyEntry from './early-entry.vue'
|
||||
import EarlyRehabEntry from './early-rehab-entry.vue'
|
||||
import FunctionEntry from './function-entry.vue'
|
||||
|
||||
/**
|
||||
* Props:
|
||||
* - excludeFields: daftar nama field yang ingin disembunyikan
|
||||
*/
|
||||
const props = defineProps<{
|
||||
type: 'early' | 'early-rehab' | 'function'
|
||||
excludeFields?: string[]
|
||||
}>()
|
||||
|
||||
const emits = defineEmits(['click', 'submit', 'cancel'])
|
||||
|
||||
const componentMap = {
|
||||
early: EarlyEntry,
|
||||
'early-rehab': EarlyRehabEntry,
|
||||
function: FunctionEntry,
|
||||
}
|
||||
|
||||
// Komponen aktif berdasarkan type
|
||||
const ActiveComponent = computed(() => componentMap[props.type])
|
||||
|
||||
const childRef = ref()
|
||||
|
||||
const validate = async () => {
|
||||
if (childRef.value?.validate) {
|
||||
const result = await childRef.value.validate()
|
||||
console.log('[Wrapper] Result from child validate:', result)
|
||||
return result
|
||||
} else {
|
||||
console.warn('validate() not found in child component')
|
||||
return { valid: false, data: null, errors: {} }
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ validate })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="ActiveComponent" :exclude-fields="excludeFields" />
|
||||
<component
|
||||
ref="childRef"
|
||||
:is="ActiveComponent"
|
||||
:exclude-fields="excludeFields"
|
||||
@click="$emit('click', $event)"
|
||||
@submit="$emit('submit', $event)"
|
||||
@cancel="$emit('cancel', $event)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -4,24 +4,88 @@ 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 emits = defineEmits(['click'])
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', val: any): void
|
||||
(e: 'submit', val: any): void
|
||||
}>()
|
||||
|
||||
const subject = ref({
|
||||
'prim-compl': '',
|
||||
'sec-compl': '',
|
||||
'cur-disea-hist': '',
|
||||
'pas-disea-hist': '',
|
||||
'fam-disea-hist': '',
|
||||
'alg-hist': '',
|
||||
'alg-react': '',
|
||||
'med-hist': '',
|
||||
'blood-type': '',
|
||||
// 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[]>([])
|
||||
@@ -55,8 +119,11 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Block>
|
||||
<Cell>
|
||||
<Label dynamic>Keluhan Utama</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Field :errMessage="errors['prim-compl']">
|
||||
<Textarea
|
||||
v-model="primaryComplaint"
|
||||
v-bind="primaryComplaintAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -65,14 +132,20 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Riwayat Penyakit Dahulu</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="pastDisease"
|
||||
v-bind="pastDiseaseAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Riwayat Penyakit Sekarang</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="currentDisease"
|
||||
v-bind="currentDiseaseAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -86,7 +159,7 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Umum</Label>
|
||||
<Field>
|
||||
<Input placeholder="Sistolik" />
|
||||
<Input placeholder="" />
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -100,7 +173,10 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Kesadaran (GCS)</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="gcs"
|
||||
v-bind="gcsAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -108,14 +184,20 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Pernapasan</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="respiratoryRate"
|
||||
v-bind="respiratoryRateAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
|
||||
<Cell>
|
||||
<Label dynamic>Jenis</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="respiratoryRateType"
|
||||
v-bind="respiratoryRateTypeAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -123,13 +205,19 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Nadi</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="pulse"
|
||||
v-bind="pulseAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Jenis</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="pulseType"
|
||||
v-bind="pulseTypeAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -137,13 +225,19 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Tekanan Darah Lengan Kanan</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="rightArmBp"
|
||||
v-bind="rightArmBpAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Tekanan Darah Lengan Kiri</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="leftArmBp"
|
||||
v-bind="leftArmBpAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -151,13 +245,19 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Suhu Aksila</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="axillaryTemp"
|
||||
v-bind="axillaryTempAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Suhu Rektal</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="rektalTemp"
|
||||
v-bind="rektalTempAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -172,7 +272,10 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Kulit</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="skin"
|
||||
v-bind="skinAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -183,19 +286,28 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Kepala</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="head"
|
||||
v-bind="headAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Telinga</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="ear"
|
||||
v-bind="earAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Hidung</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="nose"
|
||||
v-bind="noseAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -204,19 +316,28 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Rongga Mulut/Tenggorokan</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="oralCavity"
|
||||
v-bind="oralCavityAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Mata</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="eye"
|
||||
v-bind="eyeAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Lain-Lain</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="otherBodyPart"
|
||||
v-bind="otherBodyPartAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -227,13 +348,19 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Leher</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="neck"
|
||||
v-bind="neckAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Kelenjar Tiroid</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="thyroid"
|
||||
v-bind="thyroidAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
@@ -250,19 +377,28 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Thorax</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="thorax"
|
||||
v-bind="thoraxAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Jantung</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="heart"
|
||||
v-bind="heartAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Paru-Paru</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="lung"
|
||||
v-bind="lungAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -281,19 +417,28 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Abdomen</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="abdomen"
|
||||
v-bind="abdomenAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Hati</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="heart2"
|
||||
v-bind="heart2Attrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Lien</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="lien"
|
||||
v-bind="lienAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -312,19 +457,28 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Punggung</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="back"
|
||||
v-bind="backAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Ekstremitas</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="extremity"
|
||||
v-bind="extremityAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Kelamin</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="gender"
|
||||
v-bind="genderAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -332,13 +486,19 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Rectum</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="rectum"
|
||||
v-bind="rectumAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>System Syaraf</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
<Input
|
||||
v-model="nervousSystem"
|
||||
v-bind="nervousSystemAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -348,13 +508,19 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Neuromoskuloskeletal</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="neuromoskuloskeletal"
|
||||
v-bind="neuromoskuloskeletalAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Kardiorespirasi</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="cardioRespiratory"
|
||||
v-bind="cardioRespiratoryAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
@@ -369,13 +535,19 @@ const therapyOptions = ['Terapi Latihan', 'Modalitas Fisik', 'Protesa/Ortosa', '
|
||||
<Cell>
|
||||
<Label dynamic>Pencitraan</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="imaging"
|
||||
v-bind="imagingAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label dynamic>Laboratorium</Label>
|
||||
<Field>
|
||||
<Textarea />
|
||||
<Textarea
|
||||
v-model="laboratory"
|
||||
v-bind="laboratoryAttrs"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
|
||||
@@ -95,14 +95,22 @@ provide('table_data_loader', isLoading)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Header :prep="{ ...hreaderPrep }" :ref-search-nav="refSearchNav" />
|
||||
<Header
|
||||
:prep="{ ...hreaderPrep }"
|
||||
:ref-search-nav="refSearchNav"
|
||||
/>
|
||||
<Separator class="my-4 xl:my-5" />
|
||||
|
||||
<Filter :ref-search-nav="refSearchNav" />
|
||||
|
||||
<AppEncounterList :data="data" />
|
||||
|
||||
<Dialog v-model:open="isFormEntryDialogOpen" title="Filter" size="lg" prevent-outside>
|
||||
<Dialog
|
||||
v-model:open="isFormEntryDialogOpen"
|
||||
title="Filter"
|
||||
size="lg"
|
||||
prevent-outside
|
||||
>
|
||||
<AppEncounterFilter />
|
||||
</Dialog>
|
||||
<!-- <Pagination :pagination-meta="paginationMeta" @page-change="handlePageChange" /> -->
|
||||
</template>
|
||||
|
||||
@@ -5,18 +5,16 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
import { getDetail } from '~/services/encounter.service'
|
||||
|
||||
import type { Encounter } from '~/models/encounter'
|
||||
|
||||
// Components
|
||||
import CompTab from '~/components/pub/my-ui/comp-tab/comp-tab.vue'
|
||||
//
|
||||
import type { TabItem } from '~/components/pub/my-ui/comp-tab/type'
|
||||
import CompTab from '~/components/pub/my-ui/comp-tab/comp-tab.vue'
|
||||
|
||||
import Status from '~/components/app/encounter/status.vue'
|
||||
// PLASE ORDER BY TAB POSITION
|
||||
import Status from '~/components/content/encounter/status.vue'
|
||||
import AssesmentFunctionList from '~/components/content/assesment-function/list.vue'
|
||||
import EarlyMedicalAssesmentList from '~/components/content/soapi/entry.vue'
|
||||
// import AssesmentFunctionList from '~/components/content/assesment-function/list.vue'
|
||||
import PrescriptionList from '~/components/content/prescription/list.vue'
|
||||
import EarlyMedicalRehabList from '~/components/content/soapi/entry.vue'
|
||||
import PrescriptionList from '~/components/content/prescription/list.vue'
|
||||
import Consultation from '~/components/content/consultation/list.vue'
|
||||
|
||||
const route = useRoute()
|
||||
@@ -31,7 +29,10 @@ const activeTab = computed({
|
||||
})
|
||||
|
||||
const id = typeof route.params.id == 'string' ? parseInt(route.params.id) : 0
|
||||
const dataRes = await getDetail(id, { includes: 'patient,patient-person,patient-person-addresses,unit,Appointment_Doctor,Appointment_Doctor-employee,Appointment_Doctor-employee-person'})
|
||||
const dataRes = await getDetail(id, {
|
||||
includes:
|
||||
'patient,patient-person,patient-person-addresses,unit,Appointment_Doctor,Appointment_Doctor-employee,Appointment_Doctor-employee-person',
|
||||
})
|
||||
const dataResBody = dataRes.body ?? null
|
||||
const data = dataResBody?.data ?? null
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
<script setup lang="ts">
|
||||
//
|
||||
import { getValueLabelList as getDoctorValueLabelList } from '~/services/doctor.service'
|
||||
import { getValueLabelList as getEmployeeValueLabelList } from '~/services/employee.service'
|
||||
import { getValueLabelList as getUnitValueLabelList } from '~/services/unit.service'
|
||||
import type { CheckInFormData, CheckOutFormData } from '~/schemas/encounter.schema'
|
||||
import { CheckInSchema, CheckOutSchema } from '~/schemas/encounter.schema'
|
||||
|
||||
//
|
||||
import Dialog from '~/components/pub/my-ui/modal/dialog.vue'
|
||||
import CheckInView from '~/components/app/encounter/check-in-view.vue'
|
||||
import CheckInEntry from '~/components/app/encounter/check-in-entry.vue'
|
||||
import CheckOutView from '~/components/app/encounter/check-out-view.vue'
|
||||
import CheckOutEntry from '~/components/app/encounter/check-out-entry.vue'
|
||||
import type { Encounter } from '~/models/encounter'
|
||||
import { checkIn } from '~/services/encounter.service'
|
||||
|
||||
//
|
||||
const props = defineProps<{
|
||||
encounter: Encounter
|
||||
}>()
|
||||
|
||||
// doctors
|
||||
const doctors = await getDoctorValueLabelList({'includes': 'employee,employee-person'})
|
||||
const employees = await getEmployeeValueLabelList({'includes': 'person', 'position-code': 'reg'})
|
||||
const units = await getUnitValueLabelList()
|
||||
|
||||
// check in
|
||||
const checkInValues = ref<any>({
|
||||
discharge_method_code: '',
|
||||
responsible_doctor_id: 0,
|
||||
// registeredAt: '',
|
||||
})
|
||||
const checkInIsLoading = ref(false)
|
||||
const checkInIsReadonly = ref(false)
|
||||
const checkInDialogOpen = ref(false)
|
||||
|
||||
// check out
|
||||
const checkOutValues = ref<any>({
|
||||
dischargeMethod_code: '',
|
||||
unit_id: 0,
|
||||
responsibleDoctor_id: 0,
|
||||
})
|
||||
const checkOutIsLoading = ref(false)
|
||||
const checkOutIsReadonly = ref(false)
|
||||
const checkOutDialogOpen = ref(false)
|
||||
|
||||
function editCheckIn() {
|
||||
checkInDialogOpen.value = true
|
||||
}
|
||||
|
||||
function submitCheckIn(values: CheckInFormData) {
|
||||
checkIn(props.encounter.id, values)
|
||||
}
|
||||
|
||||
function editCheckOut() {
|
||||
checkOutDialogOpen.value = true
|
||||
}
|
||||
|
||||
function submitCheckOut(values: CheckOutFormData) {
|
||||
console.log(values)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="lg:grid grid-cols-2">
|
||||
<div class="border-r lg:pe-4 xl:pe-5 mb-10">
|
||||
<div class="mb-4 xl:mb-5 text-base text-center font-semibold">Informasi Masuk</div>
|
||||
<CheckInView
|
||||
:encounter="encounter"
|
||||
:is-loading="checkInIsLoading"
|
||||
:is-readonly="checkInIsReadonly"
|
||||
@edit="editCheckIn"
|
||||
/>
|
||||
</div>
|
||||
<div class="lg:ps-4 xl:ps-5">
|
||||
<Separator class="lg:hidden my-4 xl:my-5" />
|
||||
<div class="mb-4 xl:mb-5 text-base text-center font-semibold">Informasi Keluar</div>
|
||||
<CheckOutView
|
||||
:encounter="encounter"
|
||||
:is-loading="checkOutIsLoading"
|
||||
:is-readonly="checkOutIsReadonly"
|
||||
@edit="editCheckOut"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Dialog
|
||||
v-model:open="checkInDialogOpen"
|
||||
title="Ubah Informasi Masuk"
|
||||
size="md"
|
||||
prevent-outside
|
||||
>
|
||||
<CheckInEntry
|
||||
:schema="CheckInSchema"
|
||||
:values="checkInValues"
|
||||
:encounter="encounter"
|
||||
:doctors="doctors"
|
||||
:employees="employees"
|
||||
:is-loading="checkInIsLoading"
|
||||
:is-readonly="checkInIsReadonly"
|
||||
@submit="submitCheckIn"
|
||||
@cancel="checkInDialogOpen = false"
|
||||
/>
|
||||
</Dialog>
|
||||
|
||||
<Dialog
|
||||
v-model:open="checkOutDialogOpen"
|
||||
title="Ubah Informasi Keluar"
|
||||
size="lg"
|
||||
prevent-outside
|
||||
>
|
||||
<CheckOutEntry
|
||||
:schema="CheckOutSchema"
|
||||
:values="checkOutValues"
|
||||
:encounter="encounter"
|
||||
:units="units"
|
||||
:doctors="doctors"
|
||||
:is-loading="checkInIsLoading"
|
||||
:is-readonly="checkInIsReadonly"
|
||||
@submit="submitCheckOut"
|
||||
@cancel="checkInDialogOpen = false"
|
||||
/>
|
||||
</Dialog>
|
||||
</template>
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useQueryMode } from '@/composables/useQueryMode' // asumsikan ini ada
|
||||
import { useQueryMode } from '@/composables/useQueryMode'
|
||||
|
||||
import SoapiList from './list.vue'
|
||||
import EarlyForm from './form.vue'
|
||||
|
||||
@@ -1,9 +1,61 @@
|
||||
<script setup lang="ts">
|
||||
import { z } from 'zod'
|
||||
import Entry from '~/components/app/soapi/entry.vue'
|
||||
import Action from '~/components/pub/my-ui/nav-footer/ba-dr-su.vue'
|
||||
import Dialog from '~/components/pub/my-ui/modal/dialog.vue'
|
||||
import { FunctionSoapiSchema } from '~/schemas/soapi.schema'
|
||||
import { toast } from '~/components/pub/ui/toast'
|
||||
import { handleActionSave, handleActionEdit } from '~/handlers/soapi-early.handler'
|
||||
|
||||
const route = useRoute()
|
||||
const isOpen = ref(false)
|
||||
const data = ref([])
|
||||
const schema = FunctionSoapiSchema
|
||||
const payload = ref({
|
||||
encounter_id: 0,
|
||||
time: '',
|
||||
typeCode: 'function',
|
||||
value: '',
|
||||
})
|
||||
const model = ref({
|
||||
'prim-compl': '',
|
||||
'past-disease': '',
|
||||
'current-disease': '',
|
||||
gcs: '',
|
||||
'respiratory-rate': '',
|
||||
'respiratory-rate-type': '',
|
||||
pulse: '',
|
||||
'pulse-type': '',
|
||||
'right-arm-bp': '',
|
||||
'left-arm-bp': '',
|
||||
'axillary-temp': '',
|
||||
'rektal-temp': '',
|
||||
skin: '',
|
||||
head: '',
|
||||
ear: '',
|
||||
nose: '',
|
||||
'oral-cavity': '',
|
||||
eye: '',
|
||||
'other-body-part': '',
|
||||
neck: '',
|
||||
thyroid: '',
|
||||
thorax: '',
|
||||
heart: '',
|
||||
lung: '',
|
||||
abdomen: '',
|
||||
heart2: '',
|
||||
lien: '',
|
||||
back: '',
|
||||
extremity: '',
|
||||
gender: '',
|
||||
rectum: '',
|
||||
'system-syaraf': '',
|
||||
'nervous-system': '',
|
||||
'cardio-respiratory': '',
|
||||
imaging: '',
|
||||
laboratory: '',
|
||||
})
|
||||
|
||||
const isLoading = reactive<DataTableLoader>({
|
||||
isTableLoading: false,
|
||||
})
|
||||
@@ -21,19 +73,45 @@ onMounted(() => {
|
||||
getPatientList()
|
||||
})
|
||||
|
||||
function handleClick(type: string) {
|
||||
function handleOpen(type: string) {
|
||||
console.log(type)
|
||||
isOpen.value = true
|
||||
}
|
||||
|
||||
const entryRehabRef = ref()
|
||||
async function actionHandler(type: string) {
|
||||
console.log(type)
|
||||
const result = await entryRehabRef.value?.validate()
|
||||
if (result?.valid) {
|
||||
console.log('data', result.data)
|
||||
handleActionSave(
|
||||
{
|
||||
...payload.value,
|
||||
value: JSON.stringify(result.data),
|
||||
encounter_id: +route.params.id,
|
||||
time: new Date().toISOString(),
|
||||
},
|
||||
{},
|
||||
toast,
|
||||
)
|
||||
} else {
|
||||
console.log('Ada error di form', result)
|
||||
}
|
||||
}
|
||||
|
||||
provide('table_data_loader', isLoading)
|
||||
</script>
|
||||
<template>
|
||||
<Entry
|
||||
ref="entryRehabRef"
|
||||
v-model="model"
|
||||
:schema="schema"
|
||||
type="function"
|
||||
:exclude-fields="['prim-compl', 'sec-compl']"
|
||||
@click="handleClick"
|
||||
@modal="handleOpen"
|
||||
/>
|
||||
<div class="my-2 flex justify-end py-2">
|
||||
<Action @click="actionHandler" />
|
||||
</div>
|
||||
<Dialog
|
||||
v-model:open="isOpen"
|
||||
title="Pilih Prosedur"
|
||||
|
||||
@@ -1,9 +1,66 @@
|
||||
<script setup lang="ts">
|
||||
import { z } from 'zod'
|
||||
import Entry from '~/components/app/soapi/entry.vue'
|
||||
import Action from '~/components/pub/my-ui/nav-footer/ba-dr-su.vue'
|
||||
import Dialog from '~/components/pub/my-ui/modal/dialog.vue'
|
||||
import { EarlyRehabSchema } from '~/schemas/soapi.schema'
|
||||
import { toast } from '~/components/pub/ui/toast'
|
||||
import { handleActionSave, handleActionEdit } from '~/handlers/soapi-early.handler'
|
||||
|
||||
const route = useRoute()
|
||||
const isOpen = ref(false)
|
||||
const data = ref([])
|
||||
const schema = EarlyRehabSchema
|
||||
const payload = ref({
|
||||
encounter_id: 0,
|
||||
time: '',
|
||||
typeCode: 'early-rehab',
|
||||
value: '',
|
||||
})
|
||||
const model = ref({
|
||||
'prim-compl': '',
|
||||
'medical-plan': '',
|
||||
'diagnosis-medical': '',
|
||||
'rehab-trouble': '',
|
||||
'medical-trouble': '',
|
||||
'physic-modal': '',
|
||||
exercise: '',
|
||||
'ortho-pesa': '',
|
||||
education: '',
|
||||
other: '',
|
||||
cranialis: '',
|
||||
sensoris: '',
|
||||
'reflect-fisio': '',
|
||||
'reflect-pato': '',
|
||||
otonom: '',
|
||||
localis: '',
|
||||
'medical-trial': '',
|
||||
therapy: '',
|
||||
'syst-bp': '',
|
||||
'diast-bp': '',
|
||||
pulse: '',
|
||||
gcs: '',
|
||||
'respiratory-rate': '',
|
||||
temperature: '',
|
||||
ambulance: '',
|
||||
gait: '',
|
||||
'neck-rom': '',
|
||||
'body-rom': '',
|
||||
'aga-rom': '',
|
||||
'agb-rom': '',
|
||||
'neck-mmt': '',
|
||||
'body-mmt': '',
|
||||
'aga-mmt': '',
|
||||
'agb-mmt': '',
|
||||
localis: '',
|
||||
'medical-trouble': '',
|
||||
'rehab-trouble': '',
|
||||
temp: '',
|
||||
spo2: '',
|
||||
weight: '',
|
||||
height: '',
|
||||
})
|
||||
|
||||
const isLoading = reactive<DataTableLoader>({
|
||||
isTableLoading: false,
|
||||
})
|
||||
@@ -21,19 +78,45 @@ onMounted(() => {
|
||||
getPatientList()
|
||||
})
|
||||
|
||||
function handleClick(type: string) {
|
||||
function handleOpen(type: string) {
|
||||
console.log(type)
|
||||
isOpen.value = true
|
||||
}
|
||||
|
||||
const entryRehabRef = ref()
|
||||
async function actionHandler(type: string) {
|
||||
console.log(type)
|
||||
const result = await entryRehabRef.value?.validate()
|
||||
if (result?.valid) {
|
||||
console.log('data', result.data)
|
||||
handleActionSave(
|
||||
{
|
||||
...payload.value,
|
||||
value: JSON.stringify(result.data),
|
||||
encounter_id: +route.params.id,
|
||||
time: new Date().toISOString(),
|
||||
},
|
||||
{},
|
||||
toast,
|
||||
)
|
||||
} else {
|
||||
console.log('Ada error di form', result)
|
||||
}
|
||||
}
|
||||
|
||||
provide('table_data_loader', isLoading)
|
||||
</script>
|
||||
<template>
|
||||
<Entry
|
||||
ref="entryRehabRef"
|
||||
v-model="model"
|
||||
:schema="schema"
|
||||
type="early-rehab"
|
||||
:exclude-fields="['prim-compl', 'sec-compl']"
|
||||
@click="handleClick"
|
||||
@modal="handleOpen"
|
||||
/>
|
||||
<div class="my-2 flex justify-end py-2">
|
||||
<Action @click="actionHandler" />
|
||||
</div>
|
||||
<Dialog
|
||||
v-model:open="isOpen"
|
||||
title="Pilih Prosedur"
|
||||
|
||||
@@ -1,9 +1,39 @@
|
||||
<script setup lang="ts">
|
||||
import { z } from 'zod'
|
||||
import Entry from '~/components/app/soapi/entry.vue'
|
||||
import Action from '~/components/pub/my-ui/nav-footer/ba-dr-su.vue'
|
||||
import Dialog from '~/components/pub/my-ui/modal/dialog.vue'
|
||||
import { EarlySchema } from '~/schemas/soapi.schema'
|
||||
import { toast } from '~/components/pub/ui/toast'
|
||||
import { handleActionSave, handleActionEdit } from '~/handlers/soapi-early.handler'
|
||||
|
||||
const route = useRoute()
|
||||
const isOpen = ref(false)
|
||||
const data = ref([])
|
||||
const schema = EarlySchema
|
||||
const payload = ref({
|
||||
encounter_id: 0,
|
||||
time: '',
|
||||
typeCode: 'early',
|
||||
value: '',
|
||||
})
|
||||
|
||||
const model = ref({
|
||||
'prim-compl': '',
|
||||
'cur-disea-hist': '',
|
||||
'syst-bp': '',
|
||||
'diast-bp': '',
|
||||
pulse: '',
|
||||
'resp-rate': '',
|
||||
temp: '',
|
||||
weight: '',
|
||||
height: '',
|
||||
'reflect-fisio': '',
|
||||
'reflect-pato': '',
|
||||
'autonom-neuron': '',
|
||||
'medical-act': '',
|
||||
therapy: '',
|
||||
})
|
||||
const isLoading = reactive<DataTableLoader>({
|
||||
isTableLoading: false,
|
||||
})
|
||||
@@ -21,16 +51,51 @@ onMounted(() => {
|
||||
getPatientList()
|
||||
})
|
||||
|
||||
function handleClick(type: string) {
|
||||
function handleOpen(type: string) {
|
||||
console.log(type)
|
||||
isOpen.value = true
|
||||
}
|
||||
|
||||
const entryRef = ref()
|
||||
async function actionHandler(type: string) {
|
||||
console.log(type)
|
||||
const result = await entryRef.value?.validate()
|
||||
if (result?.valid) {
|
||||
console.log('data', result.data)
|
||||
handleActionSave(
|
||||
{
|
||||
...payload.value,
|
||||
value: JSON.stringify(result.data),
|
||||
encounter_id: +route.params.id,
|
||||
time: new Date().toISOString(),
|
||||
},
|
||||
{},
|
||||
toast,
|
||||
)
|
||||
} else {
|
||||
console.log('Ada error di form', result)
|
||||
}
|
||||
}
|
||||
|
||||
provide('table_data_loader', isLoading)
|
||||
</script>
|
||||
<template>
|
||||
<Entry type="early" :exclude-fields="['prim-compl', 'sec-compl']" @click="handleClick" />
|
||||
<Dialog v-model:open="isOpen" title="Pilih Prosedur" size="xl" prevent-outside>
|
||||
<Entry
|
||||
ref="entryRef"
|
||||
v-model="model"
|
||||
:schema="schema"
|
||||
type="early"
|
||||
@modal="handleOpen"
|
||||
/>
|
||||
<div class="my-2 flex justify-end py-2">
|
||||
<Action @click="actionHandler" />
|
||||
</div>
|
||||
<Dialog
|
||||
v-model:open="isOpen"
|
||||
title="Pilih Prosedur"
|
||||
size="xl"
|
||||
prevent-outside
|
||||
>
|
||||
<AppIcdMultiselectPicker :data="data" />
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import Confirmation from '~/components/pub/my-ui/confirmation/confirmation.vue'
|
||||
import Confirmation from './confirmation.vue'
|
||||
|
||||
interface RecordData {
|
||||
id: number | string
|
||||
|
||||
@@ -60,7 +60,7 @@ const settingClass = computed(() => {
|
||||
'[&_.label]:md:w-44 [&_.label]:xl:w-52',
|
||||
][getLabelSizeIdx(props.labelSize)]
|
||||
} else {
|
||||
cls += ' gap-y-4 2xl:gap-y-5 [&_.label]:pb-1 [&_.label]:!pt-0 ';
|
||||
cls += ' gap-y-2 2xl:gap-y-3 [&_.label]:pb-1 [&_.label]:!pt-0 ';
|
||||
}
|
||||
cls += ' [&:not(.preview)_.height-default]:pt-2 [&:not(.preview)_.height-default]:2xl:!pt-1.5 [&:not(.preview)_.height-compact]:!pt-1 '
|
||||
cls += '[&_textarea]:md:text-xs [&_textarea]:2xl:!text-sm '
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import { Dialog } from '~/components/pub/ui/dialog'
|
||||
import DialogContent from '~/components/pub/ui/dialog/DialogContent.vue'
|
||||
import DialogDescription from '~/components/pub/ui/dialog/DialogDescription.vue'
|
||||
|
||||
interface DialogProps {
|
||||
title: string
|
||||
titleIcon?: string
|
||||
titleClass?: string
|
||||
description?: string
|
||||
preventOutside?: boolean
|
||||
open?: boolean
|
||||
size?: 'sm' | 'md' | 'lg' | 'xl' | 'full'
|
||||
size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full'
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<DialogProps>(), {
|
||||
@@ -24,8 +28,9 @@ const sizeClass = computed(() => {
|
||||
const sizeMap = {
|
||||
sm: 'sm:max-w-[350px]',
|
||||
md: 'sm:max-w-[425px]',
|
||||
lg: 'sm:max-w-[600px]',
|
||||
xl: 'sm:max-w-[800px]',
|
||||
lg: 'sm:max-w-[720px]',
|
||||
xl: 'sm:max-w-[960px]',
|
||||
'2xl': 'sm:max-w-[1200px]',
|
||||
full: 'sm:max-w-[95vw]',
|
||||
}
|
||||
return sizeMap[props.size]
|
||||
@@ -46,10 +51,19 @@ const isOpen = computed({
|
||||
@pointer-down-outside="(e: any) => preventOutside && e.preventDefault()"
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle class="text-[20px]">{{ props.title }}</DialogTitle>
|
||||
<DialogTitle :class="`text-sm 2xl:text-base font-semibold flex ${titleClass || ''}`">
|
||||
<div class="me-2 pt-0.5">
|
||||
<Icon v-if="props.titleIcon" :name="props.titleIcon" :class="`!pt-2`" />
|
||||
</div>
|
||||
<div>
|
||||
{{ props.title }}
|
||||
</div>
|
||||
</DialogTitle>
|
||||
<DialogDescription v-if="props.description">{{ props.description }}</DialogDescription>
|
||||
</DialogHeader>
|
||||
<slot />
|
||||
<DialogDescription :class="sizeClass">
|
||||
<slot />
|
||||
</DialogDescription>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
smallMode?: boolean
|
||||
defaultClass?: string
|
||||
class?: string
|
||||
}>()
|
||||
|
||||
const defaultClass = props.defaultClass ?? 'm-2 flex gap-2 px-2'
|
||||
const additionalClass = props.class ?? ''
|
||||
const btnClass = props.smallMode ? '[&_button]:w-7 [&_button]:h-7 [&_button]:2xl:w-8 [&_button]:2xl:h-9 [&_button]:!p-0' : ''
|
||||
|
||||
type ClickType = 'back' | 'delete' | 'draft' | 'submit'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: ClickType): void
|
||||
}>()
|
||||
|
||||
function onClick(type: ClickType) {
|
||||
emit('click', type)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="`${defaultClass} ${additionalClass} ${btnClass}`">
|
||||
<div>
|
||||
<Button variant="ghost" type="button" @click="onClick('back')">
|
||||
<Icon name="i-lucide-arrow-left" />
|
||||
Kembali
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button variant="destructive" type="button" @click="onClick('delete')">
|
||||
<Icon name="i-lucide-x" />
|
||||
Hapus
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button variant="secondary" type="button" @click="onClick('draft')">
|
||||
<Icon name="i-lucide-file" />
|
||||
Draft
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button class="bg-primary" type="button" @click="onClick('submit')">
|
||||
<Icon name="i-lucide-check" />
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,50 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
smallMode?: boolean
|
||||
defaultClass?: string
|
||||
class?: string
|
||||
}>()
|
||||
|
||||
const defaultClass = props.defaultClass ?? 'm-2 flex gap-2 px-2'
|
||||
const additionalClass = props.class ?? ''
|
||||
const btnClass = props.smallMode ? '[&_button]:w-7 [&_button]:h-7 [&_button]:2xl:w-8 [&_button]:2xl:h-9 [&_button]:!p-0' : ''
|
||||
|
||||
type ClickType = 'back' | 'draft' | 'delete' | 'print'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: ClickType): void
|
||||
}>()
|
||||
|
||||
function onClick(type: ClickType) {
|
||||
emit('click', type)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="`${defaultClass} ${additionalClass} ${btnClass}`">
|
||||
<div>
|
||||
<Button variant="ghost" type="button" @click="onClick('back')">
|
||||
<Icon name="i-lucide-arrow-left" class="me-2 align-middle" />
|
||||
Back
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button type="button" @click="onClick('draft')">
|
||||
<Icon name="i-lucide-file" class="me-2" />
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button variant="destructive" type="button" @click="onClick('delete')">
|
||||
<Icon name="i-lucide-trash" class="me-2 align-middle" />
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button class="bg-teal-500" type="button" @click="onClick('print')">
|
||||
<Icon name="i-lucide-printer" class="me-2 align-middle" />
|
||||
Print
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,44 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
smallMode?: boolean
|
||||
defaultClass?: string
|
||||
class?: string
|
||||
}>()
|
||||
|
||||
const defaultClass = props.defaultClass ?? 'm-2 flex gap-2 px-2'
|
||||
const additionalClass = props.class ?? ''
|
||||
const btnClass = props.smallMode ? '[&_button]:w-7 [&_button]:h-7 [&_button]:2xl:w-8 [&_button]:2xl:h-9 [&_button]:!p-0' : ''
|
||||
|
||||
type ClickType = 'back' | 'delete' | 'submit'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: ClickType): void
|
||||
}>()
|
||||
|
||||
function onClick(type: ClickType) {
|
||||
emit('click', type)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="`${defaultClass} ${additionalClass} ${btnClass}`">
|
||||
<div>
|
||||
<Button variant="ghost" type="button" @click="onClick('back')">
|
||||
<Icon name="i-lucide-arrow-left" />
|
||||
Kembali
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button variant="destructive" type="button" @click="onClick('delete')">
|
||||
<Icon name="i-lucide-trash" />
|
||||
Hapus
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button type="button" @click="onClick('submit')">
|
||||
<Icon name="i-lucide-check" />
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,5 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
type ClickType = 'cancel' | 'draft' | 'submit' | 'print'
|
||||
const props = defineProps<{
|
||||
smallMode?: boolean
|
||||
defaultClass?: string
|
||||
class?: string
|
||||
}>()
|
||||
|
||||
const defaultClass = props.defaultClass ?? 'm-2 flex gap-2 px-2'
|
||||
const additionalClass = props.class ?? ''
|
||||
const btnClass = props.smallMode ? '[&_button]:w-7 [&_button]:h-7 [&_button]:2xl:w-8 [&_button]:2xl:h-9 [&_button]:!p-0' : ''
|
||||
|
||||
type ClickType = 'back' | 'draft' | 'submit' | 'print'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: ClickType): void
|
||||
@@ -11,22 +21,30 @@ function onClick(type: ClickType) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="m-2 flex gap-2 px-2">
|
||||
<Button class="bg-gray-400" type="button" @click="onClick('cancel')">
|
||||
<Icon name="i-lucide-arrow-left" class="me-2 align-middle" />
|
||||
Back
|
||||
</Button>
|
||||
<Button class="bg-orange-500" variant="outline" type="button" @click="onClick('draft')">
|
||||
<Icon name="i-lucide-file" class="me-2" />
|
||||
Draf
|
||||
</Button>
|
||||
<Button class="bg-primary" type="button" @click="onClick('submit')">
|
||||
<Icon name="i-lucide-check" class="me-2 align-middle" />
|
||||
Submit
|
||||
</Button>
|
||||
<Button class="bg-primary" type="button" @click="onClick('print')">
|
||||
<Icon name="i-lucide-printer" class="me-2 align-middle" />
|
||||
Print
|
||||
</Button>
|
||||
<div :class="`${defaultClass} ${additionalClass} ${btnClass}`">
|
||||
<div>
|
||||
<Button variant="ghost" type="button" @click="onClick('back')">``
|
||||
<Icon name="i-lucide-arrow-left" class="me-2 align-middle" />
|
||||
Back
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button variant="secondary" type="button" @click="onClick('draft')">
|
||||
<Icon name="i-lucide-file" class="me-2" />
|
||||
Draf
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button type="button" @click="onClick('submit')">
|
||||
<Icon name="i-lucide-check" class="me-2 align-middle" />
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button class="bg-teal-500" type="button" @click="onClick('print')">
|
||||
<Icon name="i-lucide-printer" class="me-2 align-middle" />
|
||||
Print
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
type ClickType = 'cancel' | 'draft' | 'submit'
|
||||
const props = defineProps<{
|
||||
smallMode?: boolean
|
||||
defaultClass?: string
|
||||
class?: string
|
||||
}>()
|
||||
|
||||
const defaultClass = props.defaultClass ?? 'm-2 flex gap-2 px-2'
|
||||
const additionalClass = props.class ?? ''
|
||||
const btnClass = props.smallMode ? '[&_button]:w-7 [&_button]:h-7 [&_button]:2xl:w-8 [&_button]:2xl:h-9 [&_button]:!p-0' : ''
|
||||
|
||||
type ClickType = 'back' | 'draft' | 'submit'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: ClickType): void
|
||||
@@ -11,18 +21,24 @@ function onClick(type: ClickType) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="m-2 flex gap-2 px-2">
|
||||
<Button class="bg-gray-400" type="button" @click="onClick('cancel')">
|
||||
<Icon name="i-lucide-arrow-left" class="me-2 align-middle" />
|
||||
Back
|
||||
</Button>
|
||||
<Button class="bg-orange-500" variant="outline" type="button" @click="onClick('draft')">
|
||||
<Icon name="i-lucide-file" class="me-2" />
|
||||
Draft
|
||||
</Button>
|
||||
<Button class="bg-primary" type="button" @click="onClick('submit')">
|
||||
<Icon name="i-lucide-check" class="me-2 align-middle" />
|
||||
Submit
|
||||
</Button>
|
||||
<div :class="`${defaultClass} ${additionalClass} ${btnClass}`">
|
||||
<div>
|
||||
<Button variant="ghost" type="button" @click="onClick('back')">
|
||||
<Icon name="i-lucide-arrow-left" />
|
||||
Back
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button variant="secondary" type="button" @click="onClick('draft')">
|
||||
<Icon name="i-lucide-file" />
|
||||
Draft
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button type="button" @click="onClick('submit')">
|
||||
<Icon name="i-lucide-check" />
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
type ClickType = 'cancel' | 'draft' | 'delete' | 'print'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: ClickType): void
|
||||
}>()
|
||||
|
||||
function onClick(type: ClickType) {
|
||||
emit('click', type)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="m-2 flex gap-2 px-2">
|
||||
<Button class="bg-gray-400" type="button" @click="onClick('cancel')">
|
||||
<Icon name="i-lucide-arrow-left" class="me-2 align-middle" />
|
||||
Back
|
||||
</Button>
|
||||
<Button class="bg-orange-500" variant="outline" type="button" @click="onClick('draft')">
|
||||
<Icon name="i-lucide-file" class="me-2" />
|
||||
Edit
|
||||
</Button>
|
||||
<Button class="bg-red-500" type="button" @click="onClick('delete')">
|
||||
<Icon name="i-lucide-trash" class="me-2 align-middle" />
|
||||
Delete
|
||||
</Button>
|
||||
<Button class="bg-primary" type="button" @click="onClick('print')">
|
||||
<Icon name="i-lucide-printer" class="me-2 align-middle" />
|
||||
Print
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,5 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
type ClickType = 'cancel' | 'draft' | 'delete'
|
||||
const props = defineProps<{
|
||||
smallMode?: boolean
|
||||
defaultClass?: string
|
||||
class?: string
|
||||
}>()
|
||||
|
||||
const defaultClass = props.defaultClass ?? 'm-2 flex gap-2 px-2'
|
||||
const additionalClass = props.class ?? ''
|
||||
const btnClass = props.smallMode ? '[&_button]:w-7 [&_button]:h-7 [&_button]:2xl:w-8 [&_button]:2xl:h-9 [&_button]:!p-0' : ''
|
||||
|
||||
type ClickType = 'back' | 'draft' | 'delete'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: ClickType): void
|
||||
@@ -11,18 +21,24 @@ function onClick(type: ClickType) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="m-2 flex gap-2 px-2">
|
||||
<Button class="bg-gray-400" type="button" @click="onClick('cancel')">
|
||||
<Icon name="i-lucide-arrow-left" class="me-2 align-middle" />
|
||||
Back
|
||||
</Button>
|
||||
<Button class="bg-orange-500" variant="outline" type="button" @click="onClick('draft')">
|
||||
<Icon name="i-lucide-file" class="me-2" />
|
||||
Edit
|
||||
</Button>
|
||||
<Button class="bg-red-500" type="button" @click="onClick('delete')">
|
||||
<Icon name="i-lucide-trash" class="me-2 align-middle" />
|
||||
Delete
|
||||
</Button>
|
||||
<div :class="`${defaultClass} ${additionalClass} ${btnClass}`">
|
||||
<div>
|
||||
<Button class="bg-gray-400" type="button" @click="onClick('back')">
|
||||
<Icon name="i-lucide-arrow-left" class="me-2 align-middle" />
|
||||
Back
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button class="bg-orange-500" variant="outline" type="button" @click="onClick('draft')">
|
||||
<Icon name="i-lucide-file" class="me-2" />
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button class="bg-red-500" type="button" @click="onClick('delete')">
|
||||
<Icon name="i-lucide-trash" class="me-2 align-middle" />
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
type ClickType = 'cancel' | 'draft' | 'print'
|
||||
const props = defineProps<{
|
||||
smallMode?: boolean
|
||||
defaultClass?: string
|
||||
class?: string
|
||||
}>()
|
||||
|
||||
const defaultClass = props.defaultClass ?? 'm-2 flex gap-2 px-2'
|
||||
const additionalClass = props.class ?? ''
|
||||
const btnClass = props.smallMode ? '[&_button]:w-7 [&_button]:h-7 [&_button]:2xl:w-8 [&_button]:2xl:h-9 [&_button]:!p-0' : ''
|
||||
|
||||
type ClickType = 'back' | 'draft' | 'print'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: ClickType): void
|
||||
@@ -11,18 +21,24 @@ function onClick(type: ClickType) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="m-2 flex gap-2 px-2">
|
||||
<Button class="bg-gray-400" type="button" @click="onClick('cancel')">
|
||||
<Icon name="i-lucide-arrow-left" class="me-2 align-middle" />
|
||||
Back
|
||||
</Button>
|
||||
<Button class="bg-orange-500" variant="outline" type="button" @click="onClick('draft')">
|
||||
<Icon name="i-lucide-file" class="me-2" />
|
||||
Edit
|
||||
</Button>
|
||||
<Button class="bg-primary" type="button" @click="onClick('print')">
|
||||
<Icon name="i-lucide-printer" class="me-2 align-middle" />
|
||||
Print
|
||||
</Button>
|
||||
<div :class="`${defaultClass} ${additionalClass} ${btnClass}`">
|
||||
<div>
|
||||
<Button class="bg-gray-400" type="button" @click="onClick('back')">
|
||||
<Icon name="i-lucide-arrow-left" class="me-2 align-middle" />
|
||||
Back
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button class="bg-orange-500" variant="outline" type="button" @click="onClick('draft')">
|
||||
<Icon name="i-lucide-file" class="me-2" />
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button class="bg-primary" type="button" @click="onClick('print')">
|
||||
<Icon name="i-lucide-printer" class="me-2 align-middle" />
|
||||
Print
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
type ClickType = 'cancel' | 'edit'
|
||||
const props = defineProps<{
|
||||
smallMode?: boolean
|
||||
defaultClass?: string
|
||||
class?: string
|
||||
}>()
|
||||
|
||||
const defaultClass = props.defaultClass ?? 'm-2 flex gap-2 px-2'
|
||||
const additionalClass = props.class ?? ''
|
||||
const btnClass = props.smallMode ? '[&_button]:w-7 [&_button]:h-7 [&_button]:2xl:w-8 [&_button]:2xl:h-9 [&_button]:!p-0' : ''
|
||||
|
||||
type ClickType = 'back' | 'edit'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: ClickType): void
|
||||
@@ -11,29 +21,18 @@ function onClick(type: ClickType) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="m-2 flex gap-2 px-2">
|
||||
<Button
|
||||
class="bg-gray-400"
|
||||
type="button"
|
||||
@click="onClick('cancel')"
|
||||
>
|
||||
<Icon
|
||||
name="i-lucide-arrow-left"
|
||||
class="me-2 align-middle"
|
||||
/>
|
||||
Back
|
||||
</Button>
|
||||
<Button
|
||||
class="bg-orange-500"
|
||||
variant="outline"
|
||||
type="button"
|
||||
@click="onClick('edit')"
|
||||
>
|
||||
<Icon
|
||||
name="i-lucide-file"
|
||||
class="me-2 align-middle"
|
||||
/>
|
||||
Edit
|
||||
</Button>
|
||||
<div :class="`${defaultClass} ${additionalClass} ${btnClass}`">
|
||||
<div>
|
||||
<Button variant="ghost" type="button" @click="onClick('back')">
|
||||
<Icon name="i-lucide-arrow-left" class="me-2 align-middle" />
|
||||
Back
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button @click="onClick('edit')">
|
||||
<Icon name="i-lucide-file" class="me-2 align-middle" />
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
type ClickType = 'cancel' | 'submit'
|
||||
const props = defineProps<{
|
||||
smallMode?: boolean
|
||||
defaultClass?: string
|
||||
class?: string
|
||||
}>()
|
||||
|
||||
const defaultClass = props.defaultClass ?? 'm-2 flex gap-2 px-2'
|
||||
const additionalClass = props.class ?? ''
|
||||
const btnClass = props.smallMode ? '[&_button]:w-7 [&_button]:h-7 [&_button]:2xl:w-8 [&_button]:2xl:h-9 [&_button]:!p-0' : ''
|
||||
|
||||
type ClickType = 'back' | 'submit'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: ClickType): void
|
||||
@@ -11,26 +21,18 @@ function onClick(type: ClickType) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="m-2 flex gap-2 px-2">
|
||||
<Button
|
||||
class="bg-gray-400"
|
||||
@click="onClick('cancel')"
|
||||
>
|
||||
<Icon
|
||||
name="i-lucide-arrow-left"
|
||||
class="me-2 align-middle"
|
||||
/>
|
||||
Back
|
||||
</Button>
|
||||
<Button
|
||||
class="bg-primary"
|
||||
@click="onClick('submit')"
|
||||
>
|
||||
<Icon
|
||||
name="i-lucide-check"
|
||||
class="me-2 align-middle"
|
||||
/>
|
||||
Submit
|
||||
</Button>
|
||||
<div :class="`${defaultClass} ${additionalClass} ${btnClass}`">
|
||||
<div>
|
||||
<Button variant="ghost"@click="onClick('back')" >
|
||||
<Icon name="i-lucide-arrow-left" class="" />
|
||||
Back
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button @click="onClick('submit')">
|
||||
<Icon name="i-lucide-check" class="" />
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
smallMode?: boolean
|
||||
defaultClass?: string
|
||||
class?: string
|
||||
}>()
|
||||
|
||||
const defaultClass = props.defaultClass ?? 'm-2 flex gap-2 px-2'
|
||||
const additionalClass = props.class ?? ''
|
||||
const btnClass = props.smallMode ? '[&_button]:w-7 [&_button]:h-7 [&_button]:2xl:w-8 [&_button]:2xl:h-9 [&_button]:!p-0' : ''
|
||||
|
||||
type ClickType = 'cancel' | 'edit' | 'submit'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: ClickType): void
|
||||
}>()
|
||||
|
||||
function onClick(type: ClickType) {
|
||||
emit('click', type)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="`${defaultClass} ${additionalClass} ${btnClass}`">
|
||||
<div>
|
||||
<Button
|
||||
variant="destructive"
|
||||
type="button"
|
||||
@click="onClick('cancel')"
|
||||
>
|
||||
<Icon name="i-lucide-x" />
|
||||
{{ smallMode ? '' : 'Batal' }}
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
variant="secondary"
|
||||
type="button"
|
||||
@click="onClick('edit')"
|
||||
>
|
||||
<Icon name="i-lucide-pencil" />
|
||||
{{ smallMode ? '' : 'Edit' }}
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
type="button"
|
||||
@click="onClick('submit')"
|
||||
>
|
||||
<Icon name="i-lucide-check" />
|
||||
{{ smallMode ? '' : 'Submit' }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
smallMode?: boolean
|
||||
defaultClass?: string
|
||||
class?: string
|
||||
}>()
|
||||
|
||||
const defaultClass = props.defaultClass ?? 'm-2 flex gap-2 px-2'
|
||||
const additionalClass = props.class ?? ''
|
||||
const btnClass = props.smallMode ? '[&_button]:w-7 [&_button]:h-7 [&_button]:2xl:w-8 [&_button]:2xl:h-9 [&_button]:!p-0' : ''
|
||||
|
||||
type ClickType = 'cancel' | 'save'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: ClickType): void
|
||||
}>()
|
||||
|
||||
function onClick(type: ClickType) {
|
||||
emit('click', type)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="`${defaultClass} ${additionalClass} ${btnClass}`">
|
||||
<div>
|
||||
<Button variant="ghost" type="button" @click="onClick('cancel')">
|
||||
<Icon name="i-lucide-x" />
|
||||
Batal
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button type="button" @click="onClick('save')">
|
||||
<Icon name="i-lucide-check" />
|
||||
Simpan
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
smallMode?: boolean
|
||||
defaultClass?: string
|
||||
class?: string
|
||||
}>()
|
||||
|
||||
const defaultClass = props.defaultClass ?? 'm-2 flex gap-2 px-2'
|
||||
const additionalClass = props.class ?? ''
|
||||
const btnClass = props.smallMode ? '[&_button]:w-7 [&_button]:h-7 [&_button]:2xl:w-8 [&_button]:2xl:h-9 [&_button]:!p-0' : ''
|
||||
|
||||
type ClickType = 'close' | 'save'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', type: ClickType): void
|
||||
}>()
|
||||
|
||||
function onClick(type: ClickType) {
|
||||
emit('click', type)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="`${defaultClass} ${additionalClass} ${btnClass}`">
|
||||
<div>
|
||||
<Button variant="ghost" type="button" @click="onClick('close')">
|
||||
<Icon name="i-lucide-x" />
|
||||
Tutup
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button type="button" @click="onClick('save')">
|
||||
<Icon name="i-lucide-check" />
|
||||
Simpan
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -12,7 +12,7 @@ export const buttonVariants = cva(
|
||||
destructive:
|
||||
'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
|
||||
outline:
|
||||
'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
|
||||
'border border-slate-300 dark:border-slate-600 bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
|
||||
secondary:
|
||||
'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
|
||||
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||
|
||||
@@ -34,7 +34,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
v-bind="forwarded"
|
||||
:class="
|
||||
cn(
|
||||
'fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-5 2xl:p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
|
||||
'fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-2 2x:gap-3 border bg-background p-5 2xl:p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
|
||||
props.class,
|
||||
)"
|
||||
>
|
||||
|
||||
@@ -19,7 +19,7 @@ const forwardedProps = useForwardProps(delegatedProps)
|
||||
<template>
|
||||
<DialogDescription
|
||||
v-bind="forwardedProps"
|
||||
:class="cn('text-sm text-muted-foreground', props.class)"
|
||||
:class="cn('text-sm', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</DialogDescription>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
export function useQueryParam(key: string = 'mode') {
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const getQueryParam = (key: string) => {
|
||||
return route.query[key]
|
||||
}
|
||||
|
||||
const setQueryParam = (key: string, val: string) => {
|
||||
router.replace({
|
||||
path: route.path,
|
||||
query: {
|
||||
...route.query,
|
||||
[key]: val === 'list' ? undefined : val,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const setQueryParams = (keyVal: Record<string, string>) => {
|
||||
router.replace({
|
||||
path: route.path,
|
||||
query: {
|
||||
...route.query,
|
||||
...keyVal,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return { getQueryParam, setQueryParam, setQueryParams}
|
||||
}
|
||||
@@ -9,13 +9,12 @@ export function useRBAC() {
|
||||
|
||||
const checkRole = (roleAccess: RoleAccess, _userRoles?: string[]): boolean => {
|
||||
const roles = authStore.userRole
|
||||
return roles.some((role: string) => role in roleAccess)
|
||||
return roles.some((role: string) => (role in roleAccess) || role === 'system') // system by-passes this check
|
||||
}
|
||||
|
||||
const checkPermission = (roleAccess: RoleAccess, permission: Permission, _userRoles?: string[]): boolean => {
|
||||
const roles = authStore.userRole
|
||||
// const roles = ['admisi']
|
||||
return roles.some((role: string) => roleAccess[role]?.includes(permission))
|
||||
return roles.some((role: string) => roleAccess[role]?.includes(permission) || role === 'system') // system by-passes this check
|
||||
}
|
||||
|
||||
const getUserPermissions = (roleAccess: RoleAccess, _userRoles?: string[]): Permission[] => {
|
||||
@@ -23,7 +22,7 @@ export function useRBAC() {
|
||||
// const roles = ['admisi']
|
||||
const permissions = new Set<Permission>()
|
||||
|
||||
roles.forEach((role) => {
|
||||
roles.forEach((role: string) => {
|
||||
if (roleAccess[role]) {
|
||||
roleAccess[role].forEach((permission) => permissions.add(permission))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Handlers
|
||||
import { genCrudHandler } from '~/handlers/_handler'
|
||||
|
||||
// Services
|
||||
import { create, update, remove } from '~/services/soapi-early.service'
|
||||
|
||||
export const {
|
||||
recId,
|
||||
recAction,
|
||||
recItem,
|
||||
isReadonly,
|
||||
isProcessing,
|
||||
isFormEntryDialogOpen,
|
||||
isRecordConfirmationOpen,
|
||||
onResetState,
|
||||
handleActionSave,
|
||||
handleActionEdit,
|
||||
handleActionRemove,
|
||||
handleCancelForm,
|
||||
} = genCrudHandler({
|
||||
create,
|
||||
update,
|
||||
remove,
|
||||
})
|
||||
+19
-2
@@ -66,9 +66,26 @@ export const timeUnitCodes: Record<string, string> = {
|
||||
year: 'Tahun',
|
||||
}
|
||||
|
||||
export const bigTimeUnitCodes: Record<string, string> = {
|
||||
day: 'Hari',
|
||||
week: 'Minggu',
|
||||
month: 'Bulan',
|
||||
year: 'Tahun',
|
||||
}
|
||||
|
||||
export const dischargeMethodCodes: Record<string, string> = {
|
||||
home: 'Home',
|
||||
'home-request': 'Home Request',
|
||||
home: "Pulang",
|
||||
"home-request": "Pulang Atas Permintaan Sendiri",
|
||||
"consul-back": "Konsultasi Balik / Lanjutan",
|
||||
"consul-poly": "Konsultasi Poliklinik Lain",
|
||||
"consul-executive": "Konsultasi Antar Dokter Eksekutif",
|
||||
"consul-ch-day": "Konsultasi Hari Lain",
|
||||
emergency: "Rujuk IGD",
|
||||
"emergency-covid": "Rujuk IGD Covid",
|
||||
inpatient: "Rujuk Rawat Inap",
|
||||
external: "Rujuk Faskes Lain",
|
||||
death: "Meninggal",
|
||||
"death-on-arrival": "Meninggal Saat Tiba"
|
||||
}
|
||||
|
||||
export const genderCodes: Record<string, string> = {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export interface DeathCause {
|
||||
id: bigint;
|
||||
encounter_id: bigint;
|
||||
value: any; // json mapped to 'any' type
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { DeathCause } from "./death-cause"
|
||||
import { type Doctor, genDoctor } from "./doctor"
|
||||
import { genEmployee, type Employee } from "./employee"
|
||||
import type { InternalReference } from "./internal-reference"
|
||||
import { type Patient, genPatient } from "./patient"
|
||||
import type { Specialist } from "./specialist"
|
||||
import type { Subspecialist } from "./subspecialist"
|
||||
@@ -29,8 +31,11 @@ export interface Encounter {
|
||||
earlyEducation?: string
|
||||
medicalDischargeEducation: string
|
||||
admDischargeEducation?: string
|
||||
dischargeMethod_code?: string
|
||||
discharge_method_code?: string
|
||||
discharge_reason?: string
|
||||
discharge_date?: string
|
||||
internalReferences?: InternalReference[]
|
||||
deathCause?: DeathCause
|
||||
status_code: string
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
export interface InternalReference {
|
||||
id: number;
|
||||
encounter_id: number;
|
||||
unit_id: number; // smallint mapped to number
|
||||
doctor_id: number; // int mapped to number
|
||||
}
|
||||
|
||||
export interface CreateDto {
|
||||
encounter_id: number;
|
||||
unit_id: number; // smallint mapped to number
|
||||
doctor_id: number; // int mapped to number
|
||||
}
|
||||
+173
-1
@@ -1,4 +1,4 @@
|
||||
import { type Base, genBase } from "./_base"
|
||||
import { type Base, genBase } from './_base'
|
||||
|
||||
export interface Soapi extends Base {
|
||||
encounter_id: number
|
||||
@@ -16,3 +16,175 @@ export function genSoapi(): Soapi {
|
||||
value: '',
|
||||
}
|
||||
}
|
||||
|
||||
export interface DiagnosisCode {
|
||||
code: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface AssessmentSection {
|
||||
note: string
|
||||
codes: DiagnosisCode[]
|
||||
}
|
||||
|
||||
export interface Subject {
|
||||
note: string
|
||||
'prim-compl': string
|
||||
'sec-compl': string
|
||||
'pri-complain': string
|
||||
'sec-complain': string
|
||||
'cur-disea-hist': string
|
||||
'pas-disea-hist': string
|
||||
'fam-disea-hist': string
|
||||
'alg-hist': string
|
||||
'alg-react': string
|
||||
'med-hist': string
|
||||
'blood-type': string
|
||||
}
|
||||
|
||||
export interface ObjectSection {
|
||||
note: string
|
||||
'consc-level': string
|
||||
'consc-level-det': string
|
||||
'syst-bp': string
|
||||
'diast-bp': string
|
||||
pulse: string
|
||||
'resp-rate': string
|
||||
'hear-rt': string
|
||||
'neuro-cranialis': string
|
||||
sensoris: string
|
||||
'reflect-fisio': string
|
||||
'reflect-pato': string
|
||||
'autonom-neuron': string
|
||||
'neck-rom': string
|
||||
'body-rom': string
|
||||
'aga-rom': string
|
||||
'agb-rom': string
|
||||
'neck-mmt': string
|
||||
'body-mmt': string
|
||||
'aga-mmt': string
|
||||
'agb-mmt': string
|
||||
localis: string
|
||||
'medical-trouble': string
|
||||
'rehab-medic-trouble': string
|
||||
temp: string
|
||||
spo2: string
|
||||
weight: string
|
||||
height: string
|
||||
'head-to-toe': Record<string, string>
|
||||
}
|
||||
|
||||
export interface Assessment {
|
||||
'early-diag': AssessmentSection
|
||||
'late-diag': AssessmentSection
|
||||
'sec-diag': AssessmentSection
|
||||
}
|
||||
|
||||
export interface InstructionCodeGroup {
|
||||
note: string
|
||||
codes: DiagnosisCode[]
|
||||
}
|
||||
|
||||
export interface Instruction {
|
||||
detail: string
|
||||
'medical-act': InstructionCodeGroup
|
||||
'supporting-exam': DiagnosisCode[]
|
||||
therapy: string
|
||||
medication: DiagnosisCode[]
|
||||
material: DiagnosisCode[]
|
||||
'rehab-program': string
|
||||
'physic-modal': string
|
||||
exercise: string
|
||||
'ortes-protesa': string
|
||||
education: string
|
||||
other: string
|
||||
}
|
||||
|
||||
export interface Soap extends Base {
|
||||
subject: Subject
|
||||
object: ObjectSection
|
||||
assessment: Assessment
|
||||
plan: string
|
||||
instruction: Instruction
|
||||
}
|
||||
|
||||
// ---- Generators ----
|
||||
|
||||
function genDiagnosisCode(): DiagnosisCode {
|
||||
return { code: '', name: '' }
|
||||
}
|
||||
|
||||
function genAssessmentSection(): AssessmentSection {
|
||||
return { note: '', codes: [genDiagnosisCode()] }
|
||||
}
|
||||
|
||||
export function genSoap(): Soap {
|
||||
return {
|
||||
...genBase(),
|
||||
subject: {
|
||||
note: '',
|
||||
'prim-compl': '',
|
||||
'sec-compl': '',
|
||||
'pri-complain': '',
|
||||
'sec-complain': '',
|
||||
'cur-disea-hist': '',
|
||||
'pas-disea-hist': '',
|
||||
'fam-disea-hist': '',
|
||||
'alg-hist': '',
|
||||
'alg-react': '',
|
||||
'med-hist': '',
|
||||
'blood-type': '',
|
||||
},
|
||||
object: {
|
||||
note: '',
|
||||
'consc-level': '',
|
||||
'consc-level-det': '',
|
||||
'syst-bp': '',
|
||||
'diast-bp': '',
|
||||
pulse: '',
|
||||
'resp-rate': '',
|
||||
'hear-rt': '',
|
||||
'neuro-cranialis': '',
|
||||
sensoris: '',
|
||||
'reflect-fisio': '',
|
||||
'reflect-pato': '',
|
||||
'autonom-neuron': '',
|
||||
'neck-rom': '',
|
||||
'body-rom': '',
|
||||
'aga-rom': '',
|
||||
'agb-rom': '',
|
||||
'neck-mmt': '',
|
||||
'body-mmt': '',
|
||||
'aga-mmt': '',
|
||||
'agb-mmt': '',
|
||||
localis: '',
|
||||
'medical-trouble': '',
|
||||
'rehab-medic-trouble': '',
|
||||
temp: '',
|
||||
spo2: '',
|
||||
weight: '',
|
||||
height: '',
|
||||
'head-to-toe': {},
|
||||
},
|
||||
assessment: {
|
||||
'early-diag': genAssessmentSection(),
|
||||
'late-diag': genAssessmentSection(),
|
||||
'sec-diag': genAssessmentSection(),
|
||||
},
|
||||
plan: '',
|
||||
instruction: {
|
||||
detail: '',
|
||||
'medical-act': { note: '', codes: [genDiagnosisCode()] },
|
||||
'supporting-exam': [genDiagnosisCode()],
|
||||
therapy: '',
|
||||
medication: [genDiagnosisCode()],
|
||||
material: [genDiagnosisCode()],
|
||||
'rehab-program': '',
|
||||
'physic-modal': '',
|
||||
exercise: '',
|
||||
'ortes-protesa': '',
|
||||
education: '',
|
||||
other: '',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
||||
|
||||
definePageMeta({
|
||||
middleware: ['rbac'],
|
||||
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||
roles: ['system', 'doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||
title: 'Daftar Kunjungan',
|
||||
contentFrame: 'cf-full-width',
|
||||
})
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { z } from 'zod'
|
||||
import { InternalReferenceSchema } from './internal-reference.schema'
|
||||
|
||||
// Check In
|
||||
const CheckInSchema = z.object({
|
||||
// registeredAt: z.string({ required_error: 'Tanggal masuk harus diisi' }),
|
||||
responsible_doctor_id: z.number({ required_error: 'Dokter harus diisi' }).gt(0, 'Dokter harus diisi'),
|
||||
adm_employee_id: z.number({ required_error: 'PJA harus diisi' }).gt(0, 'PJA harus diisi'),
|
||||
})
|
||||
type CheckInFormData = z.infer<typeof CheckInSchema>
|
||||
|
||||
// Checkout
|
||||
const CheckOutSchema = z.object({
|
||||
discharge_method_code: z.string({ required_error: 'Metode pulang harus diisi' }),
|
||||
discharge_date: z.string({ required_error: 'Tanggal pulang harus diisi' }),
|
||||
})
|
||||
type CheckOutFormData = z.infer<typeof CheckOutSchema>
|
||||
|
||||
// CheckoutDeath
|
||||
const CheckOutDeathSchema = z.object({
|
||||
discharge_method_code: z.string({ required_error: 'Metode pulang harus diisi' }),
|
||||
discharge_date: z.string({ required_error: 'Tanggal pulang harus diisi' }),
|
||||
death_cause: z.array(z.string()).nonempty(),
|
||||
})
|
||||
type CheckOutDeathFormData = z.infer<typeof CheckOutDeathSchema>
|
||||
|
||||
// CheckoutDeath
|
||||
const CheckOutInternalReferenceSchema = z.object({
|
||||
discharge_method_code: z.string({ required_error: 'Metode pulang harus diisi' }),
|
||||
discharge_date: z.string({ required_error: 'Tanggal pulang harus diisi' }),
|
||||
internalReferences: z.array(InternalReferenceSchema).nonempty(),
|
||||
})
|
||||
type CheckOutInternalReferenceFormData = z.infer<typeof CheckOutInternalReferenceSchema>
|
||||
|
||||
|
||||
// Exports
|
||||
export {
|
||||
CheckInSchema,
|
||||
CheckOutSchema,
|
||||
CheckOutDeathSchema,
|
||||
CheckOutInternalReferenceSchema
|
||||
}
|
||||
export type {
|
||||
CheckInFormData,
|
||||
CheckOutFormData,
|
||||
CheckOutDeathFormData,
|
||||
CheckOutInternalReferenceFormData
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { z } from 'zod'
|
||||
import type { InternalReference } from '~/models/internal-reference'
|
||||
|
||||
const InternalReferenceSchema = z.object({
|
||||
'unit_id': z.number({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'),
|
||||
'doctor_id': z.number({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'),
|
||||
})
|
||||
|
||||
type InternalReferenceFormData = z.infer<typeof InternalReferenceSchema> & Partial<InternalReference>
|
||||
|
||||
export { InternalReferenceSchema }
|
||||
export type { InternalReferenceFormData }
|
||||
@@ -0,0 +1,190 @@
|
||||
import { z } from 'zod'
|
||||
import type { Soap } from '~/models/soapi'
|
||||
|
||||
const DiagnosisCodeSchema = z.object({
|
||||
code: z.string().default(''),
|
||||
name: z.string().default(''),
|
||||
})
|
||||
|
||||
const AssessmentSectionSchema = z.object({
|
||||
note: z.string().default(''),
|
||||
codes: z.array(DiagnosisCodeSchema).default([]),
|
||||
})
|
||||
|
||||
export const EarlySchema = z.object({
|
||||
'prim-compl': z.string({ required_error: 'Keluhan utama harus diisi' }).min(1, 'Keluhan utama harus diisi'),
|
||||
'cur-disea-hist': z.string().default(''),
|
||||
'syst-bp': z.string().default(''),
|
||||
'diast-bp': z.string().default(''),
|
||||
pulse: z.string().default(''),
|
||||
'resp-rate': z.string().default(''),
|
||||
temp: z.string().default(''),
|
||||
weight: z.string().default(''),
|
||||
height: z.string().default(''),
|
||||
'reflect-fisio': z.string().default(''),
|
||||
'reflect-pato': z.string().default(''),
|
||||
'autonom-neuron': z.string().default(''),
|
||||
'medical-act': z.string().default(''),
|
||||
therapy: z.string().default(''),
|
||||
})
|
||||
|
||||
export const EarlyRehabSchema = z.object({
|
||||
'prim-compl': z.string({ required_error: 'Keluhan utama harus diisi' }).min(1, 'Keluhan utama harus diisi'),
|
||||
'medical-plan': z.string().default(''),
|
||||
'diagnosis-medical': z.string().default(''),
|
||||
'rehab-trouble': z.string().default(''),
|
||||
'medical-trouble': z.string().default(''),
|
||||
'physic-modal': z.string().default(''),
|
||||
exercise: z.string().default(''),
|
||||
'ortho-pesa': z.string().default(''),
|
||||
education: z.string().default(''),
|
||||
other: z.string().default(''),
|
||||
cranialis: z.string().default(''),
|
||||
sensoris: z.string().default(''),
|
||||
'reflect-fisio': z.string().default(''),
|
||||
'reflect-pato': z.string().default(''),
|
||||
otonom: z.string().default(''),
|
||||
localis: z.string().default(''),
|
||||
'medical-trial': z.string().default(''),
|
||||
therapy: z.string().default(''),
|
||||
'syst-bp': z.string().default(''),
|
||||
'diast-bp': z.string().default(''),
|
||||
pulse: z.string().default(''),
|
||||
gcs: z.string().default(''),
|
||||
'respiratory-rate': z.string().default(''),
|
||||
temp: z.string().default(''),
|
||||
weight: z.string().default(''),
|
||||
height: z.string().default(''),
|
||||
ambulance: z.string().default(''),
|
||||
gait: z.string().default(''),
|
||||
'neck-rom': z.string().default(''),
|
||||
'body-rom': z.string().default(''),
|
||||
'aga-rom': z.string().default(''),
|
||||
'agb-rom': z.string().default(''),
|
||||
'neck-mmt': z.string().default(''),
|
||||
'body-mmt': z.string().default(''),
|
||||
'aga-mmt': z.string().default(''),
|
||||
'agb-mmt': z.string().default(''),
|
||||
})
|
||||
|
||||
export const FunctionSoapiSchema = z.object({
|
||||
'prim-compl': z.string({ required_error: 'Keluhan utama harus diisi' }).min(1, 'Keluhan utama harus diisi'),
|
||||
'past-disease': z.string().default(''),
|
||||
'current-disease': z.string().default(''),
|
||||
gcs: z.string().default(''),
|
||||
'respiratory-rate': z.string().default(''),
|
||||
'respiratory-rate-type': z.string().default(''),
|
||||
pulse: z.string().default(''),
|
||||
'pulse-type': z.string().default(''),
|
||||
'right-arm-bp': z.string().default(''),
|
||||
'left-arm-bp': z.string().default(''),
|
||||
'axillary-temp': z.string().default(''),
|
||||
'rektal-temp': z.string().default(''),
|
||||
skin: z.string().default(''),
|
||||
head: z.string().default(''),
|
||||
ear: z.string().default(''),
|
||||
nose: z.string().default(''),
|
||||
'oral-cavity': z.string().default(''),
|
||||
eye: z.string().default(''),
|
||||
'other-body-part': z.string().default(''),
|
||||
neck: z.string().default(''),
|
||||
thyroid: z.string().default(''),
|
||||
thorax: z.string().default(''),
|
||||
heart: z.string().default(''),
|
||||
lung: z.string().default(''),
|
||||
abdomen: z.string().default(''),
|
||||
heart2: z.string().default(''),
|
||||
lien: z.string().default(''),
|
||||
back: z.string().default(''),
|
||||
extremity: z.string().default(''),
|
||||
gender: z.string().default(''),
|
||||
rectum: z.string().default(''),
|
||||
'system-syaraf': z.string().default(''),
|
||||
'nervous-system': z.string().default(''),
|
||||
'cardio-respiratory': z.string().default(''),
|
||||
imaging: z.string().default(''),
|
||||
laboratory: z.string().default(''),
|
||||
})
|
||||
|
||||
export const SubjectSchema = z.object({
|
||||
note: z.string().default(''),
|
||||
'prim-compl': z.string({ required_error: 'Keluhan utama harus diisi' }).min(1, 'Keluhan utama harus diisi'),
|
||||
'sec-compl': z.string().default(''),
|
||||
'pri-complain': z.string().default(''),
|
||||
'sec-complain': z.string().default(''),
|
||||
'cur-disea-hist': z.string().default(''),
|
||||
'pas-disea-hist': z.string().default(''),
|
||||
'fam-disea-hist': z.string().default(''),
|
||||
'alg-hist': z.string().default(''),
|
||||
'alg-react': z.string().default(''),
|
||||
'med-hist': z.string().default(''),
|
||||
'blood-type': z.string().default(''),
|
||||
})
|
||||
|
||||
export const ObjectSchema = z.object({
|
||||
note: z.string().default(''),
|
||||
'consc-level': z.string().default(''),
|
||||
'consc-level-det': z.string().default(''),
|
||||
'syst-bp': z.string().default(''),
|
||||
'diast-bp': z.string().default(''),
|
||||
pulse: z.string().default(''),
|
||||
'resp-rate': z.string().default(''),
|
||||
'hear-rt': z.string().default(''),
|
||||
'neuro-cranialis': z.string().default(''),
|
||||
sensoris: z.string().default(''),
|
||||
'reflect-fisio': z.string().default(''),
|
||||
'reflect-pato': z.string().default(''),
|
||||
'autonom-neuron': z.string().default(''),
|
||||
'neck-rom': z.string().default(''),
|
||||
'body-rom': z.string().default(''),
|
||||
'aga-rom': z.string().default(''),
|
||||
'agb-rom': z.string().default(''),
|
||||
'neck-mmt': z.string().default(''),
|
||||
'body-mmt': z.string().default(''),
|
||||
'aga-mmt': z.string().default(''),
|
||||
'agb-mmt': z.string().default(''),
|
||||
localis: z.string().default(''),
|
||||
'medical-trouble': z.string().default(''),
|
||||
'rehab-medic-trouble': z.string().default(''),
|
||||
temp: z.string().default(''),
|
||||
spo2: z.string().default(''),
|
||||
weight: z.string().default(''),
|
||||
height: z.string().default(''),
|
||||
'head-to-toe': z.record(z.string()).default({}),
|
||||
})
|
||||
|
||||
const AssessmentSchema = z.object({
|
||||
'early-diag': AssessmentSectionSchema,
|
||||
'late-diag': AssessmentSectionSchema,
|
||||
'sec-diag': AssessmentSectionSchema,
|
||||
})
|
||||
|
||||
const InstructionCodeGroupSchema = z.object({
|
||||
note: z.string().default(''),
|
||||
codes: z.array(DiagnosisCodeSchema).default([]),
|
||||
})
|
||||
|
||||
const InstructionSchema = z.object({
|
||||
detail: z.string().default(''),
|
||||
'medical-act': InstructionCodeGroupSchema,
|
||||
'supporting-exam': z.array(DiagnosisCodeSchema).default([]),
|
||||
therapy: z.string().default(''),
|
||||
medication: z.array(DiagnosisCodeSchema).default([]),
|
||||
material: z.array(DiagnosisCodeSchema).default([]),
|
||||
'rehab-program': z.string().default(''),
|
||||
'physic-modal': z.string().default(''),
|
||||
exercise: z.string().default(''),
|
||||
'ortes-protesa': z.string().default(''),
|
||||
education: z.string().default(''),
|
||||
other: z.string().default(''),
|
||||
})
|
||||
|
||||
export const SoapSchema = z.object({
|
||||
subject: SubjectSchema,
|
||||
object: ObjectSchema,
|
||||
assessment: AssessmentSchema,
|
||||
plan: z.string().default(''),
|
||||
instruction: InstructionSchema,
|
||||
})
|
||||
|
||||
export type SoapiFormData = z.infer<typeof SoapSchema> & Partial<Soap>
|
||||
@@ -33,7 +33,7 @@ export async function getValueLabelList(params: any = null): Promise<{ value: st
|
||||
if (result.success) {
|
||||
const resultData = result.body?.data || []
|
||||
data = resultData.map((item: Doctor) => ({
|
||||
value: item.id ? String(item.id) : item.id,
|
||||
value: item.id ? String(item.id) : '',
|
||||
label: item.employee?.person?.name || '',
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ export async function getValueLabelList(params: any = null): Promise<{ value: st
|
||||
const resultData = result.body?.data || []
|
||||
data = resultData.map((item: any) => ({
|
||||
value: item.id ? Number(item.id) : item.code,
|
||||
label: item.name,
|
||||
label: item.person.name,
|
||||
}))
|
||||
}
|
||||
return data
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Base
|
||||
import type { CheckInFormData } from '~/schemas/encounter.schema'
|
||||
import * as base from './_crud-base'
|
||||
|
||||
// Constants
|
||||
@@ -46,3 +47,16 @@ export function getValueLabelListConstants() {
|
||||
.filter(([key]) => allowed.includes(key))
|
||||
.map(([key, value]) => ({ value: key, label: value }))
|
||||
}
|
||||
|
||||
export async function checkIn(id: number, data: CheckInFormData) {
|
||||
try {
|
||||
const resp = await xfetch(`${path}/${id}/check-in`, 'PATCH', data)
|
||||
const result: any = {}
|
||||
result.success = resp.success
|
||||
result.body = (resp.body as Record<string, any>) || {}
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error(`Error putting ${name}:`, error)
|
||||
throw new Error(`Failed to put ${name}`)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Base
|
||||
import * as base from './_crud-base'
|
||||
|
||||
// Types
|
||||
import type { Soapi } from '~/models/soapi'
|
||||
|
||||
const path = '/api/v1/soapi'
|
||||
const name = 'soapi'
|
||||
|
||||
export function create(data: any) {
|
||||
return base.create(path, data, name)
|
||||
}
|
||||
|
||||
export function getList(params: any = null) {
|
||||
return base.getList(path, params, name)
|
||||
}
|
||||
|
||||
export function getDetail(id: number | string) {
|
||||
return base.getDetail(path, id, name)
|
||||
}
|
||||
|
||||
export function update(id: number | string, data: any) {
|
||||
return base.update(path, id, data, name)
|
||||
}
|
||||
|
||||
export function remove(id: number | string) {
|
||||
return base.remove(path, id, name)
|
||||
}
|
||||
+8
-2
@@ -5,7 +5,13 @@ export const useUserStore = defineStore(
|
||||
// const token = useCookie('authentication')
|
||||
|
||||
const isAuthenticated = computed(() => !!user.value)
|
||||
// const userRole = computed(() => user.value?.user_position_code || '')
|
||||
const userRole = computed(() => {
|
||||
const roles = user.value?.roles || []
|
||||
return roles.map((input: string) => {
|
||||
const parts = input.split('-')
|
||||
return parts.length > 1 ? parts[1]: parts[0]
|
||||
})
|
||||
})
|
||||
|
||||
const login = async (userData: any) => {
|
||||
user.value = userData
|
||||
@@ -18,7 +24,7 @@ export const useUserStore = defineStore(
|
||||
return {
|
||||
user,
|
||||
isAuthenticated,
|
||||
userRole: ['doctor'],
|
||||
userRole,
|
||||
login,
|
||||
logout,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user