Files
ndsolutionswebsite/src/components/ContactSection.astro

151 lines
6.0 KiB
Plaintext

---
// src/components/ContactSection.astro
interface Props {
id?: string;
settings?: {
title?: string;
subtitle?: string;
submit_button_text?: string;
};
}
const { id = 'contact', settings = {} } = Astro.props;
const title = settings.title || 'Kontaktieren Sie uns';
const subtitle = settings.subtitle || 'Schreiben Sie uns eine Nachricht. Wir melden uns innerhalb von 24 Stunden.';
const buttonText = settings.submit_button_text || 'Nachricht absenden';
---
<section id={id} class="py-16 px-4 max-w-4xl mx-auto">
<div class="preset-card p-8 bg-slate-900/80 border border-white/10 rounded-2xl shadow-2xl backdrop-blur-md">
<div class="text-center mb-8">
<h2 class="text-2xl font-bold text-white tracking-tight">{title}</h2>
<p class="text-slate-400 text-sm mt-2">{subtitle}</p>
</div>
<div id="form-feedback" role="status" aria-live="polite" class="hidden mb-6 p-4 rounded-lg text-sm font-semibold"></div>
<form id="contact-form" class="space-y-6" novalidate>
<div class="hidden" aria-hidden="true">
<label for="website_hp">Bitte dieses Feld leer lassen</label>
<input type="text" id="website_hp" name="website_hp" tabindex="-1" autocomplete="off" />
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label for="sender_name" class="block text-xs font-semibold text-slate-300 uppercase tracking-wider mb-2">
Ihr Name <span class="text-sky-400" aria-hidden="true">*</span>
</label>
<input
type="text"
id="sender_name"
name="sender_name"
required
aria-required="true"
placeholder="Max Mustermann"
class="w-full bg-slate-950/60 border border-slate-800 rounded-lg p-3 text-sm text-white placeholder-slate-600 focus:outline-none focus:ring-2 focus:ring-sky-500 focus:border-transparent transition-all"
/>
</div>
<div>
<label for="sender_email" class="block text-xs font-semibold text-slate-300 uppercase tracking-wider mb-2">
E-Mail Adresse <span class="text-sky-400" aria-hidden="true">*</span>
</label>
<input
type="email"
id="sender_email"
name="sender_email"
required
aria-required="true"
placeholder="max@beispiel.de"
class="w-full bg-slate-950/60 border border-slate-800 rounded-lg p-3 text-sm text-white placeholder-slate-600 focus:outline-none focus:ring-2 focus:ring-sky-500 focus:border-transparent transition-all"
/>
</div>
</div>
<div>
<label for="message_text" class="block text-xs font-semibold text-slate-300 uppercase tracking-wider mb-2">
Ihre Nachricht <span class="text-sky-400" aria-hidden="true">*</span>
</label>
<textarea
id="message_text"
name="message_text"
rows="5"
required
aria-required="true"
placeholder="Wie können wir Ihnen helfen?"
class="w-full bg-slate-950/60 border border-slate-800 rounded-lg p-3 text-sm text-white placeholder-slate-600 focus:outline-none focus:ring-2 focus:ring-sky-500 focus:border-transparent transition-all resize-y"
></textarea>
</div>
<div class="flex items-start gap-3">
<input
type="checkbox"
id="privacy_consent"
name="privacy_consent"
required
aria-required="true"
class="mt-1 h-4 w-4 accent-sky-500 rounded border-slate-800 bg-slate-950/60 cursor-pointer focus:ring-2 focus:ring-sky-500"
/>
<label for="privacy_consent" class="text-xs text-slate-400 leading-relaxed cursor-pointer">
Ich stimme der Verarbeitung meiner Angaben gemäß der <a href="/datenschutz" class="text-sky-400 underline hover:text-sky-300">Datenschutzerklärung</a> zur Kontaktaufnahme zu. <span class="text-sky-400" aria-hidden="true">*</span>
</label>
</div>
<button
type="submit"
id="btn-submit-contact"
class="w-full bg-sky-500 hover:bg-sky-400 text-slate-950 font-bold py-3.5 px-6 rounded-lg text-sm transition-all shadow-lg shadow-sky-500/20 focus:outline-none focus:ring-2 focus:ring-sky-300"
>
{buttonText}
</button>
</form>
</div>
</section>
<script>
const form = document.getElementById('contact-form') as HTMLFormElement;
const feedback = document.getElementById('form-feedback');
const submitBtn = document.getElementById('btn-submit-contact') as HTMLButtonElement;
form?.addEventListener('submit', async (e) => {
e.preventDefault();
if (!feedback || !submitBtn) return;
// Client-side Honeypot Check
const hp = (document.getElementById('website_hp') as HTMLInputElement)?.value;
if (hp) return; // Stiller Abbruch bei Bot-Befüllung
submitBtn.disabled = true;
submitBtn.textContent = 'Wird gesendet...';
const formData = new FormData(form);
const data = Object.fromEntries(formData.entries());
try {
const res = await fetch('/api/contact/send', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
const result = await res.json();
feedback.classList.remove('hidden', 'bg-red-950/80', 'text-red-300', 'border-red-800', 'bg-emerald-950/80', 'text-emerald-300', 'border-emerald-800');
if (res.ok) {
feedback.classList.add('bg-emerald-950/80', 'text-emerald-300', 'border', 'border-emerald-800');
feedback.textContent = 'Vielen Dank! Ihre Nachricht wurde erfolgreich übermittelt.';
form.reset();
} else {
throw new Error(result.error || 'Fehler beim Senden.');
}
} catch (err: any) {
feedback.classList.add('bg-red-950/80', 'text-red-300', 'border', 'border-red-800');
feedback.textContent = err.message || 'Nachricht konnte nicht gesendet werden. Bitte versuchen Sie es später erneut.';
} finally {
submitBtn.disabled = false;
submitBtn.textContent = 'Nachricht absenden';
}
});
</script>