#100DaysOfCodeChallenge -Crop Management Information System- Day 1
Tags: flutter, dart, firebase
Published: 2021-06-24 05:52:00

## Introduction

Check out the [#100DaysOfCodeChallenge - Crop Management Information System](https://dev.to/curtlycritchlow/100daysofcodechallenge-crop-management-information-system-22mo) for additional context to this blog. For day one of the challenge I created a `FarmerServiceModel` that will act a the Farmer firebase document equivalent. In the future this class will be used used with the `FirebaseFirestore.instance.collection('farmers').withConverter<FarmerServiceModel>` to maintain type safety.

## Breakdown of FarmerServiceModel Class

### Properties

```Dart
  late String id;
  late String registrationNumber;
  late final String? nationalId;
  late final String? profilePicture;
  late final String? firstName;
  late final String lastName;
  late final String? nickname;
  late final DateTime? dateOfBirth;
  late final String gender;
  late final String ethnicity;
  late final String maritalStatus;
  late final String address;
  late final bool isHeadOfHousehold;
  late final bool isFarmingPrimaryIncomeSource;
  late final bool isActiveFarmer;
  late final String farmerCategory;
  late final String subsector;
  late final String operationScale;
  late List<String>? farm;
```

These properties store all the data that will be stored in the farmer document of cloud firestore farmers collection.

### From Json Constructor
```Dart
  FarmerServiceModel.fromJson(Map<String, Object?> json)
      : this(
          id: json['id']! as String,
          registrationNumber: json['registrationNumber'] as String,
          nationalId: json['nationalId'] as String,
          profilePicture: json['profilePicture'] as String,
          firstName: json['firstName'] as String,
          lastName: json['lastName'] as String,
          nickname: json['nickname'] as String,
          dateOfBirth: json['dateOfBirth'] as DateTime,
          gender: json['gender'] as String,
          ethnicity: json['ethnicity'] as String,
          maritalStatus: json['maritalStatus'] as String,
          address: json['address'] as String,
          isHeadOfHousehold: json['isHeadOfHousehold'] as bool,
          isActiveFarmer: json['isActiveFarmer'] as bool,
          isFarmingPrimaryIncomeSource:
              json['isFarmingPrimaryIncomeScore'] as bool,
          farmerCategory: json['farmerCategory'] as String,
          subsector: json['subsector'] as String,
          operationScale: json['operationScale'] as String,
          farm: json['farm'] as List<String>,
        );
```
This constructor will be used to convert the Farmer documents in cloud firestore to the `FarmerServiceModel` Class.

### To Json Method
```Dart
Map<String, Object?> toJson() {
    return {
      'id': id,
      'registrationNumber': registrationNumber,
      'nationalId': nationalId,
      'profileProfile': profilePicture,
      'firstName': firstName,
      'lastName': lastName,
      'nickname': nickname,
      'dateOfBirth': dateOfBirth,
      'gender': gender,
      'ethnicity': ethnicity,
      'maritalStatus': maritalStatus,
      'address': address,
      'isHeadOfHousehold': isHeadOfHousehold,
      'isActiveFarmeer': isActiveFarmer,
      'isFarmingPrimaryIncomeSource': isFarmingPrimaryIncomeSource,
      'farmerCategory': farmerCategory,
      'subsector': subsector,
      'operationScale': operationScale,
      'farm': farm,
    };
  }
```

The ToJson method will convert the `FarmerServiceModel` class to a `Map<String, Object?>` the `Map<String, Object?>` is the required format for cloud firestore documents.

### Validation Methods

```Dart
// VALIDATION METHODS

  String? validateRegistrationNumber(String? value) {
    return null;
  }

  String? handleNationalIdValidation(String? value) {
    return null;
  }

  String? validateProfilePicture(String? value) {
    return null;
  }

  String? handleFirstNameValidation(String? value) {
    return null;
  }

  String? handleLastNameValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else {
      return null;
    }
  }

  String? handleNicknameValidation(String? value) {
    return null;
  }

  String? handleDateOfBirthValidation(String? value) {
    return null;
  }

  String? handleGenderValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }

  String? handleEthnicityValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }

  String? handleMaritalStatusValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }

  String? handleAddressValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }

  String? handleFarmerCategoryValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }

  String? handleSubsectorValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }

  String? handleOperationScaleValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }
```

These methods will be used on the validator property of form related widgets like the `TextFormField` widget.

```Dart
  // SAVE METHODS
  void saveRegistrationNumber(String? value) => registrationNumber = value!;
  void handleNationalIdSaved(String? value) => nationalId = value!;
  void saveProfilePicture(String? value) => profilePicture = value!;
  void handleFirstNameSaved(String? value) => firstName = value!;
  void handleLastNameSaved(String? value) => lastName = value!;
  void handleNicknameSaved(String? value) => nickname = value!;
  void handleDateOfBirthSaved(DateTime? value) => dateOfBirth = dateOfBirth;
  void handleGenderSaved(String? value) => gender = value!;
  void handleEthnicitySaved(String? value) => ethnicity = value!;
  void handleMaritalStatusSaved(String? value) => maritalStatus = value!;
  void handleAddressSaved(String? value) => address = value!;
  void handleIsHeadOfHouseholdChange(bool? value) => isHeadOfHousehold = value!;
  void handleFarmerCategorySaved(String? value) => farmerCategory = value!;
  void handleSubsectorSaved(String? value) => subsector = value!;
  void handleIsFarmingPrimaryIncomeSourceChange(bool? value) =>
      isFarmingPrimaryIncomeSource = value!;
  void handleOperationScaleSaved(String? value) => operationScale = value!;
}
```
These methods will be used on the `onSaved` property of form related widgets like `TextFormField`.

Usually the Validator and Save methods are created on the form widget but I choose to add it to the `FarmerServiceModel` class so I can easily reuse it.

### Bringing the pieces together

```Dart
import 'package:cems/utils/constants.dart';

class FarmerServiceModel {
  late String id;
  late String registrationNumber;
  late final String? nationalId;
  late final String? profilePicture;
  late final String? firstName;
  late final String lastName;
  late final String? nickname;
  late final DateTime? dateOfBirth;
  late final String gender;
  late final String ethnicity;
  late final String maritalStatus;
  late final String address;
  late final bool isHeadOfHousehold;
  late final bool isFarmingPrimaryIncomeSource;
  late final bool isActiveFarmer;
  late final String farmerCategory;
  late final String subsector;
  late final String operationScale;
  late List<String>? farm;

  FarmerServiceModel({
    required this.id,
    required this.registrationNumber,
    required this.profilePicture,
    required this.lastName,
    required this.gender,
    required this.ethnicity,
    required this.maritalStatus,
    required this.address,
    required this.isHeadOfHousehold,
    required this.isFarmingPrimaryIncomeSource,
    required this.farmerCategory,
    required this.operationScale,
    required this.subsector,
    this.nationalId,
    this.firstName,
    this.nickname,
    this.dateOfBirth,
    this.isActiveFarmer = true,
    this.farm,
  });
  FarmerServiceModel.form();

  String get name => '$firstName $lastName';

  FarmerServiceModel.fromJson(Map<String, Object?> json)
      : this(
          id: json['id']! as String,
          registrationNumber: json['registrationNumber'] as String,
          nationalId: json['nationalId'] as String,
          profilePicture: json['profilePicture'] as String,
          firstName: json['firstName'] as String,
          lastName: json['lastName'] as String,
          nickname: json['nickname'] as String,
          dateOfBirth: json['dateOfBirth'] as DateTime,
          gender: json['gender'] as String,
          ethnicity: json['ethnicity'] as String,
          maritalStatus: json['maritalStatus'] as String,
          address: json['address'] as String,
          isHeadOfHousehold: json['isHeadOfHousehold'] as bool,
          isActiveFarmer: json['isActiveFarmer'] as bool,
          isFarmingPrimaryIncomeSource:
              json['isFarmingPrimaryIncomeScore'] as bool,
          farmerCategory: json['farmerCategory'] as String,
          subsector: json['subsector'] as String,
          operationScale: json['operationScale'] as String,
          farm: json['farm'] as List<String>,
        );

  Map<String, Object?> toJson() {
    return {
      'id': id,
      'registrationNumber': registrationNumber,
      'nationalId': nationalId,
      'profileProfile': profilePicture,
      'firstName': firstName,
      'lastName': lastName,
      'nickname': nickname,
      'dateOfBirth': dateOfBirth,
      'gender': gender,
      'ethnicity': ethnicity,
      'maritalStatus': maritalStatus,
      'address': address,
      'isHeadOfHousehold': isHeadOfHousehold,
      'isActiveFarmeer': isActiveFarmer,
      'isFarmingPrimaryIncomeSource': isFarmingPrimaryIncomeSource,
      'farmerCategory': farmerCategory,
      'subsector': subsector,
      'operationScale': operationScale,
      'farm': farm,
    };
  }

  // VALIDATION METHODS

  String? validateRegistrationNumber(String? value) {
    return null;
  }

  String? handleNationalIdValidation(String? value) {
    return null;
  }

  String? validateProfilePicture(String? value) {
    return null;
  }

  String? handleFirstNameValidation(String? value) {
    return null;
  }

  String? handleLastNameValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else {
      return null;
    }
  }

  String? handleNicknameValidation(String? value) {
    return null;
  }

  String? handleDateOfBirthValidation(String? value) {
    return null;
  }

  String? handleGenderValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }

  String? handleEthnicityValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }

  String? handleMaritalStatusValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }

  String? handleAddressValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }

  String? handleFarmerCategoryValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }

  String? handleSubsectorValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }

  String? handleOperationScaleValidation(String? value) {
    if (value!.isEmpty) {
      return kEmptyFieldValidationError;
    } else
      return null;
  }

  // SAVE METHODS
  void saveRegistrationNumber(String? value) => registrationNumber = value!;
  void handleNationalIdSaved(String? value) => nationalId = value!;
  void saveProfilePicture(String? value) => profilePicture = value!;
  void handleFirstNameSaved(String? value) => firstName = value!;
  void handleLastNameSaved(String? value) => lastName = value!;
  void handleNicknameSaved(String? value) => nickname = value!;
  void handleDateOfBirthSaved(DateTime? value) => dateOfBirth = dateOfBirth;
  void handleGenderSaved(String? value) => gender = value!;
  void handleEthnicitySaved(String? value) => ethnicity = value!;
  void handleMaritalStatusSaved(String? value) => maritalStatus = value!;
  void handleAddressSaved(String? value) => address = value!;
  void handleIsHeadOfHouseholdChange(bool? value) => isHeadOfHousehold = value!;
  void handleFarmerCategorySaved(String? value) => farmerCategory = value!;
  void handleSubsectorSaved(String? value) => subsector = value!;
  void handleIsFarmingPrimaryIncomeSourceChange(bool? value) =>
      isFarmingPrimaryIncomeSource = value!;
  void handleOperationScaleSaved(String? value) => operationScale = value!;
}

```

The code snippet above shows the `FarmerServiceModel` class in its entirety.

## Connect with me

Thank you for reading my blog. Feel free to subscribe below to join me on the #100DaysOfCodeChallenge or connect with me on [LinkedIn](https://www.linkedin.com/in/curtlycritchlow/) and [Twitter](https://twitter.com/CritchlowCurtly).