feat: enhance checkout process with purchase editing and status handling

- Implemented purchase editing functionality in CheckoutPageComponent, allowing users to modify items in their purchase.
- Added a new guard (checkoutPendingPurchaseGuard) to prevent navigation away from the checkout page while a purchase is in progress.
- Updated the login page to handle return URLs after authentication.
- Enhanced product detail page to support direct purchases with a new buyNow method.
- Introduced new UI elements and logic to handle purchase status, including expired and rejected states in PurchaseStatusPageComponent.
- Improved cart component to allow editing of item quantities with a toggle button.
- Added quantity selector enhancements to disable controls when necessary.
- Updated tests to cover new functionalities and ensure proper behavior of components.
This commit is contained in:
2026-07-27 12:49:00 -03:00
parent 9dcedc9382
commit 902f65d8d0
31 changed files with 1253 additions and 219 deletions

View File

@@ -1,13 +1,15 @@
<div
class="quantity-selector d-inline-flex align-items-center overflow-hidden rounded"
[class.quantity-selector--small]="size() === 'small'"
[class.quantity-selector--disabled]="disabled()"
aria-label="Selector de cantidad"
[attr.aria-disabled]="disabled()"
>
<button
type="button"
class="quantity-selector__button border-0 p-0 fw-bold lh-1"
aria-label="Disminuir cantidad"
[disabled]="quantity() <= min()"
[disabled]="disabled() || quantity() <= min()"
(click)="onDecrease()"
>
-
@@ -22,7 +24,7 @@
type="button"
class="quantity-selector__button border-0 p-0 fw-bold lh-1"
aria-label="Aumentar cantidad"
[disabled]="atMaximum()"
[disabled]="disabled() || atMaximum()"
(click)="onIncrease()"
>
+

View File

@@ -60,3 +60,7 @@
}
}
}
.quantity-selector--disabled {
opacity: 0.55;
}

View File

@@ -52,4 +52,21 @@ describe('QuantitySelectorComponent', () => {
expect(decreaseButton.disabled).toBe(true);
expect(fixture.componentInstance.quantity()).toBe(1);
});
it('disables both controls and ignores quantity changes when disabled', () => {
const fixture = TestBed.createComponent(QuantitySelectorComponent);
fixture.componentRef.setInput('quantity', 2);
fixture.componentRef.setInput('disabled', true);
fixture.detectChanges();
const buttons = fixture.nativeElement.querySelectorAll('button') as NodeListOf<HTMLButtonElement>;
expect(Array.from(buttons).every((button) => button.disabled)).toBe(true);
expect(fixture.nativeElement.querySelector('[aria-disabled="true"]')).not.toBeNull();
(fixture.componentInstance as any).onIncrease();
(fixture.componentInstance as any).onDecrease();
expect(fixture.componentInstance.quantity()).toBe(2);
});
});

View File

@@ -13,6 +13,7 @@ export class QuantitySelectorComponent {
readonly min = input<number>(1);
readonly max = input<number | null>(100);
readonly size = input<'small' | 'medium'>('medium');
readonly disabled = input<boolean>(false);
protected readonly atMaximum = computed(() => {
const max = this.max();
@@ -23,14 +24,14 @@ export class QuantitySelectorComponent {
readonly decrease = output<void>();
protected onDecrease(): void {
if (this.quantity() > this.min()) {
if (!this.disabled() && this.quantity() > this.min()) {
this.quantity.set(this.quantity() - 1);
this.decrease.emit();
}
}
protected onIncrease(): void {
if (!this.atMaximum()) {
if (!this.disabled() && !this.atMaximum()) {
this.quantity.set(this.quantity() + 1);
this.increase.emit();
}