Merge pull request #96 from WDI-Ideas/main

api integration
This commit is contained in:
Jayesh jain
2024-07-11 20:17:49 +05:30
committed by GitHub
44 changed files with 807 additions and 100 deletions

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"dart.flutterSdkPath": "D:\\pooja\\fluttersdk\\flutter_3.22.2\\flutter"
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -0,0 +1,18 @@
class ResponseData<T> {
ResponseData(this.message, this.status, {this.data});
final T? data;
final String message;
final ResponseStatus status;
@override
String toString() => message;
}
enum ResponseStatus {
SUCCESS,
FAILED,
PRIVATE,
}

6
lib/Globalconst.dart Normal file
View File

@@ -0,0 +1,6 @@
class Globalconst {
static String token = "";
static String name = "";
static String phonenumber = "";
static String isdcode = "";
}

View File

@@ -1,7 +1,7 @@
class AppImages {
//Splash
static const String splashBg =
"assets/images/welcome_screen/svg/Splash_BG.svg";
"assets/images/welcome_screen/svg/tanamibg.svg";
static const String splashLogo =
"assets/images/welcome_screen/svg/Tanami_Capital_Splash_Logo.svg";

View File

@@ -27,3 +27,15 @@ List<String> isoCountryCode = [
"+966",
"+971",
];
/* List<String> countryFlag = [
AppImages.bahrainFlag,
// AppImages.kuwaitFlag,
// AppImages.omanFlag,
AppImages.qatarFlag,
AppImages.bahrainFlag,
AppImages.qatarFlag,
// AppImages.saudiArabiaflag,
// AppImages.unitedArabEmiratesFlag,
]; */

View File

@@ -12,8 +12,8 @@ import '../../../../../../core/styles/app_images.dart';
import '../../../../../../core/styles/app_text.dart';
import '../../../../../../core/utils/language/localizations_delegate.dart';
import '../../../../../../shared/components/button_widget.dart';
import '../../../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../../../countrySelection/presentation/bloc/choose_country_state.dart';
import '../../../../../countrySelection/bloc/choose_country_bloc.dart';
import '../../../../../countrySelection/bloc/choose_country_state.dart';
import '../../bloc/payment/invest_payment_bloc.dart';
import '../../bloc/payment/invest_payment_state.dart';

View File

@@ -9,9 +9,9 @@ import 'package:tanami_app/shared/components/text_widget.dart';
import '../../../../../../core/styles/app_color.dart';
import '../../../../../../core/utils/language/localizations_delegate.dart';
import '../../../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../../../countrySelection/presentation/bloc/choose_country_event.dart';
import '../../../../../countrySelection/presentation/bloc/choose_country_state.dart';
import '../../../../../countrySelection/bloc/choose_country_bloc.dart';
import '../../../../../countrySelection/bloc/choose_country_event.dart';
import '../../../../../countrySelection/bloc/choose_country_state.dart';
class InvestPayMethodSection extends StatelessWidget {
const InvestPayMethodSection({super.key});

View File

@@ -10,8 +10,8 @@ import 'package:tanami_app/shared/components/text_widget.dart';
import '../../../../../../core/utils/language/localizations_delegate.dart';
import '../../../../../../core/utils/text_formatter/comma_input_text_formatter.dart';
import '../../../../../../shared/components/text_from_field_widget.dart';
import '../../../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../../../countrySelection/presentation/bloc/choose_country_state.dart';
import '../../../../../countrySelection/bloc/choose_country_bloc.dart';
import '../../../../../countrySelection/bloc/choose_country_state.dart';
import '../../bloc/payment/invest_payment_bloc.dart';
import '../../bloc/payment/invest_payment_event.dart';
import '../../bloc/payment/invest_payment_state.dart';

View File

@@ -14,8 +14,8 @@ import '../../../../../../core/styles/app_images.dart';
import '../../../../../../core/styles/app_text.dart';
import '../../../../../../core/utils/language/localizations_delegate.dart';
import '../../../../../../core/utils/text_formatter/comma_input_text_formatter.dart';
import '../../../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../../../countrySelection/presentation/bloc/choose_country_state.dart';
import '../../../../../countrySelection/bloc/choose_country_bloc.dart';
import '../../../../../countrySelection/bloc/choose_country_state.dart';
import '../../bloc/deposit/deposit_payment_bloc.dart';
import '../../bloc/deposit/deposit_payment_event.dart';
import '../../bloc/deposit/deposit_payment_state.dart';

View File

@@ -8,9 +8,9 @@ import 'package:tanami_app/shared/components/text_widget.dart';
import '../../../../../../core/styles/app_color.dart';
import '../../../../../core/utils/language/localizations_delegate.dart';
import '../../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../../countrySelection/presentation/bloc/choose_country_event.dart';
import '../../../../countrySelection/presentation/bloc/choose_country_state.dart';
import '../../../../countrySelection/bloc/choose_country_bloc.dart';
import '../../../../countrySelection/bloc/choose_country_event.dart';
import '../../../../countrySelection/bloc/choose_country_state.dart';
class DepositPayMethodSection extends StatelessWidget {
const DepositPayMethodSection({super.key});

View File

@@ -0,0 +1,23 @@
import '../../../../Api_Helper/base_manager.dart';
import '../../../../shared/api/api_endpoints.dart';
import '../../../../shared/api/network_api_services.dart';
class OTPAPI {
OTPAPI();
Future<ResponseData> RequestOTP(Map<String, dynamic> data) async {
String url = ApiEndpoints.requestotpapi;
final response = await NetworkApiService().post(url, data);
return response;
}
Future<ResponseData> ResendOTPRequest(Map<String, dynamic> data) async {
String url = ApiEndpoints.requestresendotp;
final response = await NetworkApiService().post(url, data);
return response;
}
Future<ResponseData> VerifyOTP(Map<String, dynamic> data) async {
String url = ApiEndpoints.verifyotp;
final response = await NetworkApiService().post(url, data);
return response;
}
}

View File

@@ -0,0 +1,37 @@
abstract class OTPEvent {
const OTPEvent();
List<Object> get props => [];
}
class RequestOTP extends OTPEvent {
final Map<String, dynamic> OTPRequestData;
RequestOTP(this.OTPRequestData);
@override
List<Object> get props => [OTPRequestData];
}
class VerifyOTP extends OTPEvent {
VerifyOTP();
}
abstract class OTPState{}
class OTPInitial extends OTPState {}
class OTPLoading extends OTPState {}
class OTPLoaded extends OTPState {}
class OTPFailed extends OTPState {
final String failedmessage;
OTPFailed(this.failedmessage);
}
class OTPError extends OTPState {
final String errormessage;
OTPError(this.errormessage);
}

View File

@@ -0,0 +1,48 @@
import 'package:bloc/bloc.dart';
import 'package:tanami_app/features/OTP/bloc/OTPStateEvent.dart';
import '../../../Api_Helper/base_manager.dart';
import '../Repository/OTP_API.dart';
class OTPBloc extends Bloc<OTPEvent, OTPState> {
OTPBloc() : super (OTPInitial()) {
on<RequestOTP>(RequestOTPCall);
// on<VerifyOTP>(VerifyOTPCall);
}
Future<void> RequestOTPCall(RequestOTP event, Emitter<OTPState> emit) async {
if (event is RequestOTP) {
emit(OTPLoading());
final otprequestdata = event.OTPRequestData;
try {
ResponseData response = await OTPAPI().RequestOTP(otprequestdata);
if (response.status == ResponseStatus.SUCCESS) {
emit(OTPLoaded());
} else {
emit(OTPFailed("Oops something went wrong"));
}
print("//");
} catch (e) {
emit(OTPError("Oops something went wrong"));
}
}
}
/* Future<void> VerifyOTPCall(
GetCountry event, Emitter<GetCountryState> emit) async {
if (event is GetCountry) {
emit(CountryLoading());
try {
ResponseData response = await GetCountryAPI().getcountryAPI();
if (response.status == ResponseStatus.SUCCESS) {
GetCountryModel countryModel =
GetCountryModel.fromJson(response.data);
emit(CountryLoaded(countryModel));
}
print("//");
} catch (e) {
emit(CountryError("Oops Something went wrong"));
}
}
} */
}

View File

@@ -0,0 +1,15 @@
import '../../../../Api_Helper/base_manager.dart';
import '../../../../shared/api/api_endpoints.dart';
import '../../../../shared/api/network_api_services.dart';
class GetCountryAPI {
GetCountryAPI();
Future<ResponseData> getcountryAPI() async {
String url=ApiEndpoints.getcountryurl;
final response = await NetworkApiService().get(
url,
);
return response;
}
}

View File

@@ -0,0 +1,30 @@
import 'package:bloc/bloc.dart';
import 'package:tanami_app/features/countrySelection/bloc/GetCountry/getcountryevent_bloc.dart';
import '../../../../Api_Helper/base_manager.dart';
import '../../domain/model/GetCountry_model.dart';
import 'GetCountryAPI.dart';
class GetCountryBlock extends Bloc<GetCountryEvent, GetCountryState> {
GetCountryBlock() : super(CountryInitial()) {
on<GetCountry>(mapEventToState);
}
Future<void> mapEventToState(
GetCountry event, Emitter<GetCountryState> emit) async {
if (event is GetCountry) {
emit(CountryLoading());
try {
ResponseData response = await GetCountryAPI().getcountryAPI();
if (response.status == ResponseStatus.SUCCESS) {
GetCountryModel countryModel =
GetCountryModel.fromJson(response.data);
emit(CountryLoaded(countryModel));
}
print("//");
} catch (e) {
emit(CountryError("Oops Something went wrong"));
}
}
}
}

View File

@@ -0,0 +1,31 @@
import '../../domain/model/GetCountry_model.dart';
abstract class GetCountryEvent {
const GetCountryEvent();
get props => [];
}
class GetCountry extends GetCountryEvent {
GetCountry();
}
abstract class GetCountryState{}
// Define states
//enum GetCountryState { initial, loading, success, failure, error }
class CountryInitial extends GetCountryState {}
class CountryLoading extends GetCountryState {}
class CountryLoaded extends GetCountryState {
final GetCountryModel countryModel;
CountryLoaded(this.countryModel);
}
class CountryError extends GetCountryState {
final String message;
CountryError(this.message);
}

View File

@@ -0,0 +1,72 @@
class GetCountryModel {
List<Data>? data;
GetCountryModel({ this.data});
GetCountryModel.fromJson(Map<String, dynamic> json) {
if (json['data'] != null) {
data = <Data>[];
json['data'].forEach((v) {
data!.add(new Data.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.data != null) {
data['data'] = this.data!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Data {
String? id;
String? countryName;
String? countryCode;
String? isdCode;
String? flagIcon;
Null? currencyXid;
bool? isActive;
Null? createdBy;
Null? modifiedBy;
Data(
{this.id,
this.countryName,
this.countryCode,
this.isdCode,
this.flagIcon,
this.currencyXid,
this.isActive,
this.createdBy,
this.modifiedBy});
Data.fromJson(Map<String, dynamic> json) {
id = json['id'];
countryName = json['countryName'];
countryCode = json['countryCode'];
isdCode = json['isdCode'];
flagIcon = json['flagIcon'];
currencyXid = json['currency_xid'];
isActive = json['isActive'];
createdBy = json['createdBy'];
modifiedBy = json['modifiedBy'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['countryName'] = this.countryName;
data['countryCode'] = this.countryCode;
data['isdCode'] = this.isdCode;
data['flagIcon'] = this.flagIcon;
data['currency_xid'] = this.currencyXid;
data['isActive'] = this.isActive;
data['createdBy'] = this.createdBy;
data['modifiedBy'] = this.modifiedBy;
return data;
}
}

View File

@@ -27,6 +27,7 @@ class ChooseCountryLayout extends StatelessWidget {
child: ButtonWidget().elevatedBtn(
txtClr: AppColor.plainWhite,
function: () {
print("//");
goRouter.pop();
},
text: localizations.translate(AppText.confirmSelectionText),

View File

@@ -1,13 +1,18 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.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/styles/app_color.dart';
import 'package:tanami_app/core/utils/constant/country_flag_data.dart';
import 'package:tanami_app/features/countrySelection/bloc/GetCountry/getcountry_bloc.dart';
import 'package:tanami_app/features/countrySelection/bloc/GetCountry/getcountryevent_bloc.dart';
import 'package:tanami_app/shared/components/text_widget.dart';
import '../bloc/choose_country_bloc.dart';
import '../bloc/choose_country_event.dart';
import '../bloc/choose_country_state.dart';
import '../../../../shared/api/api_endpoints.dart';
import '../../bloc/choose_country_bloc.dart';
import '../../bloc/choose_country_event.dart';
import '../../bloc/choose_country_state.dart';
class CountrySelectionList extends StatelessWidget {
const CountrySelectionList({super.key});
@@ -15,6 +20,7 @@ class CountrySelectionList extends StatelessWidget {
@override
Widget build(BuildContext context) {
final radioBloc = context.read<RadioBloc>();
return BlocBuilder<RadioBloc, RadioState>(
builder: (context, state) {
int selectedIndex = -1;
@@ -22,35 +28,84 @@ class CountrySelectionList extends StatelessWidget {
selectedIndex = state.selectedIndex;
}
return Column(
children: List<Widget>.generate(countryFlag.length, (int index) {
return ListTile(
title: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.asset(
countryFlag[index],
width: 24,
height: 24,
return BlocConsumer<GetCountryBlock, GetCountryState>(
listener: (context, state) {
if (state == CountryLoaded) {
const SnackBar(content: Text("Successfully fetch"));
} else if (state == CountryError) {
const SnackBar(content: Text("error while fetching data"));
Future.delayed(Duration(milliseconds: 3), () {
context.read<GetCountryBlock>().add(GetCountry());
});
} else {
const SnackBar(content: Text(" not fetch"));
}
}, builder: (context, state) {
print(state);
if (state is CountryLoading) {
return Center(child: CircularProgressIndicator());
} else if (state is CountryLoaded) {
return ListView.builder(
itemCount: state.countryModel.data?.length ?? 0,
itemBuilder: (context, index) {
var country = state.countryModel.data![index];
print("${ApiEndpoints.base}${country.flagIcon}");
return ListTile(
title: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 24.h,
width: 24.w,
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(100)),
child: CachedNetworkImage(
maxHeightDiskCache: 200,
maxWidthDiskCache: 200,
cacheKey: country.countryName,
key: UniqueKey(),
imageUrl: "${ApiEndpoints.base}${country.flagIcon}",
height: 24.h,
width: 24.w,
placeholder: (context, url) => Container(
height: 24.h,
width: 24.w,
child: CircularProgressIndicator(),
),
errorWidget: (context, url, error) =>
Icon(Icons.error),
fit: BoxFit.cover),
),
),
/* Image.asset(
countryFlag[index],
width: 24,
height: 24,
), */
const Gap(10),
TextWidget().text14W500(country.countryName.toString(),
clr: AppColor.charcoalColor),
],
),
const Gap(10),
TextWidget().text14W500(countryName[index],
clr: AppColor.charcoalColor),
],
),
leading: Radio<int>(
activeColor: AppColor.radioActiveColor,
value: index,
groupValue: selectedIndex,
onChanged: (int? value) {
if (value != null) {
radioBloc.add(RadioSelected(value));
}
},
),
leading: Radio<int>(
activeColor: AppColor.radioActiveColor,
value: index,
groupValue: selectedIndex,
onChanged: (int? value) {
if (value != null) {
radioBloc.add(RadioSelected(value));
}
},
),
);
},
);
}),
);
} else if (state is CountryError) {
return Center(child: Text(state.message));
} else {
return Center(child: Text('Press button to fetch country data'));
}
});
},
);
}

View File

@@ -12,7 +12,7 @@ import '../../../../core/styles/app_text.dart';
import '../../../../core/utils/language/localizations_delegate.dart';
import '../../../../shared/components/button_widget.dart';
import '../../../../shared/components/text_widget.dart';
import '../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../countrySelection/bloc/choose_country_bloc.dart';
import '../bloc/restore_password_bloc.dart';
import '../bloc/restore_password_event.dart';
import '../bloc/restore_password_state.dart';

View File

@@ -12,7 +12,7 @@ import '../../../../core/styles/app_text.dart';
import '../../../../core/utils/language/localizations_delegate.dart';
import '../../../../shared/components/button_widget.dart';
import '../../../../shared/components/text_widget.dart';
import '../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../countrySelection/bloc/choose_country_bloc.dart';
import '../bloc/restore_password_phone_verification_bloc.dart';
import '../bloc/restore_password_phone_verification_event.dart';
import '../bloc/restore_password_phone_verification_state.dart';

View File

@@ -6,8 +6,8 @@ import 'package:tanami_app/core/utils/constant/country_flag_data.dart';
import '../../../../core/utils/language/localizations_delegate.dart';
import '../../../../shared/components/form_label_textfield.dart';
import '../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../countrySelection/presentation/bloc/choose_country_state.dart';
import '../../../countrySelection/bloc/choose_country_bloc.dart';
import '../../../countrySelection/bloc/choose_country_state.dart';
import '../bloc/restore_password_phone_verification_bloc.dart';
class RestorePasswordPhoneVerificationForm extends StatelessWidget {

View File

@@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../core/styles/app_color.dart';
import '../../../../shared/components/exit_app_dialog.dart';
import '../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../countrySelection/bloc/choose_country_bloc.dart';
import '../bloc/login_bloc.dart';
import 'login_layout.dart';

View File

@@ -13,7 +13,7 @@ import '../../../../core/styles/app_text.dart';
import '../../../../core/utils/language/localizations_delegate.dart';
import '../../../../shared/components/button_widget.dart';
import '../../../../shared/components/text_widget.dart';
import '../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../countrySelection/bloc/choose_country_bloc.dart';
import '../bloc/login_bloc.dart';
import '../bloc/login_event.dart';
import '../bloc/login_state.dart';

View File

@@ -7,8 +7,8 @@ import 'package:tanami_app/core/utils/constant/country_flag_data.dart';
import '../../../../core/utils/language/localizations_delegate.dart';
import '../../../../shared/components/bloc/password_field/password_visibility_bloc.dart';
import '../../../../shared/components/form_label_textfield.dart';
import '../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../countrySelection/presentation/bloc/choose_country_state.dart';
import '../../../countrySelection/bloc/choose_country_bloc.dart';
import '../../../countrySelection/bloc/choose_country_state.dart';
import '../bloc/login_bloc.dart';
class LoginForm extends StatelessWidget {

View File

@@ -2,6 +2,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:sms_autofill/sms_autofill.dart';
import 'package:tanami_app/Api_Helper/base_manager.dart';
import 'package:tanami_app/Globalconst.dart';
import '../../../OTP/Repository/OTP_API.dart';
import 'otp_event.dart';
import 'otp_state.dart';
@@ -28,9 +31,14 @@ class OtpBloc extends Bloc<OtpEvent, OtpState> {
void _onOtpSubmit(OtpSubmit event, Emitter<OtpState> emit) async {
emit(OtpSubmitting());
try {
Map<String,dynamic> otpdata= {
"token":Globalconst.token,
"otp":otpController.text
};
ResponseData response= await OTPAPI().VerifyOTP(otpdata);
// Add your OTP verification logic here
await Future.delayed(const Duration(seconds: 2));
if (otpController.text == "123456") {
// await Future.delayed(const Duration(seconds: 2));
if (response.status==ResponseStatus.SUCCESS) {
emit(OtpSubmissionSuccess());
} else {
emit(const OtpSubmissionFailure("Otp Invalid !"));

View File

@@ -4,12 +4,14 @@ import 'package:tanami_app/features/otpVerification/presentation/bloc/otp_bloc.d
import 'package:tanami_app/features/otpVerification/presentation/pages/otp_layout.dart';
import '../../../../core/styles/app_color.dart';
import '../../../register/presentation/bloc/register_bloc.dart';
import '../bloc/otp_event.dart';
import '../bloc/timer/timer_bloc.dart';
import '../bloc/timer/timer_event.dart';
class OtpScreen extends StatelessWidget {
final String fromScreen;
const OtpScreen({
super.key,
required this.fromScreen,
@@ -20,7 +22,7 @@ class OtpScreen extends StatelessWidget {
return Scaffold(
backgroundColor: AppColor.plainWhite,
resizeToAvoidBottomInset: true,
body: MultiBlocProvider(
body: MultiBlocProvider(
providers: [
BlocProvider(
// Create an instance of the OnboardingBloc
@@ -30,6 +32,11 @@ class OtpScreen extends StatelessWidget {
create: (context) =>
TimerBloc()..add(StartTimer()), // Start the timer here
),
//RegisterBloc
BlocProvider(
create: (context) =>
RegisterBloc(), // Start the timer here
),
],
child: OtpLayout(fromScreen: fromScreen),
),

View File

@@ -1,11 +1,19 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:tanami_app/core/styles/app_color.dart';
import 'package:tanami_app/core/styles/app_text.dart';
import 'package:tanami_app/shared/components/text_widget.dart';
import 'package:tanami_app/shared/components/toast_message.dart';
import '../../../../Globalconst.dart';
import '../../../../core/routes/routes.dart';
import '../../../../core/utils/language/localizations_delegate.dart';
import '../../../../shared/components/loader.dart';
import '../../../register/presentation/bloc/register_bloc.dart';
import '../../../register/presentation/bloc/register_event.dart';
import '../../../register/presentation/bloc/register_state.dart';
import '../bloc/timer/timer_bloc.dart';
import '../bloc/timer/timer_state.dart';
@@ -14,6 +22,11 @@ class ResendOtpSection extends StatelessWidget {
@override
Widget build(BuildContext context) {
String token = "";
var loginBloc = context.read<RegisterBloc>();
loginBloc.isdcode=Globalconst.isdcode;
loginBloc.phoneNumberTextField.text=Globalconst.phonenumber;
loginBloc.countrySelectionTextField.text=Globalconst.name;
var localizations = AppLocalizations.of(context);
return BlocBuilder<TimerBloc, TimerState>(
builder: (context, state) {
@@ -26,16 +39,68 @@ class ResendOtpSection extends StatelessWidget {
state.formattedDuration,
clr: AppColor.plainBlack,
),
GestureDetector(
BlocConsumer<RegisterBloc, RegisterState>(
listener: (context, state) {
print(loginBloc.state);
if (state is RegisterLoading) {
Loader.loader(context);
} else if (state is RegisterSuccess) {
successToastMessage(context, "OTP Resend Sucessfully !");
goRouter.pop();
} else if (state is RegisterFailure) {
goRouter.pop();
errorToastMessage(
context,
state.error,
);
}
},
builder: (context, state) {
bool isButtonEnabled = false;
if (state is RegisterFieldsState) {
isButtonEnabled = state.areFieldsFilled;
} else if (state is RegisterSuccess ||
state is RegisterFailure) {
isButtonEnabled = true;
}
return GestureDetector(
onTap: () {
loginBloc.add(
Resendotp(Globalconst.token),
);
print("///");
// successToastMessage(context, "OTP Resend Sucessfully !");
},
child: TextWidget().text14W500(
localizations.translate(AppText.resendSms),
clr: isButtonEnabled
? AppColor.plainBlack
: AppColor.indicatorInactiveColor,
textDecoration: TextDecoration.underline,
),
);
},
),
/* GestureDetector(
onTap: () {
successToastMessage(context, "OTP Resend Sucessfully !");
regbloc.add(
RegisterSubmitted(
loginBloc.phoneNumberTextField.text,
loginBloc.countrySelectionTextField.text,
loginBloc.isdcode
),
);
print("///");
// successToastMessage(context, "OTP Resend Sucessfully !");
},
child: TextWidget().text14W500(
localizations.translate(AppText.resendSms),
clr: AppColor.plainBlack,
textDecoration: TextDecoration.underline,
),
)
) */
],
),
);

View File

@@ -1,5 +1,8 @@
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import '../../../../Api_Helper/base_manager.dart';
import '../../../../Globalconst.dart';
import '../../../OTP/Repository/OTP_API.dart';
import 'register_event.dart';
import 'register_state.dart';
@@ -7,6 +10,7 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
final TextEditingController countrySelectionTextField =
TextEditingController();
String isdcode="";
final TextEditingController phoneNumberTextField = TextEditingController();
GlobalKey<FormState> getFormKey() {
@@ -15,7 +19,6 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
RegisterBloc() : super(RegisterInitial()) {
phoneNumberTextField.addListener(_onFormFieldChanged);
countrySelectionTextField.addListener(_onFormFieldChanged);
on<RegisterFormChanged>(_onLoginFormChanged);
on<RegisterSubmitted>((event, emit) async {
@@ -24,16 +27,40 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
}
emit(RegisterLoading());
try {
// Simulate API call
await Future.delayed(const Duration(seconds: 2));
// Replace the next line with actual API call
final isSuccess =
await _mockLoginApi(event.phoneNumber, event.countryResidence);
if (isSuccess) {
emit(RegisterSuccess());
Map<String,dynamic> requestdata={
"isdCode":event.isdcode,
"phoneNumber":event.phoneNumber
};
ResponseData response = await OTPAPI().RequestOTP(requestdata);
if (response.status == ResponseStatus.SUCCESS) {
print("///////success");
var data=response.data["data"];
String token=data["token"];
Globalconst.token=token;
emit(RegisterSuccess(token));//emit(OTPLoaded());
} else {
emit(const RegisterFailure(
"Register failed. Please check your credentials."));
//emit(OTPFailed("Oops something went wrong"));
}
} catch (e) {
emit(RegisterFailure(e.toString()));
}
});
on<Resendotp>((event, emit) async {
emit(RegisterLoading());
try {
Map<String,dynamic> requestdata={
"token":Globalconst.token,
};
ResponseData response = await OTPAPI().ResendOTPRequest(requestdata);
if (response.status == ResponseStatus.SUCCESS) {
emit(RegisterSuccess(event.token));//emit(OTPLoaded());
} else {
emit(const RegisterFailure(
"Register failed. Please check your credentials."));
//emit(OTPFailed("Oops something went wrong"));
}
} catch (e) {
emit(RegisterFailure(e.toString()));

View File

@@ -9,18 +9,32 @@ abstract class RegisterEvent extends Equatable {
class RegisterSubmitted extends RegisterEvent {
final String phoneNumber;
final String countryResidence;
final String isdcode;
const RegisterSubmitted(
this.phoneNumber,
this.countryResidence,
this.isdcode
);
@override
List<Object> get props => [phoneNumber, countryResidence];
}
class Resendotp extends RegisterEvent {
final String token;
const Resendotp(
this.token,
);
@override
List<Object> get props => [token];
}
class RegisterFormChanged extends RegisterEvent {
final String phoneNumber;
final String country;

View File

@@ -11,7 +11,14 @@ class RegisterInitial extends RegisterState {}
class RegisterLoading extends RegisterState {}
class RegisterSuccess extends RegisterState {}
class RegisterSuccess extends RegisterState {
final String token;
const RegisterSuccess(this.token);
@override
List<Object> get props => [token];
}
class RegisterFailure extends RegisterState {
final String error;

View File

@@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:tanami_app/features/register/presentation/bloc/register_bloc.dart';
import '../../../../core/styles/app_color.dart';
import '../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../countrySelection/bloc/choose_country_bloc.dart';
import 'register_layout.dart';
class RegisterScreen extends StatelessWidget {

View File

@@ -7,13 +7,14 @@ import 'package:tanami_app/core/styles/app_images.dart';
import 'package:tanami_app/shared/components/loader.dart';
import 'package:tanami_app/shared/components/toast_message.dart';
import '../../../../Globalconst.dart';
import '../../../../core/routes/route_name.dart';
import '../../../../core/routes/routes.dart';
import '../../../../core/styles/app_color.dart';
import '../../../../core/styles/app_text.dart';
import '../../../../core/utils/language/localizations_delegate.dart';
import '../../../../shared/components/button_widget.dart';
import '../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../countrySelection/bloc/choose_country_bloc.dart';
import '../bloc/register_bloc.dart';
import '../bloc/register_event.dart';
import '../bloc/register_state.dart';
@@ -25,6 +26,8 @@ class RegisterBottomSection extends StatelessWidget {
Widget build(BuildContext context) {
var localizations = AppLocalizations.of(context);
final radioBloc = context.read<RadioBloc>();
final loginBloc = context.read<RegisterBloc>();
return Column(
children: [
const Gap(90),
@@ -34,8 +37,9 @@ class RegisterBottomSection extends StatelessWidget {
height: 12,
),
const Gap(36),
BlocConsumer<RegisterBloc, RegisterState>(
BlocConsumer<RegisterBloc, RegisterState>(
listener: (context, state) {
print(loginBloc.state);
if (state is RegisterLoading) {
Loader.loader(context);
} else if (state is RegisterSuccess) {
@@ -44,6 +48,7 @@ class RegisterBottomSection extends StatelessWidget {
goRouter.pushNamed(RouteName.otpScreen,
pathParameters: {"fromScreen": "register"});
} else if (state is RegisterFailure) {
goRouter.pop();
errorToastMessage(
@@ -70,14 +75,15 @@ class RegisterBottomSection extends StatelessWidget {
? AppColor.plainWhite
: AppColor.inactiveBtnTxtColor,
function: () {
Globalconst.phonenumber=loginBloc.phoneNumberTextField.text;
isButtonEnabled
? context.read<RegisterBloc>().add(
RegisterSubmitted(
context
.read<RegisterBloc>()
.phoneNumberTextField
.text,
""),
loginBloc.phoneNumberTextField.text,
loginBloc.countrySelectionTextField.text,
loginBloc.isdcode
),
)
: null;
},

View File

@@ -1,13 +1,18 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.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/styles/app_text.dart';
import 'package:tanami_app/core/utils/constant/country_flag_data.dart';
import 'package:tanami_app/features/countrySelection/bloc/GetCountry/getcountryevent_bloc.dart';
import '../../../../Globalconst.dart';
import '../../../../core/utils/language/localizations_delegate.dart';
import '../../../../shared/api/api_endpoints.dart';
import '../../../../shared/components/form_label_textfield.dart';
import '../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../countrySelection/presentation/bloc/choose_country_state.dart';
import '../../../countrySelection/bloc/GetCountry/getcountry_bloc.dart';
import '../../../countrySelection/bloc/choose_country_bloc.dart';
import '../../../countrySelection/bloc/choose_country_state.dart';
import '../bloc/register_bloc.dart';
class RegisterForm extends StatelessWidget {
@@ -17,13 +22,29 @@ class RegisterForm extends StatelessWidget {
Widget build(BuildContext context) {
var localizations = AppLocalizations.of(context);
final loginBloc = context.read<RegisterBloc>();
final countrydata = context.read<GetCountryBlock>();
int selectedCountry = -1;
String flag = "";
return BlocConsumer<RadioBloc, RadioState>(listener: (context, state) {
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.isdcode="${countryState.countryModel.data![selectedCountry].isdCode}";
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) {
if (state is RadioSelectionChanged) {
@@ -46,11 +67,46 @@ class RegisterForm extends StatelessWidget {
FormLabelTextField(
prefixWidget: selectedCountry == -1
? null
: Image.asset(
: Padding(
padding: EdgeInsets.only(left: 12.w),
child: SizedBox(
height: 50.h,
width: 30.w,
child: Align(
alignment: Alignment.centerLeft,
child: SizedBox(
height: 30.h,
width: 30.w,
child: ClipRRect(
borderRadius:
BorderRadius.all(Radius.circular(100)),
child: CachedNetworkImage(
maxHeightDiskCache: 200,
maxWidthDiskCache: 200,
cacheKey: loginBloc
.countrySelectionTextField.text,
key: UniqueKey(),
imageUrl: flag,
height: 30.h,
width: 30.w,
placeholder: (context, url) => Container(
height: 30.h,
width: 30.w,
child: CircularProgressIndicator(),
),
errorWidget: (context, url, error) =>
Icon(Icons.error),
fit: BoxFit.cover),
),
),
),
),
),
/* Image.asset(
countryFlag[selectedCountry],
width: 20,
height: 20,
),
), */
hintText: localizations.translate(AppText.chooseCountry),
title: localizations.translate(AppText.countryOfResidence),
type: "country selection",
@@ -58,13 +114,47 @@ class RegisterForm extends StatelessWidget {
),
const Gap(20),
FormLabelTextField(
prefixWidget: selectedCountry == -1
prefixWidget: selectedCountry == -1 ||flag.isEmpty
? null
: Image.asset(
: Padding(
padding: EdgeInsets.only(left: 12.w),
child: SizedBox(
height: 50.h,
width: 30.w,
child: Align(
alignment: Alignment.centerLeft,
child: SizedBox(
height: 30.h,
width: 30.w,
child: ClipRRect(
borderRadius:
BorderRadius.all(Radius.circular(100)),
child: CachedNetworkImage(
maxHeightDiskCache: 200,
maxWidthDiskCache: 200,
cacheKey: loginBloc
.countrySelectionTextField.text,
key: UniqueKey(),
imageUrl: flag,
height: 30.h,
width: 30.w,
placeholder: (context, url) => Container(
height: 30.h,
width: 30.w,
child: CircularProgressIndicator(),
),
errorWidget: (context, url, error) =>
Icon(Icons.error),
fit: BoxFit.cover),
),
),
),
),
),/* Image.asset(
countryFlag[selectedCountry],
width: 20,
height: 20,
),
), */
hintText: "+0 (000) 000 00 00",
title: localizations.translate(AppText.phoneNumber),
type: "phone number",

View File

@@ -25,7 +25,7 @@ class SplashLayout extends StatelessWidget {
fit: BoxFit.cover,
),
),
Positioned.fill(
/* Positioned.fill(
child: Align(
alignment: Alignment.center,
child: SvgPicture.asset(
@@ -39,7 +39,7 @@ class SplashLayout extends StatelessWidget {
alignment: Alignment.bottomCenter,
child: BottomVersionWidget(),
),
),
), */
],
),
),

View File

@@ -1,9 +1,12 @@
import 'package:flutter/material.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/route_name.dart';
import 'package:tanami_app/core/routes/routes.dart';
import 'package:tanami_app/core/styles/app_color.dart';
import 'package:tanami_app/features/countrySelection/bloc/GetCountry/getcountry_bloc.dart';
import 'package:tanami_app/features/countrySelection/bloc/GetCountry/getcountryevent_bloc.dart';
import 'package:tanami_app/shared/components/button_widget.dart';
import '../../../../core/styles/app_text.dart';
@@ -28,6 +31,7 @@ class LoginSignUpButton extends StatelessWidget {
height: 56.h,
child: ButtonWidget().elevatedBtn(
function: () {
context.read<GetCountryBlock>().add(GetCountry());
goRouter.goNamed(RouteName.registerStepScreen, pathParameters: {
"fromScreentype": "welcome",
});

View File

@@ -9,9 +9,16 @@ import 'core/routes/routes.dart';
import 'core/utils/connectivity/network_connectivity.dart';
import 'core/utils/language/localizations_delegate.dart';
import 'core/utils/secure/secure_storage_service.dart';
import 'features/OTP/bloc/OTP_bloc.dart';
import 'features/biometric/presentation/bloc/biometric_bloc.dart';
import 'features/biometric/presentation/bloc/biometric_event.dart';
import 'features/countrySelection/presentation/bloc/choose_country_bloc.dart';
import 'features/countrySelection/bloc/GetCountry/getcountry_bloc.dart';
import 'features/countrySelection/bloc/choose_country_bloc.dart';
import 'features/otpVerification/presentation/bloc/otp_bloc.dart';
import 'features/otpVerification/presentation/bloc/otp_event.dart';
import 'features/otpVerification/presentation/bloc/timer/timer_bloc.dart';
import 'features/otpVerification/presentation/bloc/timer/timer_event.dart';
import 'features/register/presentation/bloc/register_bloc.dart';
import 'shared/components/bloc/bottom_nav_bar/bottom_navigation_bloc.dart';
import 'shared/components/bloc/language/lng_bloc.dart';
import 'shared/components/bloc/language/lng_event.dart';
@@ -98,6 +105,16 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
create: (_) =>
BiometricBloc(LocalAuthentication())..add(CheckBiometricEvent()),
),
BlocProvider(
create: (_) => LocalizationBloc(),
),
BlocProvider(
create: (_) => GetCountryBlock(),
),
BlocProvider(
create: (_) => OTPBloc(),
),
],
child: ScreenUtilInit(
builder: (BuildContext context, Widget? child) =>

View File

@@ -1,3 +1,10 @@
class ApiEndpoints {
static const base = ""; //App Base url
static const base="https://tanami.betadelivery.com/";
static const baseurl =
"https://tanami.betadelivery.com/api/development/v1/"; //App Base url
static const getcountryurl = baseurl + "country/getAllCountry";
static const requestotpapi=baseurl +"auth/public/register";
static const requestresendotp=baseurl+"auth/public/resend-otp";
static const verifyotp=baseurl+"auth/public/verify-otp";
}

View File

View File

@@ -1,42 +1,82 @@
// common_api.dart
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import '../../Api_Helper/base_manager.dart';
class NetworkApiService {
final Dio _dio = Dio();
// Common function for GET requests
Future<Response> get(String endpoint,
Future<ResponseData> get(String url,
{Map<String, dynamic>? queryParameters}) async {
if (kDebugMode) {
print("api url is >>> $url");
}
Response response;
try {
return await _dio.get(endpoint, queryParameters: queryParameters);
response = await _dio.get(url);
if (response.statusCode == 201 || response.statusCode == 200) {
return ResponseData<dynamic>("success", ResponseStatus.SUCCESS,
data: response.data);
} else {
try {
return ResponseData<dynamic>(
response.data['message'].toString(), ResponseStatus.FAILED);
} catch (_) {
return ResponseData<dynamic>(
data: response.data,
response.statusMessage!,
ResponseStatus.FAILED);
}}
} catch (e) {
throw _handleError(e);
return ResponseData<dynamic>(
"Something went wrong", ResponseStatus.FAILED);
}
}
// Common function for POST requests
Future<Response> post(String endpoint, dynamic data) async {
Future<ResponseData> post(String url, dynamic data) async {
if (kDebugMode) {
print("data >>> $data");
print("api url is >>> $url");
}
try {
return await _dio.post(endpoint, data: data);
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 {
try {
return ResponseData<dynamic>(
response.data['message'].toString(), ResponseStatus.FAILED);
} catch (_) {
return ResponseData<dynamic>(
data: response.data,
response.statusMessage!,
ResponseStatus.FAILED);
}}
} catch (e) {
throw _handleError(e);
return ResponseData<dynamic>(
"Oops something went wrong",
ResponseStatus.FAILED);
}
}
// Common function for PUT requests
Future<Response> put(String endpoint, dynamic data) async {
Future<Response> put(String url, dynamic data) async {
try {
return await _dio.put(endpoint, data: data);
return await _dio.put(url, data: data);
} catch (e) {
throw _handleError(e);
}
}
// Common function for DELETE requests
Future<Response> delete(String endpoint) async {
Future<Response> delete(String url) async {
try {
return await _dio.delete(endpoint);
return await _dio.delete(url);
} catch (e) {
throw _handleError(e);
}