151 lines
5.3 KiB
TypeScript
151 lines
5.3 KiB
TypeScript
"use client";
|
|
|
|
import { motion, useSpring } from "framer-motion";
|
|
import React, { useState } from "react";
|
|
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface Services19Props {
|
|
className?: string;
|
|
}
|
|
|
|
const Services19 = ({ className }: Services19Props) => {
|
|
const SPRING = {
|
|
mass: 0.1,
|
|
stiffness: 100,
|
|
damping: 10,
|
|
};
|
|
|
|
const xSpring = useSpring(0, SPRING);
|
|
const ySpring = useSpring(0, SPRING);
|
|
const scaleSpring = useSpring(0, SPRING);
|
|
const opacity = useSpring(0, SPRING);
|
|
|
|
const services = [
|
|
{
|
|
title: "پیادهسازی سامانه مدیریت ارتباط با مشتری",
|
|
categories: ["طراحی قیف", "حاکمیت داده"],
|
|
subcategories: ["اتوماسیون فروش", "داشبورد پیشبینی"],
|
|
image: "/block-media/shadcnblocks/block/guri4/img1.png",
|
|
},
|
|
{
|
|
title: "اتوماسیون بازاریابی",
|
|
categories: ["پرورش سرنخ", "امتیازدهی"],
|
|
subcategories: ["جریان چرخه عمر", "تحویل به فروش"],
|
|
image: "/block-media/shadcnblocks/block/guri4/img2.png",
|
|
},
|
|
{
|
|
title: "تولید سرنخ",
|
|
categories: ["کمپین عملکردی", "لندینگ"],
|
|
subcategories: ["ICP و پیام", "بهینهسازی تبدیل"],
|
|
image: "/block-media/shadcnblocks/block/guri4/img3.png",
|
|
},
|
|
{
|
|
title: "خدمات سئو",
|
|
categories: ["سئوی فنی", "محتوای B2B"],
|
|
subcategories: ["رتبه و ترافیک", "سرنخ ارگانیک"],
|
|
image: "/block-media/shadcnblocks/block/guri4/img4.png",
|
|
},
|
|
{
|
|
title: "مشاوره تحلیل داده",
|
|
categories: ["مدل رویداد", "داشبورد KPI"],
|
|
subcategories: ["اتریبیوشن", "تحلیل کوهورت"],
|
|
image: "/block-media/shadcnblocks/block/guri4/img5.png",
|
|
},
|
|
{
|
|
title: "عملیات پشتیبانی",
|
|
categories: ["طراحی SLA", "پایگاه دانش"],
|
|
subcategories: ["کیفیت پاسخ", "نگهداشت مشتری"],
|
|
image: "/block-media/shadcnblocks/block/guri4/img6.png",
|
|
},
|
|
];
|
|
|
|
const handlePointerMove = (e: React.PointerEvent<HTMLTableElement>) => {
|
|
const bounds = e.currentTarget.getBoundingClientRect();
|
|
xSpring.set(e.clientX - bounds.left + 20);
|
|
ySpring.set(e.clientY - bounds.top + 20);
|
|
};
|
|
|
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
|
|
return (
|
|
<section dir="rtl" lang="fa" className={cn("py-32", className)}>
|
|
<div className="container">
|
|
<div className="flex flex-col items-center justify-center gap-15">
|
|
<h1 className="text-xl font-medium tracking-tighter lg:text-2xll">
|
|
خدماتی که{" "}
|
|
<span className="font-instrumentSerif text-2xll font-normal italic lg:text-2xll">
|
|
رشد میسازند
|
|
</span>
|
|
<sup className="ps-2 align-top text-sm font-normal tracking-normal">
|
|
[۰۶]
|
|
</sup>
|
|
</h1>
|
|
<div className="relative w-full">
|
|
<table
|
|
onPointerMove={handlePointerMove}
|
|
onPointerEnter={() => {
|
|
opacity.set(1);
|
|
scaleSpring.set(1);
|
|
}}
|
|
onPointerLeave={() => {
|
|
opacity.set(0);
|
|
scaleSpring.set(0);
|
|
}}
|
|
className="w-full"
|
|
>
|
|
<tbody>
|
|
{services.map((service, index) => (
|
|
<tr
|
|
key={index}
|
|
onPointerEnter={() => {
|
|
setCurrentIndex(index);
|
|
}}
|
|
className="group relative cursor-pointer border-b"
|
|
>
|
|
<td className="py-5">
|
|
<h3 className="text-xl font-medium tracking-tight lg:text-xl">
|
|
{service.title}
|
|
</h3>
|
|
</td>
|
|
<td className="hidden lg:table-cell">
|
|
<div className="w-full max-w-2xs pe-5 text-center text-sm tracking-tighter text-foreground/30 group-hover:text-foreground lg:text-base">
|
|
<p>{service.categories[0]}</p>
|
|
<p>{service.categories[1]}</p>
|
|
</div>
|
|
</td>
|
|
<td className="text-end text-sm tracking-tighter text-foreground/30 group-hover:text-foreground lg:text-base">
|
|
<div>
|
|
<p>{service.subcategories[0]}</p>
|
|
<p>{service.subcategories[1]}</p>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
{/* Cursor-following image */}
|
|
<motion.div
|
|
className="pointer-events-none absolute top-0 start-0 hidden size-40 border sm:block"
|
|
style={{
|
|
x: xSpring,
|
|
y: ySpring,
|
|
opacity: opacity,
|
|
scale: scaleSpring,
|
|
}}
|
|
>
|
|
<img
|
|
src={services[currentIndex].image}
|
|
alt={services[currentIndex].title}
|
|
className="h-full w-full object-cover"
|
|
/>
|
|
</motion.div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export { Services19 };
|