diff --git a/src/App.tsx b/src/App.tsx index 3b1ce20..d76278e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,3 @@ -import ContactForm from "./components/contact_form/contact"; import './App.css'; import Home from "./components/home/home"; import {BrowserRouter, Route, Routes} from 'react-router-dom'; @@ -7,6 +6,9 @@ import Footer from "./components/footer/footer"; import VerifyMail from "./components/verify_email/verify_mail"; import ThankYou from "./components/verify_email/thank_you"; import DEBUG from "./components/DEBUG/DEBUG"; +import GenericForm from "./components/form/genericForm"; +import {getFormProperties} from "./components/form/formData"; +import {FormProperties} from "./components/form/formInterfaces"; function App() { return ( @@ -15,7 +17,13 @@ function App() { }/> - }/> + {getFormProperties().map((property: FormProperties) => ( + } + /> + ))} }/> }/> {process.env.NODE_ENV === 'development' && }/>} diff --git a/src/components/contact_form/validationSchema.tsx b/src/components/contact_form/validationSchema.tsx deleted file mode 100644 index 2537c2b..0000000 --- a/src/components/contact_form/validationSchema.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import * as Yup from 'yup'; - -export const validationSchema = Yup.object().shape({ - username: Yup.string() - .min(3, 'Username should be at least 3 characters') - .max(16, 'Username should not exceed 16 characters') - .matches(/^[a-zA-Z0-9_]*$/, 'Username should only include alphanumeric characters and underscore') - .required('Username is required'), - - email: Yup.string() - .email('Invalid email') - .min(3, 'Email should be at least 3 characters') - .max(254, 'Email should not exceed 254 characters') - .required(), - - question: Yup.string() - .min(10, 'Question should be at least 10 characters') - .max(2000, 'Question should not exceed 2000 characters') - .required('Question is required') -}); \ No newline at end of file diff --git a/src/components/contact_form/Contact.css b/src/components/form/GenericForm.css similarity index 100% rename from src/components/contact_form/Contact.css rename to src/components/form/GenericForm.css diff --git a/src/components/form/data/contact.tsx b/src/components/form/data/contact.tsx new file mode 100644 index 0000000..b5b3f4b --- /dev/null +++ b/src/components/form/data/contact.tsx @@ -0,0 +1,51 @@ +import {FormData} from "../formInterfaces"; +import * as Yup from "yup"; + +export const contact: FormData = { + steps: [ + { + label: "Username", + name: "username", + type: "text", + min_length: 3, + max_length: 16, + required: true, + }, + { + label: "Email", + name: "email", + type: "email", + min_length: 3, + max_length: 254, + required: true, + }, + { + label: "Question", + name: "question", + type: "textarea", + min_length: 10, + max_length: 2000, + required: true, + }, + ], + backend: 'https://forms-backend.alttd.com/api/contact/submitContactForm', + userInput: {username: '', email: '', question: ''}, + spec: Yup.object().shape({ + username: Yup.string() + .min(3, 'Username should be at least 3 characters') + .max(16, 'Username should not exceed 16 characters') + .matches(/^[a-zA-Z0-9_]*$/, 'Username should only include alphanumeric characters and underscore') + .required('Username is required'), + + email: Yup.string() + .email('Invalid email') + .min(3, 'Email should be at least 3 characters') + .max(254, 'Email should not exceed 254 characters') + .required(), + + question: Yup.string() + .min(10, 'Question should be at least 10 characters') + .max(2000, 'Question should not exceed 2000 characters') + .required('Question is required') + }) +}; \ No newline at end of file diff --git a/src/components/form/formData.tsx b/src/components/form/formData.tsx new file mode 100644 index 0000000..408c043 --- /dev/null +++ b/src/components/form/formData.tsx @@ -0,0 +1,13 @@ +import {FormProperties} from "./formInterfaces"; +import {contact} from "./data/contact"; + +const formProperties: FormProperties[] = [ + { + path: 'contact', + formData: contact + }, +] + +export function getFormProperties(): FormProperties[] { + return formProperties +} \ No newline at end of file diff --git a/src/components/form/formInterfaces.tsx b/src/components/form/formInterfaces.tsx new file mode 100644 index 0000000..5e1f85a --- /dev/null +++ b/src/components/form/formInterfaces.tsx @@ -0,0 +1,29 @@ +import * as Yup from "yup"; + +type InputNames = "username" | "email" | "question" | "discord" | "age" | "pronoun" | "join-date" | "avg-time" | + "available-days" | "available-time" | "experience" | "why-staff" | "expectations-mod" | "other"; + +export interface Step { + label: string; + name: InputNames; + type: "text" | "email" | "textarea"; + min_length: number; + max_length: number; + required: boolean; +} + +export interface UserInput { + [key: string]: string; +} + +export type FormData = { + steps: Step[]; + backend: string; + userInput: UserInput; + spec: Yup.Schema +} + +export interface FormProperties { + path: string + formData: FormData; +} \ No newline at end of file diff --git a/src/components/contact_form/contact.tsx b/src/components/form/genericForm.tsx similarity index 76% rename from src/components/contact_form/contact.tsx rename to src/components/form/genericForm.tsx index e9b0d8d..ec2364c 100644 --- a/src/components/contact_form/contact.tsx +++ b/src/components/form/genericForm.tsx @@ -1,61 +1,23 @@ import React, {useState} from "react"; -import './Contact.css'; +import './GenericForm.css'; import {useNavigate} from 'react-router-dom' -import {validationSchema} from "./validationSchema"; import {ErrorMessage, Field, Form, Formik, FormikValues} from "formik"; +import {Step, UserInput, FormData} from './formInterfaces'; +import * as Yup from "yup"; -type InputNames = "username" | "email" | "question"; - -interface Step { - label: string; - name: InputNames; - type: "text" | "email" | "textarea"; - min_length: number; - max_length: number; - required: boolean; - pattern: string; -} - -const ContactForm = () => { +const GenericForm = (formData: FormData) => { + const steps: Step[] = formData.steps; + const backend: string = formData.backend; + const userInput: UserInput = formData.userInput; + const spec: Yup.Schema = formData.spec; const navigate = useNavigate(); const [currentStep, setCurrentStep] = useState(0); - - const steps: Step[] = [ - { - label: "Username", - name: "username", - type: "text", - min_length: 3, - max_length: 16, - required: true, - pattern: "" - }, - { - label: "Email", - name: "email", - type: "email", - min_length: 3, - max_length: 254, - required: true, - pattern: "" - }, - { - label: "Question", - name: "question", - type: "textarea", - min_length: 10, - max_length: 2000, - required: true, - pattern: "" - }, - ] - const handleSubmit = async (e: FormikValues) => { try { - const response = await fetch('https://forms-backend.alttd.com/api/contact/submitContactForm', { + const response = await fetch(backend, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -63,6 +25,16 @@ const ContactForm = () => { body: JSON.stringify(e) }) if (!response.ok) { + let json: string = JSON.stringify(steps); + 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 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', { @@ -92,8 +64,8 @@ const ContactForm = () => {
{ handleSubmit(values); }} @@ -149,4 +121,4 @@ const ContactForm = () => { ); }; -export default ContactForm; \ No newline at end of file +export default GenericForm; \ No newline at end of file