205 lines
8.1 KiB
TypeScript
205 lines
8.1 KiB
TypeScript
"use client";
|
|
|
|
import { Bolt, Cloud, MessagesSquare, Star } from "lucide-react";
|
|
import { useEffect, useState } from "react";
|
|
|
|
import { Badge } from "@/components/ui/badge";
|
|
import type { CarouselApi } from "@/components/ui/carousel";
|
|
import {
|
|
Carousel,
|
|
CarouselContent,
|
|
CarouselItem,
|
|
} from "@/components/ui/carousel";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
const features = [
|
|
{
|
|
id: "feature-1",
|
|
title: "ردیابی UTM",
|
|
description:
|
|
"چند کانال را همزمان اجرا کنید و عملکرد هر کمپین را در یک نما مقایسه کنید.",
|
|
icon: Cloud,
|
|
image: "/block-media/shadcnblocks/block/placeholder-1.svg",
|
|
},
|
|
{
|
|
id: "feature-2",
|
|
title: "گزارش ROI",
|
|
description:
|
|
"مخاطبان را بر اساس رفتار، صنعت یا مرحله خرید دستهبندی کنید.",
|
|
icon: Star,
|
|
image: "/block-media/shadcnblocks/block/placeholder-2.svg",
|
|
},
|
|
{
|
|
id: "feature-3",
|
|
title: "مدیریت کمپین",
|
|
description:
|
|
"ببینید کدام کانال بیشترین سرنخ با کیفیت را میآورد.",
|
|
icon: Bolt,
|
|
image: "/block-media/shadcnblocks/block/placeholder-3.svg",
|
|
},
|
|
{
|
|
id: "feature-4",
|
|
title: "سگمنتبندی مخاطب",
|
|
description:
|
|
"مسیرهای ایمیل را بدون کدنویسی برای هر سگمنت طراحی کنید.",
|
|
icon: MessagesSquare,
|
|
image: "/block-media/shadcnblocks/block/placeholder-4.svg",
|
|
},
|
|
];
|
|
|
|
interface Feature57Props {
|
|
className?: string;
|
|
}
|
|
|
|
const Feature57 = ({ className }: Feature57Props) => {
|
|
const [selection, setSelection] = useState(0);
|
|
const [carouselApi, setCarouselApi] = useState<CarouselApi>();
|
|
|
|
const handleSelection = (index: number) => {
|
|
carouselApi?.scrollTo(index);
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (!carouselApi) {
|
|
return;
|
|
}
|
|
const updateSelection = () => {
|
|
setSelection(carouselApi.selectedScrollSnap());
|
|
};
|
|
carouselApi.on("select", updateSelection);
|
|
return () => {
|
|
carouselApi.off("select", updateSelection);
|
|
};
|
|
}, [carouselApi]);
|
|
|
|
return (
|
|
<section
|
|
dir="rtl"
|
|
lang="fa"
|
|
className={cn("py-12 md:py-24 lg:py-32", className)}
|
|
>
|
|
<div className="container mx-auto px-4">
|
|
<div className="mb-8 text-center md:mb-12">
|
|
<Badge variant="outline" className="mb-3">
|
|
کمپین
|
|
</Badge>
|
|
<h2 className="text-3xl leading-tight font-bold md:text-xl lg:text-2xll">
|
|
کمپینهایی بسازید که واقعاً تبدیل میشوند
|
|
</h2>
|
|
<p className="mx-auto mt-3 max-w-2xl text-sm text-muted-foreground md:mt-4 md:text-base">
|
|
با سگمنتبندی دقیق، پیام مناسب را به مخاطب مناسب برسانید. داده رفتاری نشان میدهد کدام محتوا بیشترین تأثیر را روی تبدیل دارد.
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<div className="mx-auto flex max-w-6xl flex-col-reverse gap-6 md:flex-row md:gap-8 lg:gap-16">
|
|
<div className="md:w-1/2 lg:w-2/5">
|
|
<ul className="grid grid-cols-1 gap-3 md:flex md:flex-col md:gap-2">
|
|
{features.map((feature, i) => {
|
|
const isSelected = selection === i;
|
|
return (
|
|
<li
|
|
key={feature.id}
|
|
className={`group relative flex cursor-pointer rounded-xl border px-4 py-3 transition-all duration-300 md:px-5 md:py-4 ${
|
|
isSelected
|
|
? "border-border bg-accent shadow-sm"
|
|
: "border-transparent hover:border-border hover:bg-accent/30"
|
|
}`}
|
|
data-open={isSelected ? "true" : undefined}
|
|
onClick={() => handleSelection(i)}
|
|
>
|
|
<div className="flex w-full items-start gap-3 md:gap-4">
|
|
<div
|
|
className={`flex aspect-square w-9 shrink-0 items-center justify-center rounded-lg transition-colors md:w-10 ${
|
|
isSelected
|
|
? "bg-primary text-primary-foreground"
|
|
: "bg-muted text-muted-foreground"
|
|
}`}
|
|
>
|
|
<feature.icon className="size-4 md:size-5" />
|
|
</div>
|
|
<div className="min-w-0 flex-1">
|
|
<h3
|
|
className={`mb-1 text-sm font-semibold transition-colors md:text-base lg:text-lg ${
|
|
isSelected
|
|
? "text-foreground"
|
|
: "text-muted-foreground"
|
|
}`}
|
|
>
|
|
{feature.title}
|
|
</h3>
|
|
<p className="line-clamp-2 text-xs text-muted-foreground transition-all md:text-sm md:group-data-open:opacity-100 lg:text-sm">
|
|
{feature.description}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
</div>
|
|
|
|
<div className="relative md:w-1/2 lg:w-3/5">
|
|
<div className="overflow-hidden rounded-xl border border-border shadow-sm">
|
|
<Carousel
|
|
setApi={setCarouselApi}
|
|
className="aspect-4/5 max-h-[500px] w-full md:aspect-3/4 lg:aspect-4/5 [&>div]:h-full"
|
|
opts={{
|
|
loop: true,
|
|
direction: "rtl",
|
|
}}
|
|
>
|
|
<CarouselContent className="mx-0 h-full w-full">
|
|
{features.map((feature) => (
|
|
<CarouselItem key={feature.id} className="px-0">
|
|
<div className="relative h-full w-full overflow-hidden">
|
|
<img
|
|
src={feature.image}
|
|
alt={`نمای ${feature.title}`}
|
|
className="h-full w-full object-cover object-center transition-transform duration-500"
|
|
/>
|
|
<div className="absolute inset-x-0 bottom-0 bg-linear-to-t from-background/80 via-background/40 to-transparent p-6">
|
|
<div className="flex items-start gap-3">
|
|
<div className="flex aspect-square w-10 shrink-0 items-center justify-center rounded-lg bg-primary text-primary-foreground">
|
|
<feature.icon className="size-5" />
|
|
</div>
|
|
<div>
|
|
<h3 className="text-xl font-semibold text-foreground">
|
|
{feature.title}
|
|
</h3>
|
|
<p className="mt-1 line-clamp-2 text-xs text-muted-foreground">
|
|
{feature.description}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CarouselItem>
|
|
))}
|
|
</CarouselContent>
|
|
</Carousel>
|
|
</div>
|
|
|
|
<div className="mt-5 flex justify-center gap-2">
|
|
{features.map((feature, i) => (
|
|
<button
|
|
key={feature.id}
|
|
className={`size-2 rounded-full transition-all ${
|
|
selection === i
|
|
? "w-6 bg-primary"
|
|
: "bg-muted hover:bg-muted-foreground/50"
|
|
}`}
|
|
onClick={() => handleSelection(i)}
|
|
aria-label={feature.title}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export { Feature57 };
|