Files

173 lines
5.8 KiB
TypeScript
Raw Permalink Normal View History

"use client";
import { motion, useInView } from "framer-motion";
import { CornerDownRight } from "lucide-react";
import React, { useEffect, useRef, useState } from "react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
// Custom hook to get previous value
const usePrevious = <T,>(value: T): T | undefined => {
const [prev, setPrev] = useState<T | undefined>(undefined);
const ref = useRef(value);
useEffect(() => {
setPrev(ref.current);
ref.current = value;
}, [value]);
return prev;
};
interface Process2Props {
className?: string;
}
const Process2 = ({ className }: Process2Props) => {
const process = [
{
step: "۱",
title: "کشف و تحقیق",
image: "/block-media/shadcnblocks/block/guri4/img11.png",
description:
"با درک اهداف کسب‌وکار، مخاطب هدف و چالش‌های فعلی شما شروع می‌کنیم. این فاز شامل تحقیق، تحلیل و برنامه‌ریزی استراتژیک برای شناسایی فرصت‌هاست.",
},
{
step: "۲",
title: "استراتژی و برنامه‌ریزی",
image: "/block-media/shadcnblocks/block/guri4/img12.png",
description:
"بر اساس یافته‌ها، استراتژی جامعی متناسب با اهداف شما توسعه می‌دهیم. این شامل تعریف رویکرد، زمان‌بندی و نقاط عطف کلیدی برای موفقیت است.",
},
{
step: "۰۳",
title: "اجرا و توسعه",
image: "/block-media/shadcnblocks/block/guri4/img10.png",
description:
"استراتژی را از طریق پیاده‌سازی و توسعه دقیق به واقعیت تبدیل می‌کنیم. تیم ما به‌صورت همکاری کار می‌کند تا هر جزئیات با نیازها و استانداردهای شما هم‌خوان باشد.",
},
{
step: "۰۴",
title: "بهینه‌سازی و بهبود",
image: "/block-media/shadcnblocks/block/guri4/img9.png",
description:
"عملکرد را به‌طور مستمر پایش و بازخورد جمع‌آوری می‌کنیم تا راه‌حل را پالایش و بهبود دهیم. این فرآیند تکراری موفقیت و رشد بلندمدت را تضمین می‌کند.",
},
];
const [active, setActive] = useState<number>(0);
const previousActive = usePrevious(active);
return (
<section dir="rtl" lang="fa" className={cn("py-32", className)}>
<div className="container">
<div className="grid grid-cols-1 gap-5 lg:grid-cols-2 lg:gap-20">
<div className="top-10 h-fit w-fit gap-3 space-y-7 py-8 lg:sticky">
<h1 className="relative w-fit text-2xll font-semibold tracking-tight lg:text-2xll">
فرآیند ما
</h1>
<p className="text-start text-base text-foreground/50">
از کشف نیازهای شما تا تحویل نهایی، هر مرحله با دقت و شفافیت پیش
می‌رود تا بهترین نتیجه حاصل شود.
</p>
<div className="relative h-90 overflow-hidden border">
{previousActive !== undefined && (
<div className="absolute top-0 h-full w-full">
<img
src={process[previousActive].image}
className="h-full w-full object-cover"
alt={process[previousActive].title}
/>
</div>
)}
<motion.div
initial={{ clipPath: "inset(0% 0% 0% 100%)" }}
animate={{ clipPath: "inset(0% 0% 0% 0%)" }}
key={active}
transition={{
type: "spring",
stiffness: 150,
damping: 20,
}}
className="h-full w-full"
>
<img
src={process[active].image}
className="h-full w-full object-cover"
alt={process[active].title}
/>
</motion.div>
</div>
<Button
variant="ghost"
className="flex items-center justify-start gap-2"
>
<CornerDownRight className="text-orange-500 rtl:rotate-180" />
تماس بگیرید
</Button>
</div>
<ul className="relative w-full lg:ps-22">
{process.map((step, index) => (
<ProcessCard
key={index}
step={step}
index={index}
setActive={setActive}
/>
))}
</ul>
</div>
</div>
</section>
);
};
const ProcessCard = ({
step,
index,
setActive,
}: {
step: {
step: string;
title: string;
image: string;
description: string;
};
index: number;
setActive: (index: number) => void;
}) => {
const ref = useRef<HTMLLIElement>(null);
const itemInView = useInView(ref, {
amount: 0,
margin: "0px 0px -60% 0px",
});
useEffect(() => {
if (itemInView) {
setActive(index);
}
}, [itemInView, index, setActive]);
return (
<li
ref={ref}
key={index}
className="relative flex flex-col justify-between gap-12 border-b py-8 lg:py-16"
>
<div className="flex w-fit items-center justify-center px-4 py-1 text-9xl tracking-tighter">
{step.step}
</div>
<div>
<h3 className="mb-4 text-start text-xl font-semibold tracking-tighter lg:text-3xl">
{step.title}
</h3>
<p className="text-start text-foreground/50">{step.description}</p>
</div>
</li>
);
};
export { Process2 };