Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fda5d9fb9 | ||
|
|
ee54e91051 | ||
|
|
1c4f4b154b | ||
|
|
30720d0738 | ||
|
|
25c6a15413 | ||
|
|
821e63953b | ||
|
|
ceaca60ece | ||
|
|
b00b857f29 | ||
|
|
cf7bdeb481 |
@@ -9,6 +9,7 @@ import DEBUG from "./components/DEBUG/DEBUG";
|
|||||||
import {getFormProperties} from "./components/form/formData";
|
import {getFormProperties} from "./components/form/formData";
|
||||||
import {FormProperties} from "./components/form/formInterfaces";
|
import {FormProperties} from "./components/form/formInterfaces";
|
||||||
import FormActiveRedirect from "./components/form/formActiveRedirect";
|
import FormActiveRedirect from "./components/form/formActiveRedirect";
|
||||||
|
import Appeal from "./components/appeal";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
@@ -26,6 +27,7 @@ function App() {
|
|||||||
))}
|
))}
|
||||||
<Route path="/verify-email" element={<VerifyMail/>}/>
|
<Route path="/verify-email" element={<VerifyMail/>}/>
|
||||||
<Route path="/thank-you" element={<ThankYou/>}/>
|
<Route path="/thank-you" element={<ThankYou/>}/>
|
||||||
|
<Route path="/appeal" element={<Appeal/>}/>
|
||||||
{process.env.NODE_ENV === 'development' && <Route path="/debug" element={<DEBUG/>}/>}
|
{process.env.NODE_ENV === 'development' && <Route path="/debug" element={<DEBUG/>}/>}
|
||||||
</Routes>
|
</Routes>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// you might need to adjust imports according to your project structure
|
||||||
|
import React, { FunctionComponent } from 'react';
|
||||||
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
|
const Appeal: FunctionComponent = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Helmet>
|
||||||
|
<title>Appeals Selection</title>
|
||||||
|
<meta name="Appeals selection page" content="Choose the type of appeal"/>
|
||||||
|
</Helmet>
|
||||||
|
<header className="App-header">
|
||||||
|
<h1>Welcome to the Appeals page</h1>
|
||||||
|
<h2><a href="/appeal/minecraft">Appeal a Minecraft punishment.</a></h2>
|
||||||
|
<h2><a href="/appeal/discord">Appeal a Discord punishment.</a></h2>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Appeal;
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
import {FormData} from "../formInterfaces";
|
||||||
|
import * as Yup from "yup";
|
||||||
|
type PunishmentsForUser = {
|
||||||
|
punishments: string[]
|
||||||
|
};
|
||||||
|
type UserForPunishments = {
|
||||||
|
username: string
|
||||||
|
};
|
||||||
|
|
||||||
|
export const minecraft_appeal: FormData = {
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
label: "What is your Minecraft username?",
|
||||||
|
additional_info: "Use the username you had when you last tried to join the server.",
|
||||||
|
name: "username",
|
||||||
|
type: "text",
|
||||||
|
min_length: 3,
|
||||||
|
max_length: 16,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "What is your email?",
|
||||||
|
additional_info: "It does not have to be your minecraft email.",
|
||||||
|
name: "email",
|
||||||
|
type: "email",
|
||||||
|
min_length: 3,
|
||||||
|
max_length: 254,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "What punishment would you like to appeal?",
|
||||||
|
additional_info: "Please select it below.",
|
||||||
|
name: "punishment",
|
||||||
|
type: "dropdown",
|
||||||
|
min_length: 10,
|
||||||
|
max_length: 2000,
|
||||||
|
required: true,
|
||||||
|
drop_down: [],
|
||||||
|
processInput: (input: string): Promise<string[]> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const userForPunishments: UserForPunishments = {
|
||||||
|
username: input,
|
||||||
|
}
|
||||||
|
fetch(`${process.env.REACT_APP_BACKEND_BASE_URL}/api/appeal/retrieve-minecraft-punishments`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(userForPunishments)
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
console.log(response)
|
||||||
|
reject(new Error('Invalid username'));
|
||||||
|
}
|
||||||
|
return response.json()
|
||||||
|
})
|
||||||
|
.then((punishmentsForUser: PunishmentsForUser) => {
|
||||||
|
resolve(punishmentsForUser.punishments);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Received an unexpected error: ' + error);
|
||||||
|
reject(error);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Why should your punishment be reduced or removed?",
|
||||||
|
additional_info: "Please take your time writing this, we're more likely to accept an appeal if effort was put into it.",
|
||||||
|
name: "appeal",
|
||||||
|
type: "textarea",
|
||||||
|
min_length: 2,
|
||||||
|
max_length: 2000,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
//TODO warning if no punishments
|
||||||
|
backend: `${process.env.REACT_APP_BACKEND_BASE_URL}/api/appeal/minecraft`,
|
||||||
|
userInput: {username: '', email: '', punishment: '', appeal: ''},
|
||||||
|
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('Email is required'),
|
||||||
|
|
||||||
|
punishment: Yup.string()
|
||||||
|
.required('You are required to select a punishment'),
|
||||||
|
|
||||||
|
appeal: Yup.string()
|
||||||
|
.min(3, 'Your appeal needs to be at least 100 characters')
|
||||||
|
.max(2000, 'Your appeal can not be longer than 2000 characters')
|
||||||
|
.required()
|
||||||
|
}),
|
||||||
|
title: "Minecraft Appeal",
|
||||||
|
backendFormName: "MinecraftAppeal",
|
||||||
|
};
|
||||||
@@ -89,6 +89,7 @@ export const apply: FormData = {
|
|||||||
min_length: 3,
|
min_length: 3,
|
||||||
max_length: 256,
|
max_length: 256,
|
||||||
required: true,
|
required: true,
|
||||||
|
additional_info: "Please include your timezone."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Do you have any previous experience being staff?",
|
label: "Do you have any previous experience being staff?",
|
||||||
@@ -163,6 +164,7 @@ export const apply: FormData = {
|
|||||||
|
|
||||||
age: Yup.number()
|
age: Yup.number()
|
||||||
.typeError('Input must be a number')
|
.typeError('Input must be a number')
|
||||||
|
.integer('Please enter a whole number')
|
||||||
.min(0, 'Please enter a valid age')
|
.min(0, 'Please enter a valid age')
|
||||||
.max(999, 'We do not accept players older than 999 years old sorry!')
|
.max(999, 'We do not accept players older than 999 years old sorry!')
|
||||||
.required('You are required to fill out your age'),
|
.required('You are required to fill out your age'),
|
||||||
@@ -175,6 +177,7 @@ export const apply: FormData = {
|
|||||||
|
|
||||||
avg_time: Yup.number()
|
avg_time: Yup.number()
|
||||||
.typeError('Please enter a number')
|
.typeError('Please enter a number')
|
||||||
|
.integer('Please enter a whole number')
|
||||||
.min(0, 'Please enter a positive number')
|
.min(0, 'Please enter a positive number')
|
||||||
.max(168, 'There are only 168 hours in a week')
|
.max(168, 'There are only 168 hours in a week')
|
||||||
.required('Please enter the average time you will be available each week'),
|
.required('Please enter the average time you will be available each week'),
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
import {FormData} from "../formInterfaces";
|
||||||
|
import * as Yup from "yup";
|
||||||
|
|
||||||
|
export const event_apply: FormData = {
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
label: "What is your Minecraft username?",
|
||||||
|
name: "username",
|
||||||
|
type: "text",
|
||||||
|
min_length: 3,
|
||||||
|
max_length: 16,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "What is your email?",
|
||||||
|
name: "email",
|
||||||
|
type: "email",
|
||||||
|
min_length: 3,
|
||||||
|
max_length: 254,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "What is your Discord username?",
|
||||||
|
name: "discord",
|
||||||
|
type: "text",
|
||||||
|
min_length: 2,
|
||||||
|
max_length: 32,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "What is your age?",
|
||||||
|
name: "age",
|
||||||
|
type: "text",
|
||||||
|
min_length: 1,
|
||||||
|
max_length: 3,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "What is your preferred pronoun?",
|
||||||
|
name: "pronoun",
|
||||||
|
type: "dropdown",
|
||||||
|
min_length: 0,
|
||||||
|
max_length: 16,
|
||||||
|
required: true,
|
||||||
|
drop_down: ["They/them", "She/her", "He/him", ""],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "On average, how many hours per week are you available to help with events?",
|
||||||
|
name: "avg_time",
|
||||||
|
type: "text",
|
||||||
|
min_length: 1,
|
||||||
|
max_length: 2,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Do you have any previous experience running events of any kind?",
|
||||||
|
name: "event_experience",
|
||||||
|
type: "textarea",
|
||||||
|
min_length: 2,
|
||||||
|
max_length: 2000,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Are you able to use voice chat on Discord",
|
||||||
|
name: "discord_vc",
|
||||||
|
type: "dropdown",
|
||||||
|
min_length: 2,
|
||||||
|
max_length: 3,
|
||||||
|
required: true,
|
||||||
|
additional_info: "Use voice chat in Discord with reasonable audio quality\n" +
|
||||||
|
"Take screenshots through your pc (normally f2 in minecraft)\n" +
|
||||||
|
"Record your screen through your pc at 20fps+ and 720p+ at normal Minecraft settings (with free programs like OBS)\n",
|
||||||
|
drop_down: ["Yes", "No", ""],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "You may share anything else you wish here.",
|
||||||
|
name: "other",
|
||||||
|
type: "textarea",
|
||||||
|
min_length: 2,
|
||||||
|
max_length: 2000,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
backend: `${process.env.REACT_APP_BACKEND_BASE_URL}/api/apply/staffApplication`,
|
||||||
|
userInput: {
|
||||||
|
username: '', email: '', discord: ''
|
||||||
|
, age: '', pronoun: '', avg_time: '', event_experience: ''
|
||||||
|
, discord_vc: '', other: ''
|
||||||
|
},
|
||||||
|
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('Please enter your username'),
|
||||||
|
|
||||||
|
email: Yup.string()
|
||||||
|
.email('Invalid email')
|
||||||
|
.min(3, 'Email should be at least 3 characters')
|
||||||
|
.max(254, 'Email should not exceed 254 characters')
|
||||||
|
.required('Please enter your email'),
|
||||||
|
|
||||||
|
discord: Yup.string()
|
||||||
|
.min(2, 'Discord name should be at least 2 characters')
|
||||||
|
.max(32, 'Discord name should be at most 32 characters')
|
||||||
|
.matches(/^(?!.*\.\.)([a-z0-9._]{2,32})$/, 'Please enter a valid Discord name')
|
||||||
|
.required('Please enter your Discord name'),
|
||||||
|
|
||||||
|
age: Yup.number()
|
||||||
|
.typeError('Input must be a number')
|
||||||
|
.integer('Please enter a whole number')
|
||||||
|
.min(0, 'Please enter a valid age')
|
||||||
|
.max(999, 'We do not accept players older than 999 years old sorry!')
|
||||||
|
.required('You are required to fill out your age'),
|
||||||
|
|
||||||
|
pronoun: Yup.string()
|
||||||
|
.max(16, 'Pronouns can\'t be longer than 16 characters'),
|
||||||
|
|
||||||
|
avg_time: Yup.number()
|
||||||
|
.typeError('Please enter a number')
|
||||||
|
.integer('Please enter a whole number')
|
||||||
|
.min(0, 'Please enter a positive number')
|
||||||
|
.max(168, 'There are only 168 hours in a week')
|
||||||
|
.required('Please enter the average time you will be available each week'),
|
||||||
|
|
||||||
|
event_experience: Yup.string()
|
||||||
|
.min(2, 'Please provide your experience with running/working on events, if you don\'t have any you can say that instead')
|
||||||
|
.max(2000, 'Please provide at most 2000 characters')
|
||||||
|
.required('Please enter your event experience or simply say you don\'t have any'),
|
||||||
|
|
||||||
|
discord_vc: Yup.string()
|
||||||
|
.matches(/(yes|no)$/i, 'Yes or no')
|
||||||
|
.required('An answer is required'),
|
||||||
|
|
||||||
|
other: Yup.string()
|
||||||
|
.max(2000, 'Please provide at most 2000 characters')
|
||||||
|
}),
|
||||||
|
title: "Event Application",
|
||||||
|
backendFormName: "EventApplication",
|
||||||
|
};
|
||||||
@@ -7,14 +7,16 @@ const FormActiveRedirect = (formData: FormData) => {
|
|||||||
const [isFormActive, setFormActive] = useState(false);
|
const [isFormActive, setFormActive] = useState(false);
|
||||||
|
|
||||||
const handleCheckForm = useCallback(async () => {
|
const handleCheckForm = useCallback(async () => {
|
||||||
const result = await fetch(`${process.env.REACT_APP_BACKEND_BASE_URL}/api/checks/formActive`, {
|
setFormActive(true);
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ formName: formData.backendFormName })
|
|
||||||
});
|
|
||||||
const response = await result.json();
|
|
||||||
setFormActive(response.isActive);
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
// const result = await fetch(`${process.env.REACT_APP_BACKEND_BASE_URL}/api/checks/formActive`, {
|
||||||
|
// method: 'POST',
|
||||||
|
// headers: { 'Content-Type': 'application/json' },
|
||||||
|
// body: JSON.stringify({ formName: formData.backendFormName })
|
||||||
|
// });
|
||||||
|
// const response = await result.json();
|
||||||
|
// setFormActive(response.isActive);
|
||||||
|
// setLoading(false);
|
||||||
}, [formData.backendFormName]);
|
}, [formData.backendFormName]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import {FormProperties} from "./formInterfaces";
|
import {FormProperties} from "./formInterfaces";
|
||||||
import {contact} from "./data/contact";
|
import {contact} from "./data/contact";
|
||||||
import {apply} from "./data/apply";
|
import {apply} from "./data/apply";
|
||||||
|
import {event_apply} from "./data/event_apply";
|
||||||
|
import {minecraft_appeal} from "./data/appeal";
|
||||||
|
|
||||||
const formProperties: FormProperties[] = [
|
const formProperties: FormProperties[] = [
|
||||||
{
|
{
|
||||||
@@ -11,6 +13,14 @@ const formProperties: FormProperties[] = [
|
|||||||
path: 'apply',
|
path: 'apply',
|
||||||
formData: apply
|
formData: apply
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'event-apply',
|
||||||
|
formData: event_apply
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'appeal/minecraft',
|
||||||
|
formData: minecraft_appeal
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export function getFormProperties(): FormProperties[] {
|
export function getFormProperties(): FormProperties[] {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, {useState} from "react";
|
import React, {useEffect, useState} from "react";
|
||||||
import './GenericForm.css';
|
import './GenericForm.css';
|
||||||
import {Field} from "formik";
|
import {Field} from "formik";
|
||||||
import {FormHandlerProps} from "./formInterfaces";
|
import {FormHandlerProps} from "./formInterfaces";
|
||||||
@@ -22,6 +22,22 @@ const FormHTML: React.FC<FormHandlerProps> = ({
|
|||||||
|
|
||||||
const [selectedOptions, setSelectedOptions] = useState(fieldValues);
|
const [selectedOptions, setSelectedOptions] = useState(fieldValues);
|
||||||
|
|
||||||
|
const [options, setOptions] = useState<string[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const { processInput, drop_down = [] } = steps[currentStep];
|
||||||
|
|
||||||
|
if (processInput) {
|
||||||
|
processInput(values['username']).then(newOptions => {
|
||||||
|
setOptions(newOptions);
|
||||||
|
//TODO be an unsetter for some error field
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setOptions(drop_down);
|
||||||
|
console.log("No data") //TODO be a setter for some error field
|
||||||
|
}
|
||||||
|
}, [currentStep, steps]);
|
||||||
|
|
||||||
if (currentField.type === 'select') {
|
if (currentField.type === 'select') {
|
||||||
return (
|
return (
|
||||||
<ReactSelect
|
<ReactSelect
|
||||||
@@ -65,6 +81,12 @@ const FormHTML: React.FC<FormHandlerProps> = ({
|
|||||||
{option}
|
{option}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
|
{options.map((option, i) => (
|
||||||
|
<option key={i} value={option}>
|
||||||
|
{option}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
{options.length === 0 ? "<p>No data found, please check if your username is valid. Or if this was a discord punishment, please use the discord appeal form</p>":"<p></p>"}
|
||||||
</Field>
|
</Field>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from "react";
|
|||||||
|
|
||||||
type InputNames = "username" | "email" | "question" | "discord" | "pc_requirements" | "age" | "pronoun" | "join_date" |
|
type InputNames = "username" | "email" | "question" | "discord" | "pc_requirements" | "age" | "pronoun" | "join_date" |
|
||||||
"avg_time" | "available_days" | "available_time" | "staff_experience" | "plugin_experience" | "why_staff" |
|
"avg_time" | "available_days" | "available_time" | "staff_experience" | "plugin_experience" | "why_staff" |
|
||||||
"expectations_mod" | "other";
|
"expectations_mod" | "event_experience" | "discord_vc" | "other" | "punishment" | "appeal";
|
||||||
|
|
||||||
export interface Step {
|
export interface Step {
|
||||||
label: string;
|
label: string;
|
||||||
@@ -15,6 +15,7 @@ export interface Step {
|
|||||||
additional_info?: string;
|
additional_info?: string;
|
||||||
drop_down?: string[]
|
drop_down?: string[]
|
||||||
multiple?: boolean
|
multiple?: boolean
|
||||||
|
processInput?: (input: string) => Promise<string[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserInput {
|
export interface UserInput {
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ const Home: FunctionComponent = () => {
|
|||||||
<header className="App-header">
|
<header className="App-header">
|
||||||
<h1>Welcome to the Altitude forms page</h1>
|
<h1>Welcome to the Altitude forms page</h1>
|
||||||
<h2><a href="/contact">Contact us.</a></h2>
|
<h2><a href="/contact">Contact us.</a></h2>
|
||||||
|
<h2><a href="/apply">Apply for staff.</a></h2>
|
||||||
|
<h2><a href="/event-apply">Apply for events.</a></h2>
|
||||||
|
<h2><a href="/appeal">Appeal a punishment.</a></h2>
|
||||||
</header>
|
</header>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -37,4 +37,16 @@ table {
|
|||||||
.form-data-value {
|
.form-data-value {
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fields {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
max-width: 1020px;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field {
|
||||||
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@ import './ThankYou.css';
|
|||||||
const ThankYou: FC = () => {
|
const ThankYou: FC = () => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
type DynamicFormData = {
|
type DynamicFormData = {
|
||||||
[key: string]: string;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (location.state === null || location.state.formData === undefined) {
|
if (location.state === null || location.state.formData === undefined) {
|
||||||
@@ -26,19 +26,23 @@ const ThankYou: FC = () => {
|
|||||||
</Helmet>
|
</Helmet>
|
||||||
<header className="header">Thank you for completing the form and verifying your email!<br></br>This is the data you entered:</header>
|
<header className="header">Thank you for completing the form and verifying your email!<br></br>This is the data you entered:</header>
|
||||||
<div className="fields">
|
<div className="fields">
|
||||||
<table>
|
{Object.entries(formData).map(([key, value]) => (
|
||||||
<tbody>
|
<div className={"field"}>
|
||||||
{Object.entries(formData).map(([key, value]) => (
|
<p><strong>{key}</strong></p>
|
||||||
<tr className="form-data-row" id={key}>
|
{
|
||||||
<td className="form-data-key">{key}</td>
|
typeof value === "string" && value.includes("\n") ?
|
||||||
<td className="form-data-value">{value}</td>
|
value
|
||||||
</tr>
|
.split("\n")
|
||||||
))}
|
.filter(str => str.trim() !== "")
|
||||||
</tbody>
|
.map((str, index) => <p style={{ wordWrap: 'break-word' }} key={index}>{str}</p>)
|
||||||
</table>
|
: <p style={{ wordWrap: 'break-word' }}>{value}</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user