chore: Form validations

This commit is contained in:
iamsivin
2024-11-06 21:35:05 +05:30
parent 28cbdb6133
commit 91ee5fc2f0
2 changed files with 47 additions and 6 deletions
@@ -1,6 +1,9 @@
<script setup>
import { computed, reactive, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { required, email, minLength } from '@vuelidate/validators';
import { useVuelidate } from '@vuelidate/core';
import countries from 'shared/constants/countries.js';
import Input from 'dashboard/components-next/input/Input.vue';
import ComboBox from 'dashboard/components-next/combobox/ComboBox.vue';
@@ -65,6 +68,13 @@ const defaultState = {
const state = reactive({ ...defaultState });
const validationRules = {
firstName: { required, minLength: minLength(2) },
email: { required, email },
};
const v$ = useVuelidate(validationRules, state);
const updateState = () => {
const [firstName = '', lastName = ''] = (props.contactData.name || '').split(
' '
@@ -108,6 +118,15 @@ const socialProfilesForm = computed(() =>
}))
);
const isValidationField = key => {
const field = FORM_CONFIG[key]?.field;
return ['firstName', 'email'].includes(field);
};
const getValidationKey = key => {
return FORM_CONFIG[key]?.field;
};
// Creates a computed property for form field binding based on FORM_CONFIG
const getFormBinding = key => {
// Get field path from config
@@ -130,7 +149,7 @@ const getFormBinding = key => {
// Set value in state and emit update
// Example 1 (nested): field = 'contact.name', value = "Jane Doe" → state.contact.name = "Jane Doe"
// Example 2 (root): field = 'email', value = "jane@example.com" → state.email = "jane@example.com"
set: value => {
set: async value => {
if (field === 'firstName' || field === 'lastName') {
state[field] = value;
// Combine first and last name into the name field
@@ -143,7 +162,11 @@ const getFormBinding = key => {
state[base] = value;
}
}
emit('update', state);
const isFormValid = await v$.value.$validate();
if (isFormValid) {
emit('update', state);
}
},
});
};
@@ -177,10 +200,24 @@ watch(() => props.contactData, updateState, { immediate: true, deep: true });
v-else
v-model="getFormBinding(item.key).value"
:placeholder="item.placeholder"
:message-type="
isValidationField(item.key) &&
v$[getValidationKey(item.key)]?.$error
? 'error'
: 'info'
"
:custom-input-class="`h-8 !pt-1 !pb-1 ${
!isDetailsView && '!border-transparent'
!isDetailsView ? '[&:not(.error)]:!border-transparent' : ''
}`"
class="w-full"
@input="
isValidationField(item.key) &&
v$[getValidationKey(item.key)].$touch()
"
@blur="
isValidationField(item.key) &&
v$[getValidationKey(item.key)].$touch()
"
/>
</template>
</div>
@@ -62,7 +62,7 @@ const inputBorderClass = computed(() => {
case 'error':
return 'border-n-ruby-8 dark:border-n-ruby-8 hover:border-n-ruby-9 dark:hover:border-n-ruby-9 disabled:border-n-ruby-8 dark:disabled:border-n-ruby-8';
default:
return 'border-n-weak dark:border-n-weak hover:border-n-slate-6 dark:hover:border-n-slate-6 disabled:border-n-weak dark:disabled:border-n-weak';
return 'border-n-weak dark:border-n-weak hover:border-n-slate-6 dark:hover:border-n-slate-6 disabled:border-n-weak dark:disabled:border-n-weak focus:border-n-brand dark:focus:border-n-brand';
}
});
@@ -86,12 +86,16 @@ const handleInput = event => {
<input
:id="id"
:value="modelValue"
:class="[customInputClass, inputBorderClass]"
:class="[
customInputClass,
inputBorderClass,
{ error: messageType === 'error' },
]"
:type="type"
:placeholder="placeholder"
:disabled="disabled"
:min="['date', 'datetime-local', 'time'].includes(type) ? min : undefined"
class="block w-full reset-base text-sm h-10 !px-3 !py-2.5 !mb-0 border rounded-lg focus:border-n-brand dark:focus:border-n-brand bg-n-alpha-black2 file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-n-slate-10 dark:placeholder:text-n-slate-10 disabled:cursor-not-allowed disabled:opacity-50 text-n-slate-12 transition-all duration-500 ease-in-out"
class="block w-full reset-base text-sm h-10 !px-3 !py-2.5 !mb-0 border rounded-lg bg-n-alpha-black2 file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-n-slate-10 dark:placeholder:text-n-slate-10 disabled:cursor-not-allowed disabled:opacity-50 text-n-slate-12 transition-all duration-500 ease-in-out"
@input="handleInput"
@blur="emit('blur')"
/>