Skip to content

Commit

Permalink
Project Details page
Browse files Browse the repository at this point in the history
  • Loading branch information
gilhanan committed Nov 2, 2023
1 parent d37651b commit 63fc88d
Show file tree
Hide file tree
Showing 12 changed files with 217 additions and 18 deletions.
1 change: 1 addition & 0 deletions public/images/chrome-web-store.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/images/github-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/images/github.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions src/app/components/ButtonLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import Link from "next/link";
import { ThemedImage } from "@components/ThemedImage";

interface ProjectDetailsProps {
url: string;
text: string;
lightSrc: string;
darkSrc: string;
}

export function ButtonLink({
url,
text,
lightSrc,
darkSrc,
}: ProjectDetailsProps): ReturnType<React.FC> {
return (
<Link
href={url}
target="_blank"
className="flex gap-2 text-sm items-center p-1 border rounded-md shadow-sm hover:bg-slate-100 dark:hover:bg-slate-800"
>
<ThemedImage
lightSrc={lightSrc}
darkSrc={darkSrc}
width={30}
alt={text}
/>
<span className="text-primary">{text}</span>
</Link>
);
}
69 changes: 69 additions & 0 deletions src/app/components/ProjectDetails.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { FiTag } from "react-icons/fi";
import chromeWebStore from "@images/chrome-web-store.svg";
import githubLight from "@images/github.svg";
import githubDark from "@images/github-dark.svg";
import { Project } from "@shared/models";
import { ThemedImage } from "@components/ThemedImage";
import { ButtonLink } from "@components/ButtonLink";

interface ProjectDetailsProps {
project: Project;
}

export function ProjectDetails({
project: {
title,
category,
url,
repo,
description,
images: { light, dark },
},
}: ProjectDetailsProps): ReturnType<React.FC> {
return (
<section className="mt-12 sm:mt-6">
<div className="flex sm:flex-row flex-col gap-8">
<div className="w-full sm:w-80 flex flex-col gap-8">
<ThemedImage
lightSrc={light}
darkSrc={dark}
className="border"
alt="Project tile image"
sizes="100vw"
style={{
width: "100%",
height: "auto",
}}
/>
<div>
<h2 className="text-primary">Links</h2>
<div className="flex flex-col gap-2">
<ButtonLink
url={url}
text="Get extension"
lightSrc={chromeWebStore}
darkSrc={chromeWebStore}
/>
<ButtonLink
url={repo}
text="Source code"
lightSrc={githubLight}
darkSrc={githubDark}
/>
</div>
</div>
</div>
<div>
<div className="flex flex-col gap-1">
<h1 className="text-3xl text-primary">{title}</h1>
<div className="flex gap-2 items-center text-secondary">
<FiTag className="w-4 h-4" />
<span className="text-sm">{category}</span>
</div>
</div>
<div className="mt-4 text-secondary">{description}</div>
</div>
</div>
</section>
);
}
2 changes: 2 additions & 0 deletions src/app/components/ProjectTile.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Project } from "@shared/models";
import { ProjectTile } from "@components/ProjectTile";

const project: Project = {
id: "1",
title: "Test Project",
url: "https://testproject.com",
category: "Chrome Extension",
Expand All @@ -11,6 +12,7 @@ const project: Project = {
light: "/test/light.jpg",
dark: "/test/dark.jpg",
},
description: <>Test project description</>,
};

describe("ProjectTile", () => {
Expand Down
4 changes: 2 additions & 2 deletions src/app/components/ProjectTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { Project } from "@shared/models";
import { ThemedImage } from "@components/ThemedImage";

export function ProjectTile({
id,
title,
url,
category,
repo,
images: { light, dark },
Expand All @@ -20,7 +20,7 @@ export function ProjectTile({
>
<FiCode />
</Link>
<Link href={url} target="_blank" aria-label={`View ${title} ${category}`}>
<Link href={`/projects/${id}`} aria-label={`View ${title} ${category}`}>
<div className="flex flex-col relative divide-y border rounded-xl shadow-md hover:shadow-xl">
<ThemedImage
lightSrc={light}
Expand Down
6 changes: 6 additions & 0 deletions src/app/components/Projects.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Projects } from "@components/Projects";
jest.mock("../data/projects", () => ({
projects: [
{
id: "1",
title: "First project",
category: "Chrome Extension",
url: "https://www.example.com",
Expand All @@ -14,8 +15,10 @@ jest.mock("../data/projects", () => ({
light: "/images/first-project-light.png",
dark: "/images/first-project-dark.png",
},
description: <>First project description</>,
},
{
id: "2",
title: "Second project",
category: "Chrome Extension",
url: "https://www.example.com",
Expand All @@ -24,8 +27,10 @@ jest.mock("../data/projects", () => ({
light: "/images/second-project-light.png",
dark: "/images/second-project-dark.png",
},
description: <>Second project description</>,
},
{
id: "3",
title: "Third project",
category: "Web Development" as Category,
url: "https://www.example.com",
Expand All @@ -34,6 +39,7 @@ jest.mock("../data/projects", () => ({
light: "/images/third-project-light.png",
dark: "/images/third-project-dark.png",
},
description: <>Third project description</>,
},
] satisfies Project[],
}));
Expand Down
16 changes: 0 additions & 16 deletions src/app/data/projects.ts

This file was deleted.

75 changes: 75 additions & 0 deletions src/app/data/projects.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Project } from "@shared/models";
import light from "@images/projects/chat-gpt-rtl.svg";
import dark from "@images/projects/chat-gpt-rtl-dark.svg";

export const projects: Project[] = [
{
id: "chat-gpt-rtl",
title: "ChatGPT RTL",
url: "https://chrome.google.com/webstore/detail/chatgpt-rtl/nabcbpmmefiigmjpopfciegmlgihkofd ",
category: "Chrome Extension",
repo: "https://github.com/gilhanan/chat-gpt-rtl",
images: {
light,
dark,
},
description: (
<div className="flex flex-col gap-4">
<div>
<p>
ChatGPT auto right-to-left alignments for Arabic, Persian, Hebrew,
and more.
</p>
<p>
An open-source plugin that automatically identifies right-to-left
paragraphs and adjusts and arranges the text in real-time.
</p>
</div>
<div>
<h2 className="text-lg text-primary">⭐️ Features ⭐️</h2>
<ul>
<li className="flex gap-1">
<span>📝</span>
<span>
Automatically identifies RTL paragraphs and adjusts the
direction in real-time.
</span>
</li>
<li className="flex gap-1">
<span>⚙️</span>
<span>
User-friendly settings popup for configuring the enabling
functionality.
</span>
</li>
<li className="flex gap-1">
<span>🌍</span>
<span>
Supports the following RTL languages: Arabic, Persian, Hebrew,
and more.
</span>
</li>
</ul>
</div>
<div>
<h2 className="text-lg text-primary">💡 How to use 💡</h2>
<ol>
<li className="flex gap-1">
<span>1️⃣</span>
<span>Install this extension.</span>
</li>
<li className="flex gap-1">
<span>2️⃣</span>
<span>Open ChatGPT discussion.</span>
</li>
<li className="flex gap-1">
<span>3️⃣</span>
<span>Enjoy chatting with RTL support!</span>
</li>
</ol>
</div>
<p>Enjoy! 🙏</p>
</div>
),
},
];
26 changes: 26 additions & 0 deletions src/app/projects/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { projects } from "@data/projects";
import { ProjectDetails } from "@components/ProjectDetails";

export const metadata: Metadata = {
title: "Project",
};

export default function ProjectPage({
params: { id },
}: {
params: { id: string };
}) {
const project = projects.find((project) => project.id === id);

if (!project) {
return notFound();
}

return <ProjectDetails project={project} />;
}

export function generateStaticParams() {
return projects.map(({ id }) => ({ id }));
}
2 changes: 2 additions & 0 deletions src/app/shared/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ export const categories = ["Chrome Extension"] as const;
export type Category = (typeof categories)[number];

export interface Project {
id: string;
title: string;
description: JSX.Element;
url: string;
category: Category;
repo: string;
Expand Down

0 comments on commit 63fc88d

Please sign in to comment.