1
0
Fork 0

Add user discount

bloc
Jonas Franz 2 years ago
parent 93956b32fe
commit 543c59bfcc
  1. 2
      lib/app.dart
  2. 11
      lib/bloc/cart_bloc.dart
  3. 39
      lib/bloc/product_bloc.dart
  4. 19
      lib/models/product.dart
  5. 2
      lib/screens/cart/total_price_text.dart
  6. 8
      lib/screens/product_list/product_item.dart

@ -16,7 +16,7 @@ class ThesisShopApp extends StatelessWidget {
BlocProvider setupBlocs() {
final userBloc = UserBloc();
final productBloc = ProductBloc(productService);
final productBloc = ProductBloc(productService, userBloc);
final cartBloc = CartBloc(productBloc);
return BlocProvider(
productBloc: productBloc,

@ -20,10 +20,10 @@ class CartBloc implements Disposable {
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);
cartStream.map((event) => event[product] ?? 0);*/
double get totalPrice => cart.calculateTotalPrice();
Stream<double> get totalPriceStream =>
@ -53,7 +53,7 @@ class CartBloc implements Disposable {
final productsByName = {
for (final product in products) product.title: product
};
_cart.removeWhere((key, _) => productsByName.containsKey(key.title));
_cart.removeWhere((key, _) => !productsByName.containsKey(key.title));
_cart = _cart
.map((key, value) => MapEntry(productsByName[key.title]!, value));
_cartSink.add(_cart);
@ -74,6 +74,7 @@ class CartBloc implements Disposable {
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);
});
}
@ -89,5 +90,7 @@ extension CartItemConverter on Cart {
entries.map((e) => CartItem(product: e.key, amount: e.value)).toList();
double calculateTotalPrice() => entries.fold(
0, (previousValue, element) => previousValue + element.key.price);
0,
(previousValue, element) =>
previousValue + element.key.price * element.value);
}

@ -1,5 +1,6 @@
import 'dart:async';
import 'package:thesis_shop/bloc/user_bloc.dart';
import 'package:thesis_shop/models/product.dart';
import 'package:thesis_shop/service/product_service.dart';
import 'package:thesis_shop/utils/disposable.dart';
@ -9,7 +10,9 @@ part 'product_bloc_states.dart';
class ProductBloc implements Disposable {
final ProductService _productService;
final UserBloc _userBloc;
bool _hasDiscount;
var _productsState = ProductsState.loading();
ProductsState get productsState => _productsState;
@ -23,17 +26,49 @@ class ProductBloc implements Disposable {
Sink<LoadProductEvent> get loadProductSink =>
_loadProductEventController.sink;
ProductBloc(this._productService) {
ProductBloc(this._productService, this._userBloc)
: _hasDiscount = _userBloc.isSignedIn {
_handleUserEvents();
_handleLoadProductEvents();
}
void _handleUserEvents() {
_userBloc.isSignedInStream.listen((isSignedIn) {
if (isSignedIn && !_hasDiscount) {
if (_productsState.isLoaded()) {
final discountedProducts = _productsState
.as<ProductsLoaded>()
.products
.map((product) => product.copyWithDiscount())
.toList();
_productsState = ProductsState.loaded(discountedProducts);
_productsStateSink.add(_productsState);
}
} else if (!isSignedIn && _hasDiscount) {
final undiscountedProducts = _productsState
.as<ProductsLoaded>()
.products
.map((product) => product.copyWithoutDiscount())
.toList();
_productsState = ProductsState.loaded(undiscountedProducts);
_productsStateSink.add(_productsState);
}
_hasDiscount = isSignedIn;
});
}
void _handleLoadProductEvents() {
_loadProductEventController.stream.listen((_) async {
_productsState = ProductsState.loading();
_productsStateSink.add(_productsState);
try {
final products = await _productService.fetchProducts();
var products = await _productService.fetchProducts();
_hasDiscount = _userBloc.isSignedIn;
if (_hasDiscount) {
products =
products.map((product) => product.copyWithDiscount()).toList();
}
_productsState = ProductsState.loaded(products);
_productsStateSink.add(_productsState);
} catch (err) {

@ -8,4 +8,23 @@ class Product {
String get priceAsString => price.toStringAsFixed(2);
const Product({required this.title, required this.price});
Product copyWithDiscount() {
return Product(title: title, price: price * 0.8);
}
Product copyWithoutDiscount() {
return Product(title: title, price: price * 1.25);
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Product &&
runtimeType == other.runtimeType &&
title == other.title &&
price == other.price;
@override
int get hashCode => title.hashCode ^ price.hashCode;
}

@ -15,7 +15,7 @@ class TotalPriceText extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Gesamtpreis: ${snapshot.requireData}',
'Gesamtpreis: ${snapshot.requireData.toStringAsFixed(2)}',
style: Theme.of(context)
.textTheme
.labelLarge

@ -13,12 +13,12 @@ class ProductItem extends StatelessWidget {
final cartBloc = AppState.of(context).blocProvider.cartBloc;
return ListTile(
title: Text('${product.title} (${product.priceAsString}€/Stück)'),
trailing: StreamBuilder<int>(
stream: cartBloc.numberOfProductStream(product),
initialData: cartBloc.numberOfProduct(product),
trailing: StreamBuilder<Cart>(
stream: cartBloc.cartStream,
initialData: cartBloc.cart,
builder: (context, snapshot) {
return NumberPicker(
value: snapshot.requireData,
value: snapshot.requireData[product] ?? 0,
onUp: () => cartBloc.quantityEventSink
.add(IncreaseQuantityEvent(product)),
onDown: () => cartBloc.quantityEventSink

Loading…
Cancel
Save