wilddragon-site/src.bright-backup/app/projects/[slug]/page.tsx
2026-04-17 15:51:01 -04:00

298 lines
11 KiB
TypeScript
Executable file

import { notFound } from "next/navigation";
import Link from "next/link";
import Image from "next/image";
import { ArrowLeft, ArrowRight, ExternalLink } from "lucide-react";
import { projects, getProjectBySlug } from "@/data/projects";
export function generateStaticParams() {
return projects.map((project) => ({
slug: project.slug,
}));
}
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const project = getProjectBySlug(slug);
if (!project) return { title: "Project Not Found" };
return {
title: `${project.client} | Zachary Gaetano`,
description: project.summary,
openGraph: {
title: `${project.client} | Zachary Gaetano`,
description: project.summary,
images: [{ url: project.thumbnail }],
},
};
}
export default async function ProjectPage({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const project = getProjectBySlug(slug);
if (!project) {
notFound();
}
// Find previous and next projects for navigation
const currentIndex = projects.findIndex((p) => p.slug === project.slug);
const prevProject = currentIndex > 0 ? projects[currentIndex - 1] : null;
const nextProject =
currentIndex < projects.length - 1 ? projects[currentIndex + 1] : null;
return (
<main className="min-h-screen bg-white">
{/* Header bar */}
<nav className="fixed top-0 left-0 right-0 z-50 bg-white/95 backdrop-blur-lg shadow-sm py-3.5">
<div className="max-w-6xl mx-auto px-6 flex items-center justify-between">
<Link
href="/#projects"
className="flex items-center gap-2 text-[13px] text-muted hover:text-primary transition-colors duration-200 group"
>
<ArrowLeft size={15} className="group-hover:-translate-x-0.5 transition-transform duration-200" />
Back to Projects
</Link>
<Link
href="/"
className="font-mono text-[10px] tracking-[0.2em] uppercase text-muted hover:text-primary transition-colors duration-200"
>
Wild Dragon
</Link>
</div>
</nav>
{/* Hero area */}
<section className="pt-32 pb-16 bg-primary">
<div className="max-w-6xl mx-auto px-6">
<div className="flex items-center gap-3 mb-5">
<span className="px-3 py-1.5 text-[10px] font-mono tracking-wider uppercase bg-accent/10 text-accent rounded-md">
{project.category}
</span>
<span className="font-mono text-[11px] text-neutral-500">
{project.year}
</span>
</div>
<h1 className="text-4xl md:text-5xl lg:text-6xl font-semibold text-white leading-tight mb-6">
{project.client}
</h1>
<p className="text-lg md:text-xl text-neutral-400 max-w-3xl leading-relaxed">
{project.summary}
</p>
</div>
</section>
{/* Project image */}
<section className="bg-neutral-100">
<div className="max-w-6xl mx-auto">
<div className="relative h-64 md:h-[28rem] overflow-hidden">
<Image
src={project.thumbnail}
alt={project.title}
fill
className="object-cover"
sizes="100vw"
priority
/>
<div className="absolute inset-0 bg-gradient-to-t from-white/10 to-transparent" />
</div>
</div>
</section>
{/* Content */}
<section className="py-20 md:py-28">
<div className="max-w-6xl mx-auto px-6">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-16">
{/* Main content */}
<div className="lg:col-span-2">
<h2 className="text-2xl font-semibold text-primary mb-8">
Overview
</h2>
<div className="space-y-5 text-muted leading-[1.8]">
{project.description.map((paragraph: string, i: number) => (
<p key={i}>{paragraph}</p>
))}
</div>
{/* Highlights */}
<h3 className="text-lg font-semibold text-primary mt-14 mb-6">
Key Highlights
</h3>
<ul className="space-y-4">
{project.highlights.map((highlight: string, i: number) => (
<li key={i} className="flex items-start gap-3">
<span className="w-1.5 h-1.5 rounded-full bg-accent mt-2.5 shrink-0" />
<span className="text-muted leading-relaxed">
{highlight}
</span>
</li>
))}
</ul>
{/* CTA */}
<div className="mt-16 p-8 rounded-xl bg-surface-dark border border-neutral-100">
<h4 className="text-base font-semibold text-primary mb-3">
Interested in a similar project?
</h4>
<p className="text-sm text-muted mb-5 leading-relaxed">
I bring the same engineering discipline and attention to detail to
every facility I design. Let&apos;s discuss how I can help with your project.
</p>
<a
href="mailto:zgaetano@wilddragon.net"
className="inline-flex items-center gap-2 px-6 py-2.5 bg-accent text-white text-sm font-medium rounded-md hover:bg-accent-light transition-all duration-200"
>
Get in Touch
<ExternalLink size={13} />
</a>
</div>
</div>
{/* Sidebar */}
<div className="space-y-10">
<div>
<h4 className="font-mono text-[10px] tracking-[0.2em] uppercase text-muted mb-3">
Client
</h4>
<p className="text-primary font-medium">{project.client}</p>
</div>
<div>
<h4 className="font-mono text-[10px] tracking-[0.2em] uppercase text-muted mb-3">
Year
</h4>
<p className="text-primary font-medium">{project.year}</p>
</div>
<div>
<h4 className="font-mono text-[10px] tracking-[0.2em] uppercase text-muted mb-3">
Scope of Work
</h4>
<div className="flex flex-wrap gap-2">
{project.scope.map((item: string) => (
<span
key={item}
className="px-3 py-1.5 text-xs font-medium bg-neutral-50 border border-neutral-100 text-muted rounded-md"
>
{item}
</span>
))}
</div>
</div>
<div>
<h4 className="font-mono text-[10px] tracking-[0.2em] uppercase text-muted mb-3">
Technologies
</h4>
<div className="flex flex-wrap gap-2">
{project.technologies.map((tech: string) => (
<span
key={tech}
className="px-3 py-1.5 text-xs font-medium bg-accent/5 text-accent rounded-md"
>
{tech}
</span>
))}
</div>
</div>
{/* Quick nav to other projects */}
<div className="pt-6 border-t border-neutral-100">
<h4 className="font-mono text-[10px] tracking-[0.2em] uppercase text-muted mb-4">
Other Projects
</h4>
<div className="space-y-2">
{projects
.filter((p) => p.slug !== project.slug)
.slice(0, 4)
.map((p) => (
<Link
key={p.slug}
href={`/projects/${p.slug}`}
className="block text-[13px] text-muted hover:text-accent transition-colors duration-200 py-1"
>
{p.client}
</Link>
))}
</div>
</div>
</div>
</div>
</div>
</section>
{/* Prev / Next navigation */}
<section className="border-t border-neutral-200">
<div className="max-w-6xl mx-auto px-6">
<div className="grid grid-cols-1 md:grid-cols-2 divide-y md:divide-y-0 md:divide-x divide-neutral-200">
{prevProject ? (
<Link
href={`/projects/${prevProject.slug}`}
className="group flex items-center gap-4 py-10 pr-8 hover:bg-neutral-50 transition-colors duration-200"
>
<ArrowLeft
size={18}
className="text-neutral-300 group-hover:text-accent group-hover:-translate-x-1 transition-all duration-200 shrink-0"
/>
<div>
<p className="font-mono text-[10px] tracking-wider uppercase text-muted mb-1">
Previous
</p>
<p className="text-sm font-medium text-primary group-hover:text-accent transition-colors duration-200">
{prevProject.client}
</p>
</div>
</Link>
) : (
<div className="py-10" />
)}
{nextProject ? (
<Link
href={`/projects/${nextProject.slug}`}
className="group flex items-center justify-end gap-4 py-10 pl-8 hover:bg-neutral-50 transition-colors duration-200"
>
<div className="text-right">
<p className="font-mono text-[10px] tracking-wider uppercase text-muted mb-1">
Next
</p>
<p className="text-sm font-medium text-primary group-hover:text-accent transition-colors duration-200">
{nextProject.client}
</p>
</div>
<ArrowRight
size={18}
className="text-neutral-300 group-hover:text-accent group-hover:translate-x-1 transition-all duration-200 shrink-0"
/>
</Link>
) : (
<div className="py-10" />
)}
</div>
</div>
</section>
{/* Footer */}
<footer className="py-10 bg-primary">
<div className="max-w-6xl mx-auto px-6 flex flex-col md:flex-row items-center justify-between gap-4">
<Link
href="/"
className="font-mono text-[10px] tracking-[0.2em] uppercase text-neutral-600 hover:text-neutral-400 transition-colors duration-200"
>
Wild Dragon
</Link>
<p className="text-[11px] text-neutral-700">
&copy; {new Date().getFullYear()} Zachary Gaetano
</p>
</div>
</footer>
</main>
);
}