Vendaweb-portal/components/checkout/CheckoutWizard.tsx

142 lines
4.9 KiB
TypeScript

import React from "react";
import { User, CreditCard, MapPin, FileText } from "lucide-react";
type Step = "customer" | "payment" | "address" | "notes";
interface CheckoutWizardProps {
currentStep: Step;
onStepChange: (step: Step) => void;
children: React.ReactNode;
}
const CheckoutWizard: React.FC<CheckoutWizardProps> = ({
currentStep,
onStepChange,
children,
}) => {
const steps = [
{ id: "customer" as Step, label: "Cliente", icon: User, shortLabel: "Cliente" },
{ id: "payment" as Step, label: "Financeiro", icon: CreditCard, shortLabel: "Financeiro" },
{ id: "address" as Step, label: "Endereço de Entrega", icon: MapPin, shortLabel: "Endereço" },
{ id: "notes" as Step, label: "Observações", icon: FileText, shortLabel: "Observações" },
];
const currentStepIndex = steps.findIndex((s) => s.id === currentStep);
return (
<div className="space-y-4 lg:space-y-6 flex flex-col h-full">
{/* Navegação dos Passos - Mobile/Tablet: Cards verticais */}
<div className="lg:hidden space-y-2">
{steps.map((step, index) => {
const Icon = step.icon;
const isActive = currentStep === step.id;
const isCompleted = index < currentStepIndex;
const isUpcoming = index > currentStepIndex;
return (
<button
key={step.id}
onClick={() => onStepChange(step.id)}
className={`w-full flex items-center gap-3 p-4 rounded-xl border-2 transition-all touch-manipulation ${
isActive
? "bg-[#002147] border-[#002147] text-white shadow-lg shadow-blue-900/20"
: isCompleted
? "bg-emerald-50 border-emerald-200 text-emerald-700 hover:bg-emerald-100"
: "bg-white border-slate-200 text-slate-600 hover:border-slate-300 hover:bg-slate-50"
}`}
>
{/* Ícone com indicador */}
<div
className={`w-10 h-10 rounded-xl flex items-center justify-center flex-shrink-0 ${
isActive
? "bg-white/20 text-white"
: isCompleted
? "bg-emerald-500 text-white"
: "bg-slate-100 text-slate-400"
}`}
>
{isCompleted ? (
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2.5"
d="M5 13l4 4L19 7"
/>
</svg>
) : (
<Icon className="w-5 h-5" />
)}
</div>
{/* Label */}
<div className="flex-1 text-left">
<div className="text-xs font-bold uppercase tracking-wider mb-0.5">
Passo {index + 1}
</div>
<div className="text-sm font-black">{step.label}</div>
</div>
{/* Indicador de seta */}
{isActive && (
<div className="text-white">
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2.5"
d="M9 5l7 7-7 7"
/>
</svg>
</div>
)}
</button>
);
})}
</div>
{/* Navegação dos Passos - Desktop: Tabs horizontais */}
<div className="hidden lg:flex border-b border-slate-200 overflow-x-auto flex-shrink-0">
{steps.map((step) => {
const Icon = step.icon;
return (
<button
key={step.id}
onClick={() => onStepChange(step.id)}
className={`flex items-center gap-2 px-8 py-4 text-xs font-black uppercase tracking-widest whitespace-nowrap transition-all relative ${
currentStep === step.id
? "text-[#002147]"
: "text-slate-400 hover:text-slate-600"
}`}
>
<Icon className="w-4 h-4" />
{step.label}
{currentStep === step.id && (
<div className="absolute bottom-0 left-0 right-0 h-1 bg-orange-500 rounded-t-full"></div>
)}
</button>
);
})}
</div>
{/* Conteúdo dos Passos */}
<div className="bg-white p-4 lg:p-8 rounded-2xl shadow-sm border border-slate-100 min-h-[350px] flex-1">
{children}
</div>
</div>
);
};
export default CheckoutWizard;