diff options
Diffstat (limited to 'src/core/utils/formValidation.js')
| -rw-r--r-- | src/core/utils/formValidation.js | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/src/core/utils/formValidation.js b/src/core/utils/formValidation.js new file mode 100644 index 00000000..0e83f4cc --- /dev/null +++ b/src/core/utils/formValidation.js @@ -0,0 +1,107 @@ +import { useCallback, useEffect, useState } from "react"; + +const validateForm = (data, queries, hasChangedInputs = null) => { + let result = { valid: true, errors: {} }; + + for (const query in queries) { + if (!hasChangedInputs || (hasChangedInputs && hasChangedInputs[query])) { + const value = data[query]; + const rules = queries[query]; + let errors = []; + let label = null; + for (const rule of rules) { + let emailValidationRegex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + if (rule.startsWith('label:')) { + label = rule.replace('label:', ''); + } else if (rule === 'required' && !value) { + errors.push('tidak boleh kosong'); + } else if (rule === 'email' && !value.match(emailValidationRegex)) { + errors.push('harus format johndoe@example.com'); + } else if (rule.startsWith('maxLength:')) { + let maxLength = parseInt(rule.replace('maxLength:', '')); + if (value && value.length > maxLength) errors.push(`maksimal ${maxLength} karakter`); + } + } + if (errors.length > 0) { + result.errors[query] = (label || query) + ' ' + errors.join(', '); + } + } + } + + if (Object.keys(result.errors).length > 0) { + result.valid = false; + } + + return result; +} + +const useFormValidation = ({ initialFormValue = {}, validationScheme = {} }) => { + const [ formInputs, setFormInputs ] = useState(initialFormValue); + const [ formErrors, setFormErrors ] = useState({}); + const [ formValidation ] = useState(validationScheme); + const [ hasChangedInputs, setHasChangedInputs ] = useState({}); + + const handleFormSubmit = (event, func) => { + if (event) { + event.preventDefault(); + + // Make all input to be has changed mode to revalidate + const changedInputs = {}; + for (const key in formInputs) changedInputs[key] = true; + setHasChangedInputs(changedInputs); + + const { valid, errors } = validateForm(formInputs, formValidation, changedInputs); + setFormErrors(errors); + + if (valid) func(); + } + }; + + const setChangedInput = (name, value = true) => { + setHasChangedInputs((hasChangedInputs) => ({ + ...hasChangedInputs, + [name]: value + })); + }; + + const handleInputChange = (event) => { + setFormInputs((formInputs) => ({ + ...formInputs, + [event.target.name]: event.target.value + })); + setChangedInput(event.target.name); + }; + + const handleSelectChange = useCallback((name, value) => { + setFormInputs((formInputs) => ({ + ...formInputs, + [name]: value + })); + setChangedInput(name); + }, []); + + const handleFormReset = () => { + setFormInputs(initialFormValue); + setFormErrors({}); + setHasChangedInputs({}); + } + + useEffect(() => { + if (formInputs) { + const { errors } = validateForm(formInputs, formValidation, hasChangedInputs); + setFormErrors(errors); + } + }, [ formInputs, formValidation, hasChangedInputs ]) + + return { + handleFormReset, + handleFormSubmit, + handleInputChange, + handleSelectChange, + hasChangedInputs, + formInputs, + formErrors + }; + }; + +export default useFormValidation;
\ No newline at end of file |
