Files
reui-blocks/blocks/timeline7.tsx
T

179 lines
5.7 KiB
TypeScript

"use client";
import { motion } from "framer-motion";
import { Check, ChevronLeft, ChevronRight, Circle } from "lucide-react";
import React, { useState } from "react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
interface Timeline7Props {
className?: string;
}
interface StepProps {
title: string;
imageSrc: string;
description: string;
}
const steps: StepProps[] = [
{
title: "معرفی",
imageSrc:
"/block-media/shadcnblocks/block/placeholder-1.svg",
description:
"به راهنمای گام‌به‌گام ما خوش آمدید. این بخش معرفی به شما کمک می‌کند با فرآیند آشنا شوید و بدانید چه انتظاری داشته باشید.",
},
{
title: "اطلاعات شخصی",
imageSrc:
"/block-media/shadcnblocks/block/placeholder-2.svg",
description:
"در این بخش، برخی اطلاعات پایه از شما جمع‌آوری می‌کنیم تا تجربه‌تان شخصی‌سازی شود و پیشنهادهای بهتری ارائه دهیم.",
},
{
title: "جزئیات آدرس",
imageSrc:
"/block-media/shadcnblocks/block/placeholder-3.svg",
description:
"لطفاً جزئیات آدرس خود را وارد کنید تا محصولات را به محل درست تحویل دهیم و هزینه ارسال محاسبه شود.",
},
{
title: "بازبینی و ثبت",
imageSrc:
"/block-media/shadcnblocks/block/placeholder-4.svg",
description:
"پیش از نهایی کردن، لحظه‌ای تمام اطلاعات واردشده را مرور کنید. می‌توانید به هر مرحله برگردید.",
},
];
const ProcessBar: React.FC<{
currentStep: number;
steps: StepProps[];
}> = ({ currentStep, steps }) => (
<div className="relative w-full scale-75">
<div className="flex items-center justify-between">
{steps.map((step, index) => (
<React.Fragment key={step.title}>
<div className="flex flex-col items-center">
<motion.div
className={`z-10 flex h-8 w-8 items-center justify-center rounded-full ${
index <= currentStep
? "bg-neutral-800 text-white"
: "bg-gray-200 text-white dark:bg-gray-800 dark:text-gray-600"
}`}
animate={{ scale: 1.02 }}
>
{index < currentStep ? (
<Check size={17} />
) : (
<Circle size={17} fill="white" />
)}
</motion.div>
</div>
{index < steps.length - 1 && (
<div className="relative grow">
<div className="absolute -top-1 h-1.5 w-full bg-muted" />
<motion.div
className="absolute -top-1 h-1.5 w-full bg-primary"
initial={{ width: "0%" }}
animate={{
width: index < currentStep ? "100%" : "0%",
}}
transition={{ duration: 0.5, ease: "easeInOut" }}
/>
</div>
)}
</React.Fragment>
))}
</div>
</div>
);
const StepperContent: React.FC<{ step: StepProps }> = ({ step }) => {
return (
<div className="my-4 flex min-h-[400px] w-full flex-col items-center justify-center overflow-hidden rounded-2xl bg-muted p-6 text-center">
<motion.div
key={step.imageSrc}
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3 }}
className="flex h-[200px] w-[500px] items-center justify-center overflow-hidden"
>
<img
src={step.imageSrc}
alt={step.title}
className="w-[500px]"
onError={(e) => {
e.currentTarget.src =
"/block-media/shadcnblocks/block/placeholder-1.svg";
}}
/>
</motion.div>
<p className="mt-6 px-10 text-base leading-snug font-normal tracking-tight text-muted-foreground">
{step.description}
</p>
</div>
);
};
const NavButtons: React.FC<{
currentStep: number;
totalSteps: number;
handlePrev: () => void;
handleNext: () => void;
}> = ({ handlePrev, handleNext }) => (
<div className="flex w-full justify-end gap-3 tracking-tight">
<Button
onClick={handleNext}
className="flex gap-2 transition-all ease-in-out hover:gap-4"
variant="default"
>
بعدی
<ChevronRight size={20} className="rtl:rotate-180" />
</Button>
<Button
onClick={handlePrev}
className="flex gap-2 transition-all ease-in-out hover:gap-4"
variant="secondary"
>
<ChevronLeft size={20} className="rtl:rotate-180" />
قبلی
</Button>
</div>
);
const Timeline7: React.FC<Timeline7Props> = ({ className }) => {
const [currentStep, setCurrentStep] = useState(1);
const handleNext = () => {
setCurrentStep((prev) => Math.min(prev + 1, steps.length - 1));
};
const handlePrev = () => {
setCurrentStep((prev) => Math.max(prev - 1, 0));
};
return (
<section dir="rtl" lang="fa" className={cn("bg-background py-32", className)}>
<div className="container flex max-w-2xl flex-col items-center gap-10 md:gap-0">
<h1 className="mb-10 text-center text-2xll font-bold tracking-tighter text-foreground">
گام‌به‌گام
</h1>
<ProcessBar currentStep={currentStep} steps={steps} />
<StepperContent step={steps[currentStep]} />
<NavButtons
handlePrev={handlePrev}
handleNext={handleNext}
currentStep={currentStep}
totalSteps={steps.length}
/>
</div>
</section>
);
};
export { Timeline7 };