import dayjs from 'dayjs'
import Image from 'next/image'
import Link from 'next/link'
import type { PostReturnType, ProcessedBlogData, StaticAuthor, Tag } from 'types/post'
import { Badge, cn } from 'ui'
import { CTASection } from '../CTASection'
import SectionContainerWithCn from '../Layouts/SectionContainerWithCn'
import { BlogTableOfContents } from '@/components/Blog/BlogTableOfContents'
import DraftModeBanner from '@/components/Blog/DraftModeBanner'
import ShareArticleActions from '@/components/Blog/ShareArticleActions'
import BlogLinks from '@/components/LaunchWeek/7/BlogLinks'
import LW11Summary from '@/components/LaunchWeek/11/LW11Summary'
import LW12Summary from '@/components/LaunchWeek/12/LWSummary'
import LW13Summary from '@/components/LaunchWeek/13/Releases/LWSummary'
import LW14Summary from '@/components/LaunchWeek/14/Releases/LWSummary'
import LW15Summary from '@/components/LaunchWeek/15/LWSummary'
import LWXSummary from '@/components/LaunchWeek/X/LWXSummary'
import { MarkdownActions } from '@/components/MarkdownActions'
import { getBlogThumbnailImage } from '@/lib/blog-images'
import { compileBlogMdx } from '@/lib/mdx/compileBlogMdx'
import mdxComponents from '@/lib/mdx/mdxComponents'
type NextCardProps = {
post: { path: string; title: string; formattedDate: string }
label: string
className?: string
}
const NextCard = (props: NextCardProps) => {
const { post, label, className } = props
return (
{'title' in post && (
{(post as { title?: string }).title}
)}
{'formattedDate' in post && (
{(post as { formattedDate?: string }).formattedDate}
)}
)
}
const BlogPostRenderer = async ({
blog,
blogMetaData,
isDraftMode,
prevPost,
nextPost,
authors,
}: {
blog: ProcessedBlogData
blogMetaData: ProcessedBlogData
isDraftMode: boolean
prevPost?: PostReturnType | null
nextPost?: PostReturnType | null
authors: Array
}) => {
const mdxRendered = await compileBlogMdx(blog.content as string, mdxComponents('blog'))
const isLaunchWeek7 = blogMetaData.launchweek === '7'
const isLaunchWeekX = blogMetaData.launchweek?.toString().toLocaleLowerCase() === 'x'
const isGAWeek = blogMetaData.launchweek?.toString().toLocaleLowerCase() === '11'
const isLaunchWeek12 = blogMetaData.launchweek?.toString().toLocaleLowerCase() === '12'
const isLaunchWeek13 = blogMetaData.launchweek?.toString().toLocaleLowerCase() === '13'
const isLaunchWeek14 = blogMetaData.launchweek?.toString().toLocaleLowerCase() === '14'
const isLaunchWeek15 = blogMetaData.launchweek?.toString().toLocaleLowerCase() === '15'
type TocJsonItem = { content: string; slug: string; lvl: number }
const rawToc = blogMetaData.toc as unknown as { json?: TocJsonItem[] } | string | undefined
const tocItems =
rawToc && typeof rawToc !== 'string' && Array.isArray(rawToc.json)
? rawToc.json.map((h) => ({ title: h.content, url: `#${h.slug}`, depth: h.lvl }))
: []
const toc = tocItems.length > 0 ? : null
const imageUrl = getBlogThumbnailImage(blogMetaData, {
fallbackToPlaceholder: false,
})
const MARGIN_BOTTOM_CN = 'mb-12'
return (
<>
{isDraftMode && }
{/*
* Outer grid: back button | main container
*
* base/md : [back:1–12] stacked above [main:1–12]
* lg : [back:1–12] stacked above [main:2–12]
* xl : [back:1–2] alongside [main:3–12]
*/}
{/* Main container — indented 1 col at lg, alongside back button at xl */}
{/* Article header — spans the full main container width */}
Blog
{blogMetaData.categories && (
<>
/
{blogMetaData.categories[0]}
>
)}
{blogMetaData.title}
{dayjs(blogMetaData.date).format('D MMM YYYY')}
·
{(blogMetaData as any).readingTime}
{authors.length > 0 && (
{authors.map((author, i: number) => {
const authorImageUrl = author.author_image_url
const authorId =
(author as any).author_id ||
(author as any).username ||
author.author.toLowerCase().replace(/\s+/g, '_')
return (
{authorImageUrl && (
)}
{author.author}
{author.position}
)
})}
)}
{/*
* Inner grid: article body | sidebar
*
* base/md : single column, sidebar hidden
* lg+ : [body:7fr] [sidebar:3fr]
*/}
{/* Article body */}
{!blogMetaData.youtubeHero && blogMetaData.imgThumb && imageUrl && (
)}
{blogMetaData.youtubeHero ? (
) : null}
{mdxRendered}
{isLaunchWeek7 &&
}
{isLaunchWeekX &&
}
{isGAWeek &&
}
{isLaunchWeek12 &&
}
{isLaunchWeek13 &&
}
{isLaunchWeek14 &&
}
{isLaunchWeek15 &&
}
{prevPost && (
)}
{nextPost && (
)}
{/* Sidebar — only above lg */}
{(blogMetaData.tags as Tag[])?.length > 0 && (
{(blogMetaData.tags as Tag[])?.map((tag) => {
const tagName = typeof tag === 'string' ? tag : tag.name
const tagId = typeof tag === 'string' ? tag : tag.id.toString()
return (
{tagName}
)
})}
)}
>
)
}
export default BlogPostRenderer