From 284ff8779fc2e47ff3c33941ae340f7a5ec70156 Mon Sep 17 00:00:00 2001 From: venba-Inspriron-3558 Date: Mon, 23 Jun 2025 16:11:45 +0530 Subject: [PATCH 1/2] minor issues fixes --- lib/Screens/hotels/hotelsDetails.dart | 42 +- lib/Screens/perdiem_amount/forexDetails.dart | 128 +- lib/Screens/policy/policy.dart | 20 +- lib/Screens/reports/advancePurchase.dart | 39 +- lib/Screens/reports/guestHouse.dart | 40 +- lib/Screens/reports/misAir.dart | 39 +- lib/Screens/reports/misForex.dart | 45 +- lib/Screens/reports/misHotel.dart | 39 +- lib/Screens/reports/reportSample.dart | 2401 +++++++++++++++-- lib/Screens/reports/servicesAnalysis.dart | 39 +- .../personalDetailsTravelAgent.dart | 55 +- .../create_user/personal_details.dart | 7 +- lib/Screens/userManagement/user_List.dart | 131 +- lib/routes/organizationSetting.dart | 9 +- lib/services/apiService.dart | 45 +- lib/widgets/popup_travelAgentList_action.dart | 38 +- lib/widgets/popup_userList_action.dart | 38 +- 17 files changed, 2653 insertions(+), 502 deletions(-) diff --git a/lib/Screens/hotels/hotelsDetails.dart b/lib/Screens/hotels/hotelsDetails.dart index 4439c91..77d0e0d 100644 --- a/lib/Screens/hotels/hotelsDetails.dart +++ b/lib/Screens/hotels/hotelsDetails.dart @@ -289,9 +289,15 @@ class HotelsDataState extends State { countryList = apiCountryData ?? []; // Map country codes to country names + // countryMap = { + // for (var item in countryList) + // item['country_code'] as String: item['country_name'] as String, + // }; + countryMap = { - for (var item in countryList) - item['country_code'] as String: item['country_name'] as String, + for (var country in countryList) + (country['country_code'] ?? ''): + '${country['country_name'] ?? ''} (${country['country_code'] ?? ''})', }; // Extract only country codes for processing @@ -482,16 +488,34 @@ class HotelsDataState extends State { menuProps: const MenuProps(backgroundColor: Colors.white), constraints: BoxConstraints(maxHeight: 200), itemBuilder: - (context, item, isSelected) => Padding( + (context, item, isSelected) { + print("contryItem - $item"); + final match = RegExp(r'^(.*)\s\((.*)\)$',).firstMatch(item); + final countryName = match?.group(1) ?? ''; + final countryCode = match?.group(2) ?? ''; + return Padding( padding: const EdgeInsets.symmetric( - horizontal: 10.0, - vertical: 8.0, + horizontal: 8.0, + vertical: 6.0, ), - child: Text( - item, - style: GoogleFonts.poppins(fontSize: 11.5), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + countryName, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + Text( + countryCode, + style: GoogleFonts.poppins(fontSize: 11.5,color:Colors.grey), + + ), + ], + ), ), - ), + );}, searchFieldProps: TextFieldProps( decoration: InputDecoration( hintText: "Search ...", diff --git a/lib/Screens/perdiem_amount/forexDetails.dart b/lib/Screens/perdiem_amount/forexDetails.dart index 3415f68..1a0d05c 100644 --- a/lib/Screens/perdiem_amount/forexDetails.dart +++ b/lib/Screens/perdiem_amount/forexDetails.dart @@ -346,9 +346,15 @@ class ForexDataState extends State { countryList = apiCountryData ?? []; // Map country codes to country names + // countryMap = { + // for (var item in countryList) + // item['country_code'] as String: item['country_name'] as String, + // }; + countryMap = { - for (var item in countryList) - item['country_code'] as String: item['country_name'] as String, + for (var country in countryList) + (country['country_code'] ?? ''): + '${country['country_name'] ?? ''} (${country['country_code'] ?? ''})', }; // Extract only country codes for processing @@ -426,18 +432,35 @@ class ForexDataState extends State { popupProps: PopupProps.menu( showSearchBox: true, // Enables search functionality menuProps: const MenuProps(backgroundColor: Colors.white), - constraints: BoxConstraints(maxHeight: 250), + constraints: BoxConstraints(maxHeight: 200), itemBuilder: - (context, item, isSelected) => Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10.0, - vertical: 8.0, - ), - child: Text( - item, - style: GoogleFonts.poppins(fontSize: 11.5), - ), - ), + (context, item, isSelected) { + print("contryItem - $item"); + final match = RegExp(r'^(.*)\s\((.*)\)$',).firstMatch(item); + final countryName = match?.group(1) ?? ''; + final countryCode = match?.group(2) ?? ''; + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 6.0, + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + countryName, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + Text( + countryCode, + style: GoogleFonts.poppins(fontSize: 11.5,color:Colors.grey), + ), + ], + ), + ), + );}, searchFieldProps: TextFieldProps( decoration: InputDecoration( hintText: "Search ...", @@ -495,10 +518,87 @@ class ForexDataState extends State { .firstWhere((entry) => entry.value == newValue) .key; selectedCountryName = newValue; - setCurrencyFromSelectedCountry(selectedCountry!); }); }, ), + // child: DropdownSearch( + // selectedItem: countryMap[selectedCountry], + // popupProps: PopupProps.menu( + // showSearchBox: true, // Enables search functionality + // menuProps: const MenuProps(backgroundColor: Colors.white), + // constraints: BoxConstraints(maxHeight: 250), + // itemBuilder: + // (context, item, isSelected) => Padding( + // padding: const EdgeInsets.symmetric( + // horizontal: 10.0, + // vertical: 8.0, + // ), + // child: Text( + // item, + // style: GoogleFonts.poppins(fontSize: 11.5), + // ), + // ), + // searchFieldProps: TextFieldProps( + // decoration: InputDecoration( + // hintText: "Search ...", + // hintStyle: GoogleFonts.poppins(fontSize: 11), + // contentPadding: EdgeInsets.symmetric(horizontal: 4), + // ), + // ), + // ), + // items: countryMap.values.toList(), + // dropdownDecoratorProps: DropDownDecoratorProps( + // dropdownSearchDecoration: InputDecoration( + // // border: InputBorder.none, + // border: OutlineInputBorder( + // borderRadius: BorderRadius.circular(8), + // borderSide: BorderSide( + // color: + // (focusStates["country_codeFocused"] ?? false) + // ? widget.layoutColor! + // : Colors.white, + // // width: 0.5, + // ), + // ), + // enabledBorder: OutlineInputBorder( + // borderSide: BorderSide( + // color: + // (focusStates["country_codeFocused"] ?? false) + // ? widget.layoutColor! + // : Colors.white, + // // : const Color(0xFFD6D5E6), + // // width: 0.5, + // // const Color(0xFFD6D5E6), + // ), + // ), + // focusedBorder: OutlineInputBorder( + // borderSide: BorderSide(color: widget.layoutColor!, width: 1), + // ), + // contentPadding: EdgeInsets.symmetric(horizontal: 10.0, + // vertical: 8.0,), + // ), + // ), + // dropdownBuilder: + // (context, selectedItem) => Align( + // // Center-align selected item + // alignment: Alignment.centerLeft, + // child: Text( + // selectedItem ?? "Select ", + // style: GoogleFonts.poppins(fontSize: 11), + // ), + // ), + // onChanged: (String? newValue) { + // setState(() { + // // Find the country_code based on selected country_name + // selectedCountry = + // countryMap.entries + // .firstWhere((entry) => entry.value == newValue) + // .key; + // selectedCountryName = newValue; + // setCurrencyFromSelectedCountry(selectedCountry!); + // }); + // }, + // ), ) ) ), diff --git a/lib/Screens/policy/policy.dart b/lib/Screens/policy/policy.dart index b9a65c5..53df327 100644 --- a/lib/Screens/policy/policy.dart +++ b/lib/Screens/policy/policy.dart @@ -644,16 +644,16 @@ class _PolicyState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - "Choose Policy Type", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - ], + // children: [ + // Text( + // "Choose Policy Type", + // style: GoogleFonts.poppins( + // fontSize: 12, + // fontWeight: FontWeight.w600, + // color: Color(0xFF575A74), + // ), + // ), + // ], ), ), ], diff --git a/lib/Screens/reports/advancePurchase.dart b/lib/Screens/reports/advancePurchase.dart index c44c7a8..f6eb16b 100644 --- a/lib/Screens/reports/advancePurchase.dart +++ b/lib/Screens/reports/advancePurchase.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:core'; import 'dart:typed_data'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; @@ -323,12 +324,16 @@ class _AdvancePurchaseState extends State if (textControllers["from_date"]!.text.isEmpty || textControllers["to_date"]!.text.isEmpty) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - backgroundColor: Colors.redAccent, - content: Text("Please choose a valid date range."), - behavior: SnackBarBehavior.floating, - ), + + Fluttertoast.showToast( + msg: "Please choose a valid date range.", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: Colors.redAccent, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, '#dc1c13','#dc1c13')", ); return; } @@ -356,13 +361,21 @@ class _AdvancePurchaseState extends State excelName, ); - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // backgroundColor: result['status'] ? Colors.green : Colors.red, - // content: Text(result['message']), - // behavior: SnackBarBehavior.floating, - // ), - // ); + final String displayBackgroundColor = result['status'] ? '#28a745' : '#dc1c13'; + final Color displayColor = result['status'] ? Colors.green : Colors.redAccent; + final String displayMessage = result['message']; + // final bool status = result['status'] == true; + + Fluttertoast.showToast( + msg: displayMessage , + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: displayColor, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, $displayBackgroundColor, $displayBackgroundColor)", + ); } void handleDomesticFilter(String query) { diff --git a/lib/Screens/reports/guestHouse.dart b/lib/Screens/reports/guestHouse.dart index 225a20d..d4af939 100644 --- a/lib/Screens/reports/guestHouse.dart +++ b/lib/Screens/reports/guestHouse.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:core'; import 'dart:typed_data'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; @@ -302,13 +303,18 @@ class _GuestHouseState extends State if (textControllers["from_date"]!.text.isEmpty || textControllers["to_date"]!.text.isEmpty) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - backgroundColor: Colors.redAccent, - content: Text("Please choose a valid date range."), - behavior: SnackBarBehavior.floating, - ), + + Fluttertoast.showToast( + msg: "Please choose a valid date range." , + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: Colors.redAccent, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, '#dc1c13', '#dc1c13')", ); + return; } @@ -335,13 +341,21 @@ class _GuestHouseState extends State excelName, ); - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // backgroundColor: result['status'] ? Colors.green : Colors.red, - // content: Text(result['message']), - // behavior: SnackBarBehavior.floating, - // ), - // ); + final String displayBackgroundColor = result['status'] ? '#28a745' : '#dc1c13'; + final Color displayColor = result['status'] ? Colors.green : Colors.redAccent; + final String displayMessage = result['message']; + // final bool status = result['status'] == true; + + Fluttertoast.showToast( + msg: displayMessage , + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: displayColor, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, $displayBackgroundColor, $displayBackgroundColor)", + ); } void handleDomesticFilter(String query) { diff --git a/lib/Screens/reports/misAir.dart b/lib/Screens/reports/misAir.dart index 79d0c42..88ec957 100644 --- a/lib/Screens/reports/misAir.dart +++ b/lib/Screens/reports/misAir.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:core'; import 'dart:typed_data'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; @@ -301,12 +302,16 @@ class _MISairState extends State with SingleTickerProviderStateMixin { if (textControllers["from_date"]!.text.isEmpty || textControllers["to_date"]!.text.isEmpty) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - backgroundColor: Colors.redAccent, - content: Text("Please choose a valid date range."), - behavior: SnackBarBehavior.floating, - ), + + Fluttertoast.showToast( + msg: "Please choose a valid date range.", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: Colors.redAccent, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, '#dc1c13', '#dc1c13')", ); return; } @@ -334,13 +339,21 @@ class _MISairState extends State with SingleTickerProviderStateMixin { excelName, ); - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // backgroundColor: result['status'] ? Colors.green : Colors.red, - // content: Text(result['message']), - // behavior: SnackBarBehavior.floating, - // ), - // ); + final String displayBackgroundColor = result['status'] ? '#28a745' : '#dc1c13'; + final Color displayColor = result['status'] ? Colors.green : Colors.redAccent; + final String displayMessage = result['message']; + // final bool status = result['status'] == true; + + Fluttertoast.showToast( + msg: displayMessage , + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: displayColor, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, $displayBackgroundColor, $displayBackgroundColor)", + ); } void handleDomesticFilter(String query) { diff --git a/lib/Screens/reports/misForex.dart b/lib/Screens/reports/misForex.dart index 8b4ce5d..7896f8e 100644 --- a/lib/Screens/reports/misForex.dart +++ b/lib/Screens/reports/misForex.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:core'; import 'dart:typed_data'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; @@ -262,12 +263,15 @@ class _MISforexState extends State if (textControllers["from_date"]!.text.isEmpty || textControllers["to_date"]!.text.isEmpty) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - backgroundColor: Colors.redAccent, - content: Text("Please choose a valid date range."), - behavior: SnackBarBehavior.floating, - ), + Fluttertoast.showToast( + msg: "Please choose a valid date range.", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: Colors.redAccent, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, '#dc1c13', '#dc1c13')", ); return; } @@ -295,13 +299,28 @@ class _MISforexState extends State excelName, ); - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // backgroundColor: result['status'] ? Colors.green : Colors.red, - // content: Text(result['message']), - // behavior: SnackBarBehavior.floating, - // ), - // ); + final String displayBackgroundColor = result['status'] ? '#28a745' : '#dc1c13'; + final Color displayColor = result['status'] ? Colors.green : Colors.redAccent; + final String displayMessage = result['message']; + // final bool status = result['status'] == true; + + Fluttertoast.showToast( + msg: displayMessage , + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: displayColor, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, $displayBackgroundColor, $displayBackgroundColor)", + ); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + backgroundColor: result['status'] ? Colors.green : Colors.red, + content: Text(result['message']), + behavior: SnackBarBehavior.floating, + ), + ); } void handleInternationalFilter(String query) { diff --git a/lib/Screens/reports/misHotel.dart b/lib/Screens/reports/misHotel.dart index 989a77f..18da2f4 100644 --- a/lib/Screens/reports/misHotel.dart +++ b/lib/Screens/reports/misHotel.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:core'; import 'dart:typed_data'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; @@ -302,12 +303,16 @@ class _MIShotelState extends State if (textControllers["from_date"]!.text.isEmpty || textControllers["to_date"]!.text.isEmpty) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - backgroundColor: Colors.redAccent, - content: Text("Please choose a valid date range."), - behavior: SnackBarBehavior.floating, - ), + + Fluttertoast.showToast( + msg: "Please choose a valid date range.", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: Colors.redAccent, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, '#dc1c13', '#dc1c13')", ); return; } @@ -335,13 +340,21 @@ class _MIShotelState extends State excelName, ); - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // backgroundColor: result['status'] ? Colors.green : Colors.red, - // content: Text(result['message']), - // behavior: SnackBarBehavior.floating, - // ), - // ); + final String displayBackgroundColor = result['status'] ? '#28a745' : '#dc1c13'; + final Color displayColor = result['status'] ? Colors.green : Colors.redAccent; + final String displayMessage = result['message']; + // final bool status = result['status'] == true; + + Fluttertoast.showToast( + msg: displayMessage , + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: displayColor, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, $displayBackgroundColor, $displayBackgroundColor)", + ); } void handleDomesticFilter(String query) { diff --git a/lib/Screens/reports/reportSample.dart b/lib/Screens/reports/reportSample.dart index 8db8a93..0effcb9 100644 --- a/lib/Screens/reports/reportSample.dart +++ b/lib/Screens/reports/reportSample.dart @@ -1,333 +1,2188 @@ import 'dart:convert'; -import 'dart:core'; -import 'package:go_router/go_router.dart'; + +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 'package:flutter/material.dart'; -import 'package:frontend/config/apiUrl.dart'; -import 'package:intl/intl.dart'; -import 'package:responsive_builder/responsive_builder.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import '../../routes/custom_appBar.dart'; -import '../../routes/custom_drawer.dart'; -import '../../routes/mainLayout.dart'; +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 ReportSample extends StatefulWidget { - const ReportSample({super.key}); +class PolicyCriteria extends StatefulWidget { + bool isDesktop; + String selectedService; + final ValueNotifier selectedTabNotifier; + String? userId; + bool isClass = true; + bool isCost = true; + final Function(List>?) onPolicyDataChanged; + + PolicyCriteria( + {super.key, + required this.isDesktop, + required this.selectedService, + required this.selectedTabNotifier, + required this.userId, + required this.isClass, + required this.isCost, + required this.onPolicyDataChanged}); @override - _ReportSampleState createState() => _ReportSampleState(); + PolicyCriteriaState createState() => PolicyCriteriaState(); } -class _ReportSampleState extends State { +class PolicyCriteriaState extends State { + String? ServiceId = "1"; + String? ServiceIndxId = "1"; + + String? orgId; + String? userId; + + Map? 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(); - String? userId; - String? orgId; - String? roleUser; - String? token; + Map costController = {}; + // Map classController = {}; + Map classAction = {}; + Map FirstApproverAction = {}; + Map SecondApproverAction = {}; + Map ThirdApproverAction = {}; + Map SelectedParallelProcess = {}; - Color? layoutColor; - Color? bodyColor; + Map FirstExceptionalApproverAction = {}; + Map SecondExceptionalApproverAction = {}; + Map ThirdExceptionalApproverAction = {}; + Map SelectedParallelExceptionalProcess = {}; + + + Map FirstAmendApproverAction = {}; + Map SecondAmendApproverAction = {}; + Map ThirdAmendApproverAction = {}; + Map SelectedParallelAmendProcess = {}; + Map policyDetailsIdMap = {}; // new + Map policyIdMap = {}; // new + + Map validationErrors = {}; + + // bool isClass = true; + // bool isCost = true; + + List>? policyData = []; + + // Map get policyServices { + // Map 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(); - getToken(); - } + fieldForPolicy(); - void loadInitialData() async { - String? layoutString = await getLayoutColor(); - String? bodyStringColor = await getBodyColor(); - setState(() { - layoutColor = layoutString != null ? Color(int.parse(layoutString)) - : Colors.redAccent; + widget.selectedTabNotifier.addListener(() { + print("selectedTab changed: ${widget.selectedTabNotifier.value}"); + setState(() { + ServiceIndxId = widget.selectedTabNotifier.value ?? "1"; - bodyColor = bodyStringColor != null ? Color(int.parse(bodyStringColor)) - : Colors.white; + print("ServiceIndxId changed: $ServiceIndxId"); + }); + + fieldForPolicy(); + fetchTrainFlightClass(); }); - } - Future initializeData() async { - token = await getToken(); - userId = await getUserId(); + void loadinitializeData() async { orgId = await getOrgId(); - roleUser = await getRoleUser(); - - - if (token == null || userId == null) { - print("Token or USerId missing"); - return; - } + userId = await getUserId(); } - - Future getUserId() async { - final prefs = await SharedPreferences.getInstance(); - final String? userDataString = prefs.getString('user_data'); - - if (userDataString != null) { - try { - final Map userData = jsonDecode(userDataString); - return userData["user_id"]?.toString(); - } catch (e) { - return null; - } - } - return null; - } - - Future getOrgId() async { - final prefs = await SharedPreferences.getInstance(); - final String? userDataString = prefs.getString('user_data'); - - if (userDataString != null) { - try { - final Map userData = jsonDecode(userDataString); - return userData["org_id"]?.toString(); - } catch (e) { - return null; - } - } - return null; - } - - Future getToken() async { - final prefs = await SharedPreferences.getInstance(); - return prefs.getString('auth_token'); - } - - @override - // Widget build(BuildContext context) { - // // TODO: implement build - // throw UnimplementedError(); + // void saveCurrentPolicy(List> services) { + // print("saveCurrentPolicy- $services"); + // if (ServiceId != null) { + // print("Saving curremt Add or Update"); + // addOrUpdatePolicy(ServiceId!); + // } // } - Widget build(BuildContext context) { - return ResponsiveBuilder(builder: (context, sizingInfo) { - bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop; + void saveCurrentPolicy(List> services) { + print("saveCurrentPolicy- $services"); - return Scaffold( - backgroundColor: Colors.white, - appBar: CustomAppBar(isDesktop: isDesktop), - drawer: CustomDrawer(isDesktop: false), - body: Row( - children: [ - // if (isDesktop) CustomDrawer(isDesktop: true), - Expanded(child: buildReportSampleLayout(isDesktop)) - ], - ), - ); + // 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(); + + // 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"); + 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"); + SelectedParallelExceptionalProcess.putIfAbsent(id, () => "3"); + + FirstAmendApproverAction.putIfAbsent(id, () => "None"); + SecondAmendApproverAction.putIfAbsent(id, () => "None"); + ThirdAmendApproverAction.putIfAbsent(id, () => "None"); + SelectedParallelAmendProcess.putIfAbsent(id, () => "3"); + + // Step 5: Add default policy entry + policyData?.add({ + "service_id": int.parse(id), + "cost": "", + "class": classAction[id], + "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], + "exceptional_parallel_process_from": SelectedParallelExceptionalProcess[id], + "a1_amendment_action": FirstAmendApproverAction[id], + "a2_amendment_action": SecondAmendApproverAction[id], + "a3_amendment_action": ThirdAmendApproverAction[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> details) { + 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() ?? ''; + + 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(); + 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(); + SelectedParallelAmendProcess[serviceId] = + item['amendment_parallel_process_from']?.toString() ?? "3"; + + 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); + + Map data = { + "service_id": serviceId, + "cost": costController[serviceId]?.text, + // "class": classController[serviceId]?.text, + "class": classAction[serviceId] ?? "", + "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], + "exceptional_parallel_process_from": SelectedParallelExceptionalProcess[serviceId], + "a1_amendment_action": FirstAmendApproverAction[serviceId], + "a2_amendment_action": SecondAmendApproverAction[serviceId], + "a3_amendment_action": ThirdAmendApproverAction[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]; + 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 aa1 = FirstAmendApproverAction[serviceId]; + final aa2 = SecondAmendApproverAction[serviceId]; + final aa3 = ThirdAmendApproverAction[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; + bool someExceptionalActionsMissing = [ae1, ae2, ae3].where((a) => a != null).length > 0 && + [ae1, ae2, ae3].where((a) => a == null).length > 0; + + bool allAmendActionsNull = aa1 == null && aa2 == null && aa3 == null; + bool someAmendActionsMissing = [aa1, aa2, aa3].where((a) => a != null).length > 0 && + [aa1, aa2, aa3].where((a) => a == null).length > 0; + + if (someActionsMissing) { + validationErrors[serviceId] = "All 3 approver actions must be selected."; + return; + } + if (someExceptionalActionsMissing) { + validationErrors[serviceId] = "All 3 exceptional approver actions must be selected."; + return; + } + if (someAmendActionsMissing) { + validationErrors[serviceId] = "All 3 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 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 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 fetchTrainFlightClass() async { + 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"; + // 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"); + SelectedParallelExceptionalProcess.putIfAbsent(ServiceId!, () => "3"); + + + FirstAmendApproverAction.putIfAbsent(ServiceId!, () => "None"); + SecondAmendApproverAction.putIfAbsent(ServiceId!, () => "None"); + ThirdAmendApproverAction.putIfAbsent(ServiceId!, () => "None"); + SelectedParallelAmendProcess.putIfAbsent(ServiceId!, () => "3"); }); + + widget.onPolicyDataChanged(policyData); } - Widget buildReportSampleLayout(bool isDesktop) { - return Container( child: buildFormLayout(isDesktop) ); + void printData() { + // print("policyServices - $policyServices"); } - Widget buildFormLayout(bool isDesktop) { - return Container( - margin: isDesktop ? EdgeInsets.all(10.0) : null, - padding: const EdgeInsets.only(top: 15, bottom: 15, left: 20, right: 20), - height: isDesktop - ? MediaQuery.of(context).size.height * 0.98 - : MediaQuery.of(context).size.height, - decoration: BoxDecoration( - border: isDesktop - ? Border.all(width: 2, color: Colors.white) - : null, - color: isDesktop ? Colors.white : Color(0xFFFCFCFC), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - // ------------------- First Row ------------------- - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + 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: [ - Text( - 'ReportSample', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ), - ), - Row( - children: [ - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF114D8B), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: BorderSide(color: Color(0xFF114D8B), width: 2), - ), - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - ), - onPressed: () { - // Your Excel export logic here - }, - child: Row( - children: [ - Text( - "Excel", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - color: Colors.white, - ), - ), - SizedBox(width: 8), - Icon(Icons.file_present_outlined, size: 15, color: Colors.white), - ], - ), - ), - SizedBox(width: 10), - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF114D8B), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: BorderSide(color: Color(0xFF114D8B), width: 2), - ), - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - ), - onPressed: () { - // Your PDF export logic here - }, - child: Row( - children: [ - Text( - "PDF", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - color: Colors.white, - ), - ), - SizedBox(width: 8), - Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white), - ], - ), - ), - ], - ), - ], - ), - - SizedBox(height: 15), - - // ------------------- Second Row ------------------- - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + Container( + // color: Colors.grey, + padding: + const EdgeInsets.only(top: 2, bottom: 2, left: 5, right: 5), + child: widget.isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("From Date", style: GoogleFonts.poppins(fontSize: 12)), - SizedBox(height: 5), - Container( - height: 40, - padding: EdgeInsets.symmetric(horizontal: 10), - decoration: BoxDecoration( - border: Border.all(color: Colors.grey.shade300), - borderRadius: BorderRadius.circular(8), - color: Colors.white, - ), - child: Center(child: Text("Select From Date")), // Replace with date picker - ), + if (widget.isClass) + buildClassWidget(widget.isDesktop), + SizedBox(width: 45), + if (widget.isCost!) buildCostWidget(widget.isDesktop), ], - ), - ), - SizedBox(width: 20), - Expanded( - child: Column( + ) + : Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("To Date", style: GoogleFonts.poppins(fontSize: 12)), - SizedBox(height: 5), - Container( - height: 40, - padding: EdgeInsets.symmetric(horizontal: 10), - decoration: BoxDecoration( - border: Border.all(color: Colors.grey.shade300), - borderRadius: BorderRadius.circular(8), - color: Colors.white, - ), - child: Center(child: Text("Select To Date")), // Replace with date picker - ), + if (widget.isClass!) + buildClassWidget(widget.isDesktop), + SizedBox(height: 10), + if (widget.isCost!) buildCostWidget(widget.isDesktop), ], ), ), ], ), - - SizedBox(height: 15), - - // ------------------- Third Row ------------------- - DefaultTabController( - length: 2, - child: Column( + ), + 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: [ - TabBar( - labelColor: Colors.black, - unselectedLabelColor: Colors.grey, - indicatorColor: Color(0xFF114D8B), - tabs: [ - Tab(text: "Domestic"), - Tab(text: "International"), + 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( + "Approver", + 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( + 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( + 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( + 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, + )), + ), + ], + ), + ), + ]), + ), + ), + ], + ), + + ), + ], ), - SizedBox(height: 10), - Container( - height: 200, // Set desired height for tab content - child: TabBarView( - children: [ - Center(child: Text("Domestic Content")), - Center(child: Text("International Content")), - ], - ), + + 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 Approver", + 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( + 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), + 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( + 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), + 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( + 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, + )), + ), + ], + ), + ), + ]), + ), + ), + ], + ), + + ), + + ], + ), + 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 Approver", + 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), + 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( + 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), + 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( + 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), + 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( + 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, + )), + ), + ], + ), + ), + ]), + ), + ), + ], + ), + + ), + + ], ), ], ), ), - // ------------------- Fourth Row (Table) ------------------- - Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: DataTable( - headingRowColor: MaterialStateColor.resolveWith( - (states) => Color(0xFFE6F0FA)), // Light blue header - columnSpacing: 20, - columns: [ - DataColumn(label: Text('ID', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))), - DataColumn(label: Text('Name', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))), - DataColumn(label: Text('Status', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))), - DataColumn(label: Text('Date', style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600))), - ], - rows: List.generate( - 10, - (index) => DataRow( - cells: [ - DataCell(Text('#$index', style: GoogleFonts.poppins(fontSize: 12))), - DataCell(Text('User $index', style: GoogleFonts.poppins(fontSize: 12))), - DataCell(Text(index % 2 == 0 ? 'Active' : 'Inactive', style: GoogleFonts.poppins(fontSize: 12))), - DataCell(Text('13 Jun 2025', style: GoogleFonts.poppins(fontSize: 12))), - ], + ), + ], + ); + } + + Widget buildClassWidget(isDesktop) { + List purposeList = []; + // if (ServiceId != null) { + // purposeList = (ServiceId == "1") + // ? (apiDataForClass?['flight_class'] ?? []) + // : (apiDataForClass?['train_class'] ?? []); + // } + + + + if (ServiceIndxId != null) { + purposeList = (ServiceIndxId == "1") + ? (apiDataForClass?['flight_class'] ?? []) + : (ServiceIndxId == "2") + ? (apiDataForClass?['hotel_class'] ?? []) + : (apiDataForClass?['train_class'] ?? []); + } + + + print("CLASSServiceId- $ServiceId"); + print("CLASSpurposeList - $purposeList"); + List newdropdownItems = purposeList + .map((item) => item['dropdown_value'] as String) + .toList(); + + + List> dropdownItems = purposeList + .map((item) => DropdownMenuItem( + value: item['dropdown_key'], + child: Text(item['dropdown_value']), + )) + .toList(); + + print("CLASS 2 - "); + + if (dropdownItems.isEmpty) { + dropdownItems.add( + DropdownMenuItem( + 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 && + newdropdownItems.isNotEmpty) { + // Important to wrap inside setState if async + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + classAction[ServiceId!] = dropdownItems.first.value!; + }); + }); + } + + String? selectedKey = classAction[ServiceId]; + + String? selectedItem = purposeList + .firstWhere((item) => item['dropdown_key'] == selectedKey)['dropdown_value']; + + + return Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Class", + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: widget.isDesktop, + child: SizedBox( + height: 40, + width: double.infinity, + child: ServiceId != null && (isLoading || dropdownItems.isEmpty) + ? const Center(child: CircularProgressIndicator()) + : DropdownSearch( + selectedItem: selectedItem, + items: newdropdownItems, // Must be List + popupProps: PopupProps.menu( + showSearchBox: true, + menuProps: const MenuProps(backgroundColor: Colors.white), + constraints: BoxConstraints(maxHeight: 200), + itemBuilder: (context, item, isSelected) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0), + child: Text( + item, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + ), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search...", + hintStyle: GoogleFonts.poppins(fontSize: 11), + contentPadding: EdgeInsets.symmetric(horizontal: 10), + ), + ), + ), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 8), + border: InputBorder.none, + ), + ), + dropdownBuilder: (context, selectedItem) => Align( + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + onChanged: (newValue) { + if (ServiceId != null && newValue != null) { + setState(() { + classAction[ServiceId!] = newValue; + selectedItem = newValue; + }); + } + }, + ), + ), + ), + ], + ), + ], + ); + } + + 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), ), ), ), ), - ), - - ], - ), + ], + ), + ], ); } - -} \ No newline at end of file +} diff --git a/lib/Screens/reports/servicesAnalysis.dart b/lib/Screens/reports/servicesAnalysis.dart index a4b170e..5f6dfe8 100644 --- a/lib/Screens/reports/servicesAnalysis.dart +++ b/lib/Screens/reports/servicesAnalysis.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:core'; import 'dart:typed_data'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; @@ -301,13 +302,17 @@ class _ServicesAnalysisState extends State if (textControllers["from_date"]!.text.isEmpty || textControllers["to_date"]!.text.isEmpty) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - backgroundColor: Colors.redAccent, - content: Text("Please choose a valid date range."), - behavior: SnackBarBehavior.floating, - ), + Fluttertoast.showToast( + msg: "Please choose a valid date range.", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: Colors.redAccent, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, '#dc1c13', '#dc1c13')", ); + return; } @@ -334,13 +339,21 @@ class _ServicesAnalysisState extends State excelName, ); - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // backgroundColor: result['status'] ? Colors.green : Colors.red, - // content: Text(result['message']), - // behavior: SnackBarBehavior.floating, - // ), - // ); + final String displayBackgroundColor = result['status'] ? '#28a745' : '#dc1c13'; + final Color displayColor = result['status'] ? Colors.green : Colors.redAccent; + final String displayMessage = result['message']; + // final bool status = result['status'] == true; + + Fluttertoast.showToast( + msg: displayMessage , + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: displayColor, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, $displayBackgroundColor, $displayBackgroundColor)", + ); } void handleDomesticFilter(String query) { diff --git a/lib/Screens/userManagement/create_traveller_agent/personalDetailsTravelAgent.dart b/lib/Screens/userManagement/create_traveller_agent/personalDetailsTravelAgent.dart index 87abaf7..11f5234 100644 --- a/lib/Screens/userManagement/create_traveller_agent/personalDetailsTravelAgent.dart +++ b/lib/Screens/userManagement/create_traveller_agent/personalDetailsTravelAgent.dart @@ -1193,10 +1193,15 @@ class PersonalDetailsState extends State { countryList = apiCountryData ?? []; // Map country codes to country names + // countryMap = { + // for (var item in countryList) + // item['country_code'] as String: item['country_name'] as String, + // // item['currency'] as String + // }; countryMap = { - for (var item in countryList) - item['country_code'] as String: item['country_name'] as String, - // item['currency'] as String + for (var country in countryList) + (country['country_code'] ?? ''): + '${country['country_name'] ?? ''} (${country['country_code'] ?? ''})', }; // Extract only country codes for processing @@ -1229,16 +1234,44 @@ class PersonalDetailsState extends State { fit: FlexFit.loose, // Allows flexible height menuProps: const MenuProps(backgroundColor: Colors.white), itemBuilder: - (context, item, isSelected) => Container( - padding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 6, - ), - child: Text( - item, - style: GoogleFonts.poppins(fontSize: 11.5), + // (context, item, isSelected) => Container( + // padding: EdgeInsets.symmetric( + // horizontal: 10, + // vertical: 6, + // ), + // child: Text( + // item, + // style: GoogleFonts.poppins(fontSize: 11.5), + // ), + // ), + (context, item, isSelected) { + print("contryItem - $item"); + final match = RegExp(r'^(.*)\s\((.*)\)$',).firstMatch(item); + final countryName = match?.group(1) ?? ''; + final countryCode = match?.group(2) ?? ''; + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 6.0, + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + countryName, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + Text( + countryCode, + style: GoogleFonts.poppins(fontSize: 11.5,color:Colors.grey), + + ), + ], ), ), + );}, constraints: BoxConstraints(maxHeight: 200), searchFieldProps: TextFieldProps( decoration: InputDecoration( diff --git a/lib/Screens/userManagement/create_user/personal_details.dart b/lib/Screens/userManagement/create_user/personal_details.dart index a79901f..5d6a4d5 100644 --- a/lib/Screens/userManagement/create_user/personal_details.dart +++ b/lib/Screens/userManagement/create_user/personal_details.dart @@ -1521,9 +1521,14 @@ class PersonalDetailsState extends State { Widget buildRole() { // Map dropdown_key (ID) -> dropdown_value (Name) + // Map roleMap = { + // for (var item in apiRoleData ?? []) + // item['dropdown_key'] as String: item['dropdown_value'] as String, + // }; Map roleMap = { for (var item in apiRoleData ?? []) - item['dropdown_key'] as String: item['dropdown_value'] as String, + if (item['dropdown_key'] != '5') + item['dropdown_key'].toString(): item['dropdown_value'].toString(), }; List roleNames = roleMap.values.toList(); diff --git a/lib/Screens/userManagement/user_List.dart b/lib/Screens/userManagement/user_List.dart index dcd27b9..25d4079 100644 --- a/lib/Screens/userManagement/user_List.dart +++ b/lib/Screens/userManagement/user_List.dart @@ -1,5 +1,7 @@ +import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:frontend/utils/auth_utils.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -43,6 +45,9 @@ class _UserListScreenState extends State { int currentPage = 0; int itemsPerPage = 10; + bool _isUploading = false; + bool _isDownloading = false; + @override void initState() { super.initState(); @@ -226,7 +231,7 @@ class _UserListScreenState extends State { context: context, builder: (context) => AlertDialog( // title: Text("User Details"), - title: Text("User Details - $subtitle", style: TextStyle(fontWeight: FontWeight.bold)), + title: Text("Upload Status - $subtitle", style: TextStyle(fontWeight: FontWeight.bold)), content: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -234,14 +239,14 @@ class _UserListScreenState extends State { // Text(subtitle, style: TextStyle(fontWeight: FontWeight.bold)), // // SizedBox(height: 12), - Text("Users Created Successfully :", style: TextStyle(fontWeight: FontWeight.bold)), + Text("Success Report :", style: TextStyle(fontWeight: FontWeight.bold)), if (successList.isNotEmpty) ...successList.asMap().entries.map((entry) => Text("${entry.key + 1}) ${entry.value} created.")) else - Text("-- There is no data to create. --"), + Text("-- no data. --"), SizedBox(height: 12), - Text("Failed to Create Users :", style: TextStyle(fontWeight: FontWeight.bold)), + Text("Failed Report :", style: TextStyle(fontWeight: FontWeight.bold)), if (failedList.isNotEmpty) ...failedList.asMap().entries.map((entry) { final data = entry.value["data"] ?? "-"; @@ -249,7 +254,7 @@ class _UserListScreenState extends State { return Text("${entry.key + 1}) $data - unable to create due to \"$reason\"."); }) else - Text("-- There is no failed data. --"), + Text("-- no data. --"), ], ), ), @@ -267,7 +272,28 @@ class _UserListScreenState extends State { } + Future handleDownload() async { + final result = await apiService.getDownloadUserTemplateForUpload(); + + final String displayBackgroundColor = result['status'] ? '#28a745' : '#dc1c13'; + final Color displayColor = result['status'] ? Colors.green : Colors.redAccent; + final String displayMessage = result['message']; + // final bool status = result['status'] == true; + + Fluttertoast.showToast( + msg: displayMessage , + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: displayColor, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, $displayBackgroundColor, $displayBackgroundColor)", + ); + } Future handleUpload() async { + final Completer completer = Completer(); + final String apiUrldata = '$apiUrl/api/user/userUpload'; // api final String? token = await getToken(); // 2kn @@ -287,16 +313,19 @@ class _UserListScreenState extends State { await reader.onLoadEnd.first; print(' file - extn : ${file.name.endsWith(".xlsx")}'); if (!file.name.endsWith('.xlsx')) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - // content: Text("Error: Not a valid Excel file "), - content: Text('Invalid file format. Please upload a .xlsx file.'), - backgroundColor: Colors.redAccent, - behavior: SnackBarBehavior.floating, - ), + Fluttertoast.showToast( + msg: 'Invalid file format. Please upload a .xlsx file.', + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: Colors.redAccent, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, #dc1c13, #dc1c13)", ); print("Error: Not a valid .xlsx file"); - return; + completer.complete(); // Complete even on error + return; // Wait for upload to finish before proceeding } if (reader.readyState == html.FileReader.DONE) { @@ -309,13 +338,17 @@ class _UserListScreenState extends State { if (fileBytes == null) { print('File Bytes: null'); - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // content: Text("Issues Occur In Files"), - // backgroundColor: Colors.redAccent, - // behavior: SnackBarBehavior.floating, - // ), - // ); + Fluttertoast.showToast( + msg: 'Issues occur in file format conversation', + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: Colors.redAccent, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, #dc1c13, #dc1c13)", + ); + completer.complete(); return; // No file selected } else { print('File Bytes: CALLING API'); @@ -386,18 +419,22 @@ class _UserListScreenState extends State { } else { // For non-200 responses final errorMsg = 'Failed to upload file: ${response.reasonPhrase}'; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(errorMsg), - backgroundColor: Colors.redAccent, - behavior: SnackBarBehavior.floating, - ), + Fluttertoast.showToast( + msg: errorMsg, + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 2, + backgroundColor: Colors.redAccent, + textColor: Colors.white, + fontSize: 18.0, + webBgColor: "linear-gradient(to right, #dc1c13, #dc1c13)", ); print(errorMsg); } } } + return completer.future; // Wait for upload to finish before proceeding } // if (!file.name.endsWith('.xlsx')) { @@ -747,7 +784,6 @@ class _UserListScreenState extends State { }, ), SizedBox(width: 5), - // Upload Button // OutlinedButton( // onPressed: handleUpload, @@ -762,16 +798,39 @@ class _UserListScreenState extends State { // ), // child: Text("User Bulk Upload"), // ), - IconButton( - icon: Image.asset( - 'assets/images/IconsImg/upload.png', - width: 25, - height: 25, + // IconButton( + // icon: Image.asset( + // 'assets/images/IconsImg/upload.png', + // width: 25, + // height: 25, + // ), + // tooltip: 'User Bulk Upload', + // onPressed: () { + // handleUpload(); + // }, + // ), + // UPLOAD BUTTON + Align( + alignment: Alignment.centerLeft, + child: _isUploading + ? const SizedBox( + width: 28, + height: 28, + child: CircularProgressIndicator(strokeWidth: 3), + ) + : IconButton( + icon: Image.asset( + 'assets/images/IconsImg/upload.png', + width: 25, + height: 25, + ), + tooltip: 'User Bulk Upload', + onPressed: () async { + setState(() => _isUploading = true); + await handleUpload(); + setState(() => _isUploading = false); + }, ), - tooltip: 'User Bulk Upload', - onPressed: () { - handleUpload(); - }, ), // Spacer(), SizedBox(width: 5), diff --git a/lib/routes/organizationSetting.dart b/lib/routes/organizationSetting.dart index 0b6865a..95663ad 100644 --- a/lib/routes/organizationSetting.dart +++ b/lib/routes/organizationSetting.dart @@ -20,6 +20,8 @@ class OrganizationSettingState extends State { final ApiService apiService = ApiService(); Color? layoutColor; + String? roleUser = ""; + void initState() { super.initState(); loadInitialData(); @@ -28,7 +30,7 @@ class OrganizationSettingState extends State { void loadInitialData() async { String? layoutString = await getLayoutColor(); // String? bodyStringColor = await getBodyColor(); - + roleUser = await getRoleUser(); setState(() { layoutColor = layoutString != null @@ -103,7 +105,6 @@ class OrganizationSettingState extends State { 'label': 'Travel Policies', 'description': 'Create and Edit Travel Policy', }, - { 'value': '/getPerdiem', 'icon': Icons.attach_money, @@ -154,6 +155,10 @@ class OrganizationSettingState extends State { }, ]; + if (roleUser == "Travel Admin") { + menuItems.removeWhere((item) => item['value'] == '/OrganizationSetup'); + } + // List rows = []; // for (int i = 0; i < menuItems.length; i += cardsPerRow) { // List cards = []; diff --git a/lib/services/apiService.dart b/lib/services/apiService.dart index 8e459aa..664c5c1 100644 --- a/lib/services/apiService.dart +++ b/lib/services/apiService.dart @@ -898,7 +898,7 @@ class ApiService { } // download the Template for bulk upload the user - Future getDownloadUserTemplateForUpload() async { + Future> getDownloadUserTemplateForUpload() async { final String apiUrldata = '$apiUrl/api/user/userUploadTemplate'; // download the Template for bulk upload user => api @@ -936,29 +936,14 @@ class ApiService { // Revoke the download URL to free up resources html.Url.revokeObjectUrl(url); + return {'status': true, 'message': 'Successfully Downloaded'}; } catch (e) { - throw Exception('Error parsing response: $e'); + return {'status': false, 'message': 'Download error: $e'}; } } else if (response.statusCode == 404) { - // showDialog( - // context: context, - // builder: (BuildContext context) { - // return AlertDialog( - // title: Text('File not found.'), - // // content: Text('File not found.'), - // actions: [ - // TextButton( - // child: Text('OK'), - // onPressed: () { - // Navigator.of(context).pop(); // Close the dialog - // }, - // ), - // ], - // ); - // }, - // ); + return {'status': false, 'message': 'File not found (404).'}; } else { - throw Exception('Failed to load plans'); + return {'status': false, 'message': 'Failed to download. Try again.'}; } } @@ -1056,7 +1041,7 @@ class ApiService { // --- Future> getDepartmentDetailsFind(int id) async { - final String apiUrldata = '$apiUrl/api/findDepartment?department_id=$id'; + final String apiUrldata = '$apiUrl/api/findDepartment?id=$id'; final token = await getToken(); @@ -1560,11 +1545,7 @@ class ApiService { } } - Future reportExcelDownload( - String apiRoute, - String body, - String name, - ) async { + Future> reportExcelDownload(String apiRoute,String body,String name,) async { final String apiUrldata = '$apiUrl/api/$apiRoute'; // Sanitize name for filename (optional) @@ -1607,14 +1588,18 @@ class ApiService { // Revoke the download URL to free up resources html.Url.revokeObjectUrl(url); - throw Exception('Sucessfully Downloaded'); + // throw Exception('Sucessfully Downloaded'); + return {'status': true, 'message': 'Successfully Downloaded'}; } catch (e) { - throw Exception('Error parsing response: $e'); + // throw Exception('Error parsing response: $e'); + return {'status': false, 'message': 'Download error: $e'}; } } else if (response.statusCode == 404) { - throw Exception('File not found.'); + // throw Exception('File not found.'); + return {'status': false, 'message': 'File not found (404).'}; } else { - throw Exception('Failed to Download'); + // throw Exception('Failed to Download'); + return {'status': false, 'message': 'Failed to download. Try again.'}; } } diff --git a/lib/widgets/popup_travelAgentList_action.dart b/lib/widgets/popup_travelAgentList_action.dart index 671384f..e928223 100644 --- a/lib/widgets/popup_travelAgentList_action.dart +++ b/lib/widgets/popup_travelAgentList_action.dart @@ -40,25 +40,25 @@ class UserActionsMenu extends StatelessWidget { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ - GestureDetector( - child: Tooltip( - message: 'View Details', - child: Icon(Icons.remove_red_eye, - color: Color(0xFF475569), size: 18) - ), - // child: Icon(Icons.remove_red_eye, - // color: Color(0xFF475569), size: 18,), - onTap: () async { - Navigator.pop(context); // Close the menu - final userId = getUserId(user['user_id']); - final usersData = await getUserDetails(userId); - context.go("/CreateTravelAgent", extra: { - "selectedUser": usersData, - "isViewMode": true, - }); - }, - ), - SizedBox(width: 8), + // GestureDetector( + // child: Tooltip( + // message: 'View Details', + // child: Icon(Icons.remove_red_eye, + // color: Color(0xFF475569), size: 18) + // ), + // // child: Icon(Icons.remove_red_eye, + // // color: Color(0xFF475569), size: 18,), + // onTap: () async { + // Navigator.pop(context); // Close the menu + // final userId = getUserId(user['user_id']); + // final usersData = await getUserDetails(userId); + // context.go("/CreateTravelAgent", extra: { + // "selectedUser": usersData, + // "isViewMode": true, + // }); + // }, + // ), + // SizedBox(width: 8), GestureDetector( child: Tooltip( message: 'Edit Details', diff --git a/lib/widgets/popup_userList_action.dart b/lib/widgets/popup_userList_action.dart index 5ff7a85..45c5a2a 100644 --- a/lib/widgets/popup_userList_action.dart +++ b/lib/widgets/popup_userList_action.dart @@ -40,25 +40,25 @@ class UserActionsMenu extends StatelessWidget { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ - GestureDetector( - child: Tooltip( - message: 'View Details', - child: Icon(Icons.remove_red_eye, - color: Color(0xFF475569), size: 18) - ), - // child: Icon(Icons.remove_red_eye, - // color: Color(0xFF475569), size: 18,), - onTap: () async { - Navigator.pop(context); // Close the menu - final userId = getUserId(user['user_id']); - final usersData = await getUserDetails(userId); - context.go("/CreateUserDetails", extra: { - "selectedUser": usersData, - "isViewMode": true, - }); - }, - ), - SizedBox(width: 8), + // GestureDetector( + // child: Tooltip( + // message: 'View Details', + // child: Icon(Icons.remove_red_eye, + // color: Color(0xFF475569), size: 18) + // ), + // // child: Icon(Icons.remove_red_eye, + // // color: Color(0xFF475569), size: 18,), + // onTap: () async { + // Navigator.pop(context); // Close the menu + // final userId = getUserId(user['user_id']); + // final usersData = await getUserDetails(userId); + // context.go("/CreateUserDetails", extra: { + // "selectedUser": usersData, + // "isViewMode": true, + // }); + // }, + // ), + // SizedBox(width: 8), GestureDetector( child: Tooltip( message: 'Edit Details', From 045b2565510e319602362e84b0682bf8f199e565 Mon Sep 17 00:00:00 2001 From: venba-Inspriron-3558 Date: Mon, 23 Jun 2025 16:13:22 +0530 Subject: [PATCH 2/2] reportsample deleted --- lib/Screens/reports/reportSample.dart | 2188 ------------------------- 1 file changed, 2188 deletions(-) delete mode 100644 lib/Screens/reports/reportSample.dart diff --git a/lib/Screens/reports/reportSample.dart b/lib/Screens/reports/reportSample.dart deleted file mode 100644 index 0effcb9..0000000 --- a/lib/Screens/reports/reportSample.dart +++ /dev/null @@ -1,2188 +0,0 @@ -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 selectedTabNotifier; - String? userId; - bool isClass = true; - bool isCost = true; - - final Function(List>?) onPolicyDataChanged; - - PolicyCriteria( - {super.key, - required this.isDesktop, - required this.selectedService, - required this.selectedTabNotifier, - required this.userId, - required this.isClass, - required this.isCost, - required this.onPolicyDataChanged}); - @override - PolicyCriteriaState createState() => PolicyCriteriaState(); -} - -class PolicyCriteriaState extends State { - String? ServiceId = "1"; - String? ServiceIndxId = "1"; - - String? orgId; - String? userId; - - Map? 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 costController = {}; - // Map classController = {}; - Map classAction = {}; - Map FirstApproverAction = {}; - Map SecondApproverAction = {}; - Map ThirdApproverAction = {}; - Map SelectedParallelProcess = {}; - - - Map FirstExceptionalApproverAction = {}; - Map SecondExceptionalApproverAction = {}; - Map ThirdExceptionalApproverAction = {}; - Map SelectedParallelExceptionalProcess = {}; - - - Map FirstAmendApproverAction = {}; - Map SecondAmendApproverAction = {}; - Map ThirdAmendApproverAction = {}; - Map SelectedParallelAmendProcess = {}; - Map policyDetailsIdMap = {}; // new - Map policyIdMap = {}; // new - - Map validationErrors = {}; - - // bool isClass = true; - // bool isCost = true; - - List>? policyData = []; - - // Map get policyServices { - // Map 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(); - fieldForPolicy(); - - - - widget.selectedTabNotifier.addListener(() { - print("selectedTab changed: ${widget.selectedTabNotifier.value}"); - setState(() { - ServiceIndxId = widget.selectedTabNotifier.value ?? "1"; - - print("ServiceIndxId changed: $ServiceIndxId"); - }); - - fieldForPolicy(); - fetchTrainFlightClass(); - }); - } - - void loadinitializeData() async { - orgId = await getOrgId(); - userId = await getUserId(); - } - - // void saveCurrentPolicy(List> services) { - // print("saveCurrentPolicy- $services"); - // if (ServiceId != null) { - // print("Saving curremt Add or Update"); - // addOrUpdatePolicy(ServiceId!); - // } - // } - - void saveCurrentPolicy(List> 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(); - - // 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"); - 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"); - SelectedParallelExceptionalProcess.putIfAbsent(id, () => "3"); - - FirstAmendApproverAction.putIfAbsent(id, () => "None"); - SecondAmendApproverAction.putIfAbsent(id, () => "None"); - ThirdAmendApproverAction.putIfAbsent(id, () => "None"); - SelectedParallelAmendProcess.putIfAbsent(id, () => "3"); - - // Step 5: Add default policy entry - policyData?.add({ - "service_id": int.parse(id), - "cost": "", - "class": classAction[id], - "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], - "exceptional_parallel_process_from": SelectedParallelExceptionalProcess[id], - "a1_amendment_action": FirstAmendApproverAction[id], - "a2_amendment_action": SecondAmendApproverAction[id], - "a3_amendment_action": ThirdAmendApproverAction[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> details) { - 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() ?? ''; - - 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(); - 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(); - SelectedParallelAmendProcess[serviceId] = - item['amendment_parallel_process_from']?.toString() ?? "3"; - - 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); - - Map data = { - "service_id": serviceId, - "cost": costController[serviceId]?.text, - // "class": classController[serviceId]?.text, - "class": classAction[serviceId] ?? "", - "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], - "exceptional_parallel_process_from": SelectedParallelExceptionalProcess[serviceId], - "a1_amendment_action": FirstAmendApproverAction[serviceId], - "a2_amendment_action": SecondAmendApproverAction[serviceId], - "a3_amendment_action": ThirdAmendApproverAction[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]; - 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 aa1 = FirstAmendApproverAction[serviceId]; - final aa2 = SecondAmendApproverAction[serviceId]; - final aa3 = ThirdAmendApproverAction[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; - bool someExceptionalActionsMissing = [ae1, ae2, ae3].where((a) => a != null).length > 0 && - [ae1, ae2, ae3].where((a) => a == null).length > 0; - - bool allAmendActionsNull = aa1 == null && aa2 == null && aa3 == null; - bool someAmendActionsMissing = [aa1, aa2, aa3].where((a) => a != null).length > 0 && - [aa1, aa2, aa3].where((a) => a == null).length > 0; - - if (someActionsMissing) { - validationErrors[serviceId] = "All 3 approver actions must be selected."; - return; - } - if (someExceptionalActionsMissing) { - validationErrors[serviceId] = "All 3 exceptional approver actions must be selected."; - return; - } - if (someAmendActionsMissing) { - validationErrors[serviceId] = "All 3 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 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 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 fetchTrainFlightClass() async { - 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"; - // 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"); - SelectedParallelExceptionalProcess.putIfAbsent(ServiceId!, () => "3"); - - - FirstAmendApproverAction.putIfAbsent(ServiceId!, () => "None"); - SecondAmendApproverAction.putIfAbsent(ServiceId!, () => "None"); - ThirdAmendApproverAction.putIfAbsent(ServiceId!, () => "None"); - SelectedParallelAmendProcess.putIfAbsent(ServiceId!, () => "3"); - }); - - 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( - "Approver", - 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( - 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( - 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( - 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 Approver", - 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( - 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), - 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( - 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), - 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( - 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, - )), - ), - ], - ), - ), - ]), - ), - ), - ], - ), - - ), - - ], - ), - 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 Approver", - 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), - 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( - 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), - 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( - 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), - 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( - 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, - )), - ), - ], - ), - ), - ]), - ), - ), - ], - ), - - ), - - ], - ), - ], - ), - ), - ), - ], - ); - } - - Widget buildClassWidget(isDesktop) { - List purposeList = []; - // if (ServiceId != null) { - // purposeList = (ServiceId == "1") - // ? (apiDataForClass?['flight_class'] ?? []) - // : (apiDataForClass?['train_class'] ?? []); - // } - - - - if (ServiceIndxId != null) { - purposeList = (ServiceIndxId == "1") - ? (apiDataForClass?['flight_class'] ?? []) - : (ServiceIndxId == "2") - ? (apiDataForClass?['hotel_class'] ?? []) - : (apiDataForClass?['train_class'] ?? []); - } - - - print("CLASSServiceId- $ServiceId"); - print("CLASSpurposeList - $purposeList"); - List newdropdownItems = purposeList - .map((item) => item['dropdown_value'] as String) - .toList(); - - - List> dropdownItems = purposeList - .map((item) => DropdownMenuItem( - value: item['dropdown_key'], - child: Text(item['dropdown_value']), - )) - .toList(); - - print("CLASS 2 - "); - - if (dropdownItems.isEmpty) { - dropdownItems.add( - DropdownMenuItem( - 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 && - newdropdownItems.isNotEmpty) { - // Important to wrap inside setState if async - WidgetsBinding.instance.addPostFrameCallback((_) { - setState(() { - classAction[ServiceId!] = dropdownItems.first.value!; - }); - }); - } - - String? selectedKey = classAction[ServiceId]; - - String? selectedItem = purposeList - .firstWhere((item) => item['dropdown_key'] == selectedKey)['dropdown_value']; - - - return Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Class", - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: widget.isDesktop, - child: SizedBox( - height: 40, - width: double.infinity, - child: ServiceId != null && (isLoading || dropdownItems.isEmpty) - ? const Center(child: CircularProgressIndicator()) - : DropdownSearch( - selectedItem: selectedItem, - items: newdropdownItems, // Must be List - popupProps: PopupProps.menu( - showSearchBox: true, - menuProps: const MenuProps(backgroundColor: Colors.white), - constraints: BoxConstraints(maxHeight: 200), - itemBuilder: (context, item, isSelected) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0), - child: Text( - item, - style: GoogleFonts.poppins(fontSize: 11.5), - ), - ), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search...", - hintStyle: GoogleFonts.poppins(fontSize: 11), - contentPadding: EdgeInsets.symmetric(horizontal: 10), - ), - ), - ), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 8), - border: InputBorder.none, - ), - ), - dropdownBuilder: (context, selectedItem) => Align( - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins(fontSize: 11), - ), - ), - onChanged: (newValue) { - if (ServiceId != null && newValue != null) { - setState(() { - classAction[ServiceId!] = newValue; - selectedItem = newValue; - }); - } - }, - ), - ), - ), - ], - ), - ], - ); - } - - 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), - ), - ), - ), - ), - ], - ), - ], - ); - } -}