111 lines
3.7 KiB
TypeScript
111 lines
3.7 KiB
TypeScript
import { useParams, Navigate } from "react-router-dom";
|
|
import { Navbar3 } from "../components/Navbar";
|
|
import { Team4, Team4Defaults } from "../components/Team4";
|
|
import { Footer3 } from "../components/Footer";
|
|
import webflowLogo from "../assets/webflow.png";
|
|
import relumeLogo from "../assets/relume.png";
|
|
|
|
const ALL_SPEAKERS = Team4Defaults.teamMembers;
|
|
|
|
const SPONSORS = [
|
|
{ src: webflowLogo, alt: "Webflow" },
|
|
{ src: relumeLogo, alt: "Relume" },
|
|
];
|
|
|
|
const SponsorsSection = () => (
|
|
<section className="bg-tech-navy px-[5%] py-16 md:py-24 font-barlow">
|
|
<div className="container">
|
|
<h2 className="mb-12 text-center text-4xl font-bold text-cloud-white md:text-5xl">
|
|
Unsere Sponsoren & Partner
|
|
</h2>
|
|
<div className="flex flex-wrap items-center justify-center gap-8">
|
|
{SPONSORS.map((sponsor) => (
|
|
<div
|
|
key={sponsor.alt}
|
|
className="flex items-center justify-center rounded-lg border border-white/10 bg-white/5 px-8 py-6"
|
|
>
|
|
<img src={sponsor.src} alt={sponsor.alt} className="h-10 w-auto object-contain" />
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
|
|
const SpeakerDetail = () => {
|
|
const { slug } = useParams<{ slug: string }>();
|
|
const speaker = ALL_SPEAKERS.find((s) => s.slug === slug);
|
|
|
|
if (!speaker) return <Navigate to="/speaker" replace />;
|
|
|
|
const otherSpeakers = ALL_SPEAKERS.filter((s) => s.slug !== slug);
|
|
|
|
return (
|
|
<div>
|
|
<Navbar3 />
|
|
|
|
{/* Hero image */}
|
|
<div className="w-full aspect-[16/7] overflow-hidden">
|
|
<img
|
|
src={(speaker.detailImage ?? speaker.image).src}
|
|
alt={(speaker.detailImage ?? speaker.image).alt}
|
|
className="size-full object-cover object-top"
|
|
/>
|
|
</div>
|
|
|
|
{/* Speaker info */}
|
|
<section className="bg-tech-navy px-[5%] py-16 md:py-24 font-barlow">
|
|
<div className="container">
|
|
<div className="grid grid-cols-1 gap-12 lg:grid-cols-2 lg:gap-20">
|
|
{/* Left: badge, name, location */}
|
|
<div>
|
|
<span className="mb-6 inline-block rounded-full bg-acid-lime px-4 py-1.5 text-sm font-bold text-tech-navy">
|
|
{speaker.category}
|
|
</span>
|
|
<h1 className="mb-4 text-5xl font-bold text-cloud-white md:text-7xl">
|
|
{speaker.name}
|
|
</h1>
|
|
{speaker.location && (
|
|
<p className="text-base text-cloud-white/60">{speaker.location}</p>
|
|
)}
|
|
</div>
|
|
|
|
{/* Right: bio + social */}
|
|
<div className="flex flex-col justify-center gap-6">
|
|
<p className="text-base leading-relaxed text-cloud-white/80 md:text-lg">
|
|
{speaker.fullBio ?? speaker.description}
|
|
</p>
|
|
{speaker.socialLinks.filter((l) => l.href !== "#").length > 0 && (
|
|
<div className="flex gap-4">
|
|
{speaker.socialLinks.filter((l) => l.href !== "#").map((link, i) => (
|
|
<a
|
|
key={i}
|
|
href={link.href}
|
|
className="text-cloud-white/60 hover:text-acid-lime transition-colors"
|
|
>
|
|
{link.icon}
|
|
</a>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Other speakers */}
|
|
<section className="bg-cloud-white px-[5%] pt-16 font-barlow">
|
|
<div className="container mb-10">
|
|
<h2 className="text-3xl font-bold text-tech-navy md:text-4xl">Weitere Speaker</h2>
|
|
</div>
|
|
</section>
|
|
<Team4 teamMembers={otherSpeakers} />
|
|
|
|
<SponsorsSection />
|
|
<Footer3 />
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SpeakerDetail;
|