diff --git a/lib/defaults/buttons/ml_elevated_button.dart b/lib/defaults/buttons/ml_elevated_button.dart index a78d2af..c0ef62c 100644 --- a/lib/defaults/buttons/ml_elevated_button.dart +++ b/lib/defaults/buttons/ml_elevated_button.dart @@ -4,10 +4,12 @@ import 'package:memory_lamp/helpers/size_mq.dart'; class MLElevatedButton extends StatelessWidget { final double? width; final Widget child; + final Color? color; final Function() onPressed; const MLElevatedButton({ this.width, + this.color, required this.child, required this.onPressed, Key? key, @@ -18,6 +20,9 @@ class MLElevatedButton extends StatelessWidget { return SizedBox( width: width ?? SizeMQ.width! * .5, child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: color, + ), child: Padding( padding: EdgeInsets.all(8.0), child: child, diff --git a/lib/defaults/ml_text.dart b/lib/defaults/ml_text.dart index cc6377e..5297f8e 100644 --- a/lib/defaults/ml_text.dart +++ b/lib/defaults/ml_text.dart @@ -5,11 +5,15 @@ class MLText extends StatelessWidget { final TextStyle? style; final FontWeight? fontWeight; final double? fontSize; + final Color? color; + final TextDecoration? textDecoration; final FontStyle? fontStyle; const MLText( this.text, { + this.textDecoration, this.style, + this.color, this.fontWeight, this.fontSize, this.fontStyle, @@ -29,6 +33,8 @@ class MLText extends StatelessWidget { TextStyle( fontWeight: fontWeight, fontSize: fontSize, + color: color, + decoration: textDecoration, fontStyle: fontStyle, ), ); diff --git a/lib/form/ml_form.dart b/lib/form/ml_form.dart new file mode 100644 index 0000000..e814042 --- /dev/null +++ b/lib/form/ml_form.dart @@ -0,0 +1,153 @@ +import 'package:flutter/material.dart'; +import 'package:memory_lamp/defaults/ml_text.dart'; +import 'package:memory_lamp/helpers/size_mq.dart'; +import 'package:memory_lamp/theming/ml_colors.dart'; + +class MLForm extends StatefulWidget { + final bool loadForSignup; + final bool loadForLogin; + const MLForm({this.loadForSignup = false, this.loadForLogin = false}); + @override + _MLFormState createState() => _MLFormState(); +} + +class _MLFormState extends State { + final _mlFormKey = GlobalKey(); + bool? remember = false; + bool? agreeToTos = false; + + @override + Widget build(BuildContext context) { + return Form( + key: _mlFormKey, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + mainAxisSize: MainAxisSize.max, + children: [ + _userNameField(), + SizedBox(height: SizeMQ.height! * .03), + if (widget.loadForLogin) _rememberMe(), + SizedBox(height: SizeMQ.height! * .03), + if (widget.loadForSignup) _emailField(), + SizedBox(height: SizeMQ.height! * .03), + if (widget.loadForSignup) _passwordField(), + SizedBox(height: SizeMQ.height! * .03), + if (widget.loadForSignup) _confirmPasswordField(), + SizedBox(height: SizeMQ.height! * .03), + if (widget.loadForSignup) _agreement(), + ], + ), + ); + } + +//username + TextFormField _userNameField() => TextFormField( + keyboardType: TextInputType.name, + decoration: _defaultInputDecoration(label: 'Username'), + ); + +//email + TextFormField _emailField() => TextFormField( + keyboardType: TextInputType.emailAddress, + decoration: _defaultInputDecoration(label: 'Email'), + ); + +//password + TextFormField _passwordField() => TextFormField( + keyboardType: TextInputType.visiblePassword, + obscureText: true, + decoration: _defaultInputDecoration( + label: 'Password', + icon: Icon(Icons.visibility), + ), + ); + +//confirmPassword + TextFormField _confirmPasswordField() => TextFormField( + keyboardType: TextInputType.visiblePassword, + obscureText: true, + decoration: _defaultInputDecoration( + label: 'Confirm Password', + icon: Icon(Icons.visibility), + ), + ); + +//AgreeToTos + Row _agreement() => Row( + children: [ + Theme( + child: Checkbox( + value: agreeToTos, + activeColor: Colors.white, + checkColor: MLColors.primary, + onChanged: (value) { + setState(() { + agreeToTos = value; + }); + }), + data: ThemeData(unselectedWidgetColor: Colors.white38), + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MLText( + "I agree with the ", + color: Colors.white, + fontSize: getProportionateScreenWidth(7), + ), + MLText( + "Terms and Conditions", + textDecoration: TextDecoration.underline, + color: Colors.white, + fontSize: getProportionateScreenWidth(7), + ), + ], + ) + ], + ); + +//rememberMe + Row _rememberMe() => Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Theme( + child: Checkbox( + value: remember, + activeColor: Colors.white, + checkColor: MLColors.primary, + onChanged: (value) { + setState(() { + remember = value; + }); + }), + data: ThemeData(unselectedWidgetColor: Colors.white38), + ), + MLText( + "Remember Me ", + color: Colors.white, + fontSize: getProportionateScreenWidth(7), + ), + ], + ); + + _defaultInputDecoration({ + required String label, + Icon? icon, + }) { + return InputDecoration( + labelStyle: TextStyle(color: Colors.white), + labelText: label, + suffixIcon: icon, + contentPadding: EdgeInsets.zero, + floatingLabelBehavior: FloatingLabelBehavior.always, + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide(color: Colors.white), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide(color: Colors.white), + ), + ); + } +} + +//TO DO: validations \ No newline at end of file diff --git a/lib/router/route_map.dart b/lib/router/route_map.dart index 570a77f..94895dc 100644 --- a/lib/router/route_map.dart +++ b/lib/router/route_map.dart @@ -1,4 +1,5 @@ import 'package:flutter/widgets.dart'; +import 'package:memory_lamp/screens/login.dart'; import 'package:memory_lamp/screens/onboarding.dart'; import 'package:memory_lamp/screens/signup.dart'; import 'package:memory_lamp/screens/testing_screen.dart'; @@ -6,6 +7,7 @@ import 'package:memory_lamp/screens/testing_screen.dart'; final Map routeMap = { OnboardingScreen.routeName: (context) => OnboardingScreen(), SignupScreen.routeName: (context) => SignupScreen(), + LoginScreen.routeName: (context) => LoginScreen(), // ------ screen for manual testing widgets TestingScreen.routeName: (context) => TestingScreen(), diff --git a/lib/screens/login.dart b/lib/screens/login.dart new file mode 100644 index 0000000..b412b91 --- /dev/null +++ b/lib/screens/login.dart @@ -0,0 +1,112 @@ +import 'package:flutter/material.dart'; +import 'package:memory_lamp/defaults/buttons/ml_elevated_button.dart'; +import 'package:memory_lamp/defaults/ml_text.dart'; +import 'package:memory_lamp/form/ml_form.dart'; +import 'package:memory_lamp/helpers/size_mq.dart'; +import 'package:memory_lamp/screens/signup.dart'; +import 'package:memory_lamp/theming/ml_colors.dart'; + +class LoginScreen extends StatefulWidget { + static String routeName = '/login'; + LoginScreen({Key? key}) : super(key: key); + + @override + _LoginScreenState createState() => _LoginScreenState(); +} + +class _LoginScreenState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: MLColors.primary, + body: SafeArea( + child: Container( + child: SingleChildScrollView( + child: Container( + height: SizeMQ.height! * .9, + padding: EdgeInsets.symmetric(horizontal: SizeMQ.width! * .1), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _welcome(), + SizedBox(width: SizeMQ.width! * .03), + MLForm( + loadForLogin: true, + ), + _loginButton(), + SizedBox(width: SizeMQ.height! * .03), + _signUpHere(context), + ], + ), + ), + ), + ), + ), + ); + } + +// ====== COMPONENTS + +//WelcomeMessage + Column _welcome() => Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: Alignment.topLeft, + child: MLText( + "Welcome Back! ", + style: TextStyle( + color: Colors.white, + fontSize: getProportionateScreenWidth(14), + fontWeight: FontWeight.normal, + height: 2, + ), + ), + ), + Align( + alignment: Alignment.topLeft, + child: MLText( + 'Log in to continue', + color: Colors.white54, + ), + ), + ], + ); + +//LoginButton + MLElevatedButton _loginButton() => MLElevatedButton( + child: MLText( + 'Log in', + color: MLColors.primary, + ), + color: Colors.white, + onPressed: () { + print('Login'); + }, + ); + +//SignUp + Row _signUpHere(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + MLText( + 'New User? ', + fontSize: getProportionateScreenWidth(7), + color: Colors.white, + ), + GestureDetector( + onTap: () { + Navigator.pushNamed(context, SignupScreen.routeName); + }, + child: MLText( + 'Sign Up Here!', + textDecoration: TextDecoration.underline, + fontSize: getProportionateScreenWidth(7), + color: Colors.blue, + ), + ), + ], + ); + } +} diff --git a/lib/screens/onboarding.dart b/lib/screens/onboarding.dart index cf4e0f1..4ca6140 100644 --- a/lib/screens/onboarding.dart +++ b/lib/screens/onboarding.dart @@ -3,7 +3,7 @@ import 'package:memory_lamp/defaults/buttons/ml_elevated_button.dart'; import 'package:memory_lamp/defaults/ml_text.dart'; import 'package:memory_lamp/helpers/asset_manager.dart'; import 'package:memory_lamp/helpers/size_mq.dart'; -import 'package:memory_lamp/screens/signup.dart'; +import 'package:memory_lamp/screens/login.dart'; import 'package:memory_lamp/theming/ml_colors.dart'; import 'package:memory_lamp/theming/ml_font.dart'; @@ -27,7 +27,7 @@ class OnboardingScreen extends StatelessWidget { SizedBox(height: SizeMQ.width! * .2), MLElevatedButton( onPressed: () => - Navigator.pushNamed(context, SignupScreen.routeName), + Navigator.pushNamed(context, LoginScreen.routeName), child: MLText( "Get Started", fontWeight: MLFont.bold, diff --git a/lib/screens/signup.dart b/lib/screens/signup.dart index 26f47e8..ab44bca 100644 --- a/lib/screens/signup.dart +++ b/lib/screens/signup.dart @@ -1,105 +1,93 @@ import 'package:flutter/material.dart'; import 'package:memory_lamp/defaults/buttons/ml_elevated_button.dart'; import 'package:memory_lamp/defaults/ml_text.dart'; +import 'package:memory_lamp/form/ml_form.dart'; import 'package:memory_lamp/helpers/size_mq.dart'; -import 'package:memory_lamp/screens/onboarding.dart'; +import 'package:memory_lamp/screens/login.dart'; import 'package:memory_lamp/theming/ml_colors.dart'; -import 'package:memory_lamp/theming/ml_font.dart'; -class SignupScreen extends StatelessWidget { +class SignupScreen extends StatefulWidget { static String routeName = '/signup'; - SignupScreen({Key? key}) : super(key: key); - final double _width = SizeMQ.width! * .6; + @override + _SignupScreenState createState() => _SignupScreenState(); +} +class _SignupScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: MLColors.bgLight, + backgroundColor: MLColors.primary, body: SafeArea( - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - OnboardingScreen.heroLogo(), - SizedBox(height: SizeMQ.width! * .1), - _thirdPartySignup(), - _divider(), - _signUp(), - _submitButton(), - ], + child: SingleChildScrollView( + child: Container( + height: SizeMQ.height! * .9, + padding: EdgeInsets.symmetric(horizontal: SizeMQ.width! * .1), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _welcome(), + MLForm( + loadForSignup: true, + ), + MLElevatedButton( + color: Colors.white, + child: MLText( + 'Create Account', + style: TextStyle(color: MLColors.primary), + ), + onPressed: () {}, + ), + _alreadyUser(context), + ], + ), ), ), ), ); } - Column _thirdPartySignup() { - return Column( - children: [ - MLElevatedButton( - width: _width, - onPressed: () {}, - child: MLText( - "Sign up via Google", - fontWeight: MLFont.light, - fontSize: MLFont.small, - ), - ), - MLElevatedButton( - width: _width, - onPressed: () {}, - child: MLText( - "Sign up via Facebook", - fontWeight: MLFont.light, - fontSize: MLFont.small, - ), - ), - ], - ); - } - - Padding _divider() { - Expanded _line = Expanded( - child: Divider( - color: MLColors.secondary, - thickness: .5, - ), - ); - return Padding( - padding: EdgeInsets.symmetric( - horizontal: SizeMQ.width! * .1, - vertical: SizeMQ.width! * .06, - ), - child: Row( +//Message + Column _welcome() => Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - _line, - Padding( - padding: EdgeInsets.symmetric(horizontal: 16), - child: MLText("OR", fontSize: MLFont.extraSmall), + MLText( + "Hello!", + color: Colors.white, + fontSize: getProportionateScreenWidth(14), + fontWeight: FontWeight.bold, + ), + MLText( + 'Create a new Account', + color: Colors.white54, ), - _line, ], - ), - ); - } + ); - Column _signUp() { - return Column( +//SignIn + Row _alreadyUser(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - MLText("email"), - MLText("password"), + MLText( + 'Already have an Account? ', + fontSize: getProportionateScreenWidth(7), + color: Colors.white, + ), + GestureDetector( + onTap: () { + Navigator.pushNamed(context, LoginScreen.routeName); + }, + child: MLText( + 'Sign in here!', + textDecoration: TextDecoration.underline, + fontSize: getProportionateScreenWidth(7), + color: Colors.blue, + ), + ), ], ); } - - MLElevatedButton _submitButton() { - return MLElevatedButton( - width: _width, - onPressed: () {}, - child: MLText("Submit"), - ); - } }