marian/src/pages/Contact.tsx
2026-02-09 01:22:39 +01:00

1006 lines
55 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useState, useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import Layout from '@/components/Layout';
import TenReasons from '@/components/TenReasons';
import GeneralNotice from '@/components/GeneralNotice';
import Disclaimer from '@/components/Disclaimer';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion';
import { Mail, Phone, MapPin, Globe, TrendingUp, LineChart, CloudSun, Newspaper, ExternalLink, Star, FileText, Shield, Lock, HelpCircle, Send, User, MessageSquare, MessageCircle, Bot } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useTranslation } from 'react-i18next';
import { sendEmail } from '@/services/emailService';
export default function ContactPage() {
const baseUrl = import.meta.env.BASE_URL;
const assetUrl = (fileName: string) => `${baseUrl}${encodeURI(fileName)}`;
const { t } = useTranslation('contact');
const location = useLocation();
const [yearsOfExperience, setYearsOfExperience] = useState(0);
const [activeTab, setActiveTab] = useState('contact');
const [formData, setFormData] = useState({
name: '',
email: '',
phone: '',
subject: '',
message: ''
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitStatus, setSubmitStatus] = useState<'idle' | 'success' | 'error'>('idle');
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setIsSubmitting(true);
setSubmitStatus('idle');
try {
// Sende E-Mail direkt über Resend API
const result = await sendEmail({
name: formData.name,
email: formData.email,
phone: formData.phone || 'Keine Angabe',
subject: formData.subject,
message: formData.message,
to: 'info@finanzen-mizera.de'
});
if (result.success) {
setSubmitStatus('success');
// Formular nach kurzer Zeit zurücksetzen
setTimeout(() => {
setFormData({ name: '', email: '', phone: '', subject: '', message: '' });
setSubmitStatus('idle');
}, 2000);
} else {
setSubmitStatus('error');
}
} catch (error) {
console.error('Fehler beim Senden:', error);
setSubmitStatus('error');
} finally {
setIsSubmitting(false);
}
};
const [weather, setWeather] = useState<{ temp?: number; wind?: number; time?: string; isLoading: boolean }>({
isLoading: true,
});
type NewsItem = { key: string; title: string; content: string };
const fallbackNewsItems: NewsItem[] = [
{
key: 'news-1',
title: 'Hartz IV - Jak chronić swoje majątki!',
content:
'Krótki przegląd kwot wolnych, chronionego majątku i typowych pułapek. Indywidualną ocenę Twojej sytuacji chętnie zbadamy.',
},
{
key: 'news-2',
title: 'Zasiłek rodzicielski',
content:
'Ważne podstawy dotyczące uprawnień, wniosku i terminów. Pomagamy dostosować odpowiednią ochronę ubezpieczeniową i planowanie finansowe wokół rodziny i pracy.',
},
{
key: 'news-3',
title: 'Zasiłek rodzinny',
content:
'Przegląd uprawnień, dowodów i ważnych terminów. W raz pytań dotyczących zabezpieczenia i zabezpieczenia dzieci chętnie wspieramy.',
},
{
key: 'news-4',
title: 'Dodatek rodzinny',
content:
'Krótko wyjaśnione: warunki, droga wniosku i częste pytania. Dajemy orientację, jakie dokumenty są typowo potrzebne.',
},
{
key: 'news-5',
title: 'Reforma zdrowotna - Obowiązek ubezpieczenia od 16 czerwca 2008',
content:
'Co oznacza obowiązek ubezpieczenia i jakie opcje istnieją w GKV/PKV? Sprawdzamy z Tobą, które rozwiązanie pasuje do sytuacji życiowej.',
},
{
key: 'news-6',
title: 'Podatek od dochodów kapitałowych jest tu',
content:
'Zwięzły przegląd opodatkowania dochodów z kapitału i możliwych wpływu na strategie inwestycyjne i emerytalne. Szczegóły wymagają indywidualnej porady.',
},
];
const translatedNewsItems = t('news.items', { returnObjects: true }) as unknown;
const newsItems: NewsItem[] = Array.isArray(translatedNewsItems)
? (translatedNewsItems as NewsItem[])
: fallbackNewsItems;
// Berechne die Erfahrungsjahre seit 1994
useEffect(() => {
const startYear = 1994;
const currentYear = new Date().getFullYear();
setYearsOfExperience(currentYear - startYear);
}, []);
useEffect(() => {
const lat = 51.2446;
const lon = 6.8013;
const load = async () => {
try {
setWeather((prev) => ({ ...prev, isLoading: true }));
const res = await fetch(
`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}&current=temperature_2m,wind_speed_10m&timezone=Europe%2FBerlin`,
);
const data = (await res.json()) as {
current?: { time?: string; temperature_2m?: number; wind_speed_10m?: number };
};
setWeather({
isLoading: false,
time: data.current?.time,
temp: data.current?.temperature_2m,
wind: data.current?.wind_speed_10m,
});
} catch {
setWeather({ isLoading: false });
}
};
void load();
}, []);
useEffect(() => {
const scrollToTabsMenu = () => {
const tabsEl = document.getElementById('contact-tabs');
if (!tabsEl) return;
const headerEl = document.querySelector('header');
const headerHeight = headerEl?.getBoundingClientRect().height ?? 0;
const breadcrumbNav = document.querySelector('nav[aria-label="Breadcrumb"]');
const breadcrumbBar = (breadcrumbNav?.closest('div.border-b') as HTMLElement | null) ?? null;
const breadcrumbHeight = breadcrumbBar?.getBoundingClientRect().height ?? 0;
const extraGap = 8;
const offset = headerHeight + breadcrumbHeight + extraGap;
const desiredTop = tabsEl.getBoundingClientRect().top + window.scrollY - offset;
const top = Math.max(0, desiredTop);
window.scrollTo({ top, behavior: 'smooth' });
};
const handleHash = () => {
const raw = window.location.hash;
const hash = raw.startsWith('#') ? raw.slice(1) : raw;
if (hash === 'card') {
setActiveTab('card');
window.setTimeout(() => {
scrollToTabsMenu();
}, 0);
return;
}
if (hash === 'contact') {
setActiveTab('contact');
window.setTimeout(() => {
scrollToTabsMenu();
}, 0);
return;
}
if (hash === 'daily-info') {
setActiveTab('daily-info');
window.setTimeout(() => {
scrollToTabsMenu();
}, 0);
return;
}
setActiveTab('contact');
};
handleHash();
window.addEventListener('hashchange', handleHash);
return () => {
window.removeEventListener('hashchange', handleHash);
};
}, []);
useEffect(() => {
const params = new URLSearchParams(location.search);
const tab = params.get('tab');
if (
tab &&
[
'contact',
'card',
'reasons',
'service',
'impressum',
'leistungen',
'datenschutz',
'links',
'news',
'daily-info',
'faq',
].includes(tab)
) {
setActiveTab(tab);
window.setTimeout(() => {
const tabsEl = document.getElementById('contact-tabs');
if (!tabsEl) return;
const headerEl = document.querySelector('header');
const headerHeight = headerEl?.getBoundingClientRect().height ?? 0;
const breadcrumbNav = document.querySelector('nav[aria-label="Breadcrumb"]');
const breadcrumbBar = (breadcrumbNav?.closest('div.border-b') as HTMLElement | null) ?? null;
const breadcrumbHeight = breadcrumbBar?.getBoundingClientRect().height ?? 0;
const extraGap = 8;
const offset = headerHeight + breadcrumbHeight + extraGap;
const desiredTop = tabsEl.getBoundingClientRect().top + window.scrollY - offset;
const top = Math.max(0, desiredTop);
window.scrollTo({ top, behavior: 'smooth' });
}, 0);
}
}, [location.search]);
return (
<Layout>
<div className="container mx-auto px-4 md:px-6 py-8">
<div className="max-w-screen-2xl mx-auto">
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center">
{t('pageTitle', 'Kontakt')}
</h2>
<div className="bg-white rounded-lg border border-gray-200 shadow-sm">
<Tabs
value={activeTab}
onValueChange={(next) => {
setActiveTab(next);
}}
className="w-full"
id="contact-tabs"
>
<div className="border-b border-gray-100 px-4 pt-6 pb-2 bg-gradient-to-r from-blue-50 to-white">
<TabsList className="grid grid-cols-11 gap-2 w-full h-auto bg-transparent border-0 shadow-none">
<TabsTrigger
value="contact"
className="relative px-3 py-2.5 text-sm font-medium rounded-lg transition-all duration-200 data-[state=active]:bg-blue-600 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=inactive]:bg-white data-[state=inactive]:text-gray-600 data-[state=inactive]:hover:bg-gray-50 data-[state=inactive]:border border-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 !outline-none !ring-0"
>
<Phone className="w-4 h-4 mr-1.5" />
{t('tabs.contact', 'Kontakt')}
</TabsTrigger>
<TabsTrigger
value="card"
className="relative px-3 py-2.5 text-sm font-medium rounded-lg transition-all duration-200 data-[state=active]:bg-blue-600 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=inactive]:bg-white data-[state=inactive]:text-gray-600 data-[state=inactive]:hover:bg-gray-50 data-[state=inactive]:border border-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 !outline-none !ring-0"
>
<MapPin className="w-4 h-4 mr-1.5" />
{t('tabs.card', 'Karte')}
</TabsTrigger>
<TabsTrigger
value="reasons"
className="relative px-3 py-2.5 text-sm font-medium rounded-lg transition-all duration-200 data-[state=active]:bg-blue-600 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=inactive]:bg-white data-[state=inactive]:text-gray-600 data-[state=inactive]:hover:bg-gray-50 data-[state=inactive]:border border-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 !outline-none !ring-0"
>
<Star className="w-4 h-4 mr-1.5" />
{t('tabs.reasons', 'Gründe')}
</TabsTrigger>
<TabsTrigger
value="service"
className="relative px-3 py-2.5 text-sm font-medium rounded-lg transition-all duration-200 data-[state=active]:bg-blue-600 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=inactive]:bg-white data-[state=inactive]:text-gray-600 data-[state=inactive]:hover:bg-gray-50 data-[state=inactive]:border border-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 !outline-none !ring-0"
>
<TrendingUp className="w-4 h-4 mr-1.5" />
{t('tabs.service', 'Service')}
</TabsTrigger>
<TabsTrigger
value="impressum"
className="relative px-3 py-2.5 text-sm font-medium rounded-lg transition-all duration-200 data-[state=active]:bg-blue-600 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=inactive]:bg-white data-[state=inactive]:text-gray-600 data-[state=inactive]:hover:bg-gray-50 data-[state=inactive]:border border-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 !outline-none !ring-0"
>
<FileText className="w-4 h-4 mr-1.5" />
{t('tabs.impressum', 'Impressum')}
</TabsTrigger>
<TabsTrigger
value="leistungen"
className="relative px-3 py-2.5 text-sm font-medium rounded-lg transition-all duration-200 data-[state=active]:bg-blue-600 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=inactive]:bg-white data-[state=inactive]:text-gray-600 data-[state=inactive]:hover:bg-gray-50 data-[state=inactive]:border border-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 !outline-none !ring-0"
>
<Shield className="w-4 h-4 mr-1.5" />
{t('tabs.leistungen', 'Leistungen')}
</TabsTrigger>
<TabsTrigger
value="datenschutz"
className="relative px-3 py-2.5 text-sm font-medium rounded-lg transition-all duration-200 data-[state=active]:bg-blue-600 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=inactive]:bg-white data-[state=inactive]:text-gray-600 data-[state=inactive]:hover:bg-gray-50 data-[state=inactive]:border border-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 !outline-none !ring-0"
>
<Lock className="w-4 h-4 mr-1.5" />
{t('tabs.datenschutz', 'Datenschutz')}
</TabsTrigger>
<TabsTrigger
value="links"
className="relative px-3 py-2.5 text-sm font-medium rounded-lg transition-all duration-200 data-[state=active]:bg-blue-600 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=inactive]:bg-white data-[state=inactive]:text-gray-600 data-[state=inactive]:hover:bg-gray-50 data-[state=inactive]:border border-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 !outline-none !ring-0"
>
<Globe className="w-4 h-4 mr-1.5" />
{t('tabs.links', 'Links')}
</TabsTrigger>
<TabsTrigger
value="news"
className="relative px-3 py-2.5 text-sm font-medium rounded-lg transition-all duration-200 data-[state=active]:bg-blue-600 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=inactive]:bg-white data-[state=inactive]:text-gray-600 data-[state=inactive]:hover:bg-gray-50 data-[state=inactive]:border border-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 !outline-none !ring-0"
>
<Newspaper className="w-4 h-4 mr-1.5" />
{t('tabs.news', 'News')}
</TabsTrigger>
<TabsTrigger
value="daily-info"
className="relative px-3 py-2.5 text-sm font-medium rounded-lg transition-all duration-200 data-[state=active]:bg-blue-600 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=inactive]:bg-white data-[state=inactive]:text-gray-600 data-[state=inactive]:hover:bg-gray-50 data-[state=inactive]:border border-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 !outline-none !ring-0"
>
<CloudSun className="w-4 h-4 mr-1.5" />
{t('tabs.dailyInfo', 'Info')}
</TabsTrigger>
<TabsTrigger
value="faq"
className="relative px-3 py-2.5 text-sm font-medium rounded-lg transition-all duration-200 data-[state=active]:bg-blue-600 data-[state=active]:text-white data-[state=active]:shadow-md data-[state=inactive]:bg-white data-[state=inactive]:text-gray-600 data-[state=inactive]:hover:bg-gray-50 data-[state=inactive]:border border-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 !outline-none !ring-0"
>
<HelpCircle className="w-4 h-4 mr-1.5" />
{t('tabs.faq', 'FAQ')}
</TabsTrigger>
</TabsList>
</div>
<TabsContent id="contact" value="contact" className="p-4 md:p-6">
<div className="grid lg:grid-cols-2 gap-8">
{/* Linke Seite - Kontaktinformationen */}
<div className="space-y-6">
<div className="flex flex-col sm:flex-row gap-4">
<div className="sm:w-48 md:w-56">
<div className="w-full aspect-[3/4] overflow-hidden rounded-xl shadow-lg border-2 border-blue-100 bg-gray-100">
<img
src={assetUrl('Fotolia_1171371_XS.jpg')}
alt={t('images.profileAlt', 'Marian-Adam Mizera')}
className="w-full h-full object-cover"
loading="lazy"
/>
</div>
</div>
<div className="flex-1">
<div className="text-2xl font-semibold text-gray-900">Marian - Adam Mizera</div>
<div className="mt-4 space-y-3 text-sm text-gray-800">
<div className="flex gap-2">
<span className="text-blue-700 font-semibold">//</span>
<span>{t('profile.role', 'Selbstständiger, unabhängiger Finanz- und Versicherungsmakler')}</span>
</div>
<div><span className="font-semibold">{t('profile.qual1', 'Geprüfter Versicherungsfachmann (BWV)')}</span></div>
<div><span className="font-semibold">{t('profile.qual2', 'Experte Betriebliche Altersversorgung (DVA)')}</span></div>
<div>{t('profile.qual2Note', '(*Deutsche Versicherungsakademie, München*)')}</div>
<div><span className="font-semibold">{t('licenseTitle', 'Versicherungsmakler')}</span> {t('licenseSuffix', 'mit Erlaubnis')}</div>
<div>{t('licenseLaw', 'nach § 34d Abs. 1 GewO')}</div>
<div>{t('since', 'Versicherungen seit 1994')}</div>
</div>
</div>
</div>
<div className="space-y-2 text-sm text-gray-800">
<div className="flex gap-2 items-start">
<span className="text-blue-700 font-semibold">//</span>
<div>
<div className="font-semibold">{t('office.title', 'HomeOffice:')}</div>
<div>{t('office.note', '(Bürotermine - nach vorheriger telefonischer Vereinbarung)')}</div>
<div className="mt-3">Rosmarinstraße 30 d</div>
<div>40235 Düsseldorf</div>
</div>
</div>
</div>
<div className="grid sm:grid-cols-2 gap-3">
<a
href="tel:021197629355"
className="flex items-center gap-3 rounded-md border border-gray-200 p-3 hover:bg-gray-50 transition-colors"
>
<Phone className="h-5 w-5 text-blue-600" />
<span className="text-sm font-medium text-gray-900">{t('labels.phone', 'Telefon')}: 0211 / 97629355</span>
</a>
<a
href="tel:01719864053"
className="flex items-center gap-3 rounded-md border border-gray-200 p-3 hover:bg-gray-50 transition-colors"
>
<Phone className="h-5 w-5 text-blue-600" />
<span className="text-sm font-medium text-gray-900">{t('labels.mobile', 'Mobil')}: 0171 / 98 64 053</span>
</a>
<a
href="mailto:info@finanzen-mizera.de"
className="flex items-center gap-3 rounded-md border border-gray-200 p-3 hover:bg-gray-50 transition-colors"
>
<Mail className="h-5 w-5 text-blue-600" />
<span className="text-sm font-medium text-gray-900">info@finanzen-mizera.de</span>
</a>
<a
href="https://www.finanzen-mizera.de"
target="_blank"
rel="noreferrer"
className="flex items-center gap-3 rounded-md border border-gray-200 p-3 hover:bg-gray-50 transition-colors"
>
<Globe className="h-5 w-5 text-blue-600" />
<span className="text-sm font-medium text-gray-900">www.finanzen-mizera.de</span>
</a>
</div>
<div className="flex items-center gap-3 rounded-md border border-gray-200 p-3 hover:bg-gray-50 transition-colors">
<div className="w-5 h-5 flex items-center justify-center">
<Bot className="w-4 h-4 text-blue-600" />
</div>
<a
href="/chatbot"
className="text-xs text-blue-700 underline hover:text-blue-900 transition-colors"
>
Chatbot starten
</a>
</div>
<div className="text-sm text-gray-600 flex items-start gap-2">
<MapPin className="h-4 w-4 text-blue-600 mt-0.5" />
<span>{t('appointmentNote', 'Termine nach vorheriger telefonischer Vereinbarung.')}</span>
</div>
</div>
{/* Rechte Seite - Kontaktformular und QR-Code */}
<div className="space-y-6">
<div className="rounded-lg border border-gray-200 bg-white p-6 shadow-sm">
<div className="text-center mb-6">
<Send className="h-8 w-8 text-blue-600 mx-auto mb-3" />
<h3 className="text-xl font-bold text-gray-900 mb-2">{t('contact.formTitle', 'Kontaktformular')}</h3>
<p className="text-gray-600 text-sm">
{t('contact.formDescription', 'Senden Sie uns eine Nachricht und wir melden uns so schnell wie möglich bei Ihnen zurück.')}
</p>
</div>
<form className="space-y-4" onSubmit={handleSubmit}>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
<User className="w-4 h-4 inline mr-1" />
{t('contact.name', 'Name')} {t('contact.required', '*')}
</label>
<input
type="text"
value={formData.name}
onChange={(e) => setFormData({...formData, name: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
placeholder={t('contact.namePlaceholder', 'Ihr Name')}
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
<Mail className="w-4 h-4 inline mr-1" />
{t('contact.email', 'E-Mail')} {t('contact.required', '*')}
</label>
<input
type="email"
value={formData.email}
onChange={(e) => setFormData({...formData, email: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
placeholder={t('contact.emailPlaceholder', 'ihre@email.de')}
required
/>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
<Phone className="w-4 h-4 inline mr-1" />
{t('contact.phone', 'Telefon')}
</label>
<input
type="tel"
value={formData.phone}
onChange={(e) => setFormData({...formData, phone: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
placeholder={t('contact.phonePlaceholder', '0123 456789')}
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
<MessageSquare className="w-4 h-4 inline mr-1" />
{t('contact.subject', 'Betreff')} {t('contact.required', '*')}
</label>
<input
type="text"
value={formData.subject}
onChange={(e) => setFormData({...formData, subject: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
placeholder={t('contact.subjectPlaceholder', 'Ihr Anliegen')}
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
<MessageSquare className="w-4 h-4 inline mr-1" />
{t('contact.message', 'Nachricht')} {t('contact.required', '*')}
</label>
<textarea
value={formData.message}
onChange={(e) => setFormData({...formData, message: e.target.value})}
rows={4}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
placeholder={t('contact.messagePlaceholder', 'Ihre Nachricht an uns...')}
required
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Button
type="submit"
className="bg-blue-600 hover:bg-blue-700 text-white text-base h-14 px-2"
disabled={isSubmitting}
>
<Send className="w-5 h-5 mr-1" />
{isSubmitting ? t('contact.sending', 'Wird gesendet...') : t('contact.send', 'Nachricht senden')}
</Button>
<Button
type="button"
variant="outline"
className="border-gray-300 text-base h-14 px-2"
onClick={() => setFormData({ name: '', email: '', phone: '', subject: '', message: '' })}
disabled={isSubmitting}
>
{t('contact.clear', 'Leeren')}
</Button>
<a
href="/chatbot"
className="inline-flex items-center justify-center border border-blue-500 text-blue-600 hover:bg-blue-50 text-base h-14 px-2 rounded-md transition-colors"
>
<Bot className="w-5 h-5 mr-1" />
{t('contact.chatbot', 'Chatbot')}
</a>
</div>
{/* Status-Meldungen */}
{submitStatus === 'success' && (
<div className="mt-4 p-3 bg-green-50 border border-green-200 rounded-md">
<div className="flex items-center gap-2 text-green-800 text-sm">
<Mail className="w-4 h-4" />
<span>{t('contact.success', 'Ihre Nachricht wurde erfolgreich gesendet! Wir melden uns bald bei Ihnen.')}</span>
</div>
</div>
)}
{submitStatus === 'error' && (
<div className="mt-4 p-3 bg-red-50 border border-red-200 rounded-md">
<div className="flex items-center gap-2 text-red-800 text-sm">
<Mail className="w-4 h-4" />
<span>{t('contact.error', 'Es ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut oder rufen Sie uns direkt an.')}</span>
</div>
</div>
)}
</form>
</div>
{/* QR-Code - kleiner und platziert wie Musterbild */}
<div className="rounded-lg border border-gray-200 bg-gray-50 p-4">
<div className="text-sm font-semibold text-gray-900 mb-3 text-center">{t('qr.title', 'QR-Code')}</div>
<a
href={assetUrl('head_kontakt_agentur_mizera.jpg')}
target="_blank"
rel="noreferrer"
className="block mx-auto"
style={{maxWidth: '40%'}}
>
<div className="w-full aspect-[3/4] overflow-hidden rounded-lg bg-white border border-gray-200">
<img
src={assetUrl('head_kontakt_agentur_mizera.jpg')}
alt={t('images.qrAlt', 'Agentur Mizera QR-Code')}
className="w-full h-full object-contain"
loading="lazy"
/>
</div>
</a>
<p className="text-xs text-gray-600 text-center mt-2">
{t('contact.qrClickHint', 'Klicken Sie zum Vergrößern')}
</p>
</div>
</div>
</div>
</TabsContent>
<TabsContent id="card" value="card" className="p-4 md:p-6 h-[75vh] overflow-y-auto">
<div className="grid md:grid-cols-2 gap-8">
<div className="text-center">
<div className="text-base font-medium text-gray-900 mb-4">{t('businessCard.front', 'Vorderseite')}</div>
<a
href={assetUrl('Visitenkarte Agentur Mizera _v.jpg')}
download="Visitenkarte_Agentur_Mizera_Vorderseite.jpg"
className="block"
>
<div className="w-full aspect-[16/10] rounded-lg shadow-lg border border-gray-200 bg-white overflow-hidden">
<img
src={assetUrl('Visitenkarte Agentur Mizera _v.jpg')}
alt={t('images.businessCardFrontAlt', 'Visitenkarte Vorderseite')}
className="w-full h-full object-contain"
loading="lazy"
/>
</div>
</a>
</div>
<div className="text-center">
<div className="text-base font-medium text-gray-900 mb-4">{t('businessCard.back', 'Rückseite')}</div>
<a
href={assetUrl('Visitenkarte Agentur Mizera _h.jpg')}
download="Visitenkarte_Agentur_Mizera_Rueckseite.jpg"
className="block"
>
<div className="w-full aspect-[16/10] rounded-lg shadow-lg border border-gray-200 bg-white overflow-hidden">
<img
src={assetUrl('Visitenkarte Agentur Mizera _h.jpg')}
alt={t('images.businessCard.back', 'Visitenkarte Rückseite')}
className="w-full h-full object-contain"
loading="lazy"
/>
</div>
</a>
</div>
</div>
</TabsContent>
<TabsContent value="reasons" className="p-4 md:p-6 h-[75vh] overflow-y-auto">
<TenReasons
title={t('reasons.title', '10 gute Gründe')}
items={t('reasons.items', {
returnObjects: true,
defaultValue: [
{ title: 'Erfahrung', description: `Mehr als ${yearsOfExperience} Jahre am Markt` },
{ title: 'Unabhängigkeit', description: 'Unabhängig von Versicherern' },
{ title: 'Transparenz', description: 'Verständliche, klare Empfehlungen' },
{ title: 'Qualität', description: 'Hohe Standards in Beratung und Service' },
{ title: 'Vertrauen', description: 'Langfristige Betreuung' },
{ title: 'Individualität', description: 'Lösungen nach Bedarf' },
{ title: 'Diskretion', description: 'Sorgfältiger Umgang mit Daten' },
{ title: 'Alles aus einer Hand', description: 'Beratung, Vergleich, Abschluss, Service' },
],
}) as Array<{ title: string; description: string }>}
years={yearsOfExperience}
/>
</TabsContent>
<TabsContent value="service" className="p-4 md:p-6 h-[75vh] overflow-hidden">
<iframe
title={t('iframes.service', 'Service')}
src="/service?embed=1"
className="w-full h-full rounded-lg border border-gray-200 bg-white"
loading="lazy"
/>
</TabsContent>
<TabsContent value="impressum" className="p-4 md:p-6 h-[75vh] overflow-hidden">
<iframe
title={t('iframes.impressum', 'Impressum')}
src="/impressum?embed=1"
className="w-full h-full rounded-lg border border-gray-200 bg-white"
loading="lazy"
/>
</TabsContent>
<TabsContent value="datenschutz" className="p-4 md:p-6 h-[75vh] overflow-hidden">
<iframe
title={t('iframes.datenschutz', 'Datenschutz')}
src="/datenschutz?embed=1"
className="w-full h-full rounded-lg border border-gray-200 bg-white"
loading="lazy"
/>
</TabsContent>
<TabsContent value="leistungen" className="p-4 md:p-6 h-[75vh] overflow-hidden">
<iframe
title={t('iframes.leistungen', 'Leistungen')}
src="/leistungen?embed=1"
className="w-full h-full rounded-lg border border-gray-200 bg-white"
loading="lazy"
/>
</TabsContent>
<TabsContent value="links" className="p-4 md:p-6 h-[75vh] overflow-hidden">
<iframe
title={t('iframes.links', 'Links')}
src="/links?embed=1"
className="w-full h-full rounded-lg border border-gray-200 bg-white"
loading="lazy"
/>
</TabsContent>
<TabsContent value="news" className="p-4 md:p-6 h-[75vh] overflow-y-auto">
<div className="rounded-lg border border-gray-200 bg-white overflow-hidden">
<div className="px-4 md:px-6 py-4 border-b border-gray-200 bg-gray-50">
<h3 className="text-xl font-bold text-gray-900">{t('tabs.news', 'Aktuelles/News')}</h3>
<div className="text-sm text-gray-600 mt-1">
{t('news.subtitle', 'Klicken Sie auf ein Thema, um Details einzublenden.')}
</div>
</div>
<Accordion type="single" collapsible className="w-full">
{newsItems.map((item) => (
<AccordionItem
key={item.key}
value={item.key}
className="border-b border-gray-200 data-[state=open]:bg-blue-50"
>
<AccordionTrigger className="px-4 md:px-6 py-3 hover:no-underline text-left">
<span className="text-sm md:text-base text-gray-900">
<span className="text-blue-700 font-semibold mr-2">»</span>
{item.title}
</span>
</AccordionTrigger>
<AccordionContent className="px-4 md:px-6">
<div className="text-sm text-gray-700 pb-4">{item.content}</div>
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</div>
</TabsContent>
<TabsContent value="daily-info" className="p-4 md:p-6 h-[75vh] overflow-y-auto">
<div className="rounded-lg border border-gray-200 bg-white overflow-hidden">
<div className="px-4 md:px-6 py-4 border-b border-gray-200 bg-gray-50">
<h3 className="text-xl font-bold text-gray-900">Tägliche Info</h3>
<div className="text-sm text-gray-600 mt-1">
Kurze Hinweise & Orientierung täglich aktualisiert.
</div>
</div>
<div className="p-4 md:p-6">
<Accordion type="multiple" className="w-full space-y-6">
<AccordionItem value="daily-economy" className="rounded-xl border border-gray-200 bg-white shadow-sm overflow-hidden">
<AccordionTrigger className="p-0 hover:no-underline">
<div className="w-full">
<div className="p-6 md:p-8 grid grid-cols-1 md:grid-cols-[80px_1fr_auto] gap-6 items-center text-left">
<div className="flex justify-center md:justify-start">
<div className="w-12 h-12 rounded-full bg-blue-700 text-white flex items-center justify-center text-2xl font-bold">1</div>
</div>
<div>
<div className="text-xl md:text-2xl font-bold text-gray-900">Wirtschaft</div>
<div className="mt-2 text-sm md:text-base text-gray-700">Tägliche Schlagzeilen & Einordnung (externe Quellen).</div>
</div>
<div className="flex justify-center md:justify-end">
<Newspaper className="w-10 h-10 text-blue-700" strokeWidth={1.25} />
</div>
</div>
<div className="h-1.5 bg-blue-700" />
</div>
</AccordionTrigger>
<AccordionContent className="px-6 md:px-8">
<div className="pb-6">
<div className="mt-4">
<div className="text-xs uppercase tracking-wide text-gray-500 font-semibold mb-2">Quellen</div>
<div className="flex flex-wrap gap-3">
{[
{ title: 'Tagesschau Wirtschaft', href: 'https://www.tagesschau.de/wirtschaft/' },
{ title: 'Wirtschaftswoche', href: 'https://www.wiwo.de/' },
].map((link) => (
<a
key={link.href}
href={link.href}
target="_blank"
rel="noreferrer"
className="text-blue-700 hover:text-blue-900 hover:underline text-sm font-medium transition-colors duration-200 flex items-center gap-1"
>
<ExternalLink className="w-3 h-3" />
<span>{link.title}</span>
</a>
))}
</div>
</div>
</div>
</AccordionContent>
</AccordionItem>
<AccordionItem value="daily-stocks" className="rounded-xl border border-gray-200 bg-white shadow-sm overflow-hidden">
<AccordionTrigger className="p-0 hover:no-underline">
<div className="w-full">
<div className="p-6 md:p-8 grid grid-cols-1 md:grid-cols-[80px_1fr_auto] gap-6 items-center text-left">
<div className="flex justify-center md:justify-start">
<div className="w-12 h-12 rounded-full bg-blue-700 text-white flex items-center justify-center text-2xl font-bold">2</div>
</div>
<div>
<div className="text-xl md:text-2xl font-bold text-gray-900">Aktienmarkt</div>
<div className="mt-2 text-sm md:text-base text-gray-700">DAX/EuroStoxx/US-Märkte News & Einordnung (externe Quellen).</div>
</div>
<div className="flex justify-center md:justify-end">
<LineChart className="w-10 h-10 text-blue-700" strokeWidth={1.25} />
</div>
</div>
<div className="h-1.5 bg-blue-700" />
</div>
</AccordionTrigger>
<AccordionContent className="px-6 md:px-8">
<div className="pb-6">
<div className="mt-4">
<div className="text-xs uppercase tracking-wide text-gray-500 font-semibold mb-2">Quellen</div>
<div className="flex flex-wrap gap-3">
{[
{ title: 'Tagesschau Börse', href: 'https://www.tagesschau.de/wirtschaft/boerse/' },
{ title: 'Börse Frankfurt', href: 'https://www.boerse-frankfurt.de/' },
].map((link) => (
<a
key={link.href}
href={link.href}
target="_blank"
rel="noreferrer"
className="text-blue-700 hover:text-blue-900 hover:underline text-sm font-medium transition-colors duration-200 flex items-center gap-1"
>
<ExternalLink className="w-3 h-3" />
<span>{link.title}</span>
</a>
))}
</div>
</div>
</div>
</AccordionContent>
</AccordionItem>
<AccordionItem value="daily-weather" className="rounded-xl border border-gray-200 bg-white shadow-sm overflow-hidden">
<AccordionTrigger className="p-0 hover:no-underline">
<div className="w-full">
<div className="p-6 md:p-8 grid grid-cols-1 md:grid-cols-[80px_1fr_auto] gap-6 items-center text-left">
<div className="flex justify-center md:justify-start">
<div className="w-12 h-12 rounded-full bg-blue-700 text-white flex items-center justify-center text-2xl font-bold">3</div>
</div>
<div>
<div className="text-xl md:text-2xl font-bold text-gray-900">Wetter (Region)</div>
<div className="mt-2 text-sm md:text-base text-gray-700">Düsseldorf (40235) & Umgebung Live-Stand + Quellen.</div>
</div>
<div className="flex justify-center md:justify-end">
<CloudSun className="w-10 h-10 text-blue-700" strokeWidth={1.25} />
</div>
</div>
<div className="h-1.5 bg-blue-700" />
</div>
</AccordionTrigger>
<AccordionContent className="px-6 md:px-8">
<div className="pb-6">
<div className="mt-4 grid grid-cols-1 sm:grid-cols-3 gap-3">
<div className="rounded-lg border border-gray-200 bg-gray-50 p-3">
<div className="text-xs text-gray-500">Temperatur</div>
<div className="mt-1 text-lg font-bold text-gray-900">
{weather.isLoading ? '…' : weather.temp != null ? `${Math.round(weather.temp)}°C` : '—'}
</div>
</div>
<div className="rounded-lg border border-gray-200 bg-gray-50 p-3">
<div className="text-xs text-gray-500">Wind</div>
<div className="mt-1 text-lg font-bold text-gray-900">
{weather.isLoading ? '…' : weather.wind != null ? `${Math.round(weather.wind)} km/h` : '—'}
</div>
</div>
<div className="rounded-lg border border-gray-200 bg-gray-50 p-3">
<div className="text-xs text-gray-500">Zeit</div>
<div className="mt-1 text-sm font-semibold text-gray-900">
{weather.isLoading ? '…' : weather.time != null ? weather.time.replace('T', ' ') : '—'}
</div>
</div>
</div>
<div className="mt-4">
<div className="text-xs uppercase tracking-wide text-gray-500 font-semibold mb-2">Quellen</div>
<div className="flex flex-wrap gap-3">
{[
{
title: 'DWD Warnungen (Düsseldorf)',
href: 'https://www.dwd.de/DE/wetter/warnungen_gemeinden/warnWetter_node.html?ort=D%C3%BCsseldorf',
},
{ title: 'wetter.com Düsseldorf', href: 'https://www.wetter.com/deutschland/duesseldorf/DE0000001.html' },
].map((link) => (
<a
key={link.href}
href={link.href}
target="_blank"
rel="noreferrer"
className="text-blue-700 hover:text-blue-900 hover:underline text-sm font-medium transition-colors duration-200 flex items-center gap-1"
>
<ExternalLink className="w-3 h-3" />
<span>{link.title}</span>
</a>
))}
</div>
</div>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
<div className="mt-4 rounded-lg border border-gray-200 p-4 bg-white">
<div className="flex items-start gap-3">
<TrendingUp className="w-5 h-5 text-blue-700 mt-0.5" strokeWidth={1.25} />
<div>
<div className="text-sm font-semibold text-gray-900">Hinweis</div>
<div className="mt-1 text-sm text-gray-700">
Wenn du möchtest, kann ich die Region für Wetter anpassen (z.B. Stadt/PLZ) und/oder statt Links ein Widget/Feed einbauen.
</div>
</div>
</div>
</div>
</div>
</div>
</TabsContent>
<TabsContent value="faq" className="p-4 md:p-6">
<div className="rounded-lg border border-gray-200 bg-white overflow-hidden">
<div className="px-4 md:px-6 py-4 border-b border-gray-200 bg-gray-50">
<h3 className="text-xl font-bold text-gray-900">{t('faq.title', 'FAQ')}</h3>
<div className="text-sm text-gray-600 mt-1">
{t('faq.subtitle', 'Klicken Sie auf ein Thema, um Details einzublenden.')}
</div>
</div>
<Accordion type="single" collapsible className="w-full">
{[
{
key: 'private-haftpflicht',
title: 'Private Haftpflichtversicherung',
content:
'Schützt Sie vor finanziellen Folgen, wenn Sie anderen unbeabsichtigt einen Personen-, Sach- oder Vermögensschaden zufügen. Sie prüft außerdem Ansprüche (passiver Rechtsschutz): berechtigte Ansprüche werden bezahlt, unberechtigte abgewehrt.',
},
{
key: 'kfz',
title: 'KFZ-Versicherung',
content:
'Kfz-Haftpflicht ist in Deutschland Pflicht und deckt Schäden ab, die Sie mit dem Fahrzeug bei anderen verursachen. Teilkasko schützt u.a. vor Diebstahl, Glasbruch, Brand, Sturm/Hagel. Vollkasko umfasst zusätzlich selbstverschuldete Unfallschäden am eigenen Fahrzeug sowie Vandalismus (je nach Tarif).',
},
{
key: 'hausrat',
title: 'Hausratversicherung',
content:
'Versichert bewegliche Gegenstände in Ihrer Wohnung/Ihrem Haus (z.B. Möbel, Kleidung, Elektrogeräte) gegen typische Gefahren wie Feuer, Leitungswasser, Sturm/Hagel und Einbruchdiebstahl. Wichtig sind passende Versicherungssumme und richtige Wohnfläche, damit kein Unterversicherung entsteht.',
},
{
key: 'rechtsschutz',
title: 'Rechtsschutzversicherung',
content:
'Übernimmt je nach Baustein Kosten für Anwälte, Gerichte, Gutachter und ggf. Mediation, wenn Sie Ihre rechtlichen Interessen durchsetzen oder abwehren müssen. Häufige Bereiche sind Privat-, Berufs-, Verkehrs- und Wohnrechtsschutz. Oft gibt es Wartezeiten und Ausschlüsse (z.B. bereits laufende Konflikte).',
},
{
key: 'bu',
title: 'Berufsunfähigkeitsversicherung',
content:
'Zahlt eine monatliche Rente, wenn Sie Ihren Beruf aus gesundheitlichen Gründen dauerhaft (meist ab 50% Berufsunfähigkeit) nicht mehr ausüben können. Entscheidend sind passende Rentenhöhe, Laufzeit (oft bis Rentenbeginn) sowie die Gesundheitsprüfung und die konkrete Ausgestaltung der Bedingungen.',
},
{
key: 'lebensversicherung',
title: 'Lebensversicherung / Risikoleben',
content:
'Risikolebensversicherung zahlt eine vereinbarte Summe, wenn die versicherte Person während der Laufzeit verstirbt typischer Schutz für Familie oder Kredit (z.B. Immobilienfinanzierung). Eine (kapitalbildende) Lebensversicherung kombiniert Todesfallschutz mit Spar-/Kapitalaufbau, ist aber je nach Produktform und Kostenstruktur sehr unterschiedlich.',
},
].map((item) => (
<AccordionItem
key={item.key}
value={item.key}
className="border-b border-gray-200 data-[state=open]:bg-blue-50"
>
<AccordionTrigger className="px-4 md:px-6 py-3 hover:no-underline text-left">
<span className="text-sm md:text-base text-gray-900">
<span className="text-blue-700 font-semibold mr-2">»</span>
{item.title}
</span>
</AccordionTrigger>
<AccordionContent className="px-4 md:px-6">
<div className="text-sm text-gray-700 pb-4">{item.content}</div>
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</div>
</TabsContent>
<div className="p-4 md:p-6">
<GeneralNotice className="rounded-md border border-gray-200 bg-white p-4" />
</div>
</Tabs>
</div>
</div>
</div>
</Layout>
);
}