diff --git a/hifi-src/index.html b/hifi-src/index.html index 304c798..b70de4d 100644 --- a/hifi-src/index.html +++ b/hifi-src/index.html @@ -8,7 +8,7 @@ Kunden-Referenzdesign) - der Rest der Seite bleibt beim Standard-Font. --> - + HifiPlanet | Car-Hifi Umbauten nach Maß diff --git a/hifi-src/src/assets/contact/grunge.png b/hifi-src/src/assets/contact/grunge.png new file mode 100644 index 0000000..59c232f Binary files /dev/null and b/hifi-src/src/assets/contact/grunge.png differ diff --git a/hifi-src/src/assets/contact/splatter.png b/hifi-src/src/assets/contact/splatter.png new file mode 100644 index 0000000..94f6b1f Binary files /dev/null and b/hifi-src/src/assets/contact/splatter.png differ diff --git a/hifi-src/src/i18n/de.js b/hifi-src/src/i18n/de.js index a6b75f2..ddc26a4 100644 --- a/hifi-src/src/i18n/de.js +++ b/hifi-src/src/i18n/de.js @@ -165,8 +165,15 @@ export default { metaTitle: 'Kontakt', metaDescription: 'Kontaktiere HifiPlanet in Amorbach für dein individuelles Car-Hifi Projekt – wir beraten dich gerne unverbindlich.', title: 'Kontakt aufnehmen', - sentTitle: 'Danke für deine Anfrage!', - sentText: 'Wir melden uns so schnell wie möglich bei dir.', + heroEyebrow: 'Kontakt', + heroTitlePre: 'Sprich', + heroTitleAccent: 'mit', + heroTitlePost: 'uns.', + heroSubtitle: 'Ob Anlage, Einbau oder Klang-Tuning für dein Fahrzeug — schreib uns, wir melden uns schnellstmöglich zurück.', + packageBoxTitle: 'Deine Anfrage bezieht sich auf', + formTitle: 'Anfrage senden', + sentTitle: 'Anfrage gesendet ✓', + sentText: 'Danke! Wir melden uns innerhalb eines Werktags bei dir.', contextIntro: 'Deine Anfrage bezieht sich auf:', contextBrand: 'Marke', contextModel: 'Modell', @@ -175,12 +182,18 @@ export default { packagePrice: 'Paketpreis', upgrades: 'Upgrades', optionalUpgrades: 'Optionale Upgrades', + totalWithUpgrades: 'Gesamt inkl. Upgrades', nameLabel: 'Name *', + namePlaceholder: 'Max Mustermann', emailLabel: 'E-Mail *', + emailPlaceholder: 'max@mail.de', phoneLabel: 'Telefon', + phonePlaceholder: 'Optional', vinLabel: 'Fahrgestellnummer (FIN)', - vinPlaceholder: 'Optional – hilft uns bei der genauen Einschätzung deines Fahrzeugs', + vinPlaceholder: 'Optional – hilft bei der Einschätzung', messageLabel: 'Nachricht', + messagePlaceholder: 'Erzähl uns von deinem Projekt – Fahrzeug, Wunschklang, Budget …', + requiredHint: '* Pflichtfelder', sending: 'Wird gesendet…', submit: 'Anfrage senden', cardTitle: 'HifiPlanet Amorbach', @@ -190,9 +203,22 @@ export default { hours: 'Öffnungszeiten', hoursWeek: 'Mo–Fr: 9:00–18:00 Uhr', hoursSat: 'Sa: 10:00–13:00 Uhr', + hoursWeekDays: 'Mo–Fr', + hoursWeekTime: '9:00 – 18:00 Uhr', + hoursSatDay: 'Sa', + hoursSatTime: '10:00 – 13:00 Uhr', directionsTitle: 'Anfahrt', mapEmbedName: 'Die Google-Maps-Karte', + mapOpenChip: 'In Maps öffnen', routePlan: 'Route planen', + featurePremiumTitle: 'Premium Klang', + featurePremiumSub: 'Höchste Qualität', + featureGermanyTitle: 'Made in Germany', + featureGermanySub: 'Präzise Handarbeit', + featureIndividualTitle: 'Individuell', + featureIndividualSub: 'Maßgeschneiderte Lösungen', + featureExpertsTitle: 'Experten Team', + featureExpertsSub: 'Leidenschaft & Know-how', }, galleryOverview: { metaTitle: 'Bildergalerie', diff --git a/hifi-src/src/i18n/en.js b/hifi-src/src/i18n/en.js index 47b1cd4..8e3d222 100644 --- a/hifi-src/src/i18n/en.js +++ b/hifi-src/src/i18n/en.js @@ -165,8 +165,15 @@ export default { metaTitle: 'Contact', metaDescription: 'Get in touch with HifiPlanet in Amorbach for your custom car-hifi project – we\'re happy to advise you, no obligation.', title: 'Get in touch', - sentTitle: 'Thanks for your inquiry!', - sentText: "We'll get back to you as soon as possible.", + heroEyebrow: 'Contact', + heroTitlePre: 'Talk', + heroTitleAccent: 'to', + heroTitlePost: 'us.', + heroSubtitle: 'Whether it\'s a system, installation, or sound tuning for your car — write to us, we\'ll get back to you as soon as possible.', + packageBoxTitle: 'Your inquiry relates to', + formTitle: 'Send inquiry', + sentTitle: 'Inquiry sent ✓', + sentText: "Thanks! We'll get back to you within one business day.", contextIntro: 'Your inquiry relates to:', contextBrand: 'Brand', contextModel: 'Model', @@ -175,12 +182,18 @@ export default { packagePrice: 'Package price', upgrades: 'Upgrades', optionalUpgrades: 'Optional upgrades', + totalWithUpgrades: 'Total incl. upgrades', nameLabel: 'Name *', + namePlaceholder: 'Max Mustermann', emailLabel: 'Email *', + emailPlaceholder: 'max@mail.de', phoneLabel: 'Phone', + phonePlaceholder: 'Optional', vinLabel: 'Vehicle identification number (VIN)', - vinPlaceholder: 'Optional – helps us assess your vehicle accurately', + vinPlaceholder: 'Optional – helps us assess your vehicle', messageLabel: 'Message', + messagePlaceholder: 'Tell us about your project – vehicle, desired sound, budget …', + requiredHint: '* Required fields', sending: 'Sending…', submit: 'Send inquiry', cardTitle: 'HifiPlanet Amorbach', @@ -190,9 +203,22 @@ export default { hours: 'Opening hours', hoursWeek: 'Mon–Fri: 9:00 AM–6:00 PM', hoursSat: 'Sat: 10:00 AM–1:00 PM', + hoursWeekDays: 'Mon–Fri', + hoursWeekTime: '9:00 AM – 6:00 PM', + hoursSatDay: 'Sat', + hoursSatTime: '10:00 AM – 1:00 PM', directionsTitle: 'Directions', mapEmbedName: 'The Google Maps map', + mapOpenChip: 'Open in Maps', routePlan: 'Get directions', + featurePremiumTitle: 'Premium Sound', + featurePremiumSub: 'Highest quality', + featureGermanyTitle: 'Made in Germany', + featureGermanySub: 'Precision craftsmanship', + featureIndividualTitle: 'Custom-built', + featureIndividualSub: 'Tailored solutions', + featureExpertsTitle: 'Expert Team', + featureExpertsSub: 'Passion & know-how', }, galleryOverview: { metaTitle: 'Photo gallery', diff --git a/hifi-src/src/index.css b/hifi-src/src/index.css index 6d5b436..949d68a 100644 --- a/hifi-src/src/index.css +++ b/hifi-src/src/index.css @@ -27,6 +27,69 @@ html { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='3' stitchTiles='stitch' result='noise'/%3E%3CfeColorMatrix in='noise' type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.14 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); } +/* ==== Kontaktformular Redesign: Design-Tokens (siehe src/referenz/Kontaktformular + Redesign/design_handoff_kontaktformular/README.md) - gescopt auf .kf-page statt + global, damit sie den Rest der Seite nicht beeinflussen. Reagiert automatisch auf + den bestehenden globalen Dark-Mode-Schalter (.dark-Klasse auf ), kein + eigener Toggle noetig. */ +.kf-page { + --kf-pagebg: linear-gradient(120deg, #eef0ea 0%, #f6f8f3 45%, #fbfcf9 100%); + --kf-card: #ffffff; + --kf-cardbrd: #e4e8dc; + --kf-text: #23271d; + --kf-text2: #2a2e24; + --kf-muted: #6c7360; + --kf-label: #838a72; + --kf-field: #fafcf6; + --kf-fieldbrd: #dde2d3; + --kf-fieldicon: #a7ad9d; + --kf-accent: #a4d417; + --kf-accent2: #8ec21a; + --kf-accentsoft: #f2f8df; + --kf-pill: #ffffff; + --kf-pillbrd: #dfe4d6; + --kf-shadow: 0 24px 60px rgba(60, 70, 40, 0.08); + --kf-shadow2: 0 16px 40px rgba(60, 70, 40, 0.06); + --kf-divider: #e8ecdf; + --kf-topo: #d7dccd; + --kf-pkgbg: #f4fbe4; + --kf-pkgbrd: #cfe89a; + --kf-btntext: #1f2417; + --kf-scrim: linear-gradient(90deg, rgba(244, 246, 241, 0.35) 0%, rgba(244, 246, 241, 0.55) 55%, rgba(246, 248, 243, 1) 100%); +} +.dark .kf-page { + --kf-pagebg: linear-gradient(120deg, #181b0f 0%, #111409 45%, #0a0c06 100%); + --kf-card: #14170e; + --kf-cardbrd: rgba(168, 225, 12, 0.16); + --kf-text: #f3f6ea; + --kf-text2: #e8ece0; + --kf-muted: #9aa38c; + --kf-label: #8f987f; + --kf-field: rgba(0, 0, 0, 0.35); + --kf-fieldbrd: #2c3323; + --kf-fieldicon: #5f6852; + --kf-accent: #a8e10c; + --kf-accent2: #b6e619; + --kf-accentsoft: rgba(168, 225, 12, 0.1); + --kf-pill: #14170e; + --kf-pillbrd: rgba(168, 225, 12, 0.28); + --kf-shadow: 0 24px 60px rgba(0, 0, 0, 0.55); + --kf-shadow2: 0 16px 40px rgba(0, 0, 0, 0.45); + --kf-divider: rgba(168, 225, 12, 0.15); + --kf-pkgbg: rgba(168, 225, 12, 0.08); + --kf-pkgbrd: rgba(168, 225, 12, 0.4); + --kf-btntext: #0f1208; +} +.kf-page input::placeholder, +.kf-page textarea::placeholder { + color: var(--kf-fieldicon); +} +.kf-page input:focus, +.kf-page textarea:focus { + border-color: var(--kf-accent) !important; + box-shadow: 0 0 0 3px rgba(164, 212, 23, 0.2); +} + .grain-band { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='3' stitchTiles='stitch' result='noise'/%3E%3CfeColorMatrix in='noise' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.13 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); background-size: 180px 180px; diff --git a/hifi-src/src/pages/public/ContactPage.jsx b/hifi-src/src/pages/public/ContactPage.jsx index 883ebe1..5c1abee 100644 --- a/hifi-src/src/pages/public/ContactPage.jsx +++ b/hifi-src/src/pages/public/ContactPage.jsx @@ -5,15 +5,92 @@ 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'; +import grungeBg from '../../assets/contact/grunge.png'; +import splatterBg from '../../assets/contact/splatter.png'; +import carPhoto from '../../assets/photos/hero-trunk.webp'; 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, contact_email: contactEmail } = useSiteSettings(); + 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: '' }); @@ -51,9 +128,8 @@ export default function ContactPage() { brand: params.get('brand') || '', model: params.get('model') || '', package: params.get('package') || '', - product: params.get('product') || '', }; - const hasContext = context.brand || context.model || context.package || context.product; + const hasPackage = Boolean(context.brand && context.model && context.package); const handleChange = (e) => setForm((f) => ({ ...f, [e.target.name]: e.target.value })); @@ -68,189 +144,454 @@ export default function ContactPage() { brand_name: context.brand || null, model_name: context.model || null, package_name: context.package || null, - product_name: context.product || 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 ( -
-

{t('contactPage.title')}

+
+ {/* Dark Mode: Grunge-Textur + Splatter + Bogen (Assets aus dem Handoff) */} +