136 lines
6.5 KiB
TypeScript
136 lines
6.5 KiB
TypeScript
"use client";
|
|
|
|
import { motion } from "framer-motion";
|
|
import Image from "next/image";
|
|
|
|
// دیتای تستی پروژهها (میتوانید با دیتای واقعی جایگزین کنید)
|
|
const projects = [
|
|
{
|
|
id: 1,
|
|
title: "سیستم مدیریت مالی فراز",
|
|
category: "نرمافزار سازمانی",
|
|
description: "یک پلتفرم یکپارچه برای مدیریت منابع مالی سازمانها با داشبوردهای تحلیلی در لحظه.",
|
|
image: "/project-1.jpg", // این عکسها را در پوشه public قرار دهید
|
|
color: "from-blue-500/20 to-purple-500/20",
|
|
},
|
|
{
|
|
id: 2,
|
|
title: "اپلیکیشن سلامتجو",
|
|
category: "اپلیکیشن موبایل",
|
|
description: "سیستم نوبتدهی و پایش سلامت بیماران با قابلیت یکپارچهسازی با گجتهای پوشیدنی.",
|
|
image: "/project-2.jpg",
|
|
color: "from-emerald-500/20 to-teal-500/20",
|
|
},
|
|
{
|
|
id: 3,
|
|
title: "پلتفرم فروشگاهی نوینشاپ",
|
|
category: "تجارت الکترونیک",
|
|
description: "فروشگاهساز ابری با معماری میکروسرویس و قابلیت مقیاسپذیری بالا برای ترافیکهای سنگین.",
|
|
image: "/project-3.jpg",
|
|
color: "from-orange-500/20 to-red-500/20",
|
|
},
|
|
{
|
|
id: 4,
|
|
title: "اتوماسیون اداری هوشمند",
|
|
category: "هوش مصنوعی",
|
|
description: "سامانه اتوماسیون مبتنی بر هوش مصنوعی برای دستهبندی خودکار نامهها و ارجاعات.",
|
|
image: "/project-4.jpg",
|
|
color: "from-indigo-500/20 to-blue-500/20",
|
|
},
|
|
];
|
|
|
|
// منحنی انیمیشن لوکس (همان که در Hero استفاده کردیم)
|
|
const customEase: [number, number, number, number] = [0.16, 1, 0.3, 1];
|
|
|
|
export default function Projects() {
|
|
return (
|
|
<section
|
|
className="relative min-h-screen py-32 flex flex-col items-center justify-center overflow-hidden bg-gray-950"
|
|
onMouseMove={(e) => {
|
|
const { currentTarget, clientX, clientY } = e;
|
|
const { left, top } = currentTarget.getBoundingClientRect();
|
|
currentTarget.style.setProperty("--mouse-x", `${clientX - left}px`);
|
|
currentTarget.style.setProperty("--mouse-y", `${clientY - top}px`);
|
|
}}
|
|
>
|
|
{/* افکت Spotlight و Grid (دقیقا مشابه Hero) */}
|
|
<div className="pointer-events-none absolute -inset-px opacity-50 before:absolute before:inset-0 before:bg-[radial-gradient(800px_circle_at_var(--mouse-x)_var(--mouse-y),rgba(255,255,255,0.06),transparent_40%)]" />
|
|
<div className="pointer-events-none absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px]" />
|
|
|
|
<div className="z-10 w-full max-w-7xl mx-auto px-4 md:px-8">
|
|
{/* هدر بخش پروژهها */}
|
|
<div className="mb-20 md:mb-32">
|
|
<motion.h2
|
|
initial={{ opacity: 0, y: 20 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true, margin: "-100px" }}
|
|
transition={{ duration: 1, ease: customEase }}
|
|
className="text-4xl md:text-6xl font-bold tracking-tight text-white mb-6"
|
|
>
|
|
خلق تجربههای <span className="text-neutral-500">ماندگار.</span>
|
|
</motion.h2>
|
|
<motion.p
|
|
initial={{ opacity: 0, y: 20 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true, margin: "-100px" }}
|
|
transition={{ duration: 1, delay: 0.1, ease: customEase }}
|
|
className="text-lg md:text-xl text-neutral-400 max-w-2xl"
|
|
>
|
|
برخی از پروژههای منتخب ما که با تمرکز بر کارایی، زیبایی و معماری قدرتمند توسعه یافتهاند.
|
|
</motion.p>
|
|
</div>
|
|
|
|
{/* گرید پروژهها */}
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 md:gap-8">
|
|
{projects.map((project, index) => (
|
|
<motion.div
|
|
key={project.id}
|
|
initial={{ opacity: 0, y: 40 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true, margin: "-100px" }}
|
|
transition={{
|
|
duration: 1.2,
|
|
delay: index * 0.15, // انیمیشن آبشاری برای کارتها
|
|
ease: customEase,
|
|
}}
|
|
className="group relative rounded-3xl bg-neutral-900/50 border border-white/5 overflow-hidden backdrop-blur-sm transition-colors hover:bg-neutral-900/80"
|
|
>
|
|
{/* بخش تصویر (بالای کارت) */}
|
|
<div className={`relative h-64 md:h-80 w-full overflow-hidden bg-gradient-to-br ${project.color}`}>
|
|
{/*
|
|
نکته: برای استفاده از Image در Next.js، کامنت زیر را بردارید و عکسها را در فولدر public بگذارید.
|
|
در اینجا موقتاً از یک گرادیانت به عنوان جایگزین عکس استفاده شده است تا خطا نگیرید.
|
|
*/}
|
|
{/* <Image
|
|
src={project.image}
|
|
alt={project.title}
|
|
fill
|
|
className="object-cover object-center transition-transform duration-700 group-hover:scale-105"
|
|
/> */}
|
|
|
|
{/* یک المان تزئینی به جای عکس واقعی (موقتی) */}
|
|
<div className="absolute inset-0 flex items-center justify-center text-white/20 font-bold text-3xl transition-transform duration-700 group-hover:scale-105">
|
|
تصویر پروژه
|
|
</div>
|
|
</div>
|
|
|
|
{/* بخش محتوا (پایین کارت) */}
|
|
<div className="p-8">
|
|
<div className="text-xs font-semibold tracking-wider text-neutral-500 mb-3 uppercase">
|
|
{project.category}
|
|
</div>
|
|
<h3 className="text-2xl font-bold text-neutral-100 mb-3 group-hover:text-white transition-colors">
|
|
{project.title}
|
|
</h3>
|
|
<p className="text-neutral-400 leading-relaxed text-sm md:text-base">
|
|
{project.description}
|
|
</p>
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|