quivr/frontend/pages/blog/[id]/index.tsx

150 lines
4.4 KiB
TypeScript
Raw Normal View History

/* eslint-disable */
2023-10-23 22:28:36 +03:00
'use client';
import type { GetStaticPaths, InferGetStaticPropsType } from 'next';
2023-10-23 22:28:36 +03:00
import Head from 'next/head';
import Image from "next/image";
2023-10-23 22:28:36 +03:00
import Link from 'next/link';
import { useEffect, useState } from 'react';
import "@/globals.css";
2023-10-23 20:24:00 +03:00
type SeoAttributes = {
id: number;
metaTitle: string;
metaDescription: string;
2023-10-23 22:28:36 +03:00
metaImage: {
id: number;
data: {
attributes: {
formats: {
large: {
url: string;
};
medium: {
url: string;
};
};
};
};
};
2023-10-23 20:24:00 +03:00
keywords: string;
metaRobots: string | null;
structuredData: string | null;
metaViewport: string | null;
canonicalURL: string | null;
};
type BlogPostAttributes = {
2023-10-23 20:24:00 +03:00
title: string; // Assuming title is extracted from the first few words of the article
Article: string;
createdAt: string;
updatedAt: string;
publishedAt: string;
seo: SeoAttributes;
};
type BlogPost = {
2023-10-23 20:24:00 +03:00
id: number;
attributes: BlogPostAttributes;
};
export const getStaticPaths: GetStaticPaths = async () => {
try {
2023-09-21 15:31:07 +03:00
const response = await fetch("https://cms.quivr.app/api/blogs");
if (!response.ok) {
2023-10-23 22:28:36 +03:00
throw new Error('Network response was not ok');
}
const data: { data: BlogPost[] } = await response.json();
const paths = data.data.map(post => ({ params: { id: post.id.toString() } }));
2023-10-23 22:28:36 +03:00
return {
paths,
2023-10-23 22:28:36 +03:00
fallback: false,
};
} catch (error) {
console.error("Error fetching blog paths:", error);
return {
2023-10-23 22:28:36 +03:00
paths: [],
fallback: false,
};
}
};
export const getStaticProps = async (context: { params: { id: string } }) => {
try {
2023-10-23 22:28:36 +03:00
const response = await fetch(`https://cms.quivr.app/api/blogs/${context.params.id}?populate=seo,seo.metaImage`);
const data: { data: BlogPost } = await response.json();
return {
props: {
post: data.data,
},
};
} catch (error) {
console.error("Error fetching blog post:", error);
return {
notFound: true,
};
}
};
const BlogPostDetail = ({ post }: InferGetStaticPropsType<typeof getStaticProps>) => {
2023-10-23 22:28:36 +03:00
const { metaTitle, metaDescription, keywords, canonicalURL } = post.attributes.seo;
// Extract different image formats
const { large, medium } = post.attributes.seo.metaImage.data.attributes.formats;
const [imageUrl, setImageUrl] = useState(medium.url);
useEffect(() => {
// Determine which image URL to use once the component has mounted on the client side
setImageUrl(window.innerWidth > 768 ? large.url : medium.url);
}, []);
2023-10-23 20:24:00 +03:00
return (
2023-10-23 22:28:36 +03:00
<section className="w-full">
<header className="bg-white text-zinc-900 py-4 border-b">
<div className="container mx-auto px-4 md:px-6">
<nav className="flex items-center justify-between">
<div className="text-2xl font-bold">Quivr - Blog</div>
<div className="space-x-4">
<Link className="text-zinc-900 hover:text-zinc-700" href="https://quivr.app">Try Quivr</Link>
<Link className="text-zinc-900 hover:text-zinc-700" href="/blog">Blog</Link>
</div>
</nav>
2023-10-23 20:24:00 +03:00
</div>
2023-10-23 22:28:36 +03:00
</header>
<div className="px-4 py-6 md:px-6 lg:py-16 md:py-12 bg-white dark:bg-black">
<Head>
<title>{metaTitle}</title>
<meta name="description" content={metaDescription} />
<meta name="keywords" content={keywords} />
{canonicalURL && <link rel="canonical" href={canonicalURL} />}
</Head>
<article className="prose prose-zinc mx-auto dark:prose-invert">
<div className="space-y-2 not-prose">
<h1 className="text-4xl font-extrabold tracking-tight lg:text-5xl lg:leading-[3.5rem] text-black dark:text-white">
{metaTitle}
</h1>
<p className="text-zinc-500 dark:text-zinc-400">Posted on {post.attributes.publishedAt}</p>
</div>
<p className="text-black dark:text-white">
{metaDescription}
</p>
<Image
2023-10-23 22:28:36 +03:00
src={imageUrl}
2023-10-23 20:46:58 +03:00
alt={metaTitle}
2023-10-23 20:24:00 +03:00
className="aspect-video overflow-hidden rounded-lg object-cover"
width={1250}
height={340}
/>
2023-10-23 22:28:36 +03:00
<div className="text-black dark:text-white" dangerouslySetInnerHTML={{ __html: post.attributes.Article }}></div>
</article>
</div>
</section>
);
}
2023-10-23 20:24:00 +03:00
export default BlogPostDetail;