enrollment-app/lib/home.dart
2026-03-26 09:45:12 +05:30

2146 lines
110 KiB
Dart
Executable File

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:nhancepolicy/customAppBar/customAppBar.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:io';
import 'package:nhancepolicy/responsive.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:jwt_decode/jwt_decode.dart';
// import 'package:fluttertoast/fluttertoast.dart';
import 'package:nhancepolicy/customAppBar/toastHelper.dart';
import 'config/environment.dart';
import 'package:nhancepolicy/logger.dart';
// void main() {
// runApp(MaterialApp(
// home: MyApp(),
// ));
// }
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
// Sample list of items
final List<String> items = [
'Personal Details',
'Family Members',
'Policies',
// 'Log Out',
];
// Sample list of icons corresponding to each item
final List<IconData> icons = [
Icons.account_circle,
Icons.group,
Icons.policy,
// Icons.logout,
];
int selectedIndex = 0; // Variable to hold the index of the selected item
late String _token;
dynamic personalDetails;
dynamic basicCoverSI;
dynamic familyDetails;
dynamic nonSelfObjectsArrayDetails;
dynamic empCodeString;
dynamic empPrimaryId;
dynamic gpaEmpName;
dynamic client_id;
dynamic gpaApiData;
dynamic gpaAPISIDetails;
List<dynamic> dataPolicy = [];
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
TextEditingController _empCodeController = TextEditingController();
TextEditingController _fullNameController = TextEditingController();
TextEditingController _email_personalController = TextEditingController();
TextEditingController _dobController = TextEditingController();
TextEditingController _genderController = TextEditingController();
TextEditingController _mobileController = TextEditingController();
String? _selectedGender; // Holds the selected gender value
bool isReadOnly = true;
List<FamilyMember> familyMembers = [];
List<String> relationshipOptions = [];
dynamic gpaPolicyName;
dynamic gmcPolicyName;
dynamic gpaGridMaster;
dynamic gmcGridMaster;
dynamic gpasumInsured;
dynamic gpaClintPolicyId;
dynamic gpaPermiumValue;
dynamic gpaSelectedSlabRateObject;
dynamic gpaSlabRates = [];
dynamic gpaAdditionalTextAmount;
dynamic gmcSlabRates = [];
dynamic gmcfamily_floaters = [];
dynamic gpaMappedFamilyFloaters;
dynamic gmcFamily_floater_Status;
dynamic gpaSelectedSI;
dynamic gpaAssignSelectedSI;
String? gmcSelectedSI;
Map<String, String?> selectedSI = {};
String? selectedRelationship;
dynamic gpaAdditionalText = 0;
dynamic gmcAdditionalText = 0;
dynamic gpasumInsuredPermium;
@override
void initState() {
super.initState();
_loadToken();
// Initialize the controller with an initial value
_genderController.text = 'Male'; // Set the initial value to 'Male'
_selectedGender = 'Male'; // Set the selected gender value
}
Future<void> _loadToken() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String? token = prefs.getString('token');
if (token != null) {
setState(() {
_token = token;
});
// Decode the JWT token received from the API response
Map<String, dynamic>? decodedToken = Jwt.parseJwt(token);
logDebug(decodedToken);
empCodeString =
decodedToken['emp_code'].toString(); // Ensure it's a string
logDebug(empCodeString); // Check if emp_code is correct
empPrimaryId = decodedToken['id'].toString();
gpaEmpName = decodedToken['name'].toString();
client_id = decodedToken['client_id'].toString();
logDebug(client_id);
// logDebug(empPrimaryId);
// Call the API when the page enters
getEmpDetails(empCodeString);
fetchRelationshipList();
getEmpPolicyDetails(empPrimaryId);
} else {
// Handle the case when token is not available
}
}
// Function to fetch data from the API
Future<void> getEmpDetails(empCodeString) async {
// Replace the URL with your API endpoint
var url = Uri.parse(Environment.apiUrl +
'getEmployeeAndDependence?emp_code=' +
empCodeString);
try {
var response = await http.get(
url,
headers: {
'APP-SIGNATURE':
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
'Authorization':
'Bearer $_token', // Add token to the Authorization header
},
);
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
// Ensure that data is not null and contains 'data' key
if (data.containsKey('data')) {
var responseData = data['data'];
// Check if responseData is a list and not empty
if (responseData is List && responseData.isNotEmpty) {
// Find all objects where relationship is not "Self"
List nonSelfObjects = (responseData as List<dynamic>)
.where((obj) => obj['relationship'] != 'Self')
.toList();
nonSelfObjectsArrayDetails = nonSelfObjects;
logDebug(nonSelfObjectsArrayDetails);
List<FamilyMember> familyMembersFromDetails =
nonSelfObjects.map((detail) {
return FamilyMember(
relationship: detail['relationship'] ?? '',
fullName: detail['name'] ?? '',
dob: detail['dob'] ?? '',
);
}).toList();
setState(() {
familyMembers = familyMembersFromDetails;
});
// Find the Self object
Map<String, dynamic>? selfObject = responseData.firstWhere(
(obj) => obj['relationship'] == 'Self',
orElse: () => null,
);
personalDetails =
selfObject; // Assuming the first item contains the desired details
logDebug(personalDetails);
_empCodeController.text = personalDetails != null
? personalDetails['emp_code'] ?? ''
: '';
_fullNameController.text =
personalDetails != null ? personalDetails['name'] ?? '' : '';
_email_personalController.text = personalDetails != null
? personalDetails['email_corporate'] ?? ''
: '';
_dobController.text =
personalDetails != null ? personalDetails['dob'] ?? '' : '';
_genderController.text =
personalDetails != null ? personalDetails['gender'] ?? '' : '';
_mobileController.text =
personalDetails != null ? personalDetails['mobile'] ?? '' : '';
} else {
logDebug('Empty or invalid data received');
}
} else {
logDebug('Invalid response format: missing "data" key');
}
} else {
// Handle other status codes
logDebug('Request failed with status: ${response.statusCode}');
}
} catch (e) {
// Handle exceptions
logDebug('Exception occurred: $e');
}
}
Future<void> getEmpPolicyDetails(empPrimaryId) async {
var url = Uri.parse(Environment.apiUrl +
'getEmployeePolicy?id=$empPrimaryId&emp_code=$empCodeString');
try {
var response = await http.get(
url,
headers: {
'APP-SIGNATURE':
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
'Authorization':
'Bearer $_token', // Add token to the Authorization header
},
);
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
if (data['status'] == 'success') {
// Ensure that data is not null and contains 'data' key
dataPolicy = List<Map<String, dynamic>>.from(
data['data']); // Assuming data is a List
List<Map<String, dynamic>> gpaPolicies = []; // Adjust type to dynamic
List<Map<String, dynamic>> gmcPolicies = []; // Adjust type to dynamic
for (var policy in dataPolicy) {
var gridMaster =
policy['GridMaster'] as Map<String, dynamic>?; // Explicit cast
if (gridMaster != null) {
var policyType =
gridMaster['policy_type'] as String?; // Explicit cast
if (policyType != null) {
if (policyType == 'GPA') {
gpaPolicies.add(
policy as Map<String, dynamic>); // Adjust type to dynamic
} else if (policyType == 'GMC') {
gmcPolicies.add(
policy as Map<String, dynamic>); // Adjust type to dynamic
}
}
}
}
if (gpaPolicies.isNotEmpty) {
// You can use gpaPolicies as needed
logDebug('GPA Policies found: $gpaPolicies');
gpaPolicyName = await gpaPolicies[0]['Policy_Name'];
gpaGridMaster = await gpaPolicies[0]['GridMaster'];
gpaSlabRates = await gpaPolicies[0]['SlabRates'];
gpasumInsured = await gpaPolicies[0]['Policy_Terms']['sumInsured2'];
gpaClintPolicyId = await gpaPolicies[0]['ClientPolicyId'];
gpaMappedFamilyFloaters =
await gpaPolicies[0]['mapped_family_floaters'];
gpaSelectedSI =
gpaMappedFamilyFloaters['basic_cover_si'].toString();
logDebug(gpasumInsured);
//find the premium amount that match sumInsured amount from policyTerm
Map<String, dynamic>? findGpasumInsuredObject =
gpaSlabRates.firstWhere(
(rate) => rate['si'] == gpasumInsured.toString(),
orElse: () => null,
);
logDebug('test');
if (findGpasumInsuredObject != null) {
gpasumInsuredPermium =
findGpasumInsuredObject['premium'].toString();
// logDebug(test);
} else {
gpasumInsuredPermium = 0;
}
// Find the object with the matching 'si' value
Map<String, dynamic>? gpaSelectedSlabRateObject =
gpaSlabRates.firstWhere(
(rate) => rate['si'] == gpaSelectedSI.toString(),
orElse: () => null,
);
if (gpaSelectedSlabRateObject != null) {
gpaAssignSelectedSI = gpaSelectedSlabRateObject['si'].toString();
} else {
gpaAssignSelectedSI = 0;
}
logDebug(gpaSelectedSlabRateObject);
if (gpaSelectedSlabRateObject != null) {
gpaPermiumValue = gpaSelectedSlabRateObject['premium'].toString();
} else {
gpaPermiumValue = 0;
}
logDebug(gpaAssignSelectedSI);
String stringValue =
gpaSelectedSI.toString(); // Extract the string from the list
int intValue1 = int.parse(stringValue);
int? intValue = int.tryParse(gpasumInsured);
logDebug('policy_trem_amound');
logDebug(intValue);
logDebug("selected si");
logDebug(intValue1);
if (intValue != null && intValue1 != null) {
if (intValue < intValue1) {
gpaAdditionalText = 1;
setState(() {
Map<String, dynamic>? findObject = gpaSlabRates.firstWhere(
(rate) => rate['si'] == gpaAssignSelectedSI.toString(),
orElse: () => null,
);
logDebug(findObject);
// setState(() {
gpaAPISIDetails = findObject;
// });
var gpaPermiumValueChanged;
if (findObject != null) {
gpaPermiumValueChanged =
gpaAPISIDetails['premium'].toString();
} else {
gpaPermiumValueChanged = 0;
}
logDebug(gpaPermiumValueChanged);
logDebug(gpaPermiumValue);
// Convert string values to integers
int gpaSelectedPermium =
int.tryParse(gpasumInsuredPermium) ?? 0;
int gpaChangedPermium =
int.tryParse(gpaPermiumValueChanged) ?? 0;
logDebug('gpasumInsuredPermium');
logDebug(gpaSelectedPermium);
logDebug("gpaChangedPermium");
logDebug(gpaChangedPermium);
// Calculate the result
int? result =
gpaSelectedPermium != null && gpaChangedPermium != null
? gpaChangedPermium - gpaSelectedPermium
: null;
logDebug(result);
gpaAdditionalTextAmount = result;
logDebug(gpaAdditionalText);
});
} else {
setState(() {
gpaAdditionalText = 0;
logDebug(gpaAdditionalText);
});
}
}
} else {
logDebug('GPA Policies not found');
}
if (gmcPolicies.isNotEmpty) {
// You can use gmcPolicies as needed
logDebug('GMC Policies found: $gmcPolicies');
gmcPolicyName = await gmcPolicies[0]['Policy_Name'];
gmcGridMaster = await gmcPolicies[0]['GridMaster'];
gmcSlabRates = await gmcPolicies[0]['SlabRates'];
// relationshipOptions =
// await await gmcPolicies[0]['Policy_Terms']['family_floaters'];
// logDebug(relationshipOptions);
gmcfamily_floaters = await gmcPolicies[0]['mapped_family_floaters'];
logDebug(gmcfamily_floaters);
setState(() {
gmcFamily_floater_Status =
gmcPolicies[0]['Policy_Terms']['family_floater'];
logDebug(gmcFamily_floater_Status);
});
} else {
logDebug('GMC Policies not found');
}
} else {
// Handle other status messages if needed
logDebug('API request failed with status: ${data['status']}');
}
} else {
// Handle other status codes
logDebug('Request failed with status: ${response.statusCode}');
}
} catch (e) {
// Handle exceptions
logDebug('Exception occurred: $e');
}
}
checkGpaSumInsured() {
logDebug(gpaAssignSelectedSI);
// logDebug(gpaPermiumValue);
// logDebug(gpaSelectedSlabRateObject);
String stringValue =
gpaSelectedSI.toString(); // Extract the string from the list
int intValue1 = int.parse(stringValue);
int? intValue = int.tryParse(gpasumInsured);
logDebug('policy_trem_amound');
logDebug(intValue);
logDebug("selected si");
logDebug(intValue1);
if (intValue != null && intValue1 != null) {
if (intValue < intValue1) {
gpaAdditionalText = 1;
setState(() {
Map<String, dynamic>? findObject = gpaSlabRates.firstWhere(
(rate) => rate['si'] == gpaSelectedSI.toString(),
orElse: () => null,
);
logDebug(findObject);
// setState(() {
gpaAPISIDetails = findObject;
// });
var gpaPermiumValueChanged;
if (findObject != null) {
gpaPermiumValueChanged = gpaAPISIDetails['premium'].toString();
} else {
gpaPermiumValueChanged = 0;
}
logDebug(gpaPermiumValueChanged);
logDebug(gpaPermiumValue);
// Convert string values to integers
int gpaSelectedPermium = int.tryParse(gpasumInsuredPermium) ?? 0;
int gpaChangedPermium = int.tryParse(gpaPermiumValueChanged) ?? 0;
logDebug('gpasumInsuredPermium');
logDebug(gpaSelectedPermium);
logDebug("gpaChangedPermium");
logDebug(gpaChangedPermium);
// Calculate the result
int? result = gpaSelectedPermium != null && gpaChangedPermium != null
? gpaChangedPermium - gpaSelectedPermium
: null;
logDebug(result);
gpaAdditionalTextAmount = result;
logDebug(gpaAdditionalText);
});
} else {
setState(() {
gpaAdditionalText = 0;
logDebug(gpaAdditionalText);
});
}
}
}
// Function to update user details
Future<void> updateUserDetails() async {
// Validate the form before submitting
if (_formKey.currentState!.validate()) {
// Prepare the request body
List<Map<String, dynamic>> requestBody = [
{
'id': personalDetails['id'], // Assuming personalDetails is a Map
'emp_code': _empCodeController.text,
'full_name': _fullNameController.text,
'dob': _dobController.text,
'gender': _selectedGender ?? '',
'mobile': _mobileController.text,
'email_corporate': _email_personalController.text,
}
];
// Make the HTTP POST request
var url = Uri.parse(Environment.apiUrl + 'editEmployeeAndDependence');
try {
var response = await http.post(
url,
body: jsonEncode(requestBody),
headers: {
'APP-SIGNATURE':
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
'Content-Type': 'application/json',
// Add authorization header if needed
'Authorization': 'Bearer $_token',
},
);
// Check the response status code
if (response.statusCode == 200) {
// ToastHelper.showSuccessToast(context, 'Successfully Saved');
getEmpDetails(empCodeString);
} else {
// Handle other status codes
// ToastHelper.showErrorToast(context, 'Failed to update user details');
logDebug('Request failed with status: ${response.statusCode}');
}
} catch (e) {
// Handle exceptions
logDebug('Exception occurred: $e');
// ToastHelper.showErrorToast(context, 'Exception occurred: $e');
}
}
}
Future<void> fetchRelationshipList() async {
// Replace the URL with your API endpoint
final url = Uri.parse(Environment.apiUrl + 'relationshipList');
try {
final response = await http.get(
url,
headers: {
'APP-SIGNATURE':
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
'Authorization':
'Bearer $_token', // Add token to the Authorization header
},
);
if (response.statusCode == 200) {
final List<dynamic> data = jsonDecode(response.body)['data'];
final List<String> relationships =
List<String>.from(data.map((item) => item['relationship_name']));
setState(() {
relationshipOptions = relationships;
});
} else {
throw Exception('Failed to fetch relationship list');
}
} catch (error) {
// ToastHelper.showErrorToast(
// context, 'Error fetching relationship list: $error');
logDebug('Error fetching relationship list: $error');
// Handle error accordingly, e.g., show a snackbar with an error message
}
}
void addFamilyMember() {
setState(() {
familyMembers.add(FamilyMember(relationship: '', fullName: '', dob: ''));
});
}
// void removeFamilyMember(int index) {
// logDebug(index);
// setState(() {
// familyMembers.removeAt(index);
// });
// logDebug(familyMembers.toString());
// }
void removeFamilyMember(int index) async {
logDebug(index);
// logDebug(nonSelfObjectsArrayDetails[index]);
// return;
try {
if (index >= 0 && index < nonSelfObjectsArrayDetails.length) {
var removeObject = nonSelfObjectsArrayDetails[index] ?? false;
logDebug(removeObject);
if (removeObject != false) {
final id = nonSelfObjectsArrayDetails[index]['id'];
// If the family member has an ID, it means it's an existing record, so make an API call to delete it
final url =
Uri.parse(Environment.apiUrl + 'deleteDependence?id=' + id);
final response = await http.get(
url,
headers: {
'APP-SIGNATURE':
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
'Content-Type': 'application/json',
'Authorization':
'Bearer $_token', // Add token to the Authorization header // Add your authorization token here
},
);
if (response.statusCode == 200) {
// If API call is successful, remove the family member from the list
setState(() {
familyMembers.removeAt(index);
nonSelfObjectsArrayDetails.removeAt(index);
});
logDebug('Family member removed successfully');
} else {
// If API call fails, print error message
logDebug('Failed to remove family member: ${response.statusCode}');
}
} else {
// If the family member doesn't have an ID, it's a new record, so simply remove it from the list locally
setState(() {
familyMembers.removeAt(index);
});
}
} else {
setState(() {
familyMembers.removeAt(index);
});
}
} catch (error) {
// Handle any errors that occur during the API call
// logDebug('Error removing family member: $error');
// ToastHelper.showErrorToast(
// context, 'Error removing family member: $error');
}
}
void saveFamilyMemberDetails() async {
logDebug(nonSelfObjectsArrayDetails);
try {
// Convert familyMembers list to a list of JSON objects
// Convert familyMembers list to a list of JSON objects
final List<Map<String, dynamic>> membersData =
familyMembers.map((member) {
logDebug(member);
// Include additional fields from personalDetails
return {
'relationship': member.relationship,
'name': member.fullName,
'dob': member.dob,
'emp_code': personalDetails['emp_code'],
'client_id': personalDetails['client_id'],
};
}).toList();
logDebug(membersData);
List<Map<String, dynamic>> updatedNewData =
List<Map<String, dynamic>>.generate(membersData.length, (index) {
Map<String, dynamic> updatedEntry = membersData[index];
if (index < nonSelfObjectsArrayDetails.length &&
nonSelfObjectsArrayDetails[index].containsKey('id')) {
updatedEntry['id'] = nonSelfObjectsArrayDetails[index]['id'];
}
return updatedEntry;
});
logDebug(updatedNewData);
// Iterate through familyMembers list and send each member's data to the API
final url = Uri.parse(Environment.apiUrl + 'addEmployeeAndDependence');
final response = await http.post(
url,
body: jsonEncode(updatedNewData),
headers: {
'APP-SIGNATURE':
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
'Content-Type': 'application/json',
'Authorization':
'Bearer $_token', // Add token to the Authorization header
},
);
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
if (data['status'] == 'success') {
// Member saved successfully
setState(() {
getEmpDetails(empCodeString);
});
// ToastHelper.showSuccessToast(context, "Saved successfully!");
}
} else {
// Failed to save member
// ToastHelper.showErrorToast(context, "Operation Failed!");
}
} catch (error) {
// ToastHelper.showErrorToast(context, "Error saving family members");
}
}
void sendGpaDataToAPI() async {
// Create a list to store the selected values for each floater
logDebug(gpaAPISIDetails);
String si = gpaSelectedSI ?? '';
// String premium = gpaAPISIDetails['premium'];
String ClientPolicyId = gpaClintPolicyId;
String emp_id = empPrimaryId;
// Create a map containing the floater details and its selected values
dynamic floaterData = [
{
'basic_cover_si': si,
// 'premium': premium,
'client_policy_id': ClientPolicyId,
'employee_id': emp_id,
'client_id': client_id,
}
];
gpaApiData = floaterData;
logDebug(gpaApiData);
try {
final jsonData = gpaApiData;
logDebug(jsonData);
// return;
// Iterate through familyMembers list and send each member's data to the API
final url = Uri.parse(
Environment.apiUrl + 'createOrUpdateEmployeePolicySiAmount');
final response = await http.post(
url,
body: jsonEncode(jsonData),
headers: {
'APP-SIGNATURE':
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
'Content-Type': 'application/json',
'Authorization':
'Bearer $_token', // Add token to the Authorization header
},
);
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
if (data['status'] == 'success') {
// Member saved successfully
setState(() {
getEmpDetails(empCodeString);
getEmpPolicyDetails(empPrimaryId);
});
floaterData = [];
// ToastHelper.showSuccessToast(context, "Saved successfully!");
logDebug('Saved successfully!');
}
} else {
// Failed to save member
// ToastHelper.showErrorToast(context, "Operation Failed!");
logDebug('Operation Failed!');
}
} catch (error) {
logDebug('Error saving family members');
// ToastHelper.showErrorToast(context, "Error saving family members");
}
}
void sendGmcDataToAPI() async {
// Create a list to store the selected values for each floater
List<Map<String, String>> selectedValues = [];
// try {
logDebug('fff');
// Iterate through each floater and get its selected value
// Iterate through each floater and get its selected value
for (var floater in gmcfamily_floaters) {
String floaterKey = floater['family_floater_key'];
String selectedSIValue = selectedSI[floaterKey] ?? '';
String client_policy_id = floater['client_policy_id'].toString();
String employee_id = floater['employee_id'].toString();
// Create a map containing the floater details and its selected values
Map<String, String> floaterData = {
'family_floater_key': floaterKey,
'basic_cover_si': selectedSIValue,
'client_policy_id': client_policy_id,
'employee_id': employee_id,
'client_id': client_id,
};
// Add the map to the list
selectedValues.add(floaterData);
}
final jsonData = selectedValues;
logDebug(jsonData);
// return;
// Iterate through each object in apidata
for (var data in jsonData) {
String basicCoverSI = data['basic_cover_si'].toString();
if (basicCoverSI == "") {
// Find the corresponding premium value in SlabRates
for (var rate in gmcfamily_floaters) {
if (rate['employee_id'] == data['employee_id']) {
// Update the premium value in the current object
data['basic_cover_si'] = rate['basic_cover_si'].toString();
break; // Stop searching once a match is found
}
}
}
}
logDebug("gwm");
logDebug(jsonData);
// return;
// Iterate through familyMembers list and send each member's data to the API
final url =
Uri.parse(Environment.apiUrl + 'createOrUpdateEmployeePolicySiAmount');
final response = await http.post(
url,
body: jsonEncode(jsonData),
headers: {
'APP-SIGNATURE':
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
'Content-Type': 'application/json',
'Authorization':
'Bearer $_token', // Add token to the Authorization header
},
);
if (response.statusCode == 200) {
Map<String, dynamic> data = json.decode(response.body);
if (data['status'] == 'success') {
// Member saved successfully
setState(() {
getEmpDetails(empCodeString);
});
// ToastHelper.showSuccessToast(context, "Saved successfully!");
logDebug('Saved successfully!');
}
} else {
logDebug('Operation Failed!');
// Failed to save member
// ToastHelper.showErrorToast(context, "Operation Failed!");
}
// } catch (error) {
logDebug('Error saving family members');
// ToastHelper.showErrorToast(context, "Error saving family members");
// }
}
@override
Widget build(BuildContext context) {
// Retrieve the arguments passed to this page
final Map<String, dynamic>? getEmpDetails =
ModalRoute.of(context)?.settings.arguments as Map<String, dynamic>?;
return Scaffold(
appBar: CustomAppBar(),
body: Container(
padding: const EdgeInsets.all(8.0), // Add edge padding
color: Color(0xFFEFF3F6),
child: Row(
children: [
Expanded(
flex: 3,
child: Container(
margin:
EdgeInsets.only(left: 100, right: 0, top: 15, bottom: 15),
child: Card(
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(left: 20, top: 15, bottom: 8),
child: Text(
'Settings',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
ListView.builder(
shrinkWrap: true,
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
final icon = icons[index];
return Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
setState(() {
selectedIndex = index;
});
},
splashColor: Colors.grey.withOpacity(0.5),
hoverColor: Colors.grey.withOpacity(0.1),
child: Padding(
padding: const EdgeInsets.all(1.0),
child: ListTile(
leading: Icon(icon),
title: Text(
item,
style: TextStyle(fontSize: 14),
),
selected: selectedIndex == index,
selectedTileColor:
Colors.grey.withOpacity(0.3),
),
),
),
);
},
),
],
),
),
),
),
Expanded(
flex: 9,
child: ListView(// Example list of widgets
children: [
Visibility(
visible: selectedIndex ==
0, // Show only when Personal Details is selected
child: Container(
margin: EdgeInsets.only(
left: 15, right: 100, top: 15, bottom: 15),
child: Card(
color:
Colors.white, // Set the background color for the card
// Add vertical margin
child: Padding(
padding: EdgeInsets.only(
left: 30, right: 30, top: 15, bottom: 30),
child: Form(
key: _formKey, // Add padding inside the card
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.only(
left: 0, top: 0, bottom: 25),
child: Row(
children: [
Container(
padding: EdgeInsets.all(
4), // Padding around the icon
decoration: BoxDecoration(
color: Color(
0xFF00989E), // Background color of the icon container
borderRadius: BorderRadius.circular(
5), // Radius of the container
),
child: Icon(
Icons.account_circle, // Icon data
color:
Colors.white, // Color of the icon
),
),
SizedBox(
width:
8), // Add some space between the icon and text
Text(
'Personal Details',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
),
),
Row(
children: [
Expanded(
child: TextFormField(
controller: _empCodeController,
readOnly: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Employee ID',
labelText: 'Employee ID',
contentPadding: EdgeInsets.symmetric(
vertical: 10, horizontal: 15),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Employee ID is required';
}
return null;
},
),
),
SizedBox(
width:
30), // Add spacing between fields
Expanded(
child: TextFormField(
controller: _fullNameController,
readOnly: isReadOnly,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Full Name',
labelText: 'Full Name',
contentPadding: EdgeInsets.symmetric(
vertical: 10, horizontal: 15),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Full Name is required';
}
return null;
},
),
),
],
),
SizedBox(height: 30),
Row(
children: [
Expanded(
child: TextFormField(
controller: _dobController,
readOnly: isReadOnly,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'DD-MM-YYYY',
labelText: 'Date of Birth',
contentPadding: EdgeInsets.symmetric(
vertical: 10, horizontal: 15),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Date of Birth is required';
}
return null;
},
),
),
SizedBox(
width:
30), // Add spacing between fields
Expanded(
child: DropdownButtonFormField<String>(
value: _selectedGender,
onChanged: (value) {
setState(() {
_selectedGender = value;
});
}, // Set the controller
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Gender',
labelText: 'Gender',
contentPadding: EdgeInsets.symmetric(
vertical: 10, horizontal: 15),
),
items: ['Male', 'Female', 'Other']
.map((gender) =>
DropdownMenuItem<String>(
value: gender,
child: Text(gender),
))
.toList(), // Set the selected value
),
),
],
),
SizedBox(height: 30),
Row(
children: [
Expanded(
child: TextFormField(
controller: _mobileController,
readOnly: true,
keyboardType: TextInputType.number,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Mobile Number',
labelText: 'Mobile Number',
contentPadding: EdgeInsets.symmetric(
vertical: 10, horizontal: 15),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Employee ID is required';
}
return null;
},
),
),
SizedBox(
width:
30), // Add spacing between fields
Expanded(
child: TextFormField(
controller: _email_personalController,
readOnly: isReadOnly,
keyboardType:
TextInputType.emailAddress,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Email ID',
labelText: 'Email ID',
contentPadding: EdgeInsets.symmetric(
vertical: 10, horizontal: 15),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Employee ID is required';
}
return null;
},
),
),
],
),
SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.only(
right:
10), // Add spacing between buttons
child: ElevatedButton(
onPressed: () {
setState(() {
// Toggle read-only state
isReadOnly = !isReadOnly;
});
},
child: Text(
'Edit',
style: TextStyle(
color: Color(0xFFE26728)),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(5),
side: BorderSide(
color: Color(
0xFFE26728)), // Add border
),
),
),
),
Container(
child: ElevatedButton(
onPressed: () {
updateUserDetails();
// Add functionality for Update button
},
child: Text(
'Update',
style: TextStyle(color: Colors.white),
),
style: ElevatedButton.styleFrom(
backgroundColor: Color(
0xFFE26728), // Set background color
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
5), // Set border radius
),
),
),
),
],
),
],
),
)),
),
),
),
Visibility(
visible: selectedIndex ==
1, // Show only when Family Members is selected
child: SingleChildScrollView(
child: Container(
margin: EdgeInsets.only(
left: 15, right: 100, top: 15, bottom: 15),
child: Card(
color: Colors
.white, // Set the background color for the card
// Add vertical margin
child: Padding(
padding: EdgeInsets.only(
left: 30, right: 30, top: 15, bottom: 30),
child: Form(
key: _formKey, // Add padding inside the card
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.only(
left: 0, top: 0, bottom: 25),
child: Row(
children: [
Container(
padding: EdgeInsets.all(
4), // Padding around the icon
decoration: BoxDecoration(
color: Color(
0xFF00989E), // Background color of the icon container
borderRadius: BorderRadius.circular(
5), // Radius of the container
),
child: Icon(
Icons.group, // Icon data
color: Colors
.white, // Color of the icon
),
),
SizedBox(
width:
8), // Add some space between the icon and text
Text(
'Family Members',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
),
),
ListView.builder(
shrinkWrap: true,
itemCount: familyMembers.length,
itemBuilder: (context, index) {
return buildFamilyMemberForm(index);
},
),
SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
margin: EdgeInsets.only(right: 10),
child: ElevatedButton.icon(
onPressed: addFamilyMember,
icon: Icon(
Icons.person_add,
color: Color(0xFF00989E),
),
label: Text(
'Add Member',
style: TextStyle(
color: Color(0xFF00989E),
),
),
),
),
],
),
SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
child: ElevatedButton(
onPressed: () {
saveFamilyMemberDetails();
},
child: Text(
'Save',
style:
TextStyle(color: Colors.white),
),
style: ElevatedButton.styleFrom(
backgroundColor: Color(
0xFFE26728), // Set background color
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(
5), // Set border radius
),
),
),
),
],
),
],
),
),
),
),
),
)),
Visibility(
visible: selectedIndex ==
2, // Show only when Family Members is selected
child: SingleChildScrollView(
child: Container(
margin: EdgeInsets.only(
left: 15, right: 100, top: 15, bottom: 15),
child: Card(
elevation: 0,
color: Colors
.white, // Set the background color for the card
// Add vertical margin
child: Padding(
padding: EdgeInsets.only(
left: 30, right: 30, top: 15, bottom: 30),
child: Form(
key: _formKey, // Add padding inside the card
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.only(
left: 0, top: 0, bottom: 25),
child: Row(
children: [
Container(
padding: EdgeInsets.all(
4), // Padding around the icon
decoration: BoxDecoration(
color: Color(
0xFF00989E), // Background color of the icon container
borderRadius: BorderRadius.circular(
5), // Radius of the container
),
child: Icon(
Icons.policy, // Icon data
color: Colors
.white, // Color of the icon
),
),
SizedBox(
width:
8), // Add some space between the icon and text
Text(
'Policies',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
),
),
SizedBox(height: 16),
Container(
child: Card(
elevation:
0, // Adjust the elevation as needed
shape: RoundedRectangleBorder(
side: BorderSide(
color: Color(0xFF868685),
width: 1), // Set border side
borderRadius: BorderRadius.circular(
10), // Set border radius
),
color: Color(0xFFFFFFFF),
child: Padding(
padding: EdgeInsets.all(30),
child: Column(
children: [
Row(
mainAxisAlignment:
MainAxisAlignment
.start,
children: [
Expanded(
flex: 1,
child: Container(
alignment: Alignment
.centerLeft,
child:
Image.asset(
'assets/policy.png', // Replace with your image path
width:
50, // Adjust the width as needed
height:
50, // Adjust the height as needed
),
)),
SizedBox(width: 5),
Expanded(
flex: 11,
child: Container(
alignment: Alignment
.centerLeft,
child: Column(
mainAxisAlignment:
MainAxisAlignment
.start,
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Text(
gpaPolicyName ??
'',
style:
TextStyle(
color: Color(
0xFF727272), // Set the color of the text
fontSize:
16, // Adjust the font size as needed
fontWeight:
FontWeight
.w400,
),
),
SizedBox(
height: 5,
),
Text(
'Group Personal Accident',
style:
TextStyle(
color: Color(
0xFF181818), // Set the color of the text
fontSize:
18, // Adjust the font size as needed
fontWeight:
FontWeight
.w600, // Adjust the font weight as needed
fontFamily:
'Poppins',
),
),
],
),
)),
]),
Row(
mainAxisAlignment:
MainAxisAlignment
.start,
children: [
Expanded(
flex: 6,
child: Container(
alignment: Alignment
.centerLeft,
child: Column(
children: [
Text(
'Name: $gpaEmpName',
style:
TextStyle(
color: Color(
0xFF181818), // Set the color of the text
fontSize:
16, // Adjust the font size as needed
fontWeight:
FontWeight
.w500,
),
),
],
),
)),
Expanded(
flex: 6,
child:
DropdownButtonFormField<
String>(
onChanged: (value) {
setState(() {
gpaSelectedSI =
value;
checkGpaSumInsured();
});
},
decoration:
InputDecoration(
border:
OutlineInputBorder(),
hintText:
'Sum Insured',
labelText:
'Sum Insured',
contentPadding:
EdgeInsets.symmetric(
vertical:
5,
horizontal:
5),
),
value: gpaSelectedSI
?.isNotEmpty ==
true
? gpaSelectedSI
: null,
items: gpaSlabRates.map<
DropdownMenuItem<
String>>((rate) {
return DropdownMenuItem<
String>(
value: rate[
'si']
.toString(),
child: Text(rate[
'si']
.toString()), // Display SI value as text
);
}).toList(),
),
)
]),
SizedBox(height: 16),
Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
if (gpaAdditionalText ==
0)
Container(), // Placeholder container when family_floater is "0"
if (gpaAdditionalText ==
1)
Expanded(
flex: 6,
child: Container(
alignment: Alignment
.centerRight,
child: Column(
children: [
Text(
'An additional premium of ₹ $gpaAdditionalTextAmount/- will be deducted from ',
style:
TextStyle(
color: Color(
0xFFEE0000), // Set the color of the text
fontSize:
14, // Adjust the font size as needed
fontWeight:
FontWeight.w400,
),
),
Text(
'your salary towards increased personal accident coverage',
style:
TextStyle(
color: Color(
0xFFEE0000), // Set the color of the text
fontSize:
14, // Adjust the font size as needed
fontWeight:
FontWeight.w400,
),
)
],
),
)),
]),
SizedBox(height: 16),
Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
Container(
child: ElevatedButton(
onPressed: () {
sendGpaDataToAPI();
},
child: Text(
'Update',
style: TextStyle(
color: Colors
.white),
),
style: ElevatedButton
.styleFrom(
backgroundColor: Color(
0xFFE26728), // Set background color
shape:
RoundedRectangleBorder(
borderRadius:
BorderRadius
.circular(
5), // Set border radius
),
),
),
),
],
),
],
)))),
SizedBox(height: 16),
Container(
child: Card(
elevation:
0, // Adjust the elevation as needed
shape: RoundedRectangleBorder(
side: BorderSide(
color: Color(0xFF868685),
width: 1), // Set border side
borderRadius: BorderRadius.circular(
10), // Set border radius
),
color: Color(0xFFFFFFFF),
child: Padding(
padding: EdgeInsets.all(30),
child: Column(
children: [
Row(
mainAxisAlignment:
MainAxisAlignment
.start,
children: [
Expanded(
flex: 1,
child: Container(
alignment: Alignment
.centerLeft,
child:
Image.asset(
'assets/policy.png', // Replace with your image path
width:
50, // Adjust the width as needed
height:
50, // Adjust the height as needed
),
)),
SizedBox(width: 5),
Expanded(
flex: 5,
child: Container(
alignment: Alignment
.centerLeft,
child: Column(
mainAxisAlignment:
MainAxisAlignment
.start,
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Text(
gmcPolicyName ??
'',
style:
TextStyle(
color: Color(
0xFF727272), // Set the color of the text
fontSize:
16, // Adjust the font size as needed
fontWeight:
FontWeight
.w400,
),
),
SizedBox(
height: 5,
),
Text(
'Group Medical Coverage',
style:
TextStyle(
color: Color(
0xFF181818), // Set the color of the text
fontSize:
18, // Adjust the font size as needed
fontWeight:
FontWeight
.w600, // Adjust the font weight as needed
fontFamily:
'Poppins',
),
),
],
),
)),
if (gmcFamily_floater_Status ==
'0')
Container(), // Placeholder container when family_floater is "0"
if (gmcFamily_floater_Status ==
'1')
Expanded(
flex: 6,
child:
DropdownButtonFormField<
String>(
onChanged:
(value) {
setState(() {
gmcSelectedSI =
value;
});
},
decoration:
InputDecoration(
border:
OutlineInputBorder(),
hintText:
'Sum Insured',
labelText:
'Sum Insured',
contentPadding:
EdgeInsets.symmetric(
vertical:
5,
horizontal:
5),
),
value: gmcSelectedSI
?.isNotEmpty ==
true
? gmcSelectedSI
: null,
items: gmcSlabRates.map<
DropdownMenuItem<
String>>((rate) {
return DropdownMenuItem<
String>(
value: rate[
'si']
.toString(),
child: Text(rate[
'si']
.toString()), // Display SI value as text
);
}).toList(),
),
)
]),
SizedBox(height: 20),
Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
if (gmcFamily_floater_Status ==
'0')
Container(), // Placeholder container when family_floater is "0"
if (gmcFamily_floater_Status ==
'1')
Expanded(
flex: 6,
child: Container(
alignment: Alignment
.centerRight,
child:
const Column(
children: [
Text(
'An additional premium of ₹ 10,000/- will be deducted from your ',
style:
TextStyle(
color: Color(
0xFFEE0000), // Set the color of the text
fontSize:
14, // Adjust the font size as needed
fontWeight:
FontWeight.w400, // Adjust the font weight as needed
fontFamily:
'Poppins',
),
),
Text(
'salary towards increased group medical coverage',
style:
TextStyle(
color: Color(
0xFFEE0000), // Set the color of the text
fontSize:
14, // Adjust the font size as needed
fontWeight:
FontWeight.w400, // Adjust the font weight as needed
fontFamily:
'Poppins',
),
)
],
),
)),
]),
SizedBox(height: 20),
// Row(
// mainAxisAlignment:
// MainAxisAlignment
// .start,
// children: [
// Expanded(
// flex: 6,
// child: Column(
// crossAxisAlignment:
// CrossAxisAlignment
// .start,
// children: [
// Text(
// 'Self: $gpaEmpName',
// style:
// TextStyle(
// color: Color(
// 0xFF181818), // Set the color of the text
// fontSize:
// 16, // Adjust the font size as needed
// fontWeight:
// FontWeight
// .w500,
// ),
// ),
// ],
// ),
// ),
// SizedBox(width: 15),
// Expanded(
// flex: 6,
// child:
// DropdownButtonFormField<
// String>(
// onChanged: (value) {
// setState(() {
// selectedSI =
// value;
// });
// },
// decoration:
// InputDecoration(
// border:
// OutlineInputBorder(),
// hintText:
// 'Sum Insured',
// labelText:
// 'Sum Insured',
// contentPadding:
// EdgeInsets.symmetric(
// vertical:
// 5,
// horizontal:
// 5),
// ),
// value: selectedSI
// ?.isNotEmpty ==
// true
// ? selectedSI
// : null,
// items: gmcSlabRates.map<
// DropdownMenuItem<
// String>>((rate) {
// return DropdownMenuItem<
// String>(
// value: rate[
// 'si']
// .toString(),
// child: Text(rate[
// 'si']
// .toString()), // Display SI value as text
// );
// }).toList(),
// ),
// )
// ]),
SizedBox(height: 20),
Column(
children: generateRows(),
),
SizedBox(height: 20),
Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
if (gmcFamily_floater_Status ==
'1')
Container(), // Placeholder container when family_floater is "0"
if (gmcFamily_floater_Status ==
'0' &&
gmcAdditionalText ==
1)
Expanded(
flex: 6,
child: Container(
alignment: Alignment
.centerRight,
child:
const Column(
children: [
Text(
'An additional premium of ₹ 30,000/- will be deducted from your ',
style:
TextStyle(
color: Color(
0xFFEE0000), // Set the color of the text
fontSize:
14, // Adjust the font size as needed
fontWeight:
FontWeight.w400, // Adjust the font weight as needed
fontFamily:
'Poppins',
),
),
Text(
'salary towards increased group medical coverage',
style:
TextStyle(
color: Color(
0xFFEE0000), // Set the color of the text
fontSize:
14, // Adjust the font size as needed
fontWeight:
FontWeight.w400, // Adjust the font weight as needed
fontFamily:
'Poppins',
),
)
],
),
)),
]),
SizedBox(height: 16),
Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
Container(
child: ElevatedButton(
onPressed: () {
sendGmcDataToAPI();
},
child: Text(
'Update',
style: TextStyle(
color: Colors
.white),
),
style: ElevatedButton
.styleFrom(
backgroundColor: Color(
0xFFE26728), // Set background color
shape:
RoundedRectangleBorder(
borderRadius:
BorderRadius
.circular(
5), // Set border radius
),
),
),
),
],
),
],
)))),
],
),
),
),
),
),
)),
]),
),
],
),
),
);
}
List<Widget> generateRows() {
List<Widget> rows = [];
for (var floater in gmcfamily_floaters) {
String floaterKey = floater['family_floater_key'];
String floaterName = floater['name'];
String siAmountFromDB = floater['basic_cover_si'] ?? 'null';
String basicCoverSI = floater['basic_cover_si'] ?? '';
rows.add(
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
flex: 6,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'$floaterKey: $floaterName', // Function to get label text dynamically
style: TextStyle(
color: Color(0xFF181818),
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
],
),
),
SizedBox(width: 15),
if (gmcFamily_floater_Status == '1')
Container(), // Placeholder container when family_floater is "0"
if (gmcFamily_floater_Status == '0')
Expanded(
flex: 6,
child: DropdownButtonFormField<String>(
onChanged: (value) {
setState(() {
selectedSI[floaterKey] = value;
});
},
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: siAmountFromDB,
// labelText: 'Sum Insured',
contentPadding:
EdgeInsets.symmetric(vertical: 5, horizontal: 5),
),
value: selectedSI[floaterKey],
// value: basicCoverSI.isNotEmpty &&
// gmcSlabRates.any(
// (rate) => rate['si'].toString() == basicCoverSI)
// ? basicCoverSI
// : null, // Use selected value for this floater key
items: gmcSlabRates.map<DropdownMenuItem<String>>((rate) {
return DropdownMenuItem<String>(
value: rate['si'].toString(),
child: Text(rate['si'].toString() +
"(" +
rate['additional_premium'].toString() +
")"), // Display SI value as text
);
}).toList(),
),
)
],
),
);
// Add SizedBox below each row
rows.add(SizedBox(height: 20));
}
return rows;
}
Widget buildFamilyMemberForm(int index) {
return Container(
margin: EdgeInsets.only(bottom: 16),
child: Card(
color: Colors.white,
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
flex: 6,
child: DropdownButtonFormField<String>(
value: familyMembers[index].relationship.isNotEmpty
? familyMembers[index].relationship
: null,
onChanged: (value) {
setState(() {
if (familyMembers.isNotEmpty) {
familyMembers[index].relationship = value ?? '';
}
});
},
items: relationshipOptions
.map((relationship) => DropdownMenuItem<String>(
value: relationship,
child: Text(relationship),
))
.toList(),
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Relationship',
labelText: 'Relationship',
contentPadding:
EdgeInsets.symmetric(vertical: 10, horizontal: 15),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Relationship is required';
}
return null;
},
),
),
SizedBox(width: 16),
Expanded(
flex: 6,
child: Align(
alignment: Alignment.centerRight,
child: SizedBox(
width: 180, // Set the desired width
child: TextButton(
onPressed: () => removeFamilyMember(index),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(
Icons.person_remove,
color: Color(
0xFF00989E), // Set the color of the icon
),
SizedBox(
width: 8), // Add space between icon and text
Text(
'Remove Member',
style: TextStyle(
color: Color(
0xFF00989E), // Set the color of the text
),
)
],
),
),
),
),
),
],
),
SizedBox(height: 16),
Row(
children: [
Expanded(
child: TextFormField(
initialValue: familyMembers[index].dob,
onChanged: (value) => familyMembers[index].dob = value,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'DD-MM-YYYY',
labelText: 'Date of Birth',
contentPadding:
EdgeInsets.symmetric(vertical: 10, horizontal: 15),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Date of Birth is required';
}
return null;
},
),
),
SizedBox(width: 16),
Expanded(
child: TextFormField(
initialValue: familyMembers[index].fullName,
onChanged: (value) =>
familyMembers[index].fullName = value,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Full Name',
labelText: 'Full Name',
contentPadding:
EdgeInsets.symmetric(vertical: 10, horizontal: 15),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Full Name is required';
}
return null;
},
),
),
],
),
],
),
),
),
);
}
}
class FamilyMember {
String relationship;
String fullName;
String dob;
FamilyMember(
{required this.relationship, required this.fullName, required this.dob});
// Convert FamilyMember object to JSON format
Map<String, dynamic> toJson() {
return {
'relationship': relationship,
'fullName': fullName,
'dob': dob,
};
}
}