mirror of
https://github.com/complexcaresolutions/frontend.zweitmeinu.ng.git
synced 2026-03-17 17:23:48 +00:00
fix: replace hardcoded content with CMS data
- Phone number: 10 locations now use CMS site-settings contact.phone - ContactForm: service dropdown options from CMS services - FAQ categories: display names derived from CMS services - Footer: Top Fachbereiche column dynamic from CMS services - SEO metadata: fachbereiche, faq, kontakt use generateMetadata() - HomeCTA: converted to async server component, fetches settings - Added phoneToHref() helper to payload-helpers.ts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1aad09cc0f
commit
0e5c9808a8
13 changed files with 190 additions and 102 deletions
|
|
@ -4,7 +4,8 @@ import { Container } from "@/components/ui/Container"
|
||||||
import { Button } from "@/components/ui/Button"
|
import { Button } from "@/components/ui/Button"
|
||||||
import { RichTextRenderer } from "@/components/ui/RichTextRenderer"
|
import { RichTextRenderer } from "@/components/ui/RichTextRenderer"
|
||||||
import { getLucideIcon } from "@/lib/icon-map"
|
import { getLucideIcon } from "@/lib/icon-map"
|
||||||
import { getServices, getServiceBySlug } from "@/lib/api"
|
import { getServices, getServiceBySlug, getSiteSettings } from "@/lib/api"
|
||||||
|
import { phoneToHref } from "@/lib/payload-helpers"
|
||||||
import { Phone, Mail, ArrowRight, Check } from "lucide-react"
|
import { Phone, Mail, ArrowRight, Check } from "lucide-react"
|
||||||
|
|
||||||
export async function generateStaticParams() {
|
export async function generateStaticParams() {
|
||||||
|
|
@ -32,14 +33,15 @@ export default async function ServiceDetailPage({
|
||||||
params: Promise<{ slug: string }>
|
params: Promise<{ slug: string }>
|
||||||
}) {
|
}) {
|
||||||
const { slug } = await params
|
const { slug } = await params
|
||||||
const service = await getServiceBySlug(slug)
|
const [service, settings] = await Promise.all([
|
||||||
|
getServiceBySlug(slug),
|
||||||
|
getSiteSettings(),
|
||||||
|
])
|
||||||
if (!service) notFound()
|
if (!service) notFound()
|
||||||
|
|
||||||
const Icon = getLucideIcon(service.icon)
|
const Icon = getLucideIcon(service.icon)
|
||||||
const shortTitle = service.title.replace(/^Zweitmeinung\s+/, "")
|
const shortTitle = service.title.replace(/^Zweitmeinung\s+/, "")
|
||||||
const categoryName = typeof service.category === "object" && service.category
|
const phone = settings?.contact?.phone || "0800 80 44 100"
|
||||||
? service.category.name
|
|
||||||
: null
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -60,7 +62,7 @@ export default async function ServiceDetailPage({
|
||||||
{service.shortDescription}
|
{service.shortDescription}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-wrap justify-center gap-4">
|
<div className="flex flex-wrap justify-center gap-4">
|
||||||
<Button href="tel:+4980080441000" variant="gold" size="lg">
|
<Button href={phoneToHref(phone)} variant="gold" size="lg">
|
||||||
<Phone className="h-4 w-4" />
|
<Phone className="h-4 w-4" />
|
||||||
Jetzt beraten lassen
|
Jetzt beraten lassen
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -197,9 +199,9 @@ export default async function ServiceDetailPage({
|
||||||
Einschätzung im Bereich {shortTitle}.
|
Einschätzung im Bereich {shortTitle}.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-wrap justify-center gap-4">
|
<div className="flex flex-wrap justify-center gap-4">
|
||||||
<Button href="tel:+4980080441000" variant="gold" size="lg">
|
<Button href={phoneToHref(phone)} variant="gold" size="lg">
|
||||||
<Phone className="h-4 w-4" />
|
<Phone className="h-4 w-4" />
|
||||||
+49 800 80 44 100
|
{phone}
|
||||||
</Button>
|
</Button>
|
||||||
<Button href="/kontakt" variant="secondary" size="lg">
|
<Button href="/kontakt" variant="secondary" size="lg">
|
||||||
<Mail className="h-4 w-4" />
|
<Mail className="h-4 w-4" />
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,17 @@ import Link from "next/link"
|
||||||
import { ArrowRight, Phone } from "lucide-react"
|
import { ArrowRight, Phone } from "lucide-react"
|
||||||
import { Container } from "@/components/ui/Container"
|
import { Container } from "@/components/ui/Container"
|
||||||
import { Button } from "@/components/ui/Button"
|
import { Button } from "@/components/ui/Button"
|
||||||
import { getServices } from "@/lib/api"
|
import { getServices, getSiteSettings } from "@/lib/api"
|
||||||
import { getLucideIcon } from "@/lib/icon-map"
|
import { getLucideIcon } from "@/lib/icon-map"
|
||||||
|
import { phoneToHref } from "@/lib/payload-helpers"
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
title: "Fachbereiche",
|
const services = await getServices()
|
||||||
description: "Medizinische Zweitmeinung in 6 Fachbereichen: Intensivmedizin, Kardiologie, Onkologie, Nephrologie, Gallenblase und Schilddrüse.",
|
const names = services.map((s) => s.title.replace(/^Zweitmeinung\s+/, "")).join(", ")
|
||||||
|
return {
|
||||||
|
title: "Fachbereiche",
|
||||||
|
description: `Medizinische Zweitmeinung in ${services.length} Fachbereichen: ${names}.`,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const colorMap: Record<string, string> = {
|
const colorMap: Record<string, string> = {
|
||||||
|
|
@ -21,7 +26,11 @@ const colorMap: Record<string, string> = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function FachbereichePage() {
|
export default async function FachbereichePage() {
|
||||||
const services = await getServices()
|
const [services, settings] = await Promise.all([
|
||||||
|
getServices(),
|
||||||
|
getSiteSettings(),
|
||||||
|
])
|
||||||
|
const phone = settings?.contact?.phone || "0800 80 44 100"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -99,9 +108,9 @@ export default async function FachbereichePage() {
|
||||||
Rufen Sie uns an – wir helfen Ihnen, den richtigen Fachbereich zu
|
Rufen Sie uns an – wir helfen Ihnen, den richtigen Fachbereich zu
|
||||||
finden und beraten Sie unverbindlich.
|
finden und beraten Sie unverbindlich.
|
||||||
</p>
|
</p>
|
||||||
<Button href="tel:+4980080441000" variant="gold" size="lg">
|
<Button href={phoneToHref(phone)} variant="gold" size="lg">
|
||||||
<Phone className="h-4 w-4" />
|
<Phone className="h-4 w-4" />
|
||||||
0800 80 44 100 (kostenlos)
|
{phone} (kostenlos)
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
|
||||||
|
|
@ -3,32 +3,39 @@ import { Container } from "@/components/ui/Container"
|
||||||
import { Button } from "@/components/ui/Button"
|
import { Button } from "@/components/ui/Button"
|
||||||
import { FAQClient } from "@/components/faq/FAQClient"
|
import { FAQClient } from "@/components/faq/FAQClient"
|
||||||
import { Phone, Mail, HelpCircle } from "lucide-react"
|
import { Phone, Mail, HelpCircle } from "lucide-react"
|
||||||
import { getFaqs } from "@/lib/api"
|
import { getFaqs, getServices, getSiteSettings } from "@/lib/api"
|
||||||
import { richTextToPlainText } from "@/components/ui/RichTextRenderer"
|
import { richTextToPlainText } from "@/components/ui/RichTextRenderer"
|
||||||
|
import { phoneToHref } from "@/lib/payload-helpers"
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
title: "FAQ - Häufige Fragen",
|
const services = await getServices()
|
||||||
description:
|
const names = services.map((s) => s.title.replace(/^Zweitmeinung\s+/, "")).join(", ")
|
||||||
"Antworten auf die wichtigsten Fragen zur medizinischen Zweitmeinung. Von Onkologie über Kardiologie bis Intensivmedizin.",
|
return {
|
||||||
}
|
title: "FAQ - Häufige Fragen",
|
||||||
|
description: `Antworten auf die wichtigsten Fragen zur medizinischen Zweitmeinung. ${names}.`,
|
||||||
const categoryNames: Record<string, string> = {
|
}
|
||||||
allgemein: "Allgemeine Fragen",
|
|
||||||
intensivmedizin: "Intensivmedizin",
|
|
||||||
kardiologie: "Kardiologie",
|
|
||||||
onkologie: "Onkologie",
|
|
||||||
nephrologie: "Nephrologie",
|
|
||||||
gallenblase: "Gallenblase",
|
|
||||||
schilddruese: "Schilddrüse",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function FAQPage() {
|
export default async function FAQPage() {
|
||||||
const faqs = await getFaqs()
|
const [faqs, services, settings] = await Promise.all([
|
||||||
|
getFaqs(),
|
||||||
|
getServices(),
|
||||||
|
getSiteSettings(),
|
||||||
|
])
|
||||||
|
|
||||||
|
const phone = settings?.contact?.phone || "0800 80 44 100"
|
||||||
|
|
||||||
|
// Build category names from services (slug suffix → title without "Zweitmeinung ")
|
||||||
|
const serviceCategoryNames: Record<string, string> = { allgemein: "Allgemeine Fragen" }
|
||||||
|
for (const s of services) {
|
||||||
|
const suffix = s.slug.replace(/^zweitmeinung-/, "")
|
||||||
|
serviceCategoryNames[suffix] = s.title.replace(/^Zweitmeinung\s+/, "")
|
||||||
|
}
|
||||||
|
|
||||||
// Derive categories from data
|
// Derive categories from data
|
||||||
const categorySlugs = [...new Set(faqs.map((f) => f.category).filter((c): c is string => !!c))]
|
const categorySlugs = [...new Set(faqs.map((f) => f.category).filter((c): c is string => !!c))]
|
||||||
const categories = categorySlugs.map((slug: string) => ({
|
const categories = categorySlugs.map((slug: string) => ({
|
||||||
name: categoryNames[slug] || slug,
|
name: serviceCategoryNames[slug] || slug,
|
||||||
slug,
|
slug,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
@ -75,7 +82,7 @@ export default async function FAQPage() {
|
||||||
kostenlose Erstberatung.
|
kostenlose Erstberatung.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-wrap justify-center gap-4">
|
<div className="flex flex-wrap justify-center gap-4">
|
||||||
<Button href="tel:+4980080441000" variant="gold" size="lg">
|
<Button href={phoneToHref(phone)} variant="gold" size="lg">
|
||||||
<Phone className="h-4 w-4" />
|
<Phone className="h-4 w-4" />
|
||||||
Jetzt anrufen
|
Jetzt anrufen
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,22 @@ import type { Metadata } from "next"
|
||||||
import { Container } from "@/components/ui/Container"
|
import { Container } from "@/components/ui/Container"
|
||||||
import { ContactForm } from "@/components/contact/ContactForm"
|
import { ContactForm } from "@/components/contact/ContactForm"
|
||||||
import { Phone, Mail, MapPin, Clock, Printer } from "lucide-react"
|
import { Phone, Mail, MapPin, Clock, Printer } from "lucide-react"
|
||||||
import { getSiteSettings } from "@/lib/api"
|
import { getSiteSettings, getServices } from "@/lib/api"
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
title: "Kontakt",
|
const settings = await getSiteSettings()
|
||||||
description: "Kontaktieren Sie uns für eine kostenlose Erstberatung. Telefon: 0800 80 44 100.",
|
const phone = settings?.contact?.phone || "0800 80 44 100"
|
||||||
|
return {
|
||||||
|
title: "Kontakt",
|
||||||
|
description: `Kontaktieren Sie uns für eine kostenlose Erstberatung. Telefon: ${phone}.`,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function KontaktPage() {
|
export default async function KontaktPage() {
|
||||||
const settings = await getSiteSettings()
|
const [settings, services] = await Promise.all([
|
||||||
|
getSiteSettings(),
|
||||||
|
getServices(),
|
||||||
|
])
|
||||||
|
|
||||||
const phone = settings?.contact?.phone || "0800 80 44 100"
|
const phone = settings?.contact?.phone || "0800 80 44 100"
|
||||||
const email = settings?.contact?.email || "kontakt@zweitmeinu.ng"
|
const email = settings?.contact?.email || "kontakt@zweitmeinu.ng"
|
||||||
|
|
@ -18,7 +25,12 @@ export default async function KontaktPage() {
|
||||||
const street = settings?.address?.street || "Hans-Böckler-Str. 19"
|
const street = settings?.address?.street || "Hans-Böckler-Str. 19"
|
||||||
const zip = settings?.address?.zip || "46236"
|
const zip = settings?.address?.zip || "46236"
|
||||||
const city = settings?.address?.city || "Bottrop"
|
const city = settings?.address?.city || "Bottrop"
|
||||||
const phoneHref = `tel:${phone.replace(/[\s/]/g, "")}`
|
const phoneHref = `tel:+49${phone.replace(/[\s/()-]/g, "").substring(1)}`
|
||||||
|
|
||||||
|
const serviceOptions = services.map((s) => ({
|
||||||
|
value: s.slug.replace(/^zweitmeinung-/, ""),
|
||||||
|
label: s.title.replace(/^Zweitmeinung\s+/, ""),
|
||||||
|
}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -109,7 +121,7 @@ export default async function KontaktPage() {
|
||||||
<h2 className="text-xl font-bold text-navy mb-6">
|
<h2 className="text-xl font-bold text-navy mb-6">
|
||||||
Nachricht senden
|
Nachricht senden
|
||||||
</h2>
|
</h2>
|
||||||
<ContactForm />
|
<ContactForm serviceOptions={serviceOptions} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import type { Metadata } from "next"
|
import type { Metadata } from "next"
|
||||||
import { TopBar, Header, Footer, EmergencyBanner } from "@/components/layout"
|
import { TopBar, Header, Footer, EmergencyBanner } from "@/components/layout"
|
||||||
import { getNavigation, getSiteSettings, getSocialLinks, getServices } from "@/lib/api"
|
import { getNavigation, getSiteSettings, getSocialLinks, getServices } from "@/lib/api"
|
||||||
|
import { phoneToHref } from "@/lib/payload-helpers"
|
||||||
import "./globals.css"
|
import "./globals.css"
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
|
|
@ -32,12 +33,20 @@ export default async function RootLayout({
|
||||||
getServices(),
|
getServices(),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
const phone = settings?.contact?.phone || "0800 80 44 100"
|
||||||
|
const email = settings?.contact?.email || "kontakt@zweitmeinu.ng"
|
||||||
|
|
||||||
const headerServices = services.map((s) => ({
|
const headerServices = services.map((s) => ({
|
||||||
title: s.title,
|
title: s.title,
|
||||||
slug: s.slug,
|
slug: s.slug,
|
||||||
icon: s.icon ?? null,
|
icon: s.icon ?? null,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
const footerServices = services.map((s) => ({
|
||||||
|
title: s.title.replace(/^Zweitmeinung\s+/, ""),
|
||||||
|
slug: s.slug,
|
||||||
|
}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang="de">
|
<html lang="de">
|
||||||
<body className="font-body antialiased">
|
<body className="font-body antialiased">
|
||||||
|
|
@ -49,12 +58,12 @@ export default async function RootLayout({
|
||||||
</a>
|
</a>
|
||||||
<div className="flex min-h-screen flex-col">
|
<div className="flex min-h-screen flex-col">
|
||||||
<TopBar settings={settings} />
|
<TopBar settings={settings} />
|
||||||
<Header mainMenu={navigation?.mainMenu ?? null} services={headerServices} />
|
<Header mainMenu={navigation?.mainMenu ?? null} services={headerServices} phone={phone} email={email} />
|
||||||
<main id="main-content" className="flex-1">
|
<main id="main-content" className="flex-1">
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
<EmergencyBanner settings={settings} />
|
<EmergencyBanner settings={settings} />
|
||||||
<Footer socialLinks={socialLinks} settings={settings} />
|
<Footer socialLinks={socialLinks} settings={settings} services={footerServices} />
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import type { Metadata } from "next"
|
import type { Metadata } from "next"
|
||||||
import { Container } from "@/components/ui/Container"
|
import { Container } from "@/components/ui/Container"
|
||||||
import { Button } from "@/components/ui/Button"
|
import { Button } from "@/components/ui/Button"
|
||||||
|
import { getSiteSettings } from "@/lib/api"
|
||||||
|
import { phoneToHref } from "@/lib/payload-helpers"
|
||||||
import {
|
import {
|
||||||
Phone, FileText, UserCheck, ClipboardCheck,
|
Phone, FileText, UserCheck, ClipboardCheck,
|
||||||
MessageSquare, HeartHandshake, Shield, Clock,
|
MessageSquare, HeartHandshake, Shield, Clock,
|
||||||
|
|
@ -28,7 +30,10 @@ const whyCards = [
|
||||||
{ title: "Persönlich", description: "Case Management und persönliche Betreuung von Anfang an.", icon: Users },
|
{ title: "Persönlich", description: "Case Management und persönliche Betreuung von Anfang an.", icon: Users },
|
||||||
]
|
]
|
||||||
|
|
||||||
export default function SoFunktionierts() {
|
export default async function SoFunktionierts() {
|
||||||
|
const settings = await getSiteSettings()
|
||||||
|
const phone = settings?.contact?.phone || "0800 80 44 100"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Hero */}
|
{/* Hero */}
|
||||||
|
|
@ -104,9 +109,9 @@ export default function SoFunktionierts() {
|
||||||
fundierte, unabhängige Einschätzung.
|
fundierte, unabhängige Einschätzung.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-wrap justify-center gap-4">
|
<div className="flex flex-wrap justify-center gap-4">
|
||||||
<Button href="tel:+4980080441000" variant="gold" size="lg">
|
<Button href={phoneToHref(phone)} variant="gold" size="lg">
|
||||||
<Phone className="h-4 w-4" />
|
<Phone className="h-4 w-4" />
|
||||||
0800 80 44 100
|
{phone}
|
||||||
</Button>
|
</Button>
|
||||||
<Button href="/kontakt" variant="secondary" size="lg">
|
<Button href="/kontakt" variant="secondary" size="lg">
|
||||||
Kontaktformular
|
Kontaktformular
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import type { Metadata } from "next"
|
import type { Metadata } from "next"
|
||||||
import { Container } from "@/components/ui/Container"
|
import { Container } from "@/components/ui/Container"
|
||||||
import { Button } from "@/components/ui/Button"
|
import { Button } from "@/components/ui/Button"
|
||||||
|
import { getSiteSettings } from "@/lib/api"
|
||||||
|
import { phoneToHref } from "@/lib/payload-helpers"
|
||||||
import {
|
import {
|
||||||
Shield, Award, Users, Heart, Phone,
|
Shield, Award, Users, Heart, Phone,
|
||||||
CheckCircle, Building, Globe,
|
CheckCircle, Building, Globe,
|
||||||
|
|
@ -18,7 +20,10 @@ const qualityCards = [
|
||||||
{ title: "Netzwerk", description: "Über 1000 Expert:innen aus über 50 Fachbereichen deutschlandweit.", icon: Globe },
|
{ title: "Netzwerk", description: "Über 1000 Expert:innen aus über 50 Fachbereichen deutschlandweit.", icon: Globe },
|
||||||
]
|
]
|
||||||
|
|
||||||
export default function UeberUnsPage() {
|
export default async function UeberUnsPage() {
|
||||||
|
const settings = await getSiteSettings()
|
||||||
|
const phone = settings?.contact?.phone || "0800 80 44 100"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Hero */}
|
{/* Hero */}
|
||||||
|
|
@ -99,7 +104,7 @@ export default function UeberUnsPage() {
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2 text-sm">
|
<div className="flex items-center gap-2 text-sm">
|
||||||
<CheckCircle className="h-4 w-4 text-gold shrink-0" />
|
<CheckCircle className="h-4 w-4 text-gold shrink-0" />
|
||||||
<span className="text-text-muted">Kostenlose Servicehotline: 0800 80 44 100</span>
|
<span className="text-text-muted">Kostenlose Servicehotline: {phone}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -117,9 +122,9 @@ export default function UeberUnsPage() {
|
||||||
<p className="text-text-muted mb-8">
|
<p className="text-text-muted mb-8">
|
||||||
Wir beraten Sie gerne unverbindlich und kostenfrei.
|
Wir beraten Sie gerne unverbindlich und kostenfrei.
|
||||||
</p>
|
</p>
|
||||||
<Button href="tel:+4980080441000" variant="gold" size="lg">
|
<Button href={phoneToHref(phone)} variant="gold" size="lg">
|
||||||
<Phone className="h-4 w-4" />
|
<Phone className="h-4 w-4" />
|
||||||
0800 80 44 100 (kostenlos)
|
{phone} (kostenlos)
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,11 @@ import { Send, Loader2, CheckCircle } from "lucide-react"
|
||||||
|
|
||||||
const PAYLOAD_URL = process.env.NEXT_PUBLIC_PAYLOAD_URL || "https://cms.c2sgmbh.de"
|
const PAYLOAD_URL = process.env.NEXT_PUBLIC_PAYLOAD_URL || "https://cms.c2sgmbh.de"
|
||||||
|
|
||||||
export function ContactForm() {
|
interface ContactFormProps {
|
||||||
|
serviceOptions?: Array<{ value: string; label: string }>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ContactForm({ serviceOptions = [] }: ContactFormProps) {
|
||||||
const [form, setForm] = useState({
|
const [form, setForm] = useState({
|
||||||
name: "",
|
name: "",
|
||||||
email: "",
|
email: "",
|
||||||
|
|
@ -52,6 +56,17 @@ export function ContactForm() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const options = serviceOptions.length > 0
|
||||||
|
? serviceOptions
|
||||||
|
: [
|
||||||
|
{ value: "intensivmedizin", label: "Intensivmedizin" },
|
||||||
|
{ value: "kardiologie", label: "Kardiologie" },
|
||||||
|
{ value: "onkologie", label: "Onkologie" },
|
||||||
|
{ value: "nephrologie", label: "Nephrologie" },
|
||||||
|
{ value: "gallenblase", label: "Gallenblase" },
|
||||||
|
{ value: "schilddruese", label: "Schilddrüse" },
|
||||||
|
]
|
||||||
|
|
||||||
if (status === "success") {
|
if (status === "success") {
|
||||||
return (
|
return (
|
||||||
<div className="text-center py-12">
|
<div className="text-center py-12">
|
||||||
|
|
@ -129,12 +144,9 @@ export function ContactForm() {
|
||||||
className="w-full px-4 py-2.5 rounded-lg border border-border bg-bg focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary text-sm"
|
className="w-full px-4 py-2.5 rounded-lg border border-border bg-bg focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary text-sm"
|
||||||
>
|
>
|
||||||
<option value="">Bitte wählen...</option>
|
<option value="">Bitte wählen...</option>
|
||||||
<option value="intensivmedizin">Intensivmedizin</option>
|
{options.map((opt) => (
|
||||||
<option value="kardiologie">Kardiologie</option>
|
<option key={opt.value} value={opt.value}>{opt.label}</option>
|
||||||
<option value="onkologie">Onkologie</option>
|
))}
|
||||||
<option value="nephrologie">Nephrologie</option>
|
|
||||||
<option value="gallenblase">Gallenblase</option>
|
|
||||||
<option value="schilddruese">Schilddrüse</option>
|
|
||||||
<option value="sonstiges">Sonstiges</option>
|
<option value="sonstiges">Sonstiges</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
import { Phone, Mail } from "lucide-react"
|
import { Phone, Mail } from "lucide-react"
|
||||||
import { Container } from "@/components/ui/Container"
|
import { Container } from "@/components/ui/Container"
|
||||||
import { Button } from "@/components/ui/Button"
|
import { Button } from "@/components/ui/Button"
|
||||||
|
import { getSiteSettings } from "@/lib/api"
|
||||||
|
import { phoneToHref } from "@/lib/payload-helpers"
|
||||||
|
|
||||||
|
export async function HomeCTA() {
|
||||||
|
const settings = await getSiteSettings()
|
||||||
|
const phone = settings?.contact?.phone || "0800 80 44 100"
|
||||||
|
|
||||||
export function HomeCTA() {
|
|
||||||
return (
|
return (
|
||||||
<section className="py-20 bg-white">
|
<section className="py-20 bg-white">
|
||||||
<Container size="md">
|
<Container size="md">
|
||||||
|
|
@ -15,7 +20,7 @@ export function HomeCTA() {
|
||||||
Sicherheit, die Sie verdienen.
|
Sicherheit, die Sie verdienen.
|
||||||
</h2>
|
</h2>
|
||||||
<div className="flex flex-wrap justify-center gap-4 mt-8">
|
<div className="flex flex-wrap justify-center gap-4 mt-8">
|
||||||
<Button href="tel:+4980080441000" variant="gold" size="lg">
|
<Button href={phoneToHref(phone)} variant="gold" size="lg">
|
||||||
<Phone className="h-4 w-4" />
|
<Phone className="h-4 w-4" />
|
||||||
Jetzt kostenlos beraten lassen
|
Jetzt kostenlos beraten lassen
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -6,51 +6,50 @@ import { socialLinksToMap } from "@/lib/payload-helpers"
|
||||||
interface FooterProps {
|
interface FooterProps {
|
||||||
socialLinks?: SocialLink[]
|
socialLinks?: SocialLink[]
|
||||||
settings?: SiteSetting | null
|
settings?: SiteSetting | null
|
||||||
|
services?: Array<{ title: string; slug: string }>
|
||||||
}
|
}
|
||||||
|
|
||||||
const footerColumns = [
|
export function Footer({ socialLinks, settings, services = [] }: FooterProps) {
|
||||||
{
|
|
||||||
title: "Top Fachbereiche",
|
|
||||||
links: [
|
|
||||||
{ label: "Kardiologie", href: "/fachbereiche/zweitmeinung-kardiologie" },
|
|
||||||
{ label: "Onkologie", href: "/fachbereiche/zweitmeinung-onkologie" },
|
|
||||||
{ label: "Intensivmedizin", href: "/fachbereiche/zweitmeinung-intensivmedizin" },
|
|
||||||
{ label: "Nephrologie", href: "/fachbereiche/zweitmeinung-nephrologie" },
|
|
||||||
{ label: "Gallenblase", href: "/fachbereiche/zweitmeinung-gallenblase" },
|
|
||||||
{ label: "Schilddrüse", href: "/fachbereiche/zweitmeinung-schilddruese" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Services",
|
|
||||||
links: [
|
|
||||||
{ label: "So funktioniert's", href: "/so-funktionierts" },
|
|
||||||
{ label: "Häufige Fragen (FAQ)", href: "/faq" },
|
|
||||||
{ label: "Alle Fachbereiche", href: "/fachbereiche" },
|
|
||||||
{ label: "Kontakt", href: "/kontakt" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Unternehmen",
|
|
||||||
links: [
|
|
||||||
{ label: "Über uns", href: "/ueber-uns" },
|
|
||||||
{ label: "Motivation", href: "/motivation" },
|
|
||||||
{ label: "complex care solutions GmbH", href: "https://complexcaresolutions.de" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Rechtliches",
|
|
||||||
links: [
|
|
||||||
{ label: "Impressum", href: "/impressum" },
|
|
||||||
{ label: "Datenschutz", href: "/datenschutz" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
export function Footer({ socialLinks, settings }: FooterProps) {
|
|
||||||
const socialMap = socialLinksToMap(socialLinks)
|
const socialMap = socialLinksToMap(socialLinks)
|
||||||
const copyright = settings?.footer?.copyrightText ||
|
const copyright = settings?.footer?.copyrightText ||
|
||||||
`\u00A9 ${new Date().getFullYear()} complex care solutions GmbH. Alle Rechte vorbehalten.`
|
`\u00A9 ${new Date().getFullYear()} complex care solutions GmbH. Alle Rechte vorbehalten.`
|
||||||
|
|
||||||
|
const fachbereicheLinks = services.length > 0
|
||||||
|
? services.map((s) => ({ label: s.title, href: `/fachbereiche/${s.slug}` }))
|
||||||
|
: [
|
||||||
|
{ label: "Kardiologie", href: "/fachbereiche/zweitmeinung-kardiologie" },
|
||||||
|
{ label: "Onkologie", href: "/fachbereiche/zweitmeinung-onkologie" },
|
||||||
|
{ label: "Intensivmedizin", href: "/fachbereiche/zweitmeinung-intensivmedizin" },
|
||||||
|
]
|
||||||
|
|
||||||
|
const footerColumns = [
|
||||||
|
{ title: "Top Fachbereiche", links: fachbereicheLinks },
|
||||||
|
{
|
||||||
|
title: "Services",
|
||||||
|
links: [
|
||||||
|
{ label: "So funktioniert's", href: "/so-funktionierts" },
|
||||||
|
{ label: "Häufige Fragen (FAQ)", href: "/faq" },
|
||||||
|
{ label: "Alle Fachbereiche", href: "/fachbereiche" },
|
||||||
|
{ label: "Kontakt", href: "/kontakt" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Unternehmen",
|
||||||
|
links: [
|
||||||
|
{ label: "Über uns", href: "/ueber-uns" },
|
||||||
|
{ label: "Motivation", href: "/motivation" },
|
||||||
|
{ label: "complex care solutions GmbH", href: "https://complexcaresolutions.de" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Rechtliches",
|
||||||
|
links: [
|
||||||
|
{ label: "Impressum", href: "/impressum" },
|
||||||
|
{ label: "Datenschutz", href: "/datenschutz" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="bg-navy text-white">
|
<footer className="bg-navy text-white">
|
||||||
{/* Trust Section */}
|
{/* Trust Section */}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ import type { Navigation } from "@c2s/payload-contracts/types"
|
||||||
interface HeaderProps {
|
interface HeaderProps {
|
||||||
mainMenu: Navigation["mainMenu"] | null
|
mainMenu: Navigation["mainMenu"] | null
|
||||||
services?: Array<{ title: string; slug: string; icon: string | null }>
|
services?: Array<{ title: string; slug: string; icon: string | null }>
|
||||||
|
phone?: string
|
||||||
|
email?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const emojiMap: Record<string, string> = {
|
const emojiMap: Record<string, string> = {
|
||||||
|
|
@ -28,7 +30,7 @@ const navLinks = [
|
||||||
{ label: "Kontakt", href: "/kontakt" },
|
{ label: "Kontakt", href: "/kontakt" },
|
||||||
]
|
]
|
||||||
|
|
||||||
export function Header({ mainMenu, services = [] }: HeaderProps) {
|
export function Header({ mainMenu, services = [], phone, email }: HeaderProps) {
|
||||||
const [mobileOpen, setMobileOpen] = useState(false)
|
const [mobileOpen, setMobileOpen] = useState(false)
|
||||||
const [megaOpen, setMegaOpen] = useState(false)
|
const [megaOpen, setMegaOpen] = useState(false)
|
||||||
const [scrolled, setScrolled] = useState(false)
|
const [scrolled, setScrolled] = useState(false)
|
||||||
|
|
@ -45,6 +47,10 @@ export function Header({ mainMenu, services = [] }: HeaderProps) {
|
||||||
icon: emojiMap[s.icon || ""] || "📋",
|
icon: emojiMap[s.icon || ""] || "📋",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
const phoneHref = phone
|
||||||
|
? `tel:+49${phone.replace(/[\s/()-]/g, "").substring(1)}`
|
||||||
|
: "tel:+4980080441000"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<header
|
<header
|
||||||
|
|
@ -128,7 +134,7 @@ export function Header({ mainMenu, services = [] }: HeaderProps) {
|
||||||
{/* Emergency CTA + Mobile Toggle */}
|
{/* Emergency CTA + Mobile Toggle */}
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<a
|
<a
|
||||||
href="tel:+4980080441000"
|
href={phoneHref}
|
||||||
className="hidden sm:flex items-center gap-2 bg-gold hover:bg-gold-hover text-navy-dark font-bold text-sm px-4 py-2 rounded-lg transition-colors animate-pulse-gold"
|
className="hidden sm:flex items-center gap-2 bg-gold hover:bg-gold-hover text-navy-dark font-bold text-sm px-4 py-2 rounded-lg transition-colors animate-pulse-gold"
|
||||||
>
|
>
|
||||||
<Phone className="h-4 w-4" />
|
<Phone className="h-4 w-4" />
|
||||||
|
|
@ -151,6 +157,8 @@ export function Header({ mainMenu, services = [] }: HeaderProps) {
|
||||||
onClose={() => setMobileOpen(false)}
|
onClose={() => setMobileOpen(false)}
|
||||||
services={megaServices}
|
services={megaServices}
|
||||||
navLinks={navLinks}
|
navLinks={navLinks}
|
||||||
|
phone={phone}
|
||||||
|
email={email}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,11 @@ interface MobileMenuProps {
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
services: Array<{ name: string; slug: string; icon: string }>
|
services: Array<{ name: string; slug: string; icon: string }>
|
||||||
navLinks: Array<{ label: string; href: string }>
|
navLinks: Array<{ label: string; href: string }>
|
||||||
|
phone?: string
|
||||||
|
email?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MobileMenu({ open, onClose, services, navLinks }: MobileMenuProps) {
|
export function MobileMenu({ open, onClose, services, navLinks, phone, email }: MobileMenuProps) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) document.body.style.overflow = "hidden"
|
if (open) document.body.style.overflow = "hidden"
|
||||||
else document.body.style.overflow = ""
|
else document.body.style.overflow = ""
|
||||||
|
|
@ -20,6 +22,11 @@ export function MobileMenu({ open, onClose, services, navLinks }: MobileMenuProp
|
||||||
|
|
||||||
if (!open) return null
|
if (!open) return null
|
||||||
|
|
||||||
|
const phoneHref = phone
|
||||||
|
? `tel:+49${phone.replace(/[\s/()-]/g, "").substring(1)}`
|
||||||
|
: "tel:+4980080441000"
|
||||||
|
const emailAddr = email || "kontakt@zweitmeinu.ng"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-[100]">
|
<div className="fixed inset-0 z-[100]">
|
||||||
{/* Backdrop */}
|
{/* Backdrop */}
|
||||||
|
|
@ -77,14 +84,14 @@ export function MobileMenu({ open, onClose, services, navLinks }: MobileMenuProp
|
||||||
{/* Emergency CTA */}
|
{/* Emergency CTA */}
|
||||||
<div className="p-4 border-t">
|
<div className="p-4 border-t">
|
||||||
<a
|
<a
|
||||||
href="tel:+4980080441000"
|
href={phoneHref}
|
||||||
className="flex items-center justify-center gap-2 w-full bg-gold hover:bg-gold-hover text-navy-dark font-bold py-3 rounded-xl transition-colors"
|
className="flex items-center justify-center gap-2 w-full bg-gold hover:bg-gold-hover text-navy-dark font-bold py-3 rounded-xl transition-colors"
|
||||||
>
|
>
|
||||||
<Phone className="h-5 w-5" />
|
<Phone className="h-5 w-5" />
|
||||||
Notfall-Zweitmeinung
|
Notfall-Zweitmeinung
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="mailto:kontakt@zweitmeinu.ng"
|
href={`mailto:${emailAddr}`}
|
||||||
className="flex items-center justify-center gap-2 w-full mt-3 border border-navy text-navy font-medium py-3 rounded-xl hover:bg-navy hover:text-white transition-colors"
|
className="flex items-center justify-center gap-2 w-full mt-3 border border-navy text-navy font-medium py-3 rounded-xl hover:bg-navy hover:text-white transition-colors"
|
||||||
>
|
>
|
||||||
<Mail className="h-5 w-5" />
|
<Mail className="h-5 w-5" />
|
||||||
|
|
|
||||||
|
|
@ -48,3 +48,11 @@ export function socialLinksToMap(
|
||||||
}
|
}
|
||||||
return map
|
return map
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function phoneToHref(phone: string | null | undefined): string {
|
||||||
|
if (!phone) return "tel:+4980080441000"
|
||||||
|
const digits = phone.replace(/[\s/()-]/g, "")
|
||||||
|
if (digits.startsWith("+")) return `tel:${digits}`
|
||||||
|
if (digits.startsWith("0")) return `tel:+49${digits.substring(1)}`
|
||||||
|
return `tel:${digits}`
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue