diff --git a/git-authors.toml b/.git-authors.toml similarity index 100% rename from git-authors.toml rename to .git-authors.toml diff --git a/mobile/lib/controllers/cart.dart b/mobile/lib/controllers/cart.dart index 2cfa3cf..c36e2d7 100644 --- a/mobile/lib/controllers/cart.dart +++ b/mobile/lib/controllers/cart.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:mobile/controllers/session.dart'; import 'package:mobile/models/cart_item.dart'; import 'package:mobile/models/product.dart'; import 'package:mobile/results.dart'; @@ -27,7 +28,9 @@ class CartControllerMemory extends CartController { final Server server; final List cart = []; - CartControllerMemory({required this.server}); + final SessionController sessionController; + + CartControllerMemory({required this.server, required this.sessionController}); @override List allCartItems() { @@ -116,10 +119,12 @@ class CartControllerMemory extends CartController { notifyListeners(); } - Future> purchase(String token) async { - final res = await server.purchaseCart(token, cart); + Future> purchase() async { + final res = await sessionController.requestWithSession( + (server, sessionToken) => server.purchaseCart(sessionToken, cart)); switch (res) { case Ok(): + await sessionController.loadUpdatedUser(); return const Ok(null); case Err(value: final message): return Err(message); @@ -133,7 +138,8 @@ class CartControllerCache extends CartControllerMemory { return File("${directory.path}/cart.json").create(); } - CartControllerCache({required super.server}) { + CartControllerCache( + {required super.server, required super.sessionController}) { load(); } diff --git a/mobile/lib/controllers/session.dart b/mobile/lib/controllers/session.dart index c3cba2d..991e39f 100644 --- a/mobile/lib/controllers/session.dart +++ b/mobile/lib/controllers/session.dart @@ -26,24 +26,22 @@ class SessionController { } } - Future> loadUser() async { + Future> loadCachedUser() async { // TODO: retrieve session from cache, if exists return _loadCurrentUser(); } + Future> loadUpdatedUser() async { + return _loadCurrentUser(); + } + Future> _loadCurrentUser() async { - final sessionUserResult = await _requestWithSession( + final sessionUserResult = await requestWithSession( (server, sessionToken) => server.sessionUser(sessionToken)); switch (sessionUserResult) { case Ok(value: final sessionUser): _sessionUser = sessionUser; notifyUserChangeListeners(); - - // The mechanism for checking that a user is logged in, only listens on - // the session provider. There we also notify sessions listeners, to - // account for this one specific case. Is this smart? idk. - notifySessionChangeListeners(); - return const Ok(null); case Err(): return const Err(null); @@ -73,7 +71,7 @@ class SessionController { } Future> addBalance() async { - final addBalanceResult = await _requestWithSession( + final addBalanceResult = await requestWithSession( (server, sessionToken) => server.addBalance(sessionToken)); if (addBalanceResult case Err(value: final message)) { return Err(message); @@ -85,7 +83,7 @@ class SessionController { } /// Package private. - Future> _requestWithSession( + Future> requestWithSession( Future> Function(Server server, String sessionToken) func) async { final sessionToken = _sessionToken; @@ -105,29 +103,25 @@ class SessionController { return result; } - /// Package private. - void _addSessionChangeListener(_ChangeListener listener) { - _sessionChangeListeners.add(listener); - } - - /// Package private. - void _addUserChangeListener(_ChangeListener listener) { - _userChangeListeners.add(listener); - } - - /// Class private. void notifySessionChangeListeners() { for (final listener in _sessionChangeListeners) { listener.notify(); } } - /// Class private. void notifyUserChangeListeners() { for (final listener in _userChangeListeners) { listener.notify(); } } + + void _addSessionChangeListener(_ChangeListener listener) { + _sessionChangeListeners.add(listener); + } + + void _addUserChangeListener(_ChangeListener listener) { + _userChangeListeners.add(listener); + } } abstract class _ChangeListener { diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index 4a1fb12..4dd10c7 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -21,7 +21,7 @@ void main() { final usersController = UsersController(server: server); final sessionController = SessionController(server: server); - sessionController.loadUser(); + sessionController.loadCachedUser(); runApp(MyApp( usersController: usersController, @@ -54,7 +54,8 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider( create: (_) => ProductController(server: server)), ChangeNotifierProvider( - create: (_) => CartControllerCache(server: server)), + create: (_) => CartControllerCache( + server: server, sessionController: sessionController)), ChangeNotifierProvider(create: (_) => ReceiptController()), ChangeNotifierProvider(create: (_) => PayingStateController()), ChangeNotifierProvider(create: (_) => AddToCartStateController()), @@ -71,13 +72,13 @@ class MyApp extends StatelessWidget { GoogleFonts.merriweatherTextTheme(Theme.of(context).textTheme), useMaterial3: true, ), - home: Consumer( - builder: (_, provider, ___) { - if (provider.controller.hasUser) { + home: Consumer2( + builder: (_, provider1, provider2, ___) { + if (provider1.controller.hasUser) { return Dashboard(); } return FutureBuilder( - future: provider.controller.loadUser(), + future: provider1.controller.loadCachedUser(), builder: (_, snapshot) { final error = snapshot.error; if (error != null) { diff --git a/mobile/lib/pages/finish_shopping_page.dart b/mobile/lib/pages/finish_shopping_page.dart index 1e08115..731fe84 100644 --- a/mobile/lib/pages/finish_shopping_page.dart +++ b/mobile/lib/pages/finish_shopping_page.dart @@ -57,42 +57,40 @@ class FinishShoppingPage extends StatelessWidget { child: Center( child: PrimaryButton( onPressed: () async { - // final session = context.read(); - // payingStateRepo.next(); - // await Future.delayed(const Duration(seconds: 1)); - // if (cartController.purchase(session.sessionToken!) - // is Err) { - // if (context.mounted) { - // showDialog( - // context: context, - // builder: (BuildContext context) => - // AlertDialog( - // content: const Text( - // 'Du har desværre ikke råd til at købe dette'), - // actions: [ - // TextButton( - // onPressed: () => - // Navigator.pop(context, 'OK'), - // child: const Text('OK'), - // ), - // ], - // ), - // ); - // } - // payingStateRepo.reset(); - // return; - // } - // receiptRepo.createReceipt(cart); - // payingStateRepo.next(); - // await Future.delayed(const Duration(seconds: 1)); - // cartController.clearCart(); - // payingStateRepo.reset(); - // if (context.mounted) { - // Navigator.pop(context); - // final RoutingController routing = - // context.read(); - // routing.routeTo(PageSelector.homePage); - // } + payingStateRepo.next(); + await Future.delayed(const Duration(seconds: 1)); + if (cartController.purchase() is Err) { + if (context.mounted) { + showDialog( + context: context, + builder: (BuildContext context) => + AlertDialog( + content: const Text( + 'Du har desværre ikke råd til at købe dette'), + actions: [ + TextButton( + onPressed: () => + Navigator.pop(context, 'OK'), + child: const Text('OK'), + ), + ], + ), + ); + } + payingStateRepo.reset(); + return; + } + receiptRepo.createReceipt(cart); + payingStateRepo.next(); + await Future.delayed(const Duration(seconds: 1)); + cartController.clearCart(); + payingStateRepo.reset(); + if (context.mounted) { + Navigator.pop(context); + final RoutingController routing = + context.read(); + routing.routeTo(PageSelector.homePage); + } }, child: const Text("Betal"))), ), diff --git a/mobile/lib/server/backend_server.dart b/mobile/lib/server/backend_server.dart index b24f319..e3f80a9 100644 --- a/mobile/lib/server/backend_server.dart +++ b/mobile/lib/server/backend_server.dart @@ -102,15 +102,21 @@ class BackendServer implements Server { @override Future> purchaseCart( String token, List cartItems) async { - final res = await http.post(Uri.parse("$_apiUrl/carts/purchase"), headers: { - "Content-Type": "application/json", - "Session-Token": token - }, body: { - "cart_items": cartItems - .map((cartItem) => - {"product_id": cartItem.product.id, "amount": cartItem.amount}) - .toList() - }).then((res) => json.decode(res.body)); + final res = await http + .post(Uri.parse("$_apiUrl/carts/purchase"), + headers: { + "Content-Type": "application/json", + "Session-Token": token + }, + body: json.encode({ + "cart_items": cartItems + .map((cartItem) => { + "product_id": cartItem.product.id, + "amount": cartItem.amount + }) + .toList() + })) + .then((res) => json.decode(res.body)); if (res["ok"]) { return Ok(null);