aboutsummaryrefslogtreecommitdiff
path: root/lib/screens
diff options
context:
space:
mode:
Diffstat (limited to 'lib/screens')
-rw-r--r--lib/screens/home.dart26
-rw-r--r--lib/screens/login.dart200
-rw-r--r--lib/screens/signup.dart140
3 files changed, 366 insertions, 0 deletions
diff --git a/lib/screens/home.dart b/lib/screens/home.dart
new file mode 100644
index 0000000..474fc48
--- /dev/null
+++ b/lib/screens/home.dart
@@ -0,0 +1,26 @@
+import 'package:flutter/material.dart';
+import "login.dart";
+
+class HomeScreen extends StatelessWidget {
+ const HomeScreen({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text("Home Page")
+ ),
+ body: Center(
+ child: ElevatedButton(
+ child: const Text("Log In"),
+ onPressed: () {
+ Navigator.push(
+ context,
+ MaterialPageRoute(builder: (context) => const LoginScreen())
+ );
+ },
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/screens/login.dart b/lib/screens/login.dart
new file mode 100644
index 0000000..1a0db55
--- /dev/null
+++ b/lib/screens/login.dart
@@ -0,0 +1,200 @@
+import "package:flutter/material.dart";
+import "package:flutter_secure_storage/flutter_secure_storage.dart";
+
+import "package:openbills/models/login.dart";
+import "package:openbills/widgets/input_box.dart";
+import "package:openbills/widgets/snackbar.dart";
+import "package:openbills/screens/signup.dart";
+
+class LoginScreen extends StatelessWidget {
+ const LoginScreen({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ centerTitle: true,
+ title: const Image(
+ height: 50,
+ image: AssetImage("assets/images/logo.png"),
+ ),
+ ),
+ body: const Center(
+ child: SizedBox(
+ width: 500,
+ child: Body(),
+ )
+ ),
+ );
+ }
+}
+
+class Body extends StatefulWidget {
+ const Body({super.key});
+
+ @override
+ State<Body> createState() => _BodyState();
+}
+
+class _BodyState extends State<Body> {
+ final accountNameController = TextEditingController();
+ final passwordController = TextEditingController();
+ LoginMethod? _method = LoginMethod.username;
+
+ final _storage = const FlutterSecureStorage();
+
+ @override
+ void dispose() {
+ accountNameController.dispose();
+ passwordController.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ Size size = MediaQuery.sizeOf(context);
+ MainAxisAlignment alignment = MainAxisAlignment.center;
+
+ if (size.width < 700) {
+ alignment = MainAxisAlignment.spaceBetween;
+ }
+
+ if (size.height < 700) {
+ alignment = MainAxisAlignment.center;
+ }
+
+ return Column (
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: alignment,
+ children: <Widget> [
+ const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
+ child: Text(
+ "OpenBills Log In",
+ textAlign: TextAlign.center,
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 30,
+ ),
+ ),
+ ),
+
+ Column(
+ children: <Widget>[
+ FormInputBox(
+ controller: accountNameController,
+ hintText: _method == LoginMethod.email ? "E-Mail" : "Username",
+ ),
+
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16),
+ child: Column(
+ children: <Widget>[
+ const Text(
+ "Log in with:",
+ textAlign: TextAlign.left,
+ style: TextStyle(
+ fontSize: 18,
+ ),
+ ),
+
+ Row(
+ children: <Widget>[
+ Flexible(
+ child: RadioListTile<LoginMethod>(
+ title: const Text("username"),
+ value: LoginMethod.username,
+ groupValue: _method,
+ onChanged: (LoginMethod? value) {
+ setState(() {
+ _method = value;
+ });
+ },
+ ),
+ ),
+
+ Flexible(
+ child: RadioListTile<LoginMethod>(
+ title: const Text("email"),
+ value: LoginMethod.email,
+ groupValue: _method,
+ onChanged: (LoginMethod? value) {
+ setState(() {
+ _method = value;
+ });
+ },
+ ),
+ ),
+ ],
+ ),
+ ],
+ )
+ ),
+
+ FormInputBox(
+ controller: passwordController,
+ hintText: "Password",
+ obscureText: true,
+ ),
+ ],
+ ),
+
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: <Widget> [
+ TextButton(
+ onPressed: () {
+ Navigator.push(
+ context,
+ MaterialPageRoute(builder: (context) => const SignupScreen())
+ );
+ },
+ child: const Text("Don't have an account? Sign up.")
+ ),
+
+ ElevatedButton(
+ onPressed: () async {
+ String name = accountNameController.text;
+ String? method = _method?.value;
+ String password = passwordController.text;
+
+ try {
+ LoginRes res = await userSignIn(name, method, password);
+ String? username = res.user.username;
+
+ await _storage.write(
+ key: "auth_token",
+ value: res.authToken,
+ aOptions: const AndroidOptions(
+ encryptedSharedPreferences: true,
+ ),
+ );
+
+ await _storage.write(
+ key: "refresh_token",
+ value: res.refreshToken,
+ aOptions: const AndroidOptions(
+ encryptedSharedPreferences: true,
+ ),
+ );
+
+ if (context.mounted) {
+ MySnackBar.show(context, "Hello, $username! Please restart the app to see the homepage.");
+ }
+ } on String catch(e) {
+ if (context.mounted) {
+ MySnackBar.show(context, "Error: $e");
+ }
+ }
+ },
+ child: const Text("Log In")
+ ),
+ ],
+ ),
+ ),
+ ],
+ );
+ }
+} \ No newline at end of file
diff --git a/lib/screens/signup.dart b/lib/screens/signup.dart
new file mode 100644
index 0000000..b155d8e
--- /dev/null
+++ b/lib/screens/signup.dart
@@ -0,0 +1,140 @@
+import "package:flutter/material.dart";
+
+import "package:openbills/models/user.dart";
+import "package:openbills/widgets/input_box.dart";
+import "package:openbills/widgets/snackbar.dart";
+
+class SignupScreen extends StatelessWidget {
+ const SignupScreen({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ centerTitle: true,
+ title: const Image(
+ height: 50,
+ image: AssetImage("assets/images/logo.png"),
+ ),
+ ),
+ body: const Center(
+ child: SizedBox(
+ width: 500,
+ child: Body(),
+ )
+ ),
+ );
+ }
+}
+
+class Body extends StatefulWidget {
+ const Body({super.key});
+
+ @override
+ State<Body> createState() => _BodyState();
+}
+
+class _BodyState extends State<Body> {
+ final usernameController = TextEditingController();
+ final emailController = TextEditingController();
+ final passwordController = TextEditingController();
+
+ @override
+ void dispose() {
+ usernameController.dispose();
+ emailController.dispose();
+ passwordController.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ Size size = MediaQuery.sizeOf(context);
+ MainAxisAlignment alignment = MainAxisAlignment.center;
+
+ if (size.width < 700) {
+ alignment = MainAxisAlignment.spaceBetween;
+ }
+
+ if (size.height < 700) {
+ alignment = MainAxisAlignment.center;
+ }
+
+ return Column (
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: alignment,
+ children: <Widget> [
+ const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
+ child: Text(
+ "OpenBills Sign Up",
+ textAlign: TextAlign.center,
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 30,
+ ),
+ ),
+ ),
+
+ Column(
+ children: <Widget>[
+ FormInputBox(
+ controller: usernameController,
+ hintText: "Username",
+ ),
+
+ FormInputBox(
+ controller: emailController,
+ hintText: "E-mail",
+ ),
+
+ FormInputBox(
+ controller: passwordController,
+ hintText: "Password",
+ obscureText: true,
+ ),
+ ],
+ ),
+
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: <Widget> [
+ TextButton(
+ onPressed: () {
+ Navigator.pop(context);
+ },
+ child: const Text("Already have an account? Sign in.")
+ ),
+
+ ElevatedButton(
+ onPressed: () async {
+ User u = User(
+ id: 0,
+ username: usernameController.text,
+ email: emailController.text,
+ );
+
+ try {
+ await userSignUp(u, passwordController.text);
+
+ if (context.mounted) {
+ MySnackBar.show(context, "Successfully created an account!");
+ Navigator.pop(context);
+ }
+ } on String catch (e) {
+ if (context.mounted) {
+ MySnackBar.show(context, "Error: $e");
+ }
+ }
+ },
+ child: const Text("Sign Up")
+ ),
+ ],
+ ),
+ ),
+ ],
+ );
+ }
+} \ No newline at end of file