ts-tat/lib/Screens/policy/policyCriteria.dart
2025-07-29 15:24:58 +05:30

2871 lines
145 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:convert';
import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import '../../config/apiUrl.dart';
import '../../services/apiService.dart';
import '../../utils/auth_utils.dart';
import '../../widgets/custom_text_field.dart';
import '../../widgets/custom_user_form.dart';
class PolicyCriteria extends StatefulWidget {
bool isDesktop;
String selectedService;
final ValueNotifier<String> selectedTabNotifier;
final ValueNotifier<String> selectedIdNotifier;
String? userId;
bool isClass = true;
bool isCost = true;
final List<int> serviceDBValueList;
final Function(List<Map<String, dynamic>>?) onPolicyDataChanged;
PolicyCriteria({
super.key,
required this.isDesktop,
required this.selectedService,
required this.selectedTabNotifier,
required this.selectedIdNotifier,
required this.userId,
required this.isClass,
required this.isCost,
required this.onPolicyDataChanged,
required this.serviceDBValueList,
});
@override
PolicyCriteriaState createState() => PolicyCriteriaState();
}
class PolicyCriteriaState extends State<PolicyCriteria> {
String? ServiceId;// = "1";
String? ServiceIndxId = "1";
String? orgId;
String? userId;
Map<String, dynamic>? apiDataForClass;
bool isLoading = true;
// final TextEditingController _costController = TextEditingController();
// final TextEditingController _classController = TextEditingController();
// String? FirstApproverAction;
// String? SecondApproverAction;
// String? ThirdApproverAction;
// String? SelectedParallelProcess = "3";
final ApiService apiService = ApiService();
Map<String, TextEditingController> costController = {};
// Map<String, TextEditingController> classController = {};
Map<String, String?> classAction = {};
Map<String, String?> FirstApproverAction = {};
Map<String, String?> SecondApproverAction = {};
Map<String, String?> ThirdApproverAction = {};
Map<String, String?> SelectedParallelProcess = {};
Map<String, String?> FirstExceptionalApproverAction = {};
Map<String, String?> SecondExceptionalApproverAction = {};
Map<String, String?> ThirdExceptionalApproverAction = {};
Map<String, String?> FourthExceptionalApproverAction = {};
Map<String, String?> SelectedParallelExceptionalProcess = {};
Map<String, String?> FirstAmendApproverAction = {};
Map<String, String?> SecondAmendApproverAction = {};
Map<String, String?> ThirdAmendApproverAction = {};
Map<String, String?> FourthAmendApproverAction = {};
Map<String, String?> SelectedParallelAmendProcess = {};
Map<String, String> policyDetailsIdMap = {}; // new
Map<String, String> policyIdMap = {}; // new
Map<String, String> validationErrors = {};
// bool isClass = true;
// bool isCost = true;
List<Map<String, dynamic>>? policyData = [];
// Map<String, dynamic> get policyServices {
// Map<String, dynamic> data = {
// "service_id": ServiceId,
// "cost": costController[ServiceId]?.text,
// "class": classController[ServiceId]?.text,
// "a1_action": FirstApproverAction[ServiceId],
// "a2_action": SecondApproverAction[ServiceId],
// "a3_action": ThirdApproverAction[ServiceId],
// "parallel_process_from": SelectedParallelProcess[ServiceId],
// "created_by": widget.userId
// };
// return data;
// }
@override
void initState() {
super.initState();
fetchTrainFlightClass();
print("whole value here - ${widget.serviceDBValueList}");
print(widget.serviceDBValueList);
fieldForPolicy();
widget.selectedIdNotifier.addListener(() {
setState(() {
ServiceId = widget.selectedIdNotifier.value ?? "1";
print("new :) ${widget.selectedIdNotifier.value}");
print("ServiceIndxId changed: $ServiceId");
});
});
widget.selectedTabNotifier.addListener(() {
print("selectedTab changed: ${widget.selectedTabNotifier.value}");
setState(() {
ServiceIndxId = widget.selectedTabNotifier.value ?? "1";
// ServiceId = widget.selectedIdNotifier.value ?? "1";
print("ServiceIndxId changed: $ServiceIndxId");
});
fieldForPolicy();
// fetchTrainFlightClass(); // old here
});
}
void loadinitializeData() async {
orgId = await getOrgId();
userId = await getUserId();
}
// void saveCurrentPolicy(List<Map<String, dynamic>> services) {
// print("saveCurrentPolicy- $services");
// if (ServiceId != null) {
// print("Saving curremt Add or Update");
// addOrUpdatePolicy(ServiceId!);
// }
// }
void saveCurrentPolicy(List<Map<String, dynamic>> services) {
print("saveCurrentPolicy- $services");
// Step 1: Save currently selected policy first (if not already saved)
if (ServiceId != null) {
print("Saving current Add or Update");
addOrUpdatePolicy(ServiceId!);
}
// Step 2: Collect existing service_ids from policyData
final existingServiceIds =
policyData?.map((e) => e['service_id'].toString()).toSet();
// Step 3: Loop through all service definitions
for (var service in services) {
String id = service['service_id'].toString();
print("164 service == $id");
// Skip if already present
if (existingServiceIds!.contains(id)) continue;
// Step 4: Initialize any missing controllers or data
costController.putIfAbsent(id, () => TextEditingController());
classAction.putIfAbsent(id, () => "1"); // working fine
FirstApproverAction.putIfAbsent(id, () => "None");
SecondApproverAction.putIfAbsent(id, () => "None");
ThirdApproverAction.putIfAbsent(id, () => "None");
SelectedParallelProcess.putIfAbsent(id, () => "3");
FirstExceptionalApproverAction.putIfAbsent(id, () => "None");
SecondExceptionalApproverAction.putIfAbsent(id, () => "None");
ThirdExceptionalApproverAction.putIfAbsent(id, () => "None");
FourthExceptionalApproverAction.putIfAbsent(id, () => "None");
SelectedParallelExceptionalProcess.putIfAbsent(id, () => "4");
FirstAmendApproverAction.putIfAbsent(id, () => "None");
SecondAmendApproverAction.putIfAbsent(id, () => "None");
ThirdAmendApproverAction.putIfAbsent(id, () => "None");
FourthAmendApproverAction.putIfAbsent(id, () => "None");
SelectedParallelAmendProcess.putIfAbsent(id, () => "4");
// Step 5: Add default policy entry
policyData?.add({
"service_id": int.parse(id),
"cost": "",
"class": classAction[id], // working fine
"a1_action": FirstApproverAction[id],
"a2_action": SecondApproverAction[id],
"a3_action": ThirdApproverAction[id],
"parallel_process_from": SelectedParallelProcess[id],
"a1_exceptional_action": FirstExceptionalApproverAction[id],
"a2_exceptional_action": SecondExceptionalApproverAction[id],
"a3_exceptional_action": ThirdExceptionalApproverAction[id],
"a4_exceptional_action": FourthExceptionalApproverAction[id],
"exceptional_parallel_process_from":
SelectedParallelExceptionalProcess[id],
"a1_amendment_action": FirstAmendApproverAction[id],
"a2_amendment_action": SecondAmendApproverAction[id],
"a3_amendment_action": ThirdAmendApproverAction[id],
"a4_amendment_action": FourthAmendApproverAction[id],
"amendment_parallel_process_from": SelectedParallelAmendProcess[id],
"created_by": widget.userId,
});
}
// Step 6: Emit updated policy data
widget.onPolicyDataChanged(policyData);
}
// To set the data (update)
void loadPolicyDetails(List<Map<String, dynamic>> details) {
print("loadPolicyDetails");
for (var item in details) {
final serviceId = item['service_id'].toString();
costController[serviceId] = TextEditingController(
text: item['cost'] ?? '',
);
// classAction[serviceId] = classAction[serviceId]?.toString();
classAction[serviceId] = item['class']?.toString() ?? ''; // working fine
FirstApproverAction[serviceId] = item['a1_action']?.toString();
SecondApproverAction[serviceId] = item['a2_action']?.toString();
ThirdApproverAction[serviceId] = item['a3_action']?.toString();
SelectedParallelProcess[serviceId] =
item['parallel_process_from']?.toString() ?? "3";
FirstExceptionalApproverAction[serviceId] =
item['a1_exceptional_action']?.toString();
SecondExceptionalApproverAction[serviceId] =
item['a2_exceptional_action']?.toString();
ThirdExceptionalApproverAction[serviceId] =
item['a3_exceptional_action']?.toString();
FourthExceptionalApproverAction[serviceId] =
item['a4_exceptional_action']?.toString();
SelectedParallelExceptionalProcess[serviceId] =
item['exceptional_parallel_process_from']?.toString() ?? "3";
FirstAmendApproverAction[serviceId] =
item['a1_amendment_action']?.toString();
SecondAmendApproverAction[serviceId] =
item['a2_amendment_action']?.toString();
ThirdAmendApproverAction[serviceId] =
item['a3_amendment_action']?.toString();
FourthAmendApproverAction[serviceId] =
item['a4_amendment_action']?.toString();
SelectedParallelAmendProcess[serviceId] =
item['amendment_parallel_process_from']?.toString() ?? "4";
if (item['policy_details_id'] != null) {
policyDetailsIdMap[serviceId] = item['policy_details_id'].toString();
}
if (item['policy_id'] != null) {
policyIdMap[serviceId] = item['policy_id'].toString();
}
}
policyData = details;
widget.onPolicyDataChanged(policyData);
if (details.isNotEmpty) {
final firstServiceId = details.first['service_id'].toString();
print('First Service ID is: $firstServiceId');
// firstServiceId == "1"
// ? fetchTrainFlightClass(1)
// : fetchTrainFlightClass(2);
}
setState(() {});
print("detailsdetails- $details");
}
void addOrUpdatePolicy(String serviceId) {
print("addOrUpdatePolicyserviceId - $serviceId");
// 1. First, find existing item if any
final existingIndex = policyData!.indexWhere(
(item) => item["service_id"] == serviceId,
);
print(FirstApproverAction);
Map<String, dynamic> data = {
"service_id": serviceId,
"cost": costController[serviceId]?.text,
// "class": classController[serviceId]?.text,
"class": classAction[serviceId] ?? "", // working fine
"a1_action": FirstApproverAction[serviceId],
"a2_action": SecondApproverAction[serviceId],
"a3_action": ThirdApproverAction[serviceId],
"parallel_process_from": SelectedParallelProcess[serviceId],
"a1_exceptional_action": FirstExceptionalApproverAction[serviceId],
"a2_exceptional_action": SecondExceptionalApproverAction[serviceId],
"a3_exceptional_action": ThirdExceptionalApproverAction[serviceId],
"a4_exceptional_action": FourthExceptionalApproverAction[serviceId],
"exceptional_parallel_process_from":
SelectedParallelExceptionalProcess[serviceId],
"a1_amendment_action": FirstAmendApproverAction[serviceId],
"a2_amendment_action": SecondAmendApproverAction[serviceId],
"a3_amendment_action": ThirdAmendApproverAction[serviceId],
"a4_amendment_action": FourthAmendApproverAction[serviceId],
"amendment_parallel_process_from":
SelectedParallelAmendProcess[serviceId],
"created_by": widget.userId,
};
final cost = costController[serviceId]?.text ?? "";
// final travelClass = classController[serviceId]?.text ?? "";
final travelClass = classAction[serviceId]; // working fine
final a1 = FirstApproverAction[serviceId];
final a2 = SecondApproverAction[serviceId];
final a3 = ThirdApproverAction[serviceId];
final ae1 = FirstExceptionalApproverAction[serviceId];
final ae2 = SecondExceptionalApproverAction[serviceId];
final ae3 = ThirdExceptionalApproverAction[serviceId];
final ae4 = FourthExceptionalApproverAction[serviceId];
final aa1 = FirstAmendApproverAction[serviceId];
final aa2 = SecondAmendApproverAction[serviceId];
final aa3 = ThirdAmendApproverAction[serviceId];
final aa4 = FourthAmendApproverAction[serviceId];
// bool hasValue = cost.trim().isNotEmpty;
// bool hasValue = cost.trim().isNotEmpty || travelClass!.isNotEmpty;
bool hasValue =
cost.trim().isNotEmpty || (travelClass?.isNotEmpty ?? false);
bool allActionsNull = a1 == null && a2 == null && a3 == null;
bool someActionsMissing =
[a1, a2, a3].where((a) => a != null).length > 0 &&
[a1, a2, a3].where((a) => a == null).length > 0;
bool allExceptionalActionsNull = ae1 == null && ae2 == null && ae3 == null && ae4 == null;
bool someExceptionalActionsMissing =
[ae1, ae2, ae3, ae4].where((a) => a != null).length > 0 &&
[ae1, ae2, ae3, ae4].where((a) => a == null).length > 0;
bool allAmendActionsNull = aa1 == null && aa2 == null && aa3 == null && aa4 == null;
bool someAmendActionsMissing =
[aa1, aa2, aa3, aa4].where((a) => a != null).length > 0 &&
[aa1, aa2, aa3, aa4].where((a) => a == null).length > 0;
if (someActionsMissing) {
validationErrors[serviceId] = "All 3 approver actions must be selected.";
return;
}
if (someExceptionalActionsMissing) {
validationErrors[serviceId] =
"All 4 exceptional approver actions must be selected.";
return;
}
if (someAmendActionsMissing) {
validationErrors[serviceId] =
"All 4 amendment approver actions must be selected.";
return;
}
if (hasValue &&
allActionsNull &&
allExceptionalActionsNull &&
allAmendActionsNull) {
validationErrors[serviceId] = "Please select all actions.";
return;
} else {
print("HAS VAlue");
}
validationErrors.remove(serviceId);
// 2. ⚡ If updating an existing item, also **keep its IDs**
if (existingIndex != -1) {
final existingItem = policyData![existingIndex];
if (existingItem.containsKey("policy_details_id")) {
data["policy_details_id"] = existingItem["policy_details_id"];
}
if (existingItem.containsKey("policy_id")) {
data["policy_id"] = existingItem["policy_id"];
}
// 3. Now update it
policyData![existingIndex] = data;
print("🔁 Updated policy for ServiceId: $serviceId");
} else {
// 4. Else add as new
policyData!.add(data);
print(" Added policy for ServiceId: $serviceId");
}
// int index =
// policyData!.indexWhere((item) => item["service_id"] == serviceId);
// if (index != -1) {
// policyData![index] = data; // Replace existing entry
// print("🔁 Updated policy for ServiceId: $serviceId");
// } else {
// policyData!.add(data); // Add new entry
// print(" Added policy for ServiceId: $serviceId");
// }
print("📋 policyData - $policyData");
}
// Future<void> fetchTrainFlightClass(int tripId) async {
// // final String apiUrldata = '$apiUrl/api/getDropdownMaster';
//
// // final String apiUrldata =
// // '$apiUrl/api/getFlightAndTrainClass?user_id=${widget.userId}&trip_type=tripId';
// final String apiUrldata = await apiService.fetchMasterDropdown();
//
// final token = await getToken();
//
// if (token == null) {
// throw Exception('Token not found. Please log in.');
// }
//
// final response = await http.get(
// Uri.parse(apiUrldata),
// headers: {
// 'Authorization': 'Bearer $token',
// 'Content-Type': 'application/json',
// },
// );
//
// if (response.statusCode == 200) {
// try {
// final data = json.decode(response.body);
// print(data);
//
// if (!data.containsKey('data') || data['data'] is! Map) {
// throw Exception(
// "Invalid response format: 'data' field is missing or not a Map");
// }
//
// Map<String, dynamic> plansJson =
// data['data']; // 'data' is a Map, not a List
// setState(() {
// apiDataForClass = plansJson; // Store API response in state
// isLoading = false;
// });
// } catch (e) {
// throw Exception('Error parsing response: $e');
// }
// } else {
// throw Exception('Failed to load plans');
// }
// }
Future<void> fetchTrainFlightClass() async {
print("ftech api");
try {
final data = await apiService.fetchMasterDropdown();
print("fetchTrainFlightClass - $data");
if (data is! Map) {
throw Exception("Invalid response format: expected a Map");
}
setState(() {
apiDataForClass = data; // Store API response in state
isLoading = false;
});
} catch (e) {
print('Error fetching role list: $e');
}
}
void fieldForPolicy() {
print("fieldForPolicy - ${widget.selectedTabNotifier.value}");
// Save current input to policyData before switching
if (ServiceId != null) {
print("Calling addOrUpdatePolicy");
addOrUpdatePolicy(
ServiceId!,
); // 👈 Save current values for existing service
}
setState(() {
// ServiceId = widget.selectedTabNotifier.value ?? "1";
final String tabIndexStr = widget.selectedTabNotifier.value;
print(" fns - $ServiceId");
// Safely convert tab index to int
final int? tabIndex = int.tryParse(tabIndexStr);
print(" tb inx - $tabIndex");
print(" db - ${widget.serviceDBValueList.length}");
print(" db list - ${widget.serviceDBValueList}");
if (tabIndex != null && tabIndex >= 0 && tabIndex <= widget.serviceDBValueList.length) {
ServiceId = widget.serviceDBValueList[tabIndex-1].toString();
print('✅ 484 Selected ServiceId: $ServiceId');
}
else {
print('❌ Invalid tab index or out of range');
}
print("502 ServiceId $ServiceId");
// Initialize controllers and variables if not present
costController.putIfAbsent(ServiceId!, () => TextEditingController());
classAction.putIfAbsent((ServiceId!), () => "1");
// classController.putIfAbsent(ServiceId!, () => TextEditingController());
FirstApproverAction.putIfAbsent(ServiceId!, () => "None");
SecondApproverAction.putIfAbsent(ServiceId!, () => "None");
ThirdApproverAction.putIfAbsent(ServiceId!, () => "None");
SelectedParallelProcess.putIfAbsent(ServiceId!, () => "3");
FirstExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None");
SecondExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None");
ThirdExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None");
FourthExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None");
SelectedParallelExceptionalProcess.putIfAbsent(ServiceId!, () => "4");
FirstAmendApproverAction.putIfAbsent(ServiceId!, () => "None");
SecondAmendApproverAction.putIfAbsent(ServiceId!, () => "None");
ThirdAmendApproverAction.putIfAbsent(ServiceId!, () => "None");
FourthAmendApproverAction.putIfAbsent(ServiceId!, () => "None");
SelectedParallelAmendProcess.putIfAbsent(ServiceId!, () => "4");
});
widget.onPolicyDataChanged(policyData);
}
void printData() {
// print("policyServices - $policyServices");
}
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// widget.isDesktop ? SizedBox(height: 10) : SizedBox(height: 5),
// Row(
// mainAxisAlignment: MainAxisAlignment.start,
// children: [
// Padding(
// padding: widget.isDesktop
// ? const EdgeInsets.only(left: 28.0)
// : const EdgeInsets.only(left: 0),
// child: Text(
// " Policy Criteria For ${widget.selectedService} ",
// style: GoogleFonts.poppins(
// fontSize: 13,
// color: Color(0xFF9E9DBD),
// fontWeight: FontWeight.bold),
// ),
// )
// ],
// ),
if (widget.isClass!)
widget.isDesktop ? SizedBox(height: 1) : SizedBox(height: 1),
Padding(
padding:
widget.isDesktop
? const EdgeInsets.only(left: 0.0)
: const EdgeInsets.only(left: 0),
child: Row(
children: [
Container(
// color: Colors.grey,
padding: const EdgeInsets.only(
top: 2,
bottom: 2,
left: 5,
right: 5,
),
child:
widget.isDesktop
? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (widget.isClass)
buildClassWidget(widget.isDesktop),
SizedBox(width: 45),
if (widget.isCost!)
buildCostWidget(widget.isDesktop),
],
)
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (widget.isClass!)
buildClassWidget(widget.isDesktop),
SizedBox(height: 10),
if (widget.isCost!)
buildCostWidget(widget.isDesktop),
],
),
),
],
),
),
if (widget.isCost!) SizedBox(height: 5),
if (validationErrors[ServiceId] != null)
Row(
children: [
Text(
validationErrors[ServiceId]!,
style: GoogleFonts.poppins(
color: Colors.red,
fontSize: 10,
fontWeight: FontWeight.bold,
),
),
],
),
if (validationErrors[ServiceId] != null) SizedBox(height: 5),
Container(
decoration: BoxDecoration(
border: null,
// border: Border.all(
// color: Color(0xFFEBEBF7),
// ),
borderRadius: BorderRadius.circular(8),
// color: Colors.brown.shade200,
),
child: Container(
child: Row(
children: [
Column(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
// color: Colors.yellow,
width:
widget.isDesktop
? MediaQuery.of(context).size.width * 0.18
: 600,
height:
widget.isDesktop
? MediaQuery.of(context).size.height * 0.56
: null,
child: Column(
children: [
Container(
margin: const EdgeInsets.only(right: 0),
decoration: BoxDecoration(
// color: Colors.grey.shade100,
// border: Border.all(
// color: Colors.grey.shade100,
// ),
),
padding: const EdgeInsets.only(
top: 10,
bottom: 0,
left: 0,
right: 35,
),
child: Row(
mainAxisAlignment:
widget.isDesktop
? MainAxisAlignment.spaceAround
: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 3,
child: Align(
alignment: Alignment.center,
child: Text(
"Normal Approval",
style: GoogleFonts.poppins(
color: Color(0xFF9E9DBD),
fontWeight: FontWeight.bold,
fontSize: 12,
),
),
),
),
// Expanded(
// flex: 2,
// child: Text(
// "Actions",
// style: GoogleFonts.poppins(
// color: Color(0xFF9E9DBD),
// fontWeight: FontWeight.bold,
// fontSize: 12),
// ),
// ),
// Text(
// "Parallel Action",
// style: GoogleFonts.poppins(
// color: Color(0xFF9E9DBD),
// fontWeight: FontWeight.bold,
// fontSize: 12),
// )
],
),
),
Divider(thickness: 0.2, color: Colors.grey),
SizedBox(
// height: 180,
// scrollDirection: Axis.vertical,
child: Container(
// height: MediaQuery.of(context).size.height * 3,
// color: Colors.grey,
decoration: BoxDecoration(
border: Border(
right: BorderSide(
color:
Colors
.blueGrey
.shade50, // Change this to your desired color
width:
1.0, // Change this to your desired width
),
),
),
margin: const EdgeInsets.only(right: 5, left: 0),
// color: Colors.grey.shade100,
child: Column(
children: [
Container(
padding: const EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
// "Approver 1",
"A1",
style: GoogleFonts.poppins(
fontSize: 13,
),
),
Spacer(),
CustomTextFieldUserWrapper(
width:
MediaQuery.of(
context,
).size.width *
0.12,
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 35,
child: DropdownSearch<String>(
selectedItem:
FirstApproverAction[ServiceId],
// enabled: !isViewMode,
popupProps: PopupProps.menu(
// showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
constraints: BoxConstraints(
maxHeight: 250,
),
itemBuilder:
(
context,
item,
isSelected,
) => Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize:
12, // 👈 Smaller text size here
color:
Colors
.black, // You can customize this
),
),
),
),
items: [
"Approval",
"Notification",
"None",
],
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border:
InputBorder.none,
contentPadding:
EdgeInsets.symmetric(
horizontal: 1,
vertical: 5,
),
),
),
dropdownBuilder:
(
context,
selectedItem,
) => Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xFF114D8B),
),
),
onChanged: (String? newValue) {
setState(() {
// Find the country_code based on selected country_name
FirstApproverAction[ServiceId!] =
newValue;
// print("selectedUserType - $selectedUserType");
// if (selectedCountry!.isNotEmpty) {
// errorMessages.remove("country_code");
// }
});
},
),
),
),
Spacer(),
GestureDetector(
onTap: () {
setState(() {
SelectedParallelProcess[ServiceId!] =
"1";
});
print(
"SelectedParallelProcess - $SelectedParallelProcess",
);
},
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
(SelectedParallelProcess[ServiceId] ==
"1")
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon(
Icons.check_circle,
size: 20,
color:
(SelectedParallelProcess[ServiceId] ==
"1")
? Colors.green
: Colors.grey,
// color: Colors.grey,
),
),
),
],
),
),
Container(
padding: const EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
// "Approver 2",
"A2",
style: GoogleFonts.poppins(
fontSize: 13,
),
),
Spacer(),
CustomTextFieldUserWrapper(
width:
MediaQuery.of(
context,
).size.width *
0.12,
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 35,
child: DropdownSearch<String>(
selectedItem:
SecondApproverAction[ServiceId],
// enabled: !isViewMode,
popupProps: PopupProps.menu(
// showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
constraints: BoxConstraints(
maxHeight: 250,
),
itemBuilder:
(
context,
item,
isSelected,
) => Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Text(
item,
style: TextStyle(
fontSize:
12, // 👈 Smaller text size here
color:
Colors
.black, // You can customize this
),
),
),
),
items: [
"Approval",
"Notification",
"None",
],
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border:
InputBorder.none,
contentPadding:
EdgeInsets.symmetric(
horizontal: 1,
vertical: 5,
),
),
),
dropdownBuilder:
(
context,
selectedItem,
) => Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xFF114D8B),
),
),
onChanged: (String? newValue) {
setState(() {
// Find the country_code based on selected country_name
SecondApproverAction[ServiceId!] =
newValue;
// print("selectedUserType - $selectedUserType");
// if (selectedCountry!.isNotEmpty) {
// errorMessages.remove("country_code");
// }
});
},
),
),
),
Spacer(),
GestureDetector(
onTap: () {
setState(() {
SelectedParallelProcess[ServiceId!] =
"2";
});
print(
"SelectedParallelProcess - $SelectedParallelProcess",
);
},
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelProcess[ServiceId] ==
"1") ||
(SelectedParallelProcess[ServiceId] ==
"2"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon(
Icons.check_circle,
size: 20,
color:
((SelectedParallelProcess[ServiceId] ==
"1") ||
(SelectedParallelProcess[ServiceId] ==
"2"))
? Colors.green
: Colors.grey,
// color: Colors.grey,
),
),
),
],
),
),
Container(
padding: const EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
"A3",
style: GoogleFonts.poppins(
fontSize: 13,
),
),
Spacer(),
CustomTextFieldUserWrapper(
width:
MediaQuery.of(
context,
).size.width *
0.12,
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 35,
child: DropdownSearch<String>(
selectedItem:
ThirdApproverAction[ServiceId],
// enabled: !isViewMode,
popupProps: PopupProps.menu(
// showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
constraints: BoxConstraints(
maxHeight: 250,
),
itemBuilder:
(
context,
item,
isSelected,
) => Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize:
12, // 👈 Smaller text size here
color:
Colors
.black, // You can customize this
),
),
),
),
items: [
"Approval",
"Notification",
"None",
],
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border:
InputBorder.none,
contentPadding:
EdgeInsets.symmetric(
horizontal: 1,
vertical: 5,
),
),
),
dropdownBuilder:
(context, selectedItem) =>
// Center-align selected item
Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xFF114D8B),
),
),
onChanged: (String? newValue) {
setState(() {
// Find the country_code based on selected country_name
ThirdApproverAction[ServiceId!] =
newValue;
// print("selectedUserType - $selectedUserType");
// if (selectedCountry!.isNotEmpty) {
// errorMessages.remove("country_code");
// }
});
},
),
),
),
Spacer(),
GestureDetector(
onTap: () {
setState(() {
SelectedParallelProcess[ServiceId!] =
"3";
});
print(
"SelectedParallelProcess - $SelectedParallelProcess[ServiceId]",
);
},
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelProcess[ServiceId] ==
"1") ||
(SelectedParallelProcess[ServiceId] ==
"2") ||
(SelectedParallelProcess[ServiceId] ==
"3"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon(
Icons.check_circle,
size: 20,
color:
((SelectedParallelProcess[ServiceId] ==
"1") ||
(SelectedParallelProcess[ServiceId] ==
"2") ||
(SelectedParallelProcess[ServiceId] ==
"3"))
? Colors.green
: Colors.grey,
// color: Colors.grey,
),
),
),
],
),
),
],
),
),
),
],
),
),
],
),
Column(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width:
widget.isDesktop
? MediaQuery.of(context).size.width * 0.18
: 600,
height:
widget.isDesktop
? MediaQuery.of(context).size.height * 0.56
: null,
child: Column(
children: [
Container(
margin: const EdgeInsets.only(right: 0),
decoration: BoxDecoration(
// color: Colors.grey.shade100,
// border: Border.all(
// color: Colors.grey.shade100,
// ),
),
padding: const EdgeInsets.only(
top: 10,
bottom: 0,
left: 0,
right: 35,
),
child: Row(
mainAxisAlignment:
widget.isDesktop
? MainAxisAlignment.spaceAround
: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 3,
child: Align(
alignment: Alignment.center,
child: Text(
"Exceptional Approval",
style: GoogleFonts.poppins(
color: Color(0xFF9E9DBD),
fontWeight: FontWeight.bold,
fontSize: 12,
),
),
),
),
// Expanded(
// flex: 2,
// child: Text(
// "Actions",
// style: GoogleFonts.poppins(
// color: Color(0xFF9E9DBD),
// fontWeight: FontWeight.bold,
// fontSize: 12),
// ),
// ),
// Text(
// "Parallel Action",
// style: GoogleFonts.poppins(
// color: Color(0xFF9E9DBD),
// fontWeight: FontWeight.bold,
// fontSize: 12),
// )
],
),
),
Divider(thickness: 0.2, color: Colors.grey),
SizedBox(
// height: 180,
// scrollDirection: Axis.vertical,
child: Container(
// height: MediaQuery.of(context).size.height * 3,
// color: Colors.grey,
decoration: BoxDecoration(
border: Border(
right: BorderSide(
color:
Colors
.blueGrey
.shade50, // Change this to your desired color
width:
1.0, // Change this to your desired width
),
),
),
margin: const EdgeInsets.only(right: 5, left: 0),
// color: Colors.grey.shade100,
child: Column(
children: [
Container(
// padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
// "Approver 1",
"A1",
style: GoogleFonts.poppins(
fontSize: 13,
),
),
Spacer(),
CustomTextFieldUserWrapper(
width:
MediaQuery.of(
context,
).size.width *
0.12,
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 35,
child: DropdownSearch<String>(
selectedItem:
FirstExceptionalApproverAction[ServiceId],
// enabled: !isViewMode,
popupProps: PopupProps.menu(
// showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
constraints: BoxConstraints(
maxHeight: 250,
),
itemBuilder:
(
context,
item,
isSelected,
) => Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize:
12, // 👈 Smaller text size here
color:
Colors
.black, // You can customize this
),
),
),
),
items: [
"Approval",
"Notification",
"None",
],
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border:
InputBorder.none,
contentPadding:
EdgeInsets.symmetric(
horizontal: 1,
vertical: 5,
),
),
),
dropdownBuilder:
(
context,
selectedItem,
) => Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xFF114D8B),
),
),
onChanged: (String? newValue) {
setState(() {
// Find the country_code based on selected country_name
FirstExceptionalApproverAction[ServiceId!] =
newValue;
// print("selectedUserType - $selectedUserType");
// if (selectedCountry!.isNotEmpty) {
// errorMessages.remove("country_code");
// }
});
},
),
),
),
Spacer(),
GestureDetector(
onTap: () {
setState(() {
SelectedParallelExceptionalProcess[ServiceId!] =
"1";
});
print(
"SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess",
);
},
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
(SelectedParallelExceptionalProcess[ServiceId] ==
"1")
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon(
Icons.check_circle,
size: 20,
color:
(SelectedParallelExceptionalProcess[ServiceId] ==
"1")
? Colors.green
: Colors.grey,
// color: Colors.grey,
),
),
),
],
),
),
Container(
// padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
// "Approver 2",
"A2",
style: GoogleFonts.poppins(
fontSize: 13,
),
),
Spacer(),
CustomTextFieldUserWrapper(
width:
MediaQuery.of(
context,
).size.width *
0.12,
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 35,
child: DropdownSearch<String>(
selectedItem:
SecondExceptionalApproverAction[ServiceId],
// enabled: !isViewMode,
popupProps: PopupProps.menu(
// showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
constraints: BoxConstraints(
maxHeight: 250,
),
itemBuilder:
(
context,
item,
isSelected,
) => Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Text(
item,
style: TextStyle(
fontSize:
12, // 👈 Smaller text size here
color:
Colors
.black, // You can customize this
),
),
),
),
items: [
"Approval",
"Notification",
"None",
],
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border:
InputBorder.none,
contentPadding:
EdgeInsets.symmetric(
horizontal: 1,
vertical: 5,
),
),
),
dropdownBuilder:
(
context,
selectedItem,
) => Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xFF114D8B),
),
),
onChanged: (String? newValue) {
setState(() {
// Find the country_code based on selected country_name
SecondExceptionalApproverAction[ServiceId!] =
newValue;
// print("selectedUserType - $selectedUserType");
// if (selectedCountry!.isNotEmpty) {
// errorMessages.remove("country_code");
// }
});
},
),
),
),
Spacer(),
GestureDetector(
onTap: () {
setState(() {
SelectedParallelExceptionalProcess[ServiceId!] =
"2";
});
print(
"SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess",
);
},
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelExceptionalProcess[ServiceId] ==
"1") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"2"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon(
Icons.check_circle,
size: 20,
color:
((SelectedParallelExceptionalProcess[ServiceId] ==
"1") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"2"))
? Colors.green
: Colors.grey,
// color: Colors.grey,
),
),
),
],
),
),
Container(
// padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
"A3",
style: GoogleFonts.poppins(
fontSize: 13,
),
),
Spacer(),
CustomTextFieldUserWrapper(
width:
MediaQuery.of(
context,
).size.width *
0.12,
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 35,
child: DropdownSearch<String>(
selectedItem:
ThirdExceptionalApproverAction[ServiceId],
// enabled: !isViewMode,
popupProps: PopupProps.menu(
// showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
constraints: BoxConstraints(
maxHeight: 250,
),
itemBuilder:
(
context,
item,
isSelected,
) => Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize:
12, // 👈 Smaller text size here
color:
Colors
.black, // You can customize this
),
),
),
),
items: [
"Approval",
"Notification",
"None",
],
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border:
InputBorder.none,
contentPadding:
EdgeInsets.symmetric(
horizontal: 1,
vertical: 5,
),
),
),
dropdownBuilder:
(context, selectedItem) =>
// Center-align selected item
Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xFF114D8B),
),
),
onChanged: (String? newValue) {
setState(() {
// Find the country_code based on selected country_name
ThirdExceptionalApproverAction[ServiceId!] =
newValue;
// print("selectedUserType - $selectedUserType");
// if (selectedCountry!.isNotEmpty) {
// errorMessages.remove("country_code");
// }
});
},
),
),
),
Spacer(),
GestureDetector(
onTap: () {
setState(() {
SelectedParallelExceptionalProcess[ServiceId!] =
"3";
});
print(
"SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess[ServiceId]",
);
},
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelExceptionalProcess[ServiceId] ==
"1") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"2") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"3"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon(
Icons.check_circle,
size: 20,
color:
((SelectedParallelExceptionalProcess[ServiceId] ==
"1") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"2") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"3"))
? Colors.green
: Colors.grey,
// color: Colors.grey,
),
),
),
],
),
),
Container(
// padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
"A4",
style: GoogleFonts.poppins(
fontSize: 13,
),
),
Spacer(),
CustomTextFieldUserWrapper(
width:
MediaQuery.of(
context,
).size.width *
0.12,
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 35,
child: DropdownSearch<String>(
selectedItem:
FourthExceptionalApproverAction[ServiceId],
// enabled: !isViewMode,
popupProps: PopupProps.menu(
// showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
constraints: BoxConstraints(
maxHeight: 250,
),
itemBuilder:
(
context,
item,
isSelected,
) => Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize:
12, // 👈 Smaller text size here
color:
Colors
.black, // You can customize this
),
),
),
),
items: [
"Approval",
"Notification",
"None",
],
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border:
InputBorder.none,
contentPadding:
EdgeInsets.symmetric(
horizontal: 1,
vertical: 5,
),
),
),
dropdownBuilder:
(context, selectedItem) =>
// Center-align selected item
Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xFF114D8B),
),
),
onChanged: (String? newValue) {
setState(() {
// Find the country_code based on selected country_name
FourthExceptionalApproverAction[ServiceId!] =
newValue;
// print("selectedUserType - $selectedUserType");
// if (selectedCountry!.isNotEmpty) {
// errorMessages.remove("country_code");
// }
});
},
),
),
),
Spacer(),
GestureDetector(
onTap: () {
setState(() {
SelectedParallelExceptionalProcess[ServiceId!] =
"4";
});
print(
"SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess[ServiceId]",
);
},
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelExceptionalProcess[ServiceId] ==
"1") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"2") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"3") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"4"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon(
Icons.check_circle,
size: 20,
color:
((SelectedParallelExceptionalProcess[ServiceId] ==
"1") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"2") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"3") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"4"))
? Colors.green
: Colors.grey,
// color: Colors.grey,
),
),
),
],
),
),
],
),
),
),
],
),
),
],
),
Column(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
//color: Colors.grey.shade100,
width:
widget.isDesktop
? MediaQuery.of(context).size.width * 0.18
: 600,
height:
widget.isDesktop
? MediaQuery.of(context).size.height * 0.56
: null,
child: Column(
children: [
Container(
margin: const EdgeInsets.only(right: 0),
decoration: BoxDecoration(
// color: Colors.grey.shade100,
// border: Border.all(
// color: Colors.grey.shade100,
// ),
),
padding: const EdgeInsets.only(
top: 10,
bottom: 0,
left: 0,
right: 35,
),
child: Row(
mainAxisAlignment:
widget.isDesktop
? MainAxisAlignment.spaceAround
: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 3,
child: Align(
alignment: Alignment.center,
child: Text(
"Amendment Approval",
style: GoogleFonts.poppins(
color: Color(0xFF9E9DBD),
fontWeight: FontWeight.bold,
fontSize: 12,
),
),
),
),
// Expanded(
// flex: 2,
// child: Text(
// "Actions",
// style: GoogleFonts.poppins(
// color: Color(0xFF9E9DBD),
// fontWeight: FontWeight.bold,
// fontSize: 12),
// ),
// ),
// Text(
// "Parallel Action",
// style: GoogleFonts.poppins(
// color: Color(0xFF9E9DBD),
// fontWeight: FontWeight.bold,
// fontSize: 12),
// )
],
),
),
Divider(thickness: 0.2, color: Colors.grey),
SizedBox(
// height: 180,
// scrollDirection: Axis.vertical,
child: Container(
// height: MediaQuery.of(context).size.height * 3,
// color: Colors.grey,
margin: const EdgeInsets.only(right: 5, left: 0),
// color: Colors.grey.shade100,
child: Column(
children: [
Container(
// padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
// "Approver 1",
"A1",
style: GoogleFonts.poppins(
fontSize: 13,
),
),
Spacer(),
CustomTextFieldUserWrapper(
width:
MediaQuery.of(
context,
).size.width *
0.12,
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 35,
child: DropdownSearch<String>(
selectedItem:
FirstAmendApproverAction[ServiceId],
// enabled: !isViewMode,
popupProps: PopupProps.menu(
// showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
constraints: BoxConstraints(
maxHeight: 250,
),
itemBuilder:
(
context,
item,
isSelected,
) => Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize:
12, // 👈 Smaller text size here
color:
Colors
.black, // You can customize this
),
),
),
),
items: [
"Approval",
"Notification",
"None",
],
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border:
InputBorder.none,
contentPadding:
EdgeInsets.symmetric(
horizontal: 1,
vertical: 5,
),
),
),
dropdownBuilder:
(
context,
selectedItem,
) => Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xFF114D8B),
),
),
onChanged: (String? newValue) {
setState(() {
// Find the country_code based on selected country_name
FirstAmendApproverAction[ServiceId!] =
newValue;
// print("selectedUserType - $selectedUserType");
// if (selectedCountry!.isNotEmpty) {
// errorMessages.remove("country_code");
// }
});
},
),
),
),
Spacer(),
GestureDetector(
onTap: () {
setState(() {
SelectedParallelAmendProcess[ServiceId!] =
"1";
});
print(
"SelectedParallelAmendProcess - $SelectedParallelAmendProcess",
);
},
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
(SelectedParallelAmendProcess[ServiceId] ==
"1")
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon(
Icons.check_circle,
size: 20,
color:
(SelectedParallelAmendProcess[ServiceId] ==
"1")
? Colors.green
: Colors.grey,
// color: Colors.grey,
),
),
),
],
),
),
Container(
// padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
// "Approver 2",
"A2",
style: GoogleFonts.poppins(
fontSize: 13,
),
),
Spacer(),
CustomTextFieldUserWrapper(
width:
MediaQuery.of(
context,
).size.width *
0.12,
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 35,
child: DropdownSearch<String>(
selectedItem:
SecondAmendApproverAction[ServiceId],
// enabled: !isViewMode,
popupProps: PopupProps.menu(
// showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
constraints: BoxConstraints(
maxHeight: 250,
),
itemBuilder:
(
context,
item,
isSelected,
) => Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Text(
item,
style: TextStyle(
fontSize:
12, // 👈 Smaller text size here
color:
Colors
.black, // You can customize this
),
),
),
),
items: [
"Approval",
"Notification",
"None",
],
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border:
InputBorder.none,
contentPadding:
EdgeInsets.symmetric(
horizontal: 1,
vertical: 5,
),
),
),
dropdownBuilder:
(
context,
selectedItem,
) => Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xFF114D8B),
),
),
onChanged: (String? newValue) {
setState(() {
// Find the country_code based on selected country_name
SecondAmendApproverAction[ServiceId!] =
newValue;
// print("selectedUserType - $selectedUserType");
// if (selectedCountry!.isNotEmpty) {
// errorMessages.remove("country_code");
// }
});
},
),
),
),
Spacer(),
GestureDetector(
onTap: () {
setState(() {
SelectedParallelAmendProcess[ServiceId!] =
"2";
});
print(
"SelectedParallelAmendProcess - $SelectedParallelAmendProcess",
);
},
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelAmendProcess[ServiceId] ==
"1") ||
(SelectedParallelAmendProcess[ServiceId] ==
"2"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon(
Icons.check_circle,
size: 20,
color:
((SelectedParallelAmendProcess[ServiceId] ==
"1") ||
(SelectedParallelAmendProcess[ServiceId] ==
"2"))
? Colors.green
: Colors.grey,
// color: Colors.grey,
),
),
),
],
),
),
Container(
// padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
"A3",
style: GoogleFonts.poppins(
fontSize: 13,
),
),
Spacer(),
CustomTextFieldUserWrapper(
width:
MediaQuery.of(
context,
).size.width *
0.12,
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 35,
child: DropdownSearch<String>(
selectedItem:
ThirdAmendApproverAction[ServiceId],
// enabled: !isViewMode,
popupProps: PopupProps.menu(
// showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
constraints: BoxConstraints(
maxHeight: 250,
),
itemBuilder:
(
context,
item,
isSelected,
) => Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize:
12, // 👈 Smaller text size here
color:
Colors
.black, // You can customize this
),
),
),
),
items: [
"Approval",
"Notification",
"None",
],
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border:
InputBorder.none,
contentPadding:
EdgeInsets.symmetric(
horizontal: 1,
vertical: 5,
),
),
),
dropdownBuilder:
(context, selectedItem) =>
// Center-align selected item
Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xFF114D8B),
),
),
onChanged: (String? newValue) {
setState(() {
// Find the country_code based on selected country_name
ThirdAmendApproverAction[ServiceId!] =
newValue;
// print("selectedUserType - $selectedUserType");
// if (selectedCountry!.isNotEmpty) {
// errorMessages.remove("country_code");
// }
});
},
),
),
),
Spacer(),
GestureDetector(
onTap: () {
setState(() {
SelectedParallelAmendProcess[ServiceId!] =
"3";
});
print(
"SelectedParallelAmendProcess - $SelectedParallelAmendProcess[ServiceId]",
);
},
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelAmendProcess[ServiceId] ==
"1") ||
(SelectedParallelAmendProcess[ServiceId] ==
"2") ||
(SelectedParallelAmendProcess[ServiceId] ==
"3"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon(
Icons.check_circle,
size: 20,
color:
((SelectedParallelAmendProcess[ServiceId] ==
"1") ||
(SelectedParallelAmendProcess[ServiceId] ==
"2") ||
(SelectedParallelAmendProcess[ServiceId] ==
"3"))
? Colors.green
: Colors.grey,
// color: Colors.grey,
),
),
),
],
),
),
Container(
// padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
"A4",
style: GoogleFonts.poppins(
fontSize: 13,
),
),
Spacer(),
CustomTextFieldUserWrapper(
width:
MediaQuery.of(
context,
).size.width *
0.12,
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 35,
child: DropdownSearch<String>(
selectedItem:
FourthAmendApproverAction[ServiceId],
// enabled: !isViewMode,
popupProps: PopupProps.menu(
// showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
constraints: BoxConstraints(
maxHeight: 250,
),
itemBuilder:
(
context,
item,
isSelected,
) => Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize:
12, // 👈 Smaller text size here
color:
Colors
.black, // You can customize this
),
),
),
),
items: [
"Approval",
"Notification",
"None",
],
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border:
InputBorder.none,
contentPadding:
EdgeInsets.symmetric(
horizontal: 1,
vertical: 5,
),
),
),
dropdownBuilder:
(context, selectedItem) =>
// Center-align selected item
Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xFF114D8B),
),
),
onChanged: (String? newValue) {
setState(() {
// Find the country_code based on selected country_name
FourthAmendApproverAction[ServiceId!] =
newValue;
// print("selectedUserType - $selectedUserType");
// if (selectedCountry!.isNotEmpty) {
// errorMessages.remove("country_code");
// }
});
},
),
),
),
Spacer(),
GestureDetector(
onTap: () {
setState(() {
SelectedParallelAmendProcess[ServiceId!] =
"4";
});
print(
"SelectedParallelAmendProcess - $SelectedParallelAmendProcess[ServiceId]",
);
},
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelAmendProcess[ServiceId] ==
"1") ||
(SelectedParallelAmendProcess[ServiceId] ==
"2") ||
(SelectedParallelAmendProcess[ServiceId] ==
"3") ||
(SelectedParallelAmendProcess[ServiceId] ==
"4"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon(
Icons.check_circle,
size: 20,
color:
((SelectedParallelAmendProcess[ServiceId] ==
"1") ||
(SelectedParallelAmendProcess[ServiceId] ==
"2") ||
(SelectedParallelAmendProcess[ServiceId] ==
"3") ||
(SelectedParallelAmendProcess[ServiceId] ==
"4"))
? Colors.green
: Colors.grey,
// color: Colors.grey,
),
),
),
],
),
),
],
),
),
),
],
),
),
],
),
],
),
),
),
],
);
}
Widget buildClassWidget(isDesktop) {
List<dynamic> purposeList = [];
String textLabel = "Class";
// if (ServiceId != null) {
// purposeList = (ServiceId == "1")
// ? (apiDataForClass?['flight_class'] ?? [])
// : (apiDataForClass?['train_class'] ?? []);
// }
if (ServiceId != null) {
// ServiceId = '1';
print("sid $ServiceId");
switch (ServiceId) {
case "1":
textLabel = "Class";
purposeList = apiDataForClass?['flight_class'] ?? [];
break;
case "5":
textLabel = "Category";
purposeList = apiDataForClass?['hotel_class'] ?? [];
break;
case "2":
textLabel = "Class";
purposeList = apiDataForClass?['train_class'] ?? [];
break;
default:
textLabel = "Class";
purposeList = [];
}
}
print("CLASS-ServiceId- $ServiceId");
print("CLASS-ServiceIndxId- $ServiceIndxId");
print("CLASS-purposeList - $purposeList");
print("CLASS-Action - ${classAction[ServiceId]}");
// ✅ Sort by dropdown_key
purposeList.sort((a, b) {
int aKey = int.tryParse(a['dropdown_key'].toString()) ?? 0;
int bKey = int.tryParse(b['dropdown_key'].toString()) ?? 0;
return aKey.compareTo(bKey);
});
List<DropdownMenuItem<String>> dropdownItems =
purposeList
.map(
(item) => DropdownMenuItem<String>(
value: item['dropdown_key'],
child: Text(item['dropdown_value']),
),
)
.toList();
if (dropdownItems.isEmpty) {
dropdownItems.add(
DropdownMenuItem<String>(
value: null,
child: Text(
"No options available",
style: GoogleFonts.poppins(color: Colors.grey),
),
),
);
}
// if (ServiceId != null) {
// if (classAction[ServiceId!] == null && dropdownItems.isNotEmpty) {
// classAction[ServiceId!] = dropdownItems.first.value!;
// }
// }
// if (ServiceId != null &&
// classAction[ServiceId!] == null &&
// dropdownItems.isNotEmpty) {
// classAction[ServiceId!] = dropdownItems.first.value!;
// }
// 1. First, when dropdownItems are ready, assign default value:
if ((ServiceId) != null &&
classAction[ServiceId] == null &&
dropdownItems.isNotEmpty) {
// Important to wrap inside setState if async
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
classAction[ServiceId!] = dropdownItems.first.value!;
});
});
}
return Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
textLabel,
style: GoogleFonts.poppins(
fontSize: 12,
// fontWeight: FontWeight.w200,
color: Colors.black,
),
),
SizedBox(height: 5),
// CustomTextFieldUserWrapper(
// isFocused: false,
// isDesktop: widget.isDesktop,
//
// child: SizedBox(
// height: 40,
// child: ServiceId != null && (isLoading || dropdownItems.isEmpty)
// ? const Center(child: CircularProgressIndicator())
// : DropdownButtonFormField<String>(
// // Assign the correct focus node
// // controller: _hotelNameController,
// value: classAction[ServiceId],
//
// style: GoogleFonts.poppins(fontSize: 12),
// decoration: InputDecoration(
// hintText: "Select",
// hintStyle: GoogleFonts.poppins(fontSize: 12),
// border: InputBorder.none,
// contentPadding: EdgeInsets.symmetric(
// horizontal: 10), // Proper padding
// ),
// onChanged: (newValue) {
// if (ServiceId != null && newValue != null) {
// setState(() {
// classAction[ServiceId!] = newValue;
// });
// }
// },
//
// items: dropdownItems,
// ),
// ),
// ),
CustomTextFieldUserWrapper(
isFocused: false,
isDesktop: isDesktop,
child: SizedBox(
height: 40,
width: double.infinity,
child:
(ServiceId!) != null && (isLoading || dropdownItems.isEmpty)
? const Center(child: CircularProgressIndicator())
: DropdownSearch<Map<String, dynamic>>(
key:
classAction[(ServiceId!)] == null
? UniqueKey()
: ValueKey(classAction[(ServiceId!)]),
items: purposeList.cast<Map<String, dynamic>>(),
// selectedItem: purposeList.firstWhere(
// (item) => item['dropdown_key'] == selectedClass,
// orElse: () => {},
// ),
selectedItem:
classAction[(ServiceId!)] != null
? purposeList.firstWhere(
(item) =>
item['dropdown_key'] ==
classAction[(ServiceId!)],
orElse: () => {},
)
: null,
itemAsString: (item) => item['dropdown_value'] ?? '',
popupProps: PopupProps.menu(
showSearchBox: false,
fit: FlexFit.loose,
menuProps: const MenuProps(
backgroundColor: Colors.white,
),
itemBuilder: (context, item, isSelected) {
final bool isNotAllowed =
item['is_allowed'] == 'No';
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 5,
),
child: Text(
item['dropdown_value'] ?? '',
style: GoogleFonts.poppins(
fontSize: 12,
color:
isNotAllowed
? Colors.redAccent
: Colors.black,
),
),
);
},
),
dropdownDecoratorProps: const DropDownDecoratorProps(
dropdownSearchDecoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
),
),
dropdownBuilder: (context, selectedItem) {
if (selectedItem == null || selectedItem.isEmpty) {
return Text(
"Select ",
style: GoogleFonts.poppins(
color: Colors.grey,
fontSize: 13,
),
);
}
return Text(
selectedItem['dropdown_value'] ?? '',
style: GoogleFonts.poppins(
fontSize: 12,
color: Colors.black,
),
);
},
onChanged:
purposeList.isNotEmpty
? (Map<String, dynamic>? newValue) async {
setState(() {
classAction[(ServiceId!)] =
newValue?['dropdown_key'];
print(
"Selected Purpose: ${classAction[(ServiceId!)]}",
);
});
}
: null,
),
),
),
],
),
],
);
}
Widget buildCostWidget(isDesktop) {
return Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Cost",
style: GoogleFonts.poppins(
fontSize: 12,
// fontWeight: FontWeight.w200,
color: Colors.black,
),
),
SizedBox(height: 5),
CustomTextFieldUserWrapper(
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 40,
child: TextField(
style: GoogleFonts.poppins(fontSize: 12),
controller: costController[ServiceId],
// enabled: !isViewMode,
onChanged: (value) {
printData();
},
decoration: InputDecoration(
labelText: "Cost",
labelStyle: GoogleFonts.poppins(
fontSize: 12,
color: Colors.grey,
),
floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16),
),
),
),
),
],
),
],
);
}
}