File size: 2,576 Bytes
f305a41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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>
  );
}