diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index eae5f94..1dd97e7 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,7 @@ - + @@ -34,5 +35,5 @@ - + diff --git a/lib/home.dart b/lib/home.dart index 495a51d..b15d7c1 100644 --- a/lib/home.dart +++ b/lib/home.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:leg_barkr_app/view/auth/register_form.dart'; import 'package:leg_barkr_app/view/metrics/metrics_page.dart'; import 'package:leg_barkr_app/view/steps/steps_page.dart'; import 'package:leg_barkr_app/view/map_page.dart'; @@ -29,7 +30,8 @@ class _HomeScreenState extends State { body: PageView( controller: _pageController, children: const [ - MetricsPage(), + RegisterForm(), // Purely for testing purposes. + //MetricsPage(), StepsPage(), MapPage(), SettingsPage() diff --git a/lib/utils/endpoints.dart b/lib/utils/endpoints.dart new file mode 100644 index 0000000..bb342ec --- /dev/null +++ b/lib/utils/endpoints.dart @@ -0,0 +1,3 @@ +const String home = "https://leg-barkr.nw.r.appspot.com/"; +const String register = "https://leg-barkr.nw.r.appspot.com/authentication/register"; +const String verify = "https://leg-barkr.nw.r.appspot.com/authentication/verify"; diff --git a/lib/utils/resources.dart b/lib/utils/resources.dart new file mode 100644 index 0000000..4b038a8 --- /dev/null +++ b/lib/utils/resources.dart @@ -0,0 +1,7 @@ +import 'package:flutter/material.dart'; + +class Resources { + static final Color primaryColour = Colors.green; + static final Color primaryAccentColour = Colors.greenAccent; + +} \ No newline at end of file diff --git a/lib/view/auth/register_form.dart b/lib/view/auth/register_form.dart new file mode 100644 index 0000000..6c5cce2 --- /dev/null +++ b/lib/view/auth/register_form.dart @@ -0,0 +1,237 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:leg_barkr_app/home.dart'; +import 'package:leg_barkr_app/utils/endpoints.dart' as Endpoints; + +class RegisterForm extends StatefulWidget { + const RegisterForm({Key? key}) : super(key: key); + + @override + _RegisterFormState createState() => _RegisterFormState(); +} + +class _RegisterFormState extends State { + final GlobalKey _formKey = GlobalKey(); + late String _firstName, _lastName, _email, _password, _confirmPassword, _deviceId; + bool _registering = false; + + void attemptRegistration(){ + final form = _formKey.currentState; + if (form!.validate()) { + form.save(); + if (_password != _confirmPassword) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Passwords do not match"))); + setState(() { _registering = false; }); + } + form.save(); + setState(() { _registering = true; }); + registerUser(); + } else { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Please enter all required fields"))); + setState(() { _registering = false; }); + } + } + + void registerUser() async { + final response = await http.post( + Uri.parse(Endpoints.register), + headers: { + 'Content-Type': 'application/json; charset=UTF-8', + }, + body: jsonEncode({ + 'name': _firstName + _lastName, + 'deviceid': _deviceId, + 'email': _email, + 'password': _password + }), + ); + if (response.statusCode == 201){ + Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreen())); + } else if (response.statusCode == 400){ + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Fields missing!"))); + } else if (response.statusCode == 409){ + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("User with given email already exists"))); + } else { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Failed registration, please try again later"))); + } + setState(() { + _registering = false; + }); + } + + @override + Widget build(BuildContext context) { + final TextFormField firstNameInput = TextFormField( + autofocus: false, + cursorColor: Colors.green, + decoration: const InputDecoration( + border: OutlineInputBorder(), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.green, + width: 2 + ) + ), + hintText: 'First Name', + //labelStyle: TextStyle(color: Colors.green), + ), + validator: (value) => value!.isEmpty ? "Please enter first name" : null, + onSaved: (value) => _firstName = value!, + ); + + final TextFormField lastNameInput = TextFormField( + autofocus: false, + cursorColor: Colors.green, + decoration: const InputDecoration( + border: OutlineInputBorder(), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.green, + width: 2 + ) + ), + hintText: 'Last Name', + //labelStyle: TextStyle(color: Colors.green), + ), + validator: (value) => value!.isEmpty ? "Please enter last name" : null, + onSaved: (value) => _lastName = value!, + ); + + final TextFormField deviceInput = TextFormField( + autofocus: false, + cursorColor: Colors.green, + decoration: const InputDecoration( + border: OutlineInputBorder(), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.green, + width: 2 + ) + ), + hintText: 'Device ID', + //labelStyle: TextStyle(color: Colors.green), + ), + validator: (value) => value!.isEmpty ? "Please enter device ID" : null, + onSaved: (value) => _deviceId = value!, + ); + + final TextFormField emailInput = TextFormField( + autofocus: false, + cursorColor: Colors.green, + decoration: const InputDecoration( + border: OutlineInputBorder(), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.green, + width: 2 + ) + ), + hintText: 'Email', + //labelStyle: TextStyle(color: Colors.green), + ), + validator: (value) => value!.isEmpty ? "Please enter email" : null, + onSaved: (value) => _email = value!, + ); + + final TextFormField passwordInput = TextFormField( + autofocus: false, + obscureText: true, + cursorColor: Colors.green, + decoration: const InputDecoration( + border: OutlineInputBorder(), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.green, + width: 2 + ) + ), + hintText: 'Password', + //labelStyle: TextStyle(color: Colors.green), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter password'; + } + return null; + }, + onSaved: (value) => _password = value!, + ); + + final TextFormField confirmPasswordInput = TextFormField( + autofocus: false, + obscureText: true, + cursorColor: Colors.green, + decoration: const InputDecoration( + border: OutlineInputBorder(), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.green, + width: 2 + ) + ), + hintText: 'Confirm password', + //labelStyle: TextStyle(color: Colors.green), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please confirm password'; + } + return null; + }, + onSaved: (value) => _confirmPassword = value!, + ); + + final Container loading = Container( + alignment: Alignment.center, + child: CircularProgressIndicator( + backgroundColor: Colors.green, + color: Colors.green, + ), + ); + + final Container registerBtn = Container( + width: double.infinity, + height: 50, + child: ElevatedButton( + onPressed: attemptRegistration, + child: Text('Register'), + style: ElevatedButton.styleFrom( + alignment: Alignment.center, + primary: Colors.green, + ) + ) + + ); + + return SafeArea( + child: SingleChildScrollView( + child: Form( + key: _formKey, + child:Container( + padding: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 100), + firstNameInput, + SizedBox(height: 20), + lastNameInput, + SizedBox(height: 20), + deviceInput, + SizedBox(height: 20), + emailInput, + SizedBox(height: 20), + passwordInput, + SizedBox(height: 20), + confirmPasswordInput, + SizedBox(height: 20), + _registering ? loading : registerBtn + ] + ) + ) + ), + ) + ); + } +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 9990d18..8b24093 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -142,6 +142,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.15.0" + http: + dependency: "direct main" + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.4" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" intl: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index c1ad566..743abb7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,6 +38,7 @@ dependencies: google_maps_flutter_web: ^0.3.2+1 charts_flutter: ^0.12.0 syncfusion_flutter_gauges: ^19.4.50 + http: ^0.13.4 dev_dependencies: