nhance_partner/lib/presentation/screens/Enquiry/enquiry/updateEndorsementDialog.dart
2026-04-03 15:04:34 +05:30

913 lines
32 KiB
Dart

import 'package:dropdown_search/dropdown_search.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:http/http.dart' as ref;
import 'package:toastification/toastification.dart';
import '../../../../core/config/env.dart';
import '../../../../core/services/api_service.dart';
import '../../../../data/services/auth_service.dart';
import '../../../../data/utils/toastNotification.dart';
import '../../../../data/utils/validators.dart';
import '../../../layouts/responsive_layout.dart';
import '../../../themes/indicators/customizd_file_upload.dart';
import '../../../themes/indicators/input_field_decoration.dart';
import '../../../themes/indicators/search_field_theme.dart';
import '../../../themes/indicators/text_field_theme.dart';
import '../../../providers/manager_provider.dart';
final decimalFormatter = [
FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d{0,2}$')),
];
class UpdateEndorsementDialog extends StatefulWidget {
final Map<String, dynamic> item;
final dynamic userId;
final dynamic managerId;
final Function(String) onSubmit;
const UpdateEndorsementDialog({
super.key,
required this.item,
required this.userId,
required this.managerId,
required this.onSubmit,
});
@override
State<UpdateEndorsementDialog> createState() => _UpdateEndorsementDialogState();
}
class _UpdateEndorsementDialogState extends State<UpdateEndorsementDialog> {
late ApiService apiService;
String? _token;
final _formKeyUpdate = GlobalKey<FormState>();
Map<String, TextEditingController> controllers = {};
List<Map<String, dynamic>> getEndrosmentType = [];
List<Map<String, dynamic>> filteredEndrosmentData = [];
String? selectedEndorsement;
String? selectedPolicyFrom;
String? selectedStatus; // "Pending" or "Completed"
String? selectedFinancialStatus;
String? selectedFileNames;
bool isLoading = false;
PlatformFile? docUploadedFile;
final List<Map<String, dynamic>> statusOptions = [
{"status_value": "Open"},
{"status_value": "Pending"},
{"status_value": "Completed"},
];
final List<Map<String, dynamic>> policyFromOptions = [
{"policy_from": "Internal"},
{"policy_from": "External"},
];
final List<Map<String, dynamic>> financialOptions = [
{ "financial_value": "Yes"},
{ "financial_value": "No"},
];
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
dropDownKeyEndorsement =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
@override
void initState() {
apiService = ApiService();
super.initState();
_initializeToken();
print("secondpage");
// 1. Initialize Controllers
controllers['endorsement_no'] = TextEditingController(text: widget.item['endorsement_no']);
controllers['remarks'] = TextEditingController(text: widget.item['endorsement_description']);
controllers['contact_person'] = TextEditingController(text: widget.item['contact_person']);
controllers['endorsement_premium'] = TextEditingController(text: widget.item['endorsement_premium']);
controllers['pending_days'] = TextEditingController(text: widget.item['pending_days']);
selectedEndorsement = widget.item['endorsement_type']?.toString();
selectedStatus = widget.item['status']?.toString();
selectedFinancialStatus = widget.item['financia_or_non_financial']?.toString();
selectedFileNames = widget.item['endorsement_completion_file'];
getEnroementType();
}
Future<void> _initializeToken() async {
_token = await AuthService.getToken();
print("APISERTOKEN - $_token");
}
// API Call logic
// Future<void> updateData() async {
// if (!_formKeyUpdate.currentState!.validate()) return;
//
// // VALIDATION: If Status is Completed, File is Mandatory
// if (selectedStatus == "Completed" && docUploadedFile == null) {
// ToastHelper.showErrorToast(context,"Document is required for Completed status",);
// return;
// }
//
//
// setState(() => isLoading = true);
//
// try {
// final Uri uri = Uri.parse('${Env.apiUrl}endorsement/updateEndorsement');
//
// if (_token == null) {
// throw Exception('Token not found. Please log in.');
// }
//
// // Use MultipartRequest (POST only)
// final request = http.MultipartRequest('POST', uri);
// request.headers['Authorization'] = 'Bearer $_token';
// request.headers['app-signature'] = Env.App_Signature;
//
// // Mapping fields to API Table
// request.fields['endorsement_type'] = selectedEndorsement ?? "";
// request.fields['endorsement_description'] = controllers['remarks']?.text ?? "";
// request.fields['endorsement_no'] = widget.item['endorsement_no'] ?? "";
// // request.fields['updated_by'] = userId;
// request.fields['status'] = selectedStatus ?? "";
//
// if (docUploadedFile != null) {
// try {
// if (docUploadedFile!.bytes != null) {
// final multipartFile = http.MultipartFile.fromBytes(
// 'endorsement_completion_file',
// docUploadedFile!.bytes!,
// filename: docUploadedFile!.name,
// );
// request.files.add(multipartFile);
// }
//
// print("📎 File attached: ${docUploadedFile!.name}");
// } catch (e) {
// print("❌ Failed to attach file: $e");
// }
// }
//
// final response = await request.send();
// if (response.statusCode == 200) {
// ToastHelper.showSuccessToast(context, 'Updated Successfully');
// Navigator.pop(context);
// widget.onSubmit("success");
// }
// } catch (e) {
// print("Error: $e");
// } finally {
// setState(() => isLoading = false);
// }
// }
Future<void> updateData() async {
// 1. Basic Form Validation
if (!_formKeyUpdate.currentState!.validate()) return;
// 2. Business Validation: File mandatory for 'Completed' status
if (selectedStatus == "Completed" && docUploadedFile == null) {
ToastHelper.showErrorToast(context, "Document is required for Completed status");
return;
}
setState(() => isLoading = true);
try {
final Uri uri = Uri.parse('${Env.apiUrl}endorsement/updateEndorsement');
// final Uri uri = Uri.parse('http://localhost/nhance_partner_be/endorsement/updateEndorsement');
if (_token == null) throw Exception('Token not found. Please log in.');
// Create Multipart Request
final request = http.MultipartRequest('POST', uri);
request.headers['Authorization'] = 'Bearer $_token';
request.headers['app-signature'] = Env.App_Signature;
// --- MAPPING FIELDS ---
// Use widget.item['id'] to identify the unique record
request.fields['id'] = widget.item['id'].toString();
request.fields['endorsement_type'] = selectedEndorsement ?? "";
request.fields['endorsement_description'] = controllers['remarks']?.text ?? "";
request.fields['endorsement_no'] = controllers['endorsement_no']?.text ?? "";
request.fields['contact_person'] = controllers['contact_person']?.text ?? "";
request.fields['endorsement_premium'] = controllers['endorsement_premium']?.text ?? "";
request.fields['pending_days'] = controllers['pending_days']?.text ?? "";
// Set updated_by from the widget parameter
request.fields['updated_by'] = widget.userId.toString();
request.fields['status'] = selectedStatus ?? "";
request.fields['financia_or_non_financial'] = selectedFinancialStatus ?? "";
// --- FILE UPLOAD LOGIC ---
if (docUploadedFile != null) {
if (docUploadedFile!.bytes != null) {
// For Web/Bytes
request.files.add(http.MultipartFile.fromBytes(
'endorsement_completion_file', // Key must match Backend
docUploadedFile!.bytes!,
filename: docUploadedFile!.name,
));
} else if (docUploadedFile!.path != null) {
// For Mobile/Desktop path
request.files.add(await http.MultipartFile.fromPath(
'endorsement_completion_file',
docUploadedFile!.path!,
filename: docUploadedFile!.name,
));
}
print("📎 Attached: ${docUploadedFile!.name}");
}
// 3. Send Request
final response = await request.send();
final responseData = await http.Response.fromStream(response);
if (response.statusCode == 200) {
ToastHelper.showSuccessToast(context, 'Updated Successfully');
Navigator.pop(context);
widget.onSubmit("success");
} else {
print("Server Error: ${responseData.body}");
ToastHelper.showErrorToast(context, "Update failed: ${response.statusCode}");
}
} catch (e) {
print("Error during update: $e");
ToastHelper.showErrorToast(context, "An error occurred");
} finally {
setState(() => isLoading = false);
}
}
@override
Widget build(BuildContext context) {
return SelectionArea(
child: AlertDialog(
backgroundColor: Colors.white,
// Add shape for a cleaner look
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
content: SizedBox(
// Set a width to prevent layout jumping
width: MediaQuery.of(context).size.width * 0.6,
child: SingleChildScrollView( // 👈 Fix 1: Prevent Overflow
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Header row
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Update Endorsement",
style: GoogleFonts.inter(
color: const Color(0xFF374141),
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
GestureDetector(
onTap: () => Navigator.pop(context),
child: Container(
padding: const EdgeInsets.all(5.0),
decoration: BoxDecoration(
color: const Color(0xFFF1F1F1),
borderRadius: BorderRadius.circular(5.0),
),
child: const Tooltip(
message: 'Close',
child: Icon(Icons.close, size: 18),
),
),
),
],
),
const SizedBox(height: 16),
// Your form content
endorsement(context),
],
),
),
),
actions: [
GestureDetector(
onTap: () {
// 👈 Fix 2: Remove "onPressed:" label. Just call the function.
updateData();
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 25.0, vertical: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: const Color(0xFF425B5B),
),
child: isLoading
? const SizedBox(height: 15, width: 15, child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2))
: const Text('Save', style: TextStyle(color: Colors.white)),
),
),
],
) );
}
Widget endorsement(BuildContext context) {
return Form(
key: _formKeyUpdate,
child: Column(
children: [
Row(
children: [
// Wrap children in Expanded so they know how much space to take in the Row
Expanded(child: buildEndrosType(context)),
const SizedBox(width: 15),
Expanded(child: buildStatusDropdown(context)),
],
),
const SizedBox(height: 10),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(child: buildPolicyNumber(context)),
const SizedBox(width: 15),
Expanded(child: buildUploadDocumentEndorsment(context)),
],
),
const SizedBox(height: 10),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(child: buildContactPerson(context)),
const SizedBox(width: 15),
Expanded(child: buildFinancialOrNonFinancial(context)),
],
),
const SizedBox(height: 10),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(child: buildEndPremium(context)),
const SizedBox(width: 15),
Expanded(child: buildPendingDays(context)),
],
),
const SizedBox(height: 10),
Row(
children: [
Expanded(child: buildEndrosRemarks(context)),
const SizedBox(width: 15),
const Spacer(), // Keeps the remark field to the left
],
),
],
),
);
}
Future<void> getEnroementType() async {
print('Insurers called');
setState(() {
isLoading = true;
});
try {
final response = await apiService.fetchMasterDropDown('Endorsement');
if (response['status'] == 200) {
print('getEnroementType - ${response['data']}');
setState(() {
getEndrosmentType = List<Map<String, dynamic>>.from(response['data']);
print('API Data - $getEndrosmentType');
filteredEndrosmentData = List.from(getEndrosmentType);
print('originalData - $filteredEndrosmentData');
});
} else {
getEndrosmentType = [];
filteredEndrosmentData = [];
}
} catch (e) {
print('Exception occurred: $e');
} finally {
setState(() {
isLoading = false;
});
}
}
// --- Specialized Widgets ---
Widget buildEndrosType(context) {
Map<String, dynamic>? selectedEndorsementd = filteredEndrosmentData
.firstWhere(
(item) => item['id'].toString() == selectedEndorsement,
orElse: () => {},
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Endorsement Type *", style: _textStyle),
SizedBox(height: 10),
Container(
color: Colors.white,
width: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
// height: 40,
child: DropdownSearch<Map<String, dynamic>>(
key: dropDownKeyEndorsement,
selectedItem: selectedEndorsementd.isNotEmpty
? selectedEndorsementd
: null,
items: (filter, infiniteScrollProps) {
return filteredEndrosmentData;
},
itemAsString: (val) =>
val['endorsement_type'].toString(), // what to show
compareFn: (item, selectedItem) =>
item['id'] == selectedItem['id'], // ✅ compare by id
validator: (val) {
if (val == null) {
return "Required"; // ✅ error message
}
return null;
},
decoratorProps: DropDownDecoratorProps(
decoration:
AppInputDecorations.dropdownDecoration(
label: "Select Endorsement Type",
).copyWith(
filled: true,
fillColor: Color( 0xFFEDF6F5,), // 👈 makes the dropdown input white
isDense: true, // 👈 Makes the field compact
contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 0), // 👈 Vertical 0 helps center the text
),
),
popupProps: PopupProps.menu(
fit: FlexFit.loose,
constraints: BoxConstraints(maxHeight: 250),
menuProps: MenuProps(
backgroundColor:
Colors.white, // 👈 sets dropdown background to white
),
showSearchBox: true,
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
hintText: "Search Endorsement Type...",
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
), // 👈 Normal border
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
width: 1.5,
), // 👈 Focused border
),
),
),
// constraints: BoxConstraints(),
),
onChanged: (val) {
if (val != null) {
print("Selected Endorsement : ${val['endorsement_type']}");
print("Id: ${val['id']}");
selectedEndorsement = val['id'];
// controllers['agentId']?.text = val['agent_code'];
// agentId = agent['id'];
}
},
),
),
],
);
}
Widget buildPolicyNumber(context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Endorsement Number *", style: _textStyle),
SizedBox(height: 10),
ThemedFormField(
backgroundColor: Color(0xFFEDF6F5),
controller: controllers['endorsement_no']!,
validator: (value) => Validators.requiredField(value, "endorsement_no"),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9\-_]')),
],
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
// keyboardType: TextInputType.multiline,
// txtheight: 45,
),
],
);
}
Widget buildStatusDropdown(context) {
// Find the selected item from the static list based on your variable
Map<String, dynamic> selectedEndorsementST = statusOptions.firstWhere(
(item) => item['status_value'].toString() == selectedStatus,
orElse: () => {},
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Status *", style: _textStyle),
const SizedBox(height: 10),
Container(
color: Colors.white,
width: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
child: DropdownSearch<Map<String, dynamic>>(
// Use a unique key for this dropdown
key: const ValueKey("statusDropdown"),
selectedItem: selectedEndorsementST.isNotEmpty
? selectedEndorsementST
: null,
items: (filter, infiniteScrollProps) {
return statusOptions; // Use the static list
},
itemAsString: (val) => val['status_value'].toString(),
compareFn: (item, selectedItem) =>
item['status_value'] == selectedItem['status_value'],
// --- REQUIRED VALIDATOR ---
validator: (val) {
if (val == null || val.isEmpty) {
return "Required";
}
return null;
},
decoratorProps: DropDownDecoratorProps(
decoration: AppInputDecorations.dropdownDecoration(
label: "Select Status",
).copyWith(
filled: true,
fillColor: Color( 0xFFEDF6F5,), // 👈 makes the dropdown input white
isDense: true, // 👈 Makes the field compact
contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 0), // 👈 Vertical 0 helps center the text
),
),
popupProps: PopupProps.menu(
fit: FlexFit.loose,
constraints: const BoxConstraints(maxHeight: 150), // Shorter for 2 items
menuProps: const MenuProps(
backgroundColor: Colors.white,
),
showSearchBox: true, // Disabled search as there are only 2 items
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
hintText: "Search Status...",
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
), // 👈 Normal border
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
width: 1.5,
), // 👈 Focused border
),
),
),
),
onChanged: (val) {
if (val != null) {
setState(() {
print("Selected Status: ${val['status_value']}");
selectedStatus = val['status_value'];
});
}
},
),
),
],
);
}
Widget buildEndrosRemarks(context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Remarks *", style: _textStyle),
SizedBox(height: 10),
ThemedFormField(
backgroundColor: Color(0xFFEDF6F5),
controller: controllers['remarks']!,
validator: (value) => Validators.requiredField(value, "remarks"),
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
// keyboardType: TextInputType.multiline,
// txtheight: 45,
),
],
);
}
Widget buildUploadDocumentEndorsment(context) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Upload Document", style: _textStyle),
SizedBox(height: 10),
ThemedUploadField(
backgroundColor: Color(0xFFEDF6F5),
hintText: selectedFileNames ?? "Upload Document",
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
onFileSelected: (fileName, file) {
setState(() {
docUploadedFile = file; // This 'file' is a PlatformFile
});
},
),
// Column(
// mainAxisAlignment: MainAxisAlignment.end,
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// ThemedUploadField(
// hintText: selectedFileNames ?? "Upload Document",
// txtwidth: MediaQuery.of(context).size.width * 0.26,
// onFileSelected: (fileName, file) {
// print("Picked file: $fileName (${file.size} bytes)");
// setState(() {
// docUploadedEndorsFile = file;
// });
// },
// ),
// // const SizedBox(height: 5),
// //
// // if (docUploadedFile != null || passportEndorsFileUrlFromApi != null)
// // Container(
// // // color: Colors.white,
// // child: Row(
// // children: [
// //
// // GestureDetector(
// // onTap: () => apiService.downloadFile(
// // apiUrl:
// // 'agent/downloadAgentCertificateFile?agent_id=$selectedEndorsId',
// // apiId: selectedEndorsId,
// // localFile: docUploadedFile,
// // fileName: selectedFileNames,
// // ),
// // child: Container(
// // padding: const EdgeInsets.all(5),
// // decoration: BoxDecoration(
// // borderRadius: BorderRadius.circular(5),
// // color: Color(0xFF425B5B),
// // // color: Colors.green.shade300,
// // ),
// // child: Row(
// // children: const [
// // Text(
// // "Download",
// // style: TextStyle(
// // fontSize: 12,
// // fontWeight: FontWeight.w200,
// // color: Colors.white,
// // ),
// // ),
// // SizedBox(width: 5),
// // Icon(Icons.download, size: 13, color: Colors.white),
// // ],
// // ),
// // ),
// // ),
// // ],
// // ),
// // ),
// ],
// ),
],
);
}
Widget buildContactPerson(context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Contact Person *", style: _textStyle),
SizedBox(height: 10),
ThemedFormField(
backgroundColor: Color(0xFFEDF6F5),
controller: controllers['contact_person']!,
validator: (value) => Validators.requiredField(value, "contact_person"),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z]')),
],
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
// keyboardType: TextInputType.multiline,
// txtheight: 45,
),
],
);
}
Widget buildEndPremium(context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("End Premium *", style: _textStyle),
SizedBox(height: 10),
ThemedFormField(
backgroundColor: Color(0xFFEDF6F5),
controller: controllers['endorsement_premium']!,
validator: (value) => Validators.requiredField(value, "endorsement_premium"),
keyboardType: const TextInputType.numberWithOptions(decimal: true),
/*
* Allow decimal amount (e.g. 6000.00).
* Integer-only formatter was removing "." and corrupting value.
*/
inputFormatters: decimalFormatter,
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
),
],
);
}
Widget buildPendingDays(context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Pending Days *", style: _textStyle),
SizedBox(height: 10),
ThemedFormField(
backgroundColor: Color(0xFFEDF6F5),
controller: controllers['pending_days']!,
validator: (value) => Validators.requiredField(value, "pending_days"),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
],
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
// keyboardType: TextInputType.multiline,
// txtheight: 45,
),
],
);
}
Widget buildFinancialOrNonFinancial(context) {
Map<String, dynamic> selectedEndorsementFNF = financialOptions.firstWhere(
(item) => item['financial_value'].toString() == selectedFinancialStatus,
orElse: () => {},
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Financial Status *", style: _textStyle),
const SizedBox(height: 10),
Container(
color: Colors.white,
width: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
child: DropdownSearch<Map<String, dynamic>>(
// Use a unique key for this dropdown
key: const ValueKey("FinancialstatusDropdown"),
selectedItem: selectedEndorsementFNF.isNotEmpty
? selectedEndorsementFNF
: null,
items: (filter, infiniteScrollProps) {
return financialOptions; // Use the static list
},
itemAsString: (val) => val['financial_value'].toString(),
compareFn: (item, selectedItem) =>
item['financial_value'] == selectedItem['financial_value'],
// --- REQUIRED VALIDATOR ---
validator: (val) {
if (val == null || val.isEmpty) {
return "Required";
}
return null;
},
decoratorProps: DropDownDecoratorProps(
decoration: AppInputDecorations.dropdownDecoration(
label: "Select Financial Status",
).copyWith(
filled: true,
fillColor: Color( 0xFFEDF6F5,), // 👈 makes the dropdown input white
isDense: true, // 👈 Makes the field compact
contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 0), // 👈 Vertical 0 helps center the text
),
),
popupProps: PopupProps.menu(
fit: FlexFit.loose,
constraints: const BoxConstraints(maxHeight: 150), // Shorter for 2 items
menuProps: const MenuProps(
backgroundColor: Colors.white,
),
showSearchBox: true, // Disabled search as there are only 2 items
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
hintText: "Search Financial Status...",
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
), // 👈 Normal border
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
width: 1.5,
), // 👈 Focused border
),
),
),
),
onChanged: (val) {
if (val != null) {
setState(() {
print("Selected Financial Status: ${val['financial_value']}");
selectedFinancialStatus = val['financial_value'];
});
}
},
),
),
],
);
}
static final TextStyle _textStyle = TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
);
static final TextStyle _textStyle1 = TextStyle(
fontSize: 9,
fontWeight: FontWeight.w400,
);
static final _dataBold = GoogleFonts.inter(
fontSize: 11,
fontWeight: FontWeight.w400,
color: Color(0xFF000000),
);
static final _dataSub = GoogleFonts.inter(
fontSize: 10,
fontWeight: FontWeight.w300,
color: Color(0xFF585757),
);
static final _headerStyle = GoogleFonts.poppins(
fontSize: 11.2,
fontWeight: FontWeight.w500,
color: Color(0xFF1E293B),
);
static final _cardheaderStyle = GoogleFonts.inter(
color: Colors.black,
fontWeight: FontWeight.w600,
fontSize: 12,
);
static final _cardBodyStyle = GoogleFonts.inter(
color: const Color(0xFF545454),
fontWeight: FontWeight.w400,
fontSize: 12,
);
}