mirror of
https://github.com/hex248/ob248.com.git
synced 2026-02-07 18:23:04 +00:00
103 lines
2.6 KiB
TypeScript
103 lines
2.6 KiB
TypeScript
import { ProjectListItem } from "@/components/ProjectListItem";
|
|
import { type ProjectEntry, projectList, projects } from "@/projects";
|
|
import { Link, Route, Routes, useParams } from "react-router-dom";
|
|
import { ThemeToggle } from "./components/theme-toggle";
|
|
|
|
function App() {
|
|
return (
|
|
<Routes>
|
|
<Route path="/" element={<Home />} />
|
|
<Route path="/projects/:slug" element={<ProjectRoute />} />
|
|
<Route path="*" element={<NotFound />} />
|
|
</Routes>
|
|
);
|
|
}
|
|
|
|
export default App;
|
|
|
|
function Home() {
|
|
const isDevMode = import.meta.env.VITE_PUBLIC_DEV === "1";
|
|
const sortedProjects: ProjectEntry[] = [...projectList].sort(
|
|
(a, b) =>
|
|
parseDate(b.metadata.date).getTime() -
|
|
parseDate(a.metadata.date).getTime(),
|
|
);
|
|
|
|
return (
|
|
<div className="min-h-dvh flex flex-col items-center justify-center gap-8 text-2xl px-6 py-10">
|
|
<div className="flex flex-col items-center gap-4">
|
|
<h1 className="picnic text-7xl text-balance">Oliver Bryan</h1>
|
|
</div>
|
|
<div className="w-full max-w-5xl grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
{sortedProjects.map((project) => (
|
|
<ProjectListItem
|
|
key={project.metadata.slug}
|
|
metadata={project.metadata}
|
|
isDevMode={isDevMode}
|
|
/>
|
|
))}
|
|
</div>
|
|
<ThemeToggle />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function ProjectRoute() {
|
|
const { slug } = useParams();
|
|
if (!slug || !projects[slug]) return <NotFound />;
|
|
|
|
const { Component } = projects[slug];
|
|
return <Component />;
|
|
}
|
|
|
|
function NotFound() {
|
|
return (
|
|
<div className="min-h-dvh flex flex-col items-center justify-center gap-4 text-2xl">
|
|
<h1 className="text-4xl text-accent text-balance">Not found</h1>
|
|
<Link className="text-accent underline" to="/">
|
|
Go home
|
|
</Link>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function parseDate(dateStr: string): Date {
|
|
const lower = dateStr.toLowerCase();
|
|
|
|
if (lower.includes("q1")) return new Date("2023-01-01");
|
|
if (lower.includes("q2")) return new Date("2023-04-01");
|
|
if (lower.includes("q3")) return new Date("2023-07-01");
|
|
if (lower.includes("q4")) return new Date("2023-10-01");
|
|
|
|
const months: Record<string, number> = {
|
|
january: 0,
|
|
february: 1,
|
|
march: 2,
|
|
april: 3,
|
|
may: 4,
|
|
june: 5,
|
|
july: 6,
|
|
august: 7,
|
|
september: 8,
|
|
october: 9,
|
|
november: 10,
|
|
december: 11,
|
|
};
|
|
|
|
for (const [monthName, monthIndex] of Object.entries(months)) {
|
|
if (lower.includes(monthName)) {
|
|
const yearMatch = dateStr.match(/\b(20\d{2})\b/);
|
|
if (yearMatch) {
|
|
return new Date(Number.parseInt(yearMatch[1], 10), monthIndex, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
const yearMatch = dateStr.match(/\b(20\d{2})\b/);
|
|
if (yearMatch) {
|
|
return new Date(Number.parseInt(yearMatch[1], 10), 0, 1);
|
|
}
|
|
|
|
return new Date(0);
|
|
}
|