Files
local/frontend/components/projects.tsx
2025-12-01 02:29:08 +01:00

129 lines
5.4 KiB
TypeScript

"use client"
import { ExternalLink, Github, Star } from "lucide-react"
import Link from "next/link"
import { useDataStore } from "@/lib/data-store"
export function Projects() {
const { projects } = useDataStore()
const featuredProject = projects.find((p) => p.featured)
const otherProjects = projects.filter((p) => !p.featured)
return (
<section id="projects" className="py-24 border-t border-border">
<div className="max-w-4xl mx-auto px-6">
<div className="grid md:grid-cols-[200px_1fr] gap-8 md:gap-12">
{/* Section label */}
<div>
<h2 className="font-mono text-sm text-muted-foreground uppercase tracking-wider">Projects</h2>
<div className="mt-2 w-12 h-px bg-primary" />
</div>
{/* Content */}
<div className="space-y-12">
{/* Featured project */}
{featuredProject && (
<div className="space-y-6">
<div className="flex items-center gap-2">
<Star size={14} className="text-primary" />
<span className="font-mono text-xs text-primary uppercase tracking-wider">Featured</span>
</div>
<div className="bg-card border border-border rounded-lg p-6 space-y-4">
<div className="flex flex-wrap items-start justify-between gap-4">
<div>
<h3 className="text-xl font-semibold text-foreground">{featuredProject.name}</h3>
<p className="text-sm text-muted-foreground">{featuredProject.role}</p>
</div>
{featuredProject.websiteUrl && (
<Link
href={featuredProject.websiteUrl}
target="_blank"
className="inline-flex items-center gap-1.5 text-sm text-primary hover:underline"
>
Visit site
<ExternalLink size={14} />
</Link>
)}
</div>
<p className="text-muted-foreground">{featuredProject.description}</p>
{featuredProject.highlights && featuredProject.highlights.length > 0 && (
<div className="space-y-2">
<h4 className="font-mono text-xs text-muted-foreground uppercase tracking-wider">
Key contributions
</h4>
<ul className="space-y-1.5">
{featuredProject.highlights.map((highlight, i) => (
<li key={i} className="text-sm text-muted-foreground flex items-start gap-2">
<span className="text-primary mt-1.5"></span>
{highlight}
</li>
))}
</ul>
</div>
)}
<div className="flex flex-wrap gap-2 pt-2">
{featuredProject.stack.map((tech) => (
<span
key={tech}
className="px-2 py-1 text-xs font-mono bg-secondary text-secondary-foreground rounded"
>
{tech}
</span>
))}
</div>
</div>
</div>
)}
{/* Other projects */}
{otherProjects.length > 0 && (
<div className="space-y-6">
<h3 className="font-mono text-xs text-muted-foreground uppercase tracking-wider">Other projects</h3>
<div className="grid gap-4">
{otherProjects.map((project) => (
<div
key={project.id}
className="group p-4 bg-card border border-border rounded-lg hover:border-primary/50 transition-colors"
>
<div className="flex items-start justify-between gap-4">
<div className="space-y-2">
<h4 className="font-mono text-foreground group-hover:text-primary transition-colors">
{project.name}
</h4>
<p className="text-sm text-muted-foreground">{project.description}</p>
<div className="flex flex-wrap gap-2">
{project.stack.map((tech) => (
<span key={tech} className="text-xs font-mono text-muted-foreground">
{tech}
</span>
))}
</div>
</div>
{project.githubUrl && (
<Link
href={project.githubUrl}
className="text-muted-foreground hover:text-foreground transition-colors"
aria-label={`View ${project.name} on GitHub`}
>
<Github size={18} />
</Link>
)}
</div>
</div>
))}
</div>
</div>
)}
</div>
</div>
</div>
</section>
)
}