diff --git a/assets/images/login/login_terminal.png b/assets/images/login/login_terminal.png new file mode 100644 index 0000000..e2b3bb1 Binary files /dev/null and b/assets/images/login/login_terminal.png differ diff --git a/assets/images/login/login_travel.png b/assets/images/login/login_travel.png new file mode 100644 index 0000000..f53fb82 Binary files /dev/null and b/assets/images/login/login_travel.png differ diff --git a/lib/Screens/authentication/login/login_widget.dart b/lib/Screens/authentication/login/login_widget.dart index ec9f1d7..2a38b92 100644 --- a/lib/Screens/authentication/login/login_widget.dart +++ b/lib/Screens/authentication/login/login_widget.dart @@ -256,7 +256,8 @@ class _LoginWidgetState extends State { double formWidth = widget.isTablet ? 400 : 300; return Container( - color: Color(0xFF114D8B), + // color: Color(0xFF114D8B), + color: Color(0xFFf5f5f5), padding: const EdgeInsets.all(20), child: Row( children: [ @@ -266,11 +267,15 @@ class _LoginWidgetState extends State { child: Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('assets/images/login/login_img1.png'), - fit: BoxFit.fill - // fit: BoxFit.cover, // or BoxFit.contain, BoxFit.fill, etc. - ), - color: Colors.blueAccent, + image: AssetImage( + 'assets/images/login/login_travel.png', + ), + + // fit: BoxFit.fill + // fit: BoxFit.contain + // fit: BoxFit.cover, // or BoxFit.contain, BoxFit.fill, etc. + ), + color: Colors.white, borderRadius: BorderRadius.only( topRight: Radius.circular(25), // Rounded top-left corner bottomRight: @@ -278,7 +283,9 @@ class _LoginWidgetState extends State { ), ), child: Padding( - padding: const EdgeInsets.only(left: 0), + padding: const EdgeInsets.only( + left: 0, + ), child: Align( alignment: Alignment.topLeft, child: Image.asset( diff --git a/lib/Screens/itnerary/flights.dart b/lib/Screens/itnerary/flights.dart index 7db00f3..5eab88f 100644 --- a/lib/Screens/itnerary/flights.dart +++ b/lib/Screens/itnerary/flights.dart @@ -19,9 +19,11 @@ class FlightScreen extends StatefulWidget { final Function(bool) onClose; final Function(Map) onSaveFlight; final Map? selectedItem; + final ValueNotifier tripTypeNotifier; FlightScreen( - {required this.apiData, + {Key? key, + required this.apiData, required this.loginUser, required this.onClose, required this.onSaveFlight, @@ -29,13 +31,15 @@ class FlightScreen extends StatefulWidget { required this.flightData, required this.hasAction, this.tripType, - this.apiDataForClass}); + required this.tripTypeNotifier, + this.apiDataForClass}) + : super(key: key); @override - _FlightScreenState createState() => _FlightScreenState(); + FlightScreenState createState() => FlightScreenState(); } -class _FlightScreenState extends State { +class FlightScreenState extends State { ApiService apiService = ApiService(); final GlobalKey _formKey = GlobalKey(); @@ -77,7 +81,7 @@ class _FlightScreenState extends State { List> rowBuilders = []; // Holds row widgets List controllers = []; // Dynamic controllers - + bool _hasInitialTripTypeLoaded = false; Map errorMessages = {}; // forex_pre_paid_card_number @override @@ -86,6 +90,24 @@ class _FlightScreenState extends State { print("TripType - ${widget.tripType}"); + // final newTripType = widget.tripTypeNotifier.value; + // print("TripType1 - $newTripType"); + + // // Listen immediately + // widget.tripTypeNotifier.addListener(() { + // final newTripType = widget.tripTypeNotifier.value; + // + // if (newTripType != null && newTripType.isNotEmpty) { + // if (_hasInitialTripTypeLoaded) { + // print("🚀 FlightScreen reacting to new trip type: $newTripType"); + // loadCountryList(newTripType); + // } else { + // print("🟡 Skipping initial tripTypeNotifier value: $newTripType"); + // _hasInitialTripTypeLoaded = true; + // } + // } + // }); + // _initializeRows(); // List purposeList = widget.apiData?['flight_trip_type'] ?? []; // selectedTripType ??= purposeList.isNotEmpty ? purposeList.first['dropdown_value'] : null; @@ -135,7 +157,7 @@ class _FlightScreenState extends State { textControllers["_time${i}Controller"] ?.addListener(() => _clearError("time_$i")); } - loadCountryList(); + // loadCountryList(); flightFirstTripDateNotifier = ValueNotifier(null); flightLastTripDateNotifier = ValueNotifier(null); @@ -144,6 +166,14 @@ class _FlightScreenState extends State { final result = getFlightTripDateRange(widget.flightData); flightFirstTripDateNotifier.value = result['firstTripDate']; flightLastTripDateNotifier.value = result['lastTripDate']; + final tripTypeValue = widget.tripTypeNotifier.value; + + if (tripTypeValue != null && tripTypeValue.isNotEmpty) { + print("🚀 Initial loadCountryList for tripType: $tripTypeValue"); + loadCountryList(tripTypeValue); + } else { + print("⚠️ tripType is null or empty, skipping loadCountryList"); + } }); } @@ -203,12 +233,14 @@ class _FlightScreenState extends State { // isCountryLoading = false; // }); // } - Future loadCountryList() async { + Future loadCountryList(newTripType) async { + print("🔄 loadCountryList called with tripType: ${newTripType}"); + setState(() { isCountryLoading = true; }); - final result = await apiService.fetchFlightsCountryList(widget.tripType); + final result = await apiService.fetchFlightsCountryList(newTripType); print("ResultCountry : $result"); @@ -1007,6 +1039,8 @@ class _FlightScreenState extends State { } List _buildSecondRow(bool isDesktop, int index) { + bool isFlightClassLoading = widget.apiDataForClass?['flight_class'] == null; + List purposeList = widget.apiDataForClass?['flight_class'] ?? []; List> dropdownItems = purposeList @@ -1344,7 +1378,7 @@ class _FlightScreenState extends State { // : MediaQuery.of(context).size.width * 0.66, child: SizedBox( height: 40, - child: isCountryLoading + child: isFlightClassLoading ? const Center(child: CircularProgressIndicator()) : DropdownButtonFormField( focusNode: focusNodes["_class${index}FocusNode"], diff --git a/lib/Screens/itnerary/forex.dart b/lib/Screens/itnerary/forex.dart index e784833..c9e67c2 100644 --- a/lib/Screens/itnerary/forex.dart +++ b/lib/Screens/itnerary/forex.dart @@ -349,6 +349,7 @@ class _ForexScreenState extends State { void handleUpdatedField() async { // Set the selected value if available + userCardNumber = await getForexCardNumber(); // userCardNumber = "CD7909043"; print("userCardNumber - $userCardNumber"); diff --git a/lib/Screens/plans/create_plans.dart b/lib/Screens/plans/create_plans.dart index e0ec347..77c737c 100644 --- a/lib/Screens/plans/create_plans.dart +++ b/lib/Screens/plans/create_plans.dart @@ -25,6 +25,7 @@ import '../../widgets/custom_radio_button.dart'; import '../../widgets/custom_text_field.dart'; import '../approvals/approval_dialogs.dart'; import '../dialog/user_selection_dialog.dart'; +import '../itnerary/flights.dart'; class CreatePlan extends StatefulWidget { CreatePlan({super.key}); @@ -294,6 +295,10 @@ class CreateNewPlan extends StatefulWidget { class CreateNewPlansState extends State { final GlobalKey dynamicItineraryKey = GlobalKey(); + final GlobalKey flightScreenKey = + GlobalKey(); + + late final ValueNotifier flightTripTypeNotifier; final ApiService apiService = ApiService(); @@ -438,6 +443,9 @@ class CreateNewPlansState extends State { @override void initState() { super.initState(); + + flightTripTypeNotifier = ValueNotifier(null); + fetchUserDetails(); fetchPlans(); @@ -479,6 +487,7 @@ class CreateNewPlansState extends State { widget.selectedPlanData['description'] ?? ''; _selectedTripType = widget.selectedPlanData['trip_type']; + flightTripTypeNotifier.value = widget.selectedPlanData['trip_type']; _selectedIsBillable = widget.selectedPlanData['is_billable'] == "1" ? "1" : "2"; @@ -1408,6 +1417,8 @@ class CreateNewPlansState extends State { Expanded( child: DynamicItinerary( key: dynamicItineraryKey, + flightScreenKey: flightScreenKey, + tripTypeNotifier: flightTripTypeNotifier, hasAction: hasAction, tripType: _selectedTripType, apiData: apiData, @@ -1538,6 +1549,10 @@ class CreateNewPlansState extends State { setState(() { _selectedTripType = newItem['dropdown_key'].toString(); + // Notify FlightScreen + flightTripTypeNotifier.value = _selectedTripType; + print( + "flightTripTypeNotifier- ${flightTripTypeNotifier.value}"); fetchTrainFlightClass( int.parse(_selectedTripType!)); dynamicItineraryKey.currentState diff --git a/lib/Screens/plans/dynamic_itinerary_stepper.dart b/lib/Screens/plans/dynamic_itinerary_stepper.dart index cf8bfc2..2d9ead4 100644 --- a/lib/Screens/plans/dynamic_itinerary_stepper.dart +++ b/lib/Screens/plans/dynamic_itinerary_stepper.dart @@ -36,6 +36,8 @@ class DynamicItinerary extends StatefulWidget { onItineraryUpdate; // Updated Signature final Map selectedPlanData; final bool isViewMode; + final GlobalKey flightScreenKey; + final ValueNotifier tripTypeNotifier; const DynamicItinerary( {super.key, @@ -47,7 +49,9 @@ class DynamicItinerary extends StatefulWidget { required this.isViewMode, required this.hasAction, this.tripType, - this.apiDataForClass}); + this.apiDataForClass, + required this.tripTypeNotifier, + required this.flightScreenKey}); @override DynamicItineraryState createState() => DynamicItineraryState(); @@ -692,6 +696,8 @@ class DynamicItineraryState extends State { case "Flight": default: selectedWidget = FlightScreen( + key: widget.flightScreenKey, + tripTypeNotifier: widget.tripTypeNotifier, hasAction: widget.hasAction, tripType: widget.tripType, onClose: handleClose, diff --git a/lib/Screens/userManagement/create_user/office_details.dart b/lib/Screens/userManagement/create_user/office_details.dart index 64007ae..1cd3a01 100644 --- a/lib/Screens/userManagement/create_user/office_details.dart +++ b/lib/Screens/userManagement/create_user/office_details.dart @@ -157,8 +157,10 @@ class _OfficeDetailsState extends State { setState(() { // apiUserData = users; - apiUserData = users.where((user) => user["role_id"] == "4").toList(); + print("Total users fetched from API: ${users.length}"); + apiUserData = users.where((user) => user["role_id"] != "5").toList(); + print("Total users fetched from API1: ${apiUserData?.length}"); print("APIUSerDATa - $apiUserData"); userList = apiUserData ?? []; diff --git a/lib/routes/custom_appBar.dart b/lib/routes/custom_appBar.dart index c4c207a..093004e 100644 --- a/lib/routes/custom_appBar.dart +++ b/lib/routes/custom_appBar.dart @@ -40,6 +40,7 @@ class _CustomAppBarState extends State { Map? userData; Map? fetchedUserData; Map userDetails = {}; + Map profileUserDetails = {}; Map? selectedOrg; Color? layoutColor; @@ -59,6 +60,24 @@ class _CustomAppBarState extends State { }); } + Future getProfileUser() async { + print("getProfileUser - $userData"); + print("getProfileUser - ${userData?['user_id']}"); + + final userIdRaw = userData?['user_id']; + final int? userId = + userIdRaw is int ? userIdRaw : int.tryParse(userIdRaw.toString()); + + if (userId != null) { + profileUserDetails = await apiService.getSingleUser(userId); + print("getProfileUser-$profileUserDetails"); + } else { + print("❌ Invalid user_id: $userIdRaw"); + } + + print("getProfileUser-$profileUserDetails"); + } + Future initializeData() async { print("initializeDatainitializeData"); token = await getToken(); @@ -72,6 +91,7 @@ class _CustomAppBarState extends State { setState(() { userData = fetchedUserData; }); + getProfileUser(); } String getTabLabel(TabSelection tab) { @@ -480,8 +500,7 @@ class _CustomAppBarState extends State { context.go( "/CreateUserDetails", extra: { - "selectedUser": userDetails, - "isEditProfile": true, + "selectedUser": profileUserDetails, "isEditProfile": true, "isViewMode": false, }, diff --git a/lib/utils/auth_utils.dart b/lib/utils/auth_utils.dart index 5c55f6c..ebc01f6 100644 --- a/lib/utils/auth_utils.dart +++ b/lib/utils/auth_utils.dart @@ -67,6 +67,7 @@ Future getRoleUser() async { Future getForexCardNumber() async { final prefs = await SharedPreferences.getInstance(); final String? userDataString = prefs.getString('user_data'); + // final String? userDataString = prefs.getString('user_data'); if (userDataString != null) { try { diff --git a/pubspec.yaml b/pubspec.yaml index 4e3115c..8ff0a0e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -75,6 +75,8 @@ flutter: uses-material-design: true assets: - assets/images/login/login_img1.png + - assets/images/login/login_terminal.png + - assets/images/login/login_travel.png - assets/images/login/travelSpend_Logo.png - assets/images/login/TravelSpendsLogo1.png - assets/images/login/VectorG.png