import { ArrowUpRight, CalendarDays, FolderKanban, Tag, UserRound, } from "lucide-react"; import Image from "next/image"; import Link from "next/link"; import { MotionFade } from "@/components/motion-fade"; import { AppCard } from "@/components/ui/app-card"; import { Button } from "@/components/ui/button"; import { CardContent } from "@/components/ui/card"; import { getLocalizedPath, type AppLocale } from "@/lib/locale"; import { getLocalizedValue, resolvePortfolioProjectViewMode, type PortfolioAssetView, type PortfolioProjectView, type PortfolioSectionView, } from "@/lib/portfolio"; type PortfolioProjectDetailProps = { item: PortfolioProjectView; locale: AppLocale; defaultLocale: AppLocale; t: (key: "back" | "preview" | "openLink" | "gallery" | "download") => string; }; function PortfolioImage({ src, alt, className, width, height, }: { src: string; alt: string; className: string; width: number; height: number; }) { return ( {alt} ); } function ProjectMeta({ item, locale, }: { item: PortfolioProjectView; locale: AppLocale; }) { const metadata = [ { icon: Tag, label: getLocalizedValue(item.category.name, locale), }, { icon: CalendarDays, label: String(item.projectYear), }, { icon: FolderKanban, label: getLocalizedValue(item.serviceLabel, locale), }, { icon: UserRound, label: item.clientName, }, ].filter((entry) => entry.label); return (
{metadata.map((meta) => { const Icon = meta.icon; return ( {meta.label} ); })}
); } function SectionBlock({ section, locale, t, }: { section: PortfolioSectionView; locale: AppLocale; t: PortfolioProjectDetailProps["t"]; }) { const title = getLocalizedValue(section.title, locale); const body = getLocalizedValue(section.body, locale); if (section.type === "GALLERY") { return (

{title}

{section.imagePath ? ( ) : null}
); } if (section.type === "LINK") { return (

{title}

{body ?

{body}

: null} {section.linkUrl ? ( ) : null}
); } return (

{title}

{body}

); } function AssetGallery({ assets, locale, t, }: { assets: PortfolioAssetView[]; locale: AppLocale; t: PortfolioProjectDetailProps["t"]; }) { if (assets.length === 0) { return null; } return (

Assets

{t("gallery")}

{assets.map((asset) => (
{asset.kind === "IMAGE" ? ( ) : (

{getLocalizedValue(asset.alt, locale)}

)}
))}
); } function BadgeCount({ count }: { count: number }) { return (
{count} {count === 1 ? "file" : "files"}
); } function ProjectHeader({ item, locale, defaultLocale, t, }: { item: PortfolioProjectView; locale: AppLocale; defaultLocale: AppLocale; t: PortfolioProjectDetailProps["t"]; }) { return (

{getLocalizedValue(item.title, locale)}

{getLocalizedValue(item.summary, locale)}

{item.previewUrl ? (
) : null}
); } function GridTemplate({ item, locale, defaultLocale, t, }: PortfolioProjectDetailProps) { return (
{item.coverImagePath ? ( ) : null}
{item.sections.map((section, index) => ( ))}
); } function StoryTemplate({ item, locale, defaultLocale, t, }: PortfolioProjectDetailProps) { return (
{item.coverImagePath ? (
) : null}
{item.sections.map((section, index) => (
{String(index + 1).padStart(2, "0")}
))}
); } function CaseStudyTemplate({ item, locale, defaultLocale, t, }: PortfolioProjectDetailProps) { const [challenge, solution, outcome, ...restSections] = item.sections; const leadSections = [challenge, solution, outcome].filter( (section): section is PortfolioSectionView => Boolean(section), ); return (
{item.coverImagePath ? ( ) : null} {leadSections.map((section, index) => (

{index === 0 ? "Challenge" : index === 1 ? "Solution" : "Outcome"}

))}

Case Study Snapshot

{getLocalizedValue(item.title, locale)}

{getLocalizedValue(item.summary, locale)}

{restSections.length > 0 ? (
{restSections.map((section, index) => ( ))}
) : null}
); } export function PortfolioProjectDetail({ item, locale, defaultLocale, t, }: PortfolioProjectDetailProps) { const viewMode = resolvePortfolioProjectViewMode(item.viewMode); if (viewMode === "STORY") { return ; } if (viewMode === "CASE_STUDY") { return ; } return ; }