formspree added

main
gitea 1 month ago
parent 5f190964b4
commit 71b1064aa9

@ -1,7 +1,7 @@
'use client';
import { useState } from 'react';
import { motion } from 'framer-motion';
import { motion, AnimatePresence } from 'framer-motion';
import Navigation from '@/components/Navigation';
import Footer from '@/components/Footer';
@ -12,25 +12,52 @@ export default function FeedbackPage() {
message: '',
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [status, setStatus] = useState<'idle' | 'submitting' | 'success' | 'error'>('idle');
const [errorMessage, setErrorMessage] = useState('');
const handleSubmit = async (e: React.FormEvent) => {
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setIsSubmitting(true);
// Handle form submission here
console.log('Feedback submitted:', formData);
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 500));
alert('Thank you for your feedback! We appreciate your input.');
setFormData({
name: '',
email: '',
message: '',
});
setIsSubmitting(false);
setStatus('submitting');
setErrorMessage('');
const form = e.currentTarget;
const data = new FormData(form);
try {
const response = await fetch(form.action, {
method: form.method,
body: data,
headers: {
'Accept': 'application/json',
},
});
if (response.ok) {
setStatus('success');
setFormData({
name: '',
email: '',
message: '',
});
form.reset();
// Reset success message after 5 seconds
setTimeout(() => {
setStatus('idle');
}, 5000);
} else {
const data = await response.json();
if (data.errors) {
setErrorMessage(data.errors.map((error: { message: string }) => error.message).join(', '));
} else {
setErrorMessage('Oops! There was a problem submitting your form.');
}
setStatus('error');
}
} catch (error) {
setErrorMessage('Oops! There was a problem submitting your form.');
setStatus('error');
}
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
@ -64,10 +91,76 @@ export default function FeedbackPage() {
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.2, ease: [0.25, 0.1, 0.25, 1] }}
>
<form
onSubmit={handleSubmit}
className="space-y-6"
>
<AnimatePresence mode="wait">
{status === 'success' ? (
<motion.div
key="success"
initial={{ opacity: 0, scale: 0.8, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ duration: 0.5, ease: [0.25, 0.1, 0.25, 1] }}
className="text-center py-12 px-6 rounded-2xl"
style={{ backgroundColor: '#FBF7F4' }}
>
<motion.div
initial={{ scale: 0 }}
animate={{ scale: 1 }}
transition={{
type: 'spring',
stiffness: 200,
damping: 15,
delay: 0.2
}}
className="w-20 h-20 mx-auto mb-6 rounded-full flex items-center justify-center"
style={{ backgroundColor: '#EED2CC' }}
>
<motion.svg
initial={{ pathLength: 0 }}
animate={{ pathLength: 1 }}
transition={{ duration: 0.5, delay: 0.4 }}
className="w-10 h-10"
fill="none"
stroke="#00171F"
strokeWidth="3"
viewBox="0 0 24 24"
>
<motion.path
strokeLinecap="round"
strokeLinejoin="round"
d="M5 13l4 4L19 7"
/>
</motion.svg>
</motion.div>
<motion.h3
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
style={{ color: '#00171F' }}
className="text-2xl md:text-3xl font-bold mb-3"
>
Thanks for your submission!
</motion.h3>
<motion.p
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.4 }}
style={{ color: '#00171F' }}
className="text-lg opacity-90"
>
Your feedback helps me improve my services.
</motion.p>
</motion.div>
) : (
<motion.form
key="form"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onSubmit={handleSubmit}
action="https://formspree.io/f/mkgyzzqw"
method="POST"
className="space-y-6"
>
<div>
<label htmlFor="name" className="block text-sm font-medium mb-2" style={{ color: '#00171F' }}>
Name <span className="text-red-500">*</span>
@ -90,7 +183,7 @@ export default function FeedbackPage() {
<div>
<label htmlFor="email" className="block text-sm font-medium mb-2" style={{ color: '#00171F' }}>
Email (optional)
Email
</label>
<input
type="email"
@ -105,7 +198,9 @@ export default function FeedbackPage() {
backgroundColor: '#FBF7F4'
}}
/>
<p className="text-sm mt-1 opacity-70" style={{ color: '#00171F' }}>
Optional - but helpful if we need to follow up
</p>
</div>
<div>
@ -128,15 +223,51 @@ export default function FeedbackPage() {
/>
</div>
<button
type="submit"
disabled={isSubmitting}
style={{ backgroundColor: '#00171F' }}
className="w-full text-white px-8 py-4 rounded-full text-lg font-semibold hover:opacity-90 transition-all transform hover:scale-105 shadow-lg hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none"
>
{isSubmitting ? 'Sending...' : 'Send Feedback'}
</button>
</form>
<AnimatePresence>
{errorMessage && (
<motion.div
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
className="p-4 rounded-lg border"
style={{
backgroundColor: '#FBF7F4',
borderColor: '#EED2CC',
color: '#00171F'
}}
>
<p className="text-sm">{errorMessage}</p>
</motion.div>
)}
</AnimatePresence>
<button
type="submit"
disabled={status === 'submitting'}
style={{ backgroundColor: '#00171F' }}
className="w-full text-white px-8 py-4 rounded-full text-lg font-semibold hover:opacity-90 transition-all transform hover:scale-105 shadow-lg hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none"
>
{status === 'submitting' ? (
<span className="flex items-center justify-center">
<motion.svg
animate={{ rotate: 360 }}
transition={{ duration: 1, repeat: Infinity, ease: 'linear' }}
className="w-5 h-5 mr-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</motion.svg>
Sending...
</span>
) : (
'Send Feedback'
)}
</button>
</motion.form>
)}
</AnimatePresence>
</motion.div>
</div>
</section>

@ -1,10 +1,9 @@
'use client';
import { useState } from 'react';
import { motion } from 'framer-motion';
import { motion, AnimatePresence } from 'framer-motion';
export default function Contact() {
const [formData, setFormData] = useState({
firstName: '',
lastName: '',
@ -13,18 +12,54 @@ export default function Contact() {
message: '',
});
const handleSubmit = (e: React.FormEvent) => {
const [status, setStatus] = useState<'idle' | 'submitting' | 'success' | 'error'>('idle');
const [errorMessage, setErrorMessage] = useState('');
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
// Handle form submission here
console.log('Form submitted:', formData);
alert('Thank you for your message! We will get back to you soon.');
setFormData({
firstName: '',
lastName: '',
email: '',
phone: '',
message: '',
});
setStatus('submitting');
setErrorMessage('');
const form = e.currentTarget;
const data = new FormData(form);
try {
const response = await fetch(form.action, {
method: form.method,
body: data,
headers: {
'Accept': 'application/json',
},
});
if (response.ok) {
setStatus('success');
setFormData({
firstName: '',
lastName: '',
email: '',
phone: '',
message: '',
});
form.reset();
// Reset success message after 5 seconds
setTimeout(() => {
setStatus('idle');
}, 5000);
} else {
const data = await response.json();
if (data.errors) {
setErrorMessage(data.errors.map((error: { message: string }) => error.message).join(', '));
} else {
setErrorMessage('Oops! There was a problem submitting your form.');
}
setStatus('error');
}
} catch (error) {
setErrorMessage('Oops! There was a problem submitting your form.');
setStatus('error');
}
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
@ -61,10 +96,76 @@ export default function Contact() {
viewport={{ once: true, margin: '-100px' }}
transition={{ duration: 0.8, delay: 0.2, ease: [0.25, 0.1, 0.25, 1] }}
>
<form
onSubmit={handleSubmit}
className="space-y-6"
>
<AnimatePresence mode="wait">
{status === 'success' ? (
<motion.div
key="success"
initial={{ opacity: 0, scale: 0.8, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ duration: 0.5, ease: [0.25, 0.1, 0.25, 1] }}
className="text-center py-12 px-6 rounded-2xl"
style={{ backgroundColor: '#FBF7F4' }}
>
<motion.div
initial={{ scale: 0 }}
animate={{ scale: 1 }}
transition={{
type: 'spring',
stiffness: 200,
damping: 15,
delay: 0.2
}}
className="w-20 h-20 mx-auto mb-6 rounded-full flex items-center justify-center"
style={{ backgroundColor: '#EED2CC' }}
>
<motion.svg
initial={{ pathLength: 0 }}
animate={{ pathLength: 1 }}
transition={{ duration: 0.5, delay: 0.4 }}
className="w-10 h-10"
fill="none"
stroke="#00171F"
strokeWidth="3"
viewBox="0 0 24 24"
>
<motion.path
strokeLinecap="round"
strokeLinejoin="round"
d="M5 13l4 4L19 7"
/>
</motion.svg>
</motion.div>
<motion.h3
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
style={{ color: '#00171F' }}
className="text-2xl md:text-3xl font-bold mb-3"
>
Thank you for your message!
</motion.h3>
<motion.p
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.4 }}
style={{ color: '#00171F' }}
className="text-lg opacity-90"
>
I&apos;ll get back to you soon.
</motion.p>
</motion.div>
) : (
<motion.form
key="form"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onSubmit={handleSubmit}
action="https://formspree.io/f/mpwblljv"
method="POST"
className="space-y-6"
>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label htmlFor="firstName" className="block text-sm font-medium mb-2" style={{ color: '#00171F' }}>
@ -144,14 +245,51 @@ export default function Contact() {
/>
</div>
<button
type="submit"
style={{ backgroundColor: '#00171F' }}
className="w-full text-white px-8 py-4 rounded-full text-lg font-semibold hover:opacity-90 transition-all transform hover:scale-105 shadow-lg hover:shadow-xl"
>
Send
</button>
</form>
<AnimatePresence>
{errorMessage && (
<motion.div
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
className="p-4 rounded-lg border"
style={{
backgroundColor: '#FBF7F4',
borderColor: '#EED2CC',
color: '#00171F'
}}
>
<p className="text-sm">{errorMessage}</p>
</motion.div>
)}
</AnimatePresence>
<button
type="submit"
disabled={status === 'submitting'}
style={{ backgroundColor: '#00171F' }}
className="w-full text-white px-8 py-4 rounded-full text-lg font-semibold hover:opacity-90 transition-all transform hover:scale-105 shadow-lg hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none"
>
{status === 'submitting' ? (
<span className="flex items-center justify-center">
<motion.svg
animate={{ rotate: 360 }}
transition={{ duration: 1, repeat: Infinity, ease: 'linear' }}
className="w-5 h-5 mr-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</motion.svg>
Sending...
</span>
) : (
'Send'
)}
</button>
</motion.form>
)}
</AnimatePresence>
</motion.div>
</div>
</section>

Loading…
Cancel
Save

Powered by TurnKey Linux.