api integration

This commit is contained in:
jayesh
2024-07-17 19:12:26 +05:30
parent 1e47dd914a
commit fab01aa29a
54 changed files with 1022 additions and 356 deletions

View File

@@ -3,13 +3,28 @@ class ApiEndpoints {
static const baseurl =
"https://tanami.betadelivery.com/api/development/v1/"; //App Base url
//Country
static const getcountryurl = "${baseurl}country/getAllCountry";
//Register
static const requestotpapi = "${baseurl}auth/public/register";
static const registerrequestapi = "${baseurl}auth/public/email-register";
//OTP
static const requestresendotp = "${baseurl}auth/public/resend-otp";
static const verifyotp = "${baseurl}auth/public/verify-otp";
static const registerrequestapi = "${baseurl}auth/public/email-register";
//Biometric
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";
//PIN
static const confirmpinapi = "${baseurl}auth/public/masterPin";
static const verifypinapi = "${baseurl}auth/public/verify-materPin";
//Login
static const loginapi = "${baseurl}auth/public/login";
//Forgot Password
static const forgotPasswordApi = "${baseurl}auth/public/forgot-password";
static const resetPasswordApi = "${baseurl}auth/public/reset-password";
}

View File

@@ -6,17 +6,22 @@ import 'package:flutter/foundation.dart';
import '../../Api_Helper/base_manager.dart';
class NetworkApiService {
final Dio _dio = Dio();
final Dio _dio = Dio(BaseOptions(
validateStatus: (status) {
return status != null &&
status < 500; // Allow any status code less than 500
},
));
// Common function for GET requests
Future<ResponseData> get(String url,
{Map<String, dynamic>? queryParameters}) async {
if (kDebugMode) {
if (kDebugMode) {
print("api url is >>> $url");
}
Response response;
try {
response = await _dio.get(url);
response = await _dio.get(url);
if (response.statusCode == 201 || response.statusCode == 200) {
return ResponseData<dynamic>("success", ResponseStatus.SUCCESS,
data: response.data);
@@ -29,10 +34,11 @@ class NetworkApiService {
data: response.data,
response.statusMessage!,
ResponseStatus.FAILED);
}}
}
}
} catch (e) {
return ResponseData<dynamic>(
"Something went wrong", ResponseStatus.FAILED);
"Something went wrong", ResponseStatus.FAILED);
}
}
@@ -43,24 +49,48 @@ class NetworkApiService {
print("api url is >>> $url");
}
try {
var response= await _dio.post(url, data: data);
if (response.statusCode == 201 || response.statusCode == 200) {
return ResponseData<dynamic>("success", ResponseStatus.SUCCESS,
var response = await _dio.post(
url,
data: data,
);
if (response.statusCode == 201 || response.statusCode == 200) {
return ResponseData<dynamic>("success", ResponseStatus.SUCCESS,
data: response.data);
}else {
} else if (response.statusCode == 400) {
if (response.data['message'] == "Master Pin is not created") {
return ResponseData<dynamic>(
response.data['message'], ResponseStatus.PRIVATE,
data: response.data);
} else if (response.data['error']['message'] ==
"MASTER PIN NOT MATCH") {
return ResponseData<dynamic>(
response.data['error']['message'], ResponseStatus.PRIVATE,
data: response.data);
} else if (response.data['error']['message'] ==
"Account already exists. Please Login instead.") {
return ResponseData<dynamic>(
response.data['error']['message'], ResponseStatus.PRIVATE,
data: response.data);
} else {
return ResponseData<dynamic>(
response.data['error']['message'], ResponseStatus.PRIVATE,
data: response.data);
}
} else {
try {
return ResponseData<dynamic>(
response.data['message'].toString(), ResponseStatus.FAILED);
response.data['error']['message'].toString(),
ResponseStatus.FAILED);
} catch (_) {
return ResponseData<dynamic>(
data: response.data,
response.statusMessage!,
ResponseStatus.FAILED);
}}
}
}
} catch (e) {
return ResponseData<dynamic>(
"Oops something went wrong",
ResponseStatus.FAILED);
"Oops something went wrong", ResponseStatus.FAILED);
}
}

View File

