import { useEffect, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { api } from '../../api/client.js';
import usePageMeta from '../../hooks/usePageMeta.js';
import ExternalEmbed from '../../components/ExternalEmbed.jsx';
import { useSiteSettings } from '../../context/SiteSettingsContext.jsx';
import { useLanguage } from '../../context/LanguageContext.jsx';
import { useCookieConsent } from '../../context/CookieConsentContext.jsx';
import { User, Mail, Phone, Car, Package, Send, MapPin, ExternalLink } from 'lucide-react';
// Die Sektions-Hintergruende (bg-light.png / bg-dark.png) kommen als fertig
// gebackene Einzelbilder ueber die CSS-Klasse .kontakt-sektion (index.css).
const digitsOnly = (value) => (value || '').replace(/[^\d+]/g, '');
const waHref = (whatsapp) => `https://wa.me/${digitsOnly(whatsapp).replace(/^0/, '49').replace('+', '')}`;
const SHOP_ADDRESS_ENCODED = encodeURIComponent('Boxbrunner Str. 20a, 63916 Amorbach');
const DIRECTIONS_URL = `https://www.google.com/maps/dir/?api=1&destination=${SHOP_ADDRESS_ENCODED}`;
const michroma = { fontFamily: "'Michroma', sans-serif" };
function WhatsAppIcon({ className }) {
return (
);
}
// Die 4 Feature-Icons aus dem Referenzdesign - kein 1:1-Lucide-Pendant fuer alle,
// daher als rohe Pfade uebernommen statt einem angenaeherten Lucide-Icon.
function FeatureIcon({ path, className }) {
return (
);
}
const FEATURE_ICON_PATHS = {
premium: 'M4 12v3M8 8v11M12 4v16M16 8v11M20 12v3',
germany: 'M12 12m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0 M12 2v2M12 20v2M2 12h2M20 12h2M5 5l1.5 1.5M17.5 17.5 19 19M19 5l-1.5 1.5M6.5 17.5 5 19',
individual: 'M6 3h12l4 6-10 12L2 9z M11 3 8 9l4 12 4-12-3-6M2 9h20',
experts: 'M20 6 9 17l-5-5',
};
// Michroma hat kein Euro-Zeichen-Glyph (rendert als Tofu/"O"-Ersatzform) - das
// Waehrungssymbol bekommt darum immer die System-Schrift, nur Ziffern/Komma bleiben
// in Michroma. Robust gegen beide Symbolpositionen (de-DE: "999,00 €", en-US: "€999.00").
function PriceMichroma({ formatted, color }) {
const [pre, post] = formatted.split('€');
return (
{pre}
€
{post}
);
}
function Field({ icon: Icon, label, name, type = 'text', required, value, onChange, placeholder }) {
return (
);
}
export default function ContactPage() {
const [params] = useSearchParams();
const { phone, whatsapp, contact_email: contactEmail } = useSiteSettings();
const { t, language } = useLanguage();
const { consent } = useCookieConsent();
const formatPrice = (value) =>
new Intl.NumberFormat(language === 'de' ? 'de-DE' : 'en-US', { style: 'currency', currency: 'EUR' }).format(value);
const [form, setForm] = useState({ name: '', email: '', phone: '', vin: '', message: '' });
const [status, setStatus] = useState('idle');
const [error, setError] = useState('');
const [upgrades, setUpgrades] = useState([]);
const [selectedUpgradeIds, setSelectedUpgradeIds] = useState([]);
const packageId = params.get('packageId');
const packageTotal = params.get('total') ? Number(params.get('total')) : null;
useEffect(() => {
if (!packageId) {
setUpgrades([]);
return;
}
api.get(`/packages/${packageId}/upgrades`).then(setUpgrades).catch(() => setUpgrades([]));
}, [packageId]);
const toggleUpgrade = (id) => {
setSelectedUpgradeIds((ids) => (ids.includes(id) ? ids.filter((x) => x !== id) : [...ids, id]));
};
const upgradesTotal = upgrades
.filter((u) => selectedUpgradeIds.includes(u.id))
.reduce((sum, u) => sum + Number(u.price), 0);
usePageMeta({
title: t('contactPage.metaTitle'),
description: t('contactPage.metaDescription'),
path: '/kontakt',
});
const context = {
brand: params.get('brand') || '',
model: params.get('model') || '',
package: params.get('package') || '',
};
const hasPackage = Boolean(context.brand && context.model && context.package);
const handleChange = (e) => setForm((f) => ({ ...f, [e.target.name]: e.target.value }));
const handleSubmit = async (e) => {
e.preventDefault();
setStatus('sending');
setError('');
try {
await api.post('/contact', {
...form,
brand_name: context.brand || null,
model_name: context.model || null,
package_name: context.package || null,
product_name: params.get('product') || null,
package_id: packageId || null,
package_product_id: params.get('productId') || null,
upgrade_ids: selectedUpgradeIds,
});
setStatus('sent');
setForm({ name: '', email: '', phone: '', vin: '', message: '' });
} catch (e) {
setError(e.message);
setStatus('idle');
}
};
const features = [
{ key: 'premium', title: t('contactPage.featurePremiumTitle'), sub: t('contactPage.featurePremiumSub') },
{ key: 'germany', title: t('contactPage.featureGermanyTitle'), sub: t('contactPage.featureGermanySub') },
{ key: 'individual', title: t('contactPage.featureIndividualTitle'), sub: t('contactPage.featureIndividualSub') },
{ key: 'experts', title: t('contactPage.featureExpertsTitle'), sub: t('contactPage.featureExpertsSub') },
];
return (
{/* Hero */}
{t('contactPage.heroEyebrow')}
{t('contactPage.heroTitlePre')} {t('contactPage.heroTitleAccent')} {t('contactPage.heroTitlePost')}
{t('contactPage.heroSubtitle')}
{/* Hauptraster */}
{/* Formular-Karte */}
{hasPackage && (
{t('contactPage.packageBoxTitle')}
{t('contactPage.contextBrand')}
{context.brand}
{t('contactPage.contextModel')}
{context.model}
{t('contactPage.contextPackage')}
{context.package}
{t('contactPage.packagePrice')}
{packageTotal != null ? : '—'}
)}
{upgrades.length > 0 && (
{t('contactPage.optionalUpgrades')}
{upgrades.map((u) => (
toggleUpgrade(u.id)}
className="mt-0.5 h-4 w-4 rounded"
style={{ accentColor: 'var(--kf-accent)' }}
/>
{u.name}
{u.description && (
{u.description}
)}
+{formatPrice(u.price)}
))}
{selectedUpgradeIds.length > 0 && packageTotal != null && (
{t('contactPage.totalWithUpgrades')}
)}
)}
{t('contactPage.formTitle')}
{status === 'sent' && (
{t('contactPage.sentTitle')}
{t('contactPage.sentText')}
)}
{/* Rechte Spalte */}
{t('contactPage.cardTitle')}
{t('contactPage.address')}
Boxbrunner Straße 20a 63916 Amorbach
{whatsapp && (
)}
{t('contactPage.hours')}
{t('contactPage.hoursWeekDays')}
{t('contactPage.hoursWeekTime')}
{t('contactPage.hoursSatDay')}
{t('contactPage.hoursSatTime')}
{consent.external && (
{t('contactPage.mapOpenChip')}
)}
{/* iframe hoeher als der sichtbare 210px-Ausschnitt + negativer margin-top:
schneidet Googles Info-Overlay (oben links) komplett und die untere
Attributionszeile bis auf den Rand an - wie im Prototyp fuellt die
Karte so buendig bis zur "Route planen"-Leiste. */}
{t('contactPage.routePlan')} →
{/* Feature-Leiste */}
{features.map((f) => (
))}
);
}