Merge pull request #103 from WDI-Ideas/pooja1

Pooja1
This commit is contained in:
poojapandeyx
2024-07-12 19:45:48 +05:30
committed by GitHub
25 changed files with 261 additions and 78 deletions

View File

@@ -3,4 +3,5 @@ class Globalconst {
static String name = "";
static String phonenumber = "";
static String isdcode = "";
static String createdpin="";
}

View File

@@ -1,5 +1,6 @@
// router.dart
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:tanami_app/core/routes/route_name.dart';
import 'package:tanami_app/features/MainScreens/Academy/presentation/pages/academy_details_screen.dart';
@@ -32,6 +33,8 @@ import 'package:tanami_app/features/welcome/presentation/pages/weclome_screen.da
import 'package:tanami_app/shared/components/no_internet.dart';
import '../../features/MainScreens/main_screen.dart';
import '../../features/countrySelection/bloc/GetCountry/get_country_bloc.dart';
import '../../features/countrySelection/bloc/GetCountry/get_country_event.dart';
import '../../features/forgotPassword/presentation/pages/restore_password_phone_verification_screen.dart';
import '../../features/login/presentation/pages/login_screen.dart';
import '../../features/register/presentation/pages/register_user_details_screen.dart';
@@ -51,6 +54,7 @@ final goRouter = GoRouter(
name: "splash",
path: RouteName.splashScreen,
builder: (context, state) {
context.read<GetCountryBlock>().add(GetCountry());
return const SplashScreen();
},
routes: [

View File

@@ -3,7 +3,7 @@ import 'package:tanami_app/features/countrySelection/bloc/GetCountry/get_country
import '../../../../Api_Helper/base_manager.dart';
import '../../domain/model/get_country_model.dart';
import '../../domain/repositories/get_country_api.dart';
import '../../repositories/get_country_api.dart';
import 'get_country_state.dart';
class GetCountryBlock extends Bloc<GetCountryEvent, GetCountryState> {

View File

@@ -1,7 +1,7 @@
import '../../../../Api_Helper/base_manager.dart';
import '../../../../shared/api/api_endpoints.dart';
import '../../../../shared/api/network_api_services.dart';
import '../../../Api_Helper/base_manager.dart';
import '../../../shared/api/api_endpoints.dart';
import '../../../shared/api/network_api_services.dart';
class GetCountryAPI {
GetCountryAPI();

View File

@@ -0,0 +1,11 @@
import '../../../Api_Helper/base_manager.dart';
import '../../../shared/api/api_endpoints.dart';
import '../../../shared/api/network_api_services.dart';
class LoginAPI {
LoginAPI();
Future<ResponseData> LoginRequest(Map<String, dynamic> data) async {
String url = ApiEndpoints.loginapi;
final response = await NetworkApiService().post(url, data);
return response;
}}

View File

@@ -1,5 +1,7 @@
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:tanami_app/Api_Helper/base_manager.dart';
import 'package:tanami_app/features/login/Repository/LoginAPI.dart';
import 'login_event.dart';
import 'login_state.dart';
@@ -10,7 +12,7 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
TextEditingController();
final TextEditingController phoneNumberTextField = TextEditingController();
final TextEditingController passwordTextField = TextEditingController();
String countryId = "";
GlobalKey<FormState> getFormKey() {
return formKey;
}
@@ -29,16 +31,28 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
emit(LoginLoading());
try {
// Simulate API call
await Future.delayed(const Duration(seconds: 2));
//await Future.delayed(const Duration(seconds: 2));
Map<String, dynamic> logindata = {
"countryId": event.countryId,
"phoneNumber": event.phoneNumber,
"passwordHash": event.password
};
ResponseData response = await LoginAPI().LoginRequest(logindata);
if (response.status == ResponseStatus.SUCCESS) {
emit(LoginSuccess());
} else {
emit(const LoginFailure(
"Login failed. Please check your credentials."));
}
// Replace the next line with actual API call
final isSuccess = await _mockLoginApi(
/* final isSuccess = await _mockLoginApi(
event.phoneNumber, event.password, event.countryResidence);
if (isSuccess) {
emit(LoginSuccess());
} else {
emit(const LoginFailure(
"Login failed. Please check your credentials."));
}
} */
} catch (e) {
emit(LoginFailure(e.toString()));
}

View File

@@ -11,12 +11,10 @@ class LoginSubmitted extends LoginEvent {
final String phoneNumber;
final String password;
final String countryResidence;
final String countryId;
const LoginSubmitted(
this.phoneNumber,
this.password,
this.countryResidence,
);
this.phoneNumber, this.password, this.countryResidence, this.countryId);
@override
List<Object> get props => [phoneNumber, password, countryResidence];

View File

@@ -30,6 +30,7 @@ class BottomSection extends StatelessWidget {
var localizations = AppLocalizations.of(context);
SecureStorageService secureStorageService = SecureStorageService();
final radioBloc = context.read<RadioBloc>();
var loginbloc = context.read<LoginBloc>();
return Column(
children: [
const Gap(12),
@@ -87,17 +88,9 @@ class BottomSection extends StatelessWidget {
: AppColor.inactiveBtnTxtColor,
function: () {
isButtonEnabled
? context.read<LoginBloc>().add(
LoginSubmitted(
context
.read<LoginBloc>()
.phoneNumberTextField
.text,
context
.read<LoginBloc>()
.passwordTextField
.text,
""),
? loginbloc.add(
LoginSubmitted(loginbloc.phoneNumberTextField.text,
loginbloc.passwordTextField.text, "",loginbloc.countryId),
)
: null;
},

View File

@@ -4,9 +4,13 @@ import 'package:gap/gap.dart';
import 'package:tanami_app/core/styles/app_text.dart';
import 'package:tanami_app/core/utils/constant/country_flag_data.dart';
import '../../../../Globalconst.dart';
import '../../../../core/utils/language/localizations_delegate.dart';
import '../../../../shared/api/api_endpoints.dart';
import '../../../../shared/components/bloc/password_field/password_visibility_bloc.dart';
import '../../../../shared/components/form_label_textfield.dart';
import '../../../countrySelection/bloc/GetCountry/get_country_bloc.dart';
import '../../../countrySelection/bloc/GetCountry/get_country_state.dart';
import '../../../countrySelection/bloc/choose_country_bloc.dart';
import '../../../countrySelection/bloc/choose_country_state.dart';
import '../bloc/login_bloc.dart';
@@ -18,6 +22,9 @@ class LoginForm extends StatelessWidget {
Widget build(BuildContext context) {
var localizations = AppLocalizations.of(context);
final loginBloc = context.read<LoginBloc>();
final countrydata = context.read<GetCountryBlock>();
String flag = "";
// Reset fields when the screen is built
loginBloc.resetFields();
@@ -26,9 +33,24 @@ class LoginForm extends StatelessWidget {
int selectedCountry = -1;
if (state is RadioSelectionChanged) {
selectedCountry = state.selectedIndex;
loginBloc.countrySelectionTextField.text = countryName[selectedCountry];
loginBloc.phoneNumberTextField.text =
"${isoCountryCode[selectedCountry]} ";
final countryState = countrydata.state;
if (countryState is CountryLoaded) {
loginBloc.countrySelectionTextField.text = countryState
.countryModel.data![selectedCountry].countryName
.toString();
loginBloc.phoneNumberTextField.text =
"${countryState.countryModel.data![selectedCountry].isdCode}";
loginBloc.countryId="${countryState.countryModel.data![selectedCountry].id}";
flag =
"${ApiEndpoints.base}${countryState.countryModel.data![selectedCountry].flagIcon}";
Globalconst.phonenumber = loginBloc.phoneNumberTextField.text;
Globalconst.name = countryState
.countryModel.data![selectedCountry].countryName
.toString();
Globalconst.isdcode =
"${countryState.countryModel.data![selectedCountry].isdCode}";
}
}
}, builder: (context, state) {
int selectedCountry = -1;

View File

@@ -0,0 +1,18 @@
import '../../../Api_Helper/base_manager.dart';
import '../../../shared/api/api_endpoints.dart';
import '../../../shared/api/network_api_services.dart';
class RegisterAPIService {
RegisterAPIService();
Future<ResponseData> RegisterRequest(Map<String, dynamic> data) async {
String url = ApiEndpoints.registerrequestapi;
final response = await NetworkApiService().post(url, data);
return response;
}
Future<ResponseData> BiometricUpdate(Map<String, dynamic> data) async {
String url = ApiEndpoints.biometricUpdateapi;
final response = await NetworkApiService().post(url, data);
return response;
}
}

View File

@@ -11,7 +11,8 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
final TextEditingController countrySelectionTextField =
TextEditingController();
String isdcode = "";
String isdcode="";
String countryId="";
final TextEditingController phoneNumberTextField = TextEditingController();
GlobalKey<FormState> getFormKey() {
@@ -28,9 +29,9 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
}
emit(RegisterLoading());
try {
Map<String, dynamic> requestdata = {
"isdCode": event.isdcode,
"phoneNumber": event.phoneNumber
Map<String,dynamic> requestdata={
"countryId":event.id,
"phoneNumber":event.phoneNumber
};
ResponseData response = await OTPAPI().requestOTP(requestdata);
if (response.status == ResponseStatus.SUCCESS) {

View File

@@ -11,11 +11,13 @@ class RegisterSubmitted extends RegisterEvent {
final String phoneNumber;
final String countryResidence;
final String isdcode;
final String id;
const RegisterSubmitted(
this.phoneNumber,
this.countryResidence,
this.isdcode
this.isdcode,
this.id
);
@override

View File

@@ -1,5 +1,8 @@
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:tanami_app/Api_Helper/base_manager.dart';
import 'package:tanami_app/Globalconst.dart';
import 'package:tanami_app/features/register/Repository/RegisterApi.dart';
import 'register_user_event.dart';
import 'register_user_state.dart';
@@ -30,10 +33,27 @@ class RegisterUserBloc extends Bloc<RegisterUserEvent, RegisterUserState> {
}
emit(RegisterUserLoading());
try {
Map<String, dynamic> registerdata = {
"token": event.token,
"firstName": event.firstName,
"lastName": event.lastName,
"emailAddress": event.email,
"passwordHash": event.password
};
ResponseData response =
await RegisterAPIService().RegisterRequest(registerdata);
if (response.status == ResponseStatus.SUCCESS) {
var data=response.data["data"];
Globalconst.token=data["token"].toString();
emit(RegisterUserSuccess());
} else {
emit( RegisterUserFailure(
response.message));
}
// Simulate API call
await Future.delayed(const Duration(seconds: 2));
// Replace the next line with actual API call
final isSuccess = await _mockLoginApi(
/* final isSuccess = await _mockLoginApi(
event.firstName,
event.password,
event.lastName,
@@ -45,7 +65,7 @@ class RegisterUserBloc extends Bloc<RegisterUserEvent, RegisterUserState> {
} else {
emit(const RegisterUserFailure(
"Register failed. Please check your credentials."));
}
} */
} catch (e) {
emit(RegisterUserFailure(e.toString()));
}

View File

@@ -13,6 +13,7 @@ class RegisterUserSubmitted extends RegisterUserEvent {
final String email;
final String password;
final String confirmPassword;
final String token;
const RegisterUserSubmitted(
this.firstName,
@@ -20,6 +21,7 @@ class RegisterUserSubmitted extends RegisterUserEvent {
this.lastName,
this.confirmPassword,
this.email,
this.token
);
@override

View File

@@ -82,7 +82,8 @@ class RegisterBottomSection extends StatelessWidget {
RegisterSubmitted(
loginBloc.phoneNumberTextField.text,
loginBloc.countrySelectionTextField.text,
loginBloc.isdcode
loginBloc.isdcode,
loginBloc.countryId
),
)
: null;

View File

@@ -35,8 +35,8 @@ class RegisterForm extends StatelessWidget {
.toString();
loginBloc.phoneNumberTextField.text =
"${countryState.countryModel.data![selectedCountry].isdCode}";
loginBloc.isdcode =
"${countryState.countryModel.data![selectedCountry].isdCode}";
loginBloc.isdcode="${countryState.countryModel.data![selectedCountry].isdCode}";
loginBloc.countryId="${countryState.countryModel.data![selectedCountry].id}";
flag =
"${ApiEndpoints.base}${countryState.countryModel.data![selectedCountry].flagIcon}";
Globalconst.phonenumber = loginBloc.phoneNumberTextField.text;

View File

@@ -8,6 +8,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:gap/gap.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:tanami_app/Globalconst.dart';
import 'package:tanami_app/core/styles/app_images.dart';
import 'package:tanami_app/shared/components/checkbox_widget.dart';
import 'package:tanami_app/shared/components/loader.dart';
@@ -31,6 +32,7 @@ class RegisterUserBottomSection extends StatelessWidget {
@override
Widget build(BuildContext context) {
var localizations = AppLocalizations.of(context);
var registerbloc = context.read<RegisterUserBloc>();
return Column(
children: [
const Gap(40),
@@ -97,7 +99,7 @@ class RegisterUserBottomSection extends StatelessWidget {
Loader.loader(context);
} else if (state is RegisterUserSuccess) {
goRouter.pop();
permissionDialog(context);
permissionDialog(context,);
} else if (state is RegisterUserFailure) {
goRouter.pop();
errorToastMessage(
@@ -128,32 +130,29 @@ class RegisterUserBottomSection extends StatelessWidget {
? AppColor.plainWhite
: AppColor.inactiveBtnTxtColor,
function: () {
isButtonEnabled
? context.read<RegisterUserBloc>().add(
RegisterUserSubmitted(
context
.read<RegisterUserBloc>()
.firstNameTextField
.text,
context
.read<RegisterUserBloc>()
.passwordTextField
.text,
context
.read<RegisterUserBloc>()
.lastNameTextField
.text,
context
.read<RegisterUserBloc>()
.repeatPasswordTextField
.text,
context
.read<RegisterUserBloc>()
.emailTextField
.text,
),
)
: null;
if(isButtonEnabled==true){
if (registerbloc.passwordTextField.text !=
registerbloc.repeatPasswordTextField.text) {
errorToastMessage(
context,
"Password and Repeat Password does not match.",
);
}else{
registerbloc.add(
RegisterUserSubmitted(
registerbloc.firstNameTextField.text,
registerbloc.passwordTextField.text,
registerbloc.lastNameTextField.text,
registerbloc.repeatPasswordTextField.text,
registerbloc.emailTextField.text,
Globalconst.token
),
);
}
}
},
text: localizations.translate(AppText.nextText),
clr: isButtonEnabled

View File

@@ -0,0 +1,17 @@
import '../../../Api_Helper/base_manager.dart';
import '../../../shared/api/api_endpoints.dart';
import '../../../shared/api/network_api_services.dart';
class PinAPIServices {
PinAPIServices();
Future<ResponseData> ConfirmPin(Map<String, dynamic> data) async {
String url = ApiEndpoints.confirmpinapi;
final response = await NetworkApiService().post(url, data);
return response;
}
Future<ResponseData> Verifypin(Map<String, dynamic> data) async {
String url = ApiEndpoints.confirmpinapi;
final response = await NetworkApiService().post(url, data);
return response;
}
}

View File

@@ -1,7 +1,10 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:tanami_app/Api_Helper/base_manager.dart';
import 'package:tanami_app/Globalconst.dart';
import 'package:tanami_app/core/styles/app_text.dart';
import '../../../../core/utils/secure/secure_storage_service.dart';
import '../../Repository/PinAPIServices.dart';
part 'pin_event.dart';
part 'pin_state.dart';
@@ -16,18 +19,48 @@ class PinBloc extends Bloc<PinEvent, PinState> {
isVerified: false,
error: '',
verifiedOnce: false)) {
on<NumberPressed>((event, emit) {
on<NumberPressed>((event, emit) async {
final newPin = state.pin + event.number;
if (newPin.length <= 6) {
emit(state.copyWith(
if (newPin.length == 6) {
if (event.fromscreen == "login") {
Map<String, dynamic> verifypindata = {
"token": Globalconst.token,
"masterPin": newPin
};
ResponseData response =
await PinAPIServices().Verifypin(verifypindata);
if (response.status == ResponseStatus.SUCCESS) {
var data = response.data["user"];
String accesstoken = data["accessToken"];
String refreshtoken = data["refreshToken"];
await secureStorageService.write('accesstoken', accesstoken);
await secureStorageService.write('refreshtoken', refreshtoken);
emit(state.copyWith(
isVerified: false,
error: AppText.incorrectPinCode,
verifiedOnce: true,
));
} else {
emit(state.copyWith(
pin: newPin,
pinComplete: newPin.length == 6,
error: 'has error',
isVerified: false,
verifiedOnce: false));
}
} else {
emit(state.copyWith(
pin: newPin,
pinComplete: newPin.length == 6,
error: '',
verifiedOnce: false));
if (newPin.length == 6) {
add(VerifyPinPressed(newPin));
add(VerifyPinPressed(newPin, event.fromscreen));
}
}
}
});
@@ -49,8 +82,16 @@ class PinBloc extends Bloc<PinEvent, PinState> {
on<VerifyPinPressed>((event, emit) async {
final storedPin = await secureStorageService.read('pin_code');
Map<String, dynamic> pindata = {
"token": Globalconst.token,
"masterPin": event.pin
};
if (storedPin == event.pin) {
ResponseData response = await PinAPIServices().ConfirmPin(pindata);
if (response.status == ResponseStatus.SUCCESS) {
await secureStorageService.write('userMPIN', storedPin.toString());
}
emit(state.copyWith(isVerified: true, error: '', verifiedOnce: true));
} else {
emit(state.copyWith(

View File

@@ -9,8 +9,9 @@ abstract class PinEvent extends Equatable {
class NumberPressed extends PinEvent {
final String number;
final String fromscreen;
const NumberPressed(this.number);
const NumberPressed(this.number,this.fromscreen);
@override
List<Object> get props => [number];
@@ -22,9 +23,9 @@ class SavePinPressed extends PinEvent {}
class VerifyPinPressed extends PinEvent {
final String pin;
const VerifyPinPressed(this.pin);
final String fromscreen;
const VerifyPinPressed(this.pin,this.fromscreen);
@override
List<Object> get props => [pin];
List<Object> get props => [pin,fromscreen];
}

View File

@@ -91,7 +91,7 @@ class ConfirmPinKey extends StatelessWidget {
final number = index == 10 ? '0' : '${index + 1}';
return GestureDetector(
onTap: () {
context.read<PinBloc>().add(NumberPressed(number));
context.read<PinBloc>().add(NumberPressed(number,"confirmpin"));
},
child: Container(
margin: const EdgeInsets.all(12),

View File

@@ -23,6 +23,7 @@ class PinKey extends StatelessWidget {
@override
Widget build(BuildContext context) {
print(fromScreen);
var localizations = AppLocalizations.of(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
@@ -34,10 +35,13 @@ class PinKey extends StatelessWidget {
state.error.isEmpty &&
!state.verifiedOnce) {
if (fromScreen == "login" || fromScreen == "LoginedInUser") {
print("login true");
successToastMessage(context,
localizations.translate(AppText.pinVerifiedSucess));
goRouter.pushNamed(RouteName.mainScreen);
} else if (fromScreen == "reset-pin") {
print("reset true");
log("Running this");
successToastMessage(
context, localizations.translate(AppText.pinUpdatedSucess));
@@ -46,6 +50,13 @@ class PinKey extends StatelessWidget {
context.read<PinBloc>().add(SavePinPressed());
goRouter.pushNamed(RouteName.confirmPinScreen);
}
} else {
if (state.pinComplete) {
errorToastMessage(
context,
state.error,
);
}
}
},
builder: (context, state) {
@@ -124,7 +135,9 @@ class PinKey extends StatelessWidget {
final number = index == 10 ? '0' : '${index + 1}';
return GestureDetector(
onTap: () {
context.read<PinBloc>().add(NumberPressed(number));
context
.read<PinBloc>()
.add(NumberPressed(number, fromScreen));
},
child: Container(
margin: const EdgeInsets.all(12),

View File

@@ -39,7 +39,7 @@ class PinTopSection extends StatelessWidget {
localizations.translate(AppText.welcomeBackText),
clr: AppColor.smokeGrayColor),
TextWidget()
.text14W700(", Jayesh", clr: AppColor.plainBlack),
.text14W700(", Pooja", clr: AppColor.plainBlack),
],
),
TextWidget().text14W500(

View File

@@ -7,4 +7,9 @@ class ApiEndpoints {
static const requestotpapi = "${baseurl}auth/public/register";
static const requestresendotp = "${baseurl}auth/public/resend-otp";
static const verifyotp = "${baseurl}auth/public/verify-otp";
static const registerrequestapi = "${baseurl}auth/public/email-register";
static const biometricUpdateapi = "${baseurl}auth/public/biometric-update";
static const confirmpinapi="${baseurl}auth/public/masterPin";
static const loginapi="${baseurl}auth/public/login";
static const verifypinapi="${baseurl}auth/public/verify-materPin";
}

View File

@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:gap/gap.dart';
import 'package:tanami_app/Api_Helper/base_manager.dart';
import 'package:tanami_app/Globalconst.dart';
import 'package:tanami_app/core/styles/app_color.dart';
import '../../core/routes/route_name.dart';
@@ -8,6 +10,7 @@ import '../../core/routes/routes.dart';
import '../../core/styles/app_text.dart';
import '../../core/utils/language/localizations_delegate.dart';
import '../../core/utils/secure/secure_storage_service.dart';
import '../../features/register/Repository/RegisterApi.dart';
import 'text_widget.dart';
import 'toast_message.dart';
@@ -82,7 +85,15 @@ permissionDialog(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
GestureDetector(
onTap: () {
onTap: () async {
Map<String, dynamic> biometricdata = {
"token": Globalconst.token,
"is_2FA_on": false
};
await RegisterAPIService()
.BiometricUpdate(biometricdata);
successToastMessage(context, "successful !");
goRouter.pop();
@@ -108,7 +119,16 @@ permissionDialog(
),
GestureDetector(
onTap: () async {
await secureStorageService.write("biometric", 'on');
Map<String, dynamic> biometricdata = {
"token": Globalconst.token,
"is_2FA_on": true
};
ResponseData response = await RegisterAPIService()
.BiometricUpdate(biometricdata);
if (response.status == ResponseStatus.SUCCESS) {
await secureStorageService.write("biometric", 'on');
}
successToastMessage(
context, "Biometric/Face Id Enabled Sucessfully !");
// successToastMessage(context, "successful !");