Reputation: 33
I worked on an e-commerce app that has register, and I had problem with the register:
problem in registering a customer:
I used a local API, and my code has 3 layers (data layer, logic layer with cubit, and presentation layer).
and then I make a a request to add data to the database, it adds data correctly, but in Flutter code, it gives me an exception, and the exception is "Exception: Failed to post customer data: type 'int' is not a subtype of type 'FutureOr<Map<String, String>>'" and I don't use int in my code ever.
my code :
customer_model.dart:
class CustomerModel {
String? firstName;
String? lastName;
String? handle;
String? phoneNumber;
String? password;
String? gender;
String? address;
CustomerModel({
required this.firstName,
required this.lastName,
required this.handle,
required this.phoneNumber,
required this.password,
required this.gender,
required this.address,
});
factory CustomerModel.fromJson(Map<String, dynamic> json) {
return CustomerModel(
firstName: json['firstName'],
lastName: json['lastName'],
handle: json['handle'],
phoneNumber: json['phoneNumber'],
password: json['password'],
gender: json['gender'],
address: json['address'],
);
}
}
customer_service.dart:
import 'dart:convert';
import 'package:http/http.dart' as http;
class CustomerService {
Future<Map<String, String>> post({
required String url,
required Map<String, String> customerData,
}) async {
try {
final response = await http.post(
Uri.parse(url),
body: jsonEncode(customerData),
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
);
return jsonDecode(response.body);
} catch (e) {
throw Exception('Failed to post customer data: $e');
}
}
}
customer_repository.dart
import 'package:on_budget/src/modules/register/signup/modules/customer/data/models/customer_model.dart';
import 'package:on_budget/src/modules/register/signup/modules/customer/data/service/customer_service.dart';
import 'package:on_budget/src/utils/helper/constants/api.dart';
class CustomerRepository {
final CustomerService addCustomerService;
CustomerRepository(this.addCustomerService);
Future<CustomerModel> addCustomer(
{required Map<String, String> customerData}) async {
final responseData = await addCustomerService.post(
url: RegisterApi.addCustomer,
customerData: customerData,
);
print('resonse of repo $responseData');
return CustomerModel.fromJson(responseData);
}
}
customer_states.dart:
import 'package:http/http.dart';
import 'package:on_budget/src/modules/register/signup/modules/customer/data/models/customer_model.dart';
abstract class CustomerStates {}
class CustomerInitial extends CustomerStates {}
class CustomerWaiting extends CustomerStates {}
class CustomerSuccess extends CustomerStates {
final CustomerModel customerModel;
CustomerSuccess({required this.customerModel});
}
class CustomerFailure extends CustomerStates {
final String error;
CustomerFailure(this.error);
}
customer_cubit.dart:
import 'package:bloc/bloc.dart';
import 'package:on_budget/src/modules/register/signup/modules/customer/data/repository/customer_repository.dart';
import 'package:on_budget/src/modules/register/signup/modules/customer/logic/customer_state.dart';
class CustomerCubit extends Cubit<CustomerStates> {
final CustomerRepository addCustomerRepository;
CustomerCubit(this.addCustomerRepository) : super(CustomerInitial());
Future<void> customerCubit(
{required Map<String, String> customerData}) async {
emit(CustomerWaiting());
try {
final result =
await addCustomerRepository.addCustomer(customerData: customerData);
print('response of cubit $result');
emit(CustomerSuccess(customerModel: result));
} catch (e) {
print('exception of cubit ${e.toString()}');
emit(CustomerFailure(e.toString()));
}
}
}
signup_for_customer.dart:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:on_budget/src/modules/home/presentation/views/home.dart';
import 'package:on_budget/src/modules/register/signup/modules/customer/data/repository/customer_repository.dart';
import 'package:on_budget/src/modules/register/signup/modules/customer/data/service/customer_service.dart';
import 'package:on_budget/src/modules/register/signup/modules/customer/logic/customer_cubit.dart';
import 'package:on_budget/src/modules/register/signup/modules/customer/logic/customer_state.dart';
import 'package:on_budget/src/modules/register/signup/modules/account_created/views/account_created.dart';
import 'package:on_budget/src/modules/register/signup/modules/customer/presentation/widgets/sign_up_form_for_customer.dart';
import 'package:on_budget/src/utils/components/leading_icon.dart';
class SignUpForCustomer extends StatefulWidget {
const SignUpForCustomer({super.key});
static String id = 'SignUpWithEmailForCustomer';
@override
State<SignUpForCustomer> createState() => _SignUpForCustomerState();
}
GlobalKey<FormState> formKey = GlobalKey();
class _SignUpForCustomerState extends State<SignUpForCustomer> {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CustomerCubit(CustomerRepository(CustomerService())),
child: Scaffold(
appBar: AppBar(
title: const Text('Sign Up'),
leading: const LeadingIcon(),
),
body: BlocConsumer<CustomerCubit, CustomerStates>(
listener: (context, state) {
if (state is CustomerWaiting) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Loading...'),
),
);
} else if (state is CustomerSuccess) {
Navigator.pushNamed(context, AccountCreated.id);
} else if (state is CustomerFailure) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.error),
),
);
}
},
builder: (context, state) {
return SignUpFormforCustomer();
},
),
),
);
}
}
gender_choice.dart:
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import '../../../../../../../utils/helper/constants/images.dart';
import '../../../supplier_or_customer/widges/sign_up_choice.dart';
class GenderChoice extends StatefulWidget {
GenderChoice({Key? key}) : super(key: key);
String? gender;
@override
GenderChoiceState createState() => GenderChoiceState();
}
class GenderChoiceState extends State<GenderChoice> {
bool isSelectMan = false;
bool isSelectWoman = false;
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
StoreOrCustomer(
image: kBoyIcon,
tap: () => setState(() {
isSelectMan = true;
isSelectWoman = false;
widget.gender = "man";
}),
isSelect: isSelectMan,
selectedRadius: 50,
selectedRadiusColor: 52,
unSelectedRadius: 50,
),
const Gap(45),
StoreOrCustomer(
image: kGirlIcon,
tap: () => setState(() {
isSelectMan = false;
isSelectWoman = true;
widget.gender = "woman";
}),
isSelect: isSelectWoman,
selectedRadius: 50,
selectedRadiusColor: 52,
unSelectedRadius: 50,
),
],
);
}
}
signup_form_textfield.dart:
import 'package:flutter/material.dart';
import 'package:on_budget/src/modules/register/login/presentation/widgets/forget_password/phone_verification_textfield.dart';
import 'package:on_budget/src/modules/register/signup/modules/customer/presentation/widgets/gender_choice.dart';
import '../../../../../../../utils/components/text_form_field.dart';
import '../../../../../../../utils/helper/functions/regex.dart';
class SignupTextFieldForCustomer extends StatefulWidget {
const SignupTextFieldForCustomer({
super.key,
required this.formKey,
required this.firstNameController,
required this.lastNameController,
// required this.phoneController,
required this.passwordController,
required this.emailController,
// required this.password,
// required this.username,
// required this.firstName,
// required this.lastName,
// required this.phone
});
final GlobalKey<FormState> formKey;
// String? password, username, firstName, lastName, phone;
final TextEditingController firstNameController;
final TextEditingController lastNameController;
// final TextEditingController phoneController;
final TextEditingController passwordController;
final TextEditingController emailController;
@override
State<SignupTextFieldForCustomer> createState() =>
_SignupTextFieldForCustomerState();
}
const bool hide = false;
class _SignupTextFieldForCustomerState
extends State<SignupTextFieldForCustomer> {
@override
Widget build(BuildContext context) {
return Form(
key: widget.formKey,
child: Column(
children: [
Row(
children: [
//first name
TextFormFieldWidget(
controller: widget.firstNameController,
width: 150,
paaddingRight: 0,
paddingLeft: 30,
paddingbottom: 0,
paddingTop: 0,
labelText: 'First Name',
keyboardType: TextInputType.name,
validate: (value) {
if (value!.isNotEmpty) {
if (!value.contains(firstNameRegExp)) {
return 'Please enter a valid first name';
}
} else if (value.isEmpty) {
return 'This field is empty!!!';
}
// widget.firstName = value;
return null;
},
),
//last name
TextFormFieldWidget(
controller: widget.lastNameController,
width: 150,
paddingLeft: 46,
paddingTop: 0,
paddingbottom: 0,
labelText: 'Last Name',
keyboardType: TextInputType.name,
validate: (value) {
if (value!.isNotEmpty) {
if (!value.contains(lastNameRegExp)) {
return 'Please enter a valid last name';
}
} else if (value.isEmpty) {
return 'This field is empty!!!';
}
// widget.lastName = value;
return null;
},
),
],
),
//email
TextFormFieldWidget(
controller: widget.emailController,
paddingbottom: 0,
paddingTop: 0,
labelText: 'Email',
keyboardType: TextInputType.emailAddress,
validate: (value) {
if (value!.isEmpty) {
return 'Email is required';
} else if (value.toLowerCase().isNotEmpty) {
if (!value.contains(emailRegExp)) {
return 'Please enter a valid email address';
}
}
// widget.email = value;
return null;
},
),
// phone number
// PhoneVerificationTextField(
// phoneNumber: '01211212239',
// lengthCheck: true,
// controller: widget.phoneController,
// ),
//password
TextFormFieldWidget(
paddingbottom: 0,
paddingTop: 0,
controller: widget.passwordController,
labelText: 'password',
obscure: hide,
keyboardType: TextInputType.emailAddress,
validate: (value) {
// widget.password = value;
if (value!.isEmpty) {
return 'password is required';
} else if (value.isNotEmpty) {
if (!value.contains(passwordRegExp)) {
return 'Password must be at least contain \n1. One small character \n2. One capital character \n3. One special character \n4. One number';
}
}
// widget.password = value;
return null;
},
),
//confirm password
TextFormFieldWidget(
paddingTop: 0,
paddingbottom: 0,
labelText: 'Confirm password',
keyboardType: TextInputType.emailAddress,
obscure: hide,
validate: (value) {
if (value != widget.passwordController.text || value!.isEmpty) {
return 'Password and Confirm Password must be same';
}
return null;
},
),
],
),
);
}
}
signup_form_field.dart:
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:gap/gap.dart';
import 'package:on_budget/src/modules/register/signup/custom_widgets/signup_alert_dialog.dart';
import 'package:on_budget/src/modules/register/signup/modules/customer/logic/customer_cubit.dart';
import 'package:on_budget/src/modules/register/signup/custom_widgets/already_have_account.dart';
import 'package:on_budget/src/modules/register/signup/custom_widgets/confirm_policy.dart';
import 'package:on_budget/src/modules/register/signup/modules/customer/presentation/widgets/gender_choice.dart';
import 'package:on_budget/src/modules/register/signup/modules/customer/presentation/widgets/signup_textfield_for_customer.dart';
import 'package:on_budget/src/utils/components/button.dart';
import 'package:on_budget/src/utils/helper/constants/colors.dart';
import 'package:on_budget/src/utils/components/background.dart';
class SignUpFormforCustomer extends StatelessWidget {
SignUpFormforCustomer({Key? key}) : super(key: key);
final formKey = GlobalKey<FormState>();
final TextEditingController firstNameController = TextEditingController();
final TextEditingController lastNameController = TextEditingController();
final TextEditingController phoneController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
final TextEditingController emailController = TextEditingController();
// Create a single instance of GenderChoice with a GlobalKey
final GlobalKey<GenderChoiceState> genderChoiceKey =
GlobalKey<GenderChoiceState>();
final GlobalKey<ConfirmPolicyState> confirmPolicykey =
GlobalKey<ConfirmPolicyState>();
bool genderIsSelected = false;
bool isValid = false;
@override
Widget build(BuildContext context) {
return Background(
child: ListView(
physics: const BouncingScrollPhysics(),
children: [
Column(
children: [
const Gap(20),
GenderChoice(key: genderChoiceKey), // Use the key here
const Gap(20),
SignupTextFieldForCustomer(
formKey: formKey,
firstNameController: firstNameController,
lastNameController: lastNameController,
// phoneController: phoneController,
passwordController: passwordController,
emailController: emailController,
),
const Gap(20),
ConfirmPolicy(
key: confirmPolicykey,
),
const Gap(30),
Button(
text: 'Sign Up',
tap: () {
if (formKey.currentState!.validate()) {
formKey.currentState!.save();
isValid = true;
}
if (isValid) {
final cubit = context.read<CustomerCubit>();
final genderState = genderChoiceKey.currentState;
final isGenderSelected = genderState?.widget.gender;
final isConfirmPolicySelected =
confirmPolicykey.currentState?.checkBox ?? false;
if (isGenderSelected == null) {
showDialog(
context: context,
builder: (context) {
return const SignUpAlertDialog(
text: 'Please choose your gender type',
button: 'Okaaay',
);
},
);
} else if (isConfirmPolicySelected == false) {
showDialog(
context: context,
builder: (context) {
return const SignUpAlertDialog(
text: 'Accept to our Terms and Policies',
button: 'Okaaay',
);
},
);
} else if (isGenderSelected == 'man' ||
isGenderSelected == 'woman' ||
isConfirmPolicySelected == true ||
isValid == true) {
log('$isValid');
cubit.customerCubit(customerData: {
"firstName": firstNameController.text,
"lastName": lastNameController.text,
"handle": emailController.text,
"gender": isGenderSelected,
"phoneNumber": '',
"address": '',
"password": passwordController.text
});
}
}
},
width: 220,
colorBtn: kPrimaryColor,
colorTxt: kSecondaryColor,
height: 30,
textSize: 20,
),
const Gap(20),
const AlreadyHaveAccount(),
],
),
],
),
);
}
}
Upvotes: 1
Views: 24