forked from mrwyndham/fastpocket
feature - added pb blogs
This commit is contained in:
parent
b11d5f8d9c
commit
7d27741840
|
@ -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" />
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue