import React, { useEffect, useState } from "react"; import InputRow from "./InputRow"; import TextArea from "./TextArea"; import { DropdownOption } from "./DropdownSelect"; /** * Defines the attribues for a form field. * * @param validation - A function that validates the string value of the user input. Returns an * error message if validation fails, returns void if the value is accepted. */ export type FormField = { type?: string, label?: string, placeholder?: string, initialValue?: string, validation?: (v: string) => string | undefined, required?: boolean, options?: DropdownOption[], onChange?: (v: string) => void, }; export type FormFields = { [key: string]: FormField; }; type Props = { onSubmit?: (e: any) => void, fields: FormFields, buttonName?: string, preventDefault?: boolean, action?: string, method?: string, }; export default function FormCreator({ onSubmit = (e) => { }, fields = {}, buttonName = "Submit", preventDefault = true, action = undefined, method = undefined, } : Props) { let initial_state = Object.entries(fields).reduce( (prev, [name, attrs]) => { prev[name] = attrs.initialValue; return prev; }, {} ); let [state, setState] = useState(initial_state); let [errors, setErrors] = useState({}); useEffect(() => { setState( Object.entries(fields).reduce( (prev: { [x: string]: string; }, [name, attrs]: [name: string, attrs: FormField]) => { prev[name] = attrs.initialValue || ""; return prev; }, {} ) ); }, [fields]); async function handleSubmit(e) { // Stop page reloading preventDefault && e.preventDefault(); // TODO: Validate fields let errs = {}; Object.entries(fields).map( ([name, attrs]) => { let err: string | undefined = undefined; if (attrs.required && !state[name]) { err = "This field is required." } else { err = validateField(name); } if (err) { errs[name] = err; } } ); setErrors(errs); if (Object.entries(errs).length > 0){ // console.log(errs); e.preventDefault(); return; } // Submit form asynchronously // await superagent // .post(submitEndpoint) // .send(state) // ; // TODO: Handle errors (include onError() prop); // Call client-supplied processing logic onSubmit(state); } function validateField(name) { let attrs = fields[name]; let err: string | undefined = undefined; if (attrs.validation && state[name]) { err = attrs.validation(state[name]); } return err; } function handleChange(e) { const { name, value } = e.target; setState({ ...state, [name]: value }); console.log(e.target); } function handleValidation(e) { const { name, value } = e.target; setErrors({ ...errors, [name]: validateField(name) }); } let form_fields: any[] = []; Object.entries(fields).map( ([name, attrs]) => { let err = errors[name]; form_fields.push(( )); } ); return (
{form_fields}
); }