feat: Hero, About, Contact components accept CMS props
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b9aa6a0a54
commit
3eeea27b92
|
|
@ -19,7 +19,19 @@ const highlights = [
|
|||
},
|
||||
];
|
||||
|
||||
export default function About() {
|
||||
interface AboutProps {
|
||||
eyebrowText?: string;
|
||||
absatz1?: string;
|
||||
absatz2?: string;
|
||||
stats?: { wert: string; label: string }[];
|
||||
}
|
||||
|
||||
export default function About({
|
||||
eyebrowText = "Über uns",
|
||||
absatz1 = "MBO-Tech-IT steht für über 30 Jahre IT-Erfahrung — angefangen bei der einfachen Hardware-Wartung, über den Aufbau großer Client-Server-Netzwerke, bis hin zu mehr als 20 Jahren Spezialisierung in der IT-Security.",
|
||||
absatz2 = "Heute liegt der Fokus auf modernen Container-Technologien, Cloud-nativer Infrastruktur und Virtualisierung. Dieses breite Fundament ermöglicht es, Lösungen zu entwickeln, die nicht nur funktionieren — sondern auch sicher und langfristig tragfähig sind.",
|
||||
stats,
|
||||
}: AboutProps = {}) {
|
||||
return (
|
||||
<section id="about" className="py-24 px-4 sm:px-6 lg:px-8 relative">
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_bottom_right,rgba(37,99,235,0.06)_0%,transparent_60%)]" />
|
||||
|
|
@ -29,23 +41,17 @@ export default function About() {
|
|||
{/* Left: Text */}
|
||||
<div>
|
||||
<span className="text-orange-400 font-mono text-xs font-bold tracking-[0.25em] uppercase">
|
||||
Über uns
|
||||
{eyebrowText}
|
||||
</span>
|
||||
<h2 className="text-4xl sm:text-5xl font-black text-slate-900 dark:text-white mt-3 mb-6 leading-tight">
|
||||
IT-Expertise,{" "}
|
||||
<span className="text-gradient">die Sie weiterbringt</span>
|
||||
</h2>
|
||||
<p className="text-slate-600 dark:text-slate-400 text-lg leading-relaxed mb-6">
|
||||
MBO-Tech-IT steht für über <strong className="text-slate-900 dark:text-white">30 Jahre IT-Erfahrung</strong> —
|
||||
angefangen bei der einfachen Hardware-Wartung, über den Aufbau großer
|
||||
Client-Server-Netzwerke, bis hin zu mehr als 20 Jahren Spezialisierung
|
||||
in der <strong className="text-slate-900 dark:text-white">IT-Security</strong>.
|
||||
{absatz1}
|
||||
</p>
|
||||
<p className="text-slate-600 dark:text-slate-400 text-lg leading-relaxed mb-8">
|
||||
Heute liegt der Fokus auf modernen Container-Technologien, Cloud-nativer
|
||||
Infrastruktur und Virtualisierung. Dieses breite Fundament ermöglicht es,
|
||||
Lösungen zu entwickeln, die nicht nur funktionieren — sondern auch
|
||||
sicher und langfristig tragfähig sind.
|
||||
{absatz2}
|
||||
</p>
|
||||
|
||||
{/* Tagline callout */}
|
||||
|
|
@ -76,6 +82,17 @@ export default function About() {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{stats && stats.length > 0 && (
|
||||
<div className="flex gap-8 mt-4">
|
||||
{stats.map((s) => (
|
||||
<div key={s.label}>
|
||||
<div className="text-3xl font-black text-orange-400">{s.wert}</div>
|
||||
<div className="text-sm text-slate-500 dark:text-slate-400">{s.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right: Process steps */}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,26 @@
|
|||
|
||||
import { useState } from "react";
|
||||
|
||||
const contactItems = [
|
||||
interface OeffnungsZeit { tag: string; von: string; bis: string }
|
||||
|
||||
interface ContactProps {
|
||||
telefon?: string;
|
||||
email?: string;
|
||||
adresseZeile1?: string;
|
||||
adresseZeile2?: string;
|
||||
oeffnungszeiten?: OeffnungsZeit[];
|
||||
}
|
||||
|
||||
type Status = "idle" | "loading" | "success" | "error";
|
||||
|
||||
export default function Contact({
|
||||
telefon = "+49 171 9345193",
|
||||
email = "kontakt@mbo-tech-it.de",
|
||||
adresseZeile1 = "Mörikestr. 2",
|
||||
adresseZeile2 = "74564 Crailsheim",
|
||||
oeffnungszeiten,
|
||||
}: ContactProps = {}) {
|
||||
const contactItems = [
|
||||
{
|
||||
icon: (
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
|
|
@ -10,8 +29,8 @@ const contactItems = [
|
|||
</svg>
|
||||
),
|
||||
label: "Telefon",
|
||||
value: "+49 171 9345193",
|
||||
href: "tel:+4917193451093",
|
||||
value: telefon,
|
||||
href: `tel:${telefon.replace(/\s/g, "")}`,
|
||||
},
|
||||
{
|
||||
icon: (
|
||||
|
|
@ -20,8 +39,8 @@ const contactItems = [
|
|||
</svg>
|
||||
),
|
||||
label: "E-Mail",
|
||||
value: "kontakt@mbo-tech-it.de",
|
||||
href: "mailto:kontakt@mbo-tech-it.de",
|
||||
value: email,
|
||||
href: `mailto:${email}`,
|
||||
},
|
||||
{
|
||||
icon: (
|
||||
|
|
@ -31,16 +50,13 @@ const contactItems = [
|
|||
</svg>
|
||||
),
|
||||
label: "Standort",
|
||||
value: "Crailsheim, 74564",
|
||||
href: "https://maps.google.com/?q=Mörikestr.+2,+74564+Crailsheim",
|
||||
value: `${adresseZeile1}, ${adresseZeile2}`,
|
||||
href: `https://maps.google.com/?q=${encodeURIComponent(adresseZeile1 + " " + adresseZeile2)}`,
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
type Status = "idle" | "loading" | "success" | "error";
|
||||
|
||||
export default function Contact() {
|
||||
const [name, setName] = useState("");
|
||||
const [email, setEmail] = useState("");
|
||||
const [emailInput, setEmailInput] = useState("");
|
||||
const [betreff, setBetreff] = useState("");
|
||||
const [nachricht, setNachricht] = useState("");
|
||||
const [status, setStatus] = useState<Status>("idle");
|
||||
|
|
@ -55,7 +71,7 @@ export default function Contact() {
|
|||
const res = await fetch("/api/contact", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ name, email, betreff, nachricht }),
|
||||
body: JSON.stringify({ name, email: emailInput, betreff, nachricht }),
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
|
|
@ -108,7 +124,7 @@ export default function Contact() {
|
|||
onClick={() => {
|
||||
setStatus("idle");
|
||||
setName("");
|
||||
setEmail("");
|
||||
setEmailInput("");
|
||||
setBetreff("");
|
||||
setNachricht("");
|
||||
}}
|
||||
|
|
@ -136,8 +152,8 @@ export default function Contact() {
|
|||
<input
|
||||
type="email"
|
||||
required
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
value={emailInput}
|
||||
onChange={(e) => setEmailInput(e.target.value)}
|
||||
placeholder="max@beispiel.de"
|
||||
className="w-full px-4 py-3 rounded-xl bg-slate-50 dark:bg-[#111925] border border-slate-300 dark:border-gray-700 text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-600 focus:outline-none focus:border-orange-500/60 focus:ring-1 focus:ring-orange-500/20 transition-colors"
|
||||
/>
|
||||
|
|
@ -239,6 +255,22 @@ export default function Contact() {
|
|||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{oeffnungszeiten && oeffnungszeiten.length > 0 && (
|
||||
<div className="mt-6 pt-6 border-t border-slate-200 dark:border-slate-700">
|
||||
<h4 className="text-sm font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wider mb-3">
|
||||
Öffnungszeiten
|
||||
</h4>
|
||||
<ul className="space-y-1">
|
||||
{oeffnungszeiten.map((oz) => (
|
||||
<li key={oz.tag} className="flex justify-between text-sm text-slate-600 dark:text-slate-400">
|
||||
<span>{oz.tag}</span>
|
||||
<span>{oz.von} – {oz.bis}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,33 @@
|
|||
// components/Hero.tsx
|
||||
"use client";
|
||||
|
||||
import { useMemo } from "react";
|
||||
import { useTypewriter } from "@/hooks/useTypewriter";
|
||||
|
||||
export default function Hero() {
|
||||
interface HeroProps {
|
||||
eyebrowText?: string;
|
||||
headline1?: string;
|
||||
subtext1?: string;
|
||||
subtext2?: string;
|
||||
cta1Text?: string;
|
||||
cta1Href?: string;
|
||||
cta2Text?: string;
|
||||
cta2Href?: string;
|
||||
bgImagePath?: string | null;
|
||||
badges?: string[];
|
||||
}
|
||||
|
||||
export default function Hero({
|
||||
eyebrowText = "Digital Denken. Lokal Handeln.",
|
||||
headline1 = "Ihre IT-Infrastruktur.",
|
||||
subtext1 = "Ihr IT-Dienstleister in Crailsheim — egal ob zu Hause oder im Büro. Von Hard- & Software über Netzwerk & WLAN bis hin zu Webseiten & Webanwendungen: Wir lösen Ihre IT-Probleme persönlich und zum fairen Preis.",
|
||||
subtext2 = "",
|
||||
cta1Text = "Jetzt anfragen",
|
||||
cta1Href = "#contact",
|
||||
cta2Text = "Unsere Leistungen",
|
||||
cta2Href = "#services",
|
||||
bgImagePath = null,
|
||||
badges = ["Docker", "Kubernetes", "Proxmox", "Hetzner Cloud", "Linux"],
|
||||
}: HeroProps = {}) {
|
||||
const words = useMemo(() => ["Professionell.", "DSGVO-konform.", "Zuverlässig.", "Skalierbar."], []);
|
||||
const typed = useTypewriter(words);
|
||||
|
||||
|
|
@ -20,48 +43,60 @@ export default function Hero() {
|
|||
<div className="absolute top-1/4 left-1/4 w-72 h-72 bg-orange-500/5 rounded-full blur-3xl animate-pulse-slow" />
|
||||
<div className="absolute bottom-1/4 right-1/4 w-80 h-80 bg-blue-600/5 rounded-full blur-3xl animate-pulse-slow" />
|
||||
|
||||
{bgImagePath && (
|
||||
<div
|
||||
className="absolute inset-0 bg-cover bg-center opacity-20"
|
||||
style={{ backgroundImage: `url(${process.env.NEXT_PUBLIC_SUPABASE_URL}/storage/v1/object/public/hero-bilder/${bgImagePath})` }}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
{/* Tagline badge */}
|
||||
<div className="inline-flex items-center gap-2 px-5 py-2 rounded-full border border-orange-500/40 bg-orange-500/10 text-orange-400 text-xs font-black tracking-[0.3em] uppercase mb-8">
|
||||
<span className="w-1.5 h-1.5 bg-orange-400 rounded-full animate-pulse" />
|
||||
Digital Denken. Lokal Handeln.
|
||||
{eyebrowText}
|
||||
</div>
|
||||
|
||||
{/* Headline */}
|
||||
<h1 className="text-5xl sm:text-6xl lg:text-7xl font-black text-slate-900 dark:text-white leading-tight mb-6 tracking-tight">
|
||||
Ihre IT-Infrastruktur.{" "}
|
||||
{headline1}{" "}
|
||||
<span className="text-gradient">
|
||||
{typed}
|
||||
<span className="animate-pulse">|</span>
|
||||
</span>
|
||||
<br />
|
||||
Skalierbar. Zuverlässig.
|
||||
</h1>
|
||||
|
||||
{/* Subheadline */}
|
||||
{subtext1 && (
|
||||
<p className="text-xl sm:text-2xl text-slate-600 dark:text-slate-400 max-w-3xl mx-auto mb-4 leading-relaxed">
|
||||
Ihr IT-Dienstleister in <strong className="text-slate-700 dark:text-slate-300">Crailsheim</strong> — egal ob zu Hause oder im Büro. Von Hard- & Software über Netzwerk & WLAN bis hin zu Webseiten & Webanwendungen: Wir lösen Ihre IT-Probleme persönlich und zum fairen Preis.
|
||||
{subtext1}
|
||||
</p>
|
||||
)}
|
||||
{subtext2 && (
|
||||
<p className="text-xl sm:text-2xl text-slate-600 dark:text-slate-400 max-w-3xl mx-auto mb-4 leading-relaxed">
|
||||
{subtext2}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Tech pills */}
|
||||
<div className="flex flex-wrap items-center justify-center gap-3 mb-10">
|
||||
{["Docker", "Kubernetes", "Proxmox", "Hetzner Cloud", "Linux"].map((tech) => (
|
||||
{badges.map((badge) => (
|
||||
<span
|
||||
key={tech}
|
||||
key={badge}
|
||||
className="px-3 py-1 rounded-md bg-slate-100 dark:bg-gray-900 border border-slate-200 dark:border-gray-700 text-slate-700 dark:text-slate-300 text-sm font-mono"
|
||||
>
|
||||
{tech}
|
||||
{badge}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* CTAs */}
|
||||
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
|
||||
<a href="#contact" className="btn-primary w-full sm:w-auto px-8 py-4 text-lg">
|
||||
Projekt anfragen
|
||||
<a href={cta1Href} className="btn-primary w-full sm:w-auto px-8 py-4 text-lg">
|
||||
{cta1Text}
|
||||
</a>
|
||||
<a href="#services" className="btn-secondary w-full sm:w-auto px-8 py-4 text-lg">
|
||||
Services ansehen
|
||||
<a href={cta2Href} className="btn-secondary w-full sm:w-auto px-8 py-4 text-lg">
|
||||
{cta2Text}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue