From caa33d0a7d5b9d4f2053fa6eb64c124db16bd011 Mon Sep 17 00:00:00 2001 From: Mikkel Troels Kongsted Date: Fri, 7 Feb 2025 09:54:27 +0100 Subject: [PATCH] log in and register mock --- mobile/lib/main.dart | 2 + mobile/lib/pages/log_in_page.dart | 89 ++++++++++++++++------ mobile/lib/pages/register_page.dart | 104 +++++++++++++++++++------- mobile/lib/repos/user.dart | 73 ++++++++++++++++++ mobile/lib/results.dart | 13 ++++ mobile/lib/widgets/error_box.dart | 34 +++++++++ mobile/lib/widgets/primary_input.dart | 7 ++ 7 files changed, 273 insertions(+), 49 deletions(-) create mode 100644 mobile/lib/repos/user.dart create mode 100644 mobile/lib/results.dart create mode 100644 mobile/lib/widgets/error_box.dart diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index b9fb5bf..f9f93ce 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -5,6 +5,7 @@ import 'package:mobile/repos/location_image.dart'; import 'package:mobile/repos/paying_state.dart'; import 'package:mobile/repos/product.dart'; import 'package:mobile/repos/receipt.dart'; +import 'package:mobile/repos/user.dart'; import 'package:provider/provider.dart'; import 'pages/landing_page.dart'; import 'package:mobile/repos/bottom_navigation_bar.dart'; @@ -27,6 +28,7 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => PayingStateRepo()), ChangeNotifierProvider(create: (_) => AddToCartStateRepo()), ChangeNotifierProvider(create: (_) => LocationImageRepo()), + ChangeNotifierProvider(create: (_) => UsersRepo()), ], child: MaterialApp( title: 'Fresh Plaza', diff --git a/mobile/lib/pages/log_in_page.dart b/mobile/lib/pages/log_in_page.dart index 34f80f6..20f879e 100644 --- a/mobile/lib/pages/log_in_page.dart +++ b/mobile/lib/pages/log_in_page.dart @@ -1,6 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:mobile/repos/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 { @@ -8,27 +12,68 @@ class LogInPage extends StatelessWidget { @override Widget build(BuildContext context) { - return Scaffold( - body: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Log ind", - style: Theme.of(context).textTheme.headlineLarge, - ), - const PrimaryInput( - label: "Mail/Tlf", placeholderText: "f.eks. example@example.com"), - const PrimaryInput( - label: "Password", placeholderText: "*********", obscure: true), - PrimaryButton( - onPressed: () => { - Navigator.of(context).push( - MaterialPageRoute(builder: (context) => Dashboard())) - }, - child: const Text("Log ind")) - ], - ) - ])); + return const Scaffold( + body: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [LogInForm()])); + } +} + +class LogInForm extends StatefulWidget { + const LogInForm({super.key}); + + @override + State createState() => LogInFormState(); +} + +class LogInFormState extends State { + bool loginError = false; + @override + Widget build(BuildContext context) { + final mailController = TextEditingController(); + final passwordController = TextEditingController(); + + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Log ind", + style: Theme.of(context).textTheme.headlineLarge, + ), + ErrorBox( + visible: loginError, + errorText: "Ugyldig mail eller password", + onClosePressed: () { + setState(() => loginError = false); + }, + ), + PrimaryInput( + label: "Mail/Tlf", + placeholderText: "f.eks. example@example.com", + controller: mailController, + ), + PrimaryInput( + label: "Password", + placeholderText: "*********", + obscure: true, + controller: passwordController, + ), + PrimaryButton( + onPressed: () { + final usersRepo = context.read(); + final loginResult = + usersRepo.login(mailController.text, passwordController.text); + if (loginResult is Ok) { + Navigator.of(context) + .push(MaterialPageRoute(builder: (context) => Dashboard())); + } else { + setState(() { + loginError = true; + }); + } + }, + child: const Text("Log ind")) + ], + ); } } diff --git a/mobile/lib/pages/register_page.dart b/mobile/lib/pages/register_page.dart index 435e550..1aff85a 100644 --- a/mobile/lib/pages/register_page.dart +++ b/mobile/lib/pages/register_page.dart @@ -1,6 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:mobile/repos/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 'log_in_page.dart'; class RegisterPage extends StatelessWidget { @@ -8,32 +12,78 @@ class RegisterPage extends StatelessWidget { @override Widget build(BuildContext context) { - return Scaffold( - body: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Opret bruger", - style: Theme.of(context).textTheme.headlineLarge, - ), - const PrimaryInput(label: "Fornavn", placeholderText: "Fornavn"), - const PrimaryInput( - label: "Mail/Tlf", placeholderText: "f.eks. example@example.com"), - const PrimaryInput( - label: "Password", placeholderText: "*********", obscure: true), - const PrimaryInput( - label: "Password (igen)", - placeholderText: "*********", - obscure: true), - PrimaryButton( - onPressed: () => { - Navigator.of(context).push(MaterialPageRoute( - builder: (context) => const LogInPage())) - }, - child: const Text("Opret bruger")) - ], - ) - ])); + return const Scaffold( + body: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [RegisterForm()])); + } +} + +class RegisterForm extends StatefulWidget { + const RegisterForm({super.key}); + + @override + State createState() => RegisterFormState(); +} + +class RegisterFormState extends State { + bool registerError = false; + + @override + Widget build(BuildContext context) { + final nameController = TextEditingController(); + final mailController = TextEditingController(); + final passwordController = TextEditingController(); + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Opret bruger", + style: Theme.of(context).textTheme.headlineLarge, + ), + ErrorBox( + visible: registerError, + errorText: "Bruger med mailen ${mailController.text}", + onClosePressed: () { + setState(() { + registerError = false; + }); + }), + PrimaryInput( + label: "Fornavn", + placeholderText: "Fornavn", + controller: nameController, + ), + PrimaryInput( + label: "Mail/Tlf", + placeholderText: "f.eks. example@example.com", + controller: mailController, + ), + PrimaryInput( + label: "Password", + placeholderText: "*********", + obscure: true, + controller: passwordController, + ), + const PrimaryInput( + label: "Password (igen)", + placeholderText: "*********", + obscure: true), + PrimaryButton( + onPressed: () { + final usersRepo = context.read(); + if (usersRepo.addUser(nameController.text, mailController.text, + passwordController.text) is Ok) { + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => const LogInPage())); + } else { + setState(() { + registerError = true; + }); + } + }, + child: const Text("Opret bruger")) + ], + ); } } diff --git a/mobile/lib/repos/user.dart b/mobile/lib/repos/user.dart new file mode 100644 index 0000000..67c188f --- /dev/null +++ b/mobile/lib/repos/user.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'package:mobile/results.dart'; + +class UsersRepo extends ChangeNotifier { + int nextId = 0; + final List users = []; + + UsersRepo() { + addTestUsers(); + } + + Result getUserById(int id) { + for (var i = 0; i < users.length; i++) { + if (users[i].id == id) { + return Ok(users[i]); + } + } + return Err("User with id $id doesn't exist"); + } + + Result 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 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); + users.add(user); + + return Ok(user); + } + + Result login(String mail, String password) { + for (var i = 0; i < users.length; i++) { + if (users[i].mail != mail) { + continue; + } + if (users[i].password == password) { + return Ok(users[i]); + } + return Err("Wrong password for user with mail $mail"); + } + return Err("User with mail $mail doesn't exist"); + } + + void addTestUsers() { + users + ..add(User( + id: nextId++, mail: "test@test.com", name: "test", password: "test")) + ..add(User(id: nextId++, mail: "", name: "", password: "")); + } +} + +class User { + final int id; + final String mail; + final String name; + final String password; + + User( + {required this.id, + required this.mail, + required this.name, + required this.password}); +} diff --git a/mobile/lib/results.dart b/mobile/lib/results.dart new file mode 100644 index 0000000..f2e277b --- /dev/null +++ b/mobile/lib/results.dart @@ -0,0 +1,13 @@ +sealed class Result {} + +final class Ok implements Result { + final T value; + + const Ok(this.value); +} + +final class Err implements Result { + final E value; + + const Err(this.value); +} diff --git a/mobile/lib/widgets/error_box.dart b/mobile/lib/widgets/error_box.dart new file mode 100644 index 0000000..e249997 --- /dev/null +++ b/mobile/lib/widgets/error_box.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; + +class ErrorBox extends StatelessWidget { + final bool visible; + final void Function() onClosePressed; + final String errorText; + const ErrorBox( + {super.key, + this.visible = true, + required this.errorText, + required this.onClosePressed}); + + @override + Widget build(BuildContext context) { + return Visibility( + visible: visible, + child: Container( + padding: const EdgeInsets.fromLTRB(10, 10, 0, 10), + margin: const EdgeInsets.all(10), + decoration: BoxDecoration( + border: Border.all(color: const Color.fromARGB(170, 248, 81, 73)), + borderRadius: const BorderRadius.all(Radius.circular(5)), + color: const Color.fromARGB(50, 248, 81, 73), + ), + child: Row( + children: [ + const Text("Ugyldigt mail eller password"), + IconButton(onPressed: onClosePressed, icon: const Icon(Icons.close)) + ], + ), + ), + ); + } +} diff --git a/mobile/lib/widgets/primary_input.dart b/mobile/lib/widgets/primary_input.dart index d21763d..720d536 100644 --- a/mobile/lib/widgets/primary_input.dart +++ b/mobile/lib/widgets/primary_input.dart @@ -6,12 +6,16 @@ class PrimaryInput extends StatelessWidget { final String label; final String placeholderText; final bool obscure; + final String? errorText; + final TextEditingController? controller; const PrimaryInput( {super.key, this.width = 300, this.height = 100, this.obscure = false, + this.errorText, + this.controller, required this.label, required this.placeholderText}); @override @@ -20,8 +24,11 @@ class PrimaryInput extends StatelessWidget { width: width, height: height, child: TextField( + controller: controller, decoration: InputDecoration( border: const OutlineInputBorder(), + errorStyle: const TextStyle(), + errorText: errorText, label: Text(label), hintText: placeholderText, filled: true,