Skip to content

Commit b6a2570

Browse files
committed
feat: restrict stepper navigation to only visited steps
- Added maxVisitedStep tracking to QuoteState to record the furthest step reached - Modified goToStep to prevent navigation beyond maxVisitedStep - Updated QuoteStepper to use maxVisitedStep for determining clickable steps instead of currentStep - Ensures users can only navigate back to steps they've already visited, preventing skipping ahead
1 parent d337086 commit b6a2570

4 files changed

Lines changed: 12 additions & 3 deletions

File tree

app/hire-me/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export default function HireMePage() {
3131
nextStep,
3232
prevStep,
3333
goToStep,
34+
maxVisitedStep,
3435
} = useQuoteBuilder();
3536

3637
const [isSubmitting, setIsSubmitting] = useState(false);
@@ -71,6 +72,7 @@ export default function HireMePage() {
7172
onNext={nextStep}
7273
onPrev={prevStep}
7374
onStepChange={goToStep}
75+
maxClickableStep={maxVisitedStep}
7476
canGoNext={
7577
state.currentStep === 6
7678
? false

src/features/hireme/components/QuoteStepper.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface QuoteStepperProps {
1111
onPrev: () => void;
1212
canGoNext: boolean;
1313
helperText?: string | null;
14+
maxClickableStep?: number;
1415
onStepChange?: (step: number) => void;
1516
}
1617

@@ -23,6 +24,7 @@ export function QuoteStepper({
2324
onPrev,
2425
canGoNext,
2526
helperText,
27+
maxClickableStep,
2628
onStepChange,
2729
}: QuoteStepperProps) {
2830
return (
@@ -46,9 +48,10 @@ export function QuoteStepper({
4648
{Array.from({ length: totalSteps }, (_, index) => {
4749
const stepNumber = index + 1;
4850
const isCurrent = stepNumber === currentStep;
49-
const isVisited = stepNumber <= currentStep;
51+
const effectiveMax = maxClickableStep ?? currentStep;
52+
const isVisited = stepNumber <= effectiveMax;
5053

51-
const canClick = !!onStepChange && stepNumber <= currentStep;
54+
const canClick = !!onStepChange && stepNumber <= effectiveMax;
5255

5356
return (
5457
<button

src/features/hireme/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export interface ContactDetails {
4848

4949
export interface QuoteState {
5050
currentStep: number;
51+
maxVisitedStep: number;
5152
projectType: ProjectType | null;
5253
basePrice: number;
5354
baseTimeline: TimelineRange | null;

src/features/hireme/useQuoteBuilder.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const INITIAL_CONTACT = {
3434

3535
const INITIAL_STATE: QuoteState = {
3636
currentStep: 1,
37+
maxVisitedStep: 1,
3738
projectType: null,
3839
basePrice: 0,
3940
baseTimeline: null,
@@ -242,6 +243,7 @@ export function useQuoteBuilder() {
242243
setState((prev) => ({
243244
...prev,
244245
currentStep: Math.min(prev.currentStep + 1, 6),
246+
maxVisitedStep: Math.max(prev.maxVisitedStep, Math.min(prev.currentStep + 1, 6)),
245247
}));
246248
}, []);
247249

@@ -255,7 +257,7 @@ export function useQuoteBuilder() {
255257
const goToStep = useCallback((step: number) => {
256258
setState((prev) => ({
257259
...prev,
258-
currentStep: Math.min(Math.max(step, 1), 6),
260+
currentStep: Math.min(Math.max(step, 1), prev.maxVisitedStep),
259261
}));
260262
}, []);
261263

@@ -283,6 +285,7 @@ export function useQuoteBuilder() {
283285
priceAfterComplexity,
284286
priceAfterTimeline,
285287
roundedFinalPrice,
288+
maxVisitedStep: state.maxVisitedStep,
286289
projectTypes: PROJECT_TYPES,
287290
budgetRanges: BUDGET_RANGES,
288291
featuresByProjectType: FEATURES_BY_PROJECT_TYPE,

0 commit comments

Comments
 (0)