From 305ac4f329bcd7c78e5b5adb3c934242f7e6c71f Mon Sep 17 00:00:00 2001 From: venba-Inspriron-3558 Date: Wed, 18 Jun 2025 18:59:48 +0530 Subject: [PATCH] report completed 3 --- lib/Screens/reports/advancePurchase.dart | 275 ++++++++++++++-------- lib/Screens/reports/guestHouse.dart | 216 ++++++++++++++--- lib/Screens/reports/misAir.dart | 213 ++++++++++++++--- lib/Screens/reports/misForex.dart | 170 ++++++++----- lib/Screens/reports/misHotel.dart | 208 ++++++++++++++-- lib/Screens/reports/servicesAnalysis.dart | 198 +++++++++++++--- 6 files changed, 1016 insertions(+), 264 deletions(-) diff --git a/lib/Screens/reports/advancePurchase.dart b/lib/Screens/reports/advancePurchase.dart index 4c2cec3..684492d 100644 --- a/lib/Screens/reports/advancePurchase.dart +++ b/lib/Screens/reports/advancePurchase.dart @@ -53,9 +53,10 @@ class _AdvancePurchaseState extends State List> internationalData = []; // Map domesticData = {}; // Map internationalData = {}; - // List> filteredDomestic = []; - List filteredInternational = []; - TextEditingController searchController = TextEditingController(); + List> filteredDomestic = []; + List> filteredInternational = []; + TextEditingController searchDomesticController = TextEditingController(); + TextEditingController searchInternationalController = TextEditingController(); bool loaderFlag = false; @@ -100,9 +101,7 @@ class _AdvancePurchaseState extends State switch (index) { case 0: return "domestic"; case 1: return "international"; - default: - // return "Unknown"; - return "domestic"; + default: return "domestic"; // return "Unknown"; } } @@ -159,7 +158,7 @@ class _AdvancePurchaseState extends State loadInitialData(); }); } catch (e) { - print("service report : $e"); + print("advance report : $e"); } } @@ -260,7 +259,7 @@ class _AdvancePurchaseState extends State domesticData = List>.from( result['status'] == 'success' ? result['data']['domestic'] ?? [] : [], ); - // filteredDomestic = domesticData; + filteredDomestic = domesticData; internationalData = List>.from( @@ -268,6 +267,8 @@ class _AdvancePurchaseState extends State ? result['data']['international'] ?? [] : [], ); + filteredInternational = internationalData; + loaderFlag = false; }); } catch (e) { @@ -327,44 +328,42 @@ class _AdvancePurchaseState extends State ); } - // void handleDomesticFilter(String query) { - // print(" so sad :( ** "); - // print("filtereddomesticData: $domesticData"); - // - // final lowerQuery = query.toLowerCase(); - // setState(() { - // filteredDomestic = - // domesticData.where((object) { - // return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) || - // (object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) || - // (object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) || - // (object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) || - // (object['flight_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || - // (object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || - // (object['sector']?.toLowerCase().contains(lowerQuery)); - // }).toList(); - // currentPage1 = 0; - // }); - // print("filtereddomesticData: $filteredDomestic"); - // } + void handleDomesticFilter(String query) { - // void handleInternationalFilter(String query) { - // final lowerQuery = query.toLowerCase(); - // setState(() { - // filteredInternational = - // internationalData.where((object) { - // return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) || - // (object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) || - // (object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) || - // (object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) || - // (object['flight_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || - // (object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || - // (object['sector']?.toLowerCase().contains(lowerQuery)); - // }).toList(); - // currentPage1 = 0; - // }); - // print("filteredInternational: $filteredInternational"); - // } + final lowerQuery = query.toLowerCase(); + setState(() { + filteredDomestic = + domesticData.where((object) { + return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['sector']?.toLowerCase().contains(lowerQuery)); + }).toList(); + currentPage1 = 0; + }); + print("handleDomesticFilter > Total entries: ${filteredDomestic?.length ?? 0}"); + } + + void handleInternationalFilter(String query) { + final lowerQuery = query.toLowerCase(); + setState(() { + filteredInternational = + internationalData.where((object) { + return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['sector']?.toLowerCase().contains(lowerQuery)); + }).toList(); + currentPage2 = 0; + }); + print("handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}"); + } @override // Widget build(BuildContext context) { @@ -763,45 +762,45 @@ class _AdvancePurchaseState extends State .ellipsis, // Ensures title doesn't overflow ), ), - // SizedBox(width: 16), - // Container( - // width: MediaQuery.of(context).size.width * 0.2, - // height: 40, - // child: TextField( - // controller: searchController, - // onChanged: handleDomesticFilter, - // decoration: InputDecoration( - // hintText: "Search ...", - // hintStyle: TextStyle( - // fontSize: 12, - // color: Color(0xFF9E9DBD), - // ), - // prefixIcon: Icon( - // Icons.search, - // color: Color(0xFF9E9DBD), - // size: 18, - // ), - // border: OutlineInputBorder( - // borderRadius: BorderRadius.circular(12), - // ), - // enabledBorder: OutlineInputBorder( - // borderRadius: BorderRadius.circular(12), - // borderSide: BorderSide( - // color: Colors.grey.shade200, - // width: 0.5, - // ), - // ), - // focusedBorder: OutlineInputBorder( - // borderRadius: BorderRadius.circular(12), - // borderSide: BorderSide( - // color: Colors.grey.shade300, - // width: 1, - // ), - // ), - // ), - // style: GoogleFonts.poppins(fontSize: 12), - // ), - // ), + SizedBox(width: 16), + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchDomesticController, + onChanged: handleDomesticFilter, + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), // /// Buttons on the right // Row( // children: [ @@ -907,19 +906,29 @@ class _AdvancePurchaseState extends State isDesktop ? constraints.maxWidth : 1300; - // List> newDomesticData = - // filteredDomestic.isNotEmpty ? filteredDomestic : domesticData; + List> newDomesticData =filteredDomestic.isNotEmpty ? filteredDomestic : domesticData; // Pagination logic List> paginatedDomestic = - domesticData + newDomesticData .skip(currentPage1 * itemsPerPage1) .take(itemsPerPage1) .toList(); - return Column( + return ( + (searchDomesticController.text.isNotEmpty && filteredDomestic.isEmpty) + ? Center( + child: Text( + "No data found", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ) + : Column( children: [ Expanded( child: SingleChildScrollView( @@ -1119,7 +1128,7 @@ class _AdvancePurchaseState extends State PaginationControls( currentPage: currentPage1, itemsPerPage: itemsPerPage1, - totalItems: domesticData.length, + totalItems: newDomesticData.length, activeColor: layoutColor, onPageChanged: (page) { setState(() { @@ -1134,7 +1143,7 @@ class _AdvancePurchaseState extends State }, ), ], - ); + )); }, ), ), @@ -1281,14 +1290,64 @@ class _AdvancePurchaseState extends State horizontal: 16.0, vertical: 8, ), - child: Text( - "International Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})", - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w500, - color: Colors.grey[700], - ), - ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + /// Title on the left + Expanded( + child: Text( + "International Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w500, + color: Colors.grey[700], + ), + overflow: TextOverflow.ellipsis, // Ensures title doesn't overflow + ), + ), + + + SizedBox(width: 16), + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchInternationalController, + onChanged: handleInternationalFilter, + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), + ]) ), Container( height: @@ -1301,16 +1360,26 @@ class _AdvancePurchaseState extends State builder: (context, constraints) { final double minWidth = isDesktop ? constraints.maxWidth : 1300; - + List> newInternationalData =filteredInternational.isNotEmpty ? filteredInternational : internationalData; // Pagination logic List> paginatedInternational = - internationalData + newInternationalData .skip(currentPage2 * itemsPerPage2) .take(itemsPerPage2) .toList(); - return Column( + return ((searchInternationalController.text.isNotEmpty && filteredInternational.isEmpty) + ? Center( + child: Text( + "No data found", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ) + :Column( children: [ Expanded( child: SingleChildScrollView( @@ -1510,7 +1579,7 @@ class _AdvancePurchaseState extends State PaginationControls( currentPage: currentPage2, itemsPerPage: itemsPerPage2, - totalItems: internationalData.length, + totalItems: newInternationalData.length, activeColor: layoutColor, onPageChanged: (page) { setState(() { @@ -1525,7 +1594,7 @@ class _AdvancePurchaseState extends State }, ), ], - ); + )); }, ), ), diff --git a/lib/Screens/reports/guestHouse.dart b/lib/Screens/reports/guestHouse.dart index c8dd587..707d06f 100644 --- a/lib/Screens/reports/guestHouse.dart +++ b/lib/Screens/reports/guestHouse.dart @@ -53,6 +53,10 @@ class _GuestHouseState extends State List> internationalData = []; // Map domesticData = {}; // Map internationalData = {}; + List> filteredDomestic = []; + List> filteredInternational = []; + TextEditingController searchDomesticController = TextEditingController(); + TextEditingController searchInternationalController = TextEditingController(); bool loaderFlag = false; @@ -107,13 +111,9 @@ class _GuestHouseState extends State String getTabName(int index) { switch (index) { - case 0: - return "domestic"; - case 1: - return "international"; - default: - // return "Unknown"; - return "domestic"; + case 0: return "domestic"; + case 1: return "international"; + default: return "domestic"; // return "Unknown"; } } @@ -158,7 +158,7 @@ class _GuestHouseState extends State loadInitialData(); }); } catch (e) { - print("service report : $e"); + print("guest report : $e"); } } @@ -277,6 +277,10 @@ class _GuestHouseState extends State ? result['data']['international'] ?? [] : [], ); + + filteredDomestic = domesticData; + filteredInternational = internationalData; + loaderFlag = false; }); } catch (e) { @@ -336,6 +340,50 @@ class _GuestHouseState extends State ); } + void handleDomesticFilter(String query) { + + final lowerQuery = query.toLowerCase(); + setState(() { + filteredDomestic = + domesticData.where((object) { + return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['customer_name']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_class']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_travel_date']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['sector']?.toLowerCase().contains(lowerQuery)); + }).toList(); + currentPage1 = 0; + }); + print("handleDomesticFilter > Total entries: ${filteredDomestic?.length ?? 0}"); + } + + void handleInternationalFilter(String query) { + final lowerQuery = query.toLowerCase(); + setState(() { + filteredInternational = + internationalData.where((object) { + return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['customer_name']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_class']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_travel_date']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['sector']?.toLowerCase().contains(lowerQuery)); + }).toList(); + currentPage2 = 0; + }); + print("handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}"); + } + + @override // Widget build(BuildContext context) { // // TODO: implement build @@ -708,6 +756,44 @@ class _GuestHouseState extends State .ellipsis, // Ensures title doesn't overflow ), ), + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchDomesticController, + onChanged: handleDomesticFilter, + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), // SizedBox(width: 16), // /// Buttons on the right // Row( @@ -813,15 +899,29 @@ class _GuestHouseState extends State final double minWidth = isDesktop ? constraints.maxWidth : 1300; + List> newDomesticData =filteredDomestic.isNotEmpty ? filteredDomestic : domesticData; + + // Pagination logic List> paginatedDomestic = - domesticData - .skip(currentPage1 * itemsPerPage1) - .take(itemsPerPage1) - .toList(); + newDomesticData + .skip(currentPage1 * itemsPerPage1) + .take(itemsPerPage1) + .toList(); - return Column( + return ( + (searchDomesticController.text.isNotEmpty && filteredDomestic.isEmpty) + ? Center( + child: Text( + "No data found", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ) + : Column( children: [ Expanded( child: SingleChildScrollView( @@ -1073,7 +1173,7 @@ class _GuestHouseState extends State PaginationControls( currentPage: currentPage1, itemsPerPage: itemsPerPage1, - totalItems: domesticData.length, + totalItems: newDomesticData.length, activeColor: layoutColor, onPageChanged: (page) { setState(() { @@ -1088,7 +1188,7 @@ class _GuestHouseState extends State }, ), ], - ); + )); }, ), ), @@ -1235,14 +1335,64 @@ class _GuestHouseState extends State horizontal: 16.0, vertical: 8, ), - child: Text( - "International Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})", - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w500, - color: Colors.grey[700], - ), - ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + /// Title on the left + Expanded( + child: Text( + "International Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w500, + color: Colors.grey[700], + ), + overflow: TextOverflow.ellipsis, // Ensures title doesn't overflow + ), + ), + + + SizedBox(width: 16), + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchInternationalController, + onChanged: handleInternationalFilter, + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), + ]) ), Container( height: @@ -1255,16 +1405,26 @@ class _GuestHouseState extends State builder: (context, constraints) { final double minWidth = isDesktop ? constraints.maxWidth : 1300; - + List> newInternationalData =filteredInternational.isNotEmpty ? filteredInternational : internationalData; // Pagination logic List> paginatedInternational = - internationalData + newInternationalData .skip(currentPage2 * itemsPerPage2) .take(itemsPerPage2) .toList(); - return Column( + return ((searchInternationalController.text.isNotEmpty && filteredInternational.isEmpty) + ? Center( + child: Text( + "No data found", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ) + :Column( children: [ Expanded( child: SingleChildScrollView( @@ -1526,7 +1686,7 @@ class _GuestHouseState extends State PaginationControls( currentPage: currentPage2, itemsPerPage: itemsPerPage2, - totalItems: internationalData.length, + totalItems: newInternationalData.length, activeColor: layoutColor, onPageChanged: (page) { setState(() { @@ -1541,7 +1701,7 @@ class _GuestHouseState extends State }, ), ], - ); + )); }, ), ), diff --git a/lib/Screens/reports/misAir.dart b/lib/Screens/reports/misAir.dart index 9207bc3..3e723d4 100644 --- a/lib/Screens/reports/misAir.dart +++ b/lib/Screens/reports/misAir.dart @@ -52,6 +52,10 @@ class _MISairState extends State with SingleTickerProviderStateMixin { List> internationalData = []; // Map domesticData = {}; // Map internationalData = {}; + List> filteredDomestic = []; + List> filteredInternational = []; + TextEditingController searchDomesticController = TextEditingController(); + TextEditingController searchInternationalController = TextEditingController(); bool loaderFlag = false; @@ -106,13 +110,9 @@ class _MISairState extends State with SingleTickerProviderStateMixin { String getTabName(int index) { switch (index) { - case 0: - return "domestic"; - case 1: - return "international"; - default: - // return "Unknown"; - return "domestic"; + case 0: return "domestic"; + case 1: return "international"; + default: return "domestic"; // return "Unknown"; } } @@ -157,7 +157,7 @@ class _MISairState extends State with SingleTickerProviderStateMixin { loadInitialData(); }); } catch (e) { - print("service report : $e"); + print("Air report : $e"); } } @@ -276,6 +276,10 @@ class _MISairState extends State with SingleTickerProviderStateMixin { ? result['data']['international'] ?? [] : [], ); + + filteredDomestic = domesticData; + filteredInternational = internationalData; + loaderFlag = false; }); } catch (e) { @@ -335,6 +339,49 @@ class _MISairState extends State with SingleTickerProviderStateMixin { ); } + void handleDomesticFilter(String query) { + final lowerQuery = query.toLowerCase(); + setState(() { + filteredDomestic = + domesticData.where((object) { + return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['customer_name']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_class']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_travel_date']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['sector']?.toLowerCase().contains(lowerQuery)); + }).toList(); + currentPage1 = 0; + }); + print("handleDomesticFilter > Total entries: ${filteredDomestic?.length ?? 0}"); + } + + void handleInternationalFilter(String query) { + final lowerQuery = query.toLowerCase(); + setState(() { + filteredInternational = + internationalData.where((object) { + return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['customer_name']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_class']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_travel_date']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['sector']?.toLowerCase().contains(lowerQuery)); + }).toList(); + currentPage2 = 0; + }); + print("handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}"); + } + + @override // Widget build(BuildContext context) { // // TODO: implement build @@ -734,6 +781,44 @@ class _MISairState extends State with SingleTickerProviderStateMixin { .ellipsis, // Ensures title doesn't overflow ), ), + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchDomesticController, + onChanged: handleDomesticFilter, + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), // SizedBox(width: 16), // /// Buttons on the right // Row( @@ -839,15 +924,29 @@ class _MISairState extends State with SingleTickerProviderStateMixin { final double minWidth = isDesktop ? constraints.maxWidth : 1300; + List> newDomesticData =filteredDomestic.isNotEmpty ? filteredDomestic : domesticData; + + // Pagination logic List> paginatedDomestic = - domesticData - .skip(currentPage1 * itemsPerPage1) - .take(itemsPerPage1) - .toList(); + newDomesticData + .skip(currentPage1 * itemsPerPage1) + .take(itemsPerPage1) + .toList(); - return Column( + return ( + (searchDomesticController.text.isNotEmpty && filteredDomestic.isEmpty) + ? Center( + child: Text( + "No data found", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ) + : Column( children: [ Expanded( child: SingleChildScrollView( @@ -1099,7 +1198,7 @@ class _MISairState extends State with SingleTickerProviderStateMixin { PaginationControls( currentPage: currentPage1, itemsPerPage: itemsPerPage1, - totalItems: domesticData.length, + totalItems: newDomesticData.length, activeColor: layoutColor, onPageChanged: (page) { setState(() { @@ -1114,7 +1213,7 @@ class _MISairState extends State with SingleTickerProviderStateMixin { }, ), ], - ); + )); }, ), ), @@ -1261,14 +1360,64 @@ class _MISairState extends State with SingleTickerProviderStateMixin { horizontal: 16.0, vertical: 8, ), - child: Text( - "International Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})", - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w500, - color: Colors.grey[700], - ), - ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + /// Title on the left + Expanded( + child: Text( + "International Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w500, + color: Colors.grey[700], + ), + overflow: TextOverflow.ellipsis, // Ensures title doesn't overflow + ), + ), + + + SizedBox(width: 16), + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchInternationalController, + onChanged: handleInternationalFilter, + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), + ]) ), Container( height: @@ -1281,16 +1430,26 @@ class _MISairState extends State with SingleTickerProviderStateMixin { builder: (context, constraints) { final double minWidth = isDesktop ? constraints.maxWidth : 1300; - + List> newInternationalData =filteredInternational.isNotEmpty ? filteredInternational : internationalData; // Pagination logic List> paginatedInternational = - internationalData + newInternationalData .skip(currentPage2 * itemsPerPage2) .take(itemsPerPage2) .toList(); - return Column( + return ((searchInternationalController.text.isNotEmpty && filteredInternational.isEmpty) + ? Center( + child: Text( + "No data found", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ) + : Column( children: [ Expanded( child: SingleChildScrollView( @@ -1557,7 +1716,7 @@ class _MISairState extends State with SingleTickerProviderStateMixin { }, ), ], - ); + )); }, ), ), diff --git a/lib/Screens/reports/misForex.dart b/lib/Screens/reports/misForex.dart index 6a18e94..89990c5 100644 --- a/lib/Screens/reports/misForex.dart +++ b/lib/Screens/reports/misForex.dart @@ -38,21 +38,18 @@ class _MISforexState extends State Color? layoutColor; Color? bodyColor; - int currentPage1 = 0; - int itemsPerPage1 = 10; - int currentPage2 = 0; - int itemsPerPage2 = 10; - late TabController _tabController; - String selectedTabName = 'domestic'; + int currentPage = 0; + int itemsPerPage = 10; + String selectedTabName = 'international'; Map focusNodes = {}; Map focusStates = {}; Map textControllers = {}; Map errorMessages = {}; // Map MISforexReport = {}; - List> domesticData = []; List> internationalData = []; - // Map domesticData = {}; // Map internationalData = {}; + List> filteredInternational = []; + TextEditingController searchInternationalController = TextEditingController(); bool loaderFlag = false; @@ -80,17 +77,6 @@ class _MISforexState extends State focusStates["from_date"] = false; } - _tabController = TabController(length: 2, vsync: this); - - _tabController.addListener(() { - if (_tabController.indexIsChanging == false) { - // Only fire when tab change is complete - setState(() { - selectedTabName = getTabName(_tabController.index); - }); - print(" :) :X Selected Tab: ${getTabName(_tabController.index)}"); - } - }); // Add focus listeners focusNodes.forEach((key, focusNode) { @@ -105,17 +91,6 @@ class _MISforexState extends State // fetchMISforexReport(); } - String getTabName(int index) { - switch (index) { - case 0: - return "domestic"; - case 1: - return "international"; - default: - // return "Unknown"; - return "domestic"; - } - } void _addFocusListener(FocusNode node, Function(bool) updateState) { node.addListener(() { @@ -158,7 +133,7 @@ class _MISforexState extends State loadInitialData(); }); } catch (e) { - print("service report : $e"); + print("Forex report : $e"); } } @@ -213,12 +188,9 @@ class _MISforexState extends State errorMessages.remove("from_date"); errorMessages.remove("to_date"); setState(() { - domesticData = []; internationalData = []; - currentPage1 = 0; - itemsPerPage1 = 10; - currentPage2 = 0; - itemsPerPage2 = 10; + currentPage = 0; + itemsPerPage = 10; }); final fromDateText = textControllers["from_date"]?.text; final toDateText = textControllers["to_date"]?.text; @@ -271,9 +243,11 @@ class _MISforexState extends State // domesticData = List>.from(result['data']['domestic'] ?? []); internationalData = List>.from( result['status'] == 'success' - ? result['data']['international'] ?? [] + ? result['data'] ?? [] : [], ); + + filteredInternational = internationalData; loaderFlag = false; }); } catch (e) { @@ -310,7 +284,7 @@ class _MISforexState extends State final formattedToDate = DateFormat('yyyy-MM-dd').format(toDate); final name = - 'MIS Forex - $selectedTabName Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})'; + 'MIS Forex - International Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})'; final safeName = name.replaceAll(RegExp(r'[^\w\s-]'), ''); final excelName = '$safeName'; @@ -333,6 +307,26 @@ class _MISforexState extends State ); } + void handleInternationalFilter(String query) { + final lowerQuery = query.toLowerCase(); + setState(() { + filteredInternational = + internationalData.where((object) { + return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['passenger_name']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['visiting_country']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['amount']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['forex_from_date']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['forex_to_date']?.toLowerCase().contains(lowerQuery)); + }).toList(); + currentPage = 0; + }); + print("handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}"); + } + @override // Widget build(BuildContext context) { // // TODO: implement build @@ -698,14 +692,64 @@ class _MISforexState extends State horizontal: 16.0, vertical: 8, ), - child: Text( - "International Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})", - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w500, - color: Colors.grey[700], - ), - ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + /// Title on the left + Expanded( + child: Text( + "International Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w500, + color: Colors.grey[700], + ), + overflow: TextOverflow.ellipsis, // Ensures title doesn't overflow + ), + ), + + + SizedBox(width: 16), + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchInternationalController, + onChanged: handleInternationalFilter, + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), + ]) ), // Table container Container( @@ -718,16 +762,26 @@ class _MISforexState extends State builder: (context, constraints) { final double minWidth = isDesktop ? constraints.maxWidth : 1300; - + List> newInternationalData =filteredInternational.isNotEmpty ? filteredInternational : internationalData; // Pagination logic List> paginatedInternational = - internationalData - .skip(currentPage2 * itemsPerPage2) - .take(itemsPerPage2) + newInternationalData + .skip(currentPage * itemsPerPage) + .take(itemsPerPage) .toList(); - return Column( + return ((searchInternationalController.text.isNotEmpty && filteredInternational.isEmpty) + ? Center( + child: Text( + "No data found", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ) + :Column( children: [ Expanded( child: SingleChildScrollView( @@ -970,24 +1024,24 @@ class _MISforexState extends State ), ), PaginationControls( - currentPage: currentPage2, - itemsPerPage: itemsPerPage2, - totalItems: internationalData.length, + currentPage: currentPage, + itemsPerPage: itemsPerPage, + totalItems: newInternationalData.length, activeColor: layoutColor, onPageChanged: (page) { setState(() { - currentPage2 = page; + currentPage = page; }); }, onItemsPerPageChanged: (items) { setState(() { - itemsPerPage2 = items; - currentPage2 = 0; + itemsPerPage = items; + currentPage = 0; }); }, ), ], - ); + )); }, ), ), diff --git a/lib/Screens/reports/misHotel.dart b/lib/Screens/reports/misHotel.dart index 06626f0..c79e60c 100644 --- a/lib/Screens/reports/misHotel.dart +++ b/lib/Screens/reports/misHotel.dart @@ -54,6 +54,10 @@ class _MIShotelState extends State List> internationalData = []; // Map domesticData = {}; // Map internationalData = {}; + List> filteredDomestic = []; + List> filteredInternational = []; + TextEditingController searchDomesticController = TextEditingController(); + TextEditingController searchInternationalController = TextEditingController(); bool loaderFlag = false; @@ -108,13 +112,9 @@ class _MIShotelState extends State String getTabName(int index) { switch (index) { - case 0: - return "domestic"; - case 1: - return "international"; - default: - // return "Unknown"; - return "domestic"; + case 0: return "domestic"; + case 1: return "international"; + default: return "domestic"; // return "Unknown"; } } @@ -142,7 +142,7 @@ class _MIShotelState extends State loadInitialData(); }); } catch (e) { - print("service report : $e"); + print("hotel report : $e"); } } void loadInitialData() async { @@ -266,6 +266,9 @@ class _MIShotelState extends State internationalData = List>.from( result['status'] == 'success' ? result['data']['international'] ?? [] : [] ); + + filteredDomestic = domesticData; + filteredInternational = internationalData; loaderFlag = false; }); } catch (e) { @@ -323,6 +326,51 @@ class _MIShotelState extends State ), ); } + + void handleDomesticFilter(String query) { + + final lowerQuery = query.toLowerCase(); + setState(() { + filteredDomestic = + domesticData.where((object) { + return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['employee_name']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['hotel_name']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['check_in_date']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['check_out_date']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['hotel_city']?.toLowerCase().contains(lowerQuery)); + }).toList(); + currentPage1 = 0; + }); + print("handleDomesticFilter > Total entries: ${filteredDomestic?.length ?? 0}"); + } + + void handleInternationalFilter(String query) { + final lowerQuery = query.toLowerCase(); + setState(() { + filteredInternational = + internationalData.where((object) { + return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['employee_name']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['hotel_name']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['check_in_date']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['check_out_date']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['hotel_city']?.toLowerCase().contains(lowerQuery)); + }).toList(); + currentPage2 = 0; + }); + print("handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}"); + } + + @override // Widget build(BuildContext context) { // // TODO: implement build @@ -698,6 +746,44 @@ class _MIShotelState extends State overflow: TextOverflow.ellipsis, // Ensures title doesn't overflow ), ), + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchDomesticController, + onChanged: handleDomesticFilter, + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), // SizedBox(width: 16), // /// Buttons on the right // Row( @@ -802,13 +888,29 @@ class _MIShotelState extends State builder: (context, constraints) { final double minWidth = isDesktop ? constraints.maxWidth : 1300; + List> newDomesticData =filteredDomestic.isNotEmpty ? filteredDomestic : domesticData; + + // Pagination logic - List> paginatedDomestic = domesticData + List> + paginatedDomestic = + newDomesticData .skip(currentPage1 * itemsPerPage1) .take(itemsPerPage1) .toList(); - return Column( + return ( + (searchDomesticController.text.isNotEmpty && filteredDomestic.isEmpty) + ? Center( + child: Text( + "No data found", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ) + : Column( children: [ Expanded( child: SingleChildScrollView( @@ -870,7 +972,7 @@ class _MIShotelState extends State PaginationControls( currentPage: currentPage1, itemsPerPage: itemsPerPage1, - totalItems: domesticData.length, + totalItems: newDomesticData.length, activeColor: layoutColor, onPageChanged: (page) { setState(() { @@ -885,7 +987,7 @@ class _MIShotelState extends State }, ), ], - ); + )); }, ), ), @@ -1027,10 +1129,64 @@ class _MIShotelState extends State // ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8), - child: Text( - "International Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})", - style: GoogleFonts.poppins(fontSize: 13, fontWeight: FontWeight.w500, color: Colors.grey[700]), - ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + /// Title on the left + Expanded( + child: Text( + "International Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w500, + color: Colors.grey[700], + ), + overflow: TextOverflow.ellipsis, // Ensures title doesn't overflow + ), + ), + + + SizedBox(width: 16), + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchInternationalController, + onChanged: handleInternationalFilter, + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), + ]) ), Container( height : isDesktop ? MediaQuery.of(context).size.height * 0.51 : 200, @@ -1038,14 +1194,24 @@ class _MIShotelState extends State child: LayoutBuilder( builder: (context, constraints) { final double minWidth = isDesktop ? constraints.maxWidth : 1300; - + List> newInternationalData =filteredInternational.isNotEmpty ? filteredInternational : internationalData; // Pagination logic - List> paginatedInternational = internationalData + List> paginatedInternational = newInternationalData .skip(currentPage2 * itemsPerPage2) .take(itemsPerPage2) .toList(); - return Column( + return ((searchInternationalController.text.isNotEmpty && filteredInternational.isEmpty) + ? Center( + child: Text( + "No data found", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ) + : Column( children: [ Expanded( child: SingleChildScrollView( @@ -1104,7 +1270,7 @@ class _MIShotelState extends State PaginationControls( currentPage: currentPage2, itemsPerPage: itemsPerPage2, - totalItems: internationalData.length, + totalItems: newInternationalData.length, activeColor: layoutColor, onPageChanged: (page) { setState(() { @@ -1119,7 +1285,7 @@ class _MIShotelState extends State }, ), ], - ); + )); }, ), ), diff --git a/lib/Screens/reports/servicesAnalysis.dart b/lib/Screens/reports/servicesAnalysis.dart index 7bfb25b..f55e238 100644 --- a/lib/Screens/reports/servicesAnalysis.dart +++ b/lib/Screens/reports/servicesAnalysis.dart @@ -53,6 +53,10 @@ class _ServicesAnalysisState extends State List> internationalData = []; // Map domesticData = {}; // Map internationalData = {}; + List> filteredDomestic = []; + List> filteredInternational = []; + TextEditingController searchDomesticController = TextEditingController(); + TextEditingController searchInternationalController = TextEditingController(); bool loaderFlag = false; @@ -107,13 +111,9 @@ class _ServicesAnalysisState extends State String getTabName(int index) { switch (index) { - case 0: - return "domestic"; - case 1: - return "international"; - default: - // return "Unknown"; - return "domestic"; + case 0: return "domestic"; + case 1: return "international"; + default: return "domestic"; // return "Unknown"; } } @@ -277,6 +277,9 @@ class _ServicesAnalysisState extends State ? result['data']['international'] ?? [] : [], ); + + filteredDomestic = domesticData; + filteredInternational = internationalData; loaderFlag = false; }); } catch (e) { @@ -336,6 +339,35 @@ class _ServicesAnalysisState extends State ); } + void handleDomesticFilter(String query) { + final lowerQuery = query.toLowerCase(); + setState(() { + filteredDomestic = + domesticData.where((object) { + return (object['Service']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_service_count']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['plan_trip_type']?.toLowerCase().contains(lowerQuery)); + }).toList(); + currentPage1 = 0; + }); + print("handleDomesticFilter > Total entries: ${filteredDomestic?.length ?? 0}"); + } + + void handleInternationalFilter(String query) { + final lowerQuery = query.toLowerCase(); + setState(() { + filteredInternational = + internationalData.where((object) { + return (object['Service']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['flight_service_count']?.toLowerCase().contains(lowerQuery) ?? false) || + (object['plan_trip_type']?.toLowerCase().contains(lowerQuery)); + }).toList(); + currentPage2 = 0; + }); + print("handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}"); + } + + @override // Widget build(BuildContext context) { // // TODO: implement build @@ -708,6 +740,44 @@ class _ServicesAnalysisState extends State .ellipsis, // Ensures title doesn't overflow ), ), + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchDomesticController, + onChanged: handleDomesticFilter, + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), // SizedBox(width: 16), // /// Buttons on the right // Row( @@ -813,15 +883,29 @@ class _ServicesAnalysisState extends State final double minWidth = isDesktop ? constraints.maxWidth : 1300; + List> newDomesticData =filteredDomestic.isNotEmpty ? filteredDomestic : domesticData; + + // Pagination logic List> paginatedDomestic = - domesticData - .skip(currentPage1 * itemsPerPage1) - .take(itemsPerPage1) - .toList(); + newDomesticData + .skip(currentPage1 * itemsPerPage1) + .take(itemsPerPage1) + .toList(); - return Column( + return ( + (searchDomesticController.text.isNotEmpty && filteredDomestic.isEmpty) + ? Center( + child: Text( + "No data found", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ) + : Column( children: [ Expanded( child: SingleChildScrollView( @@ -933,7 +1017,7 @@ class _ServicesAnalysisState extends State PaginationControls( currentPage: currentPage1, itemsPerPage: itemsPerPage1, - totalItems: domesticData.length, + totalItems: newDomesticData.length, activeColor: layoutColor, onPageChanged: (page) { setState(() { @@ -948,7 +1032,7 @@ class _ServicesAnalysisState extends State }, ), ], - ); + )); }, ), ), @@ -1095,14 +1179,64 @@ class _ServicesAnalysisState extends State horizontal: 16.0, vertical: 8, ), - child: Text( - "International Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})", - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w500, - color: Colors.grey[700], - ), - ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + /// Title on the left + Expanded( + child: Text( + "International Report (From: ${textControllers["from_date"]?.text} To: ${textControllers["to_date"]?.text})", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w500, + color: Colors.grey[700], + ), + overflow: TextOverflow.ellipsis, // Ensures title doesn't overflow + ), + ), + + + SizedBox(width: 16), + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchInternationalController, + onChanged: handleInternationalFilter, + decoration: InputDecoration( + hintText: "Search ...", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), + ]) ), Container( height: @@ -1115,16 +1249,26 @@ class _ServicesAnalysisState extends State builder: (context, constraints) { final double minWidth = isDesktop ? constraints.maxWidth : 1300; - + List> newInternationalData =filteredInternational.isNotEmpty ? filteredInternational : internationalData; // Pagination logic List> paginatedInternational = - internationalData + newInternationalData .skip(currentPage2 * itemsPerPage2) .take(itemsPerPage2) .toList(); - return Column( + return ((searchInternationalController.text.isNotEmpty && filteredInternational.isEmpty) + ? Center( + child: Text( + "No data found", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ) + : Column( children: [ Expanded( child: SingleChildScrollView( @@ -1236,7 +1380,7 @@ class _ServicesAnalysisState extends State PaginationControls( currentPage: currentPage2, itemsPerPage: itemsPerPage2, - totalItems: internationalData.length, + totalItems: newInternationalData.length, activeColor: layoutColor, onPageChanged: (page) { setState(() { @@ -1251,7 +1395,7 @@ class _ServicesAnalysisState extends State }, ), ], - ); + )); }, ), ),