Apply form hook for room page

This commit is contained in:
2023-11-04 13:23:20 +07:00
parent 32a65038f5
commit 425610d654
11 changed files with 208 additions and 473 deletions
+3 -2
View File
@@ -54,10 +54,11 @@ const useFetch = (
const response = await fetch(BASE_URL + path + '?' + query);
const json = await response.json();
if (!response.ok)
if (!response.ok) {
throw new Error(
`Error code: ${response.status} \n Messages: ${response.statusText}`,
`Error code: ${response.status} \n Messages: ${response.text}`,
);
}
setIsPending(false);
setData(json);
-170
View File
@@ -1,170 +0,0 @@
import { useState, useEffect, useCallback, ChangeEvent } from 'react';
// Utils
import { getPropValues, isObject, isRequired } from '../helpers/utils';
// Types
import { TKeyValue, TValidator } from '../globals/types';
// Constants
import { ERROR, INITIAL_STATE_SCHEMA, VALUE } from '../constants/variables';
/**
* Custom hooks to validate your Form...
*
* @param stateSchema model you stateSchema.
* @param stateValidatorSchema model your validation.
* @param submitFormCallback function to be execute during form submission.
* @returns
*/
const useForm = (
stateSchema = {},
stateValidatorSchema = {} as TValidator,
submitFormCallback: (values: TKeyValue) => void,
initialValue: string = '',
) => {
const [values, setValues] = useState<TKeyValue>(INITIAL_STATE_SCHEMA);
const [errors, setErrors] = useState(getPropValues(stateSchema, ERROR));
const [valid, isValid] = useState(getPropValues(stateSchema));
const [disable, setDisable] = useState(true);
const [isDirty, setIsDirty] = useState(false);
// Get a local copy of stateSchema
useEffect(() => {
setInitialErrorState(initialValue);
setDisable(true);
isValid(getPropValues(stateSchema));
setValues(getPropValues(stateSchema, VALUE));
// If initial value true, setValues again from stateSchema
// and enabled button
if (initialValue) {
setValues(getPropValues(stateSchema, VALUE));
setDisable(false);
}
}, [initialValue]); // eslint-disable-line
// Validate fields in forms
const validateFormFields = useCallback(
(name: string, value: string) => {
const validator = stateValidatorSchema;
// Making sure that stateValidatorSchema name is same in
// stateSchema
if (!validator[name]) return;
const field = validator[name];
let error = '';
// Skip check id field
if (name !== 'id' && name !== 'roomId') {
error = isRequired(value, field!.required);
if (isObject(field['validator']) && error === '') {
const fieldValidator = field['validator'];
// Test the function callback if the value is meet the criteria
const testFunc = fieldValidator!['func'];
if (!testFunc!(value)) {
error = fieldValidator!['error']!;
}
}
}
return error;
},
[stateValidatorSchema],
);
// Set Initial Error State
// When hooks was first rendered...
const setInitialErrorState = useCallback(
(initialValue: string) => {
Object.keys(errors).map((name) =>
setErrors((prevState) => ({
...prevState,
[name]: !initialValue // Skip error when initialValue have values
? validateFormFields(name, values[name] as string)
: '',
})),
);
},
[errors, values, validateFormFields],
);
// Used to disable submit button if there's a value in errors
// or the required field in state has no value.
// Wrapped in useCallback to cached the function to avoid intensive memory leaked
// in every re-render in component
const validateErrorState = useCallback(
() => Object.values(errors).some((error) => error),
[errors],
);
// For every changed in our state this will be fired
// To be able to disable the button
useEffect(() => {
if (isDirty) {
setDisable(validateErrorState());
}
}, [errors, isDirty, validateErrorState]);
// Event handler for handling changes in input.
const handleOnChange = useCallback(
(
event: ChangeEvent<
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
>,
) => {
setIsDirty(true);
let error = '';
const name = (event.target! as HTMLInputElement).name;
let value: string | boolean = '';
if ((event.target! as HTMLInputElement).type === 'checkbox') {
value = (event.target! as HTMLInputElement).checked;
} else {
value = (event.target! as HTMLInputElement).value;
}
if (typeof value === 'string') {
error = validateFormFields(name, value)!;
}
setValues((prevState) => ({ ...prevState, [name]: value }));
setErrors((prevState) => ({ ...prevState, [name]: error }));
isValid((prevState) => ({ ...prevState, [name]: true }));
},
[validateFormFields],
);
const handleOnSubmit = useCallback(
(event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
// Making sure that there's no error in the state
// before calling the submit callback function
// and disabled button
if (!validateErrorState()) {
submitFormCallback(values);
setDisable(true);
}
},
[validateErrorState, submitFormCallback, values],
);
return {
handleOnChange,
handleOnSubmit,
values,
errors,
disable,
setValues,
setErrors,
valid,
};
};
export default useForm;