import { createContext, useContext, type ReactNode } from 'react'; import { Button } from '@/components/ui/button'; import { useTranslation } from '@/contexts/language'; import { cn } from '@/lib/utils'; import { Check, ChevronLeft, ChevronRight, Loader2 } from 'lucide-react'; const WizardCtx = createContext(0); export interface WizardStepDef { id: string; title: string; } interface FormWizardProps { steps: WizardStepDef[]; /** Controlled current step (owned by the form so it can jump on validation). */ step: number; onStepChange: (step: number) => void; accentChip: string; submitting: boolean; submitLabel: string; submittingLabel: string; /** Extra footer node (e.g. a Preview button) shown next to Back/Next. */ footerExtra?: ReactNode; children: ReactNode; } /** * A lightweight multi-step shell for the long Lab offer forms. Steps are * declared as {@link WizardStepDef} metadata, and each block of the form is * wrapped in a {@link WizardStep}. Crucially, non-active steps are hidden with * `display:none` rather than unmounted, so nested components that own state * (e.g. `LabExtrasFields`) keep their values while you move around. */ export function FormWizard({ steps, step, onStepChange, accentChip, submitting, submitLabel, submittingLabel, footerExtra, children, }: FormWizardProps) { const { t } = useTranslation(); const last = step === steps.length - 1; return (
{/* Step nav */}
{steps.map((s, i) => ( ))}
{/* Current step content (others stay mounted but hidden) */} {children} {/* Nav */}
{footerExtra} {step > 0 && ( )} {last ? ( ) : ( )}
); } /** A block of the form shown only while its step is active (kept mounted). */ export function WizardStep({ index, children }: { index: number; children: ReactNode }) { const current = useContext(WizardCtx); return
{children}
; }