93 lines
5.0 KiB
TypeScript
93 lines
5.0 KiB
TypeScript
import { Link, useParams } from "react-router-dom";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Card, CardContent } from "@/components/ui/card";
|
|
import { ArrowLeft, Twitter, Linkedin, Github, Clock, MapPin } from "lucide-react";
|
|
import Header from "@/components/Header";
|
|
import Footer from "@/components/Footer";
|
|
|
|
const speakerData: Record<string, { initials: string; name: string; role: string; company: string; bio: string; expertise: string[]; gradient: string; sessions: { day: string; time: string; title: string; room: string }[] }> = {
|
|
"speaker-1": {
|
|
initials: "SK", name: "Sarah Kim", role: "VP Engineering", company: "Vercel",
|
|
bio: "Sarah has spent over a decade building web infrastructure at scale. As VP of Engineering at Vercel, she leads the team behind Next.js and champions developer experience. She is a frequent keynote speaker at conferences worldwide and a passionate advocate for open-source software.",
|
|
expertise: ["React", "Performance", "Server Components", "Next.js"],
|
|
gradient: "from-indigo-500 to-cyan-500",
|
|
sessions: [
|
|
{ day: "Day 1", time: "09:00", title: "Opening Keynote: The Future of Web", room: "Main Hall" },
|
|
{ day: "Day 3", time: "11:30", title: "Micro-Frontends: Lessons Learned", room: "Room B" },
|
|
],
|
|
},
|
|
"speaker-2": {
|
|
initials: "AM", name: "Alex Morgan", role: "CTO", company: "Supabase",
|
|
bio: "Alex co-founded Supabase to make backend development accessible to everyone. With deep expertise in PostgreSQL and real-time systems, they have helped thousands of developers ship faster. Previously a senior engineer at Stripe, Alex brings a unique blend of infrastructure and product thinking.",
|
|
expertise: ["TypeScript", "APIs", "Databases", "Open Source"],
|
|
gradient: "from-purple-500 to-pink-500",
|
|
sessions: [
|
|
{ day: "Day 1", time: "10:00", title: "React Server Components in Production", room: "Room A" },
|
|
{ day: "Day 2", time: "14:00", title: "Full-Stack TypeScript Patterns", room: "Room B" },
|
|
],
|
|
},
|
|
};
|
|
|
|
export default function SpeakerDetailPage() {
|
|
const { id } = useParams();
|
|
const speaker = speakerData[id || ""] || speakerData["speaker-1"];
|
|
|
|
return (
|
|
<div className="min-h-screen bg-slate-950 text-white">
|
|
<Header />
|
|
|
|
<section className="pt-32 pb-24 px-6">
|
|
<div className="mx-auto max-w-4xl">
|
|
<Link to="/speakers" className="inline-flex items-center gap-2 text-sm text-slate-400 hover:text-indigo-400 transition-colors mb-8">
|
|
<ArrowLeft className="h-4 w-4" />Back to Speakers
|
|
</Link>
|
|
|
|
<div className="flex flex-col md:flex-row gap-8 items-start">
|
|
<div className={`w-32 h-32 rounded-full bg-gradient-to-br ${speaker.gradient} flex items-center justify-center text-3xl font-bold text-white ring-2 ring-offset-2 ring-offset-slate-950 ring-indigo-500/50 shrink-0`}>
|
|
{speaker.initials}
|
|
</div>
|
|
<div className="flex-1">
|
|
<h1 className="text-4xl font-black tracking-tight mb-2">{speaker.name}</h1>
|
|
<p className="text-lg text-slate-400 mb-4">{speaker.role}, {speaker.company}</p>
|
|
<div className="flex gap-2 mb-6">
|
|
{[Twitter, Linkedin, Github].map((Icon, i) => (
|
|
<Button key={i} variant="outline" size="icon" className="border-slate-700 text-slate-400 hover:text-indigo-400 hover:border-indigo-500"><Icon className="h-4 w-4" /></Button>
|
|
))}
|
|
</div>
|
|
<div className="text-slate-300 leading-relaxed mb-6 space-y-4">
|
|
<p>{speaker.bio}</p>
|
|
</div>
|
|
<div className="flex flex-wrap gap-2">
|
|
{speaker.expertise.map((tag) => (
|
|
<Badge key={tag} className="bg-indigo-500/10 text-indigo-400 border-indigo-500/20">{tag}</Badge>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Sessions */}
|
|
<div className="mt-16">
|
|
<h2 className="text-2xl font-black tracking-tight mb-6 animate-fade-up">Sessions</h2>
|
|
<div className="space-y-4">
|
|
{speaker.sessions.map((s, i) => (
|
|
<Card key={i} className="bg-slate-900/50 border-slate-800">
|
|
<CardContent className="p-4 flex flex-col md:flex-row md:items-center gap-4">
|
|
<Badge variant="outline" className="border-indigo-500/30 text-indigo-400 shrink-0">{s.day}</Badge>
|
|
<div className="flex items-center gap-2 text-sm text-slate-400 shrink-0">
|
|
<Clock className="h-4 w-4" />{s.time}
|
|
</div>
|
|
<div className="font-semibold text-white flex-1">{s.title}</div>
|
|
<Badge variant="outline" className="border-slate-700 text-slate-400 shrink-0"><MapPin className="h-3 w-3 mr-1" />{s.room}</Badge>
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<Footer />
|
|
</div>
|
|
);
|
|
} |