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'
2024-08-08 19:37:09 +00:00
import { ErrorMessage , Field , Form , FormikProvider , FormikValues , useFormik } from "formik" ;
2024-08-06 19:07:20 +00:00
import { Step , UserInput , FormData } from './formInterfaces' ;
import * as Yup from "yup" ;
2024-08-09 22:25:44 +00:00
import formHTML from "./formHTML" ;
import FormHTML from "./formHTML" ;
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-08-06 21:21:53 +00:00
const handleSubmit = async ( formikValues : FormikValues ) = > {
2024-08-09 22:25:44 +00:00
console . log ( JSON . stringify ( 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-08-06 21:21:53 +00:00
body : JSON.stringify ( formikValues )
2024-01-13 14:53:47 +00:00
} )
if ( ! response . ok ) {
2024-08-06 21:21:53 +00:00
let json : string = JSON . stringify ( formikValues ) ;
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 ;
2024-08-06 21:21:53 +00:00
link . download = 'your_form_data.json' ;
2024-08-06 19:07:20 +00:00
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-08-06 21:21:53 +00:00
email : formikValues [ '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-08-08 19:37:09 +00:00
const formik = useFormik ( {
initialValues : userInput ,
validationSchema : spec ,
onSubmit : ( values ) = > {
handleSubmit ( values ) ;
} ,
} ) ;
const {
touched ,
errors ,
isValid ,
handleChange ,
values ,
setFieldTouched ,
2024-08-09 22:25:44 +00:00
setFieldValue ,
2024-08-08 19:37:09 +00:00
} = formik ;
2024-03-01 19:42:54 +00:00
const [ prevLength , setPrevLength ] = useState ( 0 ) ;
2024-01-13 14:53:47 +00:00
return (
2024-08-08 19:32:37 +00:00
< div >
2024-01-13 14:53:47 +00:00
< div >
2024-08-06 22:41:11 +00:00
< h1 > { formData . title } < / h1 >
2024-01-13 14:53:47 +00:00
< / div >
2024-08-08 19:37:09 +00:00
< div >
< FormikProvider value = { formik } >
< Form >
< div >
2024-03-01 19:42:54 +00:00
< div >
< label >
2024-08-09 21:16:41 +00:00
< label className = "headline" >
2024-08-08 18:33:15 +00:00
{ steps [ currentStep ] . label }
< / label >
2024-08-09 21:16:41 +00:00
< label className = "description" >
2024-08-08 18:33:15 +00:00
{
steps [ currentStep ] . additional_info ?
steps [ currentStep ] . additional_info ? . split ( '\n' ) . map ( ( line , i ) = > (
< React.Fragment key = { i } > { line } < br / > < / React.Fragment >
) )
: null
}
< / label >
< / label >
< label >
2024-08-09 22:25:44 +00:00
< FormHTML steps = { steps } currentStep = { currentStep } handleChange = { handleChange }
setFieldTouched = { setFieldTouched } setFieldValue = { setFieldValue } values = { values }
prevLength = { prevLength } setPrevLength = { setPrevLength } >
< / FormHTML >
2024-08-08 19:37:09 +00:00
< / label >
< / div >
< div >
2024-08-09 21:16:41 +00:00
< label className = "error-message" >
2024-03-01 19:42:54 +00:00
< ErrorMessage name = { steps [ currentStep ] . name } component = "div" / >
< / label >
< / div >
2024-08-08 19:37:09 +00:00
< div >
< button style = { { marginLeft : 0 } } className = "button-outer" type = "button" onClick = { prev } disabled = { currentStep === 0 } >
Previous
< / button >
2024-08-09 21:16:41 +00:00
< button className = { currentStep === ( steps . length - 1 ) ? "" : "button-outer" } type = "button" onClick = { next }
2024-08-08 19:37:09 +00:00
hidden = { currentStep === ( steps . length - 1 ) }
disabled = { ( ! touched [ steps [ currentStep ] . name ] || ! ! errors [ steps [ currentStep ] . name ] ) || currentStep === ( steps . length - 1 ) } >
Next
2024-08-09 21:16:41 +00:00
< / button >
< input className = { currentStep !== ( steps . length - 1 ) ? "" : "button-outer" } type = "submit" value = "Submit"
2024-08-08 19:37:09 +00:00
hidden = { currentStep !== ( steps . length - 1 ) }
disabled = { ! isValid || currentStep !== ( steps . length - 1 ) }
/ >
< / div >
< / div >
< / Form >
< / FormikProvider >
2024-01-13 14:53:47 +00:00
< / div >
< / div >
) ;
} ;
2024-08-06 19:07:20 +00:00
export default GenericForm ;