refactor(material): modify validation uom and item
This commit is contained in:
@@ -11,6 +11,7 @@ import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
interface Props {
|
||||
isLoading: boolean
|
||||
schema: z.ZodSchema<any>
|
||||
uoms: any[]
|
||||
items: any[]
|
||||
}
|
||||
|
||||
@@ -20,11 +21,13 @@ const emit = defineEmits<{
|
||||
submit: [data: any]
|
||||
}>()
|
||||
|
||||
const { handleSubmit, defineField, errors, meta } = useForm({
|
||||
const { handleSubmit, defineField, errors } = useForm({
|
||||
validationSchema: toTypedSchema(props.schema),
|
||||
initialValues: {
|
||||
code: '',
|
||||
name: '',
|
||||
uom_code: '',
|
||||
item_id: '',
|
||||
stock: 0,
|
||||
} as Partial<MaterialFormData>,
|
||||
})
|
||||
@@ -36,7 +39,6 @@ const [item, itemAttrs] = defineField('item_id')
|
||||
const [stock, stockAttrs] = defineField('stock')
|
||||
|
||||
const onSubmit = handleSubmit(async (values) => {
|
||||
console.log(errors)
|
||||
try {
|
||||
emit('submit', values)
|
||||
} catch (error) {
|
||||
@@ -77,30 +79,32 @@ const onSubmit = handleSubmit(async (values) => {
|
||||
<Label for="uom">Satuan</Label>
|
||||
<Select
|
||||
id="uom"
|
||||
:items="items"
|
||||
icon-name="i-lucide-chevron-down"
|
||||
placeholder="Pilih satuan"
|
||||
v-model="uom"
|
||||
v-bind="uomAttrs"
|
||||
:items="uoms"
|
||||
:disabled="isLoading"
|
||||
:class="{ 'border-red-500': errors.uom }"
|
||||
:class="{ 'border-red-500': errors.uom_code }"
|
||||
/>
|
||||
<span v-if="errors.uom" class="text-sm text-red-500">
|
||||
{{ errors.uom }}
|
||||
<span v-if="errors.uom_code" class="text-sm text-red-500">
|
||||
{{ errors.uom_code }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<Label for="item">Item</Label>
|
||||
<Select
|
||||
id="item"
|
||||
:items="items"
|
||||
icon-name="i-lucide-chevron-down"
|
||||
placeholder="Pilih item"
|
||||
v-model="item"
|
||||
v-bind="itemAttrs"
|
||||
:items="items"
|
||||
:disabled="isLoading"
|
||||
:class="{ 'border-red-500': errors.item }"
|
||||
:class="{ 'border-red-500': errors.item_id }"
|
||||
/>
|
||||
<span v-if="errors.item" class="text-sm text-red-500">
|
||||
{{ errors.uom }}
|
||||
<span v-if="errors.item_id" class="text-sm text-red-500">
|
||||
{{ errors.item_id }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
@@ -117,10 +121,8 @@ const onSubmit = handleSubmit(async (values) => {
|
||||
{{ errors.stock }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-end gap-2 my-2 py-2">
|
||||
<Button variant="secondary" class="w-[120px]" @click="emit('back')">
|
||||
Kembali
|
||||
</Button>
|
||||
<div class="my-2 flex justify-end gap-2 py-2">
|
||||
<Button variant="secondary" class="w-[120px]" @click="emit('back')"> Kembali </Button>
|
||||
<Button type="submit" class="w-[120px]">
|
||||
<Loader2 v-if="isLoading" class="mr-2 h-4 w-4 animate-spin" />
|
||||
Simpan
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
// types
|
||||
import { MaterialSchema, type MaterialFormData } from '~/schemas/material'
|
||||
// components
|
||||
import Action from '~/components/pub/custom-ui/nav-footer/ba-dr-su.vue'
|
||||
|
||||
const isLoading = ref(false)
|
||||
const uoms = [
|
||||
{ value: 'uom-1', label: 'Satuan 1' },
|
||||
{ value: 'uom-2', label: 'Satuan 2' },
|
||||
{ value: 'uom-3', label: 'Satuan 3' },
|
||||
]
|
||||
const items = [
|
||||
{ value: 'item1', label: 'Item 1' },
|
||||
{ value: 'item2', label: 'Item 2' },
|
||||
{ value: 'item-1', label: 'Item 1' },
|
||||
{ value: 'item-2', label: 'Item 2' },
|
||||
{ value: 'item-3', label: 'Item 3' },
|
||||
]
|
||||
|
||||
function onBack() {
|
||||
@@ -15,7 +19,7 @@ function onBack() {
|
||||
}
|
||||
|
||||
async function onSubmit(data: MaterialFormData) {
|
||||
console.log(data);
|
||||
console.log(data)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -24,5 +28,12 @@ async function onSubmit(data: MaterialFormData) {
|
||||
<Icon name="i-lucide-panel-bottom" class="me-2" />
|
||||
<span class="font-semibold">Tambah</span> Perlengkapan (BMHP)
|
||||
</div>
|
||||
<AppMaterialEntryForm :is-loading="isLoading" :schema="MaterialSchema" :items="items" @back="onBack" @submit="onSubmit" />
|
||||
<AppMaterialEntryForm
|
||||
:is-loading="isLoading"
|
||||
:schema="MaterialSchema"
|
||||
:uoms="uoms"
|
||||
:items="items"
|
||||
@back="onBack"
|
||||
@submit="onSubmit"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -19,6 +19,7 @@ interface Item {
|
||||
const props = defineProps<
|
||||
SelectRootProps & {
|
||||
items: Item[]
|
||||
iconName?: string
|
||||
placeholder?: string
|
||||
label?: string
|
||||
separator?: boolean
|
||||
@@ -31,7 +32,7 @@ const forwarded = useForwardPropsEmits(props, emits)
|
||||
|
||||
<template>
|
||||
<SelectRoot v-bind="forwarded">
|
||||
<SelectTrigger class="">
|
||||
<SelectTrigger :icon-name="iconName" class="flex justify-between items-center">
|
||||
<SelectValue :placeholder="placeholder" />
|
||||
</SelectTrigger>
|
||||
|
||||
|
||||
@@ -5,15 +5,15 @@ import { SelectIcon, SelectTrigger, useForwardProps } from 'radix-vue'
|
||||
import { computed } from 'vue'
|
||||
import { cn } from '~/lib/utils'
|
||||
|
||||
const props = defineProps<SelectTriggerProps & { class?: HTMLAttributes['class'] }>()
|
||||
const props = defineProps<SelectTriggerProps & { class?: HTMLAttributes['class'], iconName?: string }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps)
|
||||
const iconName = computed(() => props.iconName || 'i-radix-icons-caret-sort')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -28,7 +28,7 @@ const forwardedProps = useForwardProps(delegatedProps)
|
||||
>
|
||||
<slot />
|
||||
<SelectIcon as-child>
|
||||
<Icon name="i-radix-icons-caret-sort" class="h-4 w-4 opacity-50" />
|
||||
<Icon :name="iconName" class="h-4 w-4 opacity-50" />
|
||||
</SelectIcon>
|
||||
</SelectTrigger>
|
||||
</template>
|
||||
|
||||
@@ -3,9 +3,9 @@ import { z } from 'zod'
|
||||
const schema = z.object({
|
||||
code: z.string({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'),
|
||||
name: z.string({ required_error: 'Nama harus diisi' }).min(1, 'Nama minimum 1 karakter'),
|
||||
uom_code: z.string({ required_error: 'Kode unit harus diisi' }),
|
||||
item_id: z.string({ required_error: 'Tipe harus diisi' }),
|
||||
stock: z.preprocess((val) => Number(val), z.number({ invalid_type_error: 'Stok harus berupa angka' }).min(1)),
|
||||
uom_code: z.string({ required_error: 'Kode unit harus diisi' }).min(1, 'Kode unit harus diisi'),
|
||||
item_id: z.string({ required_error: 'Tipe harus diisi' }).min(1, 'Tipe harus diisi'),
|
||||
stock: z.preprocess((val) => Number(val), z.number({ invalid_type_error: 'Stok harus berupa angka' }).min(1, 'Stok harus lebih besar dari 0')),
|
||||
})
|
||||
|
||||
type formData = z.infer<typeof schema>
|
||||
|
||||
Reference in New Issue
Block a user