parent
00eb7808d8
commit
84222618d5
@ -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…
Reference in new issue