Initial deploy
هذا الالتزام موجود في:
103
components/project-card.tsx
Normal file
103
components/project-card.tsx
Normal file
@@ -0,0 +1,103 @@
|
||||
import Image from "next/image";
|
||||
|
||||
type ProjectCardProps = {
|
||||
project: {
|
||||
id: string;
|
||||
title: string;
|
||||
location: string;
|
||||
year: string;
|
||||
area: string;
|
||||
role: string;
|
||||
description: string;
|
||||
highlights: readonly string[];
|
||||
image: string;
|
||||
sheetImage?: string;
|
||||
imageAlt: string;
|
||||
};
|
||||
reverse?: boolean;
|
||||
priority?: boolean;
|
||||
labels?: {
|
||||
year: string;
|
||||
area: string;
|
||||
role: string;
|
||||
fullSheet: string;
|
||||
};
|
||||
};
|
||||
|
||||
export function ProjectCard({
|
||||
project,
|
||||
reverse = false,
|
||||
priority = false,
|
||||
labels,
|
||||
}: ProjectCardProps) {
|
||||
return (
|
||||
<article
|
||||
className={`project-card-shell grid gap-8 rounded-[34px] border p-4 md:p-5 lg:grid-cols-[0.78fr_1fr] lg:items-center lg:gap-14 ${
|
||||
reverse ? "lg:[&>*:first-child]:order-2 lg:[&>*:last-child]:order-1" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="image-frame mx-auto w-full max-w-[540px]">
|
||||
<div className="relative aspect-[3/5] overflow-hidden rounded-[26px]">
|
||||
<Image
|
||||
src={project.image}
|
||||
alt={project.imageAlt}
|
||||
fill
|
||||
sizes="(max-width: 1024px) 100vw, 540px"
|
||||
className="bg-white object-cover transition-transform duration-700 hover:scale-[1.03]"
|
||||
priority={priority}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col justify-center">
|
||||
<div className="type-label-wide flex flex-wrap items-center gap-x-3 gap-y-2 text-[var(--color-muted)] sm:flex-nowrap">
|
||||
<span>{project.id}</span>
|
||||
<span className="project-rule-line h-px w-12 shrink-0" />
|
||||
<span>{project.location}</span>
|
||||
</div>
|
||||
|
||||
<h3 className="type-project-title mt-5 text-[var(--color-ink)]">
|
||||
{project.title}
|
||||
</h3>
|
||||
<p className="type-body-responsive mt-5 max-w-xl text-[var(--color-muted)]">
|
||||
{project.description}
|
||||
</p>
|
||||
|
||||
<dl className="project-meta-list mt-8 grid gap-4 border-y py-6 sm:grid-cols-3">
|
||||
<div>
|
||||
<dt className="eyebrow-note">{labels?.year ?? "Year"}</dt>
|
||||
<dd className="type-body mt-2 font-semibold text-[var(--color-ink)]">{project.year}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="eyebrow-note">{labels?.area ?? "Area"}</dt>
|
||||
<dd className="type-body mt-2 font-semibold text-[var(--color-ink)]">{project.area}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="eyebrow-note">{labels?.role ?? "Role"}</dt>
|
||||
<dd className="type-body mt-2 font-semibold text-[var(--color-ink)]">{project.role}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
<ul className="type-chip mt-8 grid gap-3 text-[var(--color-muted)] sm:grid-cols-2">
|
||||
{project.highlights.map((highlight) => (
|
||||
<li key={highlight} className="flex items-center gap-3">
|
||||
<span className="h-2 w-2 rounded-full bg-[var(--color-blue-500)]" />
|
||||
<span>{highlight}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
{project.sheetImage ? (
|
||||
<a
|
||||
href={project.sheetImage}
|
||||
className="button-secondary mt-8 w-fit"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{labels?.fullSheet ?? "View full sheet"}
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
المرجع في مشكلة جديدة
حظر مستخدم