Refactor project slug handling and improve project retrieval logic
All checks were successful
Build and Deploy Gabriel Kaszewski Portfolio / build-and-deploy-local (push) Successful in 1m46s
All checks were successful
Build and Deploy Gabriel Kaszewski Portfolio / build-and-deploy-local (push) Successful in 1m46s
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import { projects } from "@/lib/data";
|
import { getProjectBySlug, projects, projectSlug } from "@/lib/data";
|
||||||
import { Project } from "@/lib/types";
|
|
||||||
import Chip from "@/components/chip";
|
import Chip from "@/components/chip";
|
||||||
import MarkdownContent from "@/components/markdown-content";
|
import MarkdownContent from "@/components/markdown-content";
|
||||||
import { Metadata } from "next";
|
import { Metadata } from "next";
|
||||||
@@ -7,16 +6,9 @@ import Image from "next/image";
|
|||||||
import { Github, Eye, CloudDownload } from "lucide-react";
|
import { Github, Eye, CloudDownload } from "lucide-react";
|
||||||
import { notFound } from "next/navigation";
|
import { notFound } from "next/navigation";
|
||||||
|
|
||||||
function getProjectByName(name: string): Project | undefined {
|
|
||||||
const decodedName = decodeURIComponent(name.replace(/\+/g, " "));
|
|
||||||
return projects.find(
|
|
||||||
(p) => p.name.toLowerCase() === decodedName.toLowerCase()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function generateStaticParams() {
|
export async function generateStaticParams() {
|
||||||
return projects.map((project) => ({
|
return projects.map((project) => ({
|
||||||
projectName: encodeURIComponent(project.name.replace(/\s/g, "+")),
|
projectName: projectSlug(project),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,13 +18,13 @@ export async function generateMetadata({
|
|||||||
params: Promise<{ projectName: string }>;
|
params: Promise<{ projectName: string }>;
|
||||||
}): Promise<Metadata> {
|
}): Promise<Metadata> {
|
||||||
const { projectName } = await params;
|
const { projectName } = await params;
|
||||||
const project = getProjectByName(projectName);
|
const project = getProjectBySlug(projectName);
|
||||||
|
|
||||||
if (!project) {
|
if (!project) {
|
||||||
return { title: "Project Not Found" };
|
return { title: "Project Not Found" };
|
||||||
}
|
}
|
||||||
|
|
||||||
const slug = encodeURIComponent(project.name.replace(/\s/g, "+"));
|
const slug = projectSlug(project);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: `${project.name} | Gabriel Kaszewski`,
|
title: `${project.name} | Gabriel Kaszewski`,
|
||||||
@@ -70,7 +62,7 @@ export default async function ProjectDetailPage({
|
|||||||
params: Promise<{ projectName: string }>;
|
params: Promise<{ projectName: string }>;
|
||||||
}) {
|
}) {
|
||||||
const { projectName } = await params;
|
const { projectName } = await params;
|
||||||
const project = getProjectByName(projectName);
|
const project = getProjectBySlug(projectName);
|
||||||
|
|
||||||
if (!project) {
|
if (!project) {
|
||||||
notFound();
|
notFound();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import Link from "next/link";
|
|||||||
import { Project } from "@/lib/types";
|
import { Project } from "@/lib/types";
|
||||||
import Chip from "@/components/chip";
|
import Chip from "@/components/chip";
|
||||||
import { Eye } from "lucide-react";
|
import { Eye } from "lucide-react";
|
||||||
|
import { projectSlug } from "@/lib/data";
|
||||||
|
|
||||||
const CommercialProjectCard = ({ project }: { project: Project }) => {
|
const CommercialProjectCard = ({ project }: { project: Project }) => {
|
||||||
return (
|
return (
|
||||||
@@ -34,7 +35,7 @@ const CommercialProjectCard = ({ project }: { project: Project }) => {
|
|||||||
|
|
||||||
<div className="flex gap-3 mt-auto">
|
<div className="flex gap-3 mt-auto">
|
||||||
<Link
|
<Link
|
||||||
href={`/projects/${project.name}`}
|
href={`/projects/${projectSlug(project)}`}
|
||||||
className="flex-1 px-4 py-3 text-center font-bold text-black bg-yellow-400 rounded-xl hover:bg-yellow-500 transition-colors glass-effect glossy-effect bottom gloss-highlight"
|
className="flex-1 px-4 py-3 text-center font-bold text-black bg-yellow-400 rounded-xl hover:bg-yellow-500 transition-colors glass-effect glossy-effect bottom gloss-highlight"
|
||||||
>
|
>
|
||||||
Read more
|
Read more
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { projectSlug } from "@/lib/data";
|
||||||
import { Project } from "@/lib/types";
|
import { Project } from "@/lib/types";
|
||||||
import Chip from "@/components/chip";
|
import Chip from "@/components/chip";
|
||||||
import ImageCarousel from "@/components/image-carousel";
|
import ImageCarousel from "@/components/image-carousel";
|
||||||
@@ -64,7 +65,7 @@ const ProjectItem = ({ project }: ProjectItemProps) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
href={`/projects/${project.name}`}
|
href={`/projects/${projectSlug(project)}`}
|
||||||
className="text-center glass-effect glossy-effect bottom gloss-highlight p-2 rounded-2xl bg-yellow-400 hover:bg-yellow-500 text-black font-bold"
|
className="text-center glass-effect glossy-effect bottom gloss-highlight p-2 rounded-2xl bg-yellow-400 hover:bg-yellow-500 text-black font-bold"
|
||||||
>
|
>
|
||||||
Read more
|
Read more
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Skill, Job, Project, FunZoneItem, Writing, Photo } from "@/lib/types";
|
import { Skill, Job, Project, FunZoneItem, Writing, Photo } from "@/lib/types";
|
||||||
|
import { slugify } from "@/lib/slug";
|
||||||
|
|
||||||
export const skills: Skill[] = [
|
export const skills: Skill[] = [
|
||||||
{ name: "Angular" },
|
{ name: "Angular" },
|
||||||
@@ -628,3 +629,8 @@ export const photos: Photo[] = [
|
|||||||
height: 2000,
|
height: 2000,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const projectSlug = (project: Project): string => slugify(project.name);
|
||||||
|
|
||||||
|
export const getProjectBySlug = (slug: string): Project | undefined =>
|
||||||
|
projects.find((project) => projectSlug(project) === slug);
|
||||||
|
|||||||
10
lib/slug.ts
Normal file
10
lib/slug.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export function slugify(value: string): string {
|
||||||
|
return value
|
||||||
|
.normalize("NFD")
|
||||||
|
.replace(/\p{Diacritic}/gu, "")
|
||||||
|
.replace(/ł/g, "l")
|
||||||
|
.replace(/Ł/g, "L")
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^a-z0-9]+/g, "-")
|
||||||
|
.replace(/^-+|-+$/g, "");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user