Skip to content

Commit 4cdbadc

Browse files
committed
Use server components
1 parent 66faeb3 commit 4cdbadc

File tree

4 files changed

+221
-278
lines changed

4 files changed

+221
-278
lines changed

apps/dashboard/src/pages/project-showcase/[slug].tsx renamed to apps/dashboard/src/app/(dashboard)/project-showcase/[slug]/page.tsx

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,20 @@
1-
import { Badge } from "@/components/ui/badge";
2-
import { Button } from "@/components/ui/button";
1+
import { ExternalLink, FileText } from "lucide-react";
2+
import Link from "next/link";
3+
import { Badge } from "../../../../@/components/ui/badge";
4+
import { Button } from "../../../../@/components/ui/button";
35
import {
46
Card,
57
CardContent,
68
CardFooter,
79
CardHeader,
810
CardTitle,
9-
} from "@/components/ui/card";
10-
import { useThirdwebClient } from "@/constants/thirdweb.client";
11-
import { resolveSchemeWithErrorHandler } from "@/lib/resolveSchemeWithErrorHandler";
12-
import { ExternalLink, FileText } from "lucide-react";
13-
import Image from "next/image";
14-
import Link from "next/link";
15-
import { useRouter } from "next/router";
16-
import { ThirdwebProvider } from "thirdweb/react";
17-
import { PROJECT_SHOWCASE_DATA } from "../../lib/project-showcase-constants";
11+
} from "../../../../@/components/ui/card";
12+
import { PROJECT_SHOWCASE_DATA } from "../../../../lib/project-showcase-constants";
1813

