diff --git a/src/app/features/store/pages/checkout-page/checkout-page.component.html b/src/app/features/store/pages/checkout-page/checkout-page.component.html index 72645d8..57a7eb2 100644 --- a/src/app/features/store/pages/checkout-page/checkout-page.component.html +++ b/src/app/features/store/pages/checkout-page/checkout-page.component.html @@ -6,7 +6,11 @@ } @else {
- + - -
+
@for (step of steps(); track step; let i = $index; let last = $last) {
@if (i > 0) { -
+
}
@@ -33,5 +35,4 @@
-
diff --git a/src/app/shared/components/stepper/stepper.component.scss b/src/app/shared/components/stepper/stepper.component.scss index 62525f3..657f4a4 100644 --- a/src/app/shared/components/stepper/stepper.component.scss +++ b/src/app/shared/components/stepper/stepper.component.scss @@ -13,6 +13,14 @@ margin-bottom: 2rem; position: relative; + &.is-disabled { + opacity: 0.5; + + .stepper-header__circle { + cursor: not-allowed; + } + } + &__item { display: flex; flex-direction: column; diff --git a/src/app/shared/components/stepper/stepper.component.spec.ts b/src/app/shared/components/stepper/stepper.component.spec.ts index f377043..19f76f5 100644 --- a/src/app/shared/components/stepper/stepper.component.spec.ts +++ b/src/app/shared/components/stepper/stepper.component.spec.ts @@ -6,7 +6,7 @@ import { StepComponent } from './step.component'; @Component({ imports: [StepperComponent, StepComponent], template: ` - +
Content 1
@@ -20,6 +20,7 @@ class TestHostComponent { @ViewChild('stepper') stepper!: StepperComponent; step1Valid = signal(true); step2Valid = signal(true); + stepperDisabled = signal(false); } describe('StepperComponent & StepComponent', () => { @@ -137,4 +138,28 @@ describe('StepperComponent & StepComponent', () => { expect(component.stepper.currentStepIndex()).toBe(0); expect(fixture.nativeElement.querySelector('#content-1')).not.toBeNull(); }); + + it('blocks all navigation and shows visual feedback while disabled', async () => { + const { fixture, component } = await setup(); + component.stepperDisabled.set(true); + fixture.detectChanges(); + + component.stepper.next(); + expect(component.stepper.currentStepIndex()).toBe(0); + + component.stepperDisabled.set(false); + fixture.detectChanges(); + component.stepper.next(); + expect(component.stepper.currentStepIndex()).toBe(1); + + component.stepperDisabled.set(true); + fixture.detectChanges(); + component.stepper.previous(); + component.stepper.goToStep(0); + + expect(component.stepper.currentStepIndex()).toBe(1); + const header = fixture.nativeElement.querySelector('.stepper-header'); + expect(header.classList.contains('is-disabled')).toBe(true); + expect(header.getAttribute('aria-disabled')).toBe('true'); + }); }); diff --git a/src/app/shared/components/stepper/stepper.component.ts b/src/app/shared/components/stepper/stepper.component.ts index fc92dcf..b6ac734 100644 --- a/src/app/shared/components/stepper/stepper.component.ts +++ b/src/app/shared/components/stepper/stepper.component.ts @@ -18,9 +18,12 @@ import { NgClass } from '@angular/common'; export class StepperComponent { readonly steps = contentChildren(StepComponent); readonly initialStepIndex = input(0); + readonly disabled = input(false); readonly currentStepIndex = linkedSignal(() => this.initialStepIndex()); next() { + if (this.disabled()) return; + const currentSteps = this.steps(); const currentIndex = this.currentStepIndex(); if (currentIndex < currentSteps.length - 1) { @@ -32,6 +35,8 @@ export class StepperComponent { } previous() { + if (this.disabled()) return; + const currentIndex = this.currentStepIndex(); if (currentIndex > 0) { this.currentStepIndex.set(currentIndex - 1); @@ -39,6 +44,8 @@ export class StepperComponent { } goToStep(index: number) { + if (this.disabled()) return; + const targetIndex = index; // Only allow navigating to completed steps or the current one if (targetIndex < this.currentStepIndex()) {