245 lines
8.3 KiB
TypeScript
245 lines
8.3 KiB
TypeScript
"use client";
|
|
|
|
import Autoplay from "embla-carousel-autoplay";
|
|
import { useEffect, useState } from "react";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import {
|
|
Carousel,
|
|
type CarouselApi,
|
|
CarouselContent,
|
|
CarouselItem,
|
|
} from "@/components/ui/carousel";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
type Product = {
|
|
name: string;
|
|
image: string;
|
|
href: string;
|
|
};
|
|
|
|
interface HeroCarouselItem {
|
|
image: string;
|
|
title?: string;
|
|
description?: string;
|
|
cta?: {
|
|
label: string;
|
|
href: string;
|
|
};
|
|
product?: Product;
|
|
}
|
|
|
|
const HERO_CAROUSEL = [
|
|
{
|
|
title: "ظرافت بیدردسر مو",
|
|
description:
|
|
"اکسسوریهای مو با طراحی ظریف که با لمس طلایی، استایل روزمره را ارتقا میدهند.",
|
|
cta: {
|
|
label: "خرید اکسسوری مو",
|
|
href: "#",
|
|
},
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/accessories/Elegant-Blonde-Hairstyle-2.png",
|
|
product: {
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/accessories/Golden-Hair-Clip-Close-Up-2.png",
|
|
href: "#",
|
|
name: "گیره مو طلایی",
|
|
},
|
|
},
|
|
{
|
|
title: "استایل خیابانی ماندگار",
|
|
description:
|
|
"سیلوئتهای کلاسیک و تنهای خنثی برای استایلی مدرن و باوقار.",
|
|
cta: {
|
|
label: "خرید کلاه",
|
|
href: "#",
|
|
},
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/accessories/Fashionable-Pose-2.png",
|
|
product: {
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/accessories/Stylish-Beige-Fedora-1.png",
|
|
href: "#",
|
|
name: "کلاه فدورا بژ",
|
|
},
|
|
},
|
|
{
|
|
title: "جزئیات چشمگیر",
|
|
description:
|
|
"جواهرات ظریف که به هر لباسی شخصیت و اعتماد به نفس میبخشد.",
|
|
cta: {
|
|
label: "مشاهده جواهرات",
|
|
href: "#",
|
|
},
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/accessories/Stylish-Seated-Portrait-2.png",
|
|
product: {
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/accessories/Elegant-Hand-Jewelry-1.png",
|
|
href: "#",
|
|
name: "زیورآلات زنجیر دست",
|
|
},
|
|
},
|
|
{
|
|
title: "جسور و براق",
|
|
description:
|
|
"عینک آفتابی شیک برای ظاهری تیز و محافظت در برابر نور روز.",
|
|
cta: {
|
|
label: "خرید عینک آفتابی",
|
|
href: "#",
|
|
},
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/accessories/Stylish-Woman-Portrait-2.png",
|
|
product: {
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/accessories/Stylish-Sunglasses-Close-Up-2.png",
|
|
href: "#",
|
|
name: "عینک آفتابی مدرن",
|
|
},
|
|
},
|
|
{
|
|
title: "پوشش راحتی مدرن",
|
|
description:
|
|
"برشهای راحت و خطوط تمیز برای لباس پوشیدن روزمره بیدردسر.",
|
|
cta: {
|
|
label: "خرید پوشاک",
|
|
href: "#",
|
|
},
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/clothes/Modern-Casual-Style-m-2.png",
|
|
product: {
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/clothes/Modern-Casual-Style-2.png",
|
|
href: "#",
|
|
name: "ست استایل راحتی",
|
|
},
|
|
},
|
|
];
|
|
|
|
interface EcommerceHero8Props {
|
|
className?: string;
|
|
carouselItems: HeroCarouselItem[];
|
|
}
|
|
|
|
const EcommerceHero8 = ({
|
|
className,
|
|
carouselItems = HERO_CAROUSEL,
|
|
}: EcommerceHero8Props) => {
|
|
const [mainCarouselApi, setMainCarouselApi] = useState<CarouselApi>();
|
|
const [secondaryCarouselApi, setSecondaryCarouselApi] =
|
|
useState<CarouselApi>();
|
|
const [current, setCurrent] = useState(0);
|
|
|
|
useEffect(() => {
|
|
if (!mainCarouselApi) return;
|
|
|
|
const updateCurrent = (api: CarouselApi) => {
|
|
if (!api) return;
|
|
setCurrent(api?.selectedScrollSnap());
|
|
secondaryCarouselApi?.scrollTo(api?.selectedScrollSnap());
|
|
};
|
|
mainCarouselApi.on("reInit", updateCurrent).on("select", updateCurrent);
|
|
|
|
return () => {
|
|
mainCarouselApi.off("reInit", updateCurrent).off("select", updateCurrent);
|
|
};
|
|
}, [mainCarouselApi, secondaryCarouselApi]);
|
|
|
|
return (
|
|
<section dir="rtl" lang="fa" className={cn("", className)}>
|
|
<div className="relative space-y-5">
|
|
<Carousel
|
|
setApi={setMainCarouselApi}
|
|
opts={{
|
|
loop: true,
|
|
}}
|
|
plugins={[Autoplay()]}
|
|
>
|
|
<CarouselContent className="m-0">
|
|
{carouselItems.map(({ title, image, description, cta }, index) => (
|
|
<CarouselItem
|
|
key={index}
|
|
className="h-dvh min-h-150 bg-muted p-0"
|
|
>
|
|
<div
|
|
style={{
|
|
backgroundImage: `url(${image})`,
|
|
}}
|
|
data-state={current === index ? "active" : "inactive"}
|
|
className="group relative size-full bg-cover bg-center bg-no-repeat after:absolute after:inset-0 after:bg-black/40"
|
|
>
|
|
<div className="relative z-10 flex size-full flex-col justify-end px-5 pb-50 lg:py-15">
|
|
<div className="flex">
|
|
<div className="space-y-7.5 text-start lg:basis-[calc(100%-620px)]">
|
|
<h2 className="max-w-100 font-serif text-2xll text-white delay-500 duration-600 group-data-[state=active]:animate-in group-data-[state=active]:slide-in-from-bottom-30 group-data-[state=active]:fade-in group-data-[state=inactive]:opacity-0">
|
|
{title}
|
|
</h2>
|
|
<p className="max-w-100 text-lg text-balance text-white duration-800 group-data-[state=active]:animate-in group-data-[state=active]:slide-in-from-bottom-60 group-data-[state=active]:fade-in">
|
|
{description}
|
|
</p>
|
|
{cta && (
|
|
<div className="duration-1000 group-data-[state=active]:animate-in group-data-[state=active]:slide-in-from-bottom-80 group-data-[state=active]:fade-in">
|
|
<Button asChild size="lg" variant="outline">
|
|
<a href={cta?.href}>{cta?.label}</a>
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CarouselItem>
|
|
))}
|
|
</CarouselContent>
|
|
</Carousel>
|
|
<div className="lg:absolute lg:end-0 lg:bottom-5">
|
|
<div className="space-y-4.5 ps-5">
|
|
<h3 className="text-start font-light lg:text-white">
|
|
کشف مجموعه ما
|
|
</h3>
|
|
<Carousel
|
|
opts={{
|
|
align: "start",
|
|
loop: true,
|
|
}}
|
|
setApi={setSecondaryCarouselApi}
|
|
className="lg:max-w-150"
|
|
>
|
|
<CarouselContent>
|
|
{carouselItems.map(({ product }, index) => (
|
|
<CarouselItem
|
|
key={index}
|
|
className="basis-[75%] lg:basis-[60%]"
|
|
>
|
|
<a
|
|
href={product?.href}
|
|
className="group relative block aspect-[1.4] overflow-hidden p-3 after:absolute after:inset-0 after:bg-black/30"
|
|
>
|
|
<div className="relative z-10 flex size-full flex-col justify-end text-start">
|
|
<h3 className="font-serif text-xl font-semibold text-white sm:text-xl">
|
|
{product?.name}
|
|
</h3>
|
|
</div>
|
|
|
|
<div className="absolute inset-0">
|
|
<img
|
|
src={product?.image}
|
|
alt={product?.name}
|
|
className="block size-full origin-center object-cover object-center transition-transform duration-500 group-hover:scale-110"
|
|
/>
|
|
</div>
|
|
</a>
|
|
</CarouselItem>
|
|
))}
|
|
</CarouselContent>
|
|
</Carousel>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export { EcommerceHero8 };
|