Skip to content

Commit 77cbb3f

Browse files
authored
feat: create certificate detail page
feat: create certificate detail page
2 parents b4d2fc4 + 38421ee commit 77cbb3f

File tree

5 files changed

+125
-7
lines changed

5 files changed

+125
-7
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { notFound } from "next/navigation";
2+
3+
import Certificate from "@/features/certificate/Certificate";
4+
import { CertificateType } from "@/features/certificate/types";
5+
6+
export async function getCertificate(slug: string) {
7+
try {
8+
const response = await fetch(`https://moonlight.hammercode.org/v1/certificates/${slug}`);
9+
if (!response.ok) return null;
10+
11+
return response.json();
12+
} catch (error) {
13+
console.error("Error fetching certificate:", error);
14+
return null;
15+
}
16+
}
17+
18+
type Props = {
19+
params: {
20+
slug: string;
21+
};
22+
};
23+
24+
const CertificateDetail = async ({ params }: Props) => {
25+
const certificate: CertificateType = await getCertificate(params.slug);
26+
if (!certificate.name) {
27+
return notFound();
28+
}
29+
30+
return <Certificate certificate={certificate} />;
31+
};
32+
33+
export default CertificateDetail;

src/app/[locale]/layout.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,3 @@ export default async function LocaleRootLayout({ children, params: { locale } }:
4848
</html>
4949
);
5050
}
51-
52-
// {
53-
// ""
54-
// }

src/components/layout/wrapper/index.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
"use client";
2+
23
import Navbar from "@/components/common/navbar";
34
import { ThemeProvider } from "../theme-provider";
45
import Footer from "@/components/common/footer/Footer";
6+
import { useParams, usePathname } from "next/navigation";
57

68
const Wrapper = ({ children }: { children: React.ReactNode }) => {
9+
const params = useParams();
10+
const pathname = usePathname();
11+
const isCertificateDetailPage = !!params?.slug && pathname.includes("certificates");
12+
713
return (
814
<ThemeProvider attribute="class" defaultTheme="light" enableSystem disableTransitionOnChange>
9-
<Navbar />
10-
{children}
11-
<Footer />
15+
{isCertificateDetailPage ? (
16+
children
17+
) : (
18+
<>
19+
<Navbar />
20+
{children}
21+
<Footer />
22+
</>
23+
)}
1224
</ThemeProvider>
1325
);
1426
};
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import Image from "next/image";
2+
import { CertificateType } from "./types";
3+
import { Button } from "@/components/ui/button";
4+
import { Link } from "@/lib/navigation";
5+
import { Linkedin, TwitterIcon } from "lucide-react";
6+
7+
type Props = {
8+
certificate: CertificateType;
9+
};
10+
11+
const Certificate = ({ certificate }: Props) => {
12+
const { _id, event, image_link, name, share_link } = certificate;
13+
return (
14+
<div className="w-full">
15+
<div className="p-4 my-12">
16+
<div className="space-y-2">
17+
<h3 className="text-hmc-primary md:text-2xl text-xl font-semibold text-center">
18+
Terima Kasih kepada <strong className="font-extrabold">{name}</strong>!
19+
</h3>
20+
<p className="md:text-base text-sm text-center text-gray-500">Kamu telah berpartisipasi dalam acara ini.</p>
21+
</div>
22+
<div className="w-full h-full relative">
23+
<div className="flex justify-center">
24+
<Image
25+
src={image_link}
26+
className="my-4 rounded-lg shadow-md object-cover object-center"
27+
width="640"
28+
height="480"
29+
alt={`Sertikat ${event} - ${name}`}
30+
/>
31+
</div>
32+
<p className="md:text-base text-sm text-center text-gray-500 mb-8">
33+
Sertifikat : <b>{_id}</b>
34+
</p>
35+
36+
<div className="flex justify-center">
37+
<Button asChild variant="tertiary">
38+
<Link href={share_link} target="_blank">
39+
UNDUH SERTIFIKAT
40+
</Link>
41+
</Button>
42+
</div>
43+
<div>
44+
<p className="md:text-base text-sm text-center text-gray-500 my-4">
45+
<strong className="md:text-lg text-md text-black">Pamerkan</strong> sertifikat ini ke teman-temanmu!
46+
</p>
47+
48+
<div className="flex justify-center space-x-6">
49+
<Button variant="secondary" size="icon">
50+
<Link
51+
href={`https://twitter.com/intent/tweet?text=Saya telah mengikuti kegiatan ${event} yang diadakan oleh Hammercode.org&url=${share_link}`}
52+
target={"_blank"}
53+
>
54+
<TwitterIcon className="w-full text-3xl text-sky-600 hover:text-sky-700" size={24} />
55+
</Link>
56+
</Button>
57+
<Button variant="secondary" size="icon">
58+
<Link href={`https://www.linkedin.com/shareArticle?mini=true&url=${share_link}`} target={"_blank"}>
59+
<Linkedin className="text-3xl text-sky-600 hover:text-sky-700" size={24} />
60+
</Link>
61+
</Button>
62+
</div>
63+
</div>
64+
</div>
65+
</div>
66+
</div>
67+
);
68+
};
69+
70+
export default Certificate;

src/features/certificate/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export type CertificateType = {
2+
_id: string;
3+
name: string;
4+
image_link: string;
5+
share_link: string;
6+
event: string;
7+
};

0 commit comments

Comments
 (0)