From 02ae938c238c9d18448d17a8ec92c0edd8c17463 Mon Sep 17 00:00:00 2001 From: Bertrand Yuan Date: Tue, 16 Dec 2025 00:12:49 +0800 Subject: feat(back-end): introduce payload Payload is the next.js Headless CMS and App Framework, I would like to pick it up and modify it as it is MIT licensed. Many features in Payload is not applicable for our project. So, I modify it so that it is light and clear. --- .../(main)/(home)/_components/call-to-action.tsx | 23 +++++ src/app/(main)/(home)/_components/hero.tsx | 98 ++++++++++++++++++++++ src/app/(main)/(home)/_components/posts.tsx | 89 ++++++++++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 src/app/(main)/(home)/_components/call-to-action.tsx create mode 100644 src/app/(main)/(home)/_components/hero.tsx create mode 100644 src/app/(main)/(home)/_components/posts.tsx (limited to 'src/app/(main)/(home)/_components') diff --git a/src/app/(main)/(home)/_components/call-to-action.tsx b/src/app/(main)/(home)/_components/call-to-action.tsx new file mode 100644 index 0000000..b75298e --- /dev/null +++ b/src/app/(main)/(home)/_components/call-to-action.tsx @@ -0,0 +1,23 @@ +import { NewsletterForm } from '@/components/newsletter-form'; +import { Section } from '@/components/section'; +import type React from 'react'; + +export function CTA(): React.ReactElement { + return ( +
+
+

+ Subscribe to the Newsletter +

+

+ Get the latest articles and updates delivered straight to your inbox. + No spam, unsubscribe anytime. +

+
+ +
+ +
+
+ ); +} diff --git a/src/app/(main)/(home)/_components/hero.tsx b/src/app/(main)/(home)/_components/hero.tsx new file mode 100644 index 0000000..04371ca --- /dev/null +++ b/src/app/(main)/(home)/_components/hero.tsx @@ -0,0 +1,98 @@ +import { baseOptions, linkItems } from '@/app/(main)/layout.config'; +import { Icons } from '@/components/icons/icons'; +import { Section } from '@/components/section'; +import { buttonVariants } from '@/components/ui/button'; +import { cn } from '@/lib/utils'; +import { getLinks } from 'fumadocs-ui/layouts/shared'; +import * as motion from 'motion/react-client'; +import Image from 'next/image'; +import Link from 'next/link'; +import Balancer from 'react-wrap-balancer'; +import heroImage from '../../../../../public/images/gradient-noise-purple-azure-light.png'; + +const Hero = () => { + const links = getLinks(linkItems, baseOptions.githubUrl); + const navItems = links.filter((item) => + ['nav', 'all'].includes(item.on ?? 'all'), + ); + + return ( +
+ + Hero Background + +
+ + + Full-Stack Developer & Tech Writer + +
+

+ I'm John Doe , a Full-Stack Developer. +

+

+ + I write about web development, software engineering, and the latest + technologies. I also create fun projects and tutorials to help you + learn and grow as a developer. + +

+ +
+ + Browse Posts + + + +
+ {navItems + .filter((item) => item.type === 'icon') + .map((item, i) => ( + + {item.icon} + {item.text} + + ))} +
+
+
+ ); +}; + +export default Hero; diff --git a/src/app/(main)/(home)/_components/posts.tsx b/src/app/(main)/(home)/_components/posts.tsx new file mode 100644 index 0000000..00ada0c --- /dev/null +++ b/src/app/(main)/(home)/_components/posts.tsx @@ -0,0 +1,89 @@ +import { Icons } from '@/components/icons/icons'; +import { PostCard } from '@/components/posts/post-card'; +import { Section } from '@/components/section'; +import { buttonVariants } from '@/components/ui/button'; +import type { Page } from '@/lib/source'; +import type { BlogPost } from '@/lib/payload-posts'; +import Link from 'next/link'; + +// 统一的文章数据格式 +interface UnifiedPost { + title: string; + description: string; + image?: string | null; + url: string; + date: string; + author: string; + tags?: string[]; +} + +// 将 MDX Page 转换为统一格式 +function transformMdxPost(post: Page): UnifiedPost { + return { + title: post.data.title, + description: post.data.description ?? '', + image: post.data.image, + url: post.url, + date: new Date(post.data.date).toDateString(), + author: post.data.author, + tags: post.data.tags, + }; +} + +// 将 Payload BlogPost 转换为统一格式 +function transformPayloadPost(post: BlogPost): UnifiedPost { + return { + title: post.title, + description: post.description, + image: post.image, + url: post.url, + date: post.date.toDateString(), + author: post.author, + tags: post.tags, + }; +} + +interface PostsProps { + mdxPosts?: Page[]; + payloadPosts?: BlogPost[]; +} + +export default function Posts({ mdxPosts = [], payloadPosts = [] }: PostsProps) { + // 转换并合并所有文章 + const allPosts: UnifiedPost[] = [ + ...mdxPosts.map(transformMdxPost), + ...payloadPosts.map(transformPayloadPost), + ]; + + // 按日期排序 + allPosts.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); + + return ( +
+
+ {allPosts.map((post) => ( + + ))} + + View More + + +
+
+ ); +} -- cgit v1.2.3