log in and register mock

This commit is contained in:
Mikkel Troels Kongsted 2025-02-07 09:54:27 +01:00
parent f4886e045c
commit caa33d0a7d
7 changed files with 273 additions and 49 deletions

View File

@ -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',

View File

@ -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<StatefulWidget> createState() => LogInFormState();
}
class LogInFormState extends State<LogInForm> {
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<UsersRepo>();
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"))
],
);
}
}

View File

@ -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<StatefulWidget> createState() => RegisterFormState();
}
class RegisterFormState extends State<RegisterForm> {
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<UsersRepo>();
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"))
],
);
}
}

View File

@ -0,0 +1,73 @@
import 'package:flutter/material.dart';
import 'package:mobile/results.dart';
class UsersRepo extends ChangeNotifier {
int nextId = 0;
final List<User> users = [];
UsersRepo() {
addTestUsers();
}
Result<User, String> 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<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);
users.add(user);
return Ok(user);
}
Result<User, String> 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});
}

13
mobile/lib/results.dart Normal file
View File

@ -0,0 +1,13 @@
sealed class Result<T, E> {}
final class Ok<T, E> implements Result<T, E> {
final T value;
const Ok(this.value);
}
final class Err<T, E> implements Result<T, E> {
final E value;
const Err(this.value);
}

View File

@ -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))
],
),
),
);
}
}

View File

@ -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,