1
0
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
thesis_shop/lib/bloc/cart_bloc.dart

96 lines
3.1 KiB

import 'dart:async';
import 'package:thesis_shop/bloc/product_bloc.dart';
import 'package:thesis_shop/models/cart_item.dart';
import 'package:thesis_shop/models/product.dart';
import 'package:thesis_shop/utils/disposable.dart';
part 'cart_events.dart';
typedef Cart = Map<Product, int>;
const Cart emptyCart = {};
class CartBloc implements Disposable {
Cart _cart = {};
Cart get cart => _cart;
final StreamController<Cart> _cartController = StreamController.broadcast();
Stream<Cart> get cartStream => _cartController.stream;
Sink<Cart> get _cartSink => _cartController.sink;
int get numberOfProducts => _cart.length;
late final Stream<int> numberOfProductsStream;
/*
int numberOfProduct(Product product) => _cart[product] ?? 0;
Stream<int> numberOfProductStream(Product product) =>
cartStream.map((event) => event[product] ?? 0);*/
double get totalPrice => cart.calculateTotalPrice();
Stream<double> get totalPriceStream =>
cartStream.map((event) => event.calculateTotalPrice());
final StreamController<ChangeQuantityEvent> _quantityEventController =
StreamController.broadcast();
Sink<ChangeQuantityEvent> get quantityEventSink =>
_quantityEventController.sink;
Stream<ChangeQuantityEvent> get _quantityEventStream =>
_quantityEventController.stream;
CartBloc(ProductBloc productBloc) {
numberOfProductsStream =
_cartController.stream.map((cart) => cart.length).asBroadcastStream();
_handleProductEvents(productBloc);
_handleQuantityChangeEvents();
}
void _handleProductEvents(ProductBloc productBloc) {
productBloc.productsStateStream.listen((event) {
if (event.hasError()) {
_cart = emptyCart;
_cartSink.add(emptyCart);
} else if (event.isLoaded()) {
final products = event.productsOrEmptyList();
final productsByName = {
for (final product in products) product.title: product
};
_cart.removeWhere((key, _) => !productsByName.containsKey(key.title));
_cart = _cart
.map((key, value) => MapEntry(productsByName[key.title]!, value));
_cartSink.add(_cart);
}
});
}
void _handleQuantityChangeEvents() {
_quantityEventStream.listen((event) {
late final int summand;
if (event is IncreaseQuantityEvent) {
summand = 1;
} else if (event is DecreaseQuantityEvent) {
summand = -1;
} else {
throw UnimplementedError();
}
final old = _cart.putIfAbsent(event.product, () => 0);
final newQuantity = old + summand;
_cart[event.product] = newQuantity.isNegative ? 0 : newQuantity;
if (_cart[event.product]! <= 0) _cart.remove(event.product);
_cartSink.add(_cart);
});
}
@override
Future<void> dispose() {
return Future.wait([_cartController.close()]);
}
}
extension CartItemConverter on Cart {
List<CartItem> toCartItems() =>
entries.map((e) => CartItem(product: e.key, amount: e.value)).toList();
double calculateTotalPrice() => entries.fold(
0,
(previousValue, element) =>
previousValue + element.key.price * element.value);
}