@@ -3,13 +3,15 @@ import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:gap/gap.dart';
import 'package:tanami_app/core/routes/routes.dart';
import 'package:tanami_app/core/styles/app_color.dart';
import 'package:tanami_app/core/styles/app_text.dart';
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
import 'package:tanami_app/features/biometric/presentation/bloc/biometric_bloc.dart';
import '../../Globalconst.dart';
import '../../core/routes/route_name.dart';
import '../../core/routes/routes.dart';
import '../../core/utils/language/localizations_delegate.dart';
import '../../features/biometric/presentation/bloc/biometric_event.dart';
import '../../features/biometric/presentation/bloc/biometric_state.dart';
import 'text_widget.dart';
@@ -17,6 +19,7 @@ deviceLockedDialog(
context,
) {
var localizations = AppLocalizations.of(context);
final SecureStorageService secureStorageService = SecureStorageService();
return showDialog(
barrierDismissible: false,
context: context,
@@ -106,11 +109,19 @@ deviceLockedDialog(
),
Gap(15.w),
GestureDetector(
onTap: () {
goRouter.pop();
context
.read<BiometricBloc>()
.add(AuthenticateBiometricEvent());
onTap: () async {
// goRouter.pop();
// context
// .read<BiometricBloc>()
// .add(AuthenticateBiometricEvent());
Globalconst.firstName =
await secureStorageService.read("first_name") ??
"";
goRouter
.goNamed(RouteName.pinScreen, pathParameters: {
"fromScreen": "LoginedInUser",
});
},
child: Container(
height: 48.h,

View File

@@ -1,14 +1,18 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:gap/gap.dart';
import 'package:tanami_app/core/styles/app_color.dart';
import 'package:tanami_app/core/styles/app_text.dart';
import 'package:tanami_app/features/login/presentation/bloc/login_bloc.dart';
import 'package:tanami_app/shared/components/password_text_form_field.dart';
import 'package:tanami_app/shared/components/text_widget.dart';
import '../../core/routes/route_name.dart';
import '../../core/routes/routes.dart';
import '../../core/utils/language/localizations_delegate.dart';
import '../../features/forgotPassword/presentation/bloc/restore_password_phone_verification_bloc.dart';
import '../../features/register/presentation/bloc/register_bloc.dart';
import 'text_from_field_widget.dart';
class FormLabelTextField extends StatelessWidget {
@@ -20,6 +24,7 @@ class FormLabelTextField extends StatelessWidget {
required this.hintText,
this.prefixWidget,
this.onChangeFun,
this.originalPasswordController,
});
final String title;
final String type;
@@ -27,9 +32,23 @@ class FormLabelTextField extends StatelessWidget {
final TextEditingController textEditingController;
final Widget? prefixWidget;
final Function(String)? onChangeFun;
final TextEditingController? originalPasswordController;
@override
Widget build(BuildContext context) {
// Map of country codes to phone number lengths
final Map<String, int> countryPhoneLengths = {
"+973": 8, // Bahrain
"+965": 8, // Kuwait
"+968": 8, // Oman
"+974": 8, // Qatar
"+966": 9, // Saudi Arabia
"+971": 9, // United Arab Emirates
};
var registerBloc = context.read<RegisterBloc>();
var loginBloc = context.read<LoginBloc>();
var restorePasswordBloc =
context.read<RestorePasswordPhoneVerificationBloc>();
var localizations = AppLocalizations.of(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -40,10 +59,11 @@ class FormLabelTextField extends StatelessWidget {
txtAlign: type == "description" ? TextAlign.start : TextAlign.center,
),
const Gap(10),
type == "password"
(type == "password" || type == "repeat-password")
? PasswordField(
controller: textEditingController,
hintText: hintText,
originalPasswordController: originalPasswordController,
)
: textFormField(
onInput: onChangeFun,
@@ -52,6 +72,47 @@ class FormLabelTextField extends StatelessWidget {
if (value != null && value.isEmpty) {
return localizations.translate(AppText.enterPhoneNo);
}
if (registerBloc.isdcode.isNotEmpty) {
// Validate phone number length based on selected country
if (countryPhoneLengths.containsKey(
registerBloc.isdcode,
)) {
final expectedLength =
countryPhoneLengths[registerBloc.isdcode];
if (value.length != expectedLength) {
return localizations.translate(
"Invalid Phone Number",
);
}
}
} else if (loginBloc.isdcode.isNotEmpty) {
// Validate phone number length based on selected country
if (countryPhoneLengths.containsKey(
loginBloc.isdcode,
)) {
final expectedLength =
countryPhoneLengths[loginBloc.isdcode];
if (value.length != expectedLength) {
return localizations.translate(
"Invalid Phone Number",
);
}
}
} else if (restorePasswordBloc.isdcode.isNotEmpty) {
// Validate phone number length based on selected country
if (countryPhoneLengths.containsKey(
restorePasswordBloc.isdcode,
)) {
final expectedLength =
countryPhoneLengths[restorePasswordBloc.isdcode];
if (value.length != expectedLength) {
return localizations.translate(
"Invalid Phone Number",
);
}
}
}
return null;
} else if (type == "country selection") {
if (textEditingController.text.isEmpty) {
@@ -64,13 +125,38 @@ class FormLabelTextField extends StatelessWidget {
.translate(AppText.pleaseEnteraDescription);
}
return null;
} else if (type == "email") {
if (value == null || value.isEmpty) {
return 'Please enter an email address.';
}
// Email validation
if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) {
return 'Please enter a valid email address.';
}
return null;
} else {
return null;
}
},
inputFormatters: [
LengthLimitingTextInputFormatter(350),
],
inputFormatters: (type == "phone number")
? registerBloc.isdcode.isNotEmpty
? [
LengthLimitingTextInputFormatter(
countryPhoneLengths[registerBloc.isdcode]),
]
: restorePasswordBloc.isdcode.isNotEmpty
? [
LengthLimitingTextInputFormatter(
countryPhoneLengths[
restorePasswordBloc.isdcode]),
]
: [
LengthLimitingTextInputFormatter(
countryPhoneLengths[loginBloc.isdcode]),
]
: [
LengthLimitingTextInputFormatter(350),
],
maxlines: type == "description" ? 6 : 1,
texttype: type == "phone number"
? TextInputType.phone

View File

@@ -0,0 +1,85 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:gap/gap.dart';
import 'package:tanami_app/core/routes/routes.dart';
import 'package:tanami_app/core/styles/app_color.dart';
import 'package:tanami_app/shared/components/text_widget.dart';
void showLanguageBottomSheet(BuildContext context) {
showModalBottomSheet(
backgroundColor: Colors.transparent,
context: context,
builder: (BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 1.sw,
height: 168.7.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.black87),
child: Column(
children: [
const Gap(10),
Center(
child: TextWidget()
.text17W700("Language", clr: Colors.white60),
),
const Gap(10),
const Divider(
color: AppColor.plainWhite,
),
const Gap(10),
InkWell(
onTap: () {
goRouter.pop();
},
child: Center(
child:
TextWidget().text15W700("English", clr: Colors.white),
),
),
const Gap(10),
const Divider(
color: AppColor.plainWhite,
),
const Gap(10),
InkWell(
onTap: () {
goRouter.pop();
},
child: Center(
child: TextWidget().text15W700("عربي", clr: Colors.white),
),
),
const Gap(20),
],
),
),
const Gap(18),
GestureDetector(
onTap: () {
goRouter.pop();
},
child: Container(
width: 1.sw,
height: 56.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.black87),
child: Center(
child:
TextWidget().text14W500("Dismiss", clr: Colors.white60),
),
),
),
const Gap(18),
],
),
);
},
);
}

View File

@@ -89,6 +89,9 @@ buildprofilelogoutdialog(context) {
onTap: () async {
context.read<BottomNavigationBloc>().add(TabChanged(2));
await secureStorageService.write('isLoginedIn', "false");
await secureStorageService.write('accesstoken', '');
await secureStorageService.write('refreshtoken', '');
goRouter.goNamed(RouteName.loginScreen, pathParameters: {
"fromScreen": "registerStep",
});

View File

@@ -1,5 +1,6 @@
import 'package:control_style/control_style.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -15,8 +16,13 @@ import 'bloc/password_field/password_visibility_state.dart';
class PasswordField extends StatelessWidget {
final TextEditingController controller;
final String hintText;
const PasswordField(
{super.key, required this.controller, required this.hintText});
final TextEditingController? originalPasswordController;
const PasswordField({
super.key,
required this.controller,
required this.hintText,
this.originalPasswordController,
});
@override
Widget build(BuildContext context) {
@@ -25,9 +31,31 @@ class PasswordField extends StatelessWidget {
builder: (context, state) {
return TextFormField(
validator: (value) {
if (value != null && value.isEmpty) {
if (value == null || value.isEmpty) {
return localizations.translate(AppText.enterPassword);
}
// Password validation rules
if (value.length < 8 || value.length > 20) {
return localizations.translate(AppText.passwordLength);
}
if (!RegExp(r'[a-z]').hasMatch(value)) {
return localizations.translate(AppText.passwordLowerCase);
}
if (!RegExp(r'[A-Z]').hasMatch(value)) {
return localizations.translate(AppText.passwordUpperCase);
}
if (!RegExp(r'\d').hasMatch(value)) {
return localizations.translate(AppText.passwordDigit);
}
if (!RegExp(r'[!@#$%&*()\-+=^]').hasMatch(value)) {
return localizations.translate(AppText.passwordSpecialCharacter);
}
if (originalPasswordController != null &&
value != originalPasswordController!.text) {
return localizations.translate("Passwords do not match");
}
return null;
},
controller: controller,
@@ -38,7 +66,12 @@ class PasswordField extends StatelessWidget {
fontSize: 14,
fontWeight: FontWeight.w500,
),
inputFormatters: [
LengthLimitingTextInputFormatter(20),
FilteringTextInputFormatter.deny(RegExp(r'\s')),
],
decoration: InputDecoration(
errorMaxLines: 2,
errorStyle: GoogleFonts.dmSans(
color: AppColor.txtErrorColor,
fontSize: 14,

View File

@@ -2,7 +2,6 @@ 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';
@@ -85,16 +84,7 @@ permissionDialog(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
GestureDetector(
onTap: () async {
Map<String, dynamic> biometricdata = {
"token": Globalconst.token,
"is_2FA_on": false
};
await RegisterAPIService()
.BiometricUpdate(biometricdata);
successToastMessage(context, "successful !");
onTap: () {
goRouter.pop();
goRouter.goNamed(RouteName.pinScreen, pathParameters: {
@@ -120,7 +110,8 @@ permissionDialog(
GestureDetector(
onTap: () async {
Map<String, dynamic> biometricdata = {
"token": Globalconst.token,
"token":
await secureStorageService.read("temp_token"),
"is_2FA_on": true
};