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.
Top comments (2)
Good job! If you are interested in Flutter, you can also look at my article about free vs paid Flutter templates. I'm sure you'll find something useful there, too. - dev.to/pablonax/free-vs-paid-flutt...
Thanks I will check it out.