mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-27 16:24:07 +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:mobile/models/product.dart';
|
||||
import 'package:mobile/results.dart';
|
||||
|
||||
class ProductIdException implements Exception {}
|
||||
|
||||
@ -82,6 +83,10 @@ class CartController extends ChangeNotifier {
|
||||
cart.clear();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Result<Null, String> pay() {
|
||||
return const Err("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
class CartItem {
|
||||
|
@ -1,15 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile/models/product.dart';
|
||||
import 'package:mobile/results.dart';
|
||||
import 'package:mobile/server/mock_server.dart';
|
||||
import 'package:mobile/server/server.dart';
|
||||
|
||||
class ProductController extends ChangeNotifier {
|
||||
final server = MockServer();
|
||||
final Server server;
|
||||
|
||||
List<Product> products = [];
|
||||
String query = "";
|
||||
ProductController() {
|
||||
ProductController({required this.server}) {
|
||||
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:mobile/results.dart';
|
||||
import 'package:mobile/server/server.dart';
|
||||
|
||||
class UsersControllerOld extends ChangeNotifier {
|
||||
int nextId = 0;
|
||||
final List<User> users = [];
|
||||
class UsersController extends ChangeNotifier {
|
||||
Server server;
|
||||
|
||||
User? _loggedInUser;
|
||||
UsersController({required this.server});
|
||||
|
||||
UsersControllerOld() {
|
||||
addTestUsers();
|
||||
}
|
||||
|
||||
Result<User, String> getUserById(int id) {
|
||||
for (var i = 0; i < users.length; i++) {
|
||||
if (users[i].id == id) {
|
||||
return Ok(users[i]);
|
||||
}
|
||||
Future<Result<Null, String>> register(
|
||||
String name, String email, String password) async {
|
||||
final res = await server.register(name, email, password);
|
||||
switch (res) {
|
||||
case Success<Null>():
|
||||
return const Ok(null);
|
||||
case Error<Null>(message: final message):
|
||||
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: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/controllers/add_to_cart_state.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/receipt.dart';
|
||||
import 'package:mobile/controllers/user.dart';
|
||||
import 'package:mobile/server/mock_server.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:mobile/controllers/routing.dart';
|
||||
|
||||
@ -20,29 +24,37 @@ class MyApp extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final server = MockServer();
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (_) => RoutingController()),
|
||||
ChangeNotifierProvider(create: (_) => ProductController()),
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => ProductController(server: server)),
|
||||
ChangeNotifierProvider(create: (_) => CartController()),
|
||||
ChangeNotifierProvider(create: (_) => ReceiptController()),
|
||||
ChangeNotifierProvider(create: (_) => PayingStateController()),
|
||||
ChangeNotifierProvider(create: (_) => AddToCartStateController()),
|
||||
ChangeNotifierProvider(create: (_) => LocationImageController()),
|
||||
ChangeNotifierProvider(create: (_) => UsersControllerOld()),
|
||||
ChangeNotifierProvider(create: (_) => UsersController(server: server)),
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => SessionController(server: server)),
|
||||
],
|
||||
child: MaterialApp(
|
||||
title: 'Fresh Plaza',
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: const Color.fromARGB(255, 149, 92, 255)),
|
||||
scaffoldBackgroundColor: const Color(0xFFFAFAFF),
|
||||
textTheme:
|
||||
GoogleFonts.merriweatherTextTheme(Theme.of(context).textTheme),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const LogInPage(),
|
||||
),
|
||||
title: 'Fresh Plaza',
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: const Color.fromARGB(255, 149, 92, 255)),
|
||||
scaffoldBackgroundColor: const Color(0xFFFAFAFF),
|
||||
textTheme:
|
||||
GoogleFonts.merriweatherTextTheme(Theme.of(context).textTheme),
|
||||
useMaterial3: true,
|
||||
),
|
||||
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/controllers/cart.dart';
|
||||
import 'package:mobile/controllers/product.dart';
|
||||
import 'package:mobile/controllers/user.dart';
|
||||
import 'package:mobile/results.dart';
|
||||
import 'package:mobile/utils/price.dart';
|
||||
import 'package:mobile/widgets/primary_button.dart';
|
||||
@ -144,8 +143,7 @@ class CartItemView extends StatelessWidget {
|
||||
}
|
||||
|
||||
class CartPage extends StatelessWidget {
|
||||
final User user;
|
||||
const CartPage({super.key, required this.user});
|
||||
const CartPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -316,7 +314,7 @@ class CartPage extends StatelessWidget {
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
FinishShoppingPage(user: user)));
|
||||
const FinishShoppingPage()));
|
||||
},
|
||||
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/controllers/routing.dart';
|
||||
import 'package:mobile/controllers/cart.dart';
|
||||
import 'package:mobile/controllers/user.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class Dashboard extends StatelessWidget {
|
||||
final User user;
|
||||
|
||||
final List<StatelessWidget> pages = [];
|
||||
|
||||
Dashboard({super.key, required this.user}) {
|
||||
Dashboard({super.key}) {
|
||||
pages.addAll([
|
||||
HomePage(
|
||||
user: user,
|
||||
),
|
||||
const HomePage(),
|
||||
const AllProductsPage(),
|
||||
CartPage(user: user),
|
||||
const CartPage(),
|
||||
const AllReceiptsPage(),
|
||||
]);
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ import 'package:mobile/controllers/routing.dart';
|
||||
import 'package:mobile/controllers/cart.dart';
|
||||
import 'package:mobile/controllers/paying_state.dart';
|
||||
import 'package:mobile/controllers/receipt.dart';
|
||||
import 'package:mobile/controllers/user.dart';
|
||||
import 'package:mobile/results.dart';
|
||||
import 'package:mobile/utils/price.dart';
|
||||
import 'package:mobile/widgets/primary_button.dart';
|
||||
@ -11,17 +10,15 @@ import 'package:mobile/widgets/receipt_item.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class FinishShoppingPage extends StatelessWidget {
|
||||
final User user;
|
||||
|
||||
const FinishShoppingPage({super.key, required this.user});
|
||||
const FinishShoppingPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final CartController cartRepo = context.read<CartController>();
|
||||
final CartController cartController = context.read<CartController>();
|
||||
final ReceiptController receiptRepo = context.read<ReceiptController>();
|
||||
final PayingStateController payingStateRepo =
|
||||
context.watch<PayingStateController>();
|
||||
final cart = cartRepo.allCartItems();
|
||||
final cart = cartController.allCartItems();
|
||||
|
||||
return Scaffold(
|
||||
body: SafeArea(
|
||||
@ -50,7 +47,7 @@ class FinishShoppingPage extends StatelessWidget {
|
||||
"Total:",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(formatDkkCents(cartRepo.totalPrice())),
|
||||
Text(formatDkkCents(cartController.totalPrice())),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -60,7 +57,8 @@ class FinishShoppingPage extends StatelessWidget {
|
||||
onPressed: () async {
|
||||
payingStateRepo.next();
|
||||
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) {
|
||||
showDialog<String>(
|
||||
context: context,
|
||||
@ -84,7 +82,7 @@ class FinishShoppingPage extends StatelessWidget {
|
||||
receiptRepo.createReceipt(cart);
|
||||
payingStateRepo.next();
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
cartRepo.clearCart();
|
||||
cartController.clearCart();
|
||||
payingStateRepo.reset();
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context);
|
||||
|
@ -1,15 +1,16 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile/controllers/session.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:provider/provider.dart';
|
||||
|
||||
class HomePage extends StatelessWidget {
|
||||
final User user;
|
||||
const HomePage({super.key, required this.user});
|
||||
const HomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final sessionController = context.read<SessionController>();
|
||||
return Column(
|
||||
children: [
|
||||
Row(
|
||||
@ -28,25 +29,29 @@ class HomePage extends StatelessWidget {
|
||||
),
|
||||
Card(
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
color: Color(0xFFFFFFFF),
|
||||
),
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Consumer<UsersControllerOld>(
|
||||
builder: (context, usersRepo, _) => Text(
|
||||
"Saldo: ${formatDkkCents(user.balanceInDkkCents)}",
|
||||
style: Theme.of(context).textTheme.headlineSmall)),
|
||||
),
|
||||
decoration: const BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
color: Color(0xFFFFFFFF),
|
||||
),
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: BuildIfSessionExists(
|
||||
sessionController: sessionController,
|
||||
placeholder: const CircularProgressIndicator(),
|
||||
builder: (context, user) => Text(
|
||||
"Saldo: ${formatDkkCents(user.balanceInDkkCents)}",
|
||||
style: Theme.of(context).textTheme.headlineSmall))),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"Velkommen ${user.name}",
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
BuildIfSessionExists(
|
||||
sessionController: sessionController,
|
||||
placeholder: const CircularProgressIndicator(),
|
||||
builder: (context, user) => Text(
|
||||
"Velkommen ${user.name}",
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -1,12 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile/controllers/session.dart';
|
||||
import 'package:mobile/pages/register_page.dart';
|
||||
import 'package:mobile/controllers/user.dart';
|
||||
import 'package:mobile/results.dart';
|
||||
import 'package:mobile/widgets/error_box.dart';
|
||||
import 'package:mobile/widgets/primary_button.dart';
|
||||
import 'package:mobile/widgets/primary_input.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'dashboard.dart';
|
||||
|
||||
class LogInPage extends StatelessWidget {
|
||||
const LogInPage({super.key});
|
||||
@ -61,19 +60,15 @@ class LogInFormState extends State<LogInForm> {
|
||||
controller: passwordController,
|
||||
),
|
||||
PrimaryButton(
|
||||
onPressed: () {
|
||||
final usersRepo = context.read<UsersControllerOld>();
|
||||
final loginResult =
|
||||
usersRepo.login(mailController.text, passwordController.text);
|
||||
|
||||
if (loginResult is Ok) {
|
||||
setState(() => loginError = false);
|
||||
Navigator.of(context).popUntil((_) => false);
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
Dashboard(user: (loginResult as Ok).value)));
|
||||
} else {
|
||||
setState(() => loginError = true);
|
||||
onPressed: () async {
|
||||
final sessionController = context.read<SessionController>();
|
||||
final loginResult = await sessionController.login(
|
||||
mailController.text, passwordController.text);
|
||||
switch (loginResult) {
|
||||
case Ok<Null, String>():
|
||||
setState(() => loginError = false);
|
||||
case Err<Null, String>():
|
||||
setState(() => loginError = true);
|
||||
}
|
||||
},
|
||||
child: const Text("Log ind")),
|
||||
|
@ -71,9 +71,9 @@ class RegisterFormState extends State<RegisterForm> {
|
||||
obscure: true),
|
||||
PrimaryButton(
|
||||
onPressed: () {
|
||||
final usersRepo = context.read<UsersControllerOld>();
|
||||
if (usersRepo.addUser(nameController.text, mailController.text,
|
||||
passwordController.text) is Ok) {
|
||||
final sessionsRepo = context.read<UsersController>();
|
||||
if (sessionsRepo.register(nameController.text,
|
||||
mailController.text, passwordController.text) is Ok) {
|
||||
setState(() => registerError = false);
|
||||
Navigator.of(context).pop();
|
||||
} else {
|
||||
|
@ -1,7 +1,6 @@
|
||||
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/controllers/user.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class _Page {
|
||||
@ -31,11 +30,9 @@ class SettingsPage extends StatelessWidget {
|
||||
icon: Icons.door_back_door,
|
||||
title: "Log ud",
|
||||
action: (context) {
|
||||
final users = context.read<UsersControllerOld>();
|
||||
users.logout();
|
||||
final sessionsController = context.read<SessionController>();
|
||||
Navigator.popUntil(context, (_) => false);
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(builder: (context) => const LogInPage()));
|
||||
sessionsController.logout();
|
||||
}),
|
||||
];
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
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:provider/provider.dart';
|
||||
|
||||
@ -8,8 +9,7 @@ class SaldoSettingsPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final usersRepo = context.watch<UsersControllerOld>();
|
||||
final user = usersRepo.loggedInUser()!;
|
||||
final sessionController = context.watch<SessionController>();
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: SafeArea(
|
||||
@ -25,12 +25,17 @@ class SaldoSettingsPage extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
Text("Nuværende saldo: ${formatDkkCents(user.balanceInDkkCents)}",
|
||||
style: Theme.of(context).textTheme.bodyLarge),
|
||||
BuildIfSessionExists(
|
||||
sessionController: sessionController,
|
||||
placeholder: const CircularProgressIndicator(),
|
||||
builder: (context, user) => Text(
|
||||
"Nuværende saldo: ${formatDkkCents(user.balanceInDkkCents)}",
|
||||
style: Theme.of(context).textTheme.bodyLarge),
|
||||
),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
user.addBalanceFounds(10000);
|
||||
usersRepo.veryBadNotifyAll();
|
||||
// TODO: implement add balance
|
||||
throw Exception("not implemented: Adding funds");
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text("Tilføj 100,00 kr"),
|
||||
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mobile/models/product.dart';
|
||||
import 'package:mobile/models/user.dart';
|
||||
import 'package:mobile/server/server.dart';
|
||||
|
||||
class BackendServer implements Server {
|
||||
@ -51,16 +52,61 @@ class BackendServer implements Server {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Response<Null>> login(
|
||||
String name,
|
||||
Future<Response<String>> login(
|
||||
String email,
|
||||
String password,
|
||||
) async {
|
||||
final res = await _post(
|
||||
endpoint: "auth/login",
|
||||
endpoint: "sessions/login",
|
||||
body: {"email": email, "password": password},
|
||||
).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"]) {
|
||||
return Success(data: null);
|
||||
} else {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:mobile/models/coordinate.dart';
|
||||
import 'package:mobile/models/product.dart';
|
||||
import 'package:mobile/models/user.dart';
|
||||
import 'package:mobile/server/server.dart';
|
||||
|
||||
class MockServer implements Server {
|
||||
@ -108,11 +109,30 @@ class MockServer implements Server {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Response<Null>> login(
|
||||
String name,
|
||||
Future<Response<String>> login(
|
||||
String email,
|
||||
String password,
|
||||
) 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);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:mobile/models/product.dart';
|
||||
import 'package:mobile/models/user.dart';
|
||||
|
||||
abstract class Server {
|
||||
Future<Response<List<Product>>> allProducts();
|
||||
@ -9,11 +10,15 @@ abstract class Server {
|
||||
String password,
|
||||
);
|
||||
|
||||
Future<Response<Null>> login(
|
||||
String name,
|
||||
Future<Response<String>> login(
|
||||
String email,
|
||||
String password,
|
||||
);
|
||||
Future<Response<Null>> logout(String token);
|
||||
|
||||
Future<Response<User>> sessionUser(String token);
|
||||
|
||||
Future<Response<Null>> payForCart(String token);
|
||||
}
|
||||
|
||||
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() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(MyApp());
|
||||
await tester.pumpWidget(const MyApp());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
|
Loading…
x
Reference in New Issue
Block a user