52 lines
2.0 KiB
TypeScript
52 lines
2.0 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 { getProjectPath } from "@/lib/project-content";
|
|
|
|
type ProjectCardProps = {
|
|
locale: Locale;
|
|
type: ProjectType;
|
|
project: {
|
|
slug: string;
|
|
titleAr: string;
|
|
titleEn: string;
|
|
summaryAr: string | null;
|
|
summaryEn: string | null;
|
|
coverImage: string | null;
|
|
category: { nameAr: string; nameEn: string } | null;
|
|
};
|
|
};
|
|
|
|
export default function ProjectCard({ locale, type, project }: ProjectCardProps) {
|
|
const title = locale === "ar" ? project.titleAr : project.titleEn;
|
|
const summary = locale === "ar" ? project.summaryAr : project.summaryEn;
|
|
const category = project.category ? (locale === "ar" ? project.category.nameAr : project.category.nameEn) : null;
|
|
|
|
return (
|
|
<article className="group overflow-hidden rounded-xl border border-border bg-card shadow-sm transition-transform hover:-translate-y-1">
|
|
<Link href={getProjectPath(locale, type, project.slug)} className="block">
|
|
<div className="relative aspect-[16/10] overflow-hidden bg-muted">
|
|
{project.coverImage ? (
|
|
<Image
|
|
src={project.coverImage}
|
|
alt={title}
|
|
fill
|
|
unoptimized
|
|
sizes="(max-width: 768px) 100vw, 33vw"
|
|
className="object-cover transition-transform duration-300 group-hover:scale-105"
|
|
/>
|
|
) : (
|
|
<div className="flex h-full items-center justify-center text-sm text-muted-foreground">{title}</div>
|
|
)}
|
|
</div>
|
|
<div className="space-y-2 p-5">
|
|
{category ? <p className="text-xs font-semibold uppercase tracking-[0.14em] text-brand-2">{category}</p> : null}
|
|
<h2 className="text-xl font-semibold tracking-tight">{title}</h2>
|
|
{summary ? <p className="text-sm leading-6 text-muted-foreground">{summary}</p> : null}
|
|
</div>
|
|
</Link>
|
|
</article>
|
|
);
|
|
}
|