mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2026-10-25 14:07:54 +00:00
Redesigned Splash Screen and Login Screen
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
|
||||
import 'package:syncrow_app/features/auth/view/widgets/auth_view_body.dart';
|
||||
|
||||
class AuthView extends StatelessWidget {
|
||||
const AuthView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<AuthCubit, AuthState>(
|
||||
builder: (context, state) {
|
||||
return const Scaffold(
|
||||
body: AuthViewBody(),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/syncrow_logo.dart';
|
||||
|
||||
import '../../../../navigation/routing_constants.dart';
|
||||
|
||||
class AuthViewBody extends StatelessWidget {
|
||||
const AuthViewBody({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 40.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const Expanded(child: SizedBox()),
|
||||
const SyncrowLogo(),
|
||||
const Expanded(flex: 2, child: SizedBox()),
|
||||
DefaultButton(
|
||||
text: 'Login',
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, Routes.authLogin);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
const DefaultButton(
|
||||
text: 'Sign Up',
|
||||
isSecondary: true,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
|
||||
class DontHaveAnAccount extends StatelessWidget {
|
||||
const DontHaveAnAccount({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 30),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
BodyLarge(
|
||||
text: "Don't have an account?",
|
||||
style: context.displaySmall.copyWith(color: Colors.white),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, Routes.authSignUp);
|
||||
},
|
||||
child: BodyLarge(
|
||||
text: "Sign Up",
|
||||
style: context.displaySmall.copyWith(
|
||||
color: Colors.black,
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
|
||||
class ForgetPassword extends StatelessWidget {
|
||||
const ForgetPassword({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
//TODO Navigate to forgot password
|
||||
},
|
||||
child: BodyMedium(
|
||||
text: "Forgot Password?",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -17,23 +17,19 @@ class LoginButton extends StatelessWidget {
|
||||
children: [
|
||||
Expanded(
|
||||
child: DefaultButton(
|
||||
enabled: AuthCubit.get(context).agreeToTerms,
|
||||
text: state is AuthLoading
|
||||
? null
|
||||
: state is AuthSuccess
|
||||
? null
|
||||
: "Login",
|
||||
child: state is AuthSuccess
|
||||
? const Icon(
|
||||
Icons.check_circle_outline,
|
||||
color: Colors.white,
|
||||
)
|
||||
: const SizedBox.square(
|
||||
dimension: 20,
|
||||
child: CircularProgressIndicator(
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
isDone: state is AuthSuccess,
|
||||
isLoading: state is AuthLoading,
|
||||
customButtonStyle: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all(
|
||||
Colors.black.withOpacity(.25),
|
||||
),
|
||||
foregroundColor: MaterialStateProperty.all(
|
||||
Colors.white,
|
||||
),
|
||||
),
|
||||
child: const Text(
|
||||
'Login',
|
||||
),
|
||||
onPressed: () {
|
||||
if (AuthCubit.get(context).formKey.currentState!.validate()) {
|
||||
AuthCubit.get(context).login();
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
|
||||
class LoginDivider extends StatelessWidget {
|
||||
const LoginDivider({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 20),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Divider(
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: BodyMedium(
|
||||
text: "or Sign in with",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Divider(
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/styles_manager.dart';
|
||||
|
||||
class LoginForm extends StatelessWidget {
|
||||
const LoginForm({
|
||||
@@ -14,77 +15,64 @@ class LoginForm extends StatelessWidget {
|
||||
builder: (context, state) {
|
||||
return Form(
|
||||
key: AuthCubit.get(context).formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: AuthCubit.get(context).emailController,
|
||||
validator: (value) {
|
||||
if (value != null) {
|
||||
if (value.isEmpty) {
|
||||
return 'Please enter your email';
|
||||
}
|
||||
//Regex for email validation
|
||||
if (!RegExp(
|
||||
r'^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$')
|
||||
.hasMatch(value)) {
|
||||
return 'Please enter a valid email';
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onTapOutside: (event) {
|
||||
AuthCubit.get(context).formKey.currentState!.validate();
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Email',
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
filled: true,
|
||||
fillColor: ColorsManager.backgroundColor.withAlpha(100),
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
contentPadding: const EdgeInsets.all(10),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const BodyMedium(
|
||||
text: "Email",
|
||||
fontColor: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
TextFormField(
|
||||
controller: AuthCubit.get(context).passwordController,
|
||||
validator: (value) {
|
||||
if (value != null) {
|
||||
if (value.isEmpty) {
|
||||
return 'Please enter your password';
|
||||
TextFormField(
|
||||
controller: AuthCubit.get(context).emailController,
|
||||
validator: (value) {
|
||||
if (value != null) {
|
||||
if (value.isEmpty) {
|
||||
return 'Please enter your email';
|
||||
}
|
||||
//Regex for email validation
|
||||
if (!RegExp(
|
||||
r'^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$')
|
||||
.hasMatch(value)) {
|
||||
return 'Please enter a valid email';
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onTapOutside: (event) {
|
||||
AuthCubit.get(context).formKey.currentState!.validate();
|
||||
},
|
||||
obscureText: !AuthCubit.get(context).isPasswordVisible,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Password',
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
AuthCubit.get(context).isPasswordVisible
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
AuthCubit.get(context).changePasswordVisibility();
|
||||
},
|
||||
),
|
||||
filled: true,
|
||||
fillColor: ColorsManager.backgroundColor.withAlpha(100),
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
contentPadding: const EdgeInsets.all(10),
|
||||
return null;
|
||||
},
|
||||
onTapOutside: (event) {
|
||||
AuthCubit.get(context).formKey.currentState!.validate();
|
||||
},
|
||||
decoration: defaultInputDecoration(context,
|
||||
hint: "[email protected]"),
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 10),
|
||||
const BodyMedium(
|
||||
text: "Password",
|
||||
fontColor: Colors.white,
|
||||
),
|
||||
TextFormField(
|
||||
controller: AuthCubit.get(context).passwordController,
|
||||
validator: (value) {
|
||||
if (value != null) {
|
||||
if (value.isNotEmpty) {
|
||||
if (value.length < 6) {
|
||||
return 'Password must be at least 8 characters';
|
||||
}
|
||||
} else {
|
||||
return 'Please enter your password';
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onTapOutside: (event) {
|
||||
AuthCubit.get(context).formKey.currentState!.validate();
|
||||
},
|
||||
obscureText: !AuthCubit.get(context).isPasswordVisible,
|
||||
decoration: defaultInputDecoration(context,
|
||||
hint: "At least 8 characters"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
|
||||
import 'package:syncrow_app/features/auth/view/widgets/login/dont_have_an_account.dart';
|
||||
import 'package:syncrow_app/features/auth/view/widgets/login/forget_password.dart';
|
||||
import 'package:syncrow_app/features/auth/view/widgets/login/login_button.dart';
|
||||
import 'package:syncrow_app/features/auth/view/widgets/login/login_divider.dart';
|
||||
import 'package:syncrow_app/features/auth/view/widgets/login/login_form.dart';
|
||||
import 'package:syncrow_app/features/auth/view/widgets/login/login_user_agreement.dart';
|
||||
import 'package:syncrow_app/features/auth/view/widgets/login/login_with_google_facebook.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
|
||||
class LoginView extends StatelessWidget {
|
||||
const LoginView({super.key});
|
||||
@@ -29,28 +36,79 @@ class LoginView extends StatelessWidget {
|
||||
},
|
||||
builder: (context, state) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(),
|
||||
body: const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: Constants.defaultPadding,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TitleMedium(
|
||||
text: 'Login',
|
||||
body: Stack(
|
||||
children: [
|
||||
Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage(
|
||||
Assets.imagesBackground,
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage(Assets.imagesVector),
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.9,
|
||||
),
|
||||
),
|
||||
LoginForm(),
|
||||
SizedBox(height: 10),
|
||||
LoginUserAgreement(),
|
||||
SizedBox(height: 10),
|
||||
LoginButton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: Constants.defaultPadding,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Center(
|
||||
child: SvgPicture.asset(
|
||||
Assets.imagesLogo,
|
||||
width: 160,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
TitleMedium(
|
||||
text: 'Login',
|
||||
style: context.titleMedium.copyWith(
|
||||
fontWeight: FontsManager.extraBold,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const LoginForm(),
|
||||
const SizedBox(height: 10),
|
||||
// const LoginUserAgreement(),
|
||||
const ForgetPassword(),
|
||||
const SizedBox(height: 10),
|
||||
const LoginButton(),
|
||||
const LoginDivider(),
|
||||
const LoginWithGoogleFacebook(),
|
||||
const DontHaveAnAccount(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
|
||||
class LoginWithGoogleFacebook extends StatelessWidget {
|
||||
const LoginWithGoogleFacebook({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: DefaultContainer(
|
||||
child: SizedBox.square(
|
||||
dimension: 24,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(Assets.iconsGoogle),
|
||||
SizedBox(width: 10),
|
||||
BodyMedium(
|
||||
text: "Google",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: DefaultContainer(
|
||||
child: SizedBox.square(
|
||||
dimension: 24,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(Assets.iconsFacebook),
|
||||
SizedBox(width: 10),
|
||||
BodyMedium(
|
||||
text: "Facebook",
|
||||
style: context.bodyMedium.copyWith(color: Colors.black),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user