deafgain-website/src/pages/Contact.tsx

182 lines
6.3 KiB
TypeScript

import { useState } from 'react'
import { motion } from 'framer-motion'
import { FaEnvelope, FaMapMarkerAlt } from 'react-icons/fa'
import { useNotification } from '../context/notification-context'
const Contact = () => {
const { showNotification } = useNotification()
const [isSubmitting, setIsSubmitting] = useState(false)
const [formData, setFormData] = useState({
name: '',
email: '',
message: '',
website: '' // Honeypot field
})
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (isSubmitting) return
setIsSubmitting(true)
try {
const response = await fetch('/api/contact', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
})
const data = await response.json()
if (data.success) {
showNotification('Message sent successfully!', 'success')
setFormData({ name: '', email: '', message: '', website: '' })
} else {
showNotification(data.message || 'Failed to send message', 'error')
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'An error occurred. Please try again later.'
showNotification(errorMessage, 'error')
} finally {
setTimeout(() => {
setIsSubmitting(false)
}, 1000)
}
}
const contactInfo = [
{
icon: <FaEnvelope className="text-2xl sm:text-3xl" />,
title: 'Email',
content: 'contact@deafgain.com'
},
{
icon: <FaMapMarkerAlt className="text-2xl sm:text-3xl" />,
title: 'Location',
content: 'Montana, United States'
}
]
return (
<div className="min-h-screen bg-accent-snow">
<div className="max-w-7xl mx-auto px-4 py-12 sm:py-20">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }}
className="text-center mb-8 sm:mb-16"
>
<h1 className="text-3xl sm:text-4xl font-bold text-secondary mb-4">Get in Touch</h1>
<p className="text-accent-mountain text-base sm:text-lg max-w-2xl mx-auto px-4">
We're here to help and answer any questions you might have
</p>
</motion.div>
<div className="grid sm:grid-cols-2 gap-6 mb-12 max-w-2xl mx-auto">
{contactInfo.map((info, index) => (
<motion.div
key={index}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.2 }}
className="bg-white p-6 rounded-lg shadow-lg text-center"
>
<div className="text-primary mb-4">{info.icon}</div>
<h3 className="text-lg sm:text-xl font-semibold mb-2">{info.title}</h3>
<p className="text-accent-mountain">{info.content}</p>
</motion.div>
))}
</div>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.4 }}
className="max-w-2xl mx-auto bg-white rounded-lg shadow-lg p-6 sm:p-8"
>
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label htmlFor="name" className="block text-accent-mountain mb-2 text-sm sm:text-base">
Name
</label>
<input
type="text"
id="name"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
className="w-full px-4 py-3 border border-accent-lake rounded-lg focus:outline-none focus:border-primary
text-base sm:text-lg"
required
minLength={2}
maxLength={50}
/>
</div>
<div>
<label htmlFor="email" className="block text-accent-mountain mb-2 text-sm sm:text-base">
Email
</label>
<input
type="email"
id="email"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
className="w-full px-4 py-3 border border-accent-lake rounded-lg focus:outline-none focus:border-primary
text-base sm:text-lg"
required
pattern="[^@\s]+@[^@\s]+\.[^@\s]+"
/>
</div>
{/* Honeypot field - hidden from humans, visible to bots */}
<div className="absolute left-[-5000px] opacity-0" aria-hidden="true">
<label htmlFor="website">Website</label>
<input
type="text"
id="website"
name="website"
value={formData.website}
onChange={(e) => setFormData({ ...formData, website: e.target.value })}
tabIndex={-1}
autoComplete="off"
/>
</div>
<div>
<label htmlFor="message" className="block text-accent-mountain mb-2 text-sm sm:text-base">
Message
</label>
<textarea
id="message"
value={formData.message}
onChange={(e) => setFormData({ ...formData, message: e.target.value })}
className="w-full px-4 py-3 border border-accent-lake rounded-lg focus:outline-none focus:border-primary
text-base sm:text-lg min-h-[120px] sm:min-h-[150px]"
required
minLength={10}
maxLength={1000}
/>
</div>
<motion.button
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
type="submit"
disabled={isSubmitting}
className={`w-full py-4 rounded-lg font-semibold text-base sm:text-lg transition-colors
${isSubmitting
? 'bg-accent-mountain text-accent-snow cursor-not-allowed'
: 'bg-primary text-accent-snow hover:bg-secondary active:bg-secondary'
}`}
>
{isSubmitting ? 'Sending...' : 'Send Message'}
</motion.button>
</form>
</motion.div>
</div>
</div>
)
}
export default Contact