1
0
Fork 0

Add user and product providers

riverpod
Jonas Franz 2 years ago
parent dfbd608f8c
commit 1a53d7b583
  1. 29
      lib/app.dart
  2. 2
      lib/models/product.dart
  3. 2
      lib/screens/cart/cart_screen.dart
  4. 27
      lib/screens/product_list/product_list_screen.dart
  5. 13
      lib/stores/product_list_provider.dart
  6. 6
      lib/stores/product_loading_provider.dart
  7. 16
      lib/stores/product_service_provider.dart
  8. 12
      lib/stores/user_store.dart
  9. 18
      lib/widgets/user_switch.dart
  10. 22
      pubspec.lock
  11. 3
      pubspec.yaml

@ -1,8 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
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_service_provider.dart';
import 'package:thesis_shop/utils/map_keys_extension.dart';
class ThesisShopApp extends StatelessWidget {
@ -12,18 +14,23 @@ class ThesisShopApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Thesis Shop',
theme: ThemeData(primarySwatch: Colors.red),
darkTheme: ThemeData(
primarySwatch: Colors.red,
brightness: Brightness.dark,
return ProviderScope(
overrides: [
productServiceProvider.overrideWithValue(productService),
],
child: MaterialApp(
title: 'Thesis Shop',
theme: ThemeData(primarySwatch: Colors.red),
darkTheme: ThemeData(
primarySwatch: Colors.red,
brightness: Brightness.dark,
),
routes: {
RouteKey.products: (context) => const ProductListScreen(),
RouteKey.cart: (context) => const CartScreen(),
}.mapKeys((key) => key.name),
initialRoute: 'products',
),
routes: {
RouteKey.products: (context) => const ProductListScreen(),
RouteKey.cart: (context) => const CartScreen(),
}.mapKeys((key) => key.name),
initialRoute: 'products',
);
}
}

@ -8,4 +8,6 @@ class Product {
String get priceAsString => price.toStringAsFixed(2);
const Product({required this.title, required this.price});
Product copyWithDiscount() => Product(title: title, price: price * 0.8);
}

@ -20,7 +20,7 @@ class CartScreen extends StatelessWidget {
return Scaffold(
appBar: AppBar(
title: const Text('Warenkorb'),
actions: [UserSwitch(isOn: true, onChanged: (_) {})],
actions: const [UserSwitch()],
),
body: Column(
mainAxisSize: MainAxisSize.max,

@ -1,31 +1,28 @@
import 'package:flutter/material.dart';
import 'package:thesis_shop/models/product.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:thesis_shop/stores/product_list_provider.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 {
class ProductListScreen extends ConsumerWidget {
const ProductListScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
const products = _productPlaceholder;
Widget build(BuildContext context, ref) {
return Scaffold(
appBar: AppBar(
title: const Text('Thesis Shop'),
actions: [UserSwitch(isOn: true, onChanged: (_) {})],
),
body: const CartButtonOverlay(
child: ProductList(products: products),
actions: const [UserSwitch()],
),
body: ref.watch(productListProvider).when(
data: (products) => CartButtonOverlay(
child: ProductList(products: products),
),
error: (error, _) => Center(child: Text(error.toString())),
loading: () => const Center(child: CircularProgressIndicator()),
),
);
}
}

@ -0,0 +1,13 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:thesis_shop/models/product.dart';
import 'package:thesis_shop/stores/product_loading_provider.dart';
import 'package:thesis_shop/stores/user_store.dart';
final productListProvider = Provider<AsyncValue<List<Product>>>((ref) {
final isSignedIn = ref.watch(userStoreProvider);
if (!isSignedIn) {
return ref.watch(productLoadingProvider);
}
return ref.watch(productLoadingProvider).whenData(
(products) => products.map((pro) => pro.copyWithDiscount()).toList());
});

@ -0,0 +1,6 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:thesis_shop/stores/product_service_provider.dart';
final productLoadingProvider = FutureProvider(
(ref) => ref.read(productServiceProvider).fetchProducts(),
dependencies: [productServiceProvider]);

@ -0,0 +1,16 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:thesis_shop/models/product.dart';
import 'package:thesis_shop/service/product_service.dart';
class ProductServiceImplementationPlaceholder implements ProductService {
@override
Future<List<Product>> fetchProducts() {
throw UnimplementedError();
}
@override
String get url => throw UnimplementedError();
}
final productServiceProvider = Provider<ProductService>(
(ref) => ProductServiceImplementationPlaceholder());

@ -0,0 +1,12 @@
import 'package:riverpod/riverpod.dart';
class UserStore extends StateNotifier<bool> {
UserStore({bool initialSignInStatus = false}) : super(initialSignInStatus);
void changeSignInStatus(bool newStatus) {
state = newStatus;
}
}
final userStoreProvider =
StateNotifierProvider<UserStore, bool>((ref) => UserStore());

@ -1,24 +1,22 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:thesis_shop/benchmark_counter.dart';
import 'package:thesis_shop/stores/user_store.dart';
class UserSwitch extends StatelessWidget {
final bool isOn;
final ValueChanged<bool> onChanged;
const UserSwitch({
required this.isOn,
required this.onChanged,
}) : super(key: const Key('user_switch'));
class UserSwitch extends ConsumerWidget {
const UserSwitch() : super(key: const Key('user_switch'));
@override
Widget build(BuildContext context) {
Widget build(BuildContext context, ref) {
final isSignedIn = ref.watch(userStoreProvider);
BenchmarkCounters.userSwitch++;
return Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.account_circle),
Switch(
value: isOn,
onChanged: onChanged,
value: isSignedIn,
onChanged: ref.read(userStoreProvider.notifier).changeSignInStatus,
activeColor: Colors.green,
)
],

@ -146,6 +146,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
flutter_riverpod:
dependency: "direct main"
description:
name: flutter_riverpod
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
flutter_test:
dependency: "direct dev"
description: flutter
@ -228,6 +235,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
riverpod:
dependency: "direct main"
description:
name: riverpod
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
sky_engine:
dependency: transitive
description: flutter
@ -247,6 +261,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
state_notifier:
dependency: transitive
description:
name: state_notifier
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.2+1"
stream_channel:
dependency: transitive
description:
@ -305,3 +326,4 @@ packages:
version: "3.1.0"
sdks:
dart: ">=2.16.1 <3.0.0"
flutter: ">=1.17.0"

@ -30,6 +30,8 @@ dependencies:
flutter:
sdk: flutter
http: ^0.13.4
riverpod: 1.0.3
flutter_riverpod: 1.0.3
dev_dependencies:
flutter_test:
sdk: flutter
@ -40,7 +42,6 @@ dev_dependencies:
# rules and activating additional ones.
flutter_lints: ^1.0.0
dart_code_metrics: ^4.10.1
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

Loading…
Cancel
Save