export default function ModalForm()

in source/console/src/components/DeviceTypeCreate/ModalForm.tsx [21:155]


export default function ModalForm(props: IProps): JSX.Element {
    const initialState = { name: "", type: "id" };
    let [attr, setAttr] = useState<IAttribute>(initialState)
    let [errs, setErrs] = useState<IErrors<IAttribute>>({});
    let [showValidation, setShowValidation] = useState<string[]>([]);

    /**
     * react useEffect hook
     * validate fields on attribute state update
     */
    useEffect(() => {
        let newErrs: IErrors<IAttribute> = {};
        const attrKeys = Object.keys(attr);
        attrKeys.forEach((key: string) => {
            const value = attr[key as keyof IAttribute];
            let error: any = validateField(key, value);

            if (!error[key]) {
                if (key === 'min') {
                    error = validateRange(key, Number(value!), Number(attr['max']));
                } else if (key === 'max') {
                    error = validateRange('min', Number(attr['min']), Number(value!)
                    );
                }
            }
            newErrs = { ...newErrs, ...error }
        })

        if (attr.default) {
            newErrs = newErrs.name ? { name: newErrs.name } : {};
        }
        setErrs({ ...newErrs });
    }, [attr])

    /**
     * checks validity of attribtue fields and submits
     * @param e 
     */
    const handleSubmit = (e: any) => {
        e.preventDefault();
        e.stopPropagation();
        e.currentTarget.checkValidity();
        if (Object.keys(errs).length === 0) {
            props.handleModalSubmit(attr);
            handleModalClose();
        }
    }

    /**
     * get fields belonging to an attribute
     * @param type 
     * @returns Object containing attribtue fields with initial values
     */
    const getAttrFieldDefaults = (type: string) => {
        let attrFields: string[];
        attrFields = getAttrFields(type);
        return attrFields.reduce(
            (acc: { [key: string]: any }, curr) => {
                let value: any;
                if (curr === "static") {
                    value = false;
                }
                else if (curr === "tsformat") {
                    value = "default";
                } else if (curr === "payload") {
                    value = [];
                }
                else {
                    value = undefined;
                }
                return (acc[curr] = value, acc)
            },
            {}
        );
    }

    /**
     * react useEffect hook
     * Resets attribute fields to that of intial type whenever modal is closed
     */
    useEffect(() => {
        if (props.showModal === false) {
            setAttr({ ...attr, ...getAttrFieldDefaults(attr.type) })
        }
    }, [props.showModal])

    /**
     * reset state and close modal
     */
    const handleModalClose = () => {
        setAttr(initialState);
        setShowValidation([]);
        props.closeModal();
    }

    /**
     * update state on form field change
     * @param event 
     */
    const handleFormChange = (event: any) => {
        let attrName = event.currentTarget.id as keyof IAttribute;
        let attrItem: { [key: string]: any } = {};
        let newFields = {};
        let valueAsNum = isNaN(event.target.valueAsNumber) ? null : event.target.valueAsNumber;
        attrItem[attrName] = valueAsNum ?? event.target.value;
        if (attrName === 'static') {
            attrItem[attrName] = attrItem[attrName] === 'true';
        } else if (attrName === "type") {
            Array.from(document.querySelectorAll("input")).forEach((input: HTMLInputElement) => {
                if(Object.keys(AttributeTypeMap).includes(input.id) && !["name", "type"].includes(input.id)) {
                    input.value = "";
                }
            });
            newFields = getAttrFieldDefaults(event.target.value);
            attr = { name: attr.name, type: event.target.value };
            setShowValidation(showValidation.filter(id => id === "name" || id === 'type'));
        } else if (attrName === "arr") {
            attrItem[attrName] = attrItem[attrName].split(',');
        }
        setAttr({ ...attr, ...newFields, ...attrItem });
    }
    
    /**
     * Shows form validation when a field is focused
     * @param event 
     */
    const handleFieldFocus = (event: any) => {
        if(!showValidation.includes(event.target.id)) {
            showValidation.push(event.target.id);
            setShowValidation([...showValidation]);
        }
    }

    return (
        <Modal show={props.showModal} onHide={() => handleModalClose()}>