diff --git a/lib/pages/auth/bloc/auth_bloc.dart b/lib/pages/auth/bloc/auth_bloc.dart index 7e57f7ab..0a3b0d24 100644 --- a/lib/pages/auth/bloc/auth_bloc.dart +++ b/lib/pages/auth/bloc/auth_bloc.dart @@ -40,10 +40,8 @@ class AuthBloc extends Bloc { if (_timer != null && _timer!.isActive) { return; } - _remainingTime = 60; - add(UpdateTimerEvent( - remainingTime: _remainingTime, isButtonEnabled: false)); - debugPrint('_remainingTime=$_remainingTime'); + _remainingTime = 1; + add(UpdateTimerEvent(remainingTime: _remainingTime, isButtonEnabled: false)); _remainingTime = (await AuthenticationAPI.sendOtp(email: forgetEmailController.text,regionUuid: regionUuid))!; _timer = Timer.periodic(const Duration(seconds: 1), (timer) { _remainingTime--; @@ -125,7 +123,6 @@ class AuthBloc extends Bloc { } catch (failure) { validate='Something went wrong'; emit(const LoginFailure(error: 'Something went wrong')); - // emit(LoginFailure(error: failure.toString())); return; } if (token.accessTokenIsNotEmpty) { @@ -187,6 +184,8 @@ class AuthBloc extends Bloc { return 'Email is required'; } else if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) { return 'Enter a valid email address'; + }else if (regionUuid=='') { + return 'Please select your region'; } return null; } diff --git a/lib/pages/auth/view/forget_password_web_page.dart b/lib/pages/auth/view/forget_password_web_page.dart index 0ae96d02..d87b277f 100644 --- a/lib/pages/auth/view/forget_password_web_page.dart +++ b/lib/pages/auth/view/forget_password_web_page.dart @@ -10,20 +10,19 @@ import 'package:syncrow_web/pages/common/first_layer.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/style.dart'; + class ForgetPasswordWebPage extends StatelessWidget { const ForgetPasswordWebPage({super.key}); @override Widget build(BuildContext context) { - return Scaffold( body: BlocProvider( create: (context) => AuthBloc()..add(RegionInitialEvent()), child: BlocConsumer( listener: (context, state) { - if (state is SuccessForgetState){ + if (state is SuccessForgetState) { Navigator.of(context).pop(); - } - else if (state is FailureForgetState) { + } else if (state is FailureForgetState) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(state.error), @@ -47,264 +46,299 @@ class ForgetPasswordWebPage extends StatelessWidget { late ScrollController _scrollController; _scrollController = ScrollController(); void _scrollToCenter() { - final double middlePosition = _scrollController.position.maxScrollExtent / 2; + final double middlePosition = + _scrollController.position.maxScrollExtent / 2; _scrollController.animateTo( middlePosition, duration: const Duration(seconds: 1), curve: Curves.easeInOut, ); } + WidgetsBinding.instance.addPostFrameCallback((_) { _scrollToCenter(); }); final forgetBloc = BlocProvider.of(context); - Size size = MediaQuery.of(context).size; + Size size = MediaQuery.of(context).size; return FirstLayer( - second: Center( - child: ListView( - shrinkWrap: true, - controller: _scrollController, - children: [ - Container( - padding: EdgeInsets.all(size.width*0.02), - margin: EdgeInsets.all(size.width*0.09), - decoration: BoxDecoration( - color: Colors.black.withOpacity(0.3), - borderRadius: const BorderRadius.all(Radius.circular(20)), - ), - child: Center( - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Spacer(), - Expanded( - flex: 3, - child: SvgPicture.asset( - Assets.loginLogo, - ), + second: Center( + child: ListView( + shrinkWrap: true, + controller: _scrollController, + children: [ + Container( + padding: EdgeInsets.all(size.width * 0.02), + margin: EdgeInsets.all(size.width * 0.09), + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.3), + borderRadius: const BorderRadius.all(Radius.circular(20)), + ), + child: Center( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Spacer(), + Expanded( + flex: 3, + child: SvgPicture.asset( + Assets.loginLogo, ), - const Spacer(), - Expanded( - flex: 3, - child: Container( - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.1), - borderRadius: const BorderRadius.all(Radius.circular(30)), - border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2)), - ), - child: Form( - key: forgetBloc.forgetFormKey, - child: Padding( - padding: EdgeInsets.symmetric( - horizontal: size.width*0.02, - vertical: size.width*0.003), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 10), - const Text( - 'Forget Password', - style: TextStyle( - color: Colors.white, - fontSize: 24, - fontWeight: FontWeight.bold), - ), - const SizedBox(height: 10), - Text( - 'Please fill in your account information to\nretrieve your password', - style: Theme.of(context).textTheme.bodySmall, - ), - const SizedBox(height: 10), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - "Country/Region", - style: Theme.of(context).textTheme.bodySmall, - ), - const SizedBox(height: 10), - SizedBox( - child: DropdownButtonFormField( - validator: forgetBloc.validateRegion, - icon: const Icon( - Icons.keyboard_arrow_down_outlined, - ), - decoration: textBoxDecoration()!.copyWith( - hintText: null, - ), - hint: SizedBox( - width: size.width * 0.11, - child: const Align( - alignment: Alignment.centerLeft, - child: Text( - 'Select your region/country', - textAlign: TextAlign.center, - overflow: TextOverflow.ellipsis, - - ), + ), + const Spacer(), + Expanded( + flex: 3, + child: Container( + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.1), + borderRadius: + const BorderRadius.all(Radius.circular(30)), + border: Border.all( + color: ColorsManager.graysColor.withOpacity(0.2)), + ), + child: Form( + key: forgetBloc.forgetFormKey, + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: size.width * 0.02, + vertical: size.width * 0.003), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 10), + const Text( + 'Forget Password', + style: TextStyle( + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + Text( + 'Please fill in your account information to\nretrieve your password', + style: Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(height: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "Country/Region", + style: + Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(height: 10), + SizedBox( + child: DropdownButtonFormField( + validator: forgetBloc.validateRegion, + icon: const Icon( + Icons.keyboard_arrow_down_outlined, + ), + decoration: textBoxDecoration()!.copyWith( + hintText: null, + ), + hint: SizedBox( + width: size.width * 0.11, + child: const Align( + alignment: Alignment.centerLeft, + child: Text( + 'Select your region/country', + textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, ), ), - isDense: true, - style: const TextStyle(color: Colors.black), - items:forgetBloc.regionList!.map((RegionModel region) { - return DropdownMenuItem( - value: region.id, - child: Text(region.name), - ); - }).toList(), - onChanged: (String? value) { - forgetBloc.add(SelectRegionEvent(val: value!,)); - }, ), - ) - ], - ), - const SizedBox(height: 20), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text("Account", - style: Theme.of(context).textTheme.bodySmall, + isDense: true, + style: + const TextStyle(color: Colors.black), + items: forgetBloc.regionList! + .map((RegionModel region) { + return DropdownMenuItem( + value: region.id, + child: Text(region.name), + ); + }).toList(), + onChanged: (String? value) { + forgetBloc.add(SelectRegionEvent( + val: value!, + )); + }, ), - const SizedBox(height: 10), - SizedBox( - child: TextFormField( - validator: forgetBloc.validateEmail, - controller: forgetBloc.forgetEmailController, - decoration: textBoxDecoration()!.copyWith(hintText: 'Enter your email'), - style: const TextStyle(color: Colors.black), - ), + ) + ], + ), + const SizedBox(height: 20), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "Account", + style: + Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(height: 10), + SizedBox( + child: TextFormField( + validator: forgetBloc.validateEmail, + controller: + forgetBloc.forgetEmailController, + decoration: textBoxDecoration()!.copyWith( + hintText: 'Enter your email'), + style: + const TextStyle(color: Colors.black), ), - ], - ), - const SizedBox(height: 20.0), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text("One Time Password", - style: Theme.of(context).textTheme.bodySmall,), - const SizedBox(height: 10), - SizedBox( - child: TextFormField( - validator: forgetBloc.validateCode, - keyboardType: TextInputType.visiblePassword, - controller: forgetBloc.forgetOtp, - decoration: textBoxDecoration()!.copyWith( - hintText: 'Enter Code', - suffixIcon: SizedBox( - width: 100, - child: Center( - child: InkWell( - onTap: () { - BlocProvider.of(context).add(StartTimerEvent()); - }, - child: - Text( - 'Get Code ${state is TimerState && !state.isButtonEnabled ? "(${ BlocProvider.of(context).formattedTime(state.remainingTime)})" : ""}', - style: TextStyle( - color: state is TimerState && !state.isButtonEnabled - ? Colors.grey - : ColorsManager.btnColor, - ), + ), + ], + ), + const SizedBox(height: 20.0), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "One Time Password", + style: + Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(height: 10), + SizedBox( + child: TextFormField( + validator: forgetBloc.validateCode, + keyboardType: + TextInputType.visiblePassword, + controller: forgetBloc.forgetOtp, + decoration: textBoxDecoration()!.copyWith( + hintText: 'Enter Code', + suffixIcon: SizedBox( + width: 100, + child: Center( + child: InkWell( + onTap: () { + BlocProvider.of( + context) + .add(StartTimerEvent()); + }, + child: Text( + 'Get Code ${state is TimerState && !state.isButtonEnabled ? "(${BlocProvider.of(context).formattedTime(state.remainingTime)}) " : ""}', + style: TextStyle( + color: state is TimerState && + !state.isButtonEnabled + ? Colors.grey + : ColorsManager.btnColor, ), ), ), ), ), - style: const TextStyle(color: Colors.black), ), + style: + const TextStyle(color: Colors.black), ), - ], - ), - const SizedBox(height: 20.0), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text("Password", - style: Theme.of(context).textTheme.bodySmall,), - const SizedBox(height: 10), - SizedBox( - child: TextFormField( - validator: forgetBloc.passwordValidator, - keyboardType: TextInputType.visiblePassword, - controller: forgetBloc.forgetPasswordController, - decoration: textBoxDecoration()!.copyWith( - hintText: 'At least 8 characters', - ), - style: const TextStyle(color: Colors.black), - ), - ), - ], - ), - const SizedBox( - height: 10, - ), - const SizedBox(height: 20.0), - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox( - width: size.width * 0.2, - child: DefaultButton( - backgroundColor: ColorsManager.btnColor, - child: const Text('Submit'), - onPressed: () { - if (forgetBloc.forgetFormKey.currentState!.validate()) { - forgetBloc.add(ChangePasswordEvent()); - } - }, - ), - ), - ], - ), - const SizedBox(height: 10.0), - SizedBox(child: Text(forgetBloc.validate, - style: const TextStyle(fontWeight: FontWeight.w700,color: ColorsManager.red ),),), - SizedBox(height: 10,), - SizedBox( - width: size.width * 0.2, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Flexible( - child: Text( - "Do you have an account? ", - style: TextStyle(color: Colors.white), - )), - InkWell( - onTap: () { - Navigator.pop(context); - }, - child: const Flexible( - child: Text( - "Sign in", - )), - ), - ], ), - ) - ], - ), + ], + ), + const SizedBox(height: 20.0), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "Password", + style: + Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(height: 10), + SizedBox( + child: TextFormField( + validator: forgetBloc.passwordValidator, + keyboardType: + TextInputType.visiblePassword, + controller: + forgetBloc.forgetPasswordController, + decoration: textBoxDecoration()!.copyWith( + hintText: 'At least 8 characters', + ), + style: + const TextStyle(color: Colors.black), + ), + ), + ], + ), + const SizedBox( + height: 10, + ), + const SizedBox(height: 20.0), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + width: size.width * 0.2, + child: DefaultButton( + backgroundColor: ColorsManager.btnColor, + child: const Text('Submit'), + onPressed: () { + if (forgetBloc + .forgetFormKey.currentState! + .validate()) { + forgetBloc.add(ChangePasswordEvent()); + } + }, + ), + ), + ], + ), + const SizedBox(height: 10.0), + SizedBox( + child: Text( + forgetBloc.validate, + style: const TextStyle( + fontWeight: FontWeight.w700, + color: ColorsManager.red), + ), + ), + SizedBox( + height: 10, + ), + SizedBox( + width: size.width * 0.2, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Flexible( + child: Text( + "Do you have an account? ", + style: TextStyle(color: Colors.white), + )), + InkWell( + onTap: () { + Navigator.pop(context); + }, + child: const Flexible( + child: Text( + "Sign in", + )), + ), + ], + ), + ) + ], ), ), ), ), - const Spacer(), - ], - ), + ), + const Spacer(), + ], ), ), - ], - ), - ) - ); + ), + ], + ), + )); } } diff --git a/lib/services/auth_api.dart b/lib/services/auth_api.dart index 3c7f3fbf..a0c0b87f 100644 --- a/lib/services/auth_api.dart +++ b/lib/services/auth_api.dart @@ -45,33 +45,38 @@ class AuthenticationAPI { "regionUuid": regionUuid }, showServerMessage: true, - options: Options(), expectedResponseModel: (json) { - Map parsedJson = jsonDecode(json); - int cooldown = parsedJson['data']['cooldown']; - debugPrint('Cooldown: $cooldown seconds'); - return cooldown; + return 30; } ); - return response; + return 30; } on DioError catch (e) { + if (e.response != null) { if (e.response!.statusCode == 400) { // Handle 400 Bad Request final errorData = e.response!.data; - String errorMessage = errorData['message'] ?? 'Unknown error'; - int cooldown = errorData['data']['cooldown'] ?? 0; - return cooldown; + String errorMessage = errorData['message']; + debugPrint('Unexpected Error: $errorMessage'); + if(errorMessage=='User not found'){ + return 1; + }else{ + int cooldown = errorData['data']['cooldown'] ?? 1; + return cooldown; + } + } else { debugPrint('Error: ${e.response!.statusCode} - ${e.response!.statusMessage}'); + return 1; } } else { debugPrint('Error: ${e.message}'); + return 1; } - return null; + return 1; } catch (e) { debugPrint('Unexpected Error: $e'); - return null; + return 1; } } @@ -79,7 +84,7 @@ class AuthenticationAPI { {required String email, required String otpCode}) async { final response = await HTTPService().post( path: ApiEndpoints.verifyOtp, - body: {"email": email, "type": "VERIFICATION", "otpCode": otpCode}, + body: {"email": email, "type": "PASSWORD", "otpCode": otpCode}, showServerMessage: true, expectedResponseModel: (json) { if (json['message'] == 'Otp Verified Successfully') {