This commit is contained in:
+2273
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,8 @@
|
|||||||
"react": "^19.3.1",
|
"react": "^19.3.1",
|
||||||
"react-dom": "^19.3.1",
|
"react-dom": "^19.3.1",
|
||||||
"react-icons": "^5.7.0",
|
"react-icons": "^5.7.0",
|
||||||
"react-router-dom": "^7.18.4"
|
"react-router-dom": "^7.18.5",
|
||||||
|
"validator": "^13.15.35"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^19.3.0",
|
"@types/react": "^19.3.0",
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import validate from '../../utils/validators/validate';
|
import validate from '../../utils/validators/validate';
|
||||||
|
|
||||||
const FormContact = (props) => {
|
const INITIAL_FORM_DATA = {
|
||||||
// const { } = props;
|
|
||||||
|
|
||||||
const [formData, setFormData] = useState({
|
|
||||||
firstname: '', //
|
firstname: '', //
|
||||||
lastname: '',
|
lastname: '',
|
||||||
email: '',
|
email: '',
|
||||||
message: '',
|
message: '',
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const FormContact = (props) => {
|
||||||
|
// const { } = props;
|
||||||
|
|
||||||
|
const [formData, setFormData] = useState(INITIAL_FORM_DATA);
|
||||||
|
|
||||||
const [errors, setErrors] = useState({});
|
const [errors, setErrors] = useState({});
|
||||||
|
|
||||||
@@ -25,12 +27,7 @@ const FormContact = (props) => {
|
|||||||
console.log('Form submitted ....');
|
console.log('Form submitted ....');
|
||||||
// TODO: send over AJAX/Fetch
|
// TODO: send over AJAX/Fetch
|
||||||
form.reset();
|
form.reset();
|
||||||
setFormData({
|
setFormData(INITIAL_FORM_DATA);
|
||||||
firstname: '', //
|
|
||||||
lastname: '',
|
|
||||||
email: '',
|
|
||||||
message: '',
|
|
||||||
});
|
|
||||||
setErrors({});
|
setErrors({});
|
||||||
} else {
|
} else {
|
||||||
console.warn('Form submit error');
|
console.warn('Form submit error');
|
||||||
@@ -47,6 +44,23 @@ const FormContact = (props) => {
|
|||||||
// console.log('Formdata', formData);
|
// console.log('Formdata', formData);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleBlur = (e) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
const validationErrors = validate({ ...formData, [name]: value });
|
||||||
|
|
||||||
|
setErrors((state) => {
|
||||||
|
const nextErrors = { ...state };
|
||||||
|
|
||||||
|
if (validationErrors[name]) {
|
||||||
|
nextErrors[name] = validationErrors[name];
|
||||||
|
} else {
|
||||||
|
delete nextErrors[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nextErrors;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="m-form-contact form-contact" noValidate onSubmit={handleSubmit}>
|
<form className="m-form-contact form-contact" noValidate onSubmit={handleSubmit}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
@@ -62,6 +76,7 @@ const FormContact = (props) => {
|
|||||||
className={`form-control input-firstname ${errors.firstname ? 'is-invalid' : ''}`}
|
className={`form-control input-firstname ${errors.firstname ? 'is-invalid' : ''}`}
|
||||||
value={formData.firstname}
|
value={formData.firstname}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
onBlur={handleBlur}
|
||||||
/>
|
/>
|
||||||
<div className="valid-feedback">OK</div>
|
<div className="valid-feedback">OK</div>
|
||||||
<div className="invalid-feedback">{errors?.firstname}</div>
|
<div className="invalid-feedback">{errors?.firstname}</div>
|
||||||
@@ -79,6 +94,7 @@ const FormContact = (props) => {
|
|||||||
className={`form-control input-lastname ${errors.lastname ? 'is-invalid' : ''}`}
|
className={`form-control input-lastname ${errors.lastname ? 'is-invalid' : ''}`}
|
||||||
value={formData.lastname}
|
value={formData.lastname}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
onBlur={handleBlur}
|
||||||
/>
|
/>
|
||||||
<div className="valid-feedback">OK</div>
|
<div className="valid-feedback">OK</div>
|
||||||
<div className="invalid-feedback">{errors?.lastname}</div>
|
<div className="invalid-feedback">{errors?.lastname}</div>
|
||||||
@@ -99,6 +115,7 @@ const FormContact = (props) => {
|
|||||||
className={`form-control input-email ${errors.email ? 'is-invalid' : ''}`}
|
className={`form-control input-email ${errors.email ? 'is-invalid' : ''}`}
|
||||||
value={formData.email}
|
value={formData.email}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
onBlur={handleBlur}
|
||||||
/>
|
/>
|
||||||
<div className="valid-feedback">OK</div>
|
<div className="valid-feedback">OK</div>
|
||||||
<div className="invalid-feedback">{errors?.email}</div>
|
<div className="invalid-feedback">{errors?.email}</div>
|
||||||
@@ -119,7 +136,8 @@ const FormContact = (props) => {
|
|||||||
id="textarea-message"
|
id="textarea-message"
|
||||||
className={`form-control textarea-message ${errors.message ? 'is-invalid' : ''}`}
|
className={`form-control textarea-message ${errors.message ? 'is-invalid' : ''}`}
|
||||||
value={formData.message}
|
value={formData.message}
|
||||||
onChange={handleChange}></textarea>
|
onChange={handleChange}
|
||||||
|
onBlur={handleBlur}></textarea>
|
||||||
<div className="valid-feedback">OK</div>
|
<div className="valid-feedback">OK</div>
|
||||||
<div className="invalid-feedback">{errors?.message}</div>
|
<div className="invalid-feedback">{errors?.message}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,25 +1,34 @@
|
|||||||
|
import validator from 'validator';
|
||||||
|
|
||||||
const validate = (formData) => {
|
const validate = (formData) => {
|
||||||
const errors = {};
|
const errors = {};
|
||||||
const emailRegEx = new RegExp(
|
const firstname = formData.firstname.trim();
|
||||||
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
const lastname = formData.lastname.trim();
|
||||||
);
|
const email = formData.email.trim();
|
||||||
|
const message = formData.message.trim();
|
||||||
|
|
||||||
if (!formData.firstname) {
|
if (validator.isEmpty(firstname)) {
|
||||||
errors.firstname = 'Firstname is required';
|
errors.firstname = 'Firstname is required';
|
||||||
|
} else if (!validator.isLength(firstname, { min: 2, max: 50 })) {
|
||||||
|
errors.firstname = 'Firstname must be between 2 and 50 characters';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.lastname) {
|
if (validator.isEmpty(lastname)) {
|
||||||
errors.lastname = 'Lastname is required';
|
errors.lastname = 'Lastname is required';
|
||||||
|
} else if (!validator.isLength(lastname, { min: 2, max: 60 })) {
|
||||||
|
errors.lastname = 'Lastname must be between 2 and 60 characters';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.email) {
|
if (validator.isEmpty(email)) {
|
||||||
errors.email = 'Email is required';
|
errors.email = 'Email is required';
|
||||||
} else if (!emailRegEx.test(formData.email)) {
|
} else if (!validator.isEmail(email)) {
|
||||||
errors.email = 'Email is invalid';
|
errors.email = 'Email is invalid';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.message) {
|
if (validator.isEmpty(message)) {
|
||||||
errors.message = 'Message is required';
|
errors.message = 'Message is required';
|
||||||
|
} else if (!validator.isLength(message, { min: 10, max: 1000 })) {
|
||||||
|
errors.message = 'Message must be between 10 and 1000 characters';
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# VITE_ als Präfix notwendig
|
||||||
|
VITE_SECRET_TOKEN="secret-token"
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
"react": "^19.3.1",
|
"react": "^19.3.1",
|
||||||
"react-dom": "^19.3.1",
|
"react-dom": "^19.3.1",
|
||||||
"react-icons": "^5.7.0",
|
"react-icons": "^5.7.0",
|
||||||
"react-router-dom": "^7.18.4"
|
"react-router-dom": "^7.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^19.3.0",
|
"@types/react": "^19.3.0",
|
||||||
@@ -1615,9 +1615,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "7.18.4",
|
"version": "7.18.5",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.4.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.5.tgz",
|
||||||
"integrity": "sha512-PUPQcMhMGRAslLcvtlPz/kmzBEWPhLdgLFrL7pLNepBL6dX0lWj4WD2cUYVgYCuT3jxvghYFg81cDTj44DhetQ==",
|
"integrity": "sha512-dTgvcXDOrLPrlLHrcZAqWveiK1hMSqN+rGAJzegP8HtmNkfRxOoshGWBNX3ZJ0cZjOHkRdlUJtaIhZMLLyGyPw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cookie": "^1.0.1",
|
"cookie": "^1.0.1",
|
||||||
@@ -1637,12 +1637,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router-dom": {
|
"node_modules/react-router-dom": {
|
||||||
"version": "7.18.4",
|
"version": "7.18.5",
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.4.tgz",
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.5.tgz",
|
||||||
"integrity": "sha512-yrfmJHIpDG7taCpqKjT1G5B6q3O2K+RN8/fgNf0lTjCwiPbQ0ei6vXX9ZjQR+7ld8Tr7Z5xmyMnZ8YJrphWQUw==",
|
"integrity": "sha512-9HcfDMU6JJ/fp6gJZYGwNE6RknVGS4kBjH1HkNw959mCJi70TVwdipQWv2FEol9uGpi+SZTFtVpJPtEQfayeOw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-router": "7.18.4"
|
"react-router": "7.18.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
"react": "^19.3.1",
|
"react": "^19.3.1",
|
||||||
"react-dom": "^19.3.1",
|
"react-dom": "^19.3.1",
|
||||||
"react-icons": "^5.7.0",
|
"react-icons": "^5.7.0",
|
||||||
"react-router-dom": "^7.18.4"
|
"react-router-dom": "^7.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^19.3.0",
|
"@types/react": "^19.3.0",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { BrowserRouter } from 'react-router-dom';
|
|||||||
import App from './App.jsx';
|
import App from './App.jsx';
|
||||||
|
|
||||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||||
import 'bootstrap'; // js
|
import 'bootstrap/dist/js/bootstrap.bundle.js'; // js
|
||||||
// import './styles/main.scss';
|
// import './styles/main.scss';
|
||||||
|
|
||||||
const root = createRoot(document.getElementById('root'));
|
const root = createRoot(document.getElementById('root'));
|
||||||
|
|||||||
@@ -20,8 +20,13 @@ import UserPage from '../pages/UserPage';
|
|||||||
// <RouterProvider router={router}>{/*<App />*/}</RouterProvider>;
|
// <RouterProvider router={router}>{/*<App />*/}</RouterProvider>;
|
||||||
|
|
||||||
const checkAuth = () => {
|
const checkAuth = () => {
|
||||||
|
// localStorage.setItem('token', 'secret-token'); // wird in localStorage nach erfolgreicher Anmeldung abgelegt
|
||||||
|
|
||||||
|
const passToken = import.meta.env.VITE_SECRET_TOKEN;
|
||||||
|
console.log(passToken);
|
||||||
|
|
||||||
const token = localStorage.getItem('token');
|
const token = localStorage.getItem('token');
|
||||||
return token && token === 'secret-token' ? true : false;
|
return token && token === passToken ? true : false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ProtectedRoute = (props) => {
|
const ProtectedRoute = (props) => {
|
||||||
@@ -55,7 +60,7 @@ const Router = () => {
|
|||||||
|
|
||||||
<Route path="/user" element={<UserPage />}>
|
<Route path="/user" element={<UserPage />}>
|
||||||
<Route index element={<h5>Index</h5>} />
|
<Route index element={<h5>Index</h5>} />
|
||||||
<Route path="profile" element={<h5>Profile</h5>} />
|
<Route path="profile/:userId" element={<UserProfilePage />} />
|
||||||
<Route path="dashboard" element={<h5>Dashboard</h5>} />
|
<Route path="dashboard" element={<h5>Dashboard</h5>} />
|
||||||
<Route path="settings" element={<h5>Settings</h5>} />
|
<Route path="settings" element={<h5>Settings</h5>} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
"react-dom": "^19.3.1",
|
"react-dom": "^19.3.1",
|
||||||
"react-hook-form": "^7.91.0",
|
"react-hook-form": "^7.91.0",
|
||||||
"react-icons": "^5.7.0",
|
"react-icons": "^5.7.0",
|
||||||
"react-router-dom": "^7.18.4"
|
"react-router-dom": "^7.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^19.3.0",
|
"@types/react": "^19.3.0",
|
||||||
@@ -1638,9 +1638,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "7.18.4",
|
"version": "7.18.5",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.4.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.5.tgz",
|
||||||
"integrity": "sha512-PUPQcMhMGRAslLcvtlPz/kmzBEWPhLdgLFrL7pLNepBL6dX0lWj4WD2cUYVgYCuT3jxvghYFg81cDTj44DhetQ==",
|
"integrity": "sha512-dTgvcXDOrLPrlLHrcZAqWveiK1hMSqN+rGAJzegP8HtmNkfRxOoshGWBNX3ZJ0cZjOHkRdlUJtaIhZMLLyGyPw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cookie": "^1.0.1",
|
"cookie": "^1.0.1",
|
||||||
@@ -1660,12 +1660,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router-dom": {
|
"node_modules/react-router-dom": {
|
||||||
"version": "7.18.4",
|
"version": "7.18.5",
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.4.tgz",
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.5.tgz",
|
||||||
"integrity": "sha512-yrfmJHIpDG7taCpqKjT1G5B6q3O2K+RN8/fgNf0lTjCwiPbQ0ei6vXX9ZjQR+7ld8Tr7Z5xmyMnZ8YJrphWQUw==",
|
"integrity": "sha512-9HcfDMU6JJ/fp6gJZYGwNE6RknVGS4kBjH1HkNw959mCJi70TVwdipQWv2FEol9uGpi+SZTFtVpJPtEQfayeOw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-router": "7.18.4"
|
"react-router": "7.18.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
"react-dom": "^19.3.1",
|
"react-dom": "^19.3.1",
|
||||||
"react-hook-form": "^7.91.0",
|
"react-hook-form": "^7.91.0",
|
||||||
"react-icons": "^5.7.0",
|
"react-icons": "^5.7.0",
|
||||||
"react-router-dom": "^7.18.4"
|
"react-router-dom": "^7.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^19.3.0",
|
"@types/react": "^19.3.0",
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const FormContact = (props) => {
|
|||||||
// AJAX/FETCH send to server
|
// AJAX/FETCH send to server
|
||||||
console.log('FormData: ', formData);
|
console.log('FormData: ', formData);
|
||||||
setFormData(INITIAL_FORM_DATA); // reset
|
setFormData(INITIAL_FORM_DATA); // reset
|
||||||
form.reset(); // not necessary in react
|
// e.currentTarget.reset(); // not necessary in react
|
||||||
setErrors({});
|
setErrors({});
|
||||||
} else {
|
} else {
|
||||||
console.error('Form submit error');
|
console.error('Form submit error');
|
||||||
@@ -39,7 +39,7 @@ const FormContact = (props) => {
|
|||||||
setFormData((state) => ({ ...state, [name]: value }));
|
setFormData((state) => ({ ...state, [name]: value }));
|
||||||
|
|
||||||
// console.log({ [e.target.name]: e.target.value });
|
// console.log({ [e.target.name]: e.target.value });
|
||||||
// console.log('formData: ', formData);
|
console.log('formData: ', formData);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -72,6 +72,7 @@ const FormContact = (props) => {
|
|||||||
name="lastname"
|
name="lastname"
|
||||||
id="input-lastname"
|
id="input-lastname"
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
value={formData.lastname}
|
||||||
className={`form-control ${errors.lastname ? 'is-invalid' : ''}`}
|
className={`form-control ${errors.lastname ? 'is-invalid' : ''}`}
|
||||||
/>
|
/>
|
||||||
<div className="invalid-feedback">{errors?.lastname || 'Error'}</div>
|
<div className="invalid-feedback">{errors?.lastname || 'Error'}</div>
|
||||||
@@ -89,6 +90,7 @@ const FormContact = (props) => {
|
|||||||
id="input-email"
|
id="input-email"
|
||||||
name="email"
|
name="email"
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
value={formData.email}
|
||||||
className={`form-control ${errors.email ? 'is-invalid' : ''}`}
|
className={`form-control ${errors.email ? 'is-invalid' : ''}`}
|
||||||
/>
|
/>
|
||||||
<div className="invalid-feedback">{errors?.email || 'Error'}</div>
|
<div className="invalid-feedback">{errors?.email || 'Error'}</div>
|
||||||
@@ -107,6 +109,7 @@ const FormContact = (props) => {
|
|||||||
cols="30"
|
cols="30"
|
||||||
rows="5"
|
rows="5"
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
value={formData.message}
|
||||||
className={`form-control ${errors.message ? 'is-invalid' : ''}`}></textarea>
|
className={`form-control ${errors.message ? 'is-invalid' : ''}`}></textarea>
|
||||||
<div className="invalid-feedback">{errors?.message || 'Error'}</div>
|
<div className="invalid-feedback">{errors?.message || 'Error'}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+47
-31
@@ -1,27 +1,41 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
|
// import validate from '../../../utils/validators/validate';
|
||||||
|
|
||||||
const FormContact = (props) => {
|
const FormContact = (props) => {
|
||||||
// const { } = props;
|
// const { } = props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm();
|
} = useForm();
|
||||||
|
|
||||||
// EventHandlers
|
// EventHandlers =======
|
||||||
const onSubmit = (data) => {
|
const onSubmit = (data) => {
|
||||||
// Event wird nur getriggert, wenn kein Fehler
|
|
||||||
console.log('submitted');
|
console.log('submitted');
|
||||||
console.log();
|
console.log('Form data:', data);
|
||||||
|
|
||||||
|
// fetch('/send', {
|
||||||
|
// method: 'POST',
|
||||||
|
// headers: {
|
||||||
|
// 'Content-Type': 'application/json',
|
||||||
|
// },
|
||||||
|
// body: JSON.stringify(data),
|
||||||
|
// })
|
||||||
|
// .then((res) => res.json())
|
||||||
|
// .then((data) => console.log(data))
|
||||||
|
// .catch((err) => console.error(err));
|
||||||
|
};
|
||||||
|
|
||||||
if (errors) {
|
if (errors) {
|
||||||
console.log(errors);
|
console.log(errors);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="m-form-contact form-contact" noValidate={true} onSubmit={handleSubmit(onSubmit)}>
|
<form className="m-form-contact form-contact" noValidate onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12 col-sm-6">
|
<div className="col-12 col-md">
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="input-firstname" className="form-label">
|
<label htmlFor="input-firstname" className="form-label">
|
||||||
Firstname
|
Firstname
|
||||||
@@ -31,17 +45,17 @@ const FormContact = (props) => {
|
|||||||
name="firstname"
|
name="firstname"
|
||||||
id="input-firstname"
|
id="input-firstname"
|
||||||
{...register('firstname', {
|
{...register('firstname', {
|
||||||
required: 'Firstname is required',
|
required: 'Firstname is invalid',
|
||||||
mixLength: { value: 2, message: 'Firstname must have at least 2 characters.' },
|
minLength: { value: 2, message: 'Firstname must have at least 2 Characters' },
|
||||||
maxLength: 60,
|
maxLength: 60,
|
||||||
})}
|
})}
|
||||||
className={`form-control ${errors.firstname ? 'is-invalid' : ''}`}
|
className={`form-control input-firstname ${errors.firstname ? 'is-invalid' : ''}`}
|
||||||
/>
|
/>
|
||||||
<div className="valid-feedback">OK</div>
|
<div className="valid-feedback">OK</div>
|
||||||
<div className="invalid-feedback">{errors?.firstname?.message || 'Error'}</div>
|
<div className="invalid-feedback">{errors?.firstname?.message || 'Error'}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12 col-sm-6">
|
<div className="col-12 col-md">
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="input-lastname" className="form-label">
|
<label htmlFor="input-lastname" className="form-label">
|
||||||
Lastname
|
Lastname
|
||||||
@@ -50,38 +64,37 @@ const FormContact = (props) => {
|
|||||||
type="text"
|
type="text"
|
||||||
name="lastname"
|
name="lastname"
|
||||||
id="input-lastname"
|
id="input-lastname"
|
||||||
{...register('lastname', {
|
{...register('lastname', { required: 'Lastname is invalid' })}
|
||||||
required: 'Lastname is required',
|
className={`form-control input-lastname ${errors.lastname ? 'is-invalid' : ''}`}
|
||||||
mixLength: { value: 2, message: 'Lastname must have at least 2 characters.' },
|
|
||||||
maxLength: 80,
|
|
||||||
})}
|
|
||||||
className={`form-control ${errors.lastname ? 'is-invalid' : ''}`}
|
|
||||||
/>
|
/>
|
||||||
<div className="invalid-feedback">{errors?.lastname?.message || 'Error'}</div>
|
<div className="valid-feedback">OK</div>
|
||||||
|
<div className="invalid-feedback">{errors?.lastname?.message}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="input-email" className="form-label">
|
<label htmlFor="input-email" className="form-label">
|
||||||
Email
|
E-Mail
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
id="input-email"
|
|
||||||
name="email"
|
name="email"
|
||||||
|
id="input-email"
|
||||||
{...register('email', {
|
{...register('email', {
|
||||||
required: 'Email is not valid',
|
required: 'Email is required!!!',
|
||||||
pattern:
|
pattern: { value: /^\S+@\S+\.\S+$/, message: 'Invalid email' },
|
||||||
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
|
||||||
})}
|
})}
|
||||||
className={`form-control ${errors.email ? 'is-invalid' : ''}`}
|
className={`form-control input-email ${errors.email ? 'is-invalid' : ''}`}
|
||||||
/>
|
/>
|
||||||
<div className="invalid-feedback">{errors?.email?.message || 'Error'}</div>
|
<div className="valid-feedback">OK</div>
|
||||||
|
<div className="invalid-feedback">Email is required</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
@@ -90,26 +103,29 @@ const FormContact = (props) => {
|
|||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
name="message"
|
name="message"
|
||||||
|
cols={4}
|
||||||
|
rows={6}
|
||||||
id="textarea-message"
|
id="textarea-message"
|
||||||
cols="30"
|
|
||||||
rows="5"
|
|
||||||
{...register('message', {
|
{...register('message', {
|
||||||
required: 'Message invalid',
|
required: 'Message invalid',
|
||||||
minLength: { value: 10, message: 'Message to short' },
|
minLength: { value: 10, message: 'Message to short' },
|
||||||
maxLength: { value: 1000, message: 'Message to long' },
|
|
||||||
})}
|
})}
|
||||||
className={`form-control ${errors.message ? 'is-invalid' : ''}`}></textarea>
|
className={`form-control textarea-message ${errors.message ? 'is-invalid' : ''}`}></textarea>
|
||||||
<div className="invalid-feedback">{errors?.message?.message || 'Error'}</div>
|
<div className="valid-feedback">OK</div>
|
||||||
|
<div className="invalid-feedback">{errors?.message?.message}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<button type="submit" className="btn btn-dark button-send-contact">
|
<div className="mb-3">
|
||||||
Send
|
<button type="submit" className="btn btn-dark button-form-send">
|
||||||
|
Send Message
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const validate = (formData) => {
|
const validate = (formData, requiredFiedls = []) => {
|
||||||
const errors = {};
|
const errors = {};
|
||||||
|
|
||||||
const emailRegExp = new RegExp(
|
const emailRegExp = new RegExp(
|
||||||
|
|||||||
Reference in New Issue
Block a user