Ebram Shereen
Ebram Shereen

Reputation: 33

exception in register using local api

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

Answers (0)

Related Questions