auth UI and Api

This commit is contained in:
mohammad
2024-07-31 12:34:37 +03:00
parent 7e9b24a95b
commit 69abad24b7
25 changed files with 323 additions and 457 deletions

View File

@ -1,28 +1,104 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:syncrow_web/pages/auth/login/bloc/login_event.dart';
import 'package:syncrow_web/pages/auth/login/bloc/login_state.dart';
import 'package:syncrow_web/pages/auth/login/model/login_with_email_model.dart';
import 'package:syncrow_web/pages/auth/login/model/token.dart';
import 'package:syncrow_web/pages/auth/login/model/user_model.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_event.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_state.dart';
import 'package:syncrow_web/pages/auth/model/login_with_email_model.dart';
import 'package:syncrow_web/pages/auth/model/token.dart';
import 'package:syncrow_web/pages/auth/model/user_model.dart';
import 'package:syncrow_web/services/auth_api.dart';
import 'package:syncrow_web/utils/snack_bar.dart';
class LoginBloc extends Bloc<LoginEvent, LoginState> {
LoginBloc() : super(LoginInitial()) {
class AuthBloc extends Bloc<AuthEvent, AuthState> {
AuthBloc() : super(LoginInitial()) {
on<LoginButtonPressed>(_login);
on<CheckBoxEvent>(checkBoxTgl);
on<CheckBoxEvent>(checkBoxToggle);
on<ChangePasswordEvent>(changePassword);
on<StartTimerEvent>(_onStartTimer);
on<StopTimerEvent>(_onStopTimer);
on<UpdateTimerEvent>(_onUpdateTimer);
on<PasswordVisibleEvent>(_passwordVisible);
}
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
final formKey = GlobalKey<FormState>();
bool isChecked = false;
bool obscureText = true;
_login(LoginButtonPressed event, Emitter<LoginState> emit) async {
////////////////////////////// forget password //////////////////////////////////
final TextEditingController forgetEmailController = TextEditingController();
final TextEditingController forgetPasswordController = TextEditingController();
final TextEditingController forgetOtp = TextEditingController();
final forgetFormKey = GlobalKey<FormState>();
Timer? _timer;
int _remainingTime = 0;
Future<void> _onStartTimer(StartTimerEvent event, Emitter<AuthState> emit) async {
if (_validateInputs(emit)) return;
print("StartTimerEvent received");
if (_timer != null && _timer!.isActive) {
print("Timer is already active");
return;
}
_remainingTime = 60;
add(UpdateTimerEvent(
remainingTime: _remainingTime, isButtonEnabled: false));
print("Timer started, initial remaining time: $_remainingTime");
await AuthenticationAPI.sendOtp(email: forgetEmailController.text);
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
_remainingTime--;
print("Timer tick, remaining time: $_remainingTime"); // Debug print
if (_remainingTime <= 0) {
_timer?.cancel();
add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true));
print("Timer finished"); // Debug print
} else {
add(UpdateTimerEvent(remainingTime: _remainingTime, isButtonEnabled: false));
}
});
}
void _onStopTimer(StopTimerEvent event, Emitter<AuthState> emit) {
_timer?.cancel();
emit(const TimerState(isButtonEnabled: true, remainingTime: 0));
}
Future<void> changePassword(
ChangePasswordEvent event, Emitter<AuthState> emit) async {
try {
emit(LoadingForgetState());
await AuthenticationAPI.forgetPassword(
password: forgetPasswordController.text, email: forgetEmailController.text);
emit(SuccessForgetState());
} catch (failure) {
print(failure);
emit(FailureForgetState(error: failure.toString()));
}
}
void _onUpdateTimer(UpdateTimerEvent event, Emitter<AuthState> emit) {
emit(TimerState(
isButtonEnabled: event.isButtonEnabled,
remainingTime: event.remainingTime));
}
///////////////////////////////////// login /////////////////////////////////////
final TextEditingController loginEmailController = TextEditingController();
final TextEditingController loginPasswordController = TextEditingController();
final loginFormKey = GlobalKey<FormState>();
bool isChecked = false;
bool obscureText = false;
String newPassword = '';
String maskedEmail = '';
String otpCode = '';
static Token token = Token.emptyConstructor();
static UserModel? user;
bool showValidationMessage = false;
void _login(LoginButtonPressed event, Emitter<AuthState> emit) async {
emit(LoginLoading());
if(isChecked) {
try {
@ -54,8 +130,8 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
value: Token.decodeToken(token.accessToken)['uuid'].toString()
);
user = UserModel.fromToken(token);
emailController.clear();
passwordController.clear();
loginEmailController.clear();
loginPasswordController.clear();
emit(LoginSuccess());
} else {
emit(const LoginFailure(error: 'Something went wrong'));
@ -66,12 +142,17 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
}
}
checkBoxTgl(CheckBoxEvent event, Emitter<LoginState> emit,){
checkBoxToggle(CheckBoxEvent event, Emitter<AuthState> emit,){
emit(LoginLoading());
isChecked = event.newValue!;
emit(LoginInitial());
}
void _passwordVisible(PasswordVisibleEvent event, Emitter<AuthState> emit) {
emit(LoginLoading());
obscureText = !event.newValue!;
emit(PasswordVisibleState());
}
void launchURL(String url) {
if (kDebugMode) {
@ -80,16 +161,6 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
}
String newPassword = '';
String maskedEmail = '';
String otpCode = '';
static Token token = Token.emptyConstructor();
static UserModel? user;
bool showValidationMessage = false;
/////////////////////////////////////VALIDATORS/////////////////////////////////////
String? validatePassword(String? value) {
@ -110,8 +181,23 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
return null;
}
String? validateCode(String? value) {
if (value == null || value.isEmpty) {
return 'Code is required';
}
return null;
}
bool _validateInputs(Emitter<AuthState> emit) {
emit(LoadingForgetState());
final nameError = validateEmail(forgetEmailController.text);
if (nameError != null) {
emit(FailureForgetState(error:nameError )) ;
// CustomSnackBar.displaySnackBar(nameError);
return true;
}
return false;
}
String? validateRegion(String? value) {
if (value == null || value.isEmpty) {
@ -227,7 +313,6 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
return '$maskedLocalPart@$domainPart';
}
final List<String> regions = [
'North America',
'South America',
@ -238,31 +323,5 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
'Antarctica',
];
// signUp() async {
// emit(LoginLoading());
// final response;
// try {
// List<String> userFullName = fullName.split(' ');
// response = await AuthenticationAPI.signUp(
// model: SignUpModel(
// email: email.toLowerCase(),
// password: signUpPassword,
// firstName: userFullName[0],
// lastName: userFullName[1]),
// );
// } catch (failure) {
// emit(AuthLoginError(message: failure.toString()));
// return;
// }
// if (response) {
// maskedEmail = maskEmail(email);
// await sendOtp();
// } else {
// emit(AuthLoginError(message: 'Something went wrong'));
// }
// }
}

View File

@ -0,0 +1,52 @@
import 'package:equatable/equatable.dart';
abstract class AuthEvent extends Equatable {
const AuthEvent();
@override
List<Object> get props => [];
}
class LoginButtonPressed extends AuthEvent {
final String username;
final String password;
const LoginButtonPressed({required this.username, required this.password});
@override
List<Object> get props => [username, password];
}
class CheckBoxEvent extends AuthEvent {
final bool? newValue;
const CheckBoxEvent({required this.newValue,});
@override
List<Object> get props => [newValue!,];
}
class GetCodeEvent extends AuthEvent{}
class SubmitEvent extends AuthEvent{}
class StartTimerEvent extends AuthEvent{}
class StopTimerEvent extends AuthEvent{}
class UpdateTimerEvent extends AuthEvent {
final int remainingTime;
final bool isButtonEnabled;
const UpdateTimerEvent({required this.remainingTime, required this.isButtonEnabled});
}
class ChangePasswordEvent extends AuthEvent{}
class SendOtpEvent extends AuthEvent{}
class PasswordVisibleEvent extends AuthEvent{
final bool? newValue;
const PasswordVisibleEvent({required this.newValue,});
}

View File

@ -0,0 +1,65 @@
import 'package:equatable/equatable.dart';
abstract class AuthState extends Equatable {
const AuthState();
@override
List<Object> get props => [];
}
class LoginInitial extends AuthState {}
class LoginLoading extends AuthState {}
class LoginSuccess extends AuthState {}
class LoginFailure extends AuthState {
final String error;
const LoginFailure({required this.error});
@override
List<Object> get props => [error];
}
class LoginValid extends AuthState {}
class LoginInvalid extends AuthState {
final String error;
const LoginInvalid({required this.error});
@override
List<Object> get props => [error];
}
class InitialForgetState extends AuthState{}
class LoadingForgetState extends AuthState{}
class SuccessForgetState extends AuthState{}
class PasswordVisibleState extends AuthState{}
class FailureForgetState extends AuthState {
final String error;
const FailureForgetState({required this.error});
@override
List<Object> get props => [error];
}
class TimerState extends AuthState {
final bool isButtonEnabled ;
final int remainingTime;
const TimerState({required this.isButtonEnabled, required this.remainingTime});
@override
List<Object> get props => [isButtonEnabled, remainingTime];
}
// class AuthState extends AuthState {}

View File

@ -1,195 +0,0 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/auth/forget_password/bloc/forget_password_event.dart';
import 'package:syncrow_web/pages/auth/forget_password/bloc/forget_password_state.dart';
import 'package:syncrow_web/services/auth_api.dart';
class ForgetPasswordBloc
extends Bloc<ForgetPasswordEvent, ForgetPasswordState> {
ForgetPasswordBloc() : super(InitialForgetState()) {
on<ChangePasswordEvent>(changePassword);
on<StartTimerEvent>(_onStartTimer);
on<StopTimerEvent>(_onStopTimer);
on<UpdateTimerEvent>(_onUpdateTimer);
}
void _onUpdateTimer(UpdateTimerEvent event, Emitter<ForgetPasswordState> emit) {
emit(TimerState(
isButtonEnabled: event.isButtonEnabled,
remainingTime: event.remainingTime));
}
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
final TextEditingController otp = TextEditingController();
final formKey = GlobalKey<FormState>();
Timer? _timer;
int _remainingTime = 0;
Future<void> _onStartTimer(
StartTimerEvent event, Emitter<ForgetPasswordState> emit) async {
if (_validateInputs(emit)) return;
print("StartTimerEvent received");
if (_timer != null && _timer!.isActive) {
print("Timer is already active");
return;
}
_remainingTime = 60;
add(UpdateTimerEvent(
remainingTime: _remainingTime, isButtonEnabled: false));
print("Timer started, initial remaining time: $_remainingTime");
await AuthenticationAPI.sendOtp(email: emailController.text);
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
_remainingTime--;
print("Timer tick, remaining time: $_remainingTime"); // Debug print
if (_remainingTime <= 0) {
_timer?.cancel();
add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true));
print("Timer finished"); // Debug print
} else {
add(UpdateTimerEvent(remainingTime: _remainingTime, isButtonEnabled: false));
}
});
}
void _onStopTimer(StopTimerEvent event, Emitter<ForgetPasswordState> emit) {
_timer?.cancel();
emit(TimerState(isButtonEnabled: true, remainingTime: 0));
}
Future<void> changePassword(
ChangePasswordEvent event, Emitter<ForgetPasswordState> emit) async {
try {
emit(LoadingForgetState());
await AuthenticationAPI.forgetPassword(
password: passwordController.text, email: emailController.text);
emit(SuccessForgetState());
} catch (failure) {
print(failure);
emit(FailureForgetState(error: failure.toString()));
}
}
String? validateEmail(String? value) {
if (value == null || value.isEmpty) {
return 'Email is required';
} else if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) {
return 'Enter a valid email address';
}
return null;
}
String? validateRegion(String? value) {
if (value == null || value.isEmpty) {
return 'Please select a region';
}
return null;
}
String? otpValidate(String? value) {
if (value == null || value.isEmpty) {
return 'Please select a region';
}
return null;
}
String? passwordValidator(String? value) {
if (value == null || value.isEmpty) {
return 'Please enter your password';
}
List<String> validationErrors = [];
if (!RegExp(r'^(?=.*[a-z])').hasMatch(value)) {
validationErrors.add(' - one lowercase letter');
}
if (!RegExp(r'^(?=.*[A-Z])').hasMatch(value)) {
validationErrors.add(' - one uppercase letter');
}
if (!RegExp(r'^(?=.*\d)').hasMatch(value)) {
validationErrors.add(' - one number');
}
if (!RegExp(r'^(?=.*[@$!%*?&])').hasMatch(value)) {
validationErrors.add(' - one special character');
}
if (value.length < 8) {
validationErrors.add(' - minimum 8 characters');
}
if (validationErrors.isNotEmpty) {
return 'Password must contain at least:\n${validationErrors.join('\n')}';
}
return null;
}
final List<String> regions = [
'North America',
'South America',
'Europe',
'Asia',
'Africa',
'Australia',
'Antarctica',
];
bool _validateInputs(Emitter<ForgetPasswordState> emit) {
emit(LoadingForgetState());
final nameError = validateEmail(emailController.text);
if (nameError != null) {
emit(FailureForgetState(error:nameError )) ;
// CustomSnackBar.displaySnackBar(nameError);
return true;
}
return false;
}
}
//
//
// _login(LoginButtonPressed event, Emitter<LoginState> emit) async {
// emit(LoginLoading());
// if(isChecked) {
// try {
// if (event.username.isEmpty || event.password.isEmpty) {
// CustomSnackBar.displaySnackBar('Please enter your credentials');
// emit(const LoginFailure(error: 'Something went wrong'));
// return;
// }
// token = await AuthenticationAPI.loginWithEmail(
// model: LoginWithEmailModel(
// email: event.username,
// password: event.password,
// ),
// );
// }
// catch (failure) {
// emit(const LoginFailure(error: 'Something went wrong'));
// // emit(LoginFailure(error: failure.toString()));
// return;
// }
// if (token.accessTokenIsNotEmpty) {
// debugPrint('token: ${token.accessToken}');
// FlutterSecureStorage storage = const FlutterSecureStorage();
// await storage.write(
// key: Token.loginAccessTokenKey, value: token.accessToken);
//
// const FlutterSecureStorage().write(
// key: UserModel.userUuidKey,
// value: Token.decodeToken(token.accessToken)['uuid'].toString()
// );
// user = UserModel.fromToken(token);
// emailController.clear();
// passwordController.clear();
// emit(LoginSuccess());
// } else {
// emit(const LoginFailure(error: 'Something went wrong'));
// }
// }
// else{
// emit(const LoginFailure(error: 'Accept terms and condition'));
// }
// }

