|
| 1 | +import { OrderedBlogGrid } from "@/components/blog"; |
1 | 2 | import type { ConfigContext } from "@/config"; |
2 | | -import { getCreationDate, type AppContext } from "@/lib/shared"; |
3 | | -import path from "node:path"; |
4 | | -import type { ComponentType, ReactNode } from "react"; |
| 3 | +import { cn } from "@/lib/cn"; |
| 4 | +import { joinPathname } from "@/lib/join-pathname"; |
| 5 | +import type { BlogIndexPage } from "@/plugins/blog"; |
| 6 | +import { buttonVariants } from "fumadocs-ui/components/ui/button"; |
| 7 | +import { ListIcon } from "lucide-react"; |
| 8 | +import type { ReactNode } from "react"; |
5 | 9 | import { Link } from "waku"; |
6 | 10 |
|
7 | 11 | export interface BlogIndexPageOptions { |
8 | 12 | heading?: ReactNode; |
9 | 13 | description?: ReactNode; |
10 | 14 | } |
11 | 15 |
|
12 | | -export type BlogIndexPage<C extends ConfigContext = ConfigContext> = ComponentType< |
13 | | - AppContext<C> & { |
14 | | - lang?: string; |
15 | | - indexPage: C["loaderConfig"]["page"]; |
16 | | - blogDir: string; |
17 | | - } |
18 | | ->; |
19 | | - |
20 | 16 | export function createBlogIndexPage<C extends ConfigContext = ConfigContext>({ |
21 | 17 | heading, |
22 | 18 | description, |
23 | 19 | }: BlogIndexPageOptions = {}): BlogIndexPage<C> { |
24 | | - return async function BlogIndexPage(props) { |
25 | | - const { lang, getLoader, indexPage, blogDir } = props; |
26 | | - const source = await getLoader(); |
27 | | - |
28 | | - const currentDate = new Date(Date.now()); |
29 | | - const postPromises: Promise<{ |
30 | | - page: C["loaderConfig"]["page"]; |
31 | | - date: Date; |
32 | | - }>[] = []; |
33 | | - for (const page of source.getPages(lang)) { |
34 | | - if (path.relative(blogDir, page.path).startsWith("..") || page === indexPage) continue; |
35 | | - const datePromise = Promise.resolve(getCreationDate(props, page)); |
36 | | - postPromises.push(datePromise.then((date) => ({ page, date: date ?? currentDate }))); |
37 | | - } |
38 | | - const posts = await Promise.all(postPromises); |
39 | | - |
40 | | - posts.sort((a, b) => b.date.getTime() - a.date.getTime()); |
| 20 | + return async function BlogIndexPage({ lang, blog, ctx }) { |
| 21 | + const source = await ctx.getLoader(); |
41 | 22 |
|
42 | 23 | return ( |
43 | 24 | <> |
44 | | - <div className="border-2 border-dashed border-fd-primary bg-fd-primary/10 p-4 z-2 md:p-8"> |
45 | | - <h1 className="text-3xl font-semibold">{heading ?? indexPage.data.title ?? "Blog"}</h1> |
46 | | - <p className="mt-4 text-fd-primary overline decoration-fd-primary empty:hidden"> |
47 | | - {description ?? indexPage.data.description} |
| 25 | + <div className="flex flex-col gap-4 items-start border-2 border-dashed border-fd-primary rounded-xl bg-fd-primary/10 p-4 z-2 md:p-8"> |
| 26 | + <h1 className="text-3xl font-semibold">{heading ?? "Blog"}</h1> |
| 27 | + <p className="text-fd-primary overline decoration-fd-primary empty:hidden"> |
| 28 | + {description} |
48 | 29 | </p> |
49 | | - </div> |
50 | | - |
51 | | - <div className="grid grid-cols-1 gap-2 mt-4 md:grid-cols-3 xl:grid-cols-4"> |
52 | | - {posts.map(({ page: post, date }) => ( |
| 30 | + {blog.tagsPath !== false && ( |
53 | 31 | <Link |
54 | | - key={post.url} |
55 | | - to={post.url} |
56 | | - className="flex flex-col bg-fd-card rounded-2xl border shadow-sm p-4 transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground" |
| 32 | + to={lang ? joinPathname(lang, blog.tagsPath) : blog.tagsPath} |
| 33 | + className={cn( |
| 34 | + buttonVariants({ |
| 35 | + variant: "primary", |
| 36 | + }), |
| 37 | + "gap-2", |
| 38 | + )} |
57 | 39 | > |
58 | | - <p className="font-medium">{post.data.title}</p> |
59 | | - <p className="text-sm text-fd-muted-foreground">{post.data.description}</p> |
60 | | - |
61 | | - <p className="mt-auto pt-4 text-xs text-fd-primary">{date.toDateString()}</p> |
| 40 | + <ListIcon className="size-4" /> |
| 41 | + All Tags |
62 | 42 | </Link> |
63 | | - ))} |
| 43 | + )} |
64 | 44 | </div> |
| 45 | + |
| 46 | + <OrderedBlogGrid |
| 47 | + posts={source.getPages(lang).filter((page) => blog.isBlog.call(ctx, page))} |
| 48 | + ctx={ctx} |
| 49 | + /> |
65 | 50 | </> |
66 | 51 | ); |
67 | 52 | }; |
|
0 commit comments