не могу создать контакт и отобразить список контактов с помощью mobx в флаттере - PullRequest
0 голосов
/ 14 января 2020

Я создал модели для данных из конечной точки API и использовал управление состоянием mobx для проекта. Чтобы создать контакт, у меня возникла ошибка, которая не позволяет мне успешно создать новый контакт.

class NewContact extends StatefulWidget {
  NewContact({Key key}) : super(key: key);

  @override
  _NewContactState createState() {
    return _NewContactState();
  }
}

class _NewContactState extends State<NewContact> {
  bool visibility = false;
  ErrorPage _errorPage;

  ContactStore contactStore;

  @override
  void initState() {
    super.initState();
    _errorPage = ErrorPage();
  }

  @override
  void dispose() {
    contactStore.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final data = MediaQuery.of(context);
    return Scaffold(
      appBar: AppBar(
        automaticallyImplyLeading: true,
        iconTheme: IconThemeData(color: Colors.black),
        backgroundColor: Colors.white,
        elevation: 0.0,
        title: Text(
          'New Contact',
          style: TextStyle(
              fontSize: 20,
              fontWeight: FontWeight.w500,
              color: Color.fromRGBO(35, 36, 44, 1)),
        ),
      ),
        body: Provider(
          create: (context) => ContactStore(),
          dispose: (context, verifyStore) => verifyStore.dispose(),
          child: Consumer<ContactStore>(
            builder: (context, contactStore, _) {
              if (contactStore.isNotInitialized) {
                contactStore.initialize(context);
              }
              return Container(
                height: data.size.height,
                width: data.size.width,
                margin: EdgeInsets.symmetric(horizontal: 22),
                child: LayoutBuilder(
                  builder: (BuildContext context, BoxConstraints constraints) {
                    return SingleChildScrollView(
                      child: Column(
                        children: <Widget>[
                          Container(
                            // height: data.size.height / 2,
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: <Widget>[
                                SizedBox(
                                  height: MediaQuery.of(context).size.height * 0.08,
                                ),
                                Text(
                                  "Step 1/2",
                                  style: TextStyle(
                                      color: Colors.black,
                                      //color: Color.fromRGBO(255, 255, 255, 1),
                                      fontSize: 14.0,
                                      fontWeight: FontWeight.w500),
                                ),
                                SizedBox(
                                  height: MediaQuery.of(context).size.height * 0.02,
                                ),
                                Text(
                                  "Personal Details",
                                  style: TextStyle(
                                    //color: Colors.black,
                                      color: Color.fromRGBO(35, 36, 44, 1),
                                      fontSize: 20.0,
                                      fontWeight: FontWeight.w500),
                                ),
                                SizedBox(
                                  height: MediaQuery.of(context).size.height * 0.06,
                                ),
                                Container(
                                  height: 60,
                                  width: MediaQuery.of(context).size.width,
                                  child: Stack(
                                    children: <Widget>[
                                      Text(
                                        "Full Name",
                                        style: TextStyle(
                                            color: Colors.black,
                                            //color: Color.fromRGBO(128, 132, 162, 1),
                                            fontSize: 14.0,
                                            fontWeight: FontWeight.w500),
                                      ),
                                      Padding(
                                        padding: const EdgeInsets.only(top: 16.0),
                                        child: Observer(
                                          name: 'description',
                                          builder: (_) => TextFormField(
                                            controller: contactStore.contactNameController,
                                            keyboardType: TextInputType.text,
                                            decoration: InputDecoration(
                                                errorText: contactStore
                                                    .contactFormErrorStore.description,
                                                hintText: "Aliyu Shamsuddeen"),
                                          ),
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                                SizedBox(
                                  height: MediaQuery.of(context).size.height * 0.03,
                                ),
                                Container(
                                  height: 60,
                                  width: MediaQuery.of(context).size.width,
                                  child: Stack(
                                    children: <Widget>[
                                      Text(
                                        "Email Address",
                                        style: TextStyle(
                                            color: Colors.black,
                                            //color: Color.fromRGBO(128, 132, 162, 1),
                                            fontSize: 14.0,
                                            fontWeight: FontWeight.w500),
                                      ),
                                      Padding(
                                        padding: const EdgeInsets.only(top: 16.0),
                                        child: Observer(
                                          name: 'contactEmail',
                                          builder: (_) => TextFormField(
                                            controller: contactStore.emailController,
                                            keyboardType: TextInputType.emailAddress,
                                            decoration: InputDecoration(
                                                errorText: contactStore
                                                    .contactFormErrorStore.contactEmail,
                                                hintText: "email@example.com"),
                                          ),
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                                SizedBox(
                                  height: MediaQuery.of(context).size.height * 0.03,
                                ),
                                Container(
                                  height: 60,
                                  width: MediaQuery.of(context).size.width,
                                  child: Stack(
                                    children: <Widget>[
                                      Text(
                                        "Mobile Number",
                                        style: TextStyle(
                                            color: Colors.black,
                                            //color: Color.fromRGBO(128, 132, 162, 1),
                                            fontSize: 14.0,
                                            fontWeight: FontWeight.w500),
                                      ),
                                      Padding(
                                        padding: const EdgeInsets.only(top: 16.0),
                                        child: Observer(
                                          name: 'contactPhone',
                                          builder: (_) => TextFormField(
                                            controller: contactStore.numberController,
                                            keyboardType: TextInputType.number,
                                            decoration: InputDecoration(
                                                errorText: contactStore
                                                    .contactFormErrorStore.contactPhone,
                                                hintText: "0803123456789"),
                                          ),
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                                SizedBox(
                                  height: MediaQuery.of(context).size.height * 0.03,
                                ),
                                Container(
                                  height: 60,
                                  width: MediaQuery.of(context).size.width,
                                  child: Stack(
                                    children: <Widget>[
                                      Text(
                                        "Address",
                                        style: TextStyle(
                                            color: Colors.black,
                                            //color: Color.fromRGBO(128, 132, 162, 1),
                                            fontSize: 14.0,
                                            fontWeight: FontWeight.w500),
                                      ),
                                      Padding(
                                        padding: const EdgeInsets.only(top: 16.0),
                                        child: Observer(
                                          name: 'contactAddress',
                                          builder: (_) => TextFormField(
                                            controller: contactStore.contactAddressController ,
                                            keyboardType: TextInputType.text,
                                            decoration: InputDecoration(
                                                errorText: contactStore
                                                    .contactFormErrorStore.contactAddress,
                                                hintText:
                                                "No.2 Galadimawa Estate Minna."),
                                          ),
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                                SizedBox(
                                  height: MediaQuery.of(context).size.height * 0.06,
                                ),
                                Container(
                                  height: 48.0,
                                  width: MediaQuery.of(context).size.width,
                                  decoration: BoxDecoration(
                                      borderRadius: BorderRadius.circular(16.0)),
                                  child: RaisedButton(
                                    elevation: 0.0,
                                    color: Color.fromRGBO(68, 74, 213, 1),
                                    onPressed: () {
//                                  Navigator.of(context)
//                                      .popAndPushNamed('/contactDetails');

                                      contactStore.saveContact();
                                    },
                                    child: Row(
                                      mainAxisAlignment: MainAxisAlignment.center,
                                      children: <Widget>[
                                        new Text(
                                          'Continue',
                                          style: new TextStyle(
                                              color:
                                              Color.fromRGBO(235, 234, 250, 1),
                                              fontSize: 14.0,
                                              fontWeight: FontWeight.w500),
                                        ),
                                        Padding(
                                          padding: const EdgeInsets.only(left: 8.0),
                                          child: Icon(
                                            Icons.arrow_forward,
                                            color: Colors.white,
                                            size: 16.0,
                                          ),
                                        ),
                                      ],
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                    );
                  },
                ),
              );
            },
          ),
        ));
  }
}

Это содержимое хранилища для модуля контактов для создания и отображения уже созданных контактов в качестве организации или как физическое лицо.

part 'contact_store.g.dart';

class ContactStore = _ContactStore with _$ContactStore;

// The store-class
abstract class _ContactStore with Store {
  final Validation _validate = new Validation();
  final ErrorStore errorStore = new ErrorStore();
  final ContactFormErrorStore contactFormErrorStore =
      new ContactFormErrorStore();

  List bankList = [
    'Access Bank',
    'Citibank',
    'Diamond Bank',
    'Ecobank Nigeria',
    'Fidelity Bank Nigeria',
    'First Bank of Nigeria',
    'First City Monument Bank',
    'Guaranty Trust Bank',
    'Heritage Bank Plc',
    'Jaiz Bank',
    'Keystone Bank Limited',
    'Providus Bank Plc',
    'Polaris Bank',
    'Stanbic IBTC Bank Nigeria Limited',
    'Standard Chartered Bank',
    'Sterling Bank',
    'SunTrust Bank Nigeria Limited',
    'Union Bank of Nigeria',
    'United Bank for Africa',
    'Unity Bank Plc',
    'Wema Bank',
    'Zenith Bank'
  ];

  List<DropdownMenuItem<String>> dropDownMenuItems;

  List<DropdownMenuItem<String>> getDropDownMenuItems() {
    List<DropdownMenuItem<String>> items = new List();
    for (String user in bankList) {
      items.add(new DropdownMenuItem(value: user, child: new Text(user)));
    }
    return items;
  }

  GlobalStore globalStore;
  List<ReactionDisposer> _disposers;
  List<Contact> contactListData;
  int id;

  final contactNameController = TextEditingController();
  final emailController = TextEditingController();
  final numberController = TextEditingController();
  final contactAddressController = TextEditingController();
  final accountNumberController = TextEditingController();
  final accountNameController = TextEditingController();
  final bankBranchController = TextEditingController();
  final contactPersonController = TextEditingController();

  @observable
  bool visibility = false;

  @observable
  int categoryId;

  @observable
  var getContactListState = Status.none;

  @observable
  bool isFiltering = false;

  @observable
  String searchText = '';

  @observable
  ObservableFuture getContactListCheck = ObservableFuture.value(null);

  @computed
  bool get isGetContactListPending =>
      getContactListCheck.status == FutureStatus.pending;

  var apiCallState = Status.none;

  @observable
  BuildContext context;

  @observable
  String description = '';

  @observable
  String contactEmail = '';

  @observable
  String contactPhone = '';

  @observable
  String contactAddress = '';

  @observable
  String accountName = '';

  @observable
  String accountNo = '';

  @observable
  String bankAddress = '';

  @observable
  String bankCode = '';

  @observable
  String currentBankType;



  @observable
  List<BankItem> bankItemList;

//  @observable
//  String contactPerson = '';

  @action
  void changedDropDownItem(String selectedBankType) {
    currentBankType = selectedBankType;
  }

  @computed
  bool get isNotInitialized => context == null;

  @computed
  bool get canNavigate => apiCallState != Status.failed;

  @computed
  bool get canCreateContact =>
      !contactFormErrorStore.hasError &&
      description.isNotEmpty &&
      contactEmail.isNotEmpty &&
      contactPhone.isNotEmpty &&
      contactAddress.isNotEmpty &&
      accountName.isNotEmpty &&
      accountNo.isNotEmpty &&
      bankAddress.isNotEmpty &&
      bankCode.isNotEmpty;

  @action
  void setContext(BuildContext val) {
    context = val;
  }

  @action
  void setVariables(BuildContext context) {
    globalStore = Provider.of<GlobalStore>(context);
  }

  @action
  void setName(String value) {
    description = value;
  }

  @action
  void setEmail(String value) {
    contactEmail = value;
  }

  @action
  void setNumber(String value) {
    contactPhone = value;
  }

  @action
  void setAddress(String value) {
    contactAddress = value;
  }

  @action
  void setAcctName(String value) {
    accountName = value;
  }

  @action
  void setAcctNumber(String value) {
    accountNo = value;
  }

  @action
  void setBankAddress(String value) {
    bankAddress = value;
  }

  @action
  void setBankCode(String value) {
    bankCode = value;
  }

  @action
  void setCurrentBankType() {
    currentBankType = dropDownMenuItems[0].value;
  }

  @action
  void validateFields() {
    String result;
    bool result1;
    result = _validate.validateFullName(description);
    contactFormErrorStore.description = result;
    result = _validate.validateEmail(contactEmail);
    contactFormErrorStore.contactEmail = result;
    result1 = _validate.isValidPhoneNumber(contactPhone);
    contactFormErrorStore.contactPhone = result1 as String;
    result = _validate.validateContactAddress(contactAddress);
    contactFormErrorStore.contactAddress = result;
    result = _validate.validateAccountName(accountName);
    contactFormErrorStore.accountName = result;
    result1 = _validate.validateAccountNumber(accountNo);
    contactFormErrorStore.accountNo = result1 as String;
    contactFormErrorStore.bankAddress = result;
    result = _validate.validateBankAddress(bankAddress);
  }

  void saveContact() async {
    validateFields();
    List<Map> contactBanksList = List<Map>();
    // List<Map> bankItems = List<Map>();
    for (BankItem bankItem in bankItemList) {
      contactBanksList.add(bankItem.toJson());
    }
    if (canCreateContact) {
      apiCallState = Status.none;
      ShowProgressIndicatorDialog(context: context);
      //await checkEmailExist();
      if (canNavigate && canCreateContact) {
        try {
          AddContact result = await ContactDataSource().addContact(
            requestPayload: AddContactRequest(

                    //category
                    description: description,
                    contactAddress: contactAddress,
                    contactPhone: contactPhone,
                    contactEmail: contactEmail,
                    contactBanksList: contactBanksList
                    //category: category,
                    )
                .toJson(),
          );
          Navigator.of(context).pop();

          if (result.message == SUCCESS) {
            Navigator.of(context).pushNamed(
              '/contactDetails',
            );
          } else {
            ShowFlushBar(context: context, message: OPERATION_UNSUCESSFUL);
          }
        } on CustomException catch (e) {
          Navigator.of(context).pop();
          errorStore.errorMessage = e.msg;
          ShowFlushBar(context: context, message: errorStore.errorMessage);
        }
      }

//      else {
//        Navigator.of(context).pop();
//        if (apiCallState == Status.failed) {
//          ShowFlushBar(context: context, message: errorStore.errorMessage);
//        }
//      }

    }
  }

  void setListeners() {
    contactNameController.addListener(() {
      setName(contactNameController.text);
    });
    emailController.addListener(() {
      setEmail(emailController.text);
    });
    numberController.addListener(() {
      setNumber(numberController.text);
    });
    contactAddressController.addListener(() {
      setAddress(contactAddressController.text);
    });
    accountNumberController.addListener(() {
      setAcctNumber(accountNumberController.text);
    });
    accountNameController.addListener(() {
      setAcctName(accountNameController.text);
    });
    bankBranchController.addListener(() {
      setBankAddress(bankBranchController.text);
    });

    contactPersonController.addListener(() {
      setBankCode(contactPersonController.text);
    });
  }

  @action
  Future getContacts() async {
    getContactListState = Status.loading;
    try {
      List<Contact> result = await ContactDataSource().contactList(
          userId: globalStore.loginData.userID,
          basicAuth: globalStore.basicAuth);
      if (searchText == "") {
        contactListData = result;
      } else {
        List<Contact> newContactListData = List<Contact>();
        for (Contact contact in result) {
          if (contact.description
                  .toLowerCase()
                  .contains(searchText.toLowerCase()) ||
              contact.contactEmail
                  .toLowerCase()
                  .contains(searchText.toLowerCase())) {
            newContactListData.add(contact);
          }
        }
        contactListData = newContactListData;
      }

      getContactListState = Status.none;
    } on CustomException catch (e) {
      getContactListState = Status.failed;
      errorStore.errorMessage = e.msg;
    }
  }

  @action
  Future getContactList(String searchText) async {
    getContactListCheck = ObservableFuture(getContacts());
  }

  @action
  Future deleteContact(int index) async {
    ShowProgressIndicatorDialog(context: context);
    try {
      DeleteContact result = await ContactDataSource().deleteContact(
          id: contactListData[index].id, basicAuth: globalStore.basicAuth);
      Navigator.of(context).pop();
      if (result.message == SUCCESS) {
        await getContactList("");
        ShowToast(
          msg: ITEM_DELETED,
          backgroundColor: main,
        );
      } else {
        Navigator.of(context).pop();
        ShowFlushBar(context: context, message: DELETE_ERROR_MSG);
      }
    } on CustomException catch (e) {
      Navigator.of(context).pop();
      errorStore.errorMessage = e.msg;
      ShowFlushBar(context: context, message: errorStore.errorMessage);
    }
  }

  @override
  void dispose() {
    for (final d in _disposers) {
      d();
    }
  }

  void initialize(BuildContext val) {
    _disposers = [
      reaction((_) => context, setVariables),
      reaction((_) => searchText, getContactList)
    ];
    setContext(val);
    getContactList("");
  }
}

class ContactFormErrorStore = _ContactFormErrorStore
    with _$ContactFormErrorStore;

abstract class _ContactFormErrorStore with Store {
  @observable
  String description = '';

  @observable
  String contactEmail = '';

  @observable
  String contactPhone = '';

  @observable
  String contactAddress = '';

  @observable
  String accountName = '';

  @observable
  String accountNo = '';

  @observable
  String bankAddress = '';

  @observable
  String bankCode = '';

  @computed
  bool get hasError =>
      description != null ||
      contactEmail != null ||
      contactPhone != null ||
      contactAddress != null ||
      accountName != null ||
      accountNo != null ||
      bankAddress != null ||
      bankCode != null;
}
...