19-
export function DetailPageUI() {
20-
const thirdwebClient = useThirdwebClient();
21-
const router = useRouter();
22-
const { slug } = router.query;
14+
export default async function DetailPage({
15+
params,
16+
}: { params: { slug: string } }) {
17+
const { slug } = params;
2318

2419
const project = PROJECT_SHOWCASE_DATA.find((p) => p.slug === slug);
2520

@@ -74,32 +69,24 @@ export function DetailPageUI() {
7469
</div>
7570
<div className="md:w-1/2">
7671
<div className="relative aspect-video h-full w-full md:aspect-square">
77-
<Image
72+
{/* <Image
7873
src={
7974
project.image?.startsWith("ipfs://")
80-
? (resolveSchemeWithErrorHandler({
75+
? ((await resolveSchemeWithErrorHandler({
8176
client: thirdwebClient,
8277
uri: project.image,
83-
}) ?? "")
78+
})) ?? "")
8479
: (project.image ?? "/assets/showcase/default_image.png")
8580
}
8681
alt={`${project.title} Thumbnail`}
87-
layout="fill"
88-
objectFit="cover"
89-
className="rounded-b-lg md:rounded-r-lg md:rounded-bl-none"
90-
/>
82+
width={500}
83+
height={500}
84+
className="rounded-b-lg md:rounded-r-lg md:rounded-bl-none object-cover"
85+
/> */}
9186
</div>
9287
</div>
9388
</div>
9489
</Card>
9590
</div>
9691
);
9792
}
98-
99-
export default function DetailPage() {
100-
return (
101-
<ThirdwebProvider>
102-
<DetailPageUI />
103-
</ThirdwebProvider>
104-
);
105-
}
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import type { Metadata } from "next";
2+
import Link from "next/link";
3+
import { Badge } from "../../../@/components/ui/badge";
4+
import {
5+
Card,
6+
CardContent,
7+
CardDescription,
8+
CardHeader,
9+
CardTitle,
10+
} from "../../../@/components/ui/card";
11+
import {
12+
Pagination,
13+
PaginationContent,
14+
PaginationItem,
15+
PaginationLink,
16+
PaginationNext,
17+
PaginationPrevious,
18+
} from "../../../@/components/ui/pagination";
19+
import {
20+
PROJECT_SHOWCASE_DATA,
21+
PROJECT_SHOWCASE_INDUSTRIES,
22+
PROJECT_SHOWCASE_ITEMS_PER_PAGE,
23+
} from "../../../lib/project-showcase-constants";
24+
import { getAbsoluteUrl } from "../../../lib/vercel-utils";
25+
26+
export const metadata: Metadata = {
27+
title: "Project Showcase | Built on thirdweb",
28+
description: "Discover the latest web3 apps and games built on thirdweb",
29+
openGraph: {
30+
title: "Project Showcase | Built on thirdweb",
31+
description: "Discover the latest web3 apps and games built on thirdweb",
32+
images: [
33+
{
34+
url: `${getAbsoluteUrl()}/assets/showcase/og_image.png`,
35+
width: 1200,
36+
height: 630,
37+
},
38+
],
39+
},
40+
};
41+
42+
export const dynamic = "force-dynamic";
43+
44+
export default function ProjectShowcasePage({
45+
searchParams,
46+
}: {
47+
searchParams: { industry?: string; page?: string };
48+
}) {
49+
const selectedIndustry = searchParams.industry || "All";
50+
const currentPage = Number.parseInt(searchParams.page || "1", 10);
51+
52+
const filteredProjects =
53+
selectedIndustry === "All"
54+
? PROJECT_SHOWCASE_DATA
55+
: PROJECT_SHOWCASE_DATA.filter((project) =>
56+
project.industries?.includes(selectedIndustry),
57+
);
58+
59+
const totalPages = Math.ceil(
60+
filteredProjects.length / PROJECT_SHOWCASE_ITEMS_PER_PAGE,
61+
);
62+
const paginatedProjects = filteredProjects.slice(
63+
(currentPage - 1) * PROJECT_SHOWCASE_ITEMS_PER_PAGE,
64+
currentPage * PROJECT_SHOWCASE_ITEMS_PER_PAGE,
65+
);
66+
67+
return (
68+
<div className="min-h-screen bg-background">
69+
<section className="w-full">{/* Hero section content */}</section>
70+
<main className="container mx-auto px-4 py-12 md:px-6">
71+
<section>
72+
<div className="mb-8">
73+
<div className="mb-8 flex flex-wrap justify-center gap-2">
74+
{PROJECT_SHOWCASE_INDUSTRIES.map((industry) => (
75+
<Link
76+
key={industry}
77+
href={`/project-showcase?industry=${industry}&page=1`}
78+
className={`inline-flex h-10 items-center justify-center rounded-md px-4 py-2 font-medium text-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring ${
79+
selectedIndustry === industry
80+
? "bg-primary text-primary-foreground shadow hover:bg-primary/90"
81+
: "border border-input bg-background hover:bg-accent hover:text-accent-foreground"
82+
}`}
83+
>
84+
{industry}
85+
</Link>
86+
))}
87+
</div>
88+
</div>
89+
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
90+
{paginatedProjects.map((project) => (
91+
<Link
92+
key={project.id}
93+
href={`/project-showcase/${project.slug}`}
94+
className="block"
95+
>
96+
<Card className="flex h-full cursor-pointer flex-col overflow-hidden transition-shadow hover:shadow-lg">
97+
{/* <Image
98+
src={project.image ?? "/assets/showcase/default_image.png"}
99+
alt={project.title}
100+
width={300}
101+
height={200}
102+
className="h-48 w-full object-cover"
103+
/> */}
104+
<CardHeader>
105+
<CardTitle className="mb-3">{project.title}</CardTitle>
106+
<CardDescription>{project.description}</CardDescription>
107+
</CardHeader>
108+
<CardContent className="flex-grow">
109+
<div className="flex flex-wrap gap-2">
110+
{project.industries?.map((industry) => (
111+
<Badge key={industry} variant="secondary">
112+
{industry}
113+
</Badge>
114+
))}
115+
</div>
116+
</CardContent>
117+
</Card>
118+
</Link>
119+
))}
120+
</div>
121+
<div className="mt-8 flex flex-col items-center">
122+
<div className="mb-4 text-muted-foreground text-sm">
123+
Showing {paginatedProjects.length} of {filteredProjects.length}{" "}
124+
projects in{" "}
125+
{selectedIndustry === "All" ? "all categories" : selectedIndustry}
126+
</div>
127+
<Pagination>
128+
<PaginationContent>
129+
<PaginationItem>
130+
<Link
131+
href={`/project-showcase?industry=${selectedIndustry}&page=${
132+
currentPage > 1 ? currentPage - 1 : 1
133+
}`}
134+
passHref
135+
legacyBehavior
136+
>
137+
<PaginationPrevious
138+
className={
139+
currentPage <= 1 ? "pointer-events-none opacity-50" : ""
140+
}
141+
/>
142+
</Link>
143+
</PaginationItem>
144+
{Array.from({ length: totalPages }, (_, i) => i + 1).map(
145+
(pageNumber) => (
146+
<PaginationItem key={`page-${pageNumber}`}>
147+
<Link
148+
href={`/project-showcase?industry=${selectedIndustry}&page=${pageNumber}`}
149+
passHref
150+
legacyBehavior
151+
>
152+
<PaginationLink isActive={currentPage === pageNumber}>
153+
{pageNumber}
154+
</PaginationLink>
155+
</Link>
156+
</PaginationItem>
157+
),
158+
)}
159+
<PaginationItem>
160+
<Link
161+
href={`/project-showcase?industry=${selectedIndustry}&page=${
162+
currentPage < totalPages ? currentPage + 1 : totalPages
163+
}`}
164+
passHref
165+
legacyBehavior
166+
>
167+
<PaginationNext
168+
className={
169+
currentPage >= totalPages
170+
? "pointer-events-none opacity-50"
171+
: ""
172+
}
173+
/>
174+
</Link>
175+
</PaginationItem>
176+
</PaginationContent>
177+
</Pagination>
178+
</div>
179+
</section>
180+
</main>
181+
</div>
182+
);
183+
}

0 commit comments

Comments
 (0)