/* ============================================================================ ABOUT - /en/about and /ar/about ---------------------------------------------------------------------------- Section 1 of docs/SHARPER_Website_Draft_Section_EN_AR.docx: who SHARP-ER is, the three consortium members and their roles, the three focus areas, and the SHARP I / II legacy the project builds on. The draft copy is the fallback; every block here is overridden field by field by api::about-page.about-page as soon as an editor fills it in. ========================================================================= */ import { Link } from "react-router"; import { ArrowIcon, Button } from "~/components/ui/Button"; import { Card } from "~/components/ui/Card"; import { createTranslator, sectionPath } from "~/i18n"; import { buildBreadcrumbJsonLd, buildMeta } from "~/lib/seo"; import type { Route } from "./+types/about"; import { isRichTextBlock, type CmsAboutPage, } from "./_page-kit/cms-types"; import { list, loadSingle, toImage } from "./_page-kit/cms.server"; import { pageCopy } from "./_page-kit/copy"; import { routeLocale } from "./_page-kit/locale"; import { RichText } from "./_page-kit/rich-text"; import { InfoPanel, PageHero, PageSection, Prose, SectionHeader, } from "./_page-kit/sections"; export async function loader({ params }: Route.LoaderArgs) { const locale = routeLocale(params); const page = await loadSingle("about-page", { locale, populate: { hero: { populate: { media: true, ctas: true } }, consortium: { populate: { partner: { populate: { logo: true } } } }, pillars: true, legacyLink: true, blocks: { on: { "blocks.rich-text": { populate: "*" } } }, seo: { populate: { ogImage: true } }, }, }); return { locale, hero: { eyebrow: page?.hero?.eyebrow ?? null, headline: page?.hero?.headline ?? null, subheading: page?.hero?.subheading ?? null, media: toImage(page?.hero?.media, "large") ?? null, }, body: page?.body ?? null, richTextBlocks: list(page?.blocks) .filter(isRichTextBlock) .map((block) => ({ id: block.id, body: block.body })), pillars: list(page?.pillars).map((pillar) => ({ title: pillar.title, description: pillar.description ?? "", })), consortium: list(page?.consortium) .filter((member) => member.partner !== null && member.partner !== undefined) .map((member) => ({ id: member.partner?.documentId ?? String(member.id ?? member.partner?.id), name: member.partner?.name ?? "", role: member.roleDescription ?? member.partner?.description ?? "", website: member.partner?.website ?? null, })), legacy: { headline: page?.legacyHeadline ?? null, body: page?.legacyBody ?? null, link: page?.legacyLink ? { label: page.legacyLink.label, href: page.legacyLink.href, isExternal: page.legacyLink.isExternal ?? false, } : null, }, seo: { title: page?.seo?.metaTitle ?? null, description: page?.seo?.metaDescription ?? null, image: toImage(page?.seo?.ogImage, "large") ?? null, noIndex: page?.seo?.noIndex ?? false, }, }; } export function meta({ loaderData, matches }: Route.MetaArgs) { const root = matches[0].loaderData; const locale = loaderData?.locale ?? root.locale; const t = createTranslator(locale); const copy = pageCopy(locale).about; return buildMeta({ locale, pathname: root.pathname, siteUrl: root.siteUrl, title: loaderData?.seo.title ?? t("nav.sections.about"), description: loaderData?.seo.description ?? copy.lead, ...(loaderData?.seo.image ? { image: { url: loaderData.seo.image.src, alt: loaderData.seo.image.alt } } : {}), noIndex: loaderData?.seo.noIndex ?? false, jsonLd: buildBreadcrumbJsonLd(root.siteUrl, [ { name: t("nav.sections.home"), pathname: sectionPath("home", locale) }, { name: t("nav.sections.about"), pathname: sectionPath("about", locale) }, ]), }); } export default function About({ loaderData }: Route.ComponentProps) { const { locale, hero, body, richTextBlocks, legacy } = loaderData; const t = createTranslator(locale); const copy = pageCopy(locale).about; const whatWeDoCopy = pageCopy(locale).whatWeDo; const pillars = loaderData.pillars.length > 0 ? loaderData.pillars : copy.pillars; const consortium = loaderData.consortium.length > 0 ? loaderData.consortium : copy.consortium.map((member) => ({ id: member.name, name: member.name, role: member.role, website: null, })); return ( <> {body ? ( ) : (

{copy.body}

)} {richTextBlocks.map((block) => ( ))}

{copy.fundingNote}

{/* WHERE WE FOCUS */}
    {pillars.map((pillar) => (
  • {pillar.description}
  • ))}
{/* THE CONSORTIUM */}
    {consortium.map((member) => (
  • {member.role} {member.website ? ( {member.name} ) : null}
  • ))}
{/* SHARP I AND II */}
{legacy.body ? ( ) : (

{copy.legacyBody}

)}
{/* The draft marks the legacy page as "[link: …]" with no target yet, so the button appears only once the CMS supplies a real one. */} {legacy.link ? ( legacy.link.isExternal ? ( ) : ( ) ) : null}
); }