Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Password reset feature #2432

Merged
merged 13 commits into from
Feb 7, 2025
6 changes: 5 additions & 1 deletion mobile-v3/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'dart:io';

import 'package:airqo/src/app/auth/bloc/ForgotPasswordBloc/forgot_password_bloc.dart';
import 'package:airqo/src/app/auth/bloc/auth_bloc.dart';
import 'package:airqo/src/app/auth/pages/password_reset/forgot_password.dart';
import 'package:airqo/src/app/auth/pages/welcome_screen.dart';
import 'package:airqo/src/app/auth/repository/auth_repository.dart';
import 'package:airqo/src/app/dashboard/bloc/dashboard/dashboard_bloc.dart';
Expand All @@ -16,12 +18,12 @@ import 'package:airqo/src/app/other/places/repository/google_places_repository.d
import 'package:airqo/src/app/other/theme/bloc/theme_bloc.dart';
import 'package:airqo/src/app/other/theme/repository/theme_repository.dart';
import 'package:airqo/src/app/profile/bloc/user_bloc.dart';
import 'package:airqo/src/app/profile/pages/guest_profile%20page.dart';
import 'package:airqo/src/app/profile/repository/user_repository.dart';
import 'package:airqo/src/app/shared/bloc/connectivity_bloc.dart';
import 'package:airqo/src/app/shared/pages/nav_page.dart';

import 'package:airqo/src/meta/utils/colors.dart';

import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
Expand Down Expand Up @@ -117,6 +119,8 @@ class AirqoMobile extends StatelessWidget {
BlocProvider(
create: (context) => ConnectivityBloc(connectivity),
),
BlocProvider(create: (context) => PasswordResetBloc(authRepository: authRepository),
)
],
child: BlocBuilder<ThemeBloc, ThemeState>(
builder: (context, state) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../repository/auth_repository.dart';
import 'forgot_password_event.dart';
import 'forgot_password_state.dart';


class PasswordResetBloc extends Bloc<PasswordResetEvent, PasswordResetState> {
final AuthRepository authRepository;

PasswordResetBloc({required this.authRepository}) : super(PasswordResetInitial()) {
on<RequestPasswordReset>((event, emit) async {
try {
emit(PasswordResetLoading(email: event.email));
await authRepository.requestPasswordReset(event.email);
emit(PasswordResetSuccess(message: '',email: event.email ));
} catch (e) {
emit(PasswordResetError(message: e.toString()));
}
});

on<UpdatePassword>((event, emit) async {
emit(PasswordResetLoading());
try {
final message = await authRepository.updatePassword(
confirmPassword: event.confirmPassword,
password: event.password,
token: event.token,
);
emit(PasswordResetSuccess(message: message));
} catch (error) {
emit(PasswordResetError(message: 'Failed to update password. \nPlease re-check the code you entered'));
}
});

on<VerifyResetCodeEvent>((event, emit) async {
emit(const PasswordResetLoading());

try {

if (RegExp(r'^\d{5}$').hasMatch(event.pin)) { // Replace with actual logic
emit(const PasswordResetVerified(
message: "PIN successfully verified. Proceed to reset password.",
));
} else {
emit(const PasswordResetError(
message: "Invalid PIN. Please try again.",
));
}
} catch (e) {
emit(const PasswordResetError(
message: "Failed to verify PIN.",
));
}
});

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'package:equatable/equatable.dart';

abstract class PasswordResetEvent extends Equatable {
@override
List<Object?> get props => [];
}

class RequestPasswordReset extends PasswordResetEvent {
final String email;

RequestPasswordReset(this.email);

@override
List<Object?> get props => [email];
}

class UpdatePassword extends PasswordResetEvent {
final String confirmPassword;
final String password;
final String token;

UpdatePassword({
required this.confirmPassword,
required this.password,
required this.token,
});

@override
List<Object?> get props => [confirmPassword, password, token];
}
Karagwa marked this conversation as resolved.
Show resolved Hide resolved

class VerifyResetCodeEvent extends PasswordResetEvent {
final String pin;

VerifyResetCodeEvent(this.pin);

@override
List<Object?> get props => [pin];
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import 'package:equatable/equatable.dart';

abstract class PasswordResetState extends Equatable {
final String? email;
const PasswordResetState({this.email});

@override
List<Object?> get props => [email];
}

class PasswordResetInitial extends PasswordResetState {
const PasswordResetInitial() : super();
}

class PasswordResetLoading extends PasswordResetState {
const PasswordResetLoading({String? email}) : super(email: email); // Optional email
}

class PasswordResetSuccess extends PasswordResetState {
final String message;

const PasswordResetSuccess({String? email, required this.message}) : super(email: email);

@override
List<Object?> get props => [email, message];
}

class PasswordResetError extends PasswordResetState {
final String message;

const PasswordResetError({String? email, required this.message})
: super(email: email); // Optional email

@override
List<Object?> get props => [email, message]; // Nullable email
}

class PasswordResetVerified extends PasswordResetState {
final String message;

const PasswordResetVerified({String? email, required this.message}) : super(email: email);

@override
List<Object?> get props => [email, message];
}
24 changes: 20 additions & 4 deletions mobile-v3/lib/src/app/auth/pages/login_page.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:airqo/src/app/auth/bloc/auth_bloc.dart';
import 'package:airqo/src/app/auth/pages/password_reset/forgot_password.dart';
import 'package:airqo/src/app/auth/pages/register_page.dart';
import 'package:airqo/src/app/shared/pages/nav_page.dart';
import 'package:airqo/src/app/shared/widgets/form_field.dart';
Expand Down Expand Up @@ -28,7 +29,7 @@ class _LoginPageState extends State<LoginPage> {
super.initState();
emailController = TextEditingController();
passwordController = TextEditingController();

try {
authBloc = context.read<AuthBloc>();

Expand Down Expand Up @@ -67,7 +68,7 @@ class _LoginPageState extends State<LoginPage> {
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
color: AppColors.boldHeadlineColor),
color: Theme.of(context).textTheme.headlineLarge?.color),
),
centerTitle: true,
),
Expand Down Expand Up @@ -174,20 +175,35 @@ class _LoginPageState extends State<LoginPage> {
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Text("Don't have an account?",
style: TextStyle(
color: AppColors.boldHeadlineColor,
color: Theme.of(context).textTheme.headlineLarge?.color,
fontWeight: FontWeight.w500)),
InkWell(
onTap: () => Navigator.of(context).push(MaterialPageRoute(
builder: (context) => CreateAccountScreen())),
child: Text(
"Create Account",
" Create Account",
style: TextStyle(
fontWeight: FontWeight.w500,
color: AppColors.primaryColor),
),
)
]),
SizedBox(height: 16),

Center(
child: InkWell(
onTap: () => Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ForgotPasswordPage())),
child: Text(
"Forgot password?",
style: TextStyle(
fontWeight: FontWeight.w500,
color: AppColors.primaryColor),
),
),
)
],

),
),
),
Expand Down
Loading
Loading