feat: update cart service and components to handle productVariantId, improve item removal and addition feedback
This commit is contained in:
@@ -54,6 +54,7 @@ export class StoreLayoutComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
productVariantId: item.product_variant_id,
|
||||||
imageUrl: item.product?.imagen ?? null,
|
imageUrl: item.product?.imagen ?? null,
|
||||||
product,
|
product,
|
||||||
originalPrice: null,
|
originalPrice: null,
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ describe('CartService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should add item and update signal', () => {
|
it('should add item and update signal', () => {
|
||||||
service.addItem(10, 2).subscribe((cart) => {
|
service.addItem(10, 2).subscribe((res) => {
|
||||||
expect(cart).toEqual(mockCart);
|
expect(res.data).toEqual(mockCart);
|
||||||
expect(service.cart()).toEqual(mockCart);
|
expect(service.cart()).toEqual(mockCart);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export class CartService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addItem(productVariantId: number, cantidad: number): Observable<Cart> {
|
addItem(productVariantId: number, cantidad: number): Observable<ApiResponse<Cart>> {
|
||||||
return this.http
|
return this.http
|
||||||
.post<ApiResponse<Cart>>(
|
.post<ApiResponse<Cart>>(
|
||||||
`${this.tenantApiUrl}/cart/items`,
|
`${this.tenantApiUrl}/cart/items`,
|
||||||
@@ -39,8 +39,7 @@ export class CartService {
|
|||||||
{ withCredentials: true }
|
{ withCredentials: true }
|
||||||
)
|
)
|
||||||
.pipe(
|
.pipe(
|
||||||
map((response) => response.data),
|
tap((response) => this.cartState.set(response.data))
|
||||||
tap((cart) => this.cartState.set(cart))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ describe('ProductDetailPageComponent', () => {
|
|||||||
navigate: vi.fn()
|
navigate: vi.fn()
|
||||||
};
|
};
|
||||||
cartServiceStub = {
|
cartServiceStub = {
|
||||||
addItem: vi.fn().mockReturnValue(of({}))
|
addItem: vi.fn().mockReturnValue(of({ message: 'Producto agregado al carrito' }))
|
||||||
};
|
};
|
||||||
toastServiceStub = {
|
toastServiceStub = {
|
||||||
success: vi.fn(),
|
success: vi.fn(),
|
||||||
@@ -277,6 +277,8 @@ describe('ProductDetailPageComponent', () => {
|
|||||||
it('keeps quantity at a minimum of one and increments locally', async () => {
|
it('keeps quantity at a minimum of one and increments locally', async () => {
|
||||||
await configureTestingModule();
|
await configureTestingModule();
|
||||||
const fixture = TestBed.createComponent(ProductDetailPageComponent);
|
const fixture = TestBed.createComponent(ProductDetailPageComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
fixture.componentInstance['selectedVariant'].set({
|
fixture.componentInstance['selectedVariant'].set({
|
||||||
variant_id: 1,
|
variant_id: 1,
|
||||||
cantidad_maxima: 10,
|
cantidad_maxima: 10,
|
||||||
|
|||||||
@@ -230,8 +230,9 @@ export class ProductDetailPageComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
this.addingToCart.set(true);
|
this.addingToCart.set(true);
|
||||||
this.cartService.addItem(variant.variant_id, this.quantity()).subscribe({
|
this.cartService.addItem(variant.variant_id, this.quantity()).subscribe({
|
||||||
next: () => {
|
next: (res) => {
|
||||||
this.toastService.success('Producto agregado al carrito');
|
const msg = res.message || 'Producto agregado al carrito';
|
||||||
|
this.toastService.success(msg);
|
||||||
this.addingToCart.set(false);
|
this.addingToCart.set(false);
|
||||||
},
|
},
|
||||||
error: (err: HttpErrorResponse) => {
|
error: (err: HttpErrorResponse) => {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { CartService } from '../../../core/services/cart/cart.service';
|
|||||||
import { ToastService } from '../../../core/services/toast.service';
|
import { ToastService } from '../../../core/services/toast.service';
|
||||||
|
|
||||||
export interface CartItemMock {
|
export interface CartItemMock {
|
||||||
|
productVariantId?: number;
|
||||||
imageUrl: string | null;
|
imageUrl: string | null;
|
||||||
product: string;
|
product: string;
|
||||||
originalPrice: number | null;
|
originalPrice: number | null;
|
||||||
@@ -68,19 +69,29 @@ export class CartComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected onItemQuantityChange(index: number, newQuantity: number): void {
|
protected onItemQuantityChange(index: number, newQuantity: number): void {
|
||||||
const item = this.cartService.cart()?.items[index];
|
const mockItem = this.items()[index];
|
||||||
if (item) {
|
const productVariantId = mockItem?.productVariantId;
|
||||||
|
if (productVariantId) {
|
||||||
this.quantityUpdates$.next({
|
this.quantityUpdates$.next({
|
||||||
productVariantId: item.product_variant_id,
|
productVariantId,
|
||||||
quantity: newQuantity
|
quantity: newQuantity
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
const item = this.cartService.cart()?.items[index];
|
||||||
|
if (item) {
|
||||||
|
this.quantityUpdates$.next({
|
||||||
|
productVariantId: item.product_variant_id,
|
||||||
|
quantity: newQuantity
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected onItemRemove(index: number): void {
|
protected onItemRemove(index: number): void {
|
||||||
const item = this.cartService.cart()?.items[index];
|
const mockItem = this.items()[index];
|
||||||
if (item) {
|
const productVariantId = mockItem?.productVariantId;
|
||||||
this.cartService.removeItem(item.product_variant_id).subscribe({
|
if (productVariantId) {
|
||||||
|
this.cartService.removeItem(productVariantId).subscribe({
|
||||||
next: (res) => {
|
next: (res) => {
|
||||||
const msg = res.message || 'Producto eliminado del carrito.';
|
const msg = res.message || 'Producto eliminado del carrito.';
|
||||||
this.toastService.success(msg);
|
this.toastService.success(msg);
|
||||||
@@ -91,6 +102,21 @@ export class CartComponent {
|
|||||||
this.toastService.danger(msg);
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user