View File

@ -1,26 +0,0 @@
import 'package:equatable/equatable.dart';
abstract class ForgetPasswordEvent extends Equatable {
const ForgetPasswordEvent();
@override
List<Object> get props => [];
}
class GetCodeEvent extends ForgetPasswordEvent{}
class SubmitEvent extends ForgetPasswordEvent{}
class StartTimerEvent extends ForgetPasswordEvent{}
class StopTimerEvent extends ForgetPasswordEvent{}
class UpdateTimerEvent extends ForgetPasswordEvent {
final int remainingTime;
final bool isButtonEnabled;
const UpdateTimerEvent({required this.remainingTime, required this.isButtonEnabled});
}
class ChangePasswordEvent extends ForgetPasswordEvent{}
class SendOtpEvent extends ForgetPasswordEvent{}

View File

@ -1,35 +0,0 @@
import 'package:equatable/equatable.dart';
class ForgetPasswordState extends Equatable{
const ForgetPasswordState();
@override
List<Object> get props => [];
}
class InitialForgetState extends ForgetPasswordState{}
class LoadingForgetState extends ForgetPasswordState{}
class SuccessForgetState extends ForgetPasswordState{}
class FailureForgetState extends ForgetPasswordState {
final String error;
const FailureForgetState({required this.error});
@override
List<Object> get props => [error];
}
class TimerState extends ForgetPasswordState {
final bool isButtonEnabled ;
final int remainingTime;
const TimerState({required this.isButtonEnabled, required this.remainingTime});
@override
List<Object> get props => [isButtonEnabled, remainingTime];
}

