Files
reui-blocks/blocks/projects8.tsx
T

205 lines
7.3 KiB
TypeScript

"use client";
import { AnimatePresence, motion } from "framer-motion";
import { useState } from "react";
import { cn } from "@/lib/utils";
interface Projects8type {
id: number;
title: string;
category: string;
description: string;
image: string;
tags: string[];
}
const categoryLabels: Record<string, string> = {
"MOONLIGHT VISIONS": "فروش",
"PIXEL PARADE": "بازاریابی",
"WANDER SKETCHES": "سامانه مدیریت ارتباط با مشتری",
"ECHO FIELDS": "تحلیل",
"NEON TAPESTRY": "پشتیبانی",
VIDEOS: "گزارش",
};
const filterCategories = [
{ key: "ALL", label: "همه" },
{ key: "MOONLIGHT VISIONS", label: "فروش" },
{ key: "PIXEL PARADE", label: "بازاریابی" },
{ key: "WANDER SKETCHES", label: "سامانه مدیریت ارتباط با مشتری" },
{ key: "ECHO FIELDS", label: "تحلیل" },
{ key: "NEON TAPESTRY", label: "پشتیبانی" },
] as const;
const Projects8Data: Projects8type[] = [
{
id: 1,
title: "افزایش ۴۰٪ نرخ تبدیل",
category: "MOONLIGHT VISIONS",
description:
"پیاده‌سازی اتوماسیون ایمیل و امتیازدهی لید برای شرکت SaaS B2B.",
image:
"/block-media/shadcnblocks/block/photos/vanessa-werder-LjFEoGuj5eY-unsplash.jpg",
tags: ["سامانه مدیریت ارتباط با مشتری", "automation"],
},
{
id: 2,
title: "کاهش ۶۰٪ زمان پاسخ‌گویی",
category: "PIXEL PARADE",
description:
"یکپارچه‌سازی سامانه مدیریت ارتباط با مشتری با سیستم تیکتینگ برای تیم پشتیبانی ۵۰ نفره.",
image:
"/block-media/shadcnblocks/block/photos/vasilis-karkalas-qOaeVSKyhhE-unsplash.jpg",
tags: ["support", "سامانه مدیریت ارتباط با مشتری"],
},
{
id: 3,
title: "داشبورد فروش یکپارچه",
category: "WANDER SKETCHES",
description:
"ساخت داشبورد KPI برای نمایش درآمد، قیف فروش و پیش‌بینی فصلی.",
image:
"/block-media/shadcnblocks/block/photos/vanessa-werder-PrsQ3hfBFTI-unsplash.jpg",
tags: ["analytics", "sales"],
},
{
id: 4,
title: "داشبورد تحلیلی",
category: "ECHO FIELDS",
description:
"داشبورد تحلیلی برای نمایش KPIهای فروش و بازاریابی با نمودارهای تعاملی.",
image:
"/block-media/shadcnblocks/block/photos/pat-whelen-gWfpmH0H2bM-unsplash.jpg",
tags: ["analytics", "dashboard"],
},
{
id: 5,
title: "خودکارسازی کمپین",
category: "NEON TAPESTRY",
description:
"راه‌اندازی جریان‌های ایمیل هدفمند برای ۱۲ بخش مخاطب مختلف.",
image:
"/block-media/shadcnblocks/block/photos/vanessa-werder-4G228Duzmn8-unsplash.jpg",
tags: ["marketing", "email"],
},
{
id: 6,
title: "گزارش عملکرد فصلی",
category: "VIDEOS",
description:
"گزارش تحلیلی سه‌ماهه با بررسی ROI کمپین‌ها و رشد درآمد تکرارشونده.",
image:
"/block-media/shadcnblocks/block/photos/vasilis-karkalas-1LT5DG5BD6Q-unsplash.jpg",
tags: ["reporting", "revenue"],
},
];
interface Projects8Props {
className?: string;
}
const Projects8 = ({ className }: Projects8Props) => {
const [activeFilter, setActiveFilter] = useState<string>("ALL");
const [filteredItems, setFilteredItems] = useState(Projects8Data);
const handleFilterChange = (category: string) => {
setActiveFilter(category);
if (category === "ALL") {
setFilteredItems(Projects8Data);
} else {
const filtered = Projects8Data.filter(
(item) =>
item.category === category ||
item.tags.includes(category.toLowerCase().replace(" ", "-")),
);
setFilteredItems(filtered);
}
};
const activeFilterLabel =
filterCategories.find((item) => item.key === activeFilter)?.label ??
categoryLabels[activeFilter] ??
activeFilter;
return (
<section dir="rtl" lang="fa" className={cn("py-32", className)}>
<div className="container">
<div className="mx-auto max-w-7xl">
<div className="mb-16 flex flex-wrap justify-center gap-8">
{filterCategories.map(({ key, label }) => (
<button
key={key}
onClick={() => handleFilterChange(key)}
className={`text-sm font-medium tracking-wider transition-colors duration-300 hover:text-foreground ${
activeFilter === key
? "border-b-2 border-border pb-1 text-foreground"
: "text-gray-500"
}`}
>
{label}
</button>
))}
</div>
<motion.div layout className="grid grid-cols-1 gap-8 md:grid-cols-3">
<AnimatePresence mode="wait">
{filteredItems.map((item) => (
<motion.div
key={item.id}
layout
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.9 }}
transition={{
duration: 0.2,
ease: "easeInOut",
}}
className="group relative cursor-pointer overflow-hidden rounded-lg"
>
<div className="relative aspect-[4/3] h-96 w-full">
<img
src={item.image}
alt={item.title}
className="object-cover transition-transform duration-300"
/>
<motion.div className="absolute inset-0 flex flex-col items-center justify-center bg-black/60 p-8 text-white opacity-0 transition-opacity duration-200 group-hover:opacity-100">
<motion.div className="translate-y-5 text-center opacity-0 transition-all duration-300 group-hover:translate-y-0 group-hover:opacity-100">
<p className="mb-4 text-xs font-medium tracking-widest text-gray-300">
{categoryLabels[item.category] ?? item.category}
</p>
<h3 className="mb-4 text-2xl font-light tracking-wide">
{item.title}
</h3>
<p className="max-w-xs text-sm leading-relaxed text-gray-200">
{item.description}
</p>
</motion.div>
</motion.div>
</div>
</motion.div>
))}
</AnimatePresence>
</motion.div>
{filteredItems.length === 0 && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="py-16 text-center"
>
<p className="text-lg text-gray-500">
موردی در دسته «{activeFilterLabel}» یافت نشد.
</p>
</motion.div>
)}
</div>
</div>
</section>
);
};
export { Projects8 };