This commit removes the redundant logo.svg file. It then adds several new components including 'footer', 'contact_form', 'home', 'verify_email' in forms/src/components directory. It also includes associated CSS files for styling these components. Updates have also been made in the index.html file for SEO metadata. Changes made aim to enhance functionality and improve user interface.
161 lines
5.1 KiB
TypeScript
161 lines
5.1 KiB
TypeScript
import React, {ChangeEvent, useState} from "react";
|
|
import './Contact.css';
|
|
import { useNavigate } from 'react-router-dom'
|
|
|
|
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;
|
|
}
|
|
|
|
type FormDataType = Record<InputNames, string>;
|
|
|
|
const ContactForm = () => {
|
|
|
|
const navigate = useNavigate()
|
|
|
|
const [formData, setFormData] = useState<FormDataType>({
|
|
username: "",
|
|
email: "",
|
|
question: ""
|
|
});
|
|
|
|
const [currentStep, setCurrentStep] = useState<number>(0);
|
|
const [errorMessage, setErrorMessage] = useState<string>("");
|
|
|
|
function handleChange(e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) {
|
|
const { name, value } = e.target;
|
|
setErrorMessage("");
|
|
switch (name) {
|
|
case 'username':
|
|
if (/^[a-zA-Z0-9_]*$/.test(value)) {
|
|
setFormData(prevState => ({ ...prevState, [name]: value }));
|
|
} else {
|
|
setErrorMessage('Invalid character entered. Please use only alphanumeric characters and underscores.');
|
|
}
|
|
break;
|
|
default:
|
|
setFormData(prevState => ({ ...prevState, [name]: value }));
|
|
}
|
|
}
|
|
|
|
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: false,
|
|
pattern: ""
|
|
},
|
|
{
|
|
label: "Question",
|
|
name: "question",
|
|
type: "textarea",
|
|
min_length: 10,
|
|
max_length: 2000,
|
|
required: true,
|
|
pattern: ""
|
|
},
|
|
]
|
|
|
|
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
e.preventDefault();
|
|
try {
|
|
const response = await fetch('http://localhost:8080/api/contact/submitContactForm', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(formData)
|
|
})
|
|
if (!response.ok) {
|
|
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: {
|
|
email: formData.email
|
|
}
|
|
});
|
|
}
|
|
} 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))
|
|
setErrorMessage('');
|
|
}
|
|
|
|
function isNextDisabled(): boolean {
|
|
let step: Step = steps[currentStep];
|
|
if (!step)
|
|
return true;
|
|
if (!step.required)
|
|
return false;
|
|
return formData[step.name].length === 0
|
|
}
|
|
|
|
function getInputField(step: Step): JSX.Element {
|
|
switch (step.type) {
|
|
case "text":
|
|
case "email":
|
|
return <input pattern={step.pattern} type={step.type} name={step.name} minLength={step.min_length}
|
|
maxLength={step.max_length} onChange={handleChange} value={formData[step.name]} required/>
|
|
case "textarea":
|
|
return <textarea name={step.name} minLength={step.min_length} maxLength={step.max_length}
|
|
onChange={handleChange} value={formData.question} required/>
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="container">
|
|
<div>
|
|
<h1>Contact Form</h1>
|
|
</div>
|
|
{errorMessage && <p>{errorMessage}</p>}
|
|
<div>
|
|
<form onSubmit={handleSubmit}>
|
|
<div>
|
|
<label>
|
|
{steps[currentStep].label}
|
|
{getInputField(steps[currentStep])}
|
|
</label>
|
|
</div>
|
|
<button type="button" onClick={prev} disabled={currentStep === 0}>
|
|
Previous
|
|
</button>
|
|
<button type="button" onClick={next} disabled={currentStep === steps.length - 1 || isNextDisabled()}>
|
|
Next
|
|
</button>
|
|
<input type="submit" value="Submit" disabled={currentStep !== steps.length - 1}
|
|
hidden={currentStep !== steps.length - 1}/>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ContactForm; |