1
0
Fork 0

Implement product store

inheritedwidget
Jonas Franz 2 years ago
parent 00eb7808d8
commit 84222618d5
  1. 8
      lib/app.dart
  2. 38
      lib/models/remote_resource.dart
  3. 43
      lib/screens/product_list/product_list_screen.dart
  4. 70
      lib/stores/product_store.dart

@ -3,6 +3,7 @@ import 'package:thesis_shop/route_key.dart';
import 'package:thesis_shop/screens/cart/cart_screen.dart';
import 'package:thesis_shop/screens/product_list/product_list_screen.dart';
import 'package:thesis_shop/service/product_service.dart';
import 'package:thesis_shop/stores/product_store.dart';
import 'package:thesis_shop/stores/user_store.dart';
import 'package:thesis_shop/utils/map_keys_extension.dart';
@ -12,7 +13,12 @@ class ThesisShopApp extends StatelessWidget {
: super(key: key);
Widget injectStores(BuildContext context, {required Widget child}) {
return UserStoreImplementation(child: child);
return UserStoreImplementation(
child: ProductStoreImplementation(
productService: productService,
child: child,
),
);
}
@override

@ -0,0 +1,38 @@
abstract class RemoteResource<T> {
RemoteResource._();
factory RemoteResource.loading() {
return LoadingRemoteResource();
}
factory RemoteResource.error(String errorMessage) {
return ErrorRemoteResource(errorMessage);
}
factory RemoteResource.finished(T value) {
return FinishedRemoteResource(value);
}
FinishedRemoteResource<T> asFinished() {
return this as FinishedRemoteResource<T>;
}
ErrorRemoteResource<T> asError() {
return this as ErrorRemoteResource<T>;
}
}
class ErrorRemoteResource<T> extends RemoteResource<T> {
final String errorMessage;
ErrorRemoteResource(this.errorMessage) : super._();
}
class LoadingRemoteResource<T> extends RemoteResource<T> {
LoadingRemoteResource() : super._();
}
class FinishedRemoteResource<T> extends RemoteResource<T> {
final T value;
FinishedRemoteResource(this.value) : super._();
}

@ -1,31 +1,44 @@
import 'package:flutter/material.dart';
import 'package:thesis_shop/models/product.dart';
import 'package:thesis_shop/models/remote_resource.dart';
import 'package:thesis_shop/screens/product_list/cart_button_overlay.dart';
import 'package:thesis_shop/screens/product_list/product_list.dart';
import 'package:thesis_shop/stores/product_store.dart';
import 'package:thesis_shop/widgets/user_switch.dart';
import 'cart_button_overlay.dart';
import 'product_list.dart';
const _productPlaceholder = [
Product(title: 'Bananen', price: 3),
Product(title: 'Äpfel', price: 2),
Product(title: 'Birnen', price: 2.5),
Product(title: 'Kirschen', price: 1.2),
];
class ProductListScreen extends StatelessWidget {
const ProductListScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
const products = _productPlaceholder;
return Scaffold(
appBar: AppBar(
title: const Text('Thesis Shop'),
actions: const [UserSwitch()],
),
body: const CartButtonOverlay(
child: ProductList(products: products),
),
body: const _ProductStateSwitch(),
);
}
}
class _ProductStateSwitch extends StatelessWidget {
const _ProductStateSwitch({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final remoteProducts = ProductStore.of(context).products;
if (remoteProducts is FinishedRemoteResource) {
final products = remoteProducts.asFinished().value;
return CartButtonOverlay(
child: ProductList(
products: products,
),
);
} else if (remoteProducts is ErrorRemoteResource) {
return Center(child: Text(remoteProducts.asError().errorMessage));
} else if (remoteProducts is LoadingRemoteResource) {
return const Center(child: CircularProgressIndicator.adaptive());
} else {
throw UnimplementedError();
}
}
}

@ -0,0 +1,70 @@
import 'package:flutter/widgets.dart';
import 'package:thesis_shop/models/product.dart';
import 'package:thesis_shop/models/remote_resource.dart';
import 'package:thesis_shop/service/product_service.dart';
class ProductStoreImplementation extends StatefulWidget {
final Widget child;
final ProductService productService;
const ProductStoreImplementation({
Key? key,
required this.child,
required this.productService,
}) : super(key: key);
@override
_ProductStoreImplementationState createState() =>
_ProductStoreImplementationState();
}
class _ProductStoreImplementationState
extends State<ProductStoreImplementation> {
RemoteResource<List<Product>> products = RemoteResource.loading();
@override
void initState() {
super.initState();
loadProducts().catchError(
(err) => setState(
() {
products = RemoteResource.error(err.toString());
},
),
);
}
Future<void> loadProducts() async {
final remoteProducts = await widget.productService.fetchProducts();
setState(() {
products = RemoteResource.finished(remoteProducts);
});
}
@override
Widget build(BuildContext context) {
return ProductStore(products: products, child: widget.child);
}
}
class ProductStore extends InheritedWidget {
const ProductStore({
Key? key,
required this.products,
required Widget child,
}) : super(key: key, child: child);
final RemoteResource<List<Product>> products;
List<Product> get mustProducts => products.asFinished().value;
static ProductStore of(BuildContext context) {
final ProductStore? result =
context.dependOnInheritedWidgetOfExactType<ProductStore>();
assert(result != null, 'No ProductStore found in context');
return result!;
}
@override
bool updateShouldNotify(ProductStore oldWidget) {
return oldWidget.products != products;
}
}
Loading…
Cancel
Save