Redesign homepage: editorial layout with current focus + featured work
Replaced the dense mini-CV homepage with an editorial landing page:
- Hero: punchy one-liner ("Researcher & builder. HRI at BU, motorsports
software at Riverhead.") instead of a paragraph bio
- Currently building: Riverhead Raceway mobile app (racehub-app) and
Hotlap (Go monorepo race event management platform)
- Featured work: Honors thesis, IEEE RO-MAN 2025, Riverhead Raceway site,
beenvoice — each with description, tags, and a direct action button
- Education: compact 2-col grid (BU + Bucknell) replaces the full card layout
- Explore: same 3-col nav to Projects / Publications / CV
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+309
-299
@@ -1,16 +1,15 @@
|
|||||||
import {
|
import {
|
||||||
ArrowUpRight,
|
ArrowUpRight,
|
||||||
Award,
|
|
||||||
BookOpen,
|
BookOpen,
|
||||||
Building,
|
|
||||||
Code,
|
Code,
|
||||||
ExternalLink,
|
ExternalLink,
|
||||||
FlaskConical,
|
FileText,
|
||||||
|
Flag,
|
||||||
|
Globe,
|
||||||
GraduationCap,
|
GraduationCap,
|
||||||
Mail,
|
Mail,
|
||||||
MapPin,
|
MapPin,
|
||||||
School,
|
Smartphone,
|
||||||
Users
|
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Badge } from "~/components/ui/badge";
|
import { Badge } from "~/components/ui/badge";
|
||||||
@@ -22,60 +21,56 @@ import {
|
|||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "~/components/ui/card";
|
} from "~/components/ui/card";
|
||||||
import { awards, educationList, experiences, researchInterests } from "~/lib/data";
|
import { educationList } from "~/lib/data";
|
||||||
|
|
||||||
|
function SectionLabel({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<h2 className="text-xs font-semibold uppercase tracking-widest text-muted-foreground">
|
||||||
|
{children}
|
||||||
|
</h2>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
const researchExperience = experiences.filter(
|
|
||||||
(exp) => exp.type === "research",
|
|
||||||
);
|
|
||||||
const teachingExperience = experiences.filter(
|
|
||||||
(exp) => exp.type === "teaching",
|
|
||||||
);
|
|
||||||
const professionalExperience = experiences.filter(
|
|
||||||
(exp) => exp.type === "professional",
|
|
||||||
);
|
|
||||||
const leadershipExperience = experiences.filter(
|
|
||||||
(exp) => exp.type === "leadership",
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-12">
|
<div className="space-y-16">
|
||||||
{/* Hero Section */}
|
|
||||||
<section className="animate-fade-in-up space-y-6">
|
{/* Hero */}
|
||||||
|
<section className="animate-fade-in-up space-y-5 pt-2">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h1 className="animate-fade-in-up-delay-1 text-3xl font-bold">
|
<h1 className="animate-fade-in-up-delay-1 text-4xl font-bold tracking-tight">
|
||||||
Sean O'Connor
|
Sean O'Connor
|
||||||
</h1>
|
</h1>
|
||||||
<p className="animate-fade-in-up-delay-2 text-xl text-muted-foreground">
|
<p className="animate-fade-in-up-delay-2 max-w-lg text-lg text-muted-foreground">
|
||||||
Computer Science and Engineering graduate pursuing a Master's
|
Researcher & builder. HRI at BU, motorsports software at Riverhead.
|
||||||
at Boston University. Research interests in human-robot interaction
|
|
||||||
and developing technologies that make robots better collaborators
|
|
||||||
with humans.
|
|
||||||
</p>
|
</p>
|
||||||
<div className="animate-fade-in-up-delay-3 flex flex-wrap gap-4 text-sm text-muted-foreground">
|
<div className="animate-fade-in-up-delay-3 flex flex-wrap gap-4 text-sm text-muted-foreground">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1.5">
|
||||||
<Mail className="h-4 w-4" />
|
<Mail className="h-4 w-4" />
|
||||||
<a href="mailto:sean@soconnor.dev" className="hover:text-primary">
|
<a
|
||||||
|
href="mailto:sean@soconnor.dev"
|
||||||
|
className="transition-colors hover:text-foreground"
|
||||||
|
>
|
||||||
sean@soconnor.dev
|
sean@soconnor.dev
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1.5">
|
||||||
<GraduationCap className="h-4 w-4" />
|
<GraduationCap className="h-4 w-4" />
|
||||||
Boston University
|
Boston University
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1.5">
|
||||||
<MapPin className="h-4 w-4" />
|
<MapPin className="h-4 w-4" />
|
||||||
Boston, MA
|
Boston, MA
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="animate-fade-in-up-delay-4 flex gap-3">
|
<div className="animate-fade-in-up-delay-4 flex gap-3">
|
||||||
<Button variant="outline" asChild className="button-hover">
|
<Button variant="outline" asChild>
|
||||||
<Link href="/cv">
|
<Link href="/cv">
|
||||||
<ExternalLink className="mr-2 h-4 w-4" />
|
<ExternalLink className="mr-2 h-4 w-4" />
|
||||||
View CV
|
CV
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="outline" asChild className="button-hover">
|
<Button variant="outline" asChild>
|
||||||
<Link href="/publications">
|
<Link href="/publications">
|
||||||
<BookOpen className="mr-2 h-4 w-4" />
|
<BookOpen className="mr-2 h-4 w-4" />
|
||||||
Publications
|
Publications
|
||||||
@@ -85,330 +80,344 @@ export default function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Research Interests */}
|
{/* Currently Building */}
|
||||||
<section className="animate-fade-in-up space-y-6">
|
<section className="animate-fade-in-up space-y-4">
|
||||||
<h2 className="text-2xl font-bold">Research Interests</h2>
|
<SectionLabel>Currently building</SectionLabel>
|
||||||
<div className="animate-fade-in-up-delay-1">
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
<Card className="card-hover">
|
|
||||||
<CardContent>
|
<Card className="card-hover card-full-height">
|
||||||
<p className="leading-relaxed text-muted-foreground">
|
<CardHeader>
|
||||||
{researchInterests}
|
<div className="flex items-start gap-3">
|
||||||
|
<div className="rounded-xl bg-primary/10 p-2.5">
|
||||||
|
<Smartphone className="h-5 w-5 text-primary" />
|
||||||
|
</div>
|
||||||
|
<div className="min-w-0">
|
||||||
|
<CardTitle>Riverhead Raceway Mobile App</CardTitle>
|
||||||
|
<CardDescription>racehub-app · React Native</CardDescription>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="card-content-stretch">
|
||||||
|
<div className="flex h-full flex-col gap-3">
|
||||||
|
<p className="text-sm leading-relaxed text-muted-foreground">
|
||||||
|
Native mobile companion for Riverhead Raceway — race-day
|
||||||
|
results, live standings, and event info for fans and
|
||||||
|
competitors on the track.
|
||||||
</p>
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-1.5">
|
||||||
|
{["React Native", "TypeScript", "tRPC"].map((t) => (
|
||||||
|
<Badge key={t} variant="secondary">
|
||||||
|
{t}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<Card className="card-hover card-full-height">
|
||||||
|
<CardHeader>
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<div className="rounded-xl bg-primary/10 p-2.5">
|
||||||
|
<Flag className="h-5 w-5 text-primary" />
|
||||||
|
</div>
|
||||||
|
<div className="min-w-0">
|
||||||
|
<CardTitle>Hotlap</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Race event management · Go monorepo
|
||||||
|
</CardDescription>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="card-content-stretch">
|
||||||
|
<div className="flex h-full flex-col gap-3">
|
||||||
|
<p className="text-sm leading-relaxed text-muted-foreground">
|
||||||
|
Full-stack race event management platform in Go.
|
||||||
|
Server-rendered public pages, a Solid.js SPA for track ops,
|
||||||
|
and a custom Go-native bundler powering the whole thing.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-1.5">
|
||||||
|
{["Go", "Solid.js", "PostgreSQL", "TypeScript"].map((t) => (
|
||||||
|
<Badge key={t} variant="secondary">
|
||||||
|
{t}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Featured Work */}
|
||||||
|
<section className="animate-fade-in-up space-y-4">
|
||||||
|
<SectionLabel>Featured work</SectionLabel>
|
||||||
|
<div className="grid-equal-height grid gap-4 md:grid-cols-2">
|
||||||
|
|
||||||
|
<Card className="card-hover card-full-height">
|
||||||
|
<CardHeader>
|
||||||
|
<div className="flex items-start justify-between gap-2">
|
||||||
|
<div className="min-w-0">
|
||||||
|
<CardTitle>Honors Thesis</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Bucknell University · 2026
|
||||||
|
</CardDescription>
|
||||||
|
</div>
|
||||||
|
<FileText className="h-5 w-5 flex-shrink-0 text-muted-foreground" />
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="card-content-stretch">
|
||||||
|
<div className="flex h-full flex-col gap-3">
|
||||||
|
<p className="text-sm leading-relaxed text-muted-foreground">
|
||||||
|
A web-based Wizard-of-Oz platform for accessible, reproducible
|
||||||
|
HRI research. Pilot study showed higher design fidelity and
|
||||||
|
usability than Choregraphe across all six sessions.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-1.5">
|
||||||
|
{["HRI", "Wizard-of-Oz", "React", "ROS2"].map((t) => (
|
||||||
|
<Badge key={t} variant="outline">
|
||||||
|
{t}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
asChild
|
||||||
|
className="mt-auto w-full"
|
||||||
|
>
|
||||||
|
<Link href="/publications">
|
||||||
|
Read thesis
|
||||||
|
<ArrowUpRight className="ml-1.5 h-3.5 w-3.5" />
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="card-hover card-full-height">
|
||||||
|
<CardHeader>
|
||||||
|
<div className="flex items-start justify-between gap-2">
|
||||||
|
<div className="min-w-0">
|
||||||
|
<CardTitle>IEEE RO-MAN 2025</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Eindhoven · First author
|
||||||
|
</CardDescription>
|
||||||
|
</div>
|
||||||
|
<BookOpen className="h-5 w-5 flex-shrink-0 text-muted-foreground" />
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="card-content-stretch">
|
||||||
|
<div className="flex h-full flex-col gap-3">
|
||||||
|
<p className="text-sm leading-relaxed text-muted-foreground">
|
||||||
|
Collaborative and Reproducible HRI Research Through a
|
||||||
|
Web-Based Wizard-of-Oz Platform. 34th IEEE International
|
||||||
|
Conference on Robot and Human Interactive Communication.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-1.5">
|
||||||
|
{["IEEE", "HRI", "Research"].map((t) => (
|
||||||
|
<Badge key={t} variant="outline">
|
||||||
|
{t}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
asChild
|
||||||
|
className="mt-auto w-full"
|
||||||
|
>
|
||||||
|
<Link href="/publications">
|
||||||
|
View paper
|
||||||
|
<ArrowUpRight className="ml-1.5 h-3.5 w-3.5" />
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="card-hover card-full-height">
|
||||||
|
<CardHeader>
|
||||||
|
<div className="flex items-start justify-between gap-2">
|
||||||
|
<div className="min-w-0">
|
||||||
|
<CardTitle>Riverhead Raceway</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Production · 250k+ monthly users
|
||||||
|
</CardDescription>
|
||||||
|
</div>
|
||||||
|
<Globe className="h-5 w-5 flex-shrink-0 text-muted-foreground" />
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="card-content-stretch">
|
||||||
|
<div className="flex h-full flex-col gap-3">
|
||||||
|
<p className="text-sm leading-relaxed text-muted-foreground">
|
||||||
|
Official website and CMS for Riverhead Raceway, NY.
|
||||||
|
Real-time race data, event management, standings, and a full
|
||||||
|
admin interface with 97+ granular permissions.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-1.5">
|
||||||
|
{["Next.js", "PostgreSQL", "tRPC"].map((t) => (
|
||||||
|
<Badge key={t} variant="outline">
|
||||||
|
{t}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
asChild
|
||||||
|
className="mt-auto w-full"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="https://riverheadraceway.com"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
Visit site
|
||||||
|
<ArrowUpRight className="ml-1.5 h-3.5 w-3.5" />
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="card-hover card-full-height">
|
||||||
|
<CardHeader>
|
||||||
|
<div className="flex items-start justify-between gap-2">
|
||||||
|
<div className="min-w-0">
|
||||||
|
<CardTitle>beenvoice</CardTitle>
|
||||||
|
<CardDescription>Invoicing for freelancers</CardDescription>
|
||||||
|
</div>
|
||||||
|
<Code className="h-5 w-5 flex-shrink-0 text-muted-foreground" />
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="card-content-stretch">
|
||||||
|
<div className="flex h-full flex-col gap-3">
|
||||||
|
<p className="text-sm leading-relaxed text-muted-foreground">
|
||||||
|
Professional invoicing: client management, PDF generation,
|
||||||
|
email delivery, timesheet view, and CSV import. Built with
|
||||||
|
tRPC and Drizzle ORM on Next.js 16.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-1.5">
|
||||||
|
{["Next.js", "tRPC", "Drizzle"].map((t) => (
|
||||||
|
<Badge key={t} variant="outline">
|
||||||
|
{t}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
asChild
|
||||||
|
className="mt-auto w-full"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="https://beenvoice.soconnor.dev"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
Try it
|
||||||
|
<ArrowUpRight className="ml-1.5 h-3.5 w-3.5" />
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Education */}
|
{/* Education */}
|
||||||
<section className="animate-fade-in-up space-y-6">
|
<section className="animate-fade-in-up space-y-4">
|
||||||
<h2 className="text-2xl font-bold">Education</h2>
|
<SectionLabel>Education</SectionLabel>
|
||||||
<div className="space-y-4">
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
{educationList.map((edu, index) => (
|
{educationList.map((edu, i) => (
|
||||||
<div key={index} className={`animate-fade-in-up-delay-${index + 1}`}>
|
<Card key={i} className="card-hover">
|
||||||
<Card className="card-hover">
|
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex items-center justify-between">
|
<CardTitle>{edu.institution}</CardTitle>
|
||||||
<div>
|
<CardDescription>{edu.degree}</CardDescription>
|
||||||
<CardTitle className="mb-1">{edu.institution}</CardTitle>
|
|
||||||
<CardDescription>{edu.location}</CardDescription>
|
|
||||||
</div>
|
|
||||||
<School className="h-5 w-5 text-muted-foreground" />
|
|
||||||
</div>
|
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-3">
|
<CardContent>
|
||||||
<div>
|
|
||||||
<p className="font-medium">{edu.degree}</p>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
{edu.graduated ? "" : "Expected "}{edu.expectedGraduation}
|
{edu.graduated ? "" : "Expected "}
|
||||||
|
{edu.expectedGraduation} · {edu.location}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
{edu.engineeringGpa && (
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="mt-2 flex flex-wrap gap-1.5">
|
||||||
{edu.engineeringGpa ? (
|
<Badge variant="secondary">
|
||||||
<>
|
Eng. GPA {edu.engineeringGpa}
|
||||||
<Badge variant="secondary">Eng. GPA: {edu.engineeringGpa}</Badge>
|
|
||||||
<Badge variant="outline">Overall GPA: {edu.gpa}</Badge>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Badge variant="secondary">GPA: {edu.gpa}</Badge>
|
|
||||||
)}
|
|
||||||
{edu.deansListSemesters.length > 0 && (
|
|
||||||
<Badge variant="outline">
|
|
||||||
Dean's List: {edu.deansListSemesters.length} semesters
|
|
||||||
</Badge>
|
</Badge>
|
||||||
|
<Badge variant="outline">Overall {edu.gpa}</Badge>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Research Experience */}
|
{/* Explore */}
|
||||||
<section className="animate-fade-in-up space-y-6">
|
<section className="animate-fade-in-up space-y-4">
|
||||||
<h2 className="text-2xl font-bold">Research Experience</h2>
|
<SectionLabel>Explore</SectionLabel>
|
||||||
<div className="space-y-6">
|
<div className="grid-equal-height grid gap-4 md:grid-cols-3">
|
||||||
{researchExperience.map((exp, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className={`animate-fade-in-up-delay-${index + 1}`}
|
|
||||||
>
|
|
||||||
<Card className="card-hover">
|
|
||||||
<CardHeader>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div>
|
|
||||||
<CardTitle className="mb-1">{exp.title}</CardTitle>
|
|
||||||
<CardDescription>{exp.organization}</CardDescription>
|
|
||||||
<CardDescription className="text-xs">
|
|
||||||
{exp.location} • {exp.period}
|
|
||||||
</CardDescription>
|
|
||||||
</div>
|
|
||||||
<FlaskConical className="h-5 w-5 text-muted-foreground" />
|
|
||||||
</div>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<ul className="space-y-2 text-sm text-muted-foreground">
|
|
||||||
{exp.description.map((item, itemIndex) => (
|
|
||||||
<li key={itemIndex} className="flex items-start gap-2">
|
|
||||||
<span className="mt-2 h-1 w-1 flex-shrink-0 rounded-full bg-muted-foreground" />
|
|
||||||
{item}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Professional Experience Highlights */}
|
|
||||||
<section className="animate-fade-in-up space-y-6">
|
|
||||||
<h2 className="text-2xl font-bold">
|
|
||||||
Professional Experience Highlights
|
|
||||||
</h2>
|
|
||||||
<div className="space-y-6">
|
|
||||||
{professionalExperience.slice(0, 2).map((exp, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className={`animate-fade-in-up-delay-${index + 1}`}
|
|
||||||
>
|
|
||||||
<Card className="card-hover">
|
|
||||||
<CardHeader>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div>
|
|
||||||
<CardTitle className="mb-1">{exp.title}</CardTitle>
|
|
||||||
<CardDescription>{exp.organization}</CardDescription>
|
|
||||||
<CardDescription className="text-xs">
|
|
||||||
{exp.location} • {exp.period}
|
|
||||||
</CardDescription>
|
|
||||||
</div>
|
|
||||||
<Building className="h-5 w-5 text-muted-foreground" />
|
|
||||||
</div>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<ul className="space-y-2 text-sm text-muted-foreground">
|
|
||||||
{exp.description.slice(0, 3).map((item, itemIndex) => (
|
|
||||||
<li key={itemIndex} className="flex items-start gap-2">
|
|
||||||
<span className="mt-2 h-1 w-1 flex-shrink-0 rounded-full bg-muted-foreground" />
|
|
||||||
{item}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Teaching Experience */}
|
|
||||||
<section className="animate-fade-in-up space-y-6">
|
|
||||||
<h2 className="text-2xl font-bold">Teaching Experience</h2>
|
|
||||||
<div className="grid-equal-height grid gap-6 md:grid-cols-2">
|
|
||||||
{teachingExperience.slice(0, 4).map((exp, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className={`animate-fade-in-up-delay-${index + 1}`}
|
|
||||||
>
|
|
||||||
<Card className="card-hover card-full-height">
|
|
||||||
<CardHeader>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<GraduationCap className="h-5 w-5 flex-shrink-0" />
|
|
||||||
<div className="min-w-0">
|
|
||||||
<CardTitle className="mb-1 break-words text-base leading-tight">
|
|
||||||
{exp.title}
|
|
||||||
</CardTitle>
|
|
||||||
<CardDescription className="break-words text-xs">
|
|
||||||
{exp.organization}
|
|
||||||
</CardDescription>
|
|
||||||
<CardDescription className="text-xs">
|
|
||||||
{exp.period}
|
|
||||||
</CardDescription>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="card-content-stretch">
|
|
||||||
<p className="text-sm leading-relaxed text-muted-foreground">
|
|
||||||
{exp.description[0]}
|
|
||||||
</p>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Leadership & Activities */}
|
|
||||||
<section className="animate-fade-in-up space-y-6">
|
|
||||||
<h2 className="text-2xl font-bold">Leadership & Activities</h2>
|
|
||||||
<div className="grid-equal-height grid gap-6 md:grid-cols-2">
|
|
||||||
{leadershipExperience.map((exp, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className={`animate-fade-in-up-delay-${index + 1}`}
|
|
||||||
>
|
|
||||||
<Card className="card-hover card-full-height">
|
|
||||||
<CardHeader>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Users className="h-5 w-5 flex-shrink-0" />
|
|
||||||
<div className="min-w-0">
|
|
||||||
<CardTitle className="mb-1 break-words text-base leading-tight">
|
|
||||||
{exp.title}
|
|
||||||
</CardTitle>
|
|
||||||
<CardDescription className="break-words text-xs">
|
|
||||||
{exp.organization}
|
|
||||||
</CardDescription>
|
|
||||||
<CardDescription className="text-xs">
|
|
||||||
{exp.period}
|
|
||||||
</CardDescription>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="card-content-stretch">
|
|
||||||
<ul className="space-y-1 text-sm text-muted-foreground">
|
|
||||||
{exp.description.slice(0, 2).map((item, itemIndex) => (
|
|
||||||
<li key={itemIndex} className="flex items-start gap-2">
|
|
||||||
<span className="mt-2 h-1 w-1 flex-shrink-0 rounded-full bg-muted-foreground" />
|
|
||||||
<span className="break-words">{item}</span>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Recent Awards & Recognition */}
|
|
||||||
<section className="animate-fade-in-up space-y-6">
|
|
||||||
<h2 className="text-2xl font-bold">Recent Awards & Recognition</h2>
|
|
||||||
<div className="grid-equal-height grid gap-4 md:grid-cols-2">
|
|
||||||
{awards.map((award, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className={`animate-fade-in-up-delay-${index + 1}`}
|
|
||||||
>
|
|
||||||
<Card className="card-hover card-full-height">
|
|
||||||
<CardHeader>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Award className="h-5 w-5 flex-shrink-0" />
|
|
||||||
<div className="min-w-0">
|
|
||||||
<CardTitle className="mb-1 break-words text-base leading-tight">
|
|
||||||
{award.title}
|
|
||||||
</CardTitle>
|
|
||||||
{award.organization && (
|
|
||||||
<CardDescription className="break-words">
|
|
||||||
{award.organization} • {award.year}
|
|
||||||
</CardDescription>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardHeader>
|
|
||||||
{award.description && (
|
|
||||||
<CardContent className="card-content-stretch">
|
|
||||||
<p className="break-words text-sm leading-relaxed text-muted-foreground">
|
|
||||||
{award.description}
|
|
||||||
</p>
|
|
||||||
</CardContent>
|
|
||||||
)}
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Quick Links */}
|
|
||||||
<section className="animate-fade-in-up space-y-6">
|
|
||||||
<h2 className="text-2xl font-bold">Explore More</h2>
|
|
||||||
<div className="grid-equal-height grid gap-6 md:grid-cols-3">
|
|
||||||
<div className="animate-fade-in-up-delay-1">
|
|
||||||
<Card className="card-hover card-full-height">
|
<Card className="card-hover card-full-height">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Code className="h-5 w-5 flex-shrink-0" />
|
<Code className="h-5 w-5 flex-shrink-0" />
|
||||||
<CardTitle className="mb-1 break-words">Projects</CardTitle>
|
<CardTitle>Projects</CardTitle>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="card-content-stretch">
|
<CardContent className="card-content-stretch">
|
||||||
<div className="flex h-full flex-col">
|
<div className="flex h-full flex-col gap-3">
|
||||||
<p className="break-words leading-relaxed text-muted-foreground">
|
<p className="text-sm leading-relaxed text-muted-foreground">
|
||||||
Explore my featured projects including HRIStudio, machine
|
HRIStudio, Riverhead Raceway, machine learning, embedded
|
||||||
learning research, and web applications.
|
systems, and more.
|
||||||
</p>
|
</p>
|
||||||
<Button variant="outline" asChild className="mt-auto w-full">
|
<Button variant="outline" asChild className="mt-auto w-full">
|
||||||
<Link href="/projects">
|
<Link href="/projects">
|
||||||
View Projects
|
View projects
|
||||||
<ArrowUpRight className="ml-2 h-4 w-4" />
|
<ArrowUpRight className="ml-2 h-4 w-4" />
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="animate-fade-in-up-delay-2">
|
|
||||||
<Card className="card-hover card-full-height">
|
<Card className="card-hover card-full-height">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<BookOpen className="h-5 w-5 flex-shrink-0" />
|
<BookOpen className="h-5 w-5 flex-shrink-0" />
|
||||||
<CardTitle className="mb-1 break-words">
|
<CardTitle>Publications</CardTitle>
|
||||||
Publications
|
|
||||||
</CardTitle>
|
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="card-content-stretch">
|
<CardContent className="card-content-stretch">
|
||||||
<div className="flex h-full flex-col">
|
<div className="flex h-full flex-col gap-3">
|
||||||
<p className="break-words leading-relaxed text-muted-foreground">
|
<p className="text-sm leading-relaxed text-muted-foreground">
|
||||||
Read my peer-reviewed publications in human-robot
|
Peer-reviewed work in human-robot interaction research.
|
||||||
interaction research.
|
|
||||||
</p>
|
</p>
|
||||||
<Button variant="outline" asChild className="mt-auto w-full">
|
<Button variant="outline" asChild className="mt-auto w-full">
|
||||||
<Link href="/publications">
|
<Link href="/publications">
|
||||||
View Publications
|
View publications
|
||||||
<ArrowUpRight className="ml-2 h-4 w-4" />
|
<ArrowUpRight className="ml-2 h-4 w-4" />
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="animate-fade-in-up-delay-3">
|
|
||||||
<Card className="card-hover card-full-height">
|
<Card className="card-hover card-full-height">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<ExternalLink className="h-5 w-5 flex-shrink-0" />
|
<ExternalLink className="h-5 w-5 flex-shrink-0" />
|
||||||
<CardTitle className="mb-1 break-words">
|
<CardTitle>CV</CardTitle>
|
||||||
Complete CV
|
|
||||||
</CardTitle>
|
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="card-content-stretch">
|
<CardContent className="card-content-stretch">
|
||||||
<div className="flex h-full flex-col">
|
<div className="flex h-full flex-col gap-3">
|
||||||
<p className="break-words leading-relaxed text-muted-foreground">
|
<p className="text-sm leading-relaxed text-muted-foreground">
|
||||||
View my complete academic and professional curriculum vitae.
|
Complete academic and professional curriculum vitae.
|
||||||
</p>
|
</p>
|
||||||
<Button variant="outline" asChild className="mt-auto w-full">
|
<Button variant="outline" asChild className="mt-auto w-full">
|
||||||
<Link href="/cv">
|
<Link href="/cv">
|
||||||
@@ -419,9 +428,10 @@ export default function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user