Spaces:
Sleeping
Sleeping
| import { ReactNode } from "react"; | |
| import { Button } from "@/components/ui/button"; | |
| import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"; | |
| export interface StepConfig { | |
| id: string; | |
| title: string; | |
| description?: string; | |
| render: () => ReactNode; | |
| } | |
| interface StepWizardProps { | |
| steps: StepConfig[]; | |
| currentIndex: number; | |
| onNext: () => void; | |
| onBack: () => void; | |
| onSubmit: () => void; | |
| isSubmitting?: boolean; | |
| canGoNext: boolean; | |
| } | |
| export function StepWizard({ | |
| steps, | |
| currentIndex, | |
| onNext, | |
| onBack, | |
| onSubmit, | |
| isSubmitting, | |
| canGoNext, | |
| }: StepWizardProps) { | |
| const step = steps[currentIndex]; | |
| const isLast = currentIndex === steps.length - 1; | |
| const progress = ((currentIndex + 1) / steps.length) * 100; | |
| return ( | |
| <Card className="max-w-3xl mx-auto"> | |
| <CardHeader> | |
| <div className="flex items-center justify-between mb-2"> | |
| <CardTitle className="text-lg font-display"> | |
| {step.title} | |
| </CardTitle> | |
| <span className="text-xs text-muted-foreground"> | |
| Step {currentIndex + 1} of {steps.length} | |
| </span> | |
| </div> | |
| <div className="h-1.5 w-full overflow-hidden rounded-full bg-muted"> | |
| <div | |
| className="h-full bg-primary transition-all" | |
| style={{ width: `${progress}%` }} | |
| /> | |
| </div> | |
| {step.description && ( | |
| <p className="mt-3 text-sm text-muted-foreground">{step.description}</p> | |
| )} | |
| </CardHeader> | |
| <CardContent className="space-y-4"> | |
| {step.render()} | |
| </CardContent> | |
| <CardFooter className="flex justify-between gap-2"> | |
| <Button | |
| type="button" | |
| variant="outline" | |
| size="sm" | |
| onClick={onBack} | |
| disabled={currentIndex === 0} | |
| > | |
| Back | |
| </Button> | |
| <div className="flex gap-2"> | |
| {!isLast && ( | |
| <Button | |
| type="button" | |
| size="sm" | |
| onClick={onNext} | |
| disabled={!canGoNext} | |
| > | |
| Next | |
| </Button> | |
| )} | |
| {isLast && ( | |
| <Button | |
| type="button" | |
| size="sm" | |
| onClick={onSubmit} | |
| disabled={isSubmitting || !canGoNext} | |
| > | |
| {isSubmitting ? "Submitting..." : "Submit"} | |
| </Button> | |
| )} | |
| </div> | |
| </CardFooter> | |
| </Card> | |
| ); | |
| } | |