2024-10-09 . 0 min(s)

1import Image from "next/image";
2import { getArticle } from "../../../../../sanity/sanity-utils";
3import { Metadata } from "next";
4import { PortableText } from "@portabletext/react";
5import { urlFor } from "../../../../../sanity/config/client-config";
6import CodeBlock from "@/app/components/CodeBlock";
7
8export interface ParamsProps {
9 params: {
10 slug: string;
11 };
12}
13
14export async function generateMetadata({
15 params,
16}: ParamsProps): Promise<Metadata> {
17 const article = await getArticle(params.slug);
18
19 return {
20 title: article.title,
21 description:
22 "Discover insightful articles on a variety of topics, ranging from web development and programming to personal growth and industry trends. Stay informed and inspired with our latest posts.",
23 openGraph: {
24 title: article.title,
25 description:
26 "Discover insightful articles on a variety of topics, ranging from web development and programming to personal growth and industry trends. Stay informed and inspired with our latest posts.",
27 images: [article.image],
28 },
29 };
30}
31
32export default async function ArticleDetails({ params }: ParamsProps) {
33 const article = await getArticle(params.slug);
34
35 return (
36 <section>
37 <div className="container mx-auto px-5 pt-20 lg:px-20">
38 <div className="flex flex-col gap-4 xl:flex-row xl:items-center xl:justify-between">
39 <div className="flex flex-col-reverse gap-4 xl:flex-col">
40 <p className="text-sm">
41 {article.date} . {article.estimatedReadingTime} min(s)
42 </p>
43 <h2 className="max-w-[550px] text-[44px] font-bold leading-[110%] md:text-[56px]">
44 {article.title}
45 </h2>
46 </div>
47
48 <Image
49 src={article.image}
50 alt={article.alt}
51 width={400}
52 height={400}
53 className="w-full max-w-full xl:w-auto"
54 />
55 </div>
56
57 <div className="prose prose-lg prose-blue max-w-[800px] pt-[100px] xl:prose-xl lg:pt-[160px]">
58 <PortableText
59 value={article.content}
60 components={{
61 types: {
62 image: ({ value }) => (
63 <Image
64 src={urlFor(value.asset).url()}
65 width={500}
66 height={500}
67 alt={value.alt}
68 style={{ maxWidth: "100%" }}
69 />
70 ),
71 code: ({ value }) => (
72 <CodeBlock code={value.code} language={value.language} />
73 ),
74 },
75 }}
76 />
77 </div>
78 </div>
79 </section>
80 );
81}
82React Hooks are functions that let you use state and other React features in functional components. Introduced in React 16.8, hooks have become an essential part of modern React development.
1import darcula from "react-syntax-highlighter/dist/cjs/prism";
2import dynamic from "next/dynamic";
3const SyntaxHighlighter = dynamic(
4 () => import("react-syntax-highlighter").then((mod) => mod.Prism),
5 { ssr: false },
6);
7const CodeBlock = ({ code, language }) => {
8 return (
9 <SyntaxHighlighter language={language} style={darcula} showLineNumbers>
10 {code}
11 </SyntaxHighlighter>
12 );
13};
14
15export default CodeBlock;
16xzccsacxzczxczxcsdsd