2024-03-01 19:42:54 +00:00
import React , { useState } from "react" ;
2024-08-06 19:07:20 +00:00
import './GenericForm.css' ;
2024-03-01 19:42:54 +00:00
import { useNavigate } from 'react-router-dom'
import { ErrorMessage , Field , Form , Formik , FormikValues } from "formik" ;
2024-08-06 19:07:20 +00:00
import { Step , UserInput , FormData } from './formInterfaces' ;
import * as Yup from "yup" ;
2024-01-13 14:53:47 +00:00
2024-08-06 19:07:20 +00:00
const GenericForm = ( formData : FormData ) = > {
const steps : Step [ ] = formData . steps ;
const backend : string = formData . backend ;
const userInput : UserInput = formData . userInput ;
const spec : Yup.Schema < any > = formData . spec ;
2024-01-13 14:53:47 +00:00
2024-03-01 19:42:54 +00:00
const navigate = useNavigate ( ) ;
2024-01-13 14:53:47 +00:00
const [ currentStep , setCurrentStep ] = useState < number > ( 0 ) ;
2024-03-01 19:42:54 +00:00
const handleSubmit = async ( e : FormikValues ) = > {
2024-01-13 14:53:47 +00:00
try {
2024-08-06 19:07:20 +00:00
const response = await fetch ( backend , {
2024-01-13 14:53:47 +00:00
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
} ,
2024-03-01 19:42:54 +00:00
body : JSON.stringify ( e )
2024-01-13 14:53:47 +00:00
} )
if ( ! response . ok ) {
2024-08-06 20:28:41 +00:00
let json : string = JSON . stringify ( userInput ) ;
2024-08-06 19:07:20 +00:00
const blob = new Blob ( [ json ] , { type : "application/json" } ) ;
const url = URL . createObjectURL ( blob ) ;
const link = document . createElement ( 'a' ) ;
link . href = url ;
link . download = 'form_data.json' ;
link . click ( ) ;
URL . revokeObjectURL ( url ) ;
//TODO clean up
2024-01-13 14:53:47 +00:00
alert ( "Your form submission was denied by the server, or the server was unable to process it, if you didn't mess with the data please contact the administrator at admin@alttd.com" ) ;
} else {
navigate ( '/verify-email' , {
state : {
2024-03-01 19:42:54 +00:00
email : e [ 'email' ]
2024-01-13 14:53:47 +00:00
}
} ) ;
}
} catch ( e ) {
alert ( "Your form submission was denied by the server, if you didn't mess with the data please contact the administrator at admin@alttd.com" )
}
} ;
const next = ( ) = > {
setCurrentStep ( current = > current + 1 )
}
const prev = ( ) = > {
setCurrentStep ( current = > Math . max ( current - 1 , 0 ) )
}
2024-03-01 19:42:54 +00:00
const [ prevLength , setPrevLength ] = useState ( 0 ) ;
2024-01-13 14:53:47 +00:00
return (
< div className = "container" >
< div >
< h1 > Contact Form < / h1 >
< / div >
< div >
2024-03-01 19:42:54 +00:00
< Formik
2024-08-06 19:07:20 +00:00
initialValues = { userInput }
validationSchema = { spec }
2024-03-01 19:42:54 +00:00
onSubmit = { ( values : FormikValues ) = > {
handleSubmit ( values ) ;
} }
>
{ ( {
touched ,
errors ,
isValid ,
handleChange ,
values ,
setFieldTouched
} ) = > (
< Form >
< div >
< label >
{ steps [ currentStep ] . label }
< Field
type = { steps [ currentStep ] . type }
name = { steps [ currentStep ] . name }
required = { steps [ currentStep ] . required }
min = { steps [ currentStep ] . min_length }
max = { steps [ currentStep ] . max_length }
as = { ( steps [ currentStep ] . type === "textarea" ) ? "textarea" : "input" }
onChange = { ( e : React.ChangeEvent < HTMLInputElement > ) = > {
handleChange ( e ) ;
2024-08-04 21:21:05 +00:00
if ( prevLength !== values [ steps [ currentStep ] . name ] . length ) {
2024-03-01 19:42:54 +00:00
setFieldTouched ( steps [ currentStep ] . name ) ;
setPrevLength ( values [ steps [ currentStep ] . name ] . length ) ;
}
} }
/ >
< ErrorMessage name = { steps [ currentStep ] . name } component = "div" / >
< / label >
< / div >
< button type = "button" onClick = { prev } disabled = { currentStep === 0 } >
Previous
< / button >
< button type = "button" onClick = { next }
hidden = { currentStep === ( steps . length - 1 ) }
disabled = { ( ! touched [ steps [ currentStep ] . name ] || ! ! errors [ steps [ currentStep ] . name ] ) || currentStep === ( steps . length - 1 ) } >
Next
< / button >
< input type = "submit" value = "Submit"
hidden = { currentStep !== ( steps . length - 1 ) }
disabled = { ! isValid || currentStep !== ( steps . length - 1 ) }
/ >
< / Form >
) }
< / Formik >
2024-01-13 14:53:47 +00:00
< / div >
< / div >
) ;
} ;
2024-08-06 19:07:20 +00:00
export default GenericForm ;