feat(medical-action-src): add type code selection with strict typing
- Add medicalActionTypeCode constants and type definition - Update MedicalActionSrc interface to use strict type for type_code - Implement select dropdown for type code in entry form - Enable type code validation in schema
This commit is contained in:
No files matched your search
@@ -5,14 +5,17 @@ import Cell from '~/components/pub/my-ui/doc-entry/cell.vue'
|
|||||||
import Field from '~/components/pub/my-ui/doc-entry/field.vue'
|
import Field from '~/components/pub/my-ui/doc-entry/field.vue'
|
||||||
import Label from '~/components/pub/my-ui/doc-entry/label.vue'
|
import Label from '~/components/pub/my-ui/doc-entry/label.vue'
|
||||||
import Button from '~/components/pub/ui/button/Button.vue'
|
import Button from '~/components/pub/ui/button/Button.vue'
|
||||||
|
import Select from '~/components/pub/my-ui/form/select.vue'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import type { MedicalActionSrcFormData } from '~/schemas/medical-action-src.schema'
|
import type { MedicalActionSrcFormData } from '~/schemas/medical-action-src.schema'
|
||||||
|
import { medicalActionTypeCode } from '~/lib/constants'
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
import type z from 'zod'
|
import type z from 'zod'
|
||||||
import { useForm } from 'vee-validate'
|
import { useForm } from 'vee-validate'
|
||||||
import { toTypedSchema } from '@vee-validate/zod'
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
|
import { mapToComboboxOptList } from '~/lib/utils'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
schema: z.ZodSchema<any>
|
schema: z.ZodSchema<any>
|
||||||
@@ -24,6 +27,8 @@ interface Props {
|
|||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
const isLoading = props.isLoading !== undefined ? props.isLoading : false
|
const isLoading = props.isLoading !== undefined ? props.isLoading : false
|
||||||
const isReadonly = props.isReadonly !== undefined ? props.isReadonly : false
|
const isReadonly = props.isReadonly !== undefined ? props.isReadonly : false
|
||||||
|
const medicalActionTypeOptions = mapToComboboxOptList(medicalActionTypeCode)
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
submit: [values: MedicalActionSrcFormData, resetForm: () => void]
|
submit: [values: MedicalActionSrcFormData, resetForm: () => void]
|
||||||
cancel: [resetForm: () => void]
|
cancel: [resetForm: () => void]
|
||||||
@@ -34,26 +39,31 @@ const { defineField, errors, meta } = useForm({
|
|||||||
initialValues: {
|
initialValues: {
|
||||||
code: '',
|
code: '',
|
||||||
name: '',
|
name: '',
|
||||||
|
type_code: '',
|
||||||
} as Partial<MedicalActionSrcFormData>,
|
} as Partial<MedicalActionSrcFormData>,
|
||||||
})
|
})
|
||||||
|
|
||||||
const [code, codeAttrs] = defineField('code')
|
const [code, codeAttrs] = defineField('code')
|
||||||
const [name, nameAttrs] = defineField('name')
|
const [name, nameAttrs] = defineField('name')
|
||||||
|
const [typeCode, typeCodeAttrs] = defineField('type_code')
|
||||||
|
|
||||||
if (props.values) {
|
if (props.values) {
|
||||||
if (props.values.code !== undefined) code.value = props.values.code
|
if (props.values.code !== undefined) code.value = props.values.code
|
||||||
if (props.values.name !== undefined) name.value = props.values.name
|
if (props.values.name !== undefined) name.value = props.values.name
|
||||||
|
if (props.values.type_code !== undefined) typeCode.value = props.values.type_code
|
||||||
}
|
}
|
||||||
|
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
code.value = ''
|
code.value = ''
|
||||||
name.value = ''
|
name.value = ''
|
||||||
|
typeCode.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSubmitForm() {
|
function onSubmitForm() {
|
||||||
const formData: MedicalActionSrcFormData = {
|
const formData: MedicalActionSrcFormData = {
|
||||||
code: code.value || '',
|
code: code.value || '',
|
||||||
name: name.value || '',
|
name: name.value || '',
|
||||||
|
type_code: typeCode.value || '',
|
||||||
}
|
}
|
||||||
emit('submit', formData, resetForm)
|
emit('submit', formData, resetForm)
|
||||||
}
|
}
|
||||||
@@ -95,6 +105,21 @@ function onCancelForm() {
|
|||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
</Cell>
|
</Cell>
|
||||||
|
<Cell>
|
||||||
|
<Label height="compact">Type Kode</Label>
|
||||||
|
<Field :errMessage="errors.name">
|
||||||
|
<Select
|
||||||
|
id="type_code"
|
||||||
|
:is-disabled="isLoading || isReadonly"
|
||||||
|
:items="medicalActionTypeOptions"
|
||||||
|
v-bind="typeCodeAttrs"
|
||||||
|
v-model="typeCode"
|
||||||
|
placeholder="Pilih medical action type"
|
||||||
|
:preserve-order="false"
|
||||||
|
class="text-sm transition-all duration-200 focus:outline-none focus:ring-1 focus:ring-black focus:ring-offset-0"
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
</Cell>
|
||||||
</Block>
|
</Block>
|
||||||
<div class="my-2 flex justify-end gap-2 py-2">
|
<div class="my-2 flex justify-end gap-2 py-2">
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -268,3 +268,13 @@ export const infraGroupCodesKeys: Record<string, string> = Object.keys(infraGrou
|
|||||||
},
|
},
|
||||||
{} as Record<string, string>,
|
{} as Record<string, string>,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const medicalActionTypeCode: Record<string, string> = {
|
||||||
|
chemo: 'Chemo',
|
||||||
|
hemo: 'Hemo',
|
||||||
|
thalasemia: 'Thalasemia',
|
||||||
|
echocardio: 'Echocardiography',
|
||||||
|
spirometry: 'Spirometry',
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type medicalActionTypeCodeKey = keyof typeof medicalActionTypeCode
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import { type Base, genBase } from './_base'
|
import { type Base, genBase } from './_base'
|
||||||
|
import type { medicalActionTypeCodeKey } from '~/lib/constants'
|
||||||
|
|
||||||
export interface MedicalActionSrc extends Base {
|
export interface MedicalActionSrc extends Base {
|
||||||
code: string
|
code: string
|
||||||
name: string
|
name: string
|
||||||
type_code: string
|
type_code: medicalActionTypeCodeKey
|
||||||
item_id: number
|
item_id: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,10 @@ const MedicalActionSrcSchema = z.object({
|
|||||||
.string({ required_error: 'Nama harus diisi' })
|
.string({ required_error: 'Nama harus diisi' })
|
||||||
.min(1, 'Nama minimum 1 karakter')
|
.min(1, 'Nama minimum 1 karakter')
|
||||||
.max(2048, 'Nama maksimum 2048 karakter'),
|
.max(2048, 'Nama maksimum 2048 karakter'),
|
||||||
// type_code: z
|
type_code: z
|
||||||
// .string({ required_error: 'Nama (ID) harus diisi' })
|
.string({ required_error: 'Nama (ID) harus diisi' })
|
||||||
// .min(1, 'Nama (ID) minimum 1 karakter')
|
.min(1, 'Nama (ID) minimum 1 karakter')
|
||||||
// .max(2048, 'Nama (ID) maksimum 2048 karakter'),
|
.max(2048, 'Nama (ID) maksimum 2048 karakter'),
|
||||||
// item_id: z.number({ required_error: 'Item ID harus diisi' }).min(1, 'Item ID minimum 1 karakter'),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
type MedicalActionSrcFormData = z.infer<typeof MedicalActionSrcSchema> & Partial<MedicalActionSrc>
|
type MedicalActionSrcFormData = z.infer<typeof MedicalActionSrcSchema> & Partial<MedicalActionSrc>
|
||||||
|
|||||||
Reference in New Issue
Block a user