Files

137 lines
6.5 KiB
TypeScript

import Image from "next/image";
import Link from "next/link";
import type { ProjectType } from "@prisma/client";
import type { Locale } from "@/lib/i18n";
import { getProjectDirectoryCopy, getProjectPath } from "@/lib/project-content";
import AnalyticsTracker from "@/components/public/analytics-tracker";
import TrackedLink from "@/components/public/tracked-link";
type ProjectDetailProps = {
locale: Locale;
type: ProjectType;
project: {
id: string;
slug: string;
titleAr: string;
titleEn: string;
descAr: string | null;
descEn: string | null;
summaryAr: string | null;
summaryEn: string | null;
coverImage: string | null;
images: string[];
technologies: string[];
externalUrl: string | null;
repoUrl: string | null;
platform: string | null;
appStoreUrl: string | null;
testflightUrl: string | null;
appVersion: string | null;
supportUrl: string | null;
appPrivacyUrl: string | null;
category: { nameAr: string; nameEn: string } | null;
};
};
export default function ProjectDetail({ locale, type, project }: ProjectDetailProps) {
const title = locale === "ar" ? project.titleAr : project.titleEn;
const summary = locale === "ar" ? project.summaryAr : project.summaryEn;
const description = locale === "ar" ? project.descAr : project.descEn;
const category = project.category ? (locale === "ar" ? project.category.nameAr : project.category.nameEn) : null;
const copy = getProjectDirectoryCopy(locale, type);
const backLabel = locale === "ar" ? `العودة إلى ${copy.eyebrow}` : `Back to ${copy.eyebrow}`;
const isApp = type === "APP";
return (
<article className="mx-auto w-full max-w-6xl space-y-10 px-4 py-10 sm:px-6 lg:px-8">
<AnalyticsTracker event="PROJECT_OPEN" entityId={project.id} />
<Link href={getProjectPath(locale, type)} className="text-sm font-medium text-brand-2 hover:underline">
{backLabel}
</Link>
<header className="max-w-3xl space-y-4">
{category ? <p className="text-sm font-semibold uppercase tracking-[0.18em] text-brand-2">{category}</p> : null}
<h1 className="text-4xl font-semibold tracking-tight sm:text-6xl">{title}</h1>
{summary ? <p className="text-xl leading-8 text-muted-foreground">{summary}</p> : null}
</header>
{project.coverImage ? (
<div className="relative aspect-[16/8] overflow-hidden rounded-2xl border border-border bg-muted">
<Image src={project.coverImage} alt={title} fill unoptimized sizes="100vw" className="object-cover" priority />
</div>
) : null}
<div className="grid gap-10 lg:grid-cols-[minmax(0,1fr)_18rem]">
<div className="space-y-8">
{description ? <p className="whitespace-pre-line text-lg leading-8 text-foreground">{description}</p> : null}
{project.images.length > 0 ? (
<div className="grid gap-4 sm:grid-cols-2">
{project.images.map((image, index) => (
<div key={image} className="relative aspect-[4/3] overflow-hidden rounded-xl border border-border bg-muted">
<Image src={image} alt={`${title} ${index + 1}`} fill unoptimized sizes="(max-width: 640px) 100vw, 50vw" className="object-cover" />
</div>
))}
</div>
) : null}
</div>
<aside className="space-y-6 rounded-xl border border-border bg-card p-5">
{project.technologies.length > 0 ? (
<div>
<h2 className="text-sm font-semibold">{locale === "ar" ? "التقنيات" : "Technologies"}</h2>
<div className="mt-3 flex flex-wrap gap-2">
{project.technologies.map((technology) => (
<span key={technology} className="rounded-full border border-border px-3 py-1 text-xs text-muted-foreground">
{technology}
</span>
))}
</div>
</div>
) : null}
{isApp ? (
<div className="space-y-3 border-t border-border pt-5 text-sm">
<h2 className="font-semibold">{locale === "ar" ? "تفاصيل التطبيق" : "App details"}</h2>
{project.platform ? <p className="text-muted-foreground">{project.platform}</p> : null}
{project.appVersion ? <p className="text-muted-foreground">{locale === "ar" ? "الإصدار" : "Version"}: {project.appVersion}</p> : null}
</div>
) : null}
<div className="flex flex-col gap-3 text-sm">
{project.externalUrl ? (
<TrackedLink href={project.externalUrl} target="_blank" rel="noreferrer" className="font-medium text-brand-2 hover:underline" entityId={project.id}>
{locale === "ar" ? "فتح الرابط" : "Open live link"}
</TrackedLink>
) : null}
{project.repoUrl ? (
<TrackedLink href={project.repoUrl} target="_blank" rel="noreferrer" className="font-medium text-brand-2 hover:underline" entityId={project.id}>
{locale === "ar" ? "مستودع GitHub" : "Open repository"}
</TrackedLink>
) : null}
{project.appStoreUrl ? (
<TrackedLink href={project.appStoreUrl} target="_blank" rel="noreferrer" className="font-medium text-brand-2 hover:underline" entityId={project.id}>
{locale === "ar" ? "فتح App Store" : "Open App Store"}
</TrackedLink>
) : null}
{project.testflightUrl ? (
<TrackedLink href={project.testflightUrl} target="_blank" rel="noreferrer" className="font-medium text-brand-2 hover:underline" entityId={project.id}>
{locale === "ar" ? "فتح TestFlight" : "Open TestFlight"}
</TrackedLink>
) : null}
{project.supportUrl ? (
<TrackedLink href={project.supportUrl} target="_blank" rel="noreferrer" className="font-medium text-brand-2 hover:underline" entityId={project.id}>
{locale === "ar" ? "رابط الدعم" : "Support link"}
</TrackedLink>
) : null}
{project.appPrivacyUrl ? (
<TrackedLink href={project.appPrivacyUrl} target="_blank" rel="noreferrer" className="font-medium text-brand-2 hover:underline" entityId={project.id}>
{locale === "ar" ? "سياسة الخصوصية" : "Privacy policy"}
</TrackedLink>
) : null}
</div>
</aside>
</div>
</article>
);
}