mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
auth UI and Api
This commit is contained in:
@ -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'));
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
52
lib/pages/auth/bloc/auth_event.dart
Normal file
52
lib/pages/auth/bloc/auth_event.dart
Normal 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,});
|
||||
}
|
65
lib/pages/auth/bloc/auth_state.dart
Normal file
65
lib/pages/auth/bloc/auth_state.dart
Normal 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 {}
|
@ -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'));
|
||||
// }
|
||||
// }
|
@ -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{}
|
@ -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];
|
||||
}
|
@ -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!,];
|
||||
}
|
@ -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 {}
|
@ -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';
|
@ -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';
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
},
|
@ -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,
|
||||
),
|
||||
);
|
||||
}
|
@ -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 {
|
@ -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",
|
||||
// )),
|
||||
// ],
|
||||
// ),
|
||||
// )
|
||||
],
|
||||
),
|
||||
),
|
Reference in New Issue
Block a user