import 'dart:async'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_event.dart'; import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_state.dart'; import 'package:syncrow_app/services/api/authentication_api.dart'; class SecurityBloc extends Bloc { bool _isPasswordVisible = false; String otpCode = ''; String validate = ''; SecurityBloc() : super(PasswordVisibilityState(false)) { on(_onSetPassword); on(_onTogglePasswordVisibility); on(_onStartTimer); on(_onStopTimer); on(_onUpdateTimer); on(verifyCode); on(changePassword); on(onDeleteAccountEvent); } void _onSetPassword(SetPassword event, Emitter emit) { if (event.password.length < 6) { emit(PasswordErrorState('Password must be at least 6 characters long.')); } else { emit(PasswordSetState('Password successfully set.')); } } void _onTogglePasswordVisibility( TogglePasswordVisibility event, Emitter emit) { _isPasswordVisible = !_isPasswordVisible; emit(PasswordVisibilityState(_isPasswordVisible)); } String? passwordValidator(String? value) { if (value == null || value.isEmpty) { return 'Please enter your password'; } List 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; } TextEditingController newPassword = TextEditingController(); Timer? _timer; int _remainingTime = 0; Future _onStartTimer( StartTimerEvent event, Emitter emit) async { if (_timer != null && _timer!.isActive) { return; } _remainingTime = 1; add(UpdateTimerEvent( remainingTime: _remainingTime, isButtonEnabled: false)); try { _remainingTime = 30; var res = (await AuthenticationAPI.sendOtp(body: { 'email': HomeCubit.user!.email, 'type': 'PASSWORD', if (HomeCubit.user!.regionUuid != null) 'regionUuid': HomeCubit.user!.regionUuid })); _remainingTime = res['cooldown']; } on DioException catch (e) { if (e.response!.statusCode == 400) { final errorData = e.response!.data; String errorMessage = errorData['message']; if (errorMessage == 'User not found') { validate = 'Invalid Credential'; emit(AuthInitialState()); return 1; } else { validate = ''; _remainingTime = errorData['data']['cooldown'] ?? 1; emit(AuthInitialState()); } } else { emit(AuthInitialState()); return 1; } emit(AuthInitialState()); } catch (e) { emit(AuthInitialState()); return 1; } _timer = Timer.periodic(const Duration(seconds: 1), (timer) { _remainingTime--; if (_remainingTime <= 0) { _timer?.cancel(); add(UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true)); } else { add(UpdateTimerEvent( remainingTime: _remainingTime, isButtonEnabled: false)); } }); } void _onStopTimer(StopTimerEvent event, Emitter emit) { _timer?.cancel(); emit(TimerState(isButtonEnabled: true, remainingTime: 0)); } void _onUpdateTimer(UpdateTimerEvent event, Emitter emit) { emit(TimerState( isButtonEnabled: event.isButtonEnabled, remainingTime: event.remainingTime)); } String formattedTime(int time) { final int days = (time / 86400).floor(); // 86400 seconds in a day final int hours = ((time % 86400) / 3600).floor(); final int minutes = (((time % 86400) % 3600) / 60).floor(); final int seconds = (((time % 86400) % 3600) % 60).floor(); final String formattedTime = [ if (days > 0) '${days}d', // Append 'd' for days if (days > 0 || hours > 0) hours .toString() .padLeft(2, '0'), // Show hours if there are days or hours minutes.toString().padLeft(2, '0'), seconds.toString().padLeft(2, '0'), ].join(':'); return formattedTime; } Future verifyCode( VerifyPassCodeEvent event, Emitter emit) async { emit(LoadingForgetState()); try { final response = await AuthenticationAPI.verifyPassCode(body: { 'email': HomeCubit.user!.email!, 'type': 'PASSWORD', 'otpCode': otpCode }); if (response['statusCode'] == 200) { _timer?.cancel(); emit(SuccessForgetState()); } } on DioException catch (e) { final errorData = e.response!.data; String errorMessage = errorData['error']['message'] ?? 'something went wrong'; validate = errorMessage; emit(AuthInitialState()); } } Future changePassword( ChangePasswordEvent event, Emitter emit) async { emit(LoadingForgetState()); try { final response = await AuthenticationAPI.forgetPassword( email: HomeCubit.user!.email!, otpCode: event.otpCode, password: newPassword.text, ); emit(ChangedPassState()); } on DioException catch (e) { final errorData = e.response!.data; String errorMessage = errorData['error']['message'] ?? 'something went wrong'; validate = errorMessage; emit(AuthInitialState()); } } Future onDeleteAccountEvent( DeleteAccountEvent event, Emitter emit) async { try { await AuthenticationAPI.deleteAccount(); emit(ChangedPassState()); } catch (e) { validate = e.toString(); emit(AuthInitialState()); } } }