Skip to content

Commit 0d5b813

Browse files
author
Andrea Aramini, INI-MBM-BNC (EXT)
committed
✨ feature: add form validation
1 parent d8d37b2 commit 0d5b813

File tree

1 file changed

+71
-22
lines changed

1 file changed

+71
-22
lines changed

src/app/components/ContactSection.jsx

+71-22
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,37 @@
11
'use client';
2-
import React, { useRef } from 'react';
2+
import React, { useEffect, useRef, useState } from 'react';
33
import Link from 'next/link';
44
import Image from 'next/image';
55
import { sendContactMeEmail } from '../lib/client.js';
66
import { motion, useAnimationControls } from 'framer-motion';
77

88
const EmailSection = () => {
9+
const [messageSent, setMessageSent] = useState(null);
10+
const [email, setEmail] = useState(null);
11+
const [subject, setSubject] = useState(null);
12+
const [message, setMessage] = useState(null);
13+
const [errors, setErrors] = useState({
14+
email: '',
15+
});
916
const formRef = useRef(null);
1017
const controls = useAnimationControls();
18+
const [isValidForm, setIsValidForm] = useState(false);
19+
20+
const validateForm = () => {
21+
let tmp = {};
22+
let anyError = false;
23+
if (!/\S+@\S+\.\S+/.test(email)) {
24+
tmp.email = 'Email is invalid.';
25+
anyError = true;
26+
} else {
27+
tmp.email = '';
28+
}
29+
if (!subject || !message || !email) {
30+
anyError = true;
31+
}
32+
setErrors(tmp);
33+
setIsValidForm(!anyError);
34+
};
1135
const handleSubmit = async (e) => {
1236
e.preventDefault();
1337
await sendContactMeEmail(
@@ -16,24 +40,36 @@ const EmailSection = () => {
1640
e.target.message.value,
1741
)
1842
.then((_) => {
43+
setMessageSent(false);
1944
formRef.current.reset();
20-
})
21-
.then((_) => {
22-
controls.set({ opacity: 0, scale: 1 });
23-
controls.start({
24-
opacity: 1,
25-
scale: 1,
26-
transition: {
27-
repeat: 1,
28-
repeatType: 'reverse',
29-
duration: 2,
30-
},
31-
});
45+
setEmail(null);
46+
setSubject(null);
47+
setMessage(null);
48+
setIsValidForm(false);
3249
})
3350
.catch((err) => {
51+
setMessageSent(true);
3452
console.log(err);
3553
});
3654
};
55+
useEffect(() => {
56+
if (email !== null || subject !== null || message !== null) {
57+
validateForm();
58+
}
59+
if (messageSent !== null && !messageSent) {
60+
controls.set({ opacity: 0, scale: 1 });
61+
controls.start({
62+
opacity: 1,
63+
scale: 1,
64+
transition: {
65+
repeat: 1,
66+
repeatType: 'reverse',
67+
duration: 2,
68+
},
69+
});
70+
setMessageSent(null);
71+
}
72+
}, [messageSent, email, subject, message]);
3773
return (
3874
<section
3975
id="contact"
@@ -78,13 +114,17 @@ const EmailSection = () => {
78114
>
79115
Your email
80116
</label>
117+
{errors.email && (
118+
<p className="text-red-500 text-sm mb-2 block">{errors.email}</p>
119+
)}
81120
<input
82121
name="email"
83122
type="text"
84123
id="email"
85124
required
86125
className="bg-secondaryBackgroud border border-primaryBorder placeholder-primaryPlaceholder text-gray-100 text-sm rounded-lg block w-full p-2.5"
87126
placeholder="lorem@ipsum.com"
127+
onChange={(e) => setEmail(e.target.value)}
88128
/>
89129
</div>
90130
<div className="mb-6">
@@ -101,6 +141,7 @@ const EmailSection = () => {
101141
required
102142
className="bg-secondaryBackgroud border border-primaryBorder placeholder-primaryPlaceholder text-gray-100 text-sm rounded-lg block w-full p-2.5"
103143
placeholder="Just saying hi"
144+
onChange={(e) => setSubject(e.target.value)}
104145
/>
105146
</div>
106147
<div className="mb-6">
@@ -114,24 +155,32 @@ const EmailSection = () => {
114155
name="message"
115156
id="message"
116157
required
117-
rows="10"
158+
rows={10}
118159
className="bg-secondaryBackgroud border border-primaryBorder placeholder-primaryPlaceholder text-gray-100 text-sm rounded-lg block w-full p-2.5"
119160
placeholder="Leave your message here..."
161+
onChange={(e) => setMessage(e.target.value)}
120162
/>
121163
</div>
122164
<button
123165
type="submit"
124-
className="rounded hover:bg-primary-400 bg-primary-600 text-primaryText w-full py-2.5 flex justify-center"
166+
className={`rounded ${isValidForm ? 'hover:bg-primary-400' : ''} bg-primary-600 text-primaryText w-full py-2.5 flex justify-center`}
167+
disabled={!isValidForm}
125168
>
126169
Send Message
127170
</button>
128-
<motion.p
129-
className="text-primary-500 text-sm mt-2 block"
130-
initial={{ opacity: 0, scale: 1 }}
131-
animate={controls}
132-
>
133-
Email sent succesfully!
134-
</motion.p>
171+
{messageSent ? (
172+
<p className="text-red-500 text-sm mt-2 block">
173+
❌ Message not set, sorry!
174+
</p>
175+
) : (
176+
<motion.p
177+
className="text-primary-500 text-sm mt-2 block"
178+
initial={{ opacity: 0, scale: 1 }}
179+
animate={controls}
180+
>
181+
✅ Email sent succesfully!
182+
</motion.p>
183+
)}
135184
</form>
136185
</div>
137186
</section>

0 commit comments

Comments
 (0)