From a32fb0d0c309b24db6d02da4de71f0b449ead085 Mon Sep 17 00:00:00 2001 From: venbaittech Date: Thu, 31 Jul 2025 18:15:37 +0530 Subject: [PATCH] UI_TRIPTYPE_SERVICE_HANDLING --- lib/Screens/allTrips/list_all_plans.dart | 1414 +++++++++-------- lib/Screens/allTrips/travel_agent_list.dart | 58 +- lib/Screens/approvals/approval_list.dart | 1346 ++++++++-------- lib/Screens/itnerary_list/flight_list.dart | 4 +- lib/Screens/plans/create_plans.dart | 100 +- .../plans/dynamic_itinerary_stepper.dart | 14 +- lib/Screens/plans/list_plans.dart | 1191 +++++++------- lib/app.dart | 61 +- lib/data/models/plan.dart | 17 +- lib/widgets/popup_listPlan_action.dart | 18 +- 10 files changed, 2309 insertions(+), 1914 deletions(-) diff --git a/lib/Screens/allTrips/list_all_plans.dart b/lib/Screens/allTrips/list_all_plans.dart index f7b5e7d..d9586e7 100644 --- a/lib/Screens/allTrips/list_all_plans.dart +++ b/lib/Screens/allTrips/list_all_plans.dart @@ -112,14 +112,14 @@ class _ListAllPlansState extends State { setState(() { layoutColor = - layoutString != null - ? Color(int.parse(layoutString)) - : Colors.redAccent; + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; bodyColor = - bodyStringColor != null - ? Color(int.parse(bodyStringColor)) - : Colors.white; + bodyStringColor != null + ? Color(int.parse(bodyStringColor)) + : Colors.white; }); } @@ -331,99 +331,99 @@ class _ListAllPlansState extends State { context: context, builder: (context) => AlertDialog( - title: Text( - label, - style: GoogleFonts.poppins( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Colors.black, - ), - overflow: TextOverflow.ellipsis, - ), - content: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - if (approverData.isNotEmpty) - SizedBox( - height: 250, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: DataTable( - columns: [ - // DataColumn(label: Text('S.No', style: GoogleFonts.poppins(fontSize: 14, fontWeight: FontWeight.w600))), - // DataColumn(label: Text('Approver ID', style: GoogleFonts.poppins(fontSize: 14, fontWeight: FontWeight.w600))), - DataColumn( - label: Text( - 'Status', - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), - ), - ], - rows: - approverData.asMap().entries.map((entry) { - final index = entry.key + 1; - final item = entry.value; - - final approverIdKey = item.keys.firstWhere( - (k) => k.endsWith('_id'), - orElse: () => '', - ); - final statusKey = item.keys.firstWhere( - (k) => k.endsWith('_status'), - orElse: () => '', - ); - - final approverId = - item[approverIdKey]?.toString() ?? '-'; - final statusText = - item[statusKey]?.toString() ?? 'Unknown'; - - return DataRow( - cells: [ - // DataCell(Text('$index')), - // DataCell(SizedBox(width: 120, child: Text(approverId, overflow: TextOverflow.ellipsis))), - DataCell( - SizedBox( - child: Text( - statusText, - overflow: TextOverflow.ellipsis, + title: Text( + label, + style: GoogleFonts.poppins( + fontSize: 18, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + overflow: TextOverflow.ellipsis, + ), + content: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (approverData.isNotEmpty) + SizedBox( + height: 250, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: DataTable( + columns: [ + // DataColumn(label: Text('S.No', style: GoogleFonts.poppins(fontSize: 14, fontWeight: FontWeight.w600))), + // DataColumn(label: Text('Approver ID', style: GoogleFonts.poppins(fontSize: 14, fontWeight: FontWeight.w600))), + DataColumn( + label: Text( + 'Status', + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w600, ), ), ), ], - ); - }).toList(), + rows: + approverData.asMap().entries.map((entry) { + final index = entry.key + 1; + final item = entry.value; + + final approverIdKey = item.keys.firstWhere( + (k) => k.endsWith('_id'), + orElse: () => '', + ); + final statusKey = item.keys.firstWhere( + (k) => k.endsWith('_status'), + orElse: () => '', + ); + + final approverId = + item[approverIdKey]?.toString() ?? '-'; + final statusText = + item[statusKey]?.toString() ?? 'Unknown'; + + return DataRow( + cells: [ + // DataCell(Text('$index')), + // DataCell(SizedBox(width: 120, child: Text(approverId, overflow: TextOverflow.ellipsis))), + DataCell( + SizedBox( + child: Text( + statusText, + overflow: TextOverflow.ellipsis, + ), + ), + ), + ], + ); + }).toList(), + ), + ), + ), + ) + else + Text( + "-- no data. --", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w300, ), ), - ), - ) - else - Text( - "-- no data. --", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w300, - ), - ), + ], + ), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + _listDialogShown = false; + }, + child: Text("Close"), + ), ], ), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.pop(context); - _listDialogShown = false; - }, - child: Text("Close"), - ), - ], - ), ); } @@ -443,16 +443,16 @@ class _ListAllPlansState extends State { drawer: CustomDrawer(isDesktop: false), body: Padding( padding: - isDesktop - ? EdgeInsets.symmetric( - horizontal: - MediaQuery.of(context).size.width * - 0.1, // 30% of screen width as horizontal padding - vertical: - MediaQuery.of(context).size.height * - 0, // 5% of screen height as vertical padding - ) - : EdgeInsets.all(0), + isDesktop + ? EdgeInsets.symmetric( + horizontal: + MediaQuery.of(context).size.width * + 0.1, // 30% of screen width as horizontal padding + vertical: + MediaQuery.of(context).size.height * + 0, // 5% of screen height as vertical padding + ) + : EdgeInsets.all(0), child: Row( children: [ // if (isDesktop) CustomDrawer(isDesktop: true), @@ -504,29 +504,29 @@ class _ListAllPlansState extends State { return Container( margin: isDesktop ? EdgeInsets.all(10.0) : null, padding: - isDesktop - ? const EdgeInsets.only(top: 15, bottom: 15, left: 20, right: 20) - : EdgeInsets.all(3.0), + isDesktop + ? const EdgeInsets.only(top: 5, bottom: 5, left: 20, right: 20) + : EdgeInsets.all(3.0), height: - isDesktop - ? MediaQuery.of(context).size.height * 0.98 - : MediaQuery.of(context).size.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, - // color: Color(0xFFF7F7FB), - ) - : null, + isDesktop + ? Border.all( + width: 2, + color: Colors.white, + // color: Color(0xFFF7F7FB), + ) + : null, color: isDesktop ? Colors.white : Color(0xFFFCFCFC), // color: Color(0xFFF7F7FB), // color: Colors.amber, ), child: Padding( - padding: const EdgeInsets.all(1.0), + padding: const EdgeInsets.only(top: 15, bottom: 15, left: 5, right: 5), child: Container( // padding: const EdgeInsets.all(10.0), color: isDesktop ? Colors.white : Color(0xFFFCFCFC), @@ -781,61 +781,62 @@ class _ListAllPlansState extends State { // filteredPlans.isNotEmpty ? filteredPlans : allPlans; List plans = - searchController.text.isEmpty ? allPlans : filteredPlans; + searchController.text.isEmpty ? allPlans : filteredPlans; plans.sort( - (a, b) => + (a, b) => int.parse(b.planId).compareTo(int.parse(a.planId)), ); List paginatedPlans = - plans - .skip(currentPage * itemsPerPage) - .take(itemsPerPage) - .toList(); + plans + .skip(currentPage * itemsPerPage) + .take(itemsPerPage) + .toList(); Widget table = LayoutBuilder( builder: (context, constraints) { double minWidth = isDesktop ? constraints.maxWidth : 1300; return SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: - ConstrainedBox( - constraints: BoxConstraints(minWidth: minWidth), - child: DataTable( - dividerThickness: 0.5, - columnSpacing: isDesktop ? 24.0 : 16.0, - border: TableBorder( - horizontalInside: BorderSide( - width: 0.5, - color: Colors.grey.shade200, + scrollDirection: Axis.horizontal, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: ConstrainedBox( + constraints: BoxConstraints(minWidth: minWidth), + child: DataTable( + dividerThickness: 0.5, + columnSpacing: isDesktop ? 24.0 : 16.0, + border: TableBorder( + horizontalInside: BorderSide( + width: 0.5, + color: Colors.grey.shade200, + ), + ), + columns: [ + DataColumn( + label: Text( + 'S.NO', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), ), ), - columns: [ - DataColumn( - label: Text( - 'S.NO', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - DataColumn( - label: Text( - 'Trip ID', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), + DataColumn( + label: Text( + 'Trip ID', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), ), - DataColumn( - label: Text( + ), + DataColumn( + label: Expanded( + flex: 1, + child: Text( 'Trip Name', style: GoogleFonts.poppins( fontSize: 13, @@ -843,329 +844,365 @@ class _ListAllPlansState extends State { ), ), ), + ), - DataColumn( - label: Text( - 'Trip Type', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), + DataColumn( + label: Text( + 'Trip Type', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), ), - DataColumn( - label: Text( - 'Emp Code', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), + ), + DataColumn( + label: Text( + 'Emp Code', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), ), - DataColumn( - label: Text( - 'Traveller', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), + ), + DataColumn( + label: Text( + 'Traveller', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), ), + ), - DataColumn( - label: Text( - 'Created On', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), + DataColumn( + label: Text( + 'Created On', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), ), - DataColumn( - label: Text( - 'Status', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), + ), + DataColumn( + label: Text( + 'Status', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), ), - DataColumn( - label: Text( - 'Actions', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), + ), + DataColumn( + label: Text( + 'Actions', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), ), - ], - rows: - // paginatedPlans.map((plan) - paginatedPlans.asMap().entries.map((entry) { - int index = entry.key; - var plan = entry.value; - return DataRow( - cells: [ - DataCell( - Text( - // "${index + 1}", - "${(currentPage * itemsPerPage) + index + 1}", - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), - ), - DataCell( - Text( - plan.planId, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), - ), - DataCell( - Text( - plan.tripTitle, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - softWrap: true, - overflow: TextOverflow.ellipsis, - ), - ), - DataCell( - Text( - plan.tripType, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), - ), - DataCell( - Text( - plan.employeeCode ?? " - ", - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), - ), - DataCell( - Text( - plan.userName.isNotEmpty - ? plan.userName - : plan.travellerName, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), - ), - - DataCell( - Text( - _formatDate(plan.createdOn), - // plan.createdOn, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), - ), - DataCell( - GestureDetector( - onTap: () => _showDetails(plan.planId), - child: Container( - width: - double - .infinity, // Set your desired fixed size (equal width and height) - height: 25, - alignment: Alignment.center, - decoration: BoxDecoration( - color: getStatusColor( - plan.statusValue, - ), - borderRadius: BorderRadius.circular( - 10, - ), + ), + ], + rows: + // paginatedPlans.map((plan) + paginatedPlans.asMap().entries.map((entry) { + int index = entry.key; + var plan = entry.value; + print("fordIf - ${plan.forexId}"); + return DataRow( + cells: [ + DataCell( + Text( + // "${index + 1}", + "${(currentPage * itemsPerPage) + index + 1}", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", ), + ), + ), + DataCell( + Text( + plan.planId, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + SizedBox( + width: 130, + child: Text( - plan.statusValue, - textAlign: TextAlign.center, + plan.tripTitle, style: TextStyle( - color: getStatusTextColor( + fontSize: 13, + fontFamily: "Inter", + ), + softWrap: true, + maxLines: 2, + // overflow: TextOverflow.ellipsis, + ), + ), + ), + DataCell( + Text( + plan.tripType, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + Text( + plan.employeeCode ?? " - ", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + Text( + plan.userName.isNotEmpty + ? plan.userName + : plan.travellerName, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + + DataCell( + Text( + _formatDate(plan.createdOn), + // plan.createdOn, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + GestureDetector( + onTap: + () => _showDetails(plan.planId), + child: Container( + width: + double + .infinity, // Set your desired fixed size (equal width and height) + height: 25, + alignment: Alignment.center, + decoration: BoxDecoration( + color: getStatusColor( plan.statusValue, ), - fontSize: 12, - fontFamily: "Inter", - fontWeight: FontWeight.w400, + borderRadius: + BorderRadius.circular(10), + ), + child: Text( + plan.statusValue, + textAlign: TextAlign.center, + style: TextStyle( + color: getStatusTextColor( + plan.statusValue, + ), + fontSize: 12, + fontFamily: "Inter", + fontWeight: FontWeight.w400, + ), ), ), ), ), - ), - DataCell( - Row( - children: [ - PopupMenuButton( - color: Colors.white, - padding: EdgeInsets.zero, - offset: Offset(0, 30), - icon: Icon( - Icons.more_vert, - color: Color(0xFF475569), - size: 14, - ), - itemBuilder: - (context) => [ - CustomPopupMenuEntry( - child: Container( - padding: - EdgeInsets.symmetric( - horizontal: 8, - vertical: 8, - ), - child: Row( - mainAxisSize: - MainAxisSize.min, - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - IconButton( - icon: Icon( - Icons - .remove_red_eye, - color: Color( - 0xFF475569, - ), - size: 18, - ), - tooltip: - 'View The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); // Close popup manually - ApiService.viewPlan( - context, - plan.planId, - isViewMode: - true, - ); - }, - ), - if (plan.statusValue == - "Pending Approval" || - plan.statusValue == - "Partially Approved") - IconButton( - icon: Image.asset( - 'assets/images/IconsImg/edit.png', - width: 20, - height: 15, - ), - tooltip: - 'Edit The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); - ApiService.viewPlan( - context, - plan.planId, - isViewMode: - false, - ); - }, - ), - IconButton( - icon: Icon( - Icons - .cancel_rounded, - size: 18, - ), - tooltip: - 'Cancellation The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); - deletePlan( - plan.planId, - ); - }, - ), - IconButton( - icon: Icon( - Icons.download, - color: Color( - 0xFF114D8B, - ), - size: 18, - ), - tooltip: - 'Download The PDF', - onPressed: () { - Navigator.pop( - context, - ); - apiService - .getPdfDownload( - plan.planId, - ); - }, - ), - IconButton( - icon: const Icon( - Icons.comment, - color: Color( - 0xFF475569, - ), - size: 11, - ), - tooltip: - 'Trip Comments', - onPressed: () { - showDialog( - context: - context, - builder: - ( - context, - ) => CommentModalList( - // planId: plan.planId, - planId: - plan.planId - .toString(), - layoutColorForUser: - layoutColor!, - role: - "Admin", - ), - ); - }, - ), - ], - ), - ), + DataCell( + Row( + children: [ + PopupMenuButton( + color: Colors.white, + padding: EdgeInsets.zero, + offset: Offset(0, 30), + icon: Icon( + Icons.more_vert, + color: Color(0xFF475569), + size: 14, ), - ], - ), - ], + itemBuilder: + (context) => [ + CustomPopupMenuEntry( + child: Container( + padding: + EdgeInsets.symmetric( + horizontal: 8, + vertical: 8, + ), + child: Row( + mainAxisSize: + MainAxisSize + .min, + mainAxisAlignment: + MainAxisAlignment + .center, + children: [ + IconButton( + icon: Icon( + Icons + .remove_red_eye, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'View The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); // Close popup manually + ApiService.viewPlan( + context, + plan.planId, + isViewMode: + true, + ); + }, + ), + if (plan.statusValue == + "Pending Approval" || + plan.statusValue == + "Partially Approved") + IconButton( + icon: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ), + tooltip: + 'Edit The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); + ApiService.viewPlan( + context, + plan.planId, + isViewMode: + false, + ); + }, + ), + IconButton( + icon: Icon( + Icons + .cancel_rounded, + size: 18, + ), + tooltip: + 'Cancellation The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); + deletePlan( + plan.planId, + ); + }, + ), + IconButton( + icon: Icon( + Icons + .download, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'Download The PDF', + onPressed: () { + Navigator.pop( + context, + ); + apiService + .getPdfDownload( + plan.planId, + ); + }, + ), + if (plan.statusValue == + "Approved" && + plan.forexId != + null && + plan.forexId != + '') + IconButton( + icon: Icon( + Icons + .monetization_on_outlined, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'Download Forex PDF', + onPressed: () { + Navigator.pop( + context, + ); + apiService + .getPdfDownload( + plan.forexId, + ); + }, + ), + IconButton( + icon: const Icon( + Icons.comment, + color: Color( + 0xFF475569, + ), + size: 11, + ), + tooltip: + 'Trip Comments', + onPressed: () { + showDialog( + context: + context, + builder: + ( + context, + ) => CommentModalList( + // planId: plan.planId, + planId: + plan.planId.toString(), + layoutColorForUser: + layoutColor!, + role: + "Admin", + ), + ); + }, + ), + ], + ), + ), + ), + ], + ), + ], + ), ), - ), - ], - ); - }).toList(), - ), + ], + ); + }).toList(), ), - )); + ), + ), + ); }, ); @@ -1225,9 +1262,9 @@ class _ListAllPlansState extends State { // color: Colors.red.shade50, child: Column( mainAxisAlignment: - MainAxisAlignment.center, + MainAxisAlignment.center, crossAxisAlignment: - CrossAxisAlignment.center, + CrossAxisAlignment.center, children: [ Image.asset( plan.tripType == 'Domestic' @@ -1235,10 +1272,10 @@ class _ListAllPlansState extends State { : 'assets/images/IconsImg/International_new.png', // width: 65, height: - plan.tripType == - 'Domestic' - ? 28 - : 30, + plan.tripType == + 'Domestic' + ? 28 + : 30, ), ], ), @@ -1248,14 +1285,14 @@ class _ListAllPlansState extends State { flex: 1, child: Column( crossAxisAlignment: - CrossAxisAlignment.start, + CrossAxisAlignment.start, children: [ Text( '${plan.tripTitle}', style: GoogleFonts.poppins( fontSize: 12, fontWeight: - FontWeight.w500, + FontWeight.w500, ), ), ], @@ -1282,144 +1319,173 @@ class _ListAllPlansState extends State { ), itemBuilder: (context) => [ - CustomPopupMenuEntry( - child: Container( - padding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 1, - // horizontal: 8, - // vertical: 8, - ), - child: Row( - mainAxisSize: - MainAxisSize - .min, - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - IconButton( - icon: Icon( - Icons - .remove_red_eye, - color: Color( - 0xFF475569, + CustomPopupMenuEntry( + child: Container( + padding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 1, + // horizontal: 8, + // vertical: 8, ), - size: 18, - ), - tooltip: - 'View The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); // Close popup manually - ApiService.viewPlan( - context, - plan.planId, - isViewMode: - true, - ); - }, - ), - if (plan.statusValue == - "Pending Approval" || - plan.statusValue == - "Partially Approved") - IconButton( - icon: Image.asset( - 'assets/images/IconsImg/edit.png', - width: 20, - height: - 15, - ), - tooltip: - 'Edit The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); - ApiService.viewPlan( - context, - plan.planId, - isViewMode: - false, - ); - }, - ), - IconButton( - icon: Icon( - Icons - .cancel_rounded, - size: 18, - ), - tooltip: - 'Cancellation The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); - deletePlan( - plan.planId, - ); - }, - ), - IconButton( - icon: Icon( - Icons - .download, - color: Color( - 0xFF114D8B, - ), - size: 18, - ), - tooltip: - 'Download The PDF', - onPressed: () { - Navigator.pop( - context, - ); - apiService - .getPdfDownload( - plan.planId, - ); - }, - ), - IconButton( - icon: const Icon( - Icons - .comment, - color: Color( - 0xFF475569, - ), - size: 11, - ), - tooltip: - 'Trip Comments', - onPressed: () { - showDialog( - context: - context, - builder: - ( - context, - ) => CommentModalList( - // planId: plan.planId, - planId: - plan.planId.toString(), - layoutColorForUser: - layoutColor!, - role: - "Admin", + child: Row( + mainAxisSize: + MainAxisSize + .min, + mainAxisAlignment: + MainAxisAlignment + .center, + children: [ + IconButton( + icon: Icon( + Icons + .remove_red_eye, + color: Color( + 0xFF475569, + ), + size: 18, ), - ); - }, + tooltip: + 'View The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); // Close popup manually + ApiService.viewPlan( + context, + plan.planId, + isViewMode: + true, + ); + }, + ), + if (plan.statusValue == + "Pending Approval" || + plan.statusValue == + "Partially Approved") + IconButton( + icon: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: + 15, + ), + tooltip: + 'Edit The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); + ApiService.viewPlan( + context, + plan.planId, + isViewMode: + false, + ); + }, + ), + IconButton( + icon: Icon( + Icons + .cancel_rounded, + size: 18, + ), + tooltip: + 'Cancellation The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); + deletePlan( + plan.planId, + ); + }, + ), + IconButton( + icon: Icon( + Icons + .download, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'Download The PDF', + onPressed: () { + Navigator.pop( + context, + ); + apiService + .getPdfDownload( + plan.planId, + ); + }, + ), + + if (plan.statusValue == + "Approved" && + plan.forexId != + null && + plan.forexId != + '') + IconButton( + icon: Icon( + Icons + .monetization_on_outlined, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'Download Forex PDF', + onPressed: () { + Navigator.pop( + context, + ); + apiService + .getPdfDownload( + plan.forexId, + ); + }, + ), + + IconButton( + icon: const Icon( + Icons + .comment, + color: Color( + 0xFF475569, + ), + size: 11, + ), + tooltip: + 'Trip Comments', + onPressed: () { + showDialog( + context: + context, + builder: + ( + context, + ) => CommentModalList( + // planId: plan.planId, + planId: + plan.planId.toString(), + layoutColorForUser: + layoutColor!, + role: + "Admin", + ), + ); + }, + ), + ], ), - ], + ), ), - ), - ), - ], + ], ), ], ), @@ -1428,84 +1494,86 @@ class _ListAllPlansState extends State { Row( mainAxisAlignment: - MainAxisAlignment.spaceBetween, + MainAxisAlignment.spaceBetween, crossAxisAlignment: - CrossAxisAlignment.end, + CrossAxisAlignment.end, children: [ - Flexible( child:Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - // plan.userName.isNotEmpty - // ? plan.userName - // : '${plan.travellerName}', - '${plan.userName.isNotEmpty ? plan.userName : plan.travellerName} (${plan.employeeCode ?? 'No Data'})', - style: GoogleFonts.poppins( - fontSize: 10, - color: Colors.black87, + Flexible( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + // plan.userName.isNotEmpty + // ? plan.userName + // : '${plan.travellerName}', + '${plan.userName.isNotEmpty ? plan.userName : plan.travellerName} (${plan.employeeCode ?? 'No Data'})', + style: GoogleFonts.poppins( + fontSize: 10, + color: Colors.black87, + ), + // overflow: TextOverflow.ellipsis, + // maxLines: 2, ), - // overflow: TextOverflow.ellipsis, - // maxLines: 2, - ), - // Text( - // // plan.userName.isNotEmpty - // // ? plan.userName - // // : '${plan.travellerName}', - // // '(${plan.employeeCode ?? 'No Data'})', - // plan.employeeCode ?? - // 'No Data', - // style: GoogleFonts.poppins( - // fontSize: 9, - // color: Colors.black87, - // ), - // ), - Text( - '${_formatDate(plan.createdOn)}', - style: GoogleFonts.poppins( - fontSize: 9, - color: Colors.grey, + // Text( + // // plan.userName.isNotEmpty + // // ? plan.userName + // // : '${plan.travellerName}', + // // '(${plan.employeeCode ?? 'No Data'})', + // plan.employeeCode ?? + // 'No Data', + // style: GoogleFonts.poppins( + // fontSize: 9, + // color: Colors.black87, + // ), + // ), + Text( + '${_formatDate(plan.createdOn)}', + style: GoogleFonts.poppins( + fontSize: 9, + color: Colors.grey, + ), ), - ), - ], - ),), + ], + ), + ), Column( mainAxisAlignment: - MainAxisAlignment.end, + MainAxisAlignment.end, crossAxisAlignment: - CrossAxisAlignment.end, + CrossAxisAlignment.end, children: [ GestureDetector( onTap: () => _showDetails( - plan.planId, - ), + plan.planId, + ), child: Container( padding: - EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), + EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), decoration: BoxDecoration( color: getStatusColor( plan.statusValue, ), borderRadius: - BorderRadius.circular( - 8, - ), + BorderRadius.circular( + 8, + ), ), child: Text( plan.statusValue, style: GoogleFonts.poppins( color: - getStatusTextColor( - plan.statusValue, - ), + getStatusTextColor( + plan.statusValue, + ), fontSize: 9, fontWeight: - FontWeight.w600, + FontWeight.w600, ), ), ), @@ -1835,34 +1903,34 @@ class _ListAllPlansState extends State { children: [ Expanded( child: - isDesktop - ? (searchController.text.isNotEmpty && - filteredPlans.isEmpty - ? Center( - child: Text( - "No Matches Found", - style: GoogleFonts.poppins( - fontSize: 14, - color: Colors.grey, - ), - ), - ) - : SingleChildScrollView( - scrollDirection: Axis.vertical, - child: table, - )) - : (searchController.text.isNotEmpty && - filteredPlans.isEmpty - ? Center( - child: Text( - "No Matches Found", - style: GoogleFonts.poppins( - fontSize: 14, - color: Colors.grey, - ), - ), - ) - : buildMobileCardView(paginatedPlans)), + isDesktop + ? (searchController.text.isNotEmpty && + filteredPlans.isEmpty + ? Center( + child: Text( + "No Matches Found", + style: GoogleFonts.poppins( + fontSize: 14, + color: Colors.grey, + ), + ), + ) + : SingleChildScrollView( + scrollDirection: Axis.vertical, + child: table, + )) + : (searchController.text.isNotEmpty && + filteredPlans.isEmpty + ? Center( + child: Text( + "No Matches Found", + style: GoogleFonts.poppins( + fontSize: 14, + color: Colors.grey, + ), + ), + ) + : buildMobileCardView(paginatedPlans)), // child: isDesktop // ? SingleChildScrollView( @@ -1919,4 +1987,4 @@ class _ListAllPlansState extends State { } return Colors.grey; } -} \ No newline at end of file +} diff --git a/lib/Screens/allTrips/travel_agent_list.dart b/lib/Screens/allTrips/travel_agent_list.dart index aa31d87..c5a6d9a 100644 --- a/lib/Screens/allTrips/travel_agent_list.dart +++ b/lib/Screens/allTrips/travel_agent_list.dart @@ -373,7 +373,15 @@ class _TravelAgentListPlansState extends State { // color: Colors.amber, ), child: Padding( - padding: const EdgeInsets.all(1.0), + padding: + isDesktop + ? const EdgeInsets.only( + top: 15, + bottom: 15, + left: 20, + right: 20, + ) + : const EdgeInsets.only(top: 15, bottom: 15, left: 5, right: 5), child: Container( // padding: const EdgeInsets.all(10.0), color: isDesktop ? Colors.white : Color(0xFFFCFCFC), @@ -473,6 +481,7 @@ class _TravelAgentListPlansState extends State { if (!isDesktop) const SizedBox(height: 10), if (!isDesktop) Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: MediaQuery.of(context).size.width * 0.85, @@ -694,14 +703,18 @@ class _TravelAgentListPlansState extends State { ), DataCell( - Text( - plan.tripTitle, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", + SizedBox( + width: 130, + child: Text( + plan.tripTitle, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + softWrap: true, + maxLines: 2, + // overflow: TextOverflow.ellipsis, ), - softWrap: true, - overflow: TextOverflow.ellipsis, ), ), @@ -870,6 +883,34 @@ class _TravelAgentListPlansState extends State { ); }, ), + if (plan.statusValue == + "Approved" && + plan.forexId != + null && + plan.forexId != + '') + IconButton( + icon: Icon( + Icons + .monetization_on_outlined, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'Download Forex PDF', + onPressed: () { + Navigator.pop( + context, + ); + apiService + .getPdfDownload( + plan.forexId, + ); + }, + ), + IconButton( icon: const Icon( Icons.comment, @@ -1003,6 +1044,7 @@ class _TravelAgentListPlansState extends State { PlanPopupMenu( plan: plan, deletePlan: deletePlan, + apiService: apiService, layoutColor: layoutColor, ), diff --git a/lib/Screens/approvals/approval_list.dart b/lib/Screens/approvals/approval_list.dart index 866af03..f1c714c 100644 --- a/lib/Screens/approvals/approval_list.dart +++ b/lib/Screens/approvals/approval_list.dart @@ -722,7 +722,7 @@ class _ApprovalListState extends State { padding: isDesktop ? const EdgeInsets.only(top: 15, bottom: 15, left: 20, right: 20) - : EdgeInsets.all(3.0), + : const EdgeInsets.only(top: 15, bottom: 15, left: 5, right: 5), height: isDesktop ? MediaQuery.of(context).size.height * 0.98 @@ -818,14 +818,14 @@ class _ApprovalListState extends State { ], ), - if (!isDesktop) SizedBox(height: 5), + if (!isDesktop) SizedBox(height: 10), isDesktop ? SizedBox.shrink() : Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( - width: MediaQuery.of(context).size.width * 0.82, + width: MediaQuery.of(context).size.width * 0.85, height: 35, child: TextField( controller: searchController, @@ -932,496 +932,530 @@ class _ApprovalListState extends State { double minWidth = isDesktop ? constraints.maxWidth : 1300; return SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: SingleChildScrollView( scrollDirection: Axis.vertical, - child: - ConstrainedBox( - constraints: BoxConstraints(minWidth: minWidth), - child: DataTable( - dividerThickness: 0.5, - columnSpacing: isDesktop ? 24.0 : 16.0, - border: TableBorder( - horizontalInside: BorderSide( - width: 0.5, - color: Colors.grey.shade200, - ), - ), - columns: [ - DataColumn( - label: Text( - 'Trip ID', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, + child: ConstrainedBox( + constraints: BoxConstraints(minWidth: minWidth), + child: DataTable( + dividerThickness: 0.5, + columnSpacing: isDesktop ? 24.0 : 16.0, + border: TableBorder( + horizontalInside: BorderSide( + width: 0.5, + color: Colors.grey.shade200, ), ), - ), - DataColumn( - label: Text( - 'Trip Name', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - DataColumn( - label: Text( - 'Emp Code', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - DataColumn( - label: Text( - 'Traveller', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - DataColumn( - label: Text( - 'Approver', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - DataColumn( - label: Text( - 'Trip Type', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - DataColumn( - label: Text( - 'Created On', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - DataColumn( - label: Text( - 'Status', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - DataColumn( - label: Text( - 'Actions', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - ], - rows: - paginatedPlans.map((plan) { - return DataRow( - cells: [ - DataCell( - Text( - plan.planId, - style: TextStyle( - fontSize: 13, - fontFamily: "Archivo", - ), - ), + columns: [ + DataColumn( + label: Text( + 'Trip ID', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), - - DataCell( - Text( - plan.tripTitle, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - softWrap: true, - overflow: TextOverflow.ellipsis, - ), + ), + ), + DataColumn( + label: Text( + 'Trip Name', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), - DataCell( - Text( - plan.employeeCode ?? " - ", - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - softWrap: true, - overflow: TextOverflow.ellipsis, - ), + ), + ), + DataColumn( + label: Text( + 'Emp Code', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), - DataCell( - Text( - plan.userName.isNotEmpty - ? plan.userName - : plan.travellerName, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - softWrap: true, - overflow: TextOverflow.ellipsis, - ), + ), + ), + DataColumn( + label: Text( + 'Traveller', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), - // DataCell( - // Column( - // crossAxisAlignment: - // CrossAxisAlignment.start, - // mainAxisAlignment: - // MainAxisAlignment.center, - // - // children: [ - // SizedBox(height: 1), - // Text( - // plan.userName.isNotEmpty - // ? plan.userName - // : plan.travellerName, - // style: TextStyle( - // fontSize: 12, - // fontFamily: "Inter", - // ), - // ), - // SizedBox(height: 3), - // Expanded( - // child: Text( - // "(${plan.employeeCode})" ?? - // " - ", - // style: GoogleFonts.poppins( - // fontSize: 10, - // // fontFamily: "Inter", - // ), - // ), - // ), - // ], - // ), - // ), - DataCell( - Text( - plan.approverName ?? " ", - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), + ), + ), + DataColumn( + label: Text( + 'Approver', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), - DataCell( - Text( - plan.tripType, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), + ), + ), + DataColumn( + label: Text( + 'Trip Type', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), - - DataCell( - Text( - // plan.createdOn, - _formatDate(plan.createdOn), - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), + ), + ), + DataColumn( + label: Text( + 'Created On', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), - // DataCell( - // Container( - // width: - // double - // .infinity, // Set your desired fixed size (equal width and height) - // height: 25, - // alignment: Alignment.center, - // decoration: BoxDecoration( - // color: getStatusColor( - // plan.statusValue, - // ), - // borderRadius: BorderRadius.circular( - // 8, - // ), - // ), - // - // child: Text( - // plan.statusValue, - // textAlign: TextAlign.center, - // style: TextStyle( - // color: getStatusTextColor( - // plan.statusValue, - // ), - // fontSize: 12, - // fontFamily: "Inter", - // fontWeight: FontWeight.w400, - // ), - // ), - // ), - // ), - DataCell( - GestureDetector( - onTap: () => _showDetails(plan.planId), - child: Container( - width: double.infinity, - height: 25, - alignment: Alignment.center, - decoration: BoxDecoration( - color: getStatusColor( - plan.statusValue, - ), - borderRadius: BorderRadius.circular( - 8, - ), - ), - child: Text( - plan.statusValue, - textAlign: TextAlign.center, + ), + ), + DataColumn( + label: Text( + 'Status', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + DataColumn( + label: Text( + 'Actions', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + rows: + paginatedPlans.map((plan) { + return DataRow( + cells: [ + DataCell( + Text( + plan.planId, style: TextStyle( - color: getStatusTextColor( - plan.statusValue, - ), - fontSize: 12, - fontFamily: "Inter", - fontWeight: FontWeight.w400, + fontSize: 13, + fontFamily: "Archivo", ), ), ), - ), - ), - DataCell( - Row( - children: [ - PopupMenuButton( - color: Colors.white, - padding: EdgeInsets.zero, - offset: Offset(0, 30), - icon: Icon( - Icons.more_vert, - color: Color(0xFF475569), - size: 14, + + DataCell( + SizedBox( + width: 130, + child: Text( + plan.tripTitle, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + softWrap: true, + maxLines: 2, + // overflow: TextOverflow.ellipsis, ), - itemBuilder: - (context) => [ - CustomPopupMenuEntry( - child: Container( - padding: - EdgeInsets.symmetric( - horizontal: 8, - vertical: 8, - ), - child: Row( - mainAxisSize: - MainAxisSize.min, - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - IconButton( - icon: Icon( - Icons - .remove_red_eye, - color: Color( - 0xFF475569, + ), + ), + DataCell( + Text( + plan.employeeCode ?? " - ", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + softWrap: true, + overflow: TextOverflow.ellipsis, + ), + ), + DataCell( + Text( + plan.userName.isNotEmpty + ? plan.userName + : plan.travellerName, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + softWrap: true, + overflow: TextOverflow.ellipsis, + ), + ), + // DataCell( + // Column( + // crossAxisAlignment: + // CrossAxisAlignment.start, + // mainAxisAlignment: + // MainAxisAlignment.center, + // + // children: [ + // SizedBox(height: 1), + // Text( + // plan.userName.isNotEmpty + // ? plan.userName + // : plan.travellerName, + // style: TextStyle( + // fontSize: 12, + // fontFamily: "Inter", + // ), + // ), + // SizedBox(height: 3), + // Expanded( + // child: Text( + // "(${plan.employeeCode})" ?? + // " - ", + // style: GoogleFonts.poppins( + // fontSize: 10, + // // fontFamily: "Inter", + // ), + // ), + // ), + // ], + // ), + // ), + DataCell( + Text( + plan.approverName ?? " ", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + Text( + plan.tripType, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + + DataCell( + Text( + // plan.createdOn, + _formatDate(plan.createdOn), + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + // DataCell( + // Container( + // width: + // double + // .infinity, // Set your desired fixed size (equal width and height) + // height: 25, + // alignment: Alignment.center, + // decoration: BoxDecoration( + // color: getStatusColor( + // plan.statusValue, + // ), + // borderRadius: BorderRadius.circular( + // 8, + // ), + // ), + // + // child: Text( + // plan.statusValue, + // textAlign: TextAlign.center, + // style: TextStyle( + // color: getStatusTextColor( + // plan.statusValue, + // ), + // fontSize: 12, + // fontFamily: "Inter", + // fontWeight: FontWeight.w400, + // ), + // ), + // ), + // ), + DataCell( + GestureDetector( + onTap: + () => _showDetails(plan.planId), + child: Container( + width: double.infinity, + height: 25, + alignment: Alignment.center, + decoration: BoxDecoration( + color: getStatusColor( + plan.statusValue, + ), + borderRadius: + BorderRadius.circular(8), + ), + child: Text( + plan.statusValue, + textAlign: TextAlign.center, + style: TextStyle( + color: getStatusTextColor( + plan.statusValue, + ), + fontSize: 12, + fontFamily: "Inter", + fontWeight: FontWeight.w400, + ), + ), + ), + ), + ), + DataCell( + Row( + children: [ + PopupMenuButton( + color: Colors.white, + padding: EdgeInsets.zero, + offset: Offset(0, 30), + icon: Icon( + Icons.more_vert, + color: Color(0xFF475569), + size: 14, + ), + itemBuilder: + (context) => [ + CustomPopupMenuEntry( + child: Container( + padding: + EdgeInsets.symmetric( + horizontal: 8, + vertical: 8, ), - size: 18, - ), - tooltip: - 'View The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); // Close popup manually - viewPlanforApprover( - plan.planId, - plan.approverId, - plan.delegaterId, - isViewMode: - true, - isApprover: - true, - ); - }, - ), - if (plan.statusValue == - "Pending Approval" || - plan.statusValue == - "Partially Approved") - IconButton( - icon: Image.asset( - 'assets/images/IconsImg/edit.png', - width: 20, - height: 15, + child: Row( + mainAxisSize: + MainAxisSize + .min, + mainAxisAlignment: + MainAxisAlignment + .center, + children: [ + IconButton( + icon: Icon( + Icons + .remove_red_eye, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'View The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); // Close popup manually + viewPlanforApprover( + plan.planId, + plan.approverId, + plan.delegaterId, + isViewMode: + true, + isApprover: + true, + ); + }, ), - tooltip: - 'Edit The Trip Details', - onPressed: () { - print( - "Approver Edit : ${plan.approverId}", - ); - print( - "Approver Edit2 : ${plan.delegaterId}", - ); - print( - "Approver Edit3 : ${plan.approver_status}", - ); - Navigator.pop( - context, - ); - ApiService.viewPlanForApprover( - context, - plan.planId, - plan.approverId, - plan.delegaterId, - plan.approver_status, - isViewMode: - false, - isApprover: - true, - ); - }, - ), - IconButton( - icon: Icon( - Icons - .cancel_rounded, - size: 18, - ), - tooltip: - 'Cancellation The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); - deletePlan( - plan.planId, - ); - }, - ), - IconButton( - icon: Icon( - Icons.download, - color: Color( - 0xFF114D8B, - ), - size: 18, - ), - tooltip: - 'Download The PDF', - onPressed: () { - Navigator.pop( - context, - ); - apiService - .getPdfDownload( + if (plan.statusValue == + "Pending Approval" || + plan.statusValue == + "Partially Approved") + IconButton( + icon: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ), + tooltip: + 'Edit The Trip Details', + onPressed: () { + print( + "Approver Edit : ${plan.approverId}", + ); + print( + "Approver Edit2 : ${plan.delegaterId}", + ); + print( + "Approver Edit3 : ${plan.approver_status}", + ); + Navigator.pop( + context, + ); + ApiService.viewPlanForApprover( + context, + plan.planId, + plan.approverId, + plan.delegaterId, + plan.approver_status, + isViewMode: + false, + isApprover: + true, + ); + }, + ), + IconButton( + icon: Icon( + Icons + .cancel_rounded, + size: 18, + ), + tooltip: + 'Cancellation The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); + deletePlan( plan.planId, ); - }, - ), - IconButton( - icon: const Icon( - Icons.comment, - color: Color( - 0xFF475569, + }, ), - size: 11, - ), - tooltip: - 'Approver Comment', - onPressed: () { - showDialog( - context: + IconButton( + icon: Icon( + Icons + .download, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'Download The PDF', + onPressed: () { + Navigator.pop( context, - builder: - ( - context, - ) => CommentModalList( - // planId: plan.planId, - planId: - plan.planId - .toString(), - layoutColorForUser: - layoutColor!, - role: - "Approver", + ); + apiService + .getPdfDownload( + plan.planId, + ); + }, + ), + if (plan.statusValue == + "Approved" && + plan.forexId != + null && + plan.forexId != + '') + IconButton( + icon: Icon( + Icons + .monetization_on_outlined, + color: Color( + 0xFF475569, ), - ); - }, + size: 18, + ), + tooltip: + 'Download Forex PDF', + onPressed: () { + Navigator.pop( + context, + ); + apiService + .getPdfDownload( + plan.forexId, + ); + }, + ), + + IconButton( + icon: const Icon( + Icons.comment, + color: Color( + 0xFF475569, + ), + size: 11, + ), + tooltip: + 'Approver Comment', + onPressed: () { + showDialog( + context: + context, + builder: + ( + context, + ) => CommentModalList( + // planId: plan.planId, + planId: + plan.planId.toString(), + layoutColorForUser: + layoutColor!, + role: + "Approver", + ), + ); + }, + ), + ], ), - ], + ), ), - ), - ), - ], + ], + ), + ], ), - ], - ), - ), - // DataCell(Row(children: [ - // IconButton( - // icon: const Icon( - // Icons.remove_red_eye, - // color: Color(0xFF475569), - // size: 18, - // ), - // onPressed: () => viewPlanforApprover( - // plan.planId, - // isViewMode: true, - // isApprover: true)), - // - // GestureDetector( - // onTap: () => ApiService.viewPlanForApprover( - // context, plan.planId, - // isViewMode: false, isApprover: true), - // child: Image.asset( - // 'assets/images/IconsImg/edit.png', - // width: 20, - // height: 15), - // ), - // - // // IconButton( - // // icon: const Icon(Icons.edit, - // // color: Colors.green), - // // onPressed: () => viewPlanforApprover(plan.planId, - // // isViewMode: false) ), - // - // SizedBox( - // width: 5, - // ), - // GestureDetector( - // onTap: () => deletePlan(plan.planId), - // child: Image.asset( - // 'assets/images/IconsImg/delete.png', - // width: 20, - // height: 15), - // ), - // - // IconButton( - // icon: const Icon( - // Icons.download, - // color: Color(0xFF475569), - // size: 18, - // ), - // onPressed: () { - // apiService.getPdfDownload(plan.planId); - // }), - // ])), - ], - ); - }).toList(), + ), + // DataCell(Row(children: [ + // IconButton( + // icon: const Icon( + // Icons.remove_red_eye, + // color: Color(0xFF475569), + // size: 18, + // ), + // onPressed: () => viewPlanforApprover( + // plan.planId, + // isViewMode: true, + // isApprover: true)), + // + // GestureDetector( + // onTap: () => ApiService.viewPlanForApprover( + // context, plan.planId, + // isViewMode: false, isApprover: true), + // child: Image.asset( + // 'assets/images/IconsImg/edit.png', + // width: 20, + // height: 15), + // ), + // + // // IconButton( + // // icon: const Icon(Icons.edit, + // // color: Colors.green), + // // onPressed: () => viewPlanforApprover(plan.planId, + // // isViewMode: false) ), + // + // SizedBox( + // width: 5, + // ), + // GestureDetector( + // onTap: () => deletePlan(plan.planId), + // child: Image.asset( + // 'assets/images/IconsImg/delete.png', + // width: 20, + // height: 15), + // ), + // + // IconButton( + // icon: const Icon( + // Icons.download, + // color: Color(0xFF475569), + // size: 18, + // ), + // onPressed: () { + // apiService.getPdfDownload(plan.planId); + // }), + // ])), + ], + ); + }).toList(), + ), + ), ), - ))); + ); }, ); @@ -1460,16 +1494,20 @@ class _ApprovalListState extends State { // color: Colors.red.shade50, child: Column( mainAxisAlignment: - MainAxisAlignment.center, + MainAxisAlignment.center, crossAxisAlignment: - CrossAxisAlignment.center, + CrossAxisAlignment.center, children: [ Image.asset( plan.tripType == 'Domestic' ? 'assets/images/IconsImg/Domestic_new.png' : 'assets/images/IconsImg/International_new.png', // width: 65, - height: plan.tripType == 'Domestic' ? 28 : 30, + height: + plan.tripType == + 'Domestic' + ? 28 + : 30, ), ], ), @@ -1479,14 +1517,14 @@ class _ApprovalListState extends State { flex: 1, child: Column( crossAxisAlignment: - CrossAxisAlignment.start, + CrossAxisAlignment.start, children: [ Text( '${plan.tripTitle}', style: GoogleFonts.poppins( fontSize: 12, fontWeight: - FontWeight.w500, + FontWeight.w500, ), ), ], @@ -1513,148 +1551,160 @@ class _ApprovalListState extends State { ), itemBuilder: (context) => [ - CustomPopupMenuEntry( - child: Container( - padding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 1, - // horizontal: 8, - // vertical: 8, - ), - child: Row( - mainAxisSize: - MainAxisSize - .min, - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - IconButton( - icon: Icon( - Icons - .remove_red_eye, - color: Color( - 0xFF475569, + CustomPopupMenuEntry( + child: Container( + padding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 1, + // horizontal: 8, + // vertical: 8, ), - size: 18, - ), - tooltip: - 'View The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); // Close popup manually - viewPlanforApprover( - plan.planId, - plan.approverId, - plan.delegaterId, - isViewMode:true, - isApprover:true, - ); - }, - ), - if (plan.statusValue == - "Pending Approval" || - plan.statusValue == - "Partially Approved") - IconButton( - icon: Image.asset( - 'assets/images/IconsImg/edit.png', - width: 20, - height: - 15, - ), - tooltip: - 'Edit The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); // Close popup manually - viewPlanforApprover( - plan.planId, - plan.approverId, - plan.delegaterId, - isViewMode: true, - isApprover: true, - ); - }, - ), - IconButton( - icon: Icon( - Icons - .download, - color: Color( - 0xFF114D8B, - ), - size: 18, - ), - tooltip: - 'Download The PDF', - onPressed: () { - Navigator.pop(context); - apiService - .getPdfDownload( - plan.planId, - ); - }, - ), - IconButton( - icon: Icon( - Icons - .download, - color: Color( - 0xFF114D8B, - ), - size: 18, - ), - tooltip: - 'Download The PDF', - onPressed: () { - Navigator.pop( - context, - ); - apiService - .getPdfDownload( - plan.planId, - ); - }, - ), - IconButton( - icon: const Icon( - Icons - .comment, - color: Color( - 0xFF475569, - ), - size: 11, - ), - tooltip: - 'Trip Comments', - onPressed: () { - showDialog( - context: context, - builder: - ( - context, - ) => CommentModalList( - // planId: plan.planId, - planId: - plan.planId - .toString(), - layoutColorForUser: - layoutColor!, - role: - "Approver", + child: Row( + mainAxisSize: + MainAxisSize + .min, + mainAxisAlignment: + MainAxisAlignment + .center, + children: [ + IconButton( + icon: Icon( + Icons + .remove_red_eye, + color: Color( + 0xFF475569, + ), + size: 18, ), - ); - }, + tooltip: + 'View The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); // Close popup manually + viewPlanforApprover( + plan.planId, + plan.approverId, + plan.delegaterId, + isViewMode: + true, + isApprover: + true, + ); + }, + ), + if (plan.statusValue == + "Pending Approval" || + plan.statusValue == + "Partially Approved") + IconButton( + icon: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: + 15, + ), + tooltip: + 'Edit The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); // Close popup manually + viewPlanforApprover( + plan.planId, + plan.approverId, + plan.delegaterId, + isViewMode: + true, + isApprover: + true, + ); + }, + ), + IconButton( + icon: Icon( + Icons + .download, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'Download The PDF', + onPressed: () { + Navigator.pop( + context, + ); + apiService + .getPdfDownload( + plan.planId, + ); + }, + ), + if (plan.statusValue == + "Approved" && + plan.forexId != + null && + plan.forexId != + '') + IconButton( + icon: Icon( + Icons + .monetization_on_outlined, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'Download Forex PDF', + onPressed: () { + Navigator.pop( + context, + ); + apiService + .getPdfDownload( + plan.forexId, + ); + }, + ), + IconButton( + icon: const Icon( + Icons + .comment, + color: Color( + 0xFF475569, + ), + size: 11, + ), + tooltip: + 'Trip Comments', + onPressed: () { + showDialog( + context: + context, + builder: + ( + context, + ) => CommentModalList( + // planId: plan.planId, + planId: + plan.planId.toString(), + layoutColorForUser: + layoutColor!, + role: + "Approver", + ), + ); + }, + ), + ], ), - ], + ), ), - ), - ), - ], + ], ), ], ), @@ -1663,69 +1713,71 @@ class _ApprovalListState extends State { Row( mainAxisAlignment: - MainAxisAlignment.spaceBetween, + MainAxisAlignment.spaceBetween, crossAxisAlignment: - CrossAxisAlignment.end, + CrossAxisAlignment.end, children: [ - Flexible( child:Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - '${plan.userName.isNotEmpty ? plan.userName : plan.travellerName} (${plan.employeeCode ?? 'No Data'})', - style: GoogleFonts.poppins( - fontSize: 10, - color: Colors.black87, + Flexible( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + '${plan.userName.isNotEmpty ? plan.userName : plan.travellerName} (${plan.employeeCode ?? 'No Data'})', + style: GoogleFonts.poppins( + fontSize: 10, + color: Colors.black87, + ), + // overflow: TextOverflow.ellipsis, + // maxLines: 2, ), - // overflow: TextOverflow.ellipsis, - // maxLines: 2, - ), - Text( - '${_formatDate(plan.createdOn)}', - style: GoogleFonts.poppins( - fontSize: 9, - color: Colors.grey, + Text( + '${_formatDate(plan.createdOn)}', + style: GoogleFonts.poppins( + fontSize: 9, + color: Colors.grey, + ), ), - ), - ], - ),), + ], + ), + ), Column( mainAxisAlignment: - MainAxisAlignment.end, + MainAxisAlignment.end, crossAxisAlignment: - CrossAxisAlignment.end, + CrossAxisAlignment.end, children: [ GestureDetector( onTap: () => _showDetails( - plan.planId, - ), + plan.planId, + ), child: Container( padding: - EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), + EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), decoration: BoxDecoration( color: getStatusColor( plan.statusValue, ), borderRadius: - BorderRadius.circular( - 8, - ), + BorderRadius.circular( + 8, + ), ), child: Text( plan.statusValue, style: GoogleFonts.poppins( color: - getStatusTextColor( - plan.statusValue, - ), + getStatusTextColor( + plan.statusValue, + ), fontSize: 9, fontWeight: - FontWeight.w600, + FontWeight.w600, ), ), ), diff --git a/lib/Screens/itnerary_list/flight_list.dart b/lib/Screens/itnerary_list/flight_list.dart index 76b58c1..3c4606b 100644 --- a/lib/Screens/itnerary_list/flight_list.dart +++ b/lib/Screens/itnerary_list/flight_list.dart @@ -254,8 +254,8 @@ class _FlightListWidgetState extends State { "No Data Found", textAlign: TextAlign.center, style: GoogleFonts.poppins( - fontSize: 20, - fontWeight: FontWeight.bold, + fontSize: 18, + fontWeight: FontWeight.w500, color: Colors.grey, ), ), diff --git a/lib/Screens/plans/create_plans.dart b/lib/Screens/plans/create_plans.dart index 76d4802..e545f60 100644 --- a/lib/Screens/plans/create_plans.dart +++ b/lib/Screens/plans/create_plans.dart @@ -448,8 +448,9 @@ class CreateNewPlansState extends State { String? selectedPurpose; Map validationErrors = {}; - List> miscellaneousList = []; + // List> miscellaneousList = [{"special_request": 1, "comments": "posta", "indx": 1}]; + List> miscellaneousList = []; List> visaList = []; List> insuranceList = []; List> accommodationList = []; @@ -1316,6 +1317,56 @@ class CreateNewPlansState extends State { } } + Future serviceHasData() async { + return miscellaneousList.isNotEmpty || + visaList.isNotEmpty || + insuranceList.isNotEmpty || + accommodationList.isNotEmpty || + trainList.isNotEmpty || + flightList.isNotEmpty || + busList.isNotEmpty || + taxiList.isNotEmpty || + forexList.isNotEmpty; + } + + void clearAllServiceLists() async { + setState(() { + miscellaneousList = []; + visaList = []; + insuranceList = []; + accommodationList = []; + trainList = []; + flightList = []; + busList = []; + taxiList = []; + forexList = []; + + planData['miscellaneous'] = []; + planData['visa'] = []; + planData['insurance'] = []; + planData['accommodation'] = []; + planData['train'] = []; + planData['flight'] = []; + planData['bus'] = []; + planData['taxi'] = []; + planData['forex'] = []; + }); + + // Debugging output + print("After clearing:"); + print("After clearing: $planData"); + + print("miscellaneousList: ${miscellaneousList.length}"); + print("visaList: ${visaList.length}"); + print("insuranceList: ${insuranceList.length}"); + print("accommodationList: ${accommodationList.length}"); + print("trainList: ${trainList.length}"); + print("flightList: ${flightList.length}"); + print("busList: ${busList.length}"); + print("taxiList: ${taxiList.length}"); + print("forexList: ${forexList.length}"); + } + Future checkExceptionalClass() async { // pretend we fetch something await Future.delayed(Duration(seconds: 1)); // Example async operation @@ -1850,6 +1901,7 @@ class CreateNewPlansState extends State { onItineraryUpdate: handleItineraryUpdate, onExeptionalClass: handleExcentionalClass, loginUser: selfId, + selectedPlanData: planData, isViewMode: widget.isViewMode, ), @@ -1948,10 +2000,45 @@ class CreateNewPlansState extends State { child: GestureDetector( onTap: () { + print("TRIP CLICKESS1"); // Request focus when user taps focusNodes["trip_typeFocusNode"]?.requestFocus(); + print("TRIP CLICKESS15"); }, child: DropdownSearch>( + onBeforePopupOpening: (selectedItem) async { + bool hasData = await serviceHasData(); + if (hasData) { + bool? shouldProceed = await showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text( + "Changing trip type will remove added services", + ), + content: Text("Do you wish to proceed?"), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(false); // Cancel + }, + child: Text("Cancel"), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); // Continue + }, + child: Text("Continue"), + ), + ], + ); + }, + ); + + return shouldProceed ?? false; + } + return true; + }, popupProps: PopupProps.menu( showSearchBox: false, // Optionally enable search fit: FlexFit.loose, @@ -2046,6 +2133,16 @@ class CreateNewPlansState extends State { widget.isViewMode ? null : (Map? newItem) { + final newTripType = + newItem?['dropdown_key'].toString(); + print("newTripType - $newTripType"); + print("_selectedTripType- $_selectedTripType"); + if (newTripType != _selectedTripType) { + print("Type changed"); + clearAllServiceLists(); + dynamicItineraryKey.currentState + ?.clearAllServiceLists(); + } if (newItem != null) { setState(() { _selectedTripType = @@ -2059,6 +2156,7 @@ class CreateNewPlansState extends State { fetchTrainFlightClass( int.parse(_selectedTripType!), ); + dynamicItineraryKey.currentState ?.updateSelectedServices(); }); diff --git a/lib/Screens/plans/dynamic_itinerary_stepper.dart b/lib/Screens/plans/dynamic_itinerary_stepper.dart index 949aa08..bb058a4 100644 --- a/lib/Screens/plans/dynamic_itinerary_stepper.dart +++ b/lib/Screens/plans/dynamic_itinerary_stepper.dart @@ -104,6 +104,7 @@ class DynamicItineraryState extends State { @override void initState() { + print("DynamicItinerary"); super.initState(); handleSelectedPlan(); updateSelectedServices(); @@ -128,7 +129,7 @@ class DynamicItineraryState extends State { // selectedIndex = null; // selectedItem = null; // }); - + print("updateTripType - $_tripType"); updateTripType(widget.tripType); } } @@ -187,6 +188,9 @@ class DynamicItineraryState extends State { _tripType = newTripType; }); updateSelectedServices(); // Refresh services based on new tripType + + print("updateTripType2 - $newTripType"); + handleSelectedPlan(); } } @@ -268,6 +272,13 @@ class DynamicItineraryState extends State { } } + void clearAllServiceLists() async { + print("clearAllServiceLists"); + setState(() { + itineraryData.updateAll((key, value) => []); + }); + } + // Future updateSelectedServices() async { // await loadAllServices(); // await loadOrgSelectedAlServices(); @@ -389,6 +400,7 @@ class DynamicItineraryState extends State { } void handleSelectedPlan() { + print("handleSelectedPlan"); // Check if selectedPlanData has itinerary data if (hasAnyItineraryData()) { print("selectedPlanData HAS DATA"); diff --git a/lib/Screens/plans/list_plans.dart b/lib/Screens/plans/list_plans.dart index 147280a..6f930ae 100644 --- a/lib/Screens/plans/list_plans.dart +++ b/lib/Screens/plans/list_plans.dart @@ -78,15 +78,15 @@ class _ListPlansState extends State { print("msUser - $msUser"); html.window.history.pushState(null, '', html.window.location.href); - if(!msUser){ - _popStateListener = html.window.onPopState.listen((event) { - if (!_dialogShown && mounted) { - _showBackConfirmationDialog(); - } + if (!msUser) { + _popStateListener = html.window.onPopState.listen((event) { + if (!_dialogShown && mounted) { + _showBackConfirmationDialog(); + } - // Re-push to prevent leaving - html.window.history.pushState(null, '', html.window.location.href); - }); + // Re-push to prevent leaving + html.window.history.pushState(null, '', html.window.location.href); + }); } } } @@ -645,7 +645,10 @@ class _ListPlansState extends State { return Container( margin: isDesktop ? EdgeInsets.all(10.0) : null, - padding: const EdgeInsets.only(top: 15, bottom: 15, left: 20, right: 20), + padding: + isDesktop + ? const EdgeInsets.only(top: 15, bottom: 15, left: 20, right: 20) + : const EdgeInsets.only(top: 15, bottom: 15, left: 5, right: 5), height: isDesktop ? MediaQuery.of(context).size.height * 0.98 @@ -839,6 +842,7 @@ class _ListPlansState extends State { if (!isDesktop) const SizedBox(height: 10), if (!isDesktop) Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: MediaQuery.of(context).size.width * 0.85, @@ -961,416 +965,455 @@ class _ListPlansState extends State { double minWidth = isDesktop ? constraints.maxWidth : 1300; return SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: SingleChildScrollView( scrollDirection: Axis.vertical, - child:ConstrainedBox( - constraints: BoxConstraints(minWidth: minWidth), - child: DataTable( - dividerThickness: 0.5, - columnSpacing: isDesktop ? 24.0 : 16.0, - border: TableBorder( - horizontalInside: BorderSide( - width: 0.5, - color: Colors.grey.shade200, - ), - ), - columns: [ - DataColumn( - label: Text( - 'Trip ID', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, + child: ConstrainedBox( + constraints: BoxConstraints(minWidth: minWidth), + child: DataTable( + dividerThickness: 0.5, + columnSpacing: isDesktop ? 24.0 : 16.0, + border: TableBorder( + horizontalInside: BorderSide( + width: 0.5, + color: Colors.grey.shade200, ), ), - ), - DataColumn( - label: Text( - 'Trip Name', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, + columns: [ + DataColumn( + label: Text( + 'Trip ID', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), ), - ), - ), - DataColumn( - label: Text( - 'Emp Code', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - DataColumn( - label: Text( - 'Traveller', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - DataColumn( - label: Text( - 'Trip Type', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - DataColumn( - label: Text( - 'Created On', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - DataColumn( - label: Text( - 'Status', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - DataColumn( - label: Text( - 'Actions', - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - ], - rows: - paginatedPlans.map((plan) { - return DataRow( - cells: [ - DataCell( - Text( - plan.planId, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), + DataColumn( + label: Expanded( + flex: 1, + child: Text( + 'Trip Name', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), ), - - DataCell( - Text( - plan.tripTitle, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - softWrap: true, - overflow: TextOverflow.ellipsis, - ), + ), + ), + DataColumn( + label: Text( + 'Emp Code', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), - - DataCell( - Text( - plan.employeeCode ?? " - ", - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), + ), + ), + DataColumn( + label: Text( + 'Traveller', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), - DataCell( - Text( - plan.userName.isNotEmpty - ? plan.userName - : plan.travellerName, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), + ), + ), + DataColumn( + label: Text( + 'Trip Type', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), - DataCell( - Text( - plan.tripType, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), + ), + ), + DataColumn( + label: Text( + 'Created On', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), - DataCell( - Text( - _formatDate(plan.createdOn), - // plan.createdOn, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - ), + ), + ), + DataColumn( + label: Text( + 'Status', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), - DataCell( - GestureDetector( - onTap: () => _showDetails(plan.planId), - child: Container( - width: - double - .infinity, // Set your desired fixed size (equal width and height) - height: 25, - alignment: Alignment.center, - decoration: BoxDecoration( - color: getStatusColor( - plan.statusValue, - ), - // color: plan.statusValue == - // "Partially Approved" - // ? Colors.yellow.shade100 - // : plan.statusValue == "Approved" - // ? Colors.green.shade100 - // : plan.statusValue == "Completed" - // ? Colors.green.shade500 - // : plan.statusValue == "Rejected" - // ? Colors.red.shade100 - // : Colors.grey.shade100, - borderRadius: BorderRadius.circular( - 10, - ), - ), - child: Text( - plan.statusValue, - textAlign: TextAlign.center, + ), + ), + DataColumn( + label: Text( + 'Actions', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + rows: + paginatedPlans.map((plan) { + return DataRow( + cells: [ + DataCell( + Text( + plan.planId, style: TextStyle( - color: getStatusTextColor( - plan.statusValue, - ), - // color: (plan.statusValue == - // "Partially Approved" || - // plan.statusValue == "Approved" || - // plan.statusValue == "Rejected") - // ? Colors.black - // : plan.statusValue == "Completed" - // ? Colors.white - // : Colors.grey, - fontSize: 12, + fontSize: 13, fontFamily: "Inter", - fontWeight: FontWeight.w400, ), ), ), - ), - ), - DataCell( - Row( - children: [ - PopupMenuButton( - color: Colors.white, - padding: EdgeInsets.zero, - offset: Offset(0, 30), - icon: Icon( - Icons.more_vert, - size: 14, - color: Color(0xFF475569), + + DataCell( + SizedBox( + width: 130, + child: Text( + plan.tripTitle, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + softWrap: true, + maxLines: 2, + // overflow: TextOverflow.ellipsis, ), - itemBuilder: - (context) => [ - CustomPopupMenuEntry( - child: Container( - padding: - EdgeInsets.symmetric( - horizontal: 8, - vertical: 8, - ), - child: Row( - mainAxisSize: - MainAxisSize.min, - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - IconButton( - icon: Icon( - Icons - .remove_red_eye, - color: Color( - 0xFF475569, + ), + ), + + DataCell( + Text( + plan.employeeCode ?? " - ", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + Text( + plan.userName.isNotEmpty + ? plan.userName + : plan.travellerName, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + Text( + plan.tripType, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + Text( + _formatDate(plan.createdOn), + // plan.createdOn, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + GestureDetector( + onTap: + () => _showDetails(plan.planId), + child: Container( + width: + double + .infinity, // Set your desired fixed size (equal width and height) + height: 25, + alignment: Alignment.center, + decoration: BoxDecoration( + color: getStatusColor( + plan.statusValue, + ), + // color: plan.statusValue == + // "Partially Approved" + // ? Colors.yellow.shade100 + // : plan.statusValue == "Approved" + // ? Colors.green.shade100 + // : plan.statusValue == "Completed" + // ? Colors.green.shade500 + // : plan.statusValue == "Rejected" + // ? Colors.red.shade100 + // : Colors.grey.shade100, + borderRadius: + BorderRadius.circular(10), + ), + child: Text( + plan.statusValue, + textAlign: TextAlign.center, + style: TextStyle( + color: getStatusTextColor( + plan.statusValue, + ), + // color: (plan.statusValue == + // "Partially Approved" || + // plan.statusValue == "Approved" || + // plan.statusValue == "Rejected") + // ? Colors.black + // : plan.statusValue == "Completed" + // ? Colors.white + // : Colors.grey, + fontSize: 12, + fontFamily: "Inter", + fontWeight: FontWeight.w400, + ), + ), + ), + ), + ), + DataCell( + Row( + children: [ + PopupMenuButton( + color: Colors.white, + padding: EdgeInsets.zero, + offset: Offset(0, 30), + icon: Icon( + Icons.more_vert, + size: 14, + color: Color(0xFF475569), + ), + itemBuilder: + (context) => [ + CustomPopupMenuEntry( + child: Container( + padding: + EdgeInsets.symmetric( + horizontal: 8, + vertical: 8, ), - size: 18, - ), - tooltip: - 'View The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); // Close popup manually - ApiService.viewPlan( - context, - plan.planId, - isViewMode: - true, - isMyTrips: true, - ); - }, - ), - if (plan.statusValue == - "Pending Approval" || - plan.statusValue == - "Partially Approved") - IconButton( - icon: Image.asset( - 'assets/images/IconsImg/edit.png', - width: 20, - height: 15, + child: Row( + mainAxisSize: + MainAxisSize + .min, + mainAxisAlignment: + MainAxisAlignment + .center, + children: [ + IconButton( + icon: Icon( + Icons + .remove_red_eye, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'View The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); // Close popup manually + ApiService.viewPlan( + context, + plan.planId, + isViewMode: + true, + isMyTrips: + true, + ); + }, ), - tooltip: - 'Edit Trip Details', - onPressed: () { - Navigator.pop( - context, - ); - ApiService.viewPlan( - context, - plan.planId, - isViewMode: - false, - isMyTrips: - true, - ); - }, - ), - IconButton( - icon: Icon( - Icons - .cancel_rounded, - size: 18, - ), - tooltip: - 'Cancellation The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); - deletePlan( - plan.planId, - ); - }, - ), - IconButton( - icon: Icon( - Icons.download, - color: Color( - 0xFF114D8B, - ), - size: 18, - ), - tooltip: - 'Download The PDF', - onPressed: () { - Navigator.pop( - context, - ); - apiService - .getPdfDownload( + if (plan.statusValue == + "Pending Approval" || + plan.statusValue == + "Partially Approved") + IconButton( + icon: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ), + tooltip: + 'Edit Trip Details', + onPressed: () { + Navigator.pop( + context, + ); + ApiService.viewPlan( + context, + plan.planId, + isViewMode: + false, + isMyTrips: + true, + ); + }, + ), + IconButton( + icon: Icon( + Icons + .cancel_rounded, + size: 18, + ), + tooltip: + 'Cancellation The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); + deletePlan( plan.planId, ); - }, - ), - IconButton( - icon: const Icon( - Icons.comment, - color: Color( - 0xFF475569, + }, ), - size: 11, - ), - tooltip: - 'Trip Comments', - onPressed: () { - showDialog( - context: + IconButton( + icon: Icon( + Icons + .download, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'Download The PDF', + onPressed: () { + Navigator.pop( context, - builder: - ( - context, - ) => CommentModalList( - // planId: plan.planId, - planId: - plan.planId - .toString(), - layoutColorForUser: - layoutColor!, - role: - "User", - ), - ); - }, - ), - ], - ), - ), - ), - ], - ), - ], - ), - ), + ); + apiService + .getPdfDownload( + plan.planId, + ); + }, + ), - // DataCell(Row(children: [ - // IconButton( - // icon: const Icon( - // Icons.remove_red_eye, - // color: Color(0xFF475569), - // size: 18, - // ), - // onPressed: () => ApiService.viewPlan( - // context, plan.planId, - // isViewMode: true)), - // - // GestureDetector( - // onTap: () => ApiService.viewPlan( - // context, plan.planId, - // isViewMode: false), - // child: Image.asset( - // 'assets/images/IconsImg/edit.png', - // width: 15, - // height: 15), - // ), - // - // // IconButton( - // // icon: const Icon(Icons.edit, - // // color: Colors.green), - // // onPressed: () => viewPlan(plan.planId, - // // isViewMode: false) ), - // - // SizedBox( - // width: 5, - // ), - // GestureDetector( - // onTap: () => deletePlan(plan.planId), - // child: Image.asset( - // 'assets/images/IconsImg/delete.png', - // width: 20, - // height: 15), - // ), - // IconButton( - // icon: const Icon( - // Icons.download, - // color: Color(0xFF475569), - // size: 18, - // ), - // onPressed: () { - // apiService.getPdfDownload(plan.planId); - // }), - // ])), - ], - ); - }).toList(), + if (plan.statusValue == + "Approved" && + plan.forexId != + null && + plan.forexId != + '') + IconButton( + icon: Icon( + Icons + .monetization_on_outlined, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'Download Forex PDF', + onPressed: () { + Navigator.pop( + context, + ); + apiService + .getPdfDownload( + plan.forexId, + ); + }, + ), + IconButton( + icon: const Icon( + Icons.comment, + color: Color( + 0xFF475569, + ), + size: 11, + ), + tooltip: + 'Trip Comments', + onPressed: () { + showDialog( + context: + context, + builder: + ( + context, + ) => CommentModalList( + // planId: plan.planId, + planId: + plan.planId.toString(), + layoutColorForUser: + layoutColor!, + role: + "User", + ), + ); + }, + ), + ], + ), + ), + ), + ], + ), + ], + ), + ), + + // DataCell(Row(children: [ + // IconButton( + // icon: const Icon( + // Icons.remove_red_eye, + // color: Color(0xFF475569), + // size: 18, + // ), + // onPressed: () => ApiService.viewPlan( + // context, plan.planId, + // isViewMode: true)), + // + // GestureDetector( + // onTap: () => ApiService.viewPlan( + // context, plan.planId, + // isViewMode: false), + // child: Image.asset( + // 'assets/images/IconsImg/edit.png', + // width: 15, + // height: 15), + // ), + // + // // IconButton( + // // icon: const Icon(Icons.edit, + // // color: Colors.green), + // // onPressed: () => viewPlan(plan.planId, + // // isViewMode: false) ), + // + // SizedBox( + // width: 5, + // ), + // GestureDetector( + // onTap: () => deletePlan(plan.planId), + // child: Image.asset( + // 'assets/images/IconsImg/delete.png', + // width: 20, + // height: 15), + // ), + // IconButton( + // icon: const Icon( + // Icons.download, + // color: Color(0xFF475569), + // size: 18, + // ), + // onPressed: () { + // apiService.getPdfDownload(plan.planId); + // }), + // ])), + ], + ); + }).toList(), + ), + ), ), - ))); + ); }, ); @@ -1409,9 +1452,9 @@ class _ListPlansState extends State { // color: Colors.red.shade50, child: Column( mainAxisAlignment: - MainAxisAlignment.center, + MainAxisAlignment.center, crossAxisAlignment: - CrossAxisAlignment.center, + CrossAxisAlignment.center, children: [ Image.asset( plan.tripType == 'Domestic' @@ -1419,7 +1462,10 @@ class _ListPlansState extends State { : 'assets/images/IconsImg/International_new.png', // width: 65, height: - plan.tripType == 'Domestic' ? 28 : 30, + plan.tripType == + 'Domestic' + ? 28 + : 30, ), ], ), @@ -1429,14 +1475,14 @@ class _ListPlansState extends State { flex: 1, child: Column( crossAxisAlignment: - CrossAxisAlignment.start, + CrossAxisAlignment.start, children: [ Text( '${plan.tripTitle}', style: GoogleFonts.poppins( fontSize: 12, fontWeight: - FontWeight.w500, + FontWeight.w500, ), ), ], @@ -1457,126 +1503,175 @@ class _ListPlansState extends State { ), itemBuilder: (context) => [ - CustomPopupMenuEntry( - child: Container( - padding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 1, - // horizontal: 8, - // vertical: 8, - ), - child: Row( - mainAxisSize: - MainAxisSize - .min, - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - IconButton( - icon: Icon( - Icons - .remove_red_eye, - color: Color( - 0xFF475569, + CustomPopupMenuEntry( + child: Container( + padding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 1, + // horizontal: 8, + // vertical: 8, ), - size: 18, - ), - tooltip: - 'View The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); // Close popup manually - ApiService.viewPlan( - context, - plan.planId, - isViewMode:true, - isMyTrips: true, - ); - }, - ), - if (plan.statusValue == - "Pending Approval" || - plan.statusValue == - "Partially Approved") - IconButton( - icon: Image.asset( - 'assets/images/IconsImg/edit.png', - width: 20, - height: - 15, + child: Row( + mainAxisSize: + MainAxisSize + .min, + mainAxisAlignment: + MainAxisAlignment + .center, + children: [ + IconButton( + icon: Icon( + Icons + .remove_red_eye, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'View The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); // Close popup manually + ApiService.viewPlan( + context, + plan.planId, + isViewMode: + true, + isMyTrips: + true, + ); + }, ), - tooltip: - 'Edit The Trip Details', - onPressed: () { - Navigator.pop( - context, - ); - ApiService.viewPlan( - context, - plan.planId, - isViewMode:false, - isMyTrips: true, - ); - }, - ), - IconButton( - icon: Icon( - Icons - .cancel_rounded, - size: 18, - ), - tooltip: - 'Cancellation The Trip Details', - onPressed: () { - Navigator.pop(context); - deletePlan(plan.planId);}, - ), - IconButton( - icon: Icon( - Icons - .download, - color: Color( - 0xFF114D8B, + if (plan.statusValue == + "Pending Approval" || + plan.statusValue == + "Partially Approved") + IconButton( + icon: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: + 15, + ), + tooltip: + 'Edit The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); + ApiService.viewPlan( + context, + plan.planId, + isViewMode: + false, + isMyTrips: + true, + ); + }, + ), + IconButton( + icon: Icon( + Icons + .cancel_rounded, + size: 18, + ), + tooltip: + 'Cancellation The Trip Details', + onPressed: () { + Navigator.pop( + context, + ); + deletePlan( + plan.planId, + ); + }, ), - size: 18, - ), - tooltip: - 'Download The PDF', - onPressed: () { - Navigator.pop(context); - apiService.getPdfDownload(plan.planId,); - }, - ), - IconButton( - icon: const Icon( - Icons - .comment, - color: Color( - 0xFF475569, + IconButton( + icon: Icon( + Icons + .download, + color: Color( + 0xFF475569, + ), + size: 18, + ), + tooltip: + 'Download The PDF', + onPressed: () { + Navigator.pop( + context, + ); + apiService + .getPdfDownload( + plan.planId, + ); + }, ), - size: 11, - ), - tooltip: - 'Trip Comments', - onPressed: () { - showDialog( - context:context, - builder:(context) => CommentModalList( - planId:plan.planId.toString(), - layoutColorForUser:layoutColor!, - role: "User", + + if (plan.statusValue == + "Approved" && + plan.forexId != + null && + plan.forexId != + '') + IconButton( + icon: Icon( + Icons + .monetization_on_outlined, + color: Color( + 0xFF475569, ), - ); - }, + size: 18, + ), + tooltip: + 'Download Forex PDF', + onPressed: () { + Navigator.pop( + context, + ); + apiService + .getPdfDownload( + plan.forexId, + ); + }, + ), + IconButton( + icon: const Icon( + Icons + .comment, + color: Color( + 0xFF475569, + ), + size: 11, + ), + tooltip: + 'Trip Comments', + onPressed: () { + showDialog( + context: + context, + builder: + ( + context, + ) => CommentModalList( + planId: + plan.planId.toString(), + layoutColorForUser: + layoutColor!, + role: + "User", + ), + ); + }, + ), + ], ), - ], + ), ), - ), - ), - ], + ], ), ], ), @@ -1585,67 +1680,69 @@ class _ListPlansState extends State { Row( mainAxisAlignment: - MainAxisAlignment.spaceBetween, + MainAxisAlignment.spaceBetween, crossAxisAlignment: - CrossAxisAlignment.end, + CrossAxisAlignment.end, children: [ - Flexible( child:Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - '${plan.userName.isNotEmpty ? plan.userName : plan.travellerName} (${plan.employeeCode ?? 'No Data'})', - style: GoogleFonts.poppins( - fontSize: 10, - color: Colors.black87, + Flexible( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + '${plan.userName.isNotEmpty ? plan.userName : plan.travellerName} (${plan.employeeCode ?? 'No Data'})', + style: GoogleFonts.poppins( + fontSize: 10, + color: Colors.black87, + ), ), - ), - Text( - '${_formatDate(plan.createdOn)}', - style: GoogleFonts.poppins( - fontSize: 9, - color: Colors.grey, + Text( + '${_formatDate(plan.createdOn)}', + style: GoogleFonts.poppins( + fontSize: 9, + color: Colors.grey, + ), ), - ), - ], - ),), + ], + ), + ), Column( mainAxisAlignment: - MainAxisAlignment.end, + MainAxisAlignment.end, crossAxisAlignment: - CrossAxisAlignment.end, + CrossAxisAlignment.end, children: [ GestureDetector( onTap: () => _showDetails( - plan.planId, - ), + plan.planId, + ), child: Container( padding: - EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), + EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), decoration: BoxDecoration( color: getStatusColor( plan.statusValue, ), borderRadius: - BorderRadius.circular( - 8, - ), + BorderRadius.circular( + 8, + ), ), child: Text( plan.statusValue, style: GoogleFonts.poppins( color: - getStatusTextColor( - plan.statusValue, - ), + getStatusTextColor( + plan.statusValue, + ), fontSize: 9, fontWeight: - FontWeight.w600, + FontWeight.w600, ), ), ), diff --git a/lib/app.dart b/lib/app.dart index e02992c..8c9d363 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; +// import 'package:flutter/rendering.dart'; import 'dart:html' as html; import 'package:frontend/config/apiUrl.dart'; // 1 newly added import 'package:frontend/services/apiService.dart'; @@ -34,8 +34,8 @@ class _MyAppState extends State { @override void initState() { super.initState(); - SemanticsBinding.instance - .ensureSemantics(); // Safe here -only for testing uncomment, Otherwise Email Template wont allow to type + // SemanticsBinding.instance + // .ensureSemantics(); // Safe here -only for testing uncomment, Otherwise Email Template wont allow to type if (kIsWeb) { final uri = Uri.parse(html.window.location.href); print("URI - $uri"); @@ -76,7 +76,7 @@ class _MyAppState extends State { }); html.window.console.log("Auth code detected: $authCode"); - }else { + } else { html.window.console.log("No auth code found or wrong path."); } } @@ -110,32 +110,34 @@ class _MyAppState extends State { setState(() { _isloading = false; }); - if(_isloading){ const CircularProgressIndicator(); } + if (_isloading) { + const CircularProgressIndicator(); + } final userData = prefs.getString('user_data'); print("MS Userdata - $userData"); final orgDataString = prefs.getString('org_data'); print("MS orgdata - $orgDataString"); - if (orgDataString != null && userData != null){ - Fluttertoast.showToast( - msg: "You're in!", - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.CENTER, - backgroundColor: Colors.green, - textColor: Colors.white, - fontSize: 16, - webBgColor: "linear-gradient(to right, #28a745, #28a745)", - ); + if (orgDataString != null && userData != null) { + Fluttertoast.showToast( + msg: "You're in!", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + backgroundColor: Colors.green, + textColor: Colors.white, + fontSize: 16, + webBgColor: "linear-gradient(to right, #28a745, #28a745)", + ); - print("Microsoft User Logged In Refer the Role - $userRole"); - // Navigate based on role - if (userRole == "Travel Agent") { - router.go('/listTravelAgentPlan'); - } else if (userRole == "Org Admin" || userRole == "Travel Admin") { - router.go('/StatusDashboard'); - } else { - router.go('/listPlan'); - } + print("Microsoft User Logged In Refer the Role - $userRole"); + // Navigate based on role + if (userRole == "Travel Agent") { + router.go('/listTravelAgentPlan'); + } else if (userRole == "Org Admin" || userRole == "Travel Admin") { + router.go('/StatusDashboard'); + } else { + router.go('/listPlan'); + } } } else { throw Exception('Token missing in response.'); @@ -172,7 +174,10 @@ class _MyAppState extends State { final prefs = await SharedPreferences.getInstance(); await prefs.setString('auth_token', token); - await prefs.setString('user_data', jsonEncode(userData)); // Store full user data + await prefs.setString( + 'user_data', + jsonEncode(userData), + ); // Store full user data if (userData != null) { final pref = await SharedPreferences.getInstance(); @@ -188,7 +193,6 @@ class _MyAppState extends State { print("MicroSoft Started"); await apiService.getOrganizationData(); print("MicroSoft end"); - } catch (e) { print('Error decoding token MS: $e'); router.go('/'); @@ -197,12 +201,9 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { - if (_isAuthRedirect) { return const MaterialApp( - home: Scaffold( - body: Center(child: CircularProgressIndicator()), - ), + home: Scaffold(body: Center(child: CircularProgressIndicator())), ); } diff --git a/lib/data/models/plan.dart b/lib/data/models/plan.dart index 9ce1b73..34ed126 100644 --- a/lib/data/models/plan.dart +++ b/lib/data/models/plan.dart @@ -20,6 +20,7 @@ class Plan { final String createdOn; final String? approverId; final String? delegaterId; + final String? forexId; Plan({ required this.planId, @@ -41,6 +42,7 @@ class Plan { required this.createdOn, this.approverId, this.delegaterId, + this.forexId, }); factory Plan.fromJson(Map json) { @@ -55,8 +57,9 @@ class Plan { ? '' : json['approver_status']?.toString() ?? "", status: json['status'] == "0" ? "Inactive" : "Active", - costCenter: json['cost_center_value']?.toString() ?? "" , - functionalDepartment: json['functional_department_value']?.toString() ?? "", + costCenter: json['cost_center_value']?.toString() ?? "", + functionalDepartment: + json['functional_department_value']?.toString() ?? "", purposeOfTravel: json['purpose_of_travel_value']?.toString() ?? "", soNumber: json['so_number']?.toString() ?? "", description: json['description']?.toString() ?? "", @@ -73,9 +76,15 @@ class Plan { statusValue: json["status_value"]?.toString() ?? "", createdOn: json["created_on"]?.toString() ?? "", approverId: - json["approver_id"] == null ? '' : json['approver_id']?.toString() ?? "", + json["approver_id"] == null + ? '' + : json['approver_id']?.toString() ?? "", delegaterId: - json["delegater_id"] == null ? '' : json['delegater_id']?.toString() ?? "", + json["delegater_id"] == null + ? '' + : json['delegater_id']?.toString() ?? "", + forexId: + json["forex_id"] == null ? '' : json['forex_id']?.toString() ?? "", ); } } diff --git a/lib/widgets/popup_listPlan_action.dart b/lib/widgets/popup_listPlan_action.dart index 0d8f83e..20d987d 100644 --- a/lib/widgets/popup_listPlan_action.dart +++ b/lib/widgets/popup_listPlan_action.dart @@ -71,7 +71,7 @@ class PlanPopupMenu extends StatelessWidget { IconButton( icon: Icon( Icons.download, - color: Color(0xFF114D8B), + color: Color(0xFF475569), size: 18, ), onPressed: () { @@ -79,6 +79,22 @@ class PlanPopupMenu extends StatelessWidget { apiService.getPdfDownload(plan.planId); }, ), + + if (plan.statusValue == "Approved" && + plan.forexId != null && + plan.forexId != '') + IconButton( + icon: Icon( + Icons.monetization_on_outlined, + color: Color(0xFF475569), + size: 18, + ), + tooltip: 'Download Forex PDF', + onPressed: () { + Navigator.pop(context); + apiService.getPdfDownload(plan.forexId); + }, + ), IconButton( icon: const Icon( Icons.comment,