Files
rheinsw-mono-repo/frontend/components/Contact/Section/ContactFormSection.tsx

214 lines
8.3 KiB
TypeScript

'use client'
import React, {useState} from 'react'
import {motion} from 'framer-motion'
import {Button} from '@/components/ui/button'
import ReCAPTCHA from 'react-google-recaptcha'
const ContactFormSection = () => {
const [form, setForm] = useState({
name: '',
email: '',
company: '',
phone: '',
website: '',
message: '',
})
const [captchaToken, setCaptchaToken] = useState('')
const [submitted, setSubmitted] = useState(false)
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const handleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
setForm({...form, [e.target.name]: e.target.value})
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setLoading(true)
setError('')
if (!captchaToken) {
setError('Bitte bestätige, dass du kein Roboter bist.')
setLoading(false)
return
}
const res = await fetch('/api/contact', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({...form, captcha: captchaToken}),
})
if (res.ok) {
setSubmitted(true)
setForm({
name: '',
email: '',
company: '',
phone: '',
website: '',
message: '',
})
setCaptchaToken('')
} else {
const resJson = await res.json()
setError(
resJson?.error ||
'Ein Fehler ist aufgetreten. Bitte versuche es später erneut.'
)
}
setLoading(false)
}
return (
<div className="w-full px-6 sm:px-12 py-20 text-left">
<motion.h2
className="text-2xl sm:text-3xl font-bold mb-2 text-foreground"
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5}}
>
Schreib uns eine Nachricht
</motion.h2>
<motion.p
className="text-sm mb-8 max-w-xl text-muted-foreground"
initial={{opacity: 0, y: 10}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.2}}
>
Wir freuen uns über dein Interesse und melden uns schnellstmöglich bei dir zurück.
</motion.p>
{submitted ? (
<div className="text-green-600 font-semibold text-lg">
Deine Nachricht wurde erfolgreich gesendet!
</div>
) : (
<form className="space-y-6" onSubmit={handleSubmit}>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{[
{
label: 'Dein Name *',
name: 'name',
type: 'text',
required: true,
placeholder: 'Max Mustermann'
},
{
label: 'Deine E-Mail *',
name: 'email',
type: 'email',
required: true,
placeholder: 'max@example.com'
},
{
label: 'Firmenname (optional)',
name: 'company',
type: 'text',
required: false,
placeholder: 'Mustermann GmbH'
},
{
label: 'Telefonnummer (optional)',
name: 'phone',
type: 'tel',
required: false,
placeholder: '+49 123 456789'
},
{
label: 'Webseite (optional)',
name: 'website',
type: 'url',
required: false,
placeholder: 'https://...'
},
].map((field, index) => (
<motion.div
key={field.name}
initial={{opacity: 0, y: 10}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1}}
>
<label className="block font-semibold mb-1 text-foreground">
{field.label}
</label>
<input
type={field.type}
name={field.name}
value={form[field.name as keyof typeof form]}
onChange={handleChange}
required={field.required}
placeholder={field.placeholder}
className="w-full p-3 rounded-md border bg-background text-foreground border-muted focus:outline-none focus:ring-2 focus:ring-primary transition"
/>
</motion.div>
))}
</div>
<motion.div
initial={{opacity: 0, y: 10}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.6}}
>
<label className="block font-semibold mb-1 text-foreground">
Deine Nachricht *
</label>
<textarea
name="message"
rows={4}
required
value={form.message}
onChange={handleChange}
placeholder="Worum geht es?"
className="w-full p-3 rounded-md border bg-background text-foreground border-muted focus:outline-none focus:ring-2 focus:ring-primary transition"
/>
</motion.div>
<motion.div
className="pt-2"
initial={{opacity: 0, y: 10}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.7}}
>
<ReCAPTCHA
sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY!}
onChange={(token) => setCaptchaToken(token ?? '')}
/>
</motion.div>
{error && (
<div className="text-red-600 font-medium pt-2">
{error}
</div>
)}
<motion.div
className="pt-4 flex justify-end"
initial={{opacity: 0, y: 10}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.8}}
>
<Button type="submit" disabled={loading} size="lg">
{loading ? 'Sende...' : '📩 Nachricht senden'}
</Button>
</motion.div>
</form>
)}
</div>
)
}
export default ContactFormSection