Files
pars-elevator/src/components/FeaturesCarousel.tsx
T
Alireza HassaniandCursor 5909899b1e Initial Next.js clone of Pars Elevator (plift.ir).
RTL Meshkee storefront with home/about/contact/products/blog, API auth/contact/blog wiring, and SEO sitemap-config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-05 14:55:42 +03:30

127 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useEffect, useState } from "react";
import { featuresSection } from "@/data/site";
export function FeaturesCarousel() {
const items = featuresSection.items;
const [index, setIndex] = useState(0);
const [perView, setPerView] = useState(3);
useEffect(() => {
const update = () => {
const w = window.innerWidth;
if (w < 768) setPerView(1);
else if (w < 992) setPerView(2);
else setPerView(3);
};
update();
window.addEventListener("resize", update);
return () => window.removeEventListener("resize", update);
}, []);
useEffect(() => {
if (items.length <= perView) return;
const id = window.setInterval(() => {
setIndex((i) => (i + 1) % items.length);
}, 3000);
return () => window.clearInterval(id);
}, [items.length, perView]);
const visible =
perView >= items.length
? items
: Array.from({ length: perView }, (_, i) => items[(index + i) % items.length]);
const showNav = items.length > perView;
return (
<section className="relative overflow-hidden bg-[#F6F6F6] pt-20 pb-24 md:pt-[6.5rem] md:pb-28">
<div
aria-hidden
className="pointer-events-none absolute inset-x-0 top-4 hidden select-none overflow-hidden text-center text-[110px] font-semibold leading-none tracking-[-8px] text-white xl:block 2xl:text-[154px]"
>
آسانسور پارس
</div>
<div className="container-plift relative z-10">
<div className="mx-auto mb-12 max-w-2xl text-center lg:mb-14">
<span className="mb-5 block text-[17px] font-medium text-[#A0A0A0]">
{featuresSection.eyebrow}
</span>
<h2 className="text-[1.7rem] font-bold uppercase leading-snug text-dark md:text-[2rem]">
{featuresSection.title}
</h2>
</div>
<div className="grid items-start gap-6 lg:grid-cols-12 lg:gap-5">
{/* side intro — ~1/4 */}
<div className="pt-2 lg:col-span-3">
<span className="mb-5 block text-[17px] font-medium text-dark">
{featuresSection.sideLabel}
</span>
<h3 className="mb-8 text-[1.35rem] font-bold leading-9 text-dark md:text-[1.55rem] md:leading-10">
{featuresSection.sideTitle}
</h3>
{showNav && (
<div className="flex gap-2">
<button
type="button"
aria-label="بعدی"
onClick={() => setIndex((i) => (i + 1) % items.length)}
className="inline-flex h-10 w-10 items-center justify-center border border-[#ddd] text-lg text-dark transition hover:border-dark"
>
‹
</button>
<button
type="button"
aria-label="قبلی"
onClick={() =>
setIndex((i) => (i - 1 + items.length) % items.length)
}
className="inline-flex h-10 w-10 items-center justify-center border border-[#ddd] text-lg text-dark transition hover:border-dark"
>
›
</button>
</div>
)}
</div>
{/* cards — show 3 on desktop like original */}
<div className="lg:col-span-9">
<div
className={`grid gap-5 ${
perView === 1
? "grid-cols-1"
: perView === 2
? "grid-cols-2"
: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3"
}`}
>
{visible.map((item, i) => (
<article
key={`${item.number}-${perView >= items.length ? item.number : `${index}-${i}`}`}
className="border border-black/[0.08] bg-white"
>
<div className="px-7 py-10 md:px-8 md:py-12 xl:px-9">
<div className="mb-5 text-[2.5rem] font-medium leading-none tracking-[-2px] text-[#A0A0A0]">
{item.number}
</div>
<h4 className="mb-3 text-[16px] font-semibold uppercase leading-7 text-dark">
{item.title}
</h4>
<p className="text-[14px] font-light leading-[26px] text-[#5C6873] text-justify">
{item.description}
</p>
</div>
</article>
))}
</div>
</div>
</div>
</div>
</section>
);
}