178 lines
4.3 KiB
Dart
178 lines
4.3 KiB
Dart
/// Cart Provider
|
|
///
|
|
/// State management for shopping cart using Riverpod.
|
|
library;
|
|
|
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
import 'package:worker/features/cart/presentation/providers/cart_state.dart';
|
|
import 'package:worker/features/products/domain/entities/product.dart';
|
|
|
|
part 'cart_provider.g.dart';
|
|
|
|
/// Cart Notifier
|
|
///
|
|
/// Manages cart state including:
|
|
/// - Adding/removing items
|
|
/// - Updating quantities
|
|
/// - Warehouse selection
|
|
/// - Discount code application
|
|
/// - Cart summary calculations
|
|
@riverpod
|
|
class Cart extends _$Cart {
|
|
@override
|
|
CartState build() {
|
|
final initialState = CartState.initial();
|
|
// Initialize with Diamond tier discount (15%)
|
|
// TODO: Get actual tier from user profile
|
|
return initialState.copyWith(
|
|
memberTier: 'Diamond',
|
|
memberDiscountPercent: 15.0,
|
|
);
|
|
}
|
|
|
|
/// Add product to cart
|
|
void addToCart(Product product, {double quantity = 1.0}) {
|
|
final existingItemIndex = state.items.indexWhere(
|
|
(item) => item.product.productId == product.productId,
|
|
);
|
|
|
|
if (existingItemIndex >= 0) {
|
|
// Update quantity if item already exists
|
|
updateQuantity(
|
|
product.productId,
|
|
state.items[existingItemIndex].quantity + quantity,
|
|
);
|
|
} else {
|
|
// Add new item
|
|
final newItem = CartItemData(
|
|
product: product,
|
|
quantity: quantity,
|
|
);
|
|
|
|
state = state.copyWith(
|
|
items: [...state.items, newItem],
|
|
);
|
|
_recalculateTotal();
|
|
}
|
|
}
|
|
|
|
/// Remove product from cart
|
|
void removeFromCart(String productId) {
|
|
state = state.copyWith(
|
|
items: state.items.where((item) => item.product.productId != productId).toList(),
|
|
);
|
|
_recalculateTotal();
|
|
}
|
|
|
|
/// Update item quantity
|
|
void updateQuantity(String productId, double newQuantity) {
|
|
if (newQuantity <= 0) {
|
|
removeFromCart(productId);
|
|
return;
|
|
}
|
|
|
|
final updatedItems = state.items.map((item) {
|
|
if (item.product.productId == productId) {
|
|
return item.copyWith(quantity: newQuantity);
|
|
}
|
|
return item;
|
|
}).toList();
|
|
|
|
state = state.copyWith(items: updatedItems);
|
|
_recalculateTotal();
|
|
}
|
|
|
|
/// Increment quantity
|
|
void incrementQuantity(String productId) {
|
|
final item = state.items.firstWhere(
|
|
(item) => item.product.productId == productId,
|
|
);
|
|
updateQuantity(productId, item.quantity + 1);
|
|
}
|
|
|
|
/// Decrement quantity
|
|
void decrementQuantity(String productId) {
|
|
final item = state.items.firstWhere(
|
|
(item) => item.product.productId == productId,
|
|
);
|
|
updateQuantity(productId, item.quantity - 1);
|
|
}
|
|
|
|
/// Clear entire cart
|
|
void clearCart() {
|
|
state = CartState.initial();
|
|
}
|
|
|
|
/// Select warehouse
|
|
void selectWarehouse(String warehouse) {
|
|
state = state.copyWith(selectedWarehouse: warehouse);
|
|
}
|
|
|
|
/// Apply discount code
|
|
void applyDiscountCode(String code) {
|
|
// TODO: Validate with backend
|
|
// For now, simulate discount application
|
|
if (code.isNotEmpty) {
|
|
state = state.copyWith(
|
|
discountCode: code,
|
|
discountCodeApplied: true,
|
|
);
|
|
_recalculateTotal();
|
|
}
|
|
}
|
|
|
|
/// Remove discount code
|
|
void removeDiscountCode() {
|
|
state = state.copyWith(
|
|
discountCode: null,
|
|
discountCodeApplied: false,
|
|
);
|
|
_recalculateTotal();
|
|
}
|
|
|
|
/// Recalculate cart totals
|
|
void _recalculateTotal() {
|
|
// Calculate subtotal
|
|
final subtotal = state.items.fold<double>(
|
|
0.0,
|
|
(sum, item) => sum + (item.product.basePrice * item.quantity),
|
|
);
|
|
|
|
// Calculate member tier discount
|
|
final memberDiscount = subtotal * (state.memberDiscountPercent / 100);
|
|
|
|
// Calculate shipping (free for now)
|
|
const shippingFee = 0.0;
|
|
|
|
// Calculate total
|
|
final total = subtotal - memberDiscount + shippingFee;
|
|
|
|
state = state.copyWith(
|
|
subtotal: subtotal,
|
|
memberDiscount: memberDiscount,
|
|
shippingFee: shippingFee,
|
|
total: total,
|
|
);
|
|
}
|
|
|
|
/// Get total quantity of all items
|
|
double get totalQuantity {
|
|
return state.items.fold<double>(
|
|
0.0,
|
|
(sum, item) => sum + item.quantity,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Cart item count provider
|
|
@riverpod
|
|
int cartItemCount(Ref ref) {
|
|
return ref.watch(cartProvider).items.length;
|
|
}
|
|
|
|
/// Cart total provider
|
|
@riverpod
|
|
double cartTotal(Ref ref) {
|
|
return ref.watch(cartProvider).total;
|
|
}
|