All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 27s
Build & Deploy / 🚀 Deploy (push) Successful in 34s
Build & Deploy / 🧪 QA (push) Successful in 1m46s
Build & Deploy / 🏗️ Build (push) Successful in 3m38s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 1m19s
Build & Deploy / 🔔 Notify (push) Successful in 5s
161 lines
7.3 KiB
TypeScript
161 lines
7.3 KiB
TypeScript
'use client';
|
|
|
|
import * as React from 'react';
|
|
import { m } from 'framer-motion';
|
|
import { Button } from '@/components/ui/Button';
|
|
import { sendContactFormAction } from '@/app/actions/contact';
|
|
|
|
export function ContactForm() {
|
|
const [status, setStatus] = React.useState<'idle' | 'loading' | 'success' | 'error'>('idle');
|
|
|
|
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
e.preventDefault();
|
|
setStatus('loading');
|
|
|
|
const formData = new FormData(e.currentTarget);
|
|
try {
|
|
const result = await sendContactFormAction(formData);
|
|
if (result.success) {
|
|
setStatus('success');
|
|
} else {
|
|
setStatus('error');
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
setStatus('error');
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="bg-white rounded-2xl p-8 md:p-12 shadow-xl border border-neutral-100 max-w-2xl mx-auto relative overflow-hidden">
|
|
{/* Decorative accent */}
|
|
<div className="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-primary to-primary-light" />
|
|
|
|
<div className="mb-8">
|
|
<h3 className="font-heading text-3xl font-extrabold text-neutral-dark mb-2">Projektanfrage stellen</h3>
|
|
<p className="text-text-secondary">Hinterlassen Sie uns Ihre Kontaktdaten und Details zu Ihrem Vorhaben. Wir melden uns umgehend bei Ihnen.</p>
|
|
</div>
|
|
|
|
{status === 'success' ? (
|
|
<m.div
|
|
initial={{ opacity: 0, scale: 0.95 }}
|
|
animate={{ opacity: 1, scale: 1 }}
|
|
className="bg-primary/10 border border-primary text-primary p-6 rounded-xl flex items-start gap-4"
|
|
>
|
|
<div className="bg-primary text-white rounded-full p-1 mt-0.5">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>
|
|
</div>
|
|
<div>
|
|
<h4 className="font-bold text-lg mb-1">Anfrage erfolgreich gesendet</h4>
|
|
<p>Vielen Dank für Ihr Interesse an der E-TIB Gruppe. Ein Ansprechpartner wird sich zeitnah mit Ihnen in Verbindung setzen.</p>
|
|
</div>
|
|
</m.div>
|
|
) : status === 'error' ? (
|
|
<m.div
|
|
initial={{ opacity: 0, scale: 0.95 }}
|
|
animate={{ opacity: 1, scale: 1 }}
|
|
className="bg-red-500/10 border border-red-500 text-red-600 p-6 rounded-xl flex items-start gap-4 mb-6"
|
|
>
|
|
<div className="bg-red-500 text-white rounded-full p-1 mt-0.5">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
|
|
</div>
|
|
<div>
|
|
<h4 className="font-bold text-lg mb-1">Fehler beim Senden</h4>
|
|
<p>Leider ist ein Fehler aufgetreten. Bitte versuchen Sie es später noch einmal oder kontaktieren Sie uns direkt per E-Mail oder Telefon.</p>
|
|
<Button variant="outline" size="sm" className="mt-4" onClick={() => setStatus('idle')}>Erneut versuchen</Button>
|
|
</div>
|
|
</m.div>
|
|
) : null}
|
|
|
|
{status !== 'success' && status !== 'error' && (
|
|
<form onSubmit={handleSubmit} className="space-y-6">
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div className="space-y-2">
|
|
<label htmlFor="name" className="block text-sm font-semibold text-neutral-dark">Vorname</label>
|
|
<input
|
|
id="name"
|
|
name="name"
|
|
required
|
|
disabled={status === 'loading'}
|
|
className="w-full bg-neutral-50 px-4 py-3 rounded-lg border border-neutral-200 focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-all"
|
|
placeholder="Max"
|
|
/>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<label htmlFor="lastName" className="block text-sm font-semibold text-neutral-dark">Nachname</label>
|
|
<input
|
|
id="lastName"
|
|
name="lastName"
|
|
required
|
|
disabled={status === 'loading'}
|
|
className="w-full bg-neutral-50 px-4 py-3 rounded-lg border border-neutral-200 focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-all"
|
|
placeholder="Mustermann"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<label htmlFor="email" className="block text-sm font-semibold text-neutral-dark">E-Mail Adresse</label>
|
|
<input
|
|
id="email"
|
|
name="email"
|
|
type="email"
|
|
required
|
|
disabled={status === 'loading'}
|
|
className="w-full bg-neutral-50 px-4 py-3 rounded-lg border border-neutral-200 focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-all"
|
|
placeholder="max@beispiel.de"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<label htmlFor="company" className="block text-sm font-semibold text-neutral-dark">Unternehmen (Optional)</label>
|
|
<input
|
|
id="company"
|
|
name="company"
|
|
disabled={status === 'loading'}
|
|
className="w-full bg-neutral-50 px-4 py-3 rounded-lg border border-neutral-200 focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-all"
|
|
placeholder="Firma GmbH"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<label htmlFor="message" className="block text-sm font-semibold text-neutral-dark">Ihre Nachricht</label>
|
|
<textarea
|
|
id="message"
|
|
name="message"
|
|
required
|
|
disabled={status === 'loading'}
|
|
rows={5}
|
|
className="w-full bg-neutral-50 px-4 py-3 rounded-lg border border-neutral-200 focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-all resize-y"
|
|
placeholder="Beschreiben Sie kurz Ihr Anliegen..."
|
|
/>
|
|
</div>
|
|
|
|
<input type="text" name="company_website" style={{ display: 'none' }} tabIndex={-1} autoComplete="off" />
|
|
|
|
<Button
|
|
type="submit"
|
|
disabled={status === 'loading'}
|
|
variant="primary"
|
|
size="lg"
|
|
className="w-full"
|
|
>
|
|
{status === 'loading' ? (
|
|
<>
|
|
<svg className="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle><path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
|
|
Wird gesendet...
|
|
</>
|
|
) : (
|
|
'Nachricht absenden'
|
|
)}
|
|
</Button>
|
|
|
|
<p className="text-xs text-text-light text-center">
|
|
Mit dem Absenden erkläre ich mich mit der Datenschutzerklärung einverstanden.
|
|
</p>
|
|
</form>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|