import { useValidation, type ValidationRule } from '@/composables/validation/useValidation' import { useValidatable } from '@/composables/validation/useValidatable' import { reactive, ref, watch } from 'vue' import type { Ref } from 'vue' /** * Interface between the validation entrypoint "useValidation" composable and the custom validation logic. */ export function useCustomValidation( modelValue: Ref, customRules: Ref | undefined, customWarningRules: Ref | undefined, customSuccessRules: Ref | undefined, errors: Ref, warnings: Ref, successes: Ref, showSuccessMessages: Ref, label: Ref, focused: Ref, isValidateOnBlur: Ref, disableErrorHandling: Ref, readonly?: Ref, disabled?: Ref, ) { const hasSuccess = ref(false) const validatorOptions = reactive({ showSuccessMessages: showSuccessMessages.value, fieldIdentifier: label.value, disableErrorHandling: disableErrorHandling.value, }) const validator = useValidation(validatorOptions) watch( () => [showSuccessMessages.value, label.value, disableErrorHandling.value], () => { validatorOptions.showSuccessMessages = showSuccessMessages.value validatorOptions.fieldIdentifier = label.value validatorOptions.disableErrorHandling = disableErrorHandling.value const isDirty = errors.value.length > 0 || warnings.value.length > 0 || successes.value.length > 0 || hasSuccess.value if (isDirty) { validate() } }, ) watch( () => [customRules?.value, customWarningRules?.value, customSuccessRules?.value], () => { const isDirty = errors.value.length > 0 || warnings.value.length > 0 || successes.value.length > 0 || hasSuccess.value if (isDirty) { validate() } }, { deep: true }, ) async function validate() { if (readonly?.value || disabled?.value) { errors.value = [] warnings.value = [] successes.value = [] hasSuccess.value = false return { hasError: false, hasWarning: false, hasSuccess: false, state: { errors: [] as string[], warnings: [] as string[], successes: [] as string[] } } } const result = await validator.validateField( modelValue.value, customRules?.value, customWarningRules?.value, customSuccessRules?.value, ) errors.value = result.state.errors warnings.value = result.state.warnings successes.value = result.state.successes hasSuccess.value = result.hasSuccess return result } useValidatable( async () => { const result = await validate() return result.state.errors.length === 0 }, () => { errors.value = [] warnings.value = [] successes.value = [] hasSuccess.value = false }, () => modelValue.value = undefined, ) watch(focused, (newVal) => { if (isValidateOnBlur.value && !newVal && !disableErrorHandling.value) { validate() } }) watch(modelValue, () => { if (!isValidateOnBlur.value && !disableErrorHandling.value) { validate() } }) function clearValidation() { errors.value = [] warnings.value = [] successes.value = [] hasSuccess.value = false } return { validate, hasSuccess, clearValidation } }