feat(cart): integrate confirmation modals for item removal in cart component

This commit is contained in:
2026-07-02 12:04:29 -03:00
parent 446d1b8970
commit bf5fd83f98
6 changed files with 253 additions and 61 deletions

View File

@@ -4,6 +4,7 @@ import { Subject, EMPTY } from 'rxjs';
import { catchError, debounceTime, groupBy, mergeMap, switchMap, tap } from 'rxjs';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { CartItemAttribute, CartItemComponent } from '../cart-item/cart-item.component';
import { ModalService } from '../../../core/services/modal.service';
import { CartService } from '../../../core/services/cart/cart.service';
import { ToastService } from '../../../core/services/toast.service';
@@ -28,6 +29,7 @@ export interface CartItemMock {
})
export class CartComponent {
private readonly cartService = inject(CartService);
private readonly modalService = inject(ModalService);
private readonly toastService = inject(ToastService);
private readonly quantityUpdates$ = new Subject<{ productVariantId: number; quantity: number }>();
@@ -88,36 +90,22 @@ export class CartComponent {
}
protected onItemRemove(index: number): void {
const mockItem = this.items()[index];
const productVariantId = mockItem?.productVariantId;
if (productVariantId) {
this.cartService.removeItem(productVariantId).subscribe({
next: (res) => {
const msg = res.message || 'Producto eliminado del carrito.';
this.toastService.success(msg);
},
error: (err: HttpErrorResponse) => {
console.error('Error removing item from cart', err);
const msg = err.error?.message || 'Error al eliminar el producto del carrito.';
this.toastService.danger(msg);
}
});
} else {
const item = this.cartService.cart()?.items[index];
if (item) {
this.cartService.removeItem(item.product_variant_id).subscribe({
next: (res) => {
const msg = res.message || 'Producto eliminado del carrito.';
this.toastService.success(msg);
},
error: (err: HttpErrorResponse) => {
console.error('Error removing item from cart', err);
const msg = err.error?.message || 'Error al eliminar el producto del carrito.';
this.toastService.danger(msg);
}
});
}
const target = this.resolveRemoveTarget(index);
if (!target) {
return;
}
this.modalService.openConfirmDelete({
title: 'Eliminar producto',
content: `Se eliminara "${target.productName}" del carrito. Esta accion no se puede deshacer.`,
confirmLabel: 'Eliminar',
cancelLabel: 'Cancelar'
}).subscribe((confirmed) => {
if (confirmed) {
this.removeItem(target.productVariantId);
}
});
}
protected readonly formattedSubtotal = computed(() => this.formatCurrency(this.subtotal()));
@@ -130,5 +118,44 @@ export class CartComponent {
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, '.');
return `$ ${parts.join(',')}`;
}
private resolveRemoveTarget(
index: number
): { productVariantId: number; productName: string } | null {
const mockItem = this.items()[index];
const productVariantId = mockItem?.productVariantId;
if (productVariantId) {
return {
productVariantId,
productName: mockItem.product
};
}
const item = this.cartService.cart()?.items[index];
if (!item) {
return null;
}
return {
productVariantId: item.product_variant_id,
productName: item.product?.nombre ?? 'este producto'
};
}
private removeItem(productVariantId: number): void {
this.cartService.removeItem(productVariantId).subscribe({
next: (res) => {
const msg = res.message || 'Producto eliminado del carrito.';
this.toastService.info(msg);
},
error: (err: HttpErrorResponse) => {
console.error('Error removing item from cart', err);
const msg = err.error?.message || 'Error al eliminar el producto del carrito.';
this.toastService.danger(msg);
}
});
}
}