Initial RTL storefront with header, slider, product sections, and local image assets. Co-authored-by: Cursor <cursoragent@cursor.com>
86 lines
3.1 KiB
TypeScript
86 lines
3.1 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import Link from "next/link";
|
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
import { Container } from "@/components/Container";
|
|
import { Placeholder } from "@/components/Placeholder";
|
|
import { heroBanners } from "@/lib/data";
|
|
import type { Slide } from "@/lib/media";
|
|
|
|
export function Hero({ slides }: { slides: Slide[] }) {
|
|
const [index, setIndex] = useState(0);
|
|
|
|
useEffect(() => {
|
|
if (slides.length <= 1) return;
|
|
const timer = setInterval(() => {
|
|
setIndex((current) => (current + 1) % slides.length);
|
|
}, 5000);
|
|
return () => clearInterval(timer);
|
|
}, [slides.length]);
|
|
|
|
const go = (direction: number) => {
|
|
if (slides.length <= 1) return;
|
|
setIndex((current) => (current + direction + slides.length) % slides.length);
|
|
};
|
|
|
|
return (
|
|
<section className="pt-5">
|
|
<Container>
|
|
<div className="relative overflow-hidden rounded-2xl bg-sky">
|
|
<div className="relative aspect-[16/6] sm:aspect-[16/5.2]">
|
|
{slides.map((slide, i) => (
|
|
<Link
|
|
key={slide.id}
|
|
href={slide.href}
|
|
className={`absolute inset-0 transition-opacity duration-500 ${i === index ? "opacity-100" : "pointer-events-none opacity-0"}`}
|
|
>
|
|
<Placeholder src={slide.image} className="h-full w-full object-cover" />
|
|
</Link>
|
|
))}
|
|
</div>
|
|
{slides.length > 1 ? (
|
|
<>
|
|
<button
|
|
type="button"
|
|
onClick={() => go(-1)}
|
|
className="absolute top-1/2 right-3 grid size-9 -translate-y-1/2 place-items-center rounded-full bg-white/90 text-navy"
|
|
aria-label="اسلاید قبلی"
|
|
>
|
|
<ChevronRight className="size-5" />
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={() => go(1)}
|
|
className="absolute top-1/2 left-3 grid size-9 -translate-y-1/2 place-items-center rounded-full bg-white/90 text-navy"
|
|
aria-label="اسلاید بعدی"
|
|
>
|
|
<ChevronLeft className="size-5" />
|
|
</button>
|
|
<div className="absolute bottom-3 left-1/2 flex -translate-x-1/2 gap-1.5">
|
|
{slides.map((slide, i) => (
|
|
<button
|
|
key={slide.id}
|
|
type="button"
|
|
onClick={() => setIndex(i)}
|
|
className={`h-1.5 rounded-full transition-all ${i === index ? "w-6 bg-primary" : "w-2 bg-white/80"}`}
|
|
aria-label={`اسلاید ${i + 1}`}
|
|
/>
|
|
))}
|
|
</div>
|
|
</>
|
|
) : null}
|
|
</div>
|
|
|
|
<div className="mt-3 grid grid-cols-1 gap-3 sm:grid-cols-2">
|
|
{heroBanners.map((banner) => (
|
|
<Link key={banner.id} href={banner.href} className="overflow-hidden rounded-xl bg-sky">
|
|
<Placeholder src={banner.image} className="h-[92px] w-full object-cover sm:h-[110px]" />
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</Container>
|
|
</section>
|
|
);
|
|
}
|