#100DaysOfCodeChallenge -Crop Management Information System- Day 1

Introduction

Check out the #100DaysOfCodeChallenge - Crop Management Information System 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

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

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

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

// 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.

// 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

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 and Twitter.

14