Files
sass-mohfarawati/app/[locale]/(site)/about/page.tsx
T
2026-08-06 02:27:49 +02:00

150 lines
5.2 KiB
TypeScript

import type { Metadata } from "next";
import { getLocale, getTranslations } from "next-intl/server";
import { Container } from "@/components/layout/container";
import { PageHero } from "@/components/layout/page-hero";
import { MotionFade } from "@/components/motion-fade";
import { AppCard } from "@/components/ui/app-card";
import { Badge } from "@/components/ui/badge";
import { CapabilitiesSection } from "@/components/home/capabilities-section";
import { ProcessSection } from "@/components/home/process-section";
import { ContactCtaSection } from "@/components/home/contact-cta-section";
import type {
CapabilitiesSectionCopy,
ContactCtaSectionCopy,
ProcessSectionCopy,
} from "@/components/home/types";
import { getSiteSettings } from "@/lib/app-config";
import { getLocalizedPath, resolveLocale } from "@/lib/locale";
import { buildLocalizedMetadata } from "@/lib/metadata";
type AboutPageProps = {
params: Promise<{
locale: string;
}>;
};
export const dynamic = "force-dynamic";
export async function generateMetadata({ params }: AboutPageProps): Promise<Metadata> {
await params;
const siteSettings = await getSiteSettings();
const localeKey = resolveLocale(await getLocale().catch(() => siteSettings.defaultLocale), siteSettings.defaultLocale);
const t = await getTranslations({ locale: localeKey, namespace: "aboutPage" });
return await buildLocalizedMetadata({
locale: localeKey,
pathname: "/about",
title: t("title"),
description: t("description"),
});
}
export default async function AboutPage({ params }: AboutPageProps) {
await params;
const siteSettings = await getSiteSettings();
const localeKey = resolveLocale(await getLocale().catch(() => siteSettings.defaultLocale), siteSettings.defaultLocale);
const t = await getTranslations({ locale: localeKey, namespace: "aboutPage" });
const contactHref = getLocalizedPath(localeKey, "/contact", siteSettings.defaultLocale);
const capabilitiesCopy: CapabilitiesSectionCopy = {
eyebrow: t("capabilities.eyebrow"),
title: t("capabilities.title"),
description: t("capabilities.description"),
items: t.raw("capabilities.items") as CapabilitiesSectionCopy["items"],
};
const processCopy: ProcessSectionCopy = {
eyebrow: t("process.eyebrow"),
title: t("process.title"),
description: t("process.description"),
steps: t.raw("process.steps") as ProcessSectionCopy["steps"],
};
const contactCtaCopy: ContactCtaSectionCopy = {
eyebrow: t("contactCta.eyebrow"),
title: t("contactCta.title"),
description: t("contactCta.description"),
contactCta: t("contactCta.contactCta"),
githubCta: t("contactCta.githubCta"),
emailLabel: t("contactCta.emailLabel"),
emailValue: t("contactCta.emailValue"),
availabilityLabel: t("contactCta.availabilityLabel"),
availabilityValue: t("contactCta.availabilityValue"),
githubHref: t("contactCta.githubHref"),
};
const storyParagraphs = t.raw("story.paragraphs") as string[];
const toolItems = t.raw("tools.items") as string[];
return (
<>
<PageHero
locale={localeKey}
badge={t("heroEyebrow")}
title={t("title")}
description={t("description")}
/>
<Container className="flex flex-col gap-16 pb-16 sm:gap-20 lg:gap-24 lg:pb-20">
<MotionFade>
<section className="mx-auto max-w-3xl space-y-6">
<p className="eyebrow text-caption font-medium text-brand-primary">
{t("story.eyebrow")}
</p>
<h2 className="text-balance text-h2 text-foreground">{t("story.title")}</h2>
<div className="space-y-4">
{storyParagraphs.map((paragraph) => (
<p key={paragraph} className="text-body-lg text-muted-foreground">
{paragraph}
</p>
))}
</div>
</section>
</MotionFade>
<MotionFade delay={0.06}>
<CapabilitiesSection copy={capabilitiesCopy} />
</MotionFade>
<MotionFade delay={0.08}>
<AppCard padding="lg">
<div className="space-y-5">
<div className="space-y-2">
<p className="eyebrow text-caption font-medium text-brand-primary">
{t("tools.eyebrow")}
</p>
<h3 className="text-title font-semibold text-foreground">{t("tools.title")}</h3>
</div>
<div className="flex flex-wrap gap-2">
{toolItems.map((tool) => (
<Badge key={tool} variant="secondary">
{tool}
</Badge>
))}
</div>
</div>
</AppCard>
</MotionFade>
<MotionFade delay={0.1}>
<ProcessSection copy={processCopy} />
</MotionFade>
<MotionFade delay={0.12}>
<p className="mx-auto max-w-2xl text-center text-small text-muted-foreground">
<span className="text-brand-primary">{t("personalNote.eyebrow")}</span>
{" — "}
{t("personalNote.text")}
</p>
</MotionFade>
<MotionFade delay={0.14}>
<ContactCtaSection copy={contactCtaCopy} contactHref={contactHref} />
</MotionFade>
</Container>
</>
);
}