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 createState() => _MyAppState(); } class _MyAppState extends State { // Sample list of items final List items = [ 'Personal Details', 'Family Members', 'Policies', // 'Log Out', ]; // Sample list of icons corresponding to each item final List 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 dataPolicy = []; final GlobalKey _formKey = GlobalKey(); 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 familyMembers = []; List 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 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 _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? 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 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 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) .where((obj) => obj['relationship'] != 'Self') .toList(); nonSelfObjectsArrayDetails = nonSelfObjects; logDebug(nonSelfObjectsArrayDetails); List familyMembersFromDetails = nonSelfObjects.map((detail) { return FamilyMember( relationship: detail['relationship'] ?? '', fullName: detail['name'] ?? '', dob: detail['dob'] ?? '', ); }).toList(); setState(() { familyMembers = familyMembersFromDetails; }); // Find the Self object Map? 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 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 data = json.decode(response.body); if (data['status'] == 'success') { // Ensure that data is not null and contains 'data' key dataPolicy = List>.from( data['data']); // Assuming data is a List List> gpaPolicies = []; // Adjust type to dynamic List> gmcPolicies = []; // Adjust type to dynamic for (var policy in dataPolicy) { var gridMaster = policy['GridMaster'] as Map?; // 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); // Adjust type to dynamic } else if (policyType == 'GMC') { gmcPolicies.add( policy as Map); // 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? 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? 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? 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? 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 updateUserDetails() async { // Validate the form before submitting if (_formKey.currentState!.validate()) { // Prepare the request body List> 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 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 data = jsonDecode(response.body)['data']; final List relationships = List.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> 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> updatedNewData = List>.generate(membersData.length, (index) { Map 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 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 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> 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 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 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? getEmpDetails = ModalRoute.of(context)?.settings.arguments as Map?; 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( 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( 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 generateRows() { List 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( 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>((rate) { return DropdownMenuItem( 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( value: familyMembers[index].relationship.isNotEmpty ? familyMembers[index].relationship : null, onChanged: (value) { setState(() { if (familyMembers.isNotEmpty) { familyMembers[index].relationship = value ?? ''; } }); }, items: relationshipOptions .map((relationship) => DropdownMenuItem( 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 toJson() { return { 'relationship': relationship, 'fullName': fullName, 'dob': dob, }; } }