import React, { useState } from 'react';
import { Row, Col } from 'react-bootstrap';
import './Form1.css';
function Form1() {
const [formData, setFormData] = useState({
name: '',
email: '',
file: null,
number: '',
DOB: '',
gender: '',
username: '',
password: '',
repassword: '',
city: '',
state: '',
zip: '',
country: '',
address: ''
});
const [errorMessage, setErrorMessage] = useState({});
const [submissions, setSubmissions] = useState([]);
const [isEditing, setIsEditing] = useState(false);
const [currentEditIndex, setCurrentEditIndex] = useState(null);
const calculateAge = (dob) => {
const birthDate = new Date(dob);
const today = new Date();
let age = today.getFullYear() - birthDate.getFullYear();
const monthDifference = today.getMonth() - birthDate.getMonth();
if (monthDifference < 0 || (monthDifference === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
return age;
};
const validateField = (name, value) => {
let error = '';
const nameRegex = /^[A-Za-z\s]{2,50}$/;
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const phoneRegex = /^[6-9]\d{9}$/;
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
const usernameRegex = /^[a-zA-Z0-9]{3,20}$/;
const addressRegex = /^[a-zA-Z0-9]{5,100}$/;
const zipRegex = /^\d{5}(?:[-\s]\d{4})?$/;
const cityRegex = /^[A-Za-z\s]{3,30}$/;
const stateRegex = /^[A-Za-z\s]{2,20}$/;
const countryRegex = /^[A-Za-z\s]{5,60}$/;
switch (name) {
case 'name':
if (!value) {
error = 'Name is required!';
} else if (!nameRegex.test(value)) {
error = 'Please enter a valid name (2-50 alphabetic characters).';
}
break;
case 'email':
if (!value) {
error = 'Email is required!';
} else if (!emailRegex.test(value)) {
error = 'Please enter a valid email address.';
}
break;
case 'file':
if (!value) {
error = 'File is required';
} else if (!['image/jpeg', 'image/png'].includes(value.type) || value.size > 5 * 1024 * 1024) {
error = 'Please upload a valid file (jpg/png) with size up to 5MB.';
}
break;
case 'number':
if (!value) {
error = 'Please enter a valid number!';
} else if (!phoneRegex.test(value)) {
error = 'Please enter a valid Indian phone number (10 digits).';
}
break;
case 'DOB':
if (!value) {
error = 'Please enter your date of birth';
} else if (calculateAge(value) < 13) {
error = 'You must be at least 13 years old.';
}
break;
case 'gender':
if (!value) {
error = 'Please select your gender';
}
break;
case 'username':
if (!value) {
error = 'Username is required!';
} else if (!usernameRegex.test(value)) {
error = 'Please enter a valid username (3-20 alphanumeric characters).';
}
break;
case 'password':
if (!value) {
error = 'Password is required';
} else if (!passwordRegex.test(value)) {
error = 'Password must be at least 8 characters long and include at least one uppercase letter, one lowercase letter, one number, and one special character.';
}
break;
case 'repassword':
if (value !== formData.password) {
error = 'Passwords do not match.';
}
break;
case 'city':
if (!value) {
error = 'Please enter your city.';
}
else if(!cityRegex.test(value)) {
error = 'Please enter a valid city name (3-30 alphabetic characters).';
}
break;
case 'state':
if (!value) {
error = 'Please enter your state or province.';
} else if (!stateRegex.test(value)) {
error = 'Please enter a valid state name (2-20 alphabetic characters).'
}
break;
case 'zip':
if (!value) {
error = 'Zip/Postal is required';
}
else if(!zipRegex.test(value)) {
error = 'Please enter a valid Zip/Postal (6 digits).';
}
break;
case 'country':
if (!value) {
error = 'Please enter your country.';
} else if (!countryRegex.test(value)) {
error = "Please enter a valid country name (2-60 alphabetic characters)."
}
break;
case 'address':
if (!value) {
error = 'Please enter a valid address.';
} else if(!addressRegex.test(value)) {
error = 'Please enter a valid address (5-100 alphanumeric character)';
}
break;
default:
break;
}
return error;
};
const handleChange = (e) => {
const { name, value, type, files } = e.target;
const newValue = type === 'file' ? files[0] : value;
setFormData({
...formData,
[name]: newValue
});
const error = validateField(name, newValue);
setErrorMessage({
...errorMessage,
[name]: error
});
};
const validateForm = (values) => {
const errors = {};
for (let field in values) {
const error = validateField(field, values[field]);
if (error) {
errors[field] = error;
}
}
return errors;
};
const handleSubmit = (e) => {
e.preventDefault();
const errors = validateForm(formData);
if (Object.keys(errors).length === 0) {
if (isEditing) {
const updatedSubmissions = submissions.map((submission, index) =>
index === currentEditIndex ? formData : submission
);
setSubmissions(updatedSubmissions);
setIsEditing(false);
setCurrentEditIndex(null);
} else {
setSubmissions([...submissions, formData]);
}
localStorage.setItem('submissions', JSON.stringify([...submissions, formData]));
alert('Form submitted successfully!');
handleReset();
} else {
setErrorMessage(errors);
}
};
const handleReset = () => {
setFormData({
name: '',
email: '',
file: null,
number: '',
DOB: '',
gender: '',
username: '',
password: '',
repassword: '',
city: '',
state: '',
zip: '',
country: '',
address: ''
});
setErrorMessage({});
};
const handleEdit = (index) => {
setFormData(submissions[index]);
setIsEditing(true);
setCurrentEditIndex(index);
};
const handleDelete = (index) => {
const updatedSubmissions = submissions.filter((_, i) => i !== index);
setSubmissions(updatedSubmissions);
localStorage.setItem('submissions', JSON.stringify(updatedSubmissions));
};
return (
<>
<div className="App">
<h1>Form</h1>
<fieldset>
<form onSubmit={handleSubmit}>
<Row className="">
<Col xs={12} >
<Row className="g-3 mb-6">
<Col sm={6} md={6}>
<label htmlFor="name">Name*</label>
<input type="text" name="name" id="name" placeholder="Enter Your Name"
value={formData.name} onChange={handleChange} required />
{errorMessage.name && <p className="error text-danger">{errorMessage.name}</p>}
</Col>
<Col sm={6} md={6}>
<label htmlFor="email">Email*</label>
<input type="email" name="email" id="email" placeholder="Enter Your Email"
value={formData.email} onChange={handleChange} required />
{errorMessage.email && <p className="error text-danger">{errorMessage.email}</p>}
</Col>
<Col sm={6} md={6}>
<label htmlFor="file">File*</label>
<input type="file" name="file" id="file" placeholder="Upload Your File"
onChange={handleChange} required />
{errorMessage.file && <p className="error text-danger">{errorMessage.file}</p>}
</Col>
<Col sm={6} md={6}>
<label htmlFor="number">Phone Number*</label>
<input type="tel" maxLength={10} name="number" id="number" placeholder="Your Contact"
value={formData.number} onChange={handleChange} required />
{errorMessage.number && <p className="error text-danger">{errorMessage.number}</p>}
</Col>
<Col sm={6} md={6}>
<label htmlFor="DOB">DOB*</label>
<input type="date" name="DOB" id="DOB" placeholder="Date of Birth"
value={formData.DOB} onChange={handleChange} required />
{errorMessage.DOB && <p className="error text-danger">{errorMessage.DOB}</p>}
</Col>
<Col sm={6} md={6}>
<label htmlFor="username">UserName*</label>
<input type="text" name="username" id="username" placeholder="UserName"
value={formData.username} onChange={handleChange} required />
{errorMessage.username && <p className="error text-danger">{errorMessage.username}</p>}
</Col>
<Col sm={6} md={6}>
<label htmlFor="password">Password*</label>
<input type="password" name="password" id="password" placeholder="Enter Password"
value={formData.password} onChange={handleChange} required />
{errorMessage.password && <p className="error text-danger">{errorMessage.password}</p>}
</Col>
<Col sm={6} md={6}>
<label htmlFor="repassword">Re-password*</label>
<input type="password" name="repassword" id="repassword" placeholder="Confirm Password"
value={formData.repassword} onChange={handleChange} required />
{errorMessage.repassword && <p className="error text-danger">{errorMessage.repassword}</p>}
</Col>
<Col sm={6} md={6}>
<label htmlFor="city">City*</label>
<input type="text" name="city" id="city" placeholder="Enter City Name"
value={formData.city} onChange={handleChange} required />
{errorMessage.city && <p className="error text-danger">{errorMessage.city}</p>}
</Col>
<Col sm={6} md={6}>
<label htmlFor="state">State/Province*</label>
<input type="text" name="state" id="state" placeholder="State/Province"
value={formData.state} onChange={handleChange} required />
{errorMessage.state && <p className="error text-danger">{errorMessage.state}</p>}
</Col>
<Col sm={6} md={6}>
<label htmlFor="zip">Zip/Postal Code*</label>
<input type="tel" maxLength={7} name="zip" id="zip" placeholder="Zip/Postal"
value={formData.zip} onChange={handleChange} required />
{errorMessage.zip && <p className="error text-danger">{errorMessage.zip}</p>}
</Col>
<Col sm={6} md={6}>
<label htmlFor="country">Country*</label>
<input type="text" name="country" id="country" placeholder="Enter Country Name"
value={formData.country} onChange={handleChange} required />
{errorMessage.country && <p className="error text-danger">{errorMessage.country}</p>}
</Col>
<label htmlFor="gender">Gender*</label>
<input type="radio" name="gender" id="male" value="Male" className='radio'
checked={formData.gender === 'Male'} onChange={handleChange} required />Male
<input type="radio" name="gender" id="female" value="Female" className='radio'
checked={formData.gender === 'Female'} onChange={handleChange} required />Female
<input type="radio" name="gender" id="other" value="Other" className='radio'
checked={formData.gender === 'Other'} onChange={handleChange} required />Other
{errorMessage.gender && <p className="error text-danger">{errorMessage.gender}</p>}
<Col sm={6} md={12}>
<label htmlFor="address">Address*</label>
<input type="text" name="address" id="address" placeholder="Your Address"
value={formData.address} onChange={handleChange} required />
{errorMessage.address && <p className="error text-danger">{errorMessage.address}</p>}
</Col>
<Col sm={6} md={6}>
<button type="button" onClick={handleReset}>Reset</button>
</Col>
<Col sm={6} md={6}>
<button type="submit">{isEditing ? 'Update' : 'Submit'}</button>
</Col>
</Row>
</Col>
</Row>
</form>
</fieldset>
</div>
<br /><br />
<div className='contain-table'>
<table className="table table-striped">
<thead>
<tr>
<th>No.</th>
<th>Name</th>
<th>Email</th>
<th>Phone No.</th>
<th>DOB</th>
<th>Gender</th>
<th>UserName</th>
<th>City</th>
<th>Country</th>
<th colSpan={2} className="text-center">Actions</th>
</tr>
</thead>
<tbody>
{submissions.map((submission, index) => (
<tr key={index}>
<td>{index + 1}</td>
<td>{submission.name}</td>
<td>{submission.email}</td>
<td>{submission.number}</td>
<td>{submission.DOB}</td>
<td>{submission.gender}</td>
<td>{submission.username}</td>
<td>{submission.city}</td>
<td>{submission.country}</td>
<td>
<button onClick={() => handleEdit(index)} className="button">Edit</button>
<button onClick={() => handleDelete(index)} className="button">Delete</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</>
);
}
export default Form1;
Date
object – Rooftree