205 lines
7.3 KiB
TypeScript
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 };
|