Files
reui-blocks/blocks/services21.tsx
T

142 lines
5.5 KiB
TypeScript
Raw Normal View History

"use client";
import { motion } from "framer-motion";
import { ArrowUpRight } from "lucide-react";
import React, { useEffect, useRef, useState } from "react";
import { BorderButton } from "@/components/shadcnblocks/border-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 Services21Props {
className?: string;
}
const Services21 = ({ className }: Services21Props) => {
const services = [
{
id: "{۱}",
title: "کشف و ممیزی",
image: "/block-media/shadcnblocks/block/guri4/img11.png",
description:
"قیف، داده و فرآیند فعلی را بررسی می‌کنیم تا گلوگاه‌های جذب، تبدیل و نگهداشت مشخص شوند و اولویت‌ها بر اساس اثر درآمد انتخاب گردند.",
},
{
id: "{۲}",
title: "طراحی سیستم رشد",
image: "/block-media/shadcnblocks/block/guri3/img25.jpeg",
description:
"نقشه کانال، سامانه مدیریت ارتباط با مشتری، اتوماسیون و KPIها را طراحی می‌کنیم تا تیم‌ها روی یک منبع حقیقت کار کنند و بودجه به کانال‌های پربازده برود.",
},
{
id: "{۰۳}",
title: "پیاده‌سازی عملیاتی",
image: "/block-media/shadcnblocks/block/guri4/img10.png",
description:
"ابزارها، جریان‌ها و داشبوردها را مستقر می‌کنیم. فروش و بازاریابی با داده تمیز و فرآیند شفاف وارد اجرا می‌شوند.",
},
{
id: "{۰۴}",
title: "فعال‌سازی تیم",
image: "/block-media/shadcnblocks/block/guri4/img9.png",
description:
"آموزش، راهنمای فروش و دارایی‌های فروش را تحویل می‌دهیم تا پذیرش سیستم بالا بماند و عملکرد از فرد به کل تیم منتقل شود.",
},
{
id: "{۰۵}",
title: "بهینه‌سازی مستمر",
image: "/block-media/shadcnblocks/block/guri3/img25.jpeg",
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="flex w-full flex-col justify-between lg:flex-row lg:gap-20">
<div className="top-10 h-fit w-full space-y-7 py-8 lg:sticky lg:max-w-xs">
<div className="relative h-90 overflow-hidden">
{previousActive !== undefined && (
<div className="absolute top-0 h-full w-full">
<img
src={services[previousActive].image}
className="h-full w-full object-cover"
alt={services[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={services[active].image}
className="h-full w-full object-cover"
alt={services[active].title}
/>
</motion.div>
</div>
<p className="font-semibold tracking-tight text-foreground/20">
{services[active].title}
</p>
<p className="text-base text-foreground/50">
{services[active].description}
</p>
</div>
<div className="relative w-full xl:ps-20">
<ul>
{services.map((service, index) => (
<li
key={index}
onMouseEnter={() => setActive(index)}
className={cn(
"cursor-pointer border-b border-foreground/20 py-8 text-2xll font-semibold tracking-tight lg:text-2xll",
)}
>
<div
className={index === active ? "opacity-100" : "opacity-20"}
>
<span>{service.title}</span>
<sup className="align-super text-sm text-red-500 lg:text-3xl">
{service.id}
</sup>
</div>
</li>
))}
</ul>
<BorderButton className="group mt-10 gap-2 border-red-100 bg-red-500/10 text-red-500">
شروع کنید
<ArrowUpRight className="size-4 transition-transform duration-300 rtl:rotate-180 group-hover:rotate-45 rtl:group-hover:-rotate-[135deg]" />
</BorderButton>
</div>
</div>
</div>
</section>
);
};
export { Services21 };