feat(blog) add CMS, render blog posts list

- use GitHub repo as cms, read idx.json
- blog posts list
This commit is contained in:
lumither committed 2024-04-27 12:03:08 +08:00
1 parent 7419e7e3cf
commit 603dbf71a6
7 files changed
+98 -2

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
BLOG_ENDPOINT=https://raw.githubusercontents.com/lumither/blog-posts/master
; use mirror
+33
View File
@@ -0,0 +1,33 @@
import React from 'react';
import Link from 'next/link';
import { Card, CardBody, CardHeader } from '@nextui-org/card';
import { Divider } from '@nextui-org/react';
type Props = {
post: JSON
}
function BlogPostCard({ post }: Props) {
const name = (post as any)['name'];
const { title, desc } = (post as any)['meta'] as { title: string, desc: string };
return (
<div>
{/*todo: to be update*/ }
{/*<Link href={ `/blog/${ name }` }>*/}
<Card>
<CardHeader>
<p className={ 'font-bold' }>{ title }</p>
</CardHeader>
<Divider />
<CardBody>
{ desc }
</CardBody>
</Card>
{/*</Link>*/}
</div>
);
}
export default BlogPostCard;
+19
View File
@@ -0,0 +1,19 @@
import { Result } from '@/app/public/type/Result';
export default async function fetch_posts(url: string): Promise<Result<JSON[], Error>> {
const response = await fetch(`${ url }/posts/idx.json`);
if (!response.ok) {
return {
ok: false,
error: new Error(response.statusText)
};
}
const res = await response.json();
const posts = res['idx'].filter((posts: { type: string }) => posts.type === 'md');
return {
ok: true,
value: posts
};
}
+15
View File
@@ -0,0 +1,15 @@
import React from 'react';
function Layout({
children
}: {
children: React.ReactNode;
}) {
return (
<div className={ 'flex items-stretch justify-center' }>
{ children }
</div>
);
}
export default Layout;
+21 -2
View File
@@ -1,8 +1,27 @@
import React from 'react';
import fetch_posts from '@/app/blog/fetch_posts';
import BlogPostCard from '@/app/blog/BlogPostCard';
async function Blog() {
const res = await fetch_posts(process.env.BLOG_ENDPOINT!);
if (!res.ok) {
console.log(res.error);
return;
}
const posts = res.value;
// console.log(posts);
function Blog() {
return (
<div></div>
// blog list
<ul className={ 'flex flex-col items-center w-full max-w-[1024px]' }>
{ posts.map((post, key) => (
<li key={ key } className={ 'my-3.5 mx-7 w-[80%]' }>
<BlogPostCard post={ post } />
</li>)
) }
</ul>
);
}
+7
View File
@@ -0,0 +1,7 @@
export type Result<T, E> = {
ok: true;
value: T;
} | {
ok: false;
error: E;
};
+1
View File
@@ -4,6 +4,7 @@
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"target": "ESNext",
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",