Skip to content

Commit 09daec0

Browse files
committed
feat(pages, resources): enhance resource detail page with improved layout and error handling, add new category resources page
1 parent e275a31 commit 09daec0

File tree

4 files changed

+63
-13
lines changed

4 files changed

+63
-13
lines changed
Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { notFound } from "next/navigation";
12
import { getResourceBySlug } from "@/actions/resources";
23

34
type Props = {
@@ -7,14 +8,39 @@ type Props = {
78
export default async function ResourceDetailPage({ params }: Props) {
89
const { slug } = await params;
910
const resource = await getResourceBySlug(slug);
11+
if (!resource) return notFound();
12+
1013
return (
11-
<main className="max-w-screen-xl mx-auto p-4">
12-
<h1>{resource.title}</h1>
13-
<p>{resource.description}</p>
14-
<p>{resource.tags.join(", ")}</p>
15-
<p>{resource.author.name}</p>
16-
<p>{resource.created_at}</p>
17-
<img src={resource.image} alt={resource.title} />
14+
<main className="max-w-4xl mx-auto px-4 py-8">
15+
<article className="space-y-6">
16+
<header className="space-y-4">
17+
<h1 className="text-3xl font-bold text-white">{resource.name}</h1>
18+
<p className="text-gray-600 text-lg">
19+
{resource.description || "No description available."}
20+
</p>
21+
<div className="flex flex-wrap gap-2">
22+
{resource.tags?.map((tag, idx) => (
23+
<span
24+
key={idx}
25+
className="bg-blue-100 text-blue-800 text-sm font-medium px-2.5 py-0.5 rounded"
26+
>
27+
{tag}
28+
</span>
29+
))}
30+
</div>
31+
<div className="text-sm text-gray-500">
32+
<span>{new Date(resource.created_at).toLocaleDateString()}</span>
33+
</div>
34+
</header>
35+
36+
{resource.image && (
37+
<img
38+
src={resource.image}
39+
alt={resource.name}
40+
className="w-full h-auto rounded-xl shadow-md"
41+
/>
42+
)}
43+
</article>
1844
</main>
1945
);
2046
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Heading } from "@/components/ui";
2+
3+
type Props = {
4+
params: { category: string };
5+
};
6+
7+
export default async function ResourcesByCategoryPage({ params }: Props) {
8+
const { category } = await params;
9+
10+
return (
11+
<main className="max-w-screen-xl mx-auto p-4">
12+
<Heading
13+
title={category}
14+
subtitle="Explore all the resources by category"
15+
/>
16+
{JSON.stringify(category)}
17+
</main>
18+
);
19+
}

src/app/(public)/resources/page.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,21 @@ import type { Metadata } from "next";
22

33
import { getResources } from "@/actions/resources";
44
import { ResourceList } from "@/components/resources";
5+
import { Heading } from "@/components/ui";
56
import { PROJECT_NAME } from "@/config/constants";
67

78
export const metadata: Metadata = {
89
title: `Resources - ${PROJECT_NAME}`,
9-
description: "Resources page",
10+
description: "Explore all the resources",
1011
};
1112

1213
export default async function ResourcesPage() {
1314
const resources = await getResources();
15+
if (resources.length === 0) return <div>No resources found</div>;
1416

1517
return (
1618
<main className="max-w-screen-xl mx-auto p-4">
17-
<h1>Resources</h1>
19+
<Heading title="Resources" subtitle="Explore all the resources" />
1820
<ResourceList resources={resources} />
1921
</main>
2022
);

src/app/layout.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ import type { Metadata, Viewport } from "next";
33
import { Outfit, Roboto_Mono } from "next/font/google";
44
import { Navbar, Sidebar } from "@/components/layout";
55
import { BackToTop } from "@/components/ui";
6-
import { ResourceFilters } from "@/components/resources";
6+
// import { ResourceFilters } from "@/components/resources";
77
import { PROJECT_NAME, PROJECT_DESCRIPTION } from "@/config/constants";
88
import Providers from "./providers";
99

1010
import "../styles/globals.css";
11+
import { getCategories } from "@/actions/categories";
1112

1213
const outfit = Outfit({
1314
variable: "--font-outfit",
@@ -37,16 +38,18 @@ type Props = {
3738
children: Readonly<React.ReactNode>;
3839
};
3940

40-
export default function RootLayout({ children }: Props) {
41+
export default async function RootLayout({ children }: Props) {
42+
const categories = await getCategories();
43+
4144
return (
4245
<html lang="en" suppressHydrationWarning>
4346
<body className={`${outfit.variable} ${robotoMono.variable} antialiased`}>
4447
<Providers>
4548
<div className="relative mx-auto max-w-screen-2xl md:flex md:flex-row bg-white dark:bg-neutral-950">
46-
<Sidebar />
49+
<Sidebar categories={categories} />
4750
<div className="w-full">
4851
<Navbar />
49-
<ResourceFilters />
52+
{/* <ResourceFilters /> */}
5053
{children}
5154
</div>
5255
<BackToTop />

0 commit comments

Comments
 (0)