feat(cemo): layouting form
This commit is contained in:
@@ -0,0 +1,306 @@
|
||||
<script setup lang="ts">
|
||||
// Components
|
||||
import Block from '~/components/pub/my-ui/doc-entry/block.vue'
|
||||
import Cell from '~/components/pub/my-ui/doc-entry/cell.vue'
|
||||
import Field from '~/components/pub/my-ui/doc-entry/field.vue'
|
||||
import Label from '~/components/pub/my-ui/doc-entry/label.vue'
|
||||
import Button from '~/components/pub/ui/button/Button.vue'
|
||||
import Combobox from '~/components/pub/my-ui/combobox/combobox.vue'
|
||||
import Input from '~/components/pub/ui/input/Input.vue'
|
||||
import DatepickerSingle from '~/components/pub/my-ui/datepicker/datepicker-single.vue'
|
||||
|
||||
// Types
|
||||
import type { Ref } from 'vue'
|
||||
import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type'
|
||||
|
||||
// Helpers
|
||||
import type z from 'zod'
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
|
||||
interface Props {
|
||||
schema: z.ZodSchema<any>
|
||||
values?: any
|
||||
isLoading?: boolean
|
||||
isReadonly?: boolean
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const isLoading = props.isLoading !== undefined ? props.isLoading : false
|
||||
const isReadonly = props.isReadonly !== undefined ? props.isReadonly : false
|
||||
|
||||
const items = [
|
||||
{ value: 'item-1', label: 'Item 1' },
|
||||
{ value: 'item-2', label: 'Item 2' },
|
||||
{ value: 'item-3', label: 'Item 3' },
|
||||
]
|
||||
|
||||
const emit = defineEmits<{
|
||||
submit: [values: any, resetForm: () => void]
|
||||
cancel: [resetForm: () => void]
|
||||
}>()
|
||||
|
||||
const { defineField, errors, meta } = useForm({
|
||||
validationSchema: toTypedSchema(props.schema),
|
||||
initialValues: {
|
||||
namaPasien: '',
|
||||
tanggalLahir: '',
|
||||
noRM: '',
|
||||
alamat: '',
|
||||
beratBadan: '',
|
||||
tinggiBadan: '',
|
||||
diagnosa: '',
|
||||
siklus: '',
|
||||
periodeAwal: '',
|
||||
periodeAkhir: '',
|
||||
tanggalKemoterapi: '',
|
||||
dokterKRJ: '',
|
||||
},
|
||||
})
|
||||
|
||||
// Define form fields
|
||||
const [namaPasien, namaPasienAttrs] = defineField('namaPasien')
|
||||
const [tanggalLahir, tanggalLahirAttrs] = defineField('tanggalLahir')
|
||||
const [noRM, noRMAttrs] = defineField('noRM')
|
||||
const [alamat, alamatAttrs] = defineField('alamat')
|
||||
const [beratBadan, beratBadanAttrs] = defineField('beratBadan')
|
||||
const [tinggiBadan, tinggiBadanAttrs] = defineField('tinggiBadan')
|
||||
const [diagnosa, diagnosaAttrs] = defineField('diagnosa')
|
||||
const [siklus, siklusAttrs] = defineField('siklus')
|
||||
const [periodeAwal, periodeAwalAttrs] = defineField('periodeAwal')
|
||||
const [periodeAkhir, periodeAkhirAttrs] = defineField('periodeAkhir')
|
||||
const [tanggalKemoterapi, tanggalKemoterapiAttrs] = defineField('tanggalKemoterapi')
|
||||
const [dokterKRJ, dokterKRJAttrs] = defineField('dokterKRJ')
|
||||
|
||||
// Set initial values if provided
|
||||
if (props.values) {
|
||||
Object.entries(props.values).forEach(([key, value]) => {
|
||||
if (value !== undefined) {
|
||||
const field = defineField(key)[0]
|
||||
field.value = value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const resetForm = () => {
|
||||
// Object.keys(meta.value.initialValues).forEach((key) => {
|
||||
// const field = defineField(key)[0]
|
||||
// field.value = ''
|
||||
// })
|
||||
}
|
||||
|
||||
function onSubmitForm() {
|
||||
const formData = {
|
||||
namaPasien: namaPasien.value,
|
||||
tanggalLahir: tanggalLahir.value,
|
||||
noRM: noRM.value,
|
||||
alamat: alamat.value,
|
||||
beratBadan: beratBadan.value,
|
||||
tinggiBadan: tinggiBadan.value,
|
||||
diagnosa: diagnosa.value,
|
||||
siklus: siklus.value,
|
||||
periodeAwal: periodeAwal.value,
|
||||
periodeAkhir: periodeAkhir.value,
|
||||
tanggalKemoterapi: tanggalKemoterapi.value,
|
||||
dokterKRJ: dokterKRJ.value,
|
||||
}
|
||||
emit('submit', formData, resetForm)
|
||||
}
|
||||
|
||||
function onCancelForm() {
|
||||
emit('cancel', resetForm)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form @submit.prevent>
|
||||
<!-- Data Pasien Section -->
|
||||
<div class="mb-6">
|
||||
<h3 class="mb-4 text-lg font-semibold">Data Pasien</h3>
|
||||
<Block
|
||||
labelSize="thin"
|
||||
class="!mb-2.5 !pt-0 xl:!mb-3"
|
||||
>
|
||||
<Cell>
|
||||
<Label height="compact">Nama Pasien</Label>
|
||||
<Field :errMessage="errors.namaPasien">
|
||||
<Input
|
||||
v-model="namaPasien"
|
||||
v-bind="namaPasienAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Masukkan nama pasien"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label height="compact">Tanggal Lahir</Label>
|
||||
<Field :errMessage="errors.tanggalLahir">
|
||||
<DatePicker
|
||||
v-model="tanggalLahir"
|
||||
v-bind="tanggalLahirAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih tanggal lahir"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label height="compact">No. RM</Label>
|
||||
<Field :errMessage="errors.noRM">
|
||||
<Input
|
||||
v-model="noRM"
|
||||
v-bind="noRMAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Masukkan nomor RM"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label height="compact">Alamat</Label>
|
||||
<Field :errMessage="errors.alamat">
|
||||
<Input
|
||||
v-model="alamat"
|
||||
v-bind="alamatAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Masukkan alamat"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label height="compact">Berat Badan</Label>
|
||||
<Field :errMessage="errors.beratBadan">
|
||||
<Input
|
||||
v-model="beratBadan"
|
||||
v-bind="beratBadanAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Masukkan berat badan"
|
||||
type="number"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label height="compact">Tinggi Badan</Label>
|
||||
<Field :errMessage="errors.tinggiBadan">
|
||||
<Input
|
||||
v-model="tinggiBadan"
|
||||
v-bind="tinggiBadanAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Masukkan tinggi badan"
|
||||
type="number"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label height="compact">Diagnosa</Label>
|
||||
<Field :errMessage="errors.diagnosa">
|
||||
<Combobox
|
||||
id="diagnose"
|
||||
v-model="diagnosa"
|
||||
v-bind="diagnosaAttrs"
|
||||
:items="items"
|
||||
:is-disabled="isLoading || isReadonly"
|
||||
placeholder="Tentukan diagnosa pasien"
|
||||
search-placeholder="Cari diagnosa"
|
||||
empty-message="Diagnosa tidak ditemukan"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
</div>
|
||||
|
||||
<!-- Protokol Kemoterapi Section -->
|
||||
<div class="mb-6">
|
||||
<h3 class="mb-4 text-lg font-semibold">Protokol Kemoterapi</h3>
|
||||
<Block
|
||||
labelSize="thin"
|
||||
class="!mb-2.5 !pt-0 xl:!mb-3"
|
||||
>
|
||||
<Cell>
|
||||
<Label height="compact">Siklus</Label>
|
||||
<Field :errMessage="errors.siklus">
|
||||
<Input
|
||||
v-model="siklus"
|
||||
v-bind="siklusAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Masukkan siklus"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label height="compact">Periode</Label>
|
||||
<div class="flex items-center gap-4">
|
||||
<Field
|
||||
:errMessage="errors.periodeAwal"
|
||||
class="flex-1"
|
||||
>
|
||||
<DatepickerSingle
|
||||
v-model="periodeAwal"
|
||||
v-bind="periodeAwalAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Mulai Periode"
|
||||
/>
|
||||
</Field>
|
||||
<span>Sampai</span>
|
||||
<Field
|
||||
:errMessage="errors.periodeAkhir"
|
||||
class="flex-1"
|
||||
>
|
||||
<DatepickerSingle
|
||||
v-model="periodeAkhir"
|
||||
v-bind="periodeAkhirAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Akhir Periode"
|
||||
/>
|
||||
</Field>
|
||||
</div>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label height="compact">Tanggal Kemoterapi</Label>
|
||||
<Field :errMessage="errors.tanggalKemoterapi">
|
||||
<DatepickerSingle
|
||||
v-model="tanggalKemoterapi"
|
||||
v-bind="tanggalKemoterapiAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih tanggal kemoterapi"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label height="compact">Dokter Ruang Tindakan</Label>
|
||||
<Field :errMessage="errors.dokterKRJ">
|
||||
<Combobox
|
||||
id="doktor"
|
||||
v-model="dokterKRJ"
|
||||
v-bind="dokterKRJAttrs"
|
||||
:items="items"
|
||||
:is-disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih dokter"
|
||||
search-placeholder="Cari dokter"
|
||||
empty-message="Dokter tidak ditemukan"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
</div>
|
||||
|
||||
<!-- Form Actions -->
|
||||
<div class="flex justify-end gap-2 py-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
class="w-[120px]"
|
||||
@click="onCancelForm"
|
||||
>
|
||||
Kembali
|
||||
</Button>
|
||||
<Button
|
||||
v-if="!isReadonly"
|
||||
type="button"
|
||||
class="w-[120px]"
|
||||
:disabled="isLoading || !meta.valid"
|
||||
@click="onSubmitForm"
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
Reference in New Issue
Block a user