mirror of
https://github.com/sergeyyarkov/devthread.ru.git
synced 2026-10-11 18:29:10 +03:00
form validation
This commit is contained in:
parent
ab68bca48e
commit
63a7c9e62b
5
package-lock.json
generated
5
package-lock.json
generated
@ -17297,6 +17297,11 @@
|
|||||||
"react-side-effect": "^2.1.0"
|
"react-side-effect": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-hook-form": {
|
||||||
|
"version": "6.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-6.0.8.tgz",
|
||||||
|
"integrity": "sha512-lf1TTuRuqHkYJqDtNIgDu9Rk7euKWkFaG2+XZ3FSkngiFWR72Lj96/FeSGF+ZMylCLdCFq2F059kzucVKWvDiQ=="
|
||||||
|
},
|
||||||
"react-hot-loader": {
|
"react-hot-loader": {
|
||||||
"version": "4.12.21",
|
"version": "4.12.21",
|
||||||
"resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-4.12.21.tgz",
|
"resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-4.12.21.tgz",
|
||||||
|
|||||||
@ -46,7 +46,8 @@
|
|||||||
"react": "^16.12.0",
|
"react": "^16.12.0",
|
||||||
"react-dom": "^16.12.0",
|
"react-dom": "^16.12.0",
|
||||||
"react-flexbox-grid": "^2.1.2",
|
"react-flexbox-grid": "^2.1.2",
|
||||||
"react-helmet": "^6.1.0"
|
"react-helmet": "^6.1.0",
|
||||||
|
"react-hook-form": "^6.0.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "2.0.5"
|
"prettier": "2.0.5"
|
||||||
|
|||||||
@ -30,7 +30,7 @@ const ArticleCard = ({
|
|||||||
<div className="article-card__tags">
|
<div className="article-card__tags">
|
||||||
<ul>
|
<ul>
|
||||||
{tags.map((tag, i) => (
|
{tags.map((tag, i) => (
|
||||||
<li key={i}>
|
<li className="tag-item" key={i}>
|
||||||
<Link to={`/tag/${tag}`}>{tag}</Link>
|
<Link to={`/tag/${tag}`}>{tag}</Link>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -34,18 +34,6 @@
|
|||||||
& li {
|
& li {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
& a {
|
|
||||||
padding: 5px 10px;
|
|
||||||
background: #EBF1FE;
|
|
||||||
text-decoration: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 14px;
|
|
||||||
transition: all .1s;
|
|
||||||
&:hover {
|
|
||||||
background: #d8e3fd;
|
|
||||||
color: #3972f4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
& .contacts-submitted {
|
& .contacts-submitted {
|
||||||
|
min-height: 290px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
& h2 {
|
& h2 {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
@ -40,11 +41,18 @@
|
|||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
& form {
|
& form {
|
||||||
|
& .error-info {
|
||||||
|
text-align: left;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
color: #df4e4e;
|
||||||
|
}
|
||||||
|
& .error-field {
|
||||||
|
border: 1px solid #ff3737;
|
||||||
|
}
|
||||||
& .form-content {
|
& .form-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 0 20px;
|
|
||||||
}
|
}
|
||||||
& input {
|
& input {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
|
import { useForm } from "react-hook-form"
|
||||||
|
|
||||||
function encode(data) {
|
function encode(data) {
|
||||||
return Object.keys(data)
|
return Object.keys(data)
|
||||||
@ -7,6 +8,7 @@ function encode(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ContactsFrom = () => {
|
const ContactsFrom = () => {
|
||||||
|
const { register, handleSubmit, errors } = useForm()
|
||||||
const [state, setState] = React.useState({})
|
const [state, setState] = React.useState({})
|
||||||
const [submitted, setSubmitted] = React.useState(false)
|
const [submitted, setSubmitted] = React.useState(false)
|
||||||
const [error, setError] = React.useState(false)
|
const [error, setError] = React.useState(false)
|
||||||
@ -15,18 +17,19 @@ const ContactsFrom = () => {
|
|||||||
setState({ ...state, [e.target.name]: e.target.value })
|
setState({ ...state, [e.target.name]: e.target.value })
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSubmit = e => {
|
const onSubmit = () => {
|
||||||
e.preventDefault()
|
|
||||||
const form = e.target
|
|
||||||
fetch("/", {
|
fetch("/", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||||
body: encode({
|
body: encode({
|
||||||
"form-name": form.getAttribute("name"),
|
"form-name": "contact",
|
||||||
...state,
|
...state,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
.then(() => setSubmitted(true))
|
.then(() => {
|
||||||
|
setSubmitted(true)
|
||||||
|
setState({})
|
||||||
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
setError(true)
|
setError(true)
|
||||||
@ -72,40 +75,59 @@ const ContactsFrom = () => {
|
|||||||
<div className="contacts-form">
|
<div className="contacts-form">
|
||||||
<h2>форма обратной связи</h2>
|
<h2>форма обратной связи</h2>
|
||||||
<form
|
<form
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
name="contact"
|
name="contact"
|
||||||
method="POST"
|
method="POST"
|
||||||
data-netlify="true"
|
data-netlify="true"
|
||||||
data-netlify-honeypot="bot-field"
|
data-netlify-honeypot="bot-field"
|
||||||
>
|
>
|
||||||
|
{Object.keys(errors).filter(
|
||||||
|
field =>
|
||||||
|
errors[field].type === "required" ||
|
||||||
|
errors[field].type === "pattern"
|
||||||
|
).length > 0 ? (
|
||||||
|
<p className="error-info">* Заполните все поля в нужном формате </p>
|
||||||
|
) : null}
|
||||||
<div hidden>
|
<div hidden>
|
||||||
Не заполняйте это
|
Не заполняйте это
|
||||||
<input name="bot-field" onChange={handleChange} />
|
<input name="bot-field" onChange={handleChange} />
|
||||||
</div>
|
</div>
|
||||||
<div className="form-content">
|
<div className="form-content">
|
||||||
<input
|
<input
|
||||||
|
className={errors.name ? "error-field" : null}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
name="name"
|
name="name"
|
||||||
placeholder="Ваше имя"
|
placeholder="Введите ваше имя"
|
||||||
type="text"
|
type="text"
|
||||||
|
ref={register({ required: true, maxLength: 100 })}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
|
className={errors.email ? "error-field" : null}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
name="email"
|
name="email"
|
||||||
placeholder="Ваша почта"
|
placeholder="Ваша почта example@email.com"
|
||||||
type="email"
|
type="email"
|
||||||
|
ref={register({
|
||||||
|
required: true,
|
||||||
|
pattern: /^\S+@\S+$/i,
|
||||||
|
maxLength: 100,
|
||||||
|
})}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
|
className={errors.subject ? "error-field" : null}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
name="subject"
|
name="subject"
|
||||||
placeholder="Тема сообщения"
|
placeholder="Тема сообщения"
|
||||||
type="text"
|
type="text"
|
||||||
|
ref={register({ required: true })}
|
||||||
/>
|
/>
|
||||||
<textarea
|
<textarea
|
||||||
|
className={errors.message ? "error-field" : null}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
name="message"
|
name="message"
|
||||||
placeholder="Ваше сообщение..."
|
placeholder="Ваше сообщение..."
|
||||||
defaultValue={""}
|
defaultValue={""}
|
||||||
|
ref={register({ required: true })}
|
||||||
/>
|
/>
|
||||||
<div className="submit-btn">
|
<div className="submit-btn">
|
||||||
<button className="btn-primary" type="submit">
|
<button className="btn-primary" type="submit">
|
||||||
|
|||||||
@ -51,6 +51,9 @@ header {
|
|||||||
& .telegram-svg-social {
|
& .telegram-svg-social {
|
||||||
fill: #0088cc;
|
fill: #0088cc;
|
||||||
}
|
}
|
||||||
|
& .yadzen-svg-social {
|
||||||
|
fill: #2E3238;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
& a {
|
& a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@ -132,6 +135,9 @@ header {
|
|||||||
& .telegram-svg-social {
|
& .telegram-svg-social {
|
||||||
fill: #0088cc;
|
fill: #0088cc;
|
||||||
}
|
}
|
||||||
|
& .yadzen-svg-social {
|
||||||
|
fill: #2E3238;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
& svg {
|
& svg {
|
||||||
& .telegram-svg-social {
|
& .telegram-svg-social {
|
||||||
@ -232,6 +238,19 @@ header {
|
|||||||
& .twitter-svg-social {
|
& .twitter-svg-social {
|
||||||
fill: $white-clr;
|
fill: $white-clr;
|
||||||
}
|
}
|
||||||
|
& .yadzen-svg-social {
|
||||||
|
fill: $white-clr;
|
||||||
|
&_black {
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& svg:hover {
|
||||||
|
& .yadzen-svg-social {
|
||||||
|
&_black {
|
||||||
|
fill: $white-clr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
& .header-nav__links {
|
& .header-nav__links {
|
||||||
@ -282,6 +301,16 @@ header {
|
|||||||
}
|
}
|
||||||
& .yadzen-svg-social {
|
& .yadzen-svg-social {
|
||||||
fill: $white-clr;
|
fill: $white-clr;
|
||||||
|
&_black {
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& svg:hover {
|
||||||
|
& .yadzen-svg-social {
|
||||||
|
&_black {
|
||||||
|
fill: $white-clr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<g clip-path="url(#yadzen-icon)">
|
<g clip-path="url(#yadzen-icon)">
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.40624 0C4.90261 0.000333036 2.47489 0.0119894 1.22873 1.22891C0.0118761 2.47479 0.000217256 5.01652 0.000217256 8.40618C3.76404 8.2926 5.48522 8.19836 6.85797 6.85787C8.19838 5.48512 8.29266 3.76398 8.40624 0ZM1.22851 15.7712C0.0116588 14.5253 0 11.9836 0 8.59396C3.76383 8.70754 5.48501 8.80178 6.85776 10.1423C8.19817 11.515 8.29245 13.2362 8.40603 16.9998C4.9024 16.9998 2.47468 16.9885 1.22851 15.7712ZM8.59392 16.9998C8.7075 13.2362 8.80178 11.515 10.1422 10.1423C11.5149 8.80178 13.2361 8.70754 17 8.59396C16.9996 11.9836 16.988 14.5253 15.7711 15.7712C14.5249 16.9885 12.0976 16.9998 8.59392 16.9998ZM8.59392 0C8.7075 3.76398 8.80178 5.48512 10.1422 6.85787C11.5149 8.19836 13.2361 8.2926 17 8.40618C16.9996 5.01652 16.988 2.47479 15.7711 1.22891C14.5249 0.0119894 12.0976 0.000333036 8.59392 0Z" fill="black"/>
|
<path class="yadzen-svg-social" fill-rule="evenodd" clip-rule="evenodd" d="M8.40624 0C4.90261 0.000333036 2.47489 0.0119894 1.22873 1.22891C0.0118761 2.47479 0.000217256 5.01652 0.000217256 8.40618C3.76404 8.2926 5.48522 8.19836 6.85797 6.85787C8.19838 5.48512 8.29266 3.76398 8.40624 0ZM1.22851 15.7712C0.0116588 14.5253 0 11.9836 0 8.59396C3.76383 8.70754 5.48501 8.80178 6.85776 10.1423C8.19817 11.515 8.29245 13.2362 8.40603 16.9998C4.9024 16.9998 2.47468 16.9885 1.22851 15.7712ZM8.59392 16.9998C8.7075 13.2362 8.80178 11.515 10.1422 10.1423C11.5149 8.80178 13.2361 8.70754 17 8.59396C16.9996 11.9836 16.988 14.5253 15.7711 15.7712C14.5249 16.9885 12.0976 16.9998 8.59392 16.9998ZM8.59392 0C8.7075 3.76398 8.80178 5.48512 10.1422 6.85787C11.5149 8.19836 13.2361 8.2926 17 8.40618C16.9996 5.01652 16.988 2.47479 15.7711 1.22891C14.5249 0.0119894 12.0976 0.000333036 8.59392 0Z" fill="black"/>
|
||||||
<path class="yadzen-svg-social" fill-rule="evenodd" clip-rule="evenodd" d="M10.1422 10.1423C8.80178 11.515 8.7075 13.2362 8.59392 16.9998C12.0976 16.9998 14.5249 16.9885 15.7711 15.7712C16.988 14.5253 16.9996 11.9836 17 8.59396C13.2362 8.70754 11.5149 8.80178 10.1422 10.1423ZM0 8.59396C0 11.9836 0.0116588 14.5253 1.22851 15.7712C2.47468 16.9885 4.9024 16.9998 8.40603 16.9998C8.29245 13.2362 8.19817 11.515 6.85776 10.1423C5.48501 8.80178 3.76383 8.70754 0 8.59396ZM8.40624 0C4.90261 0.000333036 2.47489 0.0119894 1.22873 1.22891C0.0118761 2.47479 0.000217256 5.01652 0.000217256 8.40618C3.76404 8.2926 5.48522 8.19836 6.85797 6.85787C8.19838 5.48512 8.29266 3.76398 8.40624 0ZM10.1422 6.85787C8.80178 5.48512 8.7075 3.76398 8.59392 0C12.0976 0.000333036 14.5249 0.0119894 15.7711 1.22891C16.988 2.47479 16.9996 5.01652 17 8.40618C13.2362 8.2926 11.5149 8.19836 10.1422 6.85787Z" fill="url(#paint0_linear)"/>
|
<path class="yadzen-svg-social" fill-rule="evenodd" clip-rule="evenodd" d="M10.1422 10.1423C8.80178 11.515 8.7075 13.2362 8.59392 16.9998C12.0976 16.9998 14.5249 16.9885 15.7711 15.7712C16.988 14.5253 16.9996 11.9836 17 8.59396C13.2362 8.70754 11.5149 8.80178 10.1422 10.1423ZM0 8.59396C0 11.9836 0.0116588 14.5253 1.22851 15.7712C2.47468 16.9885 4.9024 16.9998 8.40603 16.9998C8.29245 13.2362 8.19817 11.515 6.85776 10.1423C5.48501 8.80178 3.76383 8.70754 0 8.59396ZM8.40624 0C4.90261 0.000333036 2.47489 0.0119894 1.22873 1.22891C0.0118761 2.47479 0.000217256 5.01652 0.000217256 8.40618C3.76404 8.2926 5.48522 8.19836 6.85797 6.85787C8.19838 5.48512 8.29266 3.76398 8.40624 0ZM10.1422 6.85787C8.80178 5.48512 8.7075 3.76398 8.59392 0C12.0976 0.000333036 14.5249 0.0119894 15.7711 1.22891C16.988 2.47479 16.9996 5.01652 17 8.40618C13.2362 8.2926 11.5149 8.19836 10.1422 6.85787Z" fill="url(#paint0_linear)"/>
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M17 8.59466V8.50074V8.40713C13.2361 8.29323 11.5149 8.19934 10.1422 6.85854C8.80179 5.48607 8.70751 3.76496 8.59392 0.000976562H8.49996H8.40604C8.29246 3.76496 8.19818 5.48607 6.85773 6.85854C5.48498 8.19934 3.7638 8.29323 0 8.40713V8.50074V8.59466C3.7638 8.70853 5.48498 8.80245 6.85773 10.1429C8.19818 11.5157 8.29246 13.2368 8.40604 17.0008H8.49996H8.59392C8.70751 13.2368 8.80179 11.5157 10.1422 10.1429C11.5149 8.80245 13.2361 8.70853 17 8.59466Z" fill="white"/>
|
<path class="yadzen-svg-social_black" fill-rule="evenodd" clip-rule="evenodd" d="M17 8.59466V8.50074V8.40713C13.2361 8.29323 11.5149 8.19934 10.1422 6.85854C8.80179 5.48607 8.70751 3.76496 8.59392 0.000976562H8.49996H8.40604C8.29246 3.76496 8.19818 5.48607 6.85773 6.85854C5.48498 8.19934 3.7638 8.29323 0 8.40713V8.50074V8.59466C3.7638 8.70853 5.48498 8.80245 6.85773 10.1429C8.19818 11.5157 8.29246 13.2368 8.40604 17.0008H8.49996H8.59392C8.70751 13.2368 8.80179 11.5157 10.1422 10.1429C11.5149 8.80245 13.2361 8.70853 17 8.59466Z" fill="white"/>
|
||||||
</g>
|
</g>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="paint0_linear" x1="17" y1="16.9998" x2="17" y2="0" gradientUnits="userSpaceOnUse">
|
<linearGradient id="paint0_linear" x1="17" y1="16.9998" x2="17" y2="0" gradientUnits="userSpaceOnUse">
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.0 KiB |
@ -40,7 +40,6 @@
|
|||||||
color: #6ab0f3;
|
color: #6ab0f3;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
transition: all .1s;
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #d8e3fd;
|
background: #d8e3fd;
|
||||||
color: #3972f4;
|
color: #3972f4;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user