feat(ui): update UI v1

This commit is contained in:
fatemeh sane
2026-09-25 22:49:30 +03:30
parent 805f4594d4
commit 853ad67db5
82 changed files with 10311 additions and 505 deletions
+61 -32
View File
@@ -1,60 +1,89 @@
import React from 'react'
import { Link } from 'react-router-dom'
import { ArrowLeftIcon } from 'lucide-react'
import { useStatusLabel } from '../api'
import { useLang } from '../i18n/lang'
import { PremiumButton } from './PremiumButton'
import type { StaticProject } from '../data/projectsData'
import type { ProjectCardItem } from '../data/site'
export function ProjectCard({ project }: any) {
type ProjectCardProps = {
project: StaticProject | ProjectCardItem;
imageUrl?: string;
detailHref?: string;
}
export function ProjectCard({ project, imageUrl, detailHref }: ProjectCardProps) {
const isOngoing = project.status === 'progress'
const statusText = useStatusLabel(project.status)
const { t, href, lang } = useLang()
const { t, lang } = useLang()
// Type guards for backward compatibility
const isStatic = 'name' in project;
// Resolve localized texts
const title = isStatic
? (project.name[lang as 'en' | 'fa'] || project.name.en)
: (project as ProjectCardItem).title;
const locRaw = isStatic ? project.location : (project as ProjectCardItem).location;
const location = typeof locRaw === 'string' ? locRaw : (locRaw?.[lang as 'en' | 'fa'] || locRaw?.en);
const areaRaw = isStatic ? project.area : (project as ProjectCardItem).area;
const area = typeof areaRaw === 'string' ? areaRaw : (areaRaw?.[lang as 'en' | 'fa'] || areaRaw?.en);
const finalImageUrl = imageUrl || (project as ProjectCardItem).image;
const finalDetailHref = detailHref || (project as ProjectCardItem).detailHref || '#';
const dotColor = isOngoing ? 'bg-copper animate-pulse' : 'bg-ivory/60'
const textColor = isOngoing ? 'text-copper' : 'text-ivory/90'
return (
<article className="group flex h-full flex-col overflow-hidden rounded-2xl border border-white/10 bg-char/85 backdrop-blur-xl shadow-[0_10px_30px_rgba(0,0,0,0.3)] transition-all duration-500 ease-lux hover:-translate-y-2 hover:border-copper/50 hover:shadow-[0_20px_40px_rgba(0,0,0,0.6),0_0_30px_rgba(197,143,92,0.2)] focus:outline-none focus-visible:ring-2 focus-visible:ring-copper">
<Link to={href(`/projects/${project.slug || '#'}`)} className="flex h-full flex-col focus:outline-none">
{/* کادر تصویر به همراه نشانگر وضعیت کپسولی و گوی دکمه شیشه‌ای */}
<div className="relative aspect-[4/3] w-full overflow-hidden">
<img
src={project.image}
alt={project.title}
className="h-full w-full object-cover transition-transform duration-700 ease-lux group-hover:scale-105"
/>
<Link to={finalDetailHref} className="flex flex-1 flex-col focus:outline-none">
{/* Fixed height image wrapper */}
<div className="relative w-full overflow-hidden">
{finalImageUrl && (
<img
src={finalImageUrl}
alt={title}
className="w-full h-[250px] object-cover transition-transform duration-700 ease-lux group-hover:scale-110"
/>
)}
{/* نشانگر وضعیت کپسولی شیشه‌ای */}
<div className={`absolute top-4 ltr:left-4 rtl:right-4 flex items-center gap-2 rounded-full border border-white/15 bg-ink/75 px-4 py-1.5 text-xs font-light backdrop-blur-xl shadow-[inset_0_1px_1px_rgba(255,255,255,0.2),0_4px_15px_rgba(0,0,0,0.4)] ${textColor}`}>
<div
className={`absolute top-4 ltr:left-4 rtl:right-4 flex items-center gap-2 rounded-full border border-white/15 bg-ink/75 px-4 py-1.5 text-xs font-light backdrop-blur-xl shadow-[inset_0_1px_1px_rgba(255,255,255,0.2),0_4px_15px_rgba(0,0,0,0.4)] ${textColor}`}
>
<span className={`h-2 w-2 rounded-full ${dotColor} ${isOngoing ? 'shadow-[0_0_10px_rgba(197,143,92,0.9)]' : ''}`} />
{statusText}
</div>
{/* گوی دکمه شیشه‌ای شناور برای ورود به پروژه */}
<div className="absolute bottom-4 ltr:right-4 rtl:left-4 flex h-11 w-11 items-center justify-center rounded-full border border-white/25 bg-ink/65 text-copper backdrop-blur-xl shadow-[inset_0_1px_1px_rgba(255,255,255,0.25),0_6px_20px_rgba(0,0,0,0.4)] transition-all duration-400 ease-lux group-hover:scale-110 group-hover:border-copper group-hover:bg-copper group-hover:text-char group-hover:shadow-[0_0_25px_rgba(197,143,92,0.6)]">
<ArrowLeftIcon className="h-5 w-5 ltr:-scale-x-100 transition-transform duration-300 rtl:group-hover:-translate-x-0.5 ltr:group-hover:translate-x-0.5" />
</div>
</div>
<div className="flex flex-1 flex-col p-7">
<div className="flex flex-1 flex-col p-7 pb-4">
<div className="text-center">
<h3 className="font-pinar text-xl font-bold text-ivory transition-colors duration-300 group-hover:text-copper">
{project.title}
{title}
</h3>
<p className="mt-4 text-sm font-light text-ivory/60">
{project.location}
</p>
{location && <p className="mt-4 text-sm font-light text-ivory/60">{location}</p>}
</div>
<div className="my-6 h-px w-full bg-white/10" />
<div className="mt-auto flex items-center justify-between text-sm font-light text-ivory/60">
<span>{t('yearLabel')} {project.year}</span>
{/* واحد زیربنا در محتوای انگلیسی داخل خود مقدار است — فقط در فارسی اضافه می‌شود */}
<span>{lang === 'fa' ? `${project.area} ${t('sqm')}` : project.area}</span>
</div>
{area && (
<>
<div className="my-6 h-px w-full bg-white/10" />
<div className="mt-auto flex items-center justify-end text-sm font-light text-ivory/60">
{/* واحد زیربنا در محتوای انگلیسی داخل خود مقدار است — فقط در فارسی اضافه می‌شود */}
<span>{lang === 'fa' ? `${area} ${t('sqm')}` : area}</span>
</div>
</>
)}
</div>
</Link>
{/* پایهٔ کارت: یک دکمه واحد */}
<div className="flex flex-col gap-2 px-7 pb-7">
<PremiumButton to={finalDetailHref} className="w-full">
{t('viewProject')}
</PremiumButton>
</div>
</article>
)
}
}