feature - added pb blogs

This commit is contained in:
James Wyndham 2024-02-20 07:49:46 +08:00
parent b11d5f8d9c
commit 7d27741840
6 changed files with 61 additions and 62 deletions

View File

@ -1,22 +1,9 @@
import fs from "fs";
import matter from "gray-matter";
import BlogContent from "@/sections/BlogContent"; import BlogContent from "@/sections/BlogContent";
import Link from "next/link";
import Image from "next/image";
import xButton from "@/images/icon-x.svg";
import getPostMetadata from "@/utils/getPostMetaData"; import getPostMetadata from "@/utils/getPostMetaData";
import { headers } from "next/headers"; import { headers } from "next/headers";
import React from "react"; import React from "react";
import Icon from "@/components/icon";
import Spacer from "@/components/Utilities/Spacer"; import Spacer from "@/components/Utilities/Spacer";
import pb from "@/lib/pocketbase";
const getPostContent = (slug: string) => {
const folder = "blogs/";
const file = `${folder}${slug}.md`;
const content = fs.readFileSync(file, "utf8");
const matterResult = matter(content);
return matterResult;
};
export async function generateMetadata({ export async function generateMetadata({
params, params,
@ -26,11 +13,15 @@ export async function generateMetadata({
const { slug } = params; const { slug } = params;
const headersList = headers(); const headersList = headers();
const siteURL = headersList.get("host"); const siteURL = headersList.get("host");
const post = getPostContent(slug); pb.autoCancellation(false);
const post = await pb.collection("blog").getFirstListItem(`slug="${slug}"`, {
requestKey: "metaData",
});
pb.autoCancellation(true);
return { return {
title: `${post.data.title}`, title: `${post.title}`,
description: `${post.data.subtitle}`, description: `${post.subtitle}`,
alternates: { alternates: {
canonical: `https://${siteURL}/blogs/${slug}`, canonical: `https://${siteURL}/blogs/${slug}`,
}, },
@ -38,16 +29,19 @@ export async function generateMetadata({
} }
export const generateStaticParams = async () => { export const generateStaticParams = async () => {
const posts = getPostMetadata(); const posts = await getPostMetadata();
return posts.map((post) => ({ return posts.map((post) => ({
slug: post.slug, slug: post.slug,
id: post.id,
})); }));
}; };
const PostPage = (props: any) => { const PostPage = async (props: any) => {
const slug = props.params.slug; const post = await pb
const post = getPostContent(slug); .collection("blog")
const showModal = props.searchParams?.modal; .getFirstListItem(`slug="${props.params.slug}"`, {
requestKey: "post",
});
return ( return (
<div className="flex flex-col h-full w-full bg-white dark:bg-black px-8 md:max-w-3xl md:mx-auto"> <div className="flex flex-col h-full w-full bg-white dark:bg-black px-8 md:max-w-3xl md:mx-auto">
<Spacer className="pt-32" /> <Spacer className="pt-32" />

View File

@ -4,12 +4,12 @@ import getPostMetadata from "@/utils/getPostMetaData";
import React from "react"; import React from "react";
import Background from "@/components/Utilities/Background"; import Background from "@/components/Utilities/Background";
export default function BlogsPage() { export default async function BlogsPage() {
const postMetadata = getPostMetadata(); const postMetadata = await getPostMetadata();
const postPreviews = postMetadata const postPreviews = postMetadata
.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()) .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
.map((post) => <BlogCard key={post.slug} {...post} />); .map((post) => <BlogCard key={post.slug} {...(post as any)} />);
return ( return (
<main <main
id="content" id="content"
@ -31,7 +31,7 @@ export default function BlogsPage() {
} }
/> />
<div className="max-w-6xl mx-auto mb-24 h-full w-full py-12 px-8"> <div className="max-w-6xl mx-auto mb-24 h-full w-full py-12 px-8">
<div className="w-full flex items-start justify-center flex-row flex-wrap gap-x-8 gap-y-8 md:gap-12 text-black dark:text-white"> <div className="w-full flex items-start justify-center flex-row flex-wrap gap-x-8 gap-y-8 md:gap-8 text-black dark:text-white">
{postPreviews} {postPreviews}
</div> </div>
</div> </div>

View File

@ -5,7 +5,6 @@ import pb from "@/lib/pocketbase";
import { getAuthCookie } from "@/app/(auth)/actions"; import { getAuthCookie } from "@/app/(auth)/actions";
export async function apiPrices() { export async function apiPrices() {
console.log('prices')
try { try {
const pocketbaseUrl = process.env.NEXT_PUBLIC_POCKETBASE_URL_STRING; const pocketbaseUrl = process.env.NEXT_PUBLIC_POCKETBASE_URL_STRING;
if (!pocketbaseUrl) { if (!pocketbaseUrl) {

View File

@ -4,7 +4,17 @@ import { PostMetadata } from "@/types";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
function BlogCard({ title, slug, subtitle, image }: PostMetadata) { function BlogCard({
title,
slug,
subtitle,
imageUrl,
}: {
title: string;
slug: string;
subtitle: string;
imageUrl: string;
}) {
return ( return (
<> <>
<Link <Link
@ -13,7 +23,7 @@ function BlogCard({ title, slug, subtitle, image }: PostMetadata) {
> >
<div className="w-full aspect-[4/3] bg-slate-400 rounded-lg overflow-hidden relative"> <div className="w-full aspect-[4/3] bg-slate-400 rounded-lg overflow-hidden relative">
<Image <Image
src={image} src={imageUrl}
alt={title} alt={title}
className="w-full h-full object-cover" className="w-full h-full object-cover"
fill fill

View File

@ -1,32 +1,24 @@
import React from "react"; import React from "react";
import Image from "next/image"; import Image from "next/image";
import matter from "gray-matter";
import Markdown from "markdown-to-jsx";
interface BlogContentProps { function BlogContent({ post }: { post: any }) {
post: matter.GrayMatterFile<string>;
}
function BlogContent({ post }: BlogContentProps) {
return ( return (
<> <>
<h1 className="text-3xl text-black dark:text-slate-200"> <h1 className="text-3xl text-black dark:text-slate-200">{post.title}</h1>
{post.data.title}
</h1>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{/* Not sure if name is required */} {/* Not sure if name is required */}
<p className="text-black dark:text-slate-200"> <p className="text-black dark:text-slate-200">{post.author ?? ""}</p>
{post.data.author ?? ""}
</p>
<span className="text-black dark:text-slate-200">|</span> <span className="text-black dark:text-slate-200">|</span>
<p className="text-black dark:text-slate-200">{post.data.date}</p> <p className="text-black dark:text-slate-200">
{new Date(post.date).toLocaleDateString()}
</p>
</div> </div>
<article className="prose prose-img:rounded-xl max-w-none prose-p:text-black dark:prose-p:text-white prose-a:text-primary prose-h2:text-black dark:prose-h2:text-white prose-li:text-black dark:prose-li:text-white prose-strong:text-black dark:prose-strong:text-white prose-blockquote:pr-2 prose-blockquote:font-normal"> <article className="prose prose-img:rounded-xl max-w-none prose-p:text-black dark:prose-p:text-white prose-a:text-primary prose-h2:text-black dark:prose-h2:text-white prose-li:text-black dark:prose-li:text-white prose-strong:text-black dark:prose-strong:text-white prose-blockquote:pr-2 prose-blockquote:font-normal">
<div className="h-full w-full"> <div className="h-full w-full">
<Image <Image
priority priority
src={post.data.image} src={post.imageUrl}
alt="post-image" alt="post-image"
width={0} width={0}
height={0} height={0}
@ -39,7 +31,7 @@ function BlogContent({ post }: BlogContentProps) {
}} }}
/> />
</div> </div>
<Markdown>{post.content}</Markdown> <div dangerouslySetInnerHTML={{ __html: post.content }}></div>
</article> </article>
</> </>
); );

View File

@ -2,27 +2,31 @@ import { PostMetadata } from "@/types";
import fs from "fs"; import fs from "fs";
import matter from "gray-matter"; import matter from "gray-matter";
import path from 'path' import path from 'path'
import pb from '@/lib/pocketbase';
const getPostMetadata = (): PostMetadata[] => { const getPostMetadata = async () => {
const folder = path.join(process.cwd(), '/blogs'); // const folder = path.join(process.cwd(), '/blogs');
const files = fs.readdirSync(folder); // const files = fs.readdirSync(folder);
const markdownPosts = files.filter((file) => file.endsWith(".md")); // const markdownPosts = files.filter((file) => file.endsWith(".md"));
// Get gray-matter data from each file. // Get gray-matter data from each file.
const posts = markdownPosts.map((fileName) => { // const posts = markdownPosts.map((fileName) => {
const fileContents = fs.readFileSync(`blogs/${fileName}`, "utf8"); // const fileContents = fs.readFileSync(`blogs/${fileName}`, "utf8");
const matterResult = matter(fileContents); // const matterResult = matter(fileContents);
return { // return {
title: matterResult.data.title, // title: matterResult.data.title,
date: matterResult.data.date, // date: matterResult.data.date,
author: matterResult.data.author, // author: matterResult.data.author,
subtitle: matterResult.data.subtitle, // subtitle: matterResult.data.subtitle,
slug: fileName.replace(".md", ""), // slug: fileName.replace(".md", ""),
image: matterResult.data.image, // image: matterResult.data.image,
}; // };
}); // });
return posts;
return (await (pb.collection("blog").getList(1, 50))).items;
}; };
export default getPostMetadata; export default getPostMetadata;