mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-28 08:44:06 +02:00
implement auth - almost works
This commit is contained in:
parent
28f9bb46e2
commit
be00f1c965
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:mobile/models/product.dart';
|
import 'package:mobile/models/product.dart';
|
||||||
|
import 'package:mobile/results.dart';
|
||||||
|
|
||||||
class ProductIdException implements Exception {}
|
class ProductIdException implements Exception {}
|
||||||
|
|
||||||
@ -82,6 +83,10 @@ class CartController extends ChangeNotifier {
|
|||||||
cart.clear();
|
cart.clear();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<Null, String> pay() {
|
||||||
|
return const Err("Not implemented");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CartItem {
|
class CartItem {
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:mobile/models/product.dart';
|
import 'package:mobile/models/product.dart';
|
||||||
import 'package:mobile/results.dart';
|
import 'package:mobile/results.dart';
|
||||||
import 'package:mobile/server/mock_server.dart';
|
|
||||||
import 'package:mobile/server/server.dart';
|
import 'package:mobile/server/server.dart';
|
||||||
|
|
||||||
class ProductController extends ChangeNotifier {
|
class ProductController extends ChangeNotifier {
|
||||||
final server = MockServer();
|
final Server server;
|
||||||
|
|
||||||
List<Product> products = [];
|
List<Product> products = [];
|
||||||
String query = "";
|
String query = "";
|
||||||
ProductController() {
|
ProductController({required this.server}) {
|
||||||
fetchProductsFromServer();
|
fetchProductsFromServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:mobile/models/user.dart';
|
||||||
|
import 'package:mobile/results.dart';
|
||||||
|
import 'package:mobile/server/server.dart';
|
||||||
|
|
||||||
|
class SessionController extends ChangeNotifier {
|
||||||
|
final Server server;
|
||||||
|
String? _sessionToken;
|
||||||
|
|
||||||
|
SessionController({required this.server});
|
||||||
|
|
||||||
|
Future<Result<Null, String>> login(String email, String password) async {
|
||||||
|
switch (await server.login(email, password)) {
|
||||||
|
case Success<String>(data: final token):
|
||||||
|
_sessionToken = token;
|
||||||
|
notifyListeners();
|
||||||
|
return const Ok(null);
|
||||||
|
case Error<String>(message: final message):
|
||||||
|
notifyListeners();
|
||||||
|
return Err(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Result<User, Null>> user() async {
|
||||||
|
final token = _sessionToken;
|
||||||
|
if (token == null) {
|
||||||
|
notifyListeners();
|
||||||
|
return const Err(null);
|
||||||
|
}
|
||||||
|
final res = await server.sessionUser(token);
|
||||||
|
switch (res) {
|
||||||
|
case Success<User>(data: final user):
|
||||||
|
return Ok(user);
|
||||||
|
case Error<User>():
|
||||||
|
_sessionToken = null;
|
||||||
|
notifyListeners();
|
||||||
|
return const Err(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get sessionToken {
|
||||||
|
return _sessionToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> logout() async {
|
||||||
|
final token = _sessionToken;
|
||||||
|
if (token != null) {
|
||||||
|
server.logout(token);
|
||||||
|
_sessionToken = null;
|
||||||
|
}
|
||||||
|
print(_sessionToken);
|
||||||
|
print("notifying listeners");
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<int, String> pay(int userId, int amount) {
|
||||||
|
return const Err("not implemented");
|
||||||
|
}
|
||||||
|
}
|
@ -1,136 +1,20 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:mobile/results.dart';
|
import 'package:mobile/results.dart';
|
||||||
|
import 'package:mobile/server/server.dart';
|
||||||
|
|
||||||
class UsersControllerOld extends ChangeNotifier {
|
class UsersController extends ChangeNotifier {
|
||||||
int nextId = 0;
|
Server server;
|
||||||
final List<User> users = [];
|
|
||||||
|
|
||||||
User? _loggedInUser;
|
UsersController({required this.server});
|
||||||
|
|
||||||
UsersControllerOld() {
|
Future<Result<Null, String>> register(
|
||||||
addTestUsers();
|
String name, String email, String password) async {
|
||||||
}
|
final res = await server.register(name, email, password);
|
||||||
|
switch (res) {
|
||||||
Result<User, String> getUserById(int id) {
|
case Success<Null>():
|
||||||
for (var i = 0; i < users.length; i++) {
|
return const Ok(null);
|
||||||
if (users[i].id == id) {
|
case Error<Null>(message: final message):
|
||||||
return Ok(users[i]);
|
return Err(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err("User with id $id doesn't exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<User, String> getUserByMail(String mail) {
|
|
||||||
for (var i = 0; i < users.length; i++) {
|
|
||||||
if (users[i].mail == mail) {
|
|
||||||
return Ok(users[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Err("User with mail $mail doesn't exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<User, String> addUser(String name, String mail, String password) {
|
|
||||||
if (getUserByMail(mail) is Ok) {
|
|
||||||
return Err("User with mail $mail already exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
final user = User(
|
|
||||||
id: nextId++,
|
|
||||||
name: name,
|
|
||||||
mail: mail,
|
|
||||||
password: password,
|
|
||||||
balanceInDkkCents: 0);
|
|
||||||
users.add(user);
|
|
||||||
|
|
||||||
return Ok(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<User, String> login(String mail, String password) {
|
|
||||||
User? user;
|
|
||||||
for (var i = 0; i < users.length; i++) {
|
|
||||||
if (users[i].mail == mail) {
|
|
||||||
user = users[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (user == null) {
|
|
||||||
return Err("User with mail $mail doesn't exist");
|
|
||||||
}
|
|
||||||
if (user.password != password) {
|
|
||||||
return Err("Wrong password for user with mail $mail");
|
|
||||||
}
|
|
||||||
_loggedInUser = user;
|
|
||||||
notifyListeners();
|
|
||||||
return Ok(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
void logout() {
|
|
||||||
_loggedInUser = null;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
User? loggedInUser() {
|
|
||||||
return _loggedInUser;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<int, String> pay(int userId, int amount) {
|
|
||||||
final user = getUserById(userId);
|
|
||||||
if (user is Ok) {
|
|
||||||
return (user as User).pay(amount);
|
|
||||||
}
|
|
||||||
return Err("User with id $userId doesn't exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
void addTestUsers() {
|
|
||||||
users
|
|
||||||
..add(User(
|
|
||||||
id: nextId++,
|
|
||||||
mail: "test@test.com",
|
|
||||||
name: "test",
|
|
||||||
password: "test",
|
|
||||||
balanceInDkkCents: 10000))
|
|
||||||
..add(User(
|
|
||||||
id: nextId++,
|
|
||||||
mail: "",
|
|
||||||
name: "",
|
|
||||||
password: "",
|
|
||||||
balanceInDkkCents: 100000));
|
|
||||||
}
|
|
||||||
|
|
||||||
void veryBadNotifyAll() {
|
|
||||||
// ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
|
|
||||||
// TODO: THIS SHOULD BE FIXED
|
|
||||||
// FIXME: DO SOMETHING ELSE PLEASE!!!!!
|
|
||||||
// ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class User {
|
|
||||||
final int id;
|
|
||||||
final String mail;
|
|
||||||
final String name;
|
|
||||||
final String password;
|
|
||||||
|
|
||||||
// balance is in øre
|
|
||||||
int balanceInDkkCents;
|
|
||||||
|
|
||||||
User({
|
|
||||||
required this.id,
|
|
||||||
required this.mail,
|
|
||||||
required this.name,
|
|
||||||
required this.password,
|
|
||||||
required this.balanceInDkkCents,
|
|
||||||
});
|
|
||||||
|
|
||||||
void addBalanceFounds(int amount) {
|
|
||||||
balanceInDkkCents += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<int, String> pay(int amount) {
|
|
||||||
if (balanceInDkkCents < amount) {
|
|
||||||
return Err("User can not afford paying amount $amount");
|
|
||||||
}
|
|
||||||
balanceInDkkCents -= amount;
|
|
||||||
return Ok(balanceInDkkCents);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'package:mobile/controllers/session.dart';
|
||||||
|
import 'package:mobile/models/user.dart';
|
||||||
|
import 'package:mobile/pages/dashboard.dart';
|
||||||
import 'package:mobile/pages/log_in_page.dart';
|
import 'package:mobile/pages/log_in_page.dart';
|
||||||
import 'package:mobile/controllers/add_to_cart_state.dart';
|
import 'package:mobile/controllers/add_to_cart_state.dart';
|
||||||
import 'package:mobile/controllers/cart.dart';
|
import 'package:mobile/controllers/cart.dart';
|
||||||
@ -8,6 +11,7 @@ import 'package:mobile/controllers/paying_state.dart';
|
|||||||
import 'package:mobile/controllers/product.dart';
|
import 'package:mobile/controllers/product.dart';
|
||||||
import 'package:mobile/controllers/receipt.dart';
|
import 'package:mobile/controllers/receipt.dart';
|
||||||
import 'package:mobile/controllers/user.dart';
|
import 'package:mobile/controllers/user.dart';
|
||||||
|
import 'package:mobile/server/mock_server.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:mobile/controllers/routing.dart';
|
import 'package:mobile/controllers/routing.dart';
|
||||||
|
|
||||||
@ -20,16 +24,20 @@ class MyApp extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final server = MockServer();
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
ChangeNotifierProvider(create: (_) => RoutingController()),
|
ChangeNotifierProvider(create: (_) => RoutingController()),
|
||||||
ChangeNotifierProvider(create: (_) => ProductController()),
|
ChangeNotifierProvider(
|
||||||
|
create: (_) => ProductController(server: server)),
|
||||||
ChangeNotifierProvider(create: (_) => CartController()),
|
ChangeNotifierProvider(create: (_) => CartController()),
|
||||||
ChangeNotifierProvider(create: (_) => ReceiptController()),
|
ChangeNotifierProvider(create: (_) => ReceiptController()),
|
||||||
ChangeNotifierProvider(create: (_) => PayingStateController()),
|
ChangeNotifierProvider(create: (_) => PayingStateController()),
|
||||||
ChangeNotifierProvider(create: (_) => AddToCartStateController()),
|
ChangeNotifierProvider(create: (_) => AddToCartStateController()),
|
||||||
ChangeNotifierProvider(create: (_) => LocationImageController()),
|
ChangeNotifierProvider(create: (_) => LocationImageController()),
|
||||||
ChangeNotifierProvider(create: (_) => UsersControllerOld()),
|
ChangeNotifierProvider(create: (_) => UsersController(server: server)),
|
||||||
|
ChangeNotifierProvider(
|
||||||
|
create: (_) => SessionController(server: server)),
|
||||||
],
|
],
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
title: 'Fresh Plaza',
|
title: 'Fresh Plaza',
|
||||||
@ -41,8 +49,12 @@ class MyApp extends StatelessWidget {
|
|||||||
GoogleFonts.merriweatherTextTheme(Theme.of(context).textTheme),
|
GoogleFonts.merriweatherTextTheme(Theme.of(context).textTheme),
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
),
|
),
|
||||||
home: const LogInPage(),
|
home: Consumer<SessionController>(
|
||||||
),
|
builder: (_, sessionController, __) {
|
||||||
|
if (sessionController.sessionToken is String) return Dashboard();
|
||||||
|
return const LogInPage();
|
||||||
|
},
|
||||||
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
35
mobile/lib/models/user.dart
Normal file
35
mobile/lib/models/user.dart
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import 'package:mobile/results.dart';
|
||||||
|
|
||||||
|
class User {
|
||||||
|
final int id;
|
||||||
|
final String email;
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
// balance is in øre
|
||||||
|
int balanceInDkkCents;
|
||||||
|
|
||||||
|
User({
|
||||||
|
required this.id,
|
||||||
|
required this.email,
|
||||||
|
required this.name,
|
||||||
|
required this.balanceInDkkCents,
|
||||||
|
});
|
||||||
|
|
||||||
|
User.fromJson(Map<String, dynamic> json)
|
||||||
|
: id = json["id"],
|
||||||
|
email = json["email"],
|
||||||
|
name = json["name"],
|
||||||
|
balanceInDkkCents = json["balanceInDkkCents"];
|
||||||
|
|
||||||
|
void addBalanceFounds(int amount) {
|
||||||
|
balanceInDkkCents += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<int, String> pay(int amount) {
|
||||||
|
if (balanceInDkkCents < amount) {
|
||||||
|
return Err("User can not afford paying amount $amount");
|
||||||
|
}
|
||||||
|
balanceInDkkCents -= amount;
|
||||||
|
return Ok(balanceInDkkCents);
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,6 @@ import 'package:mobile/models/product.dart';
|
|||||||
import 'package:mobile/pages/finish_shopping_page.dart';
|
import 'package:mobile/pages/finish_shopping_page.dart';
|
||||||
import 'package:mobile/controllers/cart.dart';
|
import 'package:mobile/controllers/cart.dart';
|
||||||
import 'package:mobile/controllers/product.dart';
|
import 'package:mobile/controllers/product.dart';
|
||||||
import 'package:mobile/controllers/user.dart';
|
|
||||||
import 'package:mobile/results.dart';
|
import 'package:mobile/results.dart';
|
||||||
import 'package:mobile/utils/price.dart';
|
import 'package:mobile/utils/price.dart';
|
||||||
import 'package:mobile/widgets/primary_button.dart';
|
import 'package:mobile/widgets/primary_button.dart';
|
||||||
@ -144,8 +143,7 @@ class CartItemView extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CartPage extends StatelessWidget {
|
class CartPage extends StatelessWidget {
|
||||||
final User user;
|
const CartPage({super.key});
|
||||||
const CartPage({super.key, required this.user});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -316,7 +314,7 @@ class CartPage extends StatelessWidget {
|
|||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
FinishShoppingPage(user: user)));
|
const FinishShoppingPage()));
|
||||||
},
|
},
|
||||||
child: const Text("Afslut indkøb")),
|
child: const Text("Afslut indkøb")),
|
||||||
),
|
),
|
||||||
|
@ -5,21 +5,16 @@ import 'package:mobile/pages/all_receipts_page.dart';
|
|||||||
import 'package:mobile/pages/home_page.dart';
|
import 'package:mobile/pages/home_page.dart';
|
||||||
import 'package:mobile/controllers/routing.dart';
|
import 'package:mobile/controllers/routing.dart';
|
||||||
import 'package:mobile/controllers/cart.dart';
|
import 'package:mobile/controllers/cart.dart';
|
||||||
import 'package:mobile/controllers/user.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class Dashboard extends StatelessWidget {
|
class Dashboard extends StatelessWidget {
|
||||||
final User user;
|
|
||||||
|
|
||||||
final List<StatelessWidget> pages = [];
|
final List<StatelessWidget> pages = [];
|
||||||
|
|
||||||
Dashboard({super.key, required this.user}) {
|
Dashboard({super.key}) {
|
||||||
pages.addAll([
|
pages.addAll([
|
||||||
HomePage(
|
const HomePage(),
|
||||||
user: user,
|
|
||||||
),
|
|
||||||
const AllProductsPage(),
|
const AllProductsPage(),
|
||||||
CartPage(user: user),
|
const CartPage(),
|
||||||
const AllReceiptsPage(),
|
const AllReceiptsPage(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ import 'package:mobile/controllers/routing.dart';
|
|||||||
import 'package:mobile/controllers/cart.dart';
|
import 'package:mobile/controllers/cart.dart';
|
||||||
import 'package:mobile/controllers/paying_state.dart';
|
import 'package:mobile/controllers/paying_state.dart';
|
||||||
import 'package:mobile/controllers/receipt.dart';
|
import 'package:mobile/controllers/receipt.dart';
|
||||||
import 'package:mobile/controllers/user.dart';
|
|
||||||
import 'package:mobile/results.dart';
|
import 'package:mobile/results.dart';
|
||||||
import 'package:mobile/utils/price.dart';
|
import 'package:mobile/utils/price.dart';
|
||||||
import 'package:mobile/widgets/primary_button.dart';
|
import 'package:mobile/widgets/primary_button.dart';
|
||||||
@ -11,17 +10,15 @@ import 'package:mobile/widgets/receipt_item.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class FinishShoppingPage extends StatelessWidget {
|
class FinishShoppingPage extends StatelessWidget {
|
||||||
final User user;
|
const FinishShoppingPage({super.key});
|
||||||
|
|
||||||
const FinishShoppingPage({super.key, required this.user});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final CartController cartRepo = context.read<CartController>();
|
final CartController cartController = context.read<CartController>();
|
||||||
final ReceiptController receiptRepo = context.read<ReceiptController>();
|
final ReceiptController receiptRepo = context.read<ReceiptController>();
|
||||||
final PayingStateController payingStateRepo =
|
final PayingStateController payingStateRepo =
|
||||||
context.watch<PayingStateController>();
|
context.watch<PayingStateController>();
|
||||||
final cart = cartRepo.allCartItems();
|
final cart = cartController.allCartItems();
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
@ -50,7 +47,7 @@ class FinishShoppingPage extends StatelessWidget {
|
|||||||
"Total:",
|
"Total:",
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
Text(formatDkkCents(cartRepo.totalPrice())),
|
Text(formatDkkCents(cartController.totalPrice())),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -60,7 +57,8 @@ class FinishShoppingPage extends StatelessWidget {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
payingStateRepo.next();
|
payingStateRepo.next();
|
||||||
await Future.delayed(const Duration(seconds: 1));
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
if (user.pay(cartRepo.totalPrice()) is Err) {
|
// TODO: implement paying for user
|
||||||
|
if (cartController.pay() is Err) {
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
showDialog<String>(
|
showDialog<String>(
|
||||||
context: context,
|
context: context,
|
||||||
@ -84,7 +82,7 @@ class FinishShoppingPage extends StatelessWidget {
|
|||||||
receiptRepo.createReceipt(cart);
|
receiptRepo.createReceipt(cart);
|
||||||
payingStateRepo.next();
|
payingStateRepo.next();
|
||||||
await Future.delayed(const Duration(seconds: 1));
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
cartRepo.clearCart();
|
cartController.clearCart();
|
||||||
payingStateRepo.reset();
|
payingStateRepo.reset();
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:mobile/controllers/session.dart';
|
||||||
import 'package:mobile/pages/settings_page.dart';
|
import 'package:mobile/pages/settings_page.dart';
|
||||||
import 'package:mobile/controllers/user.dart';
|
import 'package:mobile/utils/build_if_session_exists.dart';
|
||||||
import 'package:mobile/utils/price.dart';
|
import 'package:mobile/utils/price.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class HomePage extends StatelessWidget {
|
class HomePage extends StatelessWidget {
|
||||||
final User user;
|
const HomePage({super.key});
|
||||||
const HomePage({super.key, required this.user});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final sessionController = context.read<SessionController>();
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
@ -33,20 +34,24 @@ class HomePage extends StatelessWidget {
|
|||||||
color: Color(0xFFFFFFFF),
|
color: Color(0xFFFFFFFF),
|
||||||
),
|
),
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
child: Consumer<UsersControllerOld>(
|
child: BuildIfSessionExists(
|
||||||
builder: (context, usersRepo, _) => Text(
|
sessionController: sessionController,
|
||||||
|
placeholder: const CircularProgressIndicator(),
|
||||||
|
builder: (context, user) => Text(
|
||||||
"Saldo: ${formatDkkCents(user.balanceInDkkCents)}",
|
"Saldo: ${formatDkkCents(user.balanceInDkkCents)}",
|
||||||
style: Theme.of(context).textTheme.headlineSmall)),
|
style: Theme.of(context).textTheme.headlineSmall))),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
BuildIfSessionExists(
|
||||||
|
sessionController: sessionController,
|
||||||
|
placeholder: const CircularProgressIndicator(),
|
||||||
|
builder: (context, user) => Text(
|
||||||
"Velkommen ${user.name}",
|
"Velkommen ${user.name}",
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
style: Theme.of(context).textTheme.headlineMedium,
|
||||||
),
|
))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:mobile/controllers/session.dart';
|
||||||
import 'package:mobile/pages/register_page.dart';
|
import 'package:mobile/pages/register_page.dart';
|
||||||
import 'package:mobile/controllers/user.dart';
|
|
||||||
import 'package:mobile/results.dart';
|
import 'package:mobile/results.dart';
|
||||||
import 'package:mobile/widgets/error_box.dart';
|
import 'package:mobile/widgets/error_box.dart';
|
||||||
import 'package:mobile/widgets/primary_button.dart';
|
import 'package:mobile/widgets/primary_button.dart';
|
||||||
import 'package:mobile/widgets/primary_input.dart';
|
import 'package:mobile/widgets/primary_input.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'dashboard.dart';
|
|
||||||
|
|
||||||
class LogInPage extends StatelessWidget {
|
class LogInPage extends StatelessWidget {
|
||||||
const LogInPage({super.key});
|
const LogInPage({super.key});
|
||||||
@ -61,18 +60,14 @@ class LogInFormState extends State<LogInForm> {
|
|||||||
controller: passwordController,
|
controller: passwordController,
|
||||||
),
|
),
|
||||||
PrimaryButton(
|
PrimaryButton(
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
final usersRepo = context.read<UsersControllerOld>();
|
final sessionController = context.read<SessionController>();
|
||||||
final loginResult =
|
final loginResult = await sessionController.login(
|
||||||
usersRepo.login(mailController.text, passwordController.text);
|
mailController.text, passwordController.text);
|
||||||
|
switch (loginResult) {
|
||||||
if (loginResult is Ok) {
|
case Ok<Null, String>():
|
||||||
setState(() => loginError = false);
|
setState(() => loginError = false);
|
||||||
Navigator.of(context).popUntil((_) => false);
|
case Err<Null, String>():
|
||||||
Navigator.of(context).push(MaterialPageRoute(
|
|
||||||
builder: (context) =>
|
|
||||||
Dashboard(user: (loginResult as Ok).value)));
|
|
||||||
} else {
|
|
||||||
setState(() => loginError = true);
|
setState(() => loginError = true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -71,9 +71,9 @@ class RegisterFormState extends State<RegisterForm> {
|
|||||||
obscure: true),
|
obscure: true),
|
||||||
PrimaryButton(
|
PrimaryButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
final usersRepo = context.read<UsersControllerOld>();
|
final sessionsRepo = context.read<UsersController>();
|
||||||
if (usersRepo.addUser(nameController.text, mailController.text,
|
if (sessionsRepo.register(nameController.text,
|
||||||
passwordController.text) is Ok) {
|
mailController.text, passwordController.text) is Ok) {
|
||||||
setState(() => registerError = false);
|
setState(() => registerError = false);
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:mobile/pages/log_in_page.dart';
|
import 'package:mobile/controllers/session.dart';
|
||||||
import 'package:mobile/pages/settings_pages/saldo.dart';
|
import 'package:mobile/pages/settings_pages/saldo.dart';
|
||||||
import 'package:mobile/controllers/user.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class _Page {
|
class _Page {
|
||||||
@ -31,11 +30,9 @@ class SettingsPage extends StatelessWidget {
|
|||||||
icon: Icons.door_back_door,
|
icon: Icons.door_back_door,
|
||||||
title: "Log ud",
|
title: "Log ud",
|
||||||
action: (context) {
|
action: (context) {
|
||||||
final users = context.read<UsersControllerOld>();
|
final sessionsController = context.read<SessionController>();
|
||||||
users.logout();
|
|
||||||
Navigator.popUntil(context, (_) => false);
|
Navigator.popUntil(context, (_) => false);
|
||||||
Navigator.of(context)
|
sessionsController.logout();
|
||||||
.push(MaterialPageRoute(builder: (context) => const LogInPage()));
|
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:mobile/controllers/user.dart';
|
import 'package:mobile/controllers/session.dart';
|
||||||
|
import 'package:mobile/utils/build_if_session_exists.dart';
|
||||||
import 'package:mobile/utils/price.dart';
|
import 'package:mobile/utils/price.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
@ -8,8 +9,7 @@ class SaldoSettingsPage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final usersRepo = context.watch<UsersControllerOld>();
|
final sessionController = context.watch<SessionController>();
|
||||||
final user = usersRepo.loggedInUser()!;
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
@ -25,12 +25,17 @@ class SaldoSettingsPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Text("Nuværende saldo: ${formatDkkCents(user.balanceInDkkCents)}",
|
BuildIfSessionExists(
|
||||||
|
sessionController: sessionController,
|
||||||
|
placeholder: const CircularProgressIndicator(),
|
||||||
|
builder: (context, user) => Text(
|
||||||
|
"Nuværende saldo: ${formatDkkCents(user.balanceInDkkCents)}",
|
||||||
style: Theme.of(context).textTheme.bodyLarge),
|
style: Theme.of(context).textTheme.bodyLarge),
|
||||||
|
),
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
user.addBalanceFounds(10000);
|
// TODO: implement add balance
|
||||||
usersRepo.veryBadNotifyAll();
|
throw Exception("not implemented: Adding funds");
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.add),
|
icon: const Icon(Icons.add),
|
||||||
label: const Text("Tilføj 100,00 kr"),
|
label: const Text("Tilføj 100,00 kr"),
|
||||||
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
|||||||
|
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:mobile/models/product.dart';
|
import 'package:mobile/models/product.dart';
|
||||||
|
import 'package:mobile/models/user.dart';
|
||||||
import 'package:mobile/server/server.dart';
|
import 'package:mobile/server/server.dart';
|
||||||
|
|
||||||
class BackendServer implements Server {
|
class BackendServer implements Server {
|
||||||
@ -51,16 +52,61 @@ class BackendServer implements Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Response<Null>> login(
|
Future<Response<String>> login(
|
||||||
String name,
|
|
||||||
String email,
|
String email,
|
||||||
String password,
|
String password,
|
||||||
) async {
|
) async {
|
||||||
final res = await _post(
|
final res = await _post(
|
||||||
endpoint: "auth/login",
|
endpoint: "sessions/login",
|
||||||
body: {"email": email, "password": password},
|
body: {"email": email, "password": password},
|
||||||
).then((res) => json.decode(res.body));
|
).then((res) => json.decode(res.body));
|
||||||
|
|
||||||
|
if (res["ok"]) {
|
||||||
|
return Success(data: res["token"]);
|
||||||
|
} else {
|
||||||
|
return Error(message: res["message"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Response<Null>> logout(String token) async {
|
||||||
|
final res = await _post(
|
||||||
|
endpoint: "sessions/logout",
|
||||||
|
body: {
|
||||||
|
"token": token,
|
||||||
|
},
|
||||||
|
).then((res) => json.decode(res.body));
|
||||||
|
|
||||||
|
if (res["ok"]) {
|
||||||
|
return Success(data: null);
|
||||||
|
} else {
|
||||||
|
return Error(message: res["message"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Response<User>> sessionUser(String token) async {
|
||||||
|
final res = await http
|
||||||
|
.get(
|
||||||
|
Uri.parse("$_apiUrl/sessions/user/$token"),
|
||||||
|
)
|
||||||
|
.then((res) => json.decode(res.body));
|
||||||
|
if (res["ok"]) {
|
||||||
|
return Error(message: res["message"]);
|
||||||
|
} else {
|
||||||
|
return Success(data: User.fromJson(res));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Response<Null>> payForCart(String token) async {
|
||||||
|
final res = await _post(
|
||||||
|
endpoint: "cart/pay",
|
||||||
|
body: {
|
||||||
|
"token": token,
|
||||||
|
},
|
||||||
|
).then((res) => json.decode(res.body));
|
||||||
|
|
||||||
if (res["ok"]) {
|
if (res["ok"]) {
|
||||||
return Success(data: null);
|
return Success(data: null);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:mobile/models/coordinate.dart';
|
import 'package:mobile/models/coordinate.dart';
|
||||||
import 'package:mobile/models/product.dart';
|
import 'package:mobile/models/product.dart';
|
||||||
|
import 'package:mobile/models/user.dart';
|
||||||
import 'package:mobile/server/server.dart';
|
import 'package:mobile/server/server.dart';
|
||||||
|
|
||||||
class MockServer implements Server {
|
class MockServer implements Server {
|
||||||
@ -108,11 +109,30 @@ class MockServer implements Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Response<Null>> login(
|
Future<Response<String>> login(
|
||||||
String name,
|
|
||||||
String email,
|
String email,
|
||||||
String password,
|
String password,
|
||||||
) async {
|
) async {
|
||||||
|
return Success(data: "asdsadasdsad");
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Response<Null>> logout(String token) async {
|
||||||
|
return Success(data: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Response<User>> sessionUser(String token) async {
|
||||||
|
return Success(
|
||||||
|
data: User(
|
||||||
|
id: 0,
|
||||||
|
email: "test@test.com",
|
||||||
|
name: "testuser",
|
||||||
|
balanceInDkkCents: 10000));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Response<Null>> payForCart(String token) async {
|
||||||
return Success(data: null);
|
return Success(data: null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:mobile/models/product.dart';
|
import 'package:mobile/models/product.dart';
|
||||||
|
import 'package:mobile/models/user.dart';
|
||||||
|
|
||||||
abstract class Server {
|
abstract class Server {
|
||||||
Future<Response<List<Product>>> allProducts();
|
Future<Response<List<Product>>> allProducts();
|
||||||
@ -9,11 +10,15 @@ abstract class Server {
|
|||||||
String password,
|
String password,
|
||||||
);
|
);
|
||||||
|
|
||||||
Future<Response<Null>> login(
|
Future<Response<String>> login(
|
||||||
String name,
|
|
||||||
String email,
|
String email,
|
||||||
String password,
|
String password,
|
||||||
);
|
);
|
||||||
|
Future<Response<Null>> logout(String token);
|
||||||
|
|
||||||
|
Future<Response<User>> sessionUser(String token);
|
||||||
|
|
||||||
|
Future<Response<Null>> payForCart(String token);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class Response<Data> {}
|
sealed class Response<Data> {}
|
||||||
|
33
mobile/lib/utils/build_if_session_exists.dart
Normal file
33
mobile/lib/utils/build_if_session_exists.dart
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:mobile/controllers/session.dart';
|
||||||
|
import 'package:mobile/models/user.dart';
|
||||||
|
import 'package:mobile/results.dart';
|
||||||
|
|
||||||
|
class BuildIfSessionExists extends StatelessWidget {
|
||||||
|
final SessionController sessionController;
|
||||||
|
final Widget placeholder;
|
||||||
|
final Widget Function(BuildContext, User) builder;
|
||||||
|
|
||||||
|
const BuildIfSessionExists(
|
||||||
|
{super.key,
|
||||||
|
required this.sessionController,
|
||||||
|
required this.placeholder,
|
||||||
|
required this.builder});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FutureBuilder(
|
||||||
|
future: sessionController.user(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final data = snapshot.data;
|
||||||
|
if (data == null) {
|
||||||
|
return placeholder;
|
||||||
|
}
|
||||||
|
if (data is Ok<User, Null>) {
|
||||||
|
final user = data.value;
|
||||||
|
return builder(context, user);
|
||||||
|
}
|
||||||
|
return Container();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,7 @@ import 'package:mobile/main.dart';
|
|||||||
void main() {
|
void main() {
|
||||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||||
// Build our app and trigger a frame.
|
// Build our app and trigger a frame.
|
||||||
await tester.pumpWidget(MyApp());
|
await tester.pumpWidget(const MyApp());
|
||||||
|
|
||||||
// Verify that our counter starts at 0.
|
// Verify that our counter starts at 0.
|
||||||
expect(find.text('0'), findsOneWidget);
|
expect(find.text('0'), findsOneWidget);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user