Implemented home creation and add counter to the sign up screen

This commit is contained in:
Abdullah Alassaf
2024-06-03 00:26:07 +03:00
parent 9877dde78e
commit 6a9c2967d2
12 changed files with 577 additions and 13 deletions
+10 -4
View File
@@ -9,7 +9,6 @@ import 'package:syncrow_app/features/auth/model/user_model.dart';
import 'package:syncrow_app/navigation/navigation_service.dart';
import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/services/api/authentication_api.dart';
part 'auth_state.dart';
class AuthCubit extends Cubit<AuthState> {
@@ -202,15 +201,22 @@ class AuthCubit extends Cubit<AuthState> {
sendOtp() async {
try {
final response =
await AuthenticationAPI.sendOtp(body: {'email': email, 'type': 'VERIFICATION'});
// otpCode = response['otp'];
await AuthenticationAPI.sendOtp(body: {'email': email, 'type': 'VERIFICATION'});
emit(AuthSignUpSuccess());
} catch (_) {
emit(AuthLoginError(message: 'Something went wrong'));
}
}
reSendOtp() async {
try {
await AuthenticationAPI.sendOtp(body: {'email': email, 'type': 'VERIFICATION'});
emit(ResendOtpSuccess());
} catch (_) {
emit(AuthLoginError(message: 'Something went wrong'));
}
}
verifyOtp() async {
emit(AuthLoginLoading());
try {
+2
View File
@@ -24,6 +24,8 @@ class AuthOtpSuccess extends AuthSuccess {}
class AuthSignUpSuccess extends AuthSuccess {}
class ResendOtpSuccess extends AuthSuccess {}
class AuthLoginError extends AuthError {
AuthLoginError({required super.message, super.code});
}
+109 -4
View File
@@ -1,3 +1,4 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@@ -9,12 +10,106 @@ import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.da
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/helpers/life_cycle_event_handler.dart';
import 'package:syncrow_app/utils/helpers/shared_preferences_helper.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class OtpView extends StatelessWidget {
class OtpView extends StatefulWidget {
const OtpView({super.key});
@override
State<OtpView> createState() => _OtpViewState();
}
class _OtpViewState extends State<OtpView> {
bool timerCanceled = false;
Timer? countdownTimer;
Duration myDuration = const Duration();
late LifecycleEventHandler _lifecycleEventHandler;
String otpCode = '';
int? remainingSec = 30;
@override
void initState() {
super.initState();
bool timerStarted = false;
_lifecycleEventHandler = LifecycleEventHandler(
resumeCallBack: () async {
SharedPreferencesHelper.saveBoolToSP('timeStampSaved', false);
String timeStampInBackground = await SharedPreferencesHelper.readStringFromSP('timeStamp');
int savedCounter = await SharedPreferencesHelper.readIntFromSP('savedCounter');
DateTime currentTime = DateTime.now();
int differenceInSeconds = timeStampInBackground.isNotEmpty
? currentTime.difference(DateTime.parse(timeStampInBackground)).inSeconds
: 0;
remainingSec = differenceInSeconds > savedCounter ? 0 : savedCounter - differenceInSeconds;
timerStarted = true;
startTimer(remainingSec ?? 0);
return;
},
suspendingCallBack: () async {
handleTimerOnBackground();
},
onPauseCallBack: () async {
handleTimerOnBackground();
},
inactiveCallBack: () async {
handleTimerOnBackground();
},
);
WidgetsBinding.instance.addObserver(_lifecycleEventHandler);
if (!timerStarted) {
timerStarted = false;
startTimer(remainingSec ?? 0);
}
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(_lifecycleEventHandler);
super.dispose();
}
handleTimerOnBackground() async {
bool timeStampSaved = await SharedPreferencesHelper.readBoolFromSP('timeStampSaved') ?? false;
if (!timeStampSaved) {
final dateInString = DateTime.now().toString();
SharedPreferencesHelper.saveIntToSP('savedCounter', remainingSec ?? 0);
SharedPreferencesHelper.saveStringToSP('timeStamp', dateInString);
SharedPreferencesHelper.saveBoolToSP('timeStampSaved', true);
}
}
void startTimer(int sec) {
timerCanceled = false;
if (countdownTimer != null) {
countdownTimer!.cancel();
countdownTimer = null;
}
myDuration = Duration(seconds: sec);
int seconds = sec;
countdownTimer = Timer.periodic(const Duration(seconds: 1), (values) {
seconds = seconds - 1;
remainingSec = seconds;
if (mounted) {
if (seconds < 0) {
setState(() {
countdownTimer!.cancel();
timerCanceled = true;
WidgetsBinding.instance.removeObserver(_lifecycleEventHandler);
});
} else {
setState(() {
myDuration = Duration(seconds: remainingSec ?? seconds);
});
}
}
});
}
@override
Widget build(BuildContext context) {
String maskedEmail = AuthCubit.get(context).maskEmail(AuthCubit.get(context).email);
@@ -23,6 +118,9 @@ class OtpView extends StatelessWidget {
if (state is AuthOtpSuccess) {
Navigator.pushNamedAndRemoveUntil(context, Routes.homeRoute, (value) => false);
}
if (state is ResendOtpSuccess) {
startTimer(30);
}
},
builder: (context, state) {
return Scaffold(
@@ -215,10 +313,18 @@ class OtpView extends StatelessWidget {
Colors.white,
),
),
child: const Text(
'Resend',
child: Text(
timerCanceled
? 'Resend'
: myDuration.inSeconds
.remainder(60)
.toString()
.padLeft(2, '0'),
),
onPressed: () async {
if (!timerCanceled) {
return;
}
if ((state is! AuthLoading)) {
await AuthCubit.get(context).sendOtp();
FocusScope.of(context).unfocus();
@@ -241,6 +347,5 @@ class OtpView extends StatelessWidget {
);
},
);
;
}
}
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/utils/context_extension.dart';
class ForgetPassword extends StatelessWidget {
@@ -14,7 +15,7 @@ class ForgetPassword extends StatelessWidget {
const Spacer(),
TextButton(
onPressed: () {
//TODO Navigate to forgot password
Navigator.popAndPushNamed(context, Routes.otpRoute);
},
child: BodyMedium(
text: "Forgot Password?",