feat: enhance blog and dashboard UI components
- Update blog post dates in English and Chinese content - Refactor blog layout with header section and container - Simplify blog page and post layouts - Improve blog card and grid styling - Add initial dashboard page with sidebar and breadcrumbs - Adjust header section subtitle color
This commit is contained in:
parent
71eaefefbf
commit
58401624c0
@ -2,7 +2,7 @@
|
|||||||
title: What is MkSaaS?
|
title: What is MkSaaS?
|
||||||
description: MkSaaS is the best boilerplate for building AI SaaS websites.
|
description: MkSaaS is the best boilerplate for building AI SaaS websites.
|
||||||
image: /images/blog/mksaas-og.png
|
image: /images/blog/mksaas-og.png
|
||||||
date: 2024-11-24T12:00:00.000Z
|
date: 2024-11-26T12:00:00.000Z
|
||||||
published: true
|
published: true
|
||||||
categories: [news, guide]
|
categories: [news, guide]
|
||||||
author: mksaas
|
author: mksaas
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
title: MkSaaS 是什么?
|
title: MkSaaS 是什么?
|
||||||
description: MkSaaS 是构建 AI SaaS 网站的最佳样板。
|
description: MkSaaS 是构建 AI SaaS 网站的最佳样板。
|
||||||
image: /images/blog/mksaas-og.png
|
image: /images/blog/mksaas-og.png
|
||||||
date: 2024-11-24T12:00:00.000Z
|
date: 2024-11-26T12:00:00.000Z
|
||||||
published: true
|
published: true
|
||||||
categories: [news, guide]
|
categories: [news, guide]
|
||||||
author: mksaas
|
author: mksaas
|
||||||
|
@ -1,5 +1,25 @@
|
|||||||
|
import Container from '@/components/container';
|
||||||
|
import { HeaderSection } from '@/components/shared/header-section';
|
||||||
import { PropsWithChildren } from 'react';
|
import { PropsWithChildren } from 'react';
|
||||||
|
|
||||||
export default function BlogLayout({ children }: PropsWithChildren) {
|
export default async function BlogListLayout({
|
||||||
return children;
|
children,
|
||||||
}
|
}: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<div className="mb-16">
|
||||||
|
<div className="mt-8 w-full flex flex-col items-center justify-center gap-8">
|
||||||
|
<HeaderSection
|
||||||
|
titleAs="h2"
|
||||||
|
title="MkSaaS Blog"
|
||||||
|
subtitle="Read our latest blog posts about MkSaaS"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* <BlogCategoryFilter /> */}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Container className="mt-8 px-4">
|
||||||
|
{children}
|
||||||
|
</Container>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -36,20 +36,6 @@ export default async function BlogPage({ params }: BlogPageProps) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container className="py-8 md:py-12">
|
<BlogGrid posts={sortedPosts} />
|
||||||
<div className="">
|
|
||||||
<div className="flex flex-col items-start gap-4 md:flex-row md:justify-between md:gap-8">
|
|
||||||
<div className="flex-1 space-y-4">
|
|
||||||
<h1 className="inline-block text-4xl font-bold tracking-tight lg:text-5xl">
|
|
||||||
Blog
|
|
||||||
</h1>
|
|
||||||
<p className="text-xl text-muted-foreground">
|
|
||||||
Latest news and updates from our team
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<BlogGrid posts={sortedPosts} />
|
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -1,10 +1,9 @@
|
|||||||
import Container from '@/components/container';
|
import Container from '@/components/container';
|
||||||
import { Separator } from '@/components/ui/separator';
|
|
||||||
import { PropsWithChildren } from 'react';
|
import { PropsWithChildren } from 'react';
|
||||||
|
|
||||||
export default function BlogPostLayout({ children }: PropsWithChildren) {
|
export default function BlogPostLayout({ children }: PropsWithChildren) {
|
||||||
return (
|
return (
|
||||||
<Container className="py-8 md:py-12">
|
<Container className="py-8 px-4">
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
@ -92,9 +92,9 @@ export default async function BlogPostPage(props: NextPageProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-8">
|
<div className="flex flex-col gap-8">
|
||||||
{/* Content section */}
|
{/* content section */}
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||||
{/* Left column */}
|
{/* left column (blog post content) */}
|
||||||
<div className="lg:col-span-2 flex flex-col">
|
<div className="lg:col-span-2 flex flex-col">
|
||||||
{/* Basic information */}
|
{/* Basic information */}
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
@ -129,7 +129,7 @@ export default async function BlogPostPage(props: NextPageProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right column (sidebar) */}
|
{/* right column (sidebar) */}
|
||||||
<div>
|
<div>
|
||||||
<div className="space-y-4 lg:sticky lg:top-24">
|
<div className="space-y-4 lg:sticky lg:top-24">
|
||||||
{/* author info */}
|
{/* author info */}
|
||||||
@ -184,6 +184,9 @@ export default async function BlogPostPage(props: NextPageProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* newsletter */}
|
||||||
|
{/* TODO: add newsletter */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -71,9 +71,9 @@ export default function BlogCard({ post }: BlogCardProps) {
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
{/* Post excerpt, hidden for now */}
|
{/* Post excerpt, hidden for now */}
|
||||||
<div className="hidden">
|
<div className="">
|
||||||
{post.description && (
|
{post.description && (
|
||||||
<p className="mt-2 line-clamp-3 text-sm text-gray-500 dark:text-gray-400">
|
<p className="mt-2 line-clamp-2 text-sm text-gray-500 dark:text-gray-400">
|
||||||
<Link href={postUrl}>{post.description}</Link>
|
<Link href={postUrl}>{post.description}</Link>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
@ -83,7 +83,7 @@ export default function BlogCard({ post }: BlogCardProps) {
|
|||||||
{/* Author and date */}
|
{/* Author and date */}
|
||||||
<div className="mt-auto pt-4 flex items-center justify-between space-x-4 text-muted-foreground">
|
<div className="mt-auto pt-4 flex items-center justify-between space-x-4 text-muted-foreground">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div className="relative h-5 w-5 flex-shrink-0">
|
<div className="relative h-8 w-8 flex-shrink-0">
|
||||||
{post?.author?.avatar && (
|
{post?.author?.avatar && (
|
||||||
<Image
|
<Image
|
||||||
src={post?.author?.avatar}
|
src={post?.author?.avatar}
|
||||||
|
@ -11,7 +11,7 @@ export default function BlogGrid({ posts }: BlogGridProps) {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{posts?.length > 0 && (
|
{posts?.length > 0 && (
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-12">
|
||||||
{posts.map((post) => (
|
{posts.map((post) => (
|
||||||
<BlogCard key={post.slug} post={post} />
|
<BlogCard key={post.slug} post={post} />
|
||||||
))}
|
))}
|
||||||
@ -25,7 +25,7 @@ export function BlogGridSkeleton({
|
|||||||
count = POSTS_PER_PAGE,
|
count = POSTS_PER_PAGE,
|
||||||
}: { count?: number }) {
|
}: { count?: number }) {
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-12">
|
||||||
{[...Array(count)].map((_, index) => (
|
{[...Array(count)].map((_, index) => (
|
||||||
<BlogCardSkeleton key={index} />
|
<BlogCardSkeleton key={index} />
|
||||||
))}
|
))}
|
||||||
|
@ -45,7 +45,7 @@ export function HeaderSection({
|
|||||||
</TitleComponent>
|
</TitleComponent>
|
||||||
) : null}
|
) : null}
|
||||||
{subtitle ? (
|
{subtitle ? (
|
||||||
<SubtitleComponent className="text-balance text-lg text-foreground/80">
|
<SubtitleComponent className="text-balance text-lg text-muted-foreground">
|
||||||
{subtitle}
|
{subtitle}
|
||||||
</SubtitleComponent>
|
</SubtitleComponent>
|
||||||
) : null}
|
) : null}
|
||||||
|
Loading…
Reference in New Issue
Block a user