2146 lines
110 KiB
Dart
Executable File
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,
|
|
};
|
|
}
|
|
}
|