import { listPublishedArtworks, listPublishedPortfolioGroups } from "@cms/db" import Image from "next/image" import { getTranslations } from "next-intl/server" import { Link } from "@/i18n/navigation" export const dynamic = "force-dynamic" type SearchParamsInput = Record type PortfolioPageProps = { searchParams: Promise } function readFirstValue(value: string | string[] | undefined): string | null { if (Array.isArray(value)) { return value[0] ?? null } return value ?? null } function resolveGroupFilter(searchParams: SearchParamsInput) { const gallery = readFirstValue(searchParams.gallery) if (gallery) { return { groupType: "gallery" as const, groupSlug: gallery } } const album = readFirstValue(searchParams.album) if (album) { return { groupType: "album" as const, groupSlug: album } } const category = readFirstValue(searchParams.category) if (category) { return { groupType: "category" as const, groupSlug: category } } const tag = readFirstValue(searchParams.tag) if (tag) { return { groupType: "tag" as const, groupSlug: tag } } return null } function resolveSort(searchParams: SearchParamsInput): "latest" | "title_asc" | "title_desc" { const sort = readFirstValue(searchParams.sort) if (sort === "title_asc" || sort === "title_desc") { return sort } return "latest" } function buildPortfolioQuery( filter: ReturnType, sort: ReturnType, ) { const query: Record = {} if (filter) { query[filter.groupType] = filter.groupSlug } if (sort !== "latest") { query.sort = sort } return query } function findPreviewAsset( renditions: Array<{ slot: string mediaAssetId: string mediaAsset: { id: string altText: string | null title: string } }>, ) { const byPreference = renditions.find((item) => item.slot === "card") ?? renditions.find((item) => item.slot === "thumbnail") ?? renditions.find((item) => item.slot === "full") ?? renditions[0] return byPreference ?? null } export default async function PortfolioPage({ searchParams }: PortfolioPageProps) { const [resolvedSearchParams, t] = await Promise.all([searchParams, getTranslations("Portfolio")]) const activeFilter = resolveGroupFilter(resolvedSearchParams) const activeSort = resolveSort(resolvedSearchParams) const [groups, artworks] = await Promise.all([ listPublishedPortfolioGroups(), listPublishedArtworks( activeFilter ? { groupType: activeFilter.groupType, groupSlug: activeFilter.groupSlug, sort: activeSort, } : { sort: activeSort, }, ), ]) return (

{t("badge")}

{t("title")}

{t("description")}

{t("filters.clear")} {groups.galleries.map((group) => ( {t("filters.gallery")}: {group.name} ))} {groups.albums.map((group) => ( {t("filters.album")}: {group.name} ))} {groups.categories.map((group) => ( {t("filters.category")}: {group.name} ))} {groups.tags.map((group) => ( {t("filters.tag")}: {group.name} ))}
{t("sort.label")}: {t("sort.latest")} {t("sort.titleAsc")} {t("sort.titleDesc")}
{artworks.length === 0 ? (
{t("empty")}
) : (
{artworks.map((artwork) => { const preview = findPreviewAsset(artwork.renditions) return (
{preview ? ( {preview.mediaAsset.altText ) : (
{t("noPreview")}
)}

{artwork.title}

{artwork.description || t("noDescription")}

{t("viewArtwork")}
) })}
)}
) }