feat(form): add validation error styling to form components
Add error state handling and styling for form inputs and select components using vee-validate. Also adjust delete button alignment in person-relative form.
This commit is contained in:
@@ -85,14 +85,17 @@ const { title = 'Kontak Pasien', isReadonly = false } = props
|
||||
numeric-only
|
||||
:is-disabled="isReadonly"
|
||||
/>
|
||||
<DE.Cell class="flex items-end justify-start">
|
||||
<ButtonAction
|
||||
:disabled="isReadonly"
|
||||
preset="delete"
|
||||
:title="`Hapus Kontak ${idx + 1}`"
|
||||
icon-only
|
||||
@click="remove(idx)"
|
||||
/>
|
||||
<DE.Cell class="flex items-start justify-start">
|
||||
<DE.Field :class="idx === 0 ? 'mt-[30px]' : 'mt-0'">
|
||||
<ButtonAction
|
||||
v-if="idx !== 0"
|
||||
:disabled="isReadonly"
|
||||
preset="delete"
|
||||
:title="`Hapus Kontak ${idx + 1}`"
|
||||
icon-only
|
||||
@click="remove(idx)"
|
||||
/>
|
||||
</DE.Field>
|
||||
</DE.Cell>
|
||||
</DE.Block>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
import type { FormErrors } from '~/types/error'
|
||||
import { Input } from '~/components/pub/ui/input'
|
||||
import { cn } from '~/lib/utils'
|
||||
import { computed } from 'vue'
|
||||
import { useFieldError } from 'vee-validate'
|
||||
|
||||
import * as DE from '~/components/pub/my-ui/doc-entry'
|
||||
|
||||
@@ -43,6 +45,10 @@ function handleInput(event: Event) {
|
||||
target.dispatchEvent(new Event('input', { bubbles: true }))
|
||||
}
|
||||
}
|
||||
|
||||
// Get error state from vee-validate
|
||||
const fieldError = useFieldError(() => props.fieldName)
|
||||
const hasError = computed(() => !!fieldError.value)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -70,7 +76,10 @@ function handleInput(event: Event) {
|
||||
v-bind="componentField"
|
||||
:placeholder="placeholder"
|
||||
:maxlength="maxLength"
|
||||
:class="cn('focus:border-primary focus:ring-2 focus:ring-primary focus:ring-offset-0')"
|
||||
:class="cn(
|
||||
'focus:border-primary focus:ring-2 focus:ring-primary focus:ring-offset-0',
|
||||
hasError && 'border-red-500 focus:border-red-500 focus:ring-red-500'
|
||||
)"
|
||||
autocomplete="off"
|
||||
aria-autocomplete="none"
|
||||
autocorrect="off"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { SelectRoot } from 'radix-vue'
|
||||
import { watch } from 'vue'
|
||||
import { watch, computed } from 'vue'
|
||||
import { useFieldError } from 'vee-validate'
|
||||
import SelectContent from '~/components/pub/ui/select/SelectContent.vue'
|
||||
import SelectGroup from '~/components/pub/ui/select/SelectGroup.vue'
|
||||
import SelectItem from '~/components/pub/ui/select/SelectItem.vue'
|
||||
@@ -29,9 +30,14 @@ const props = defineProps<{
|
||||
isDisabled?: boolean
|
||||
autoWidth?: boolean
|
||||
autoFill?: boolean
|
||||
id?: string
|
||||
// otherPlacement sudah tidak digunakan, diganti dengan priority system di Item interface
|
||||
}>()
|
||||
|
||||
// Get error state from vee-validate if id is provided
|
||||
const fieldError = props.id ? useFieldError(() => props.id!) : ref(null)
|
||||
const hasError = computed(() => !!fieldError.value)
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: string]
|
||||
}>()
|
||||
@@ -121,6 +127,7 @@ watch(
|
||||
'cursor-not-allowed bg-gray-100 opacity-50': isDisabled,
|
||||
'bg-white text-black dark:bg-gray-800 dark:text-white': !isDisabled,
|
||||
'w-full': !autoWidth,
|
||||
'border-red-500 focus:ring-red-500': hasError,
|
||||
},
|
||||
props.class,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user