import type { Metadata } from "next"; import Link from "next/link"; import { notFound } from "next/navigation"; import { ContentPageShell } from "@/components/ContentPageShell"; import { HtmlContent } from "@/components/HtmlContent"; import { PortfolioGallery } from "@/components/PortfolioGallery"; import { PortfolioProjectLink } from "@/components/PortfolioProjectLink"; import { categoryLabelFa, findPortfolioCategory, getRootCategories, portfolioCategoryHref, topPortfolioCategories, type PortfolioCategory, } from "@/data/portfolioCategories"; import { ApiNotFoundError, formatFaDate, getPortfolio, getPortfolioCategories, getPortfolioCoverImage, } from "@/lib/api"; type PortfolioDetailPageProps = { params: Promise<{ slug: string }>; }; function mapApiCategories( items: Awaited>, ): PortfolioCategory[] { return items.map((item) => ({ id: String(item.id), slug: item.slug, nameEn: item.name, nameFa: item.nameFa || item.name, parentId: item.parentId, sortOrder: item.sortOrder ?? 0, })); } function findRootForCategory( categoryId: string | number | null | undefined, categories: PortfolioCategory[], ): PortfolioCategory | undefined { if (categoryId == null) return undefined; let current = categories.find((c) => c.id === String(categoryId)); if (!current) return undefined; while (current?.parentId) { const parent = categories.find((c) => c.id === String(current?.parentId)); if (!parent) break; current = parent; } return current; } export async function generateMetadata({ params, }: PortfolioDetailPageProps): Promise { const { slug } = await params; try { const portfolio = await getPortfolio(slug); const title = portfolio.titleFa || portfolio.title; return { title: `${title} | مشکی`, description: portfolio.abstract ?? undefined, }; } catch { return { title: "نمونه‌کار | مشکی" }; } } export default async function PortfolioDetailPage({ params, }: PortfolioDetailPageProps) { const { slug } = await params; let portfolio; try { portfolio = await getPortfolio(slug); } catch (error) { if (error instanceof ApiNotFoundError) notFound(); throw error; } const cover = getPortfolioCoverImage(portfolio); const date = formatFaDate(portfolio.publishedAt); const title = portfolio.titleFa || portfolio.title; let allCategories: PortfolioCategory[] = topPortfolioCategories; try { allCategories = mapApiCategories(await getPortfolioCategories()); } catch { allCategories = topPortfolioCategories; } const categoryFa = categoryLabelFa(portfolio.categoryName, allCategories); const rootCategory = findRootForCategory(portfolio.categoryId, allCategories) ?? findPortfolioCategory(portfolio.categoryName, getRootCategories(allCategories)); const gallery = (portfolio.gallery ?? []).filter( (item) => item.url !== cover, ); const titleEn = portfolio.titleEn ?? (portfolio.titleFa && portfolio.title !== portfolio.titleFa ? portfolio.title : null); const categoryHref = rootCategory ? portfolioCategoryHref(rootCategory.slug) : "/portfolio"; return (
{titleEn ? (

{titleEn}

) : null}

{title}

{portfolio.abstract ? (

{portfolio.abstract}

) : null}
({ id: item.mediaId, url: item.url, }))} category={categoryFa} date={date} dateTime={portfolio.publishedAt} /> {portfolio.mainTextHtml ? (
) : null}
{portfolio.projectUrl ? ( ) : null}
); }