Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 82 additions & 13 deletions components/stepper/stepper.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,83 @@
interface StepperProps {}

export default function Stepper() {
/*TODO: Replace this with the actual Stepper implementation*/
return (
<div
className={
"h-[100px] border border-dashed border-gray-200 rounded flex justify-center items-center"
}
>
<code className={"text-2xl"}>{"<Stepper />"}</code>
</div>
);
import { steps } from "./steps";

interface StepperProps {
currentStep: number;
onStepClick: (stepId: number) => void;
}

const Stepper: React.FC<StepperProps> = ({ currentStep, onStepClick }) => {
const getStepStatus = (
stepId: number
): "completed" | "current" | "upcoming" => {
if (stepId < currentStep) return "completed";
if (stepId === currentStep) return "current";
return "upcoming";
};

const isClickable = (stepId: number): boolean => {
return stepId <= currentStep;
};

return (
<div className="flex items-center justify-center p-4 mb-6 lg:mb-0">
<div className="flex items-center justify-center w-full">
{steps.map((step, index) => {
const status = getStepStatus(step.id);
const clickable = isClickable(step.id);
const isLast = index === steps.length - 1;

return (
<div
key={step.id}
className={`flex items-center ${isLast ? "" : "flex-grow"}`}
>
<div className="relative">
<button
onClick={() => clickable && onStepClick(step.id)}
disabled={!clickable}
className={`w-[30px] h-[30px] lg:w-10 lg:h-10 rounded-full flex items-center justify-center
text-xs lg:text-sm font-semibold transition-colors
${
status === "completed" || status === "current"
? "bg-blue-500 text-white"
: "bg-gray-200 text-gray-700"
}
${
clickable
? "cursor-pointer hover:opacity-80"
: "cursor-not-allowed"
}`}
aria-label={`Step ${step.id}: ${step.label}`}
aria-current={status === "current" ? "step" : undefined}
>
{step.id}
</button>

<span
className={`absolute top-full left-1/2 transform -translate-x-1/2 mt-1 lg:mt-1 text-xs lg:text-base font-semibold whitespace-nowrap
${
status === "completed" || status === "current"
? "text-gray-700"
: "text-gray-500"
}`}
>
{step.label}
</span>
</div>

{!isLast && (
<div
className={`h-1 lg:h-1.5 flex-grow ${
status === "completed" ? "bg-blue-500" : "bg-gray-200"
}`}
/>
)}
</div>
);
})}
</div>
</div>
);
};

export default Stepper;
12 changes: 9 additions & 3 deletions components/stepper/steps.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
interface Step {
title: string;
export interface Step {
id: number;
label: string;
}

export const steps: Step[] = [];
export const steps: Step[] = [
{ id: 1, label: "Service" },
{ id: 2, label: "Termin" },
{ id: 3, label: "Fahrzeug" },
{ id: 4, label: "Kontakt" },
];
41 changes: 32 additions & 9 deletions hooks/useStepper.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
import { useState } from "react";
import { steps } from "../components/stepper/steps";

export default function useStepper() {
const [currentStep, setCurrentStep] = useState<number>(0);
function handleNextStep() {
setCurrentStep((prev) => {
return prev + 1;
});
}
return { currentStep, handleNextStep };
}
const useStepper = () => {
const [currentStep, setCurrentStep] = useState(1);

const handleNextStep = () => {
setCurrentStep((prev) => Math.min(prev + 1, steps.length));
};

const handlePrevStep = () => {
setCurrentStep((prev) => Math.max(prev - 1, 1));
};

const handleStepClick = (stepId: number) => {
if (stepId <= currentStep) {
setCurrentStep(stepId);
}
};

const isFirstStep = currentStep === 1;
const isLastStep = currentStep === steps.length;

return {
currentStep,
handleNextStep,
handlePrevStep,
handleStepClick,
isFirstStep,
isLastStep,
};
};

export default useStepper;
33 changes: 18 additions & 15 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,22 @@ import Stepper from "../components/stepper/stepper";
import useStepper from "../hooks/useStepper";

export default function Home() {
const { currentStep, handleNextStep } = useStepper();
return (
<>
<Header />
<MainWrapper>
<StepperWrapper>
{/*TODO: Make sure the Stepper handles clicks on the button*/}
<Stepper />
</StepperWrapper>
<ButtonWrapper>
<Button onClick={handleNextStep}>Next</Button>
</ButtonWrapper>
</MainWrapper>
</>
);
const { currentStep, handleNextStep, handleStepClick, isLastStep } =
useStepper();

return (
<>
<Header />
<MainWrapper>
<StepperWrapper>
<Stepper currentStep={currentStep} onStepClick={handleStepClick} />
</StepperWrapper>
{!isLastStep && (
<ButtonWrapper>
<Button onClick={handleNextStep}>Next</Button>
</ButtonWrapper>
)}
</MainWrapper>
</>
);
}