142 lines
4.9 KiB
TypeScript
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;
|
||
|
|
|