View File

@ -1,28 +0,0 @@
import 'package:equatable/equatable.dart';
abstract class LoginEvent extends Equatable {
const LoginEvent();
@override
List<Object> get props => [];
}
class LoginButtonPressed extends LoginEvent {
final String username;
final String password;
const LoginButtonPressed({required this.username, required this.password});
@override
List<Object> get props => [username, password];
}
class CheckBoxEvent extends LoginEvent {
final bool? newValue;
const CheckBoxEvent({required this.newValue,});
@override
List<Object> get props => [newValue!,];
}

View File

@ -1,39 +0,0 @@
import 'package:equatable/equatable.dart';
abstract class LoginState extends Equatable {
const LoginState();
@override
List<Object> get props => [];
}
class LoginInitial extends LoginState {}
class LoginLoading extends LoginState {}
class LoginSuccess extends LoginState {}
class LoginFailure extends LoginState {
final String error;
const LoginFailure({required this.error});
@override
List<Object> get props => [error];
}
class LoginValid extends LoginState {}
class LoginInvalid extends LoginState {
final String error;
const LoginInvalid({required this.error});
@override
List<Object> get props => [error];
}
// class LoginState extends LoginState {}

View File

@ -1,5 +1,6 @@
import 'package:syncrow_web/pages/auth/login/model/token.dart';
import 'package:syncrow_web/pages/auth/model/token.dart';
class UserModel {
static String userUuidKey = 'userUuid';

View File

@ -1,8 +1,7 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/auth/forget_password/view/forget_password_mobile_page.dart';
import 'package:syncrow_web/pages/auth/forget_password/view/forget_password_web_page.dart';
import 'package:syncrow_web/pages/auth/view/forget_password_mobile_page.dart';
import 'package:syncrow_web/pages/auth/view/forget_password_web_page.dart';
import 'package:syncrow_web/utils/responsive_layout.dart';

View File

@ -1,10 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/auth/forget_password/bloc/forget_password_bloc.dart';
import 'package:syncrow_web/pages/auth/forget_password/bloc/forget_password_event.dart';
import 'package:syncrow_web/pages/auth/forget_password/bloc/forget_password_state.dart';
import 'package:syncrow_web/pages/auth/login/view/login_page.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_event.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_state.dart';
import 'package:syncrow_web/pages/common/default_button.dart';
import 'package:syncrow_web/pages/common/first_layer.dart';
import 'package:syncrow_web/utils/color_manager.dart';
@ -18,8 +17,8 @@ class ForgetPasswordWebPage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
body: BlocProvider(
create: (context) => ForgetPasswordBloc(),
child: BlocConsumer<ForgetPasswordBloc, ForgetPasswordState>(
create: (context) => AuthBloc(),
child: BlocConsumer<AuthBloc, AuthState>(
listener: (context, state) {
if (state is LoadingForgetState) {
} else if (state is FailureForgetState) {
@ -42,8 +41,8 @@ class ForgetPasswordWebPage extends StatelessWidget {
);
}
Widget _buildForm(BuildContext context, ForgetPasswordState state) {
final forgetBloc = BlocProvider.of<ForgetPasswordBloc>(context);
Widget _buildForm(BuildContext context, AuthState state) {
final forgetBloc = BlocProvider.of<AuthBloc>(context);
return FirstLayer(
second: Container(
margin: const EdgeInsets.all(50),
@ -74,7 +73,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2)),
),
child: Form(
key: forgetBloc.formKey,
key: forgetBloc.forgetFormKey,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 20),
child: Column(
@ -147,7 +146,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
width: MediaQuery.sizeOf(context).width * 0.2,
child: TextFormField(
validator: forgetBloc.validateEmail,
controller: forgetBloc.emailController,
controller: forgetBloc.forgetEmailController,
decoration: textBoxDecoration()!.copyWith(hintText: 'Enter your email'),
style: const TextStyle(color: Colors.black),
),
@ -164,9 +163,9 @@ class ForgetPasswordWebPage extends StatelessWidget {
SizedBox(
width: MediaQuery.sizeOf(context).width * 0.2,
child: TextFormField(
validator: forgetBloc.otpValidate,
validator: forgetBloc.validateCode,
keyboardType: TextInputType.visiblePassword,
controller: forgetBloc.otp,
controller: forgetBloc.forgetOtp,
decoration: textBoxDecoration()!.copyWith(
hintText: 'Enter Code',
suffixIcon: SizedBox(
@ -174,7 +173,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
child: Center(
child: InkWell(
onTap: () {
BlocProvider.of<ForgetPasswordBloc>(context).add(StartTimerEvent());
BlocProvider.of<AuthBloc>(context).add(StartTimerEvent());
},
child: Text(
'Get Code ${state is TimerState && !state.isButtonEnabled ? "(${state.remainingTime.toString()})" : ""}',
@ -205,7 +204,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
child: TextFormField(
validator: forgetBloc.passwordValidator,
keyboardType: TextInputType.visiblePassword,
controller: forgetBloc.passwordController,
controller: forgetBloc.forgetPasswordController,
decoration: textBoxDecoration()!.copyWith(
hintText: 'At least 8 characters',
),
@ -224,7 +223,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
backgroundColor: ColorsManager.btnColor,
child: const Text('Submit'),
onPressed: () {
if (forgetBloc.formKey.currentState!.validate()) {
if (forgetBloc.forgetFormKey.currentState!.validate()) {
forgetBloc.add(ChangePasswordEvent());
}
},

View File

@ -3,10 +3,10 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/pages/auth/forget_password/view/forget_password_page.dart';
import 'package:syncrow_web/pages/auth/login/bloc/login_bloc.dart';
import 'package:syncrow_web/pages/auth/login/bloc/login_event.dart';
import 'package:syncrow_web/pages/auth/login/bloc/login_state.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_event.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_state.dart';
import 'package:syncrow_web/pages/auth/view/forget_password_page.dart';
import 'package:syncrow_web/pages/common/default_button.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
@ -20,8 +20,8 @@ class LoginMobilePage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
body: BlocProvider(
create: (context) => LoginBloc(),
child: BlocConsumer<LoginBloc, LoginState>(
create: (context) => AuthBloc(),
child: BlocConsumer<AuthBloc, AuthState>(
listener: (context, state) {
if (state is LoginSuccess) {
// Navigate to home screen after successful login
@ -51,7 +51,7 @@ class LoginMobilePage extends StatelessWidget {
}
Widget _buildLoginForm(BuildContext context) {
final loginBloc = BlocProvider.of<LoginBloc>(context);
final loginBloc = BlocProvider.of<AuthBloc>(context);
final TextEditingController _usernameController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
return Center(
@ -108,7 +108,7 @@ class LoginMobilePage extends StatelessWidget {
color:
ColorsManager.graysColor.withOpacity(0.2))),
child: Form(
key: loginBloc.formKey,
key: loginBloc.loginFormKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
@ -174,7 +174,7 @@ class LoginMobilePage extends StatelessWidget {
SizedBox(
child: TextFormField(
validator: loginBloc.validateEmail,
controller: loginBloc.emailController,
controller: loginBloc.loginEmailController,
decoration: textBoxDecoration()!
.copyWith(hintText: 'Enter your email'),
style: const TextStyle(color: Colors.black),
@ -196,7 +196,7 @@ class LoginMobilePage extends StatelessWidget {
validator: loginBloc.validatePassword,
obscureText: loginBloc.obscureText,
keyboardType: TextInputType.visiblePassword,
controller: loginBloc.passwordController,
controller: loginBloc.loginPasswordController,
decoration: textBoxDecoration()!.copyWith(
hintText: 'At least 8 characters',
),
@ -297,14 +297,14 @@ class LoginMobilePage extends StatelessWidget {
: ColorsManager.grayColor,
child: const Text('Sign in'),
onPressed: () {
if (loginBloc.formKey.currentState!
if (loginBloc.loginFormKey.currentState!
.validate()) {
loginBloc.add(
LoginButtonPressed(
username:
loginBloc.emailController.text,
loginBloc.loginEmailController.text,
password:
loginBloc.passwordController.text,
loginBloc.loginPasswordController.text,
),
);
}

View File

@ -1,8 +1,8 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:syncrow_web/pages/auth/login/view/login_mobile_page.dart';
import 'package:syncrow_web/pages/auth/login/view/login_web_page.dart';
import 'package:syncrow_web/pages/auth/view/login_mobile_page.dart';
import 'package:syncrow_web/pages/auth/view/login_web_page.dart';
import 'package:syncrow_web/utils/responsive_layout.dart';
class LoginPage extends StatelessWidget {

View File

@ -4,10 +4,10 @@ import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/pages/auth/login/bloc/login_bloc.dart';
import 'package:syncrow_web/pages/auth/login/bloc/login_event.dart';
import 'package:syncrow_web/pages/auth/login/bloc/login_state.dart';
import 'package:syncrow_web/pages/auth/forget_password/view/forget_password_page.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_event.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_state.dart';
import 'package:syncrow_web/pages/auth/view/forget_password_page.dart';
import 'package:syncrow_web/pages/common/default_button.dart';
import 'package:syncrow_web/pages/common/first_layer.dart';
import 'package:syncrow_web/utils/color_manager.dart';
@ -22,8 +22,8 @@ class LoginWebPage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
body: BlocProvider(
create: (context) => LoginBloc(),
child: BlocConsumer<LoginBloc, LoginState>(
create: (context) => AuthBloc(),
child: BlocConsumer<AuthBloc, AuthState>(
listener: (context, state) {
if (state is LoginSuccess) {
// Navigate to home screen after successful login
@ -44,7 +44,7 @@ class LoginWebPage extends StatelessWidget {
if (state is LoginLoading) {
return const Center(child: CircularProgressIndicator());
} else {
return _buildLoginForm(context);
return _buildLoginForm(context,state);
}
},
),
@ -52,8 +52,8 @@ class LoginWebPage extends StatelessWidget {
);
}
Widget _buildLoginForm(BuildContext context) {
final loginBloc = BlocProvider.of<LoginBloc>(context);
Widget _buildLoginForm(BuildContext context,AuthState state) {
final loginBloc = BlocProvider.of<AuthBloc>(context);
return FirstLayer(
second: Container(
margin: const EdgeInsets.all(50),
@ -83,7 +83,7 @@ class LoginWebPage extends StatelessWidget {
borderRadius: const BorderRadius.all(Radius.circular(30)),
border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2))),
child: Form(
key: loginBloc.formKey,
key: loginBloc.loginFormKey,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 20),
child: Column(
@ -151,7 +151,7 @@ class LoginWebPage extends StatelessWidget {
width: MediaQuery.sizeOf(context).width * 0.2,
child: TextFormField(
validator:loginBloc.validateEmail ,
controller:loginBloc.emailController,
controller:loginBloc.loginEmailController,
decoration: textBoxDecoration()!.copyWith(hintText: 'Enter your email'),
style: const TextStyle(color: Colors.black),
),
@ -163,17 +163,29 @@ class LoginWebPage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text("Password",
style: smallTextStyle,),
Text("Password", style: smallTextStyle,),
SizedBox(
width: MediaQuery.sizeOf(context).width * 0.2,
child: TextFormField(
validator:loginBloc.validatePassword ,
validator:loginBloc.validatePassword,
obscureText:loginBloc.obscureText,
keyboardType: TextInputType.visiblePassword,
controller:loginBloc.passwordController,
controller:loginBloc.loginPasswordController,
decoration: textBoxDecoration()!.copyWith(
hintText: 'At least 8 characters',
suffixIcon: IconButton(onPressed: () {
loginBloc.add(PasswordVisibleEvent(newValue: loginBloc.obscureText));
},
icon: SizedBox(
child: SvgPicture.asset(
loginBloc.obscureText?
Assets.visiblePassword :
Assets.invisiblePassword,
height: 15,
width: 15,
),
),
)
),
style: const TextStyle(color: Colors.black),
),
@ -265,10 +277,10 @@ class LoginWebPage extends StatelessWidget {
ColorsManager.btnColor:ColorsManager.grayColor,
child: const Text('Sign in'),
onPressed: () {
if (loginBloc.formKey.currentState!.validate()) {
if (loginBloc.loginFormKey.currentState!.validate()) {
loginBloc.add(LoginButtonPressed(
username: loginBloc.emailController.text,
password: loginBloc.passwordController.text,
username: loginBloc.loginEmailController.text,
password: loginBloc.loginPasswordController.text,
),
);
}
@ -359,24 +371,24 @@ class LoginWebPage extends StatelessWidget {
// ],
// ),
// ),
SizedBox(
width: MediaQuery.sizeOf(context).width * 0.2,
child: const Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Flexible(
child: Text(
"Don't you have an account? ",
style: TextStyle(color: Colors.white),
)),
Flexible(
child: Text(
"Sign up",
)),
],
),
)
// SizedBox(
// width: MediaQuery.sizeOf(context).width * 0.2,
// child: const Row(
// mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// Flexible(
// child: Text(
// "Don't you have an account? ",
// style: TextStyle(color: Colors.white),
// )),
// Flexible(
// child: Text(
// "Sign up",
// )),
// ],
// ),
// )
],
),
),