From f424225abc1ecae4eebbda9a2a3c0ba958f48f73 Mon Sep 17 00:00:00 2001 From: Amirhossein Khalili Date: Thu, 11 Jun 2026 21:21:52 +0330 Subject: [PATCH] feat(blog): refresh post detail layout --- src/app/blog/[slug]/page.tsx | 196 +++++++++++++++---------- src/components/BlogPostActions.tsx | 11 +- src/components/BlogTableOfContents.tsx | 75 ++++++++++ 3 files changed, 196 insertions(+), 86 deletions(-) create mode 100644 src/components/BlogTableOfContents.tsx diff --git a/src/app/blog/[slug]/page.tsx b/src/app/blog/[slug]/page.tsx index 48c2752..7b2913f 100644 --- a/src/app/blog/[slug]/page.tsx +++ b/src/app/blog/[slug]/page.tsx @@ -1,20 +1,23 @@ import type { Metadata } from "next"; import { notFound } from "next/navigation"; +import { CalendarDays, Clock3, Hash, ListTree } from "lucide-react"; import BlogPostActions from "@/components/BlogPostActions"; import BlogPostInteractions from "@/components/BlogPostInteractions"; +import BlogTableOfContents from "@/components/BlogTableOfContents"; import BlogThumbnail from "@/components/BlogThumbnail"; import Markdown from "@/components/Markdown"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Badge } from "@/components/ui/badge"; -import { Button } from "@/components/ui/button"; import { Link } from "@/lib/router"; import { blogPostPath, blogPostUrl, normalizeBlogSlugParam } from "@/lib/blog-routes"; -import { extractMarkdownHeadings, type MarkdownHeading } from "@/lib/markdown-headings"; +import { extractMarkdownHeadings } from "@/lib/markdown-headings"; import { PublicApiError, getPublicPost, getRecommendedPosts } from "@/lib/public-api"; import { apiBaseUrl, siteUrl, toAbsoluteUrl } from "@/lib/site"; import type * as Types from "@/lib/types"; -import { formatJalaliDate, getBlogCardImageUrl, getBlogHeroImageUrl } from "@/lib/utils"; +import { formatJalaliDate, getBlogCardImageUrl, getBlogHeroImageUrl, toPersianDigits } from "@/lib/utils"; type Params = Promise<{ slug: string }>; +type Writer = NonNullable[number]; export const dynamic = "force-dynamic"; @@ -23,8 +26,8 @@ function cleanText(value?: string | null) { return value.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim(); } -function authorName(post: Types.PostListSchema) { - return [post.author.first_name, post.author.last_name].filter(Boolean).join(" ") || post.author.username; +function personName(person: { first_name: string; last_name: string; username: string }) { + return [person.first_name, person.last_name].filter(Boolean).join(" ") || person.username; } async function loadPost(slug: string) { @@ -46,40 +49,79 @@ async function loadRecommended(slug: string) { } } -function TableOfContents({ headings }: { headings: MarkdownHeading[] }) { - if (!headings.length) { - return

برای این نوشته فهرست تیترها ثبت نشده است.

; +function Topics({ tags }: { tags: Types.PostListSchema["tags"] }) { + if (!tags.length) { + return null; } return ( -