feature: user can change quantity and remove products
This commit is contained in:
parent
9000ea0052
commit
2b88cee10b
@ -13,3 +13,8 @@ export interface CartModel {
|
|||||||
totalPrice: number;
|
totalPrice: number;
|
||||||
items: CartItemModel[];
|
items: CartItemModel[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CartItemRequest {
|
||||||
|
productId: number;
|
||||||
|
quantity: number;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
|
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
|
||||||
import { effect, inject, Injectable, signal } from "@angular/core";
|
import { effect, inject, Injectable, signal } from "@angular/core";
|
||||||
import { API_URL } from "../tokens/api-url-tokens";
|
import { API_URL } from "../tokens/api-url-tokens";
|
||||||
import { CartModel } from "../models/cart.model";
|
import { CartItemModel, CartItemRequest, CartModel } from "../models/cart.model";
|
||||||
import { AuthService, AuthState } from "@app/features/auth/services/auth-service";
|
import { AuthService, AuthState } from "@app/features/auth/services/auth-service";
|
||||||
|
import { Cart } from "@app/shared/components/cart/cart";
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: "root",
|
providedIn: "root",
|
||||||
@ -36,4 +37,12 @@ export class CartService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateCart(data: CartItemRequest) {
|
||||||
|
return this.http.patch<CartModel>(this.apiUrl + "/cart", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFromCart(productId: number) {
|
||||||
|
return this.http.delete<CartModel>(this.apiUrl + "/cart", { body: { productId: productId } });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,17 +7,19 @@
|
|||||||
<p class="text-sm truncate max-w-30 mt-2">{{ cartItem.title }}</p>
|
<p class="text-sm truncate max-w-30 mt-2">{{ cartItem.title }}</p>
|
||||||
<div class="mt-auto flex space-x-4 items-center text-gray-600">
|
<div class="mt-auto flex space-x-4 items-center text-gray-600">
|
||||||
<p class="text-sm">Rs. {{ cartItem.price }} x {{ cartItem.quantity }}</p>
|
<p class="text-sm">Rs. {{ cartItem.price }} x {{ cartItem.quantity }}</p>
|
||||||
<button class="active:scale-80" title="Remove Item">
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col justify-between">
|
||||||
|
<div class="mt-2 flex space-x-2 items-center">
|
||||||
|
<p class="font-medium">Rs. {{ cartItem.subtotal }}</p>
|
||||||
|
<button (click)="removeProduct()" class="active:scale-80 py-0" title="Remove Item">
|
||||||
<lucide-angular [name]="TrashIcon" class="w-3" />
|
<lucide-angular [name]="TrashIcon" class="w-3" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<p class="mt-2 font-medium flex-1">Rs. {{ cartItem.subtotal }}</p>
|
|
||||||
<div class="flex max-h-7 text-xs text-center text-gray-700">
|
<div class="flex max-h-7 text-xs text-center text-gray-700">
|
||||||
<button class="btn btn-ghost py-1! px-2 rounded-r-none!">-</button>
|
<button (click)="decrementQty()" class="btn btn-ghost py-1! px-2 rounded-r-none!">-</button>
|
||||||
<p class="py-1 px-2 border-y border-y-gray-300">{{ cartItem.quantity }}</p>
|
<p class="w-7 text-center py-1 px-2 border-y border-y-gray-300">{{ cartItem.quantity }}</p>
|
||||||
<button class="btn py-1! btn-ghost px-2 rounded-l-none!">+</button>
|
<button (click)="incrementQty()" class="btn py-1! btn-ghost px-2 rounded-l-none!">+</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { Component, Input } from "@angular/core";
|
import { Component, EventEmitter, Input, Output, signal } from "@angular/core";
|
||||||
import { CartItemModel } from "@app/core/models/cart.model";
|
import { CartItemModel, CartItemRequest } from "@app/core/models/cart.model";
|
||||||
import { LucideAngularModule, Trash } from "lucide-angular";
|
import { LucideAngularModule, Trash } from "lucide-angular";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -10,5 +10,25 @@ import { LucideAngularModule, Trash } from "lucide-angular";
|
|||||||
})
|
})
|
||||||
export class CartItem {
|
export class CartItem {
|
||||||
@Input() cartItem!: CartItemModel;
|
@Input() cartItem!: CartItemModel;
|
||||||
|
@Output() qtyChangeEvent = new EventEmitter<CartItemRequest>();
|
||||||
|
@Output() productDeleteEvent = new EventEmitter<number>();
|
||||||
TrashIcon = Trash;
|
TrashIcon = Trash;
|
||||||
|
|
||||||
|
incrementQty() {
|
||||||
|
if (this.cartItem.quantity < 10) {
|
||||||
|
this.cartItem.quantity += 1;
|
||||||
|
this.qtyChangeEvent.emit({ productId: this.cartItem.id, quantity: this.cartItem.quantity });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decrementQty() {
|
||||||
|
if (this.cartItem.quantity > 1) {
|
||||||
|
this.cartItem.quantity -= 1;
|
||||||
|
this.qtyChangeEvent.emit({ productId: this.cartItem.id, quantity: this.cartItem.quantity });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeProduct() {
|
||||||
|
this.productDeleteEvent.emit(this.cartItem.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,9 +4,17 @@
|
|||||||
} @else if (authService.authState() === AuthState.Loading) {
|
} @else if (authService.authState() === AuthState.Loading) {
|
||||||
<li><a class="block h-full w-full">Loading</a></li>
|
<li><a class="block h-full w-full">Loading</a></li>
|
||||||
} @else {
|
} @else {
|
||||||
<ol>
|
<ol
|
||||||
|
[class.pointer-events-none]="isLoading()"
|
||||||
|
[class.opacity-40]="isLoading()"
|
||||||
|
[class.cursor-block]="isLoading()"
|
||||||
|
>
|
||||||
@for (item of cart.items; track item.id) {
|
@for (item of cart.items; track item.id) {
|
||||||
<app-cart-item [cartItem]="item" />
|
<app-cart-item
|
||||||
|
(qtyChangeEvent)="updateProductQty($event)"
|
||||||
|
(productDeleteEvent)="removeProduct($event)"
|
||||||
|
[cartItem]="item"
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
import { Component, computed, inject, Input } from "@angular/core";
|
import { Component, computed, inject, Input, signal } from "@angular/core";
|
||||||
import { CartModel } from "@app/core/models/cart.model";
|
import { CartItemModel, CartItemRequest, CartModel } from "@app/core/models/cart.model";
|
||||||
import { CartItem } from "../cart-item/cart-item";
|
import { CartItem } from "../cart-item/cart-item";
|
||||||
import { AuthService, AuthState } from "@app/features/auth/services/auth-service";
|
import { AuthService, AuthState } from "@app/features/auth/services/auth-service";
|
||||||
|
import { CartService } from "@app/core/services/cart-service";
|
||||||
|
import { finalize, tap } from "rxjs";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-cart",
|
selector: "app-cart",
|
||||||
@ -12,6 +14,31 @@ import { AuthService, AuthState } from "@app/features/auth/services/auth-service
|
|||||||
export class Cart {
|
export class Cart {
|
||||||
@Input() cart!: CartModel;
|
@Input() cart!: CartModel;
|
||||||
|
|
||||||
|
isLoading = signal(false);
|
||||||
|
|
||||||
protected readonly authService = inject(AuthService);
|
protected readonly authService = inject(AuthService);
|
||||||
|
protected readonly cartService = inject(CartService);
|
||||||
protected readonly AuthState = AuthState;
|
protected readonly AuthState = AuthState;
|
||||||
|
|
||||||
|
updateProductQty(cartItem: CartItemRequest) {
|
||||||
|
this.isLoading.set(true);
|
||||||
|
|
||||||
|
this.cartService
|
||||||
|
.updateCart(cartItem)
|
||||||
|
.pipe(finalize(() => this.isLoading.set(false)))
|
||||||
|
.subscribe((cartdata) => {
|
||||||
|
this.cart = cartdata;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
removeProduct(productId: number) {
|
||||||
|
this.isLoading.set(true);
|
||||||
|
|
||||||
|
this.cartService
|
||||||
|
.removeFromCart(productId)
|
||||||
|
.pipe(finalize(() => this.isLoading.set(false)))
|
||||||
|
.subscribe((cartData) => {
|
||||||
|
this.cart = cartData;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user