diff --git a/lib/Screens/allTrips/list_all_plans.dart b/lib/Screens/allTrips/list_all_plans.dart index f7b5e7d..cedf96b 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), @@ -540,23 +540,29 @@ class _ListAllPlansState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Row( - children: [ - Text( - 'All Trips', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ), + Padding( + padding: + isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.only(left: 14.0), + child: Row( + children: [ + Text( + 'All Trips', + style: GoogleFonts.poppins( + fontSize: isDesktop ? 16 : 14, + fontWeight: FontWeight.w600, + color: Colors.black, + ), - // style: TextStyle( - // fontFamily: "Inter", - // fontSize: isDesktop ? 16 : 14, - // fontWeight: FontWeight.w600, - // color: const Color(0xFF212121) ) - ), - ], + // style: TextStyle( + // fontFamily: "Inter", + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + // color: const Color(0xFF212121) ) + ), + ], + ), ), SizedBox(width: 1), @@ -781,61 +787,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 +850,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 + .getForexPdfDownload( + 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 +1268,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 +1278,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 +1291,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 +1325,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 + .getForexPdfDownload( + 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 +1500,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 +1909,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 +1993,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..acfb6f0 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), @@ -387,22 +395,28 @@ class _TravelAgentListPlansState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Row( - children: [ - Text( - 'Trips', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, + Padding( + padding: + isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.only(left: 14.0), + child: Row( + children: [ + Text( + 'Trips', + style: GoogleFonts.poppins( + fontSize: isDesktop ? 16 : 14, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + // style: TextStyle( + // fontFamily: "Inter", + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + // color: Color(0xFF212121)) ), - // style: TextStyle( - // fontFamily: "Inter", - // fontSize: isDesktop ? 16 : 14, - // fontWeight: FontWeight.w600, - // color: Color(0xFF212121)) - ), - ], + ], + ), ), Spacer(), @@ -447,7 +461,7 @@ class _TravelAgentListPlansState extends State { ), // SizedBox(width: 16), - Spacer(), + // Spacer(), // ElevatedButton( // style: ElevatedButton.styleFrom( // foregroundColor: Colors.white, @@ -473,6 +487,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 +709,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 +889,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 + .getForexPdfDownload( + plan.forexId, + ); + }, + ), + IconButton( icon: const Icon( Icons.comment, @@ -1003,6 +1050,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..09e509b 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 @@ -755,22 +755,28 @@ class _ApprovalListState extends State { // ), Row( children: [ - Row( - children: [ - Text( - 'My Approvals', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, + Padding( + padding: + isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.only(left: 14.0), + child: Row( + children: [ + Text( + 'My Approvals', + style: GoogleFonts.poppins( + fontSize: isDesktop ? 16 : 14, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + // style: TextStyle( + // fontFamily: "Inter", + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + // ) ), - // style: TextStyle( - // fontFamily: "Inter", - // fontSize: isDesktop ? 16 : 14, - // fontWeight: FontWeight.w600, - // ) - ), - ], + ], + ), ), if (isDesktop) SizedBox(width: MediaQuery.of(context).size.width * 0.23), @@ -818,14 +824,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 +938,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 + .getForexPdfDownload( + 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 +1500,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 +1523,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 +1557,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 + .getForexPdfDownload( + 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 +1719,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/dashboard/status_dashboard.dart b/lib/Screens/dashboard/status_dashboard.dart index c9544a3..7e26f2d 100644 --- a/lib/Screens/dashboard/status_dashboard.dart +++ b/lib/Screens/dashboard/status_dashboard.dart @@ -52,14 +52,14 @@ class StatusDashboardState extends State { "Partially Approved", "Approved", "Rejected", - "Cancelled" + "Cancelled", ]; - // Extract counts for "Both" section - List getStatusValues(Map serviceData) { - final both = serviceData['Both'] ?? {}; - return statusLabels.map((label) => (both[label] ?? 0) as int).toList(); - } + // Extract counts for "Both" section + List getStatusValues(Map serviceData) { + final both = serviceData['Both'] ?? {}; + return statusLabels.map((label) => (both[label] ?? 0) as int).toList(); + } @override void initState() { @@ -150,8 +150,7 @@ class StatusDashboardState extends State { checkbackbutton(); }); setState(() { - isLoading = true; - + isLoading = true; }); // If token exists, load the dashboard data loadDashboardData(); @@ -320,25 +319,27 @@ class StatusDashboardState extends State { setState(() { // currentData = selectedView == "Today" ? todayBasedCount : weekBasedCount; - typeData = selectedView == "Today" - ? typeBasedTodayCount - : typeBasedWeeklyCount ; - statusData = selectedView == "Today" - ? statusBasedTodayCount - : statusBasedWeeklyCount ; + typeData = + selectedView == "Today" ? typeBasedTodayCount : typeBasedWeeklyCount; + statusData = + selectedView == "Today" + ? statusBasedTodayCount + : statusBasedWeeklyCount; - flightData = selectedView == "Today" - ? getStatusValues(todayBasedCount['flight'] ?? {}) - : getStatusValues(weekBasedCount['flight'] ?? {}); - accommodationData = selectedView == "Today" - ? getStatusValues(todayBasedCount['acomodation'] ?? {}) - : getStatusValues(weekBasedCount['acomodation'] ?? {}); - forexData = selectedView == "Today" - ? getStatusValues(todayBasedCount['forex'] ?? {}) - : getStatusValues(weekBasedCount['forex'] ?? {}); + flightData = + selectedView == "Today" + ? getStatusValues(todayBasedCount['flight'] ?? {}) + : getStatusValues(weekBasedCount['flight'] ?? {}); + accommodationData = + selectedView == "Today" + ? getStatusValues(todayBasedCount['acomodation'] ?? {}) + : getStatusValues(weekBasedCount['acomodation'] ?? {}); + forexData = + selectedView == "Today" + ? getStatusValues(todayBasedCount['forex'] ?? {}) + : getStatusValues(weekBasedCount['forex'] ?? {}); }); - print("statusBasedCount - => $statusBasedCount"); print("Current Data - => $currentData"); // 👇 Local function to create the card widget @@ -403,6 +404,7 @@ class StatusDashboardState extends State { print("dashboard .."); } } + String capitalize(String s) => s[0].toUpperCase() + s.substring(1); Widget toggleChip(String label) { @@ -450,7 +452,7 @@ class StatusDashboardState extends State { child: Column( children: [ Tooltip( - message: label , + message: label, child: Image.asset( label == 'Domestic' ? 'assets/images/IconsImg/Domestic_new.png' @@ -478,10 +480,10 @@ class StatusDashboardState extends State { child: Text( label, style: GoogleFonts.poppins( - fontSize: 10, + fontSize: 12, color: color, // color: const Color(0xFFEAF3FB), - fontWeight: FontWeight.w700, + fontWeight: FontWeight.w500, ), ), ), @@ -542,61 +544,65 @@ class StatusDashboardState extends State { color: const Color(0xFFEAF3FB), borderRadius: BorderRadius.circular(8), ), - child: isDesktop - ? Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - count.toString(), - style: GoogleFonts.poppins( - fontSize: 18, - color: Colors.black87, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 6), - Text( - label, - maxLines: 2, - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.center, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black87, - ), - ), - ], - ) - : Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - label, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black87, + child: + isDesktop + ? Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + count.toString(), + style: GoogleFonts.poppins( + fontSize: 18, + color: Colors.black87, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 6), + Text( + label, + maxLines: 2, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.center, + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black87, + ), + ), + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + label, + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black87, + ), + ), + ), + const SizedBox(width: 10), + Text( + count.toString(), + style: GoogleFonts.poppins( + fontSize: 16, + color: Colors.black87, + fontWeight: FontWeight.bold, + ), + ), + ], ), - ), - ), - const SizedBox(width: 10), - Text( - count.toString(), - style: GoogleFonts.poppins( - fontSize: 16, - color: Colors.black87, - fontWeight: FontWeight.bold, - ), - ), - ], - ), ), ); } - - Widget buildCategoryCard(String title, IconData icon, List statusLabels,List values) { - + Widget buildCategoryCard( + String title, + IconData icon, + List statusLabels, + List values, + ) { final statusIcons = [ Icons.calendar_today, Icons.assignment, @@ -607,9 +613,9 @@ class StatusDashboardState extends State { final statusColors = [ Color(0xFFFBFFCA), - Color(0xFFFFF1CD),// Colors.yellow.shade100, // Color(0xFFCAE77B), - Color(0xFFDAFFE8),// Colors.green.shade100, // Color(0xFF72D480), - Color(0xFFFFD6D3),// Colors.red.shade100, // Color(0xFFF88C8C), + Color(0xFFFFF1CD), // Colors.yellow.shade100, // Color(0xFFCAE77B), + Color(0xFFDAFFE8), // Colors.green.shade100, // Color(0xFF72D480), + Color(0xFFFFD6D3), // Colors.red.shade100, // Color(0xFFF88C8C), Color(0xFFFFA8A8), // Colors.red.shade200, // Color(0xFFE94B4B), ]; @@ -650,17 +656,16 @@ class StatusDashboardState extends State { color: Color(0xFF004A8E), shape: BoxShape.circle, ), - child: Icon( - icon, - color: Colors.white, - size: 20, - ), + child: Icon(icon, color: Colors.white, size: 20), ), const SizedBox(width: 10), - Text(title, style: GoogleFonts.poppins( + Text( + title, + style: GoogleFonts.poppins( color: Colors.black87, - fontWeight: FontWeight.bold - ),), + fontWeight: FontWeight.bold, + ), + ), ], ), const SizedBox(height: 12), @@ -678,7 +683,9 @@ class StatusDashboardState extends State { height: 28, decoration: BoxDecoration( color: statusColors[index], // background color - borderRadius: BorderRadius.circular(4), // square with slight rounding + borderRadius: BorderRadius.circular( + 4, + ), // square with slight rounding ), alignment: Alignment.center, child: Icon( @@ -688,16 +695,20 @@ class StatusDashboardState extends State { ), ), const SizedBox(width: 6), - Text(statusLabels[index], style: GoogleFonts.poppins( - color: Colors.black87, - ),), + Text( + statusLabels[index], + style: GoogleFonts.poppins(color: Colors.black87), + ), ], ), - Text(values[index].toString(), style: GoogleFonts.poppins( - fontSize: 10, - color: Colors.black87, - fontWeight: FontWeight.bold, - ),), + Text( + values[index].toString(), + style: GoogleFonts.poppins( + fontSize: 10, + color: Colors.black87, + fontWeight: FontWeight.bold, + ), + ), ], ), ); @@ -802,251 +813,383 @@ class StatusDashboardState extends State { appBar: CustomAppBar(isDesktop: isDesktop), drawer: CustomDrawer(isDesktop: false), body: Padding( - padding: isDesktop - ? const EdgeInsets.symmetric(vertical: 5) - : EdgeInsets.zero, + padding: + isDesktop + ? const EdgeInsets.symmetric(vertical: 5) + : EdgeInsets.zero, child: Center( child: ConstrainedBox( - constraints: BoxConstraints( - maxWidth: 1200, - ), + constraints: BoxConstraints(maxWidth: 1200), child: SingleChildScrollView( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 15.0), // ✅ Scroll content padding + padding: const EdgeInsets.symmetric( + horizontal: 15.0, + ), // ✅ Scroll content padding child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - isLoading ? Center(child: CircularProgressIndicator()) : - LayoutBuilder( - builder: (context, constraints) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // First Row: Toggle Buttons Row - Row( - mainAxisAlignment: MainAxisAlignment.end, + isLoading + ? Center(child: CircularProgressIndicator()) + : LayoutBuilder( + builder: (context, constraints) { + return Column( + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Container( - height: 36, - decoration: BoxDecoration( - color: const Color(0xFFEAEAEA), - borderRadius: BorderRadius.circular(20), - ), - child: Row( - children: [ - toggleChip("Today"), - toggleChip("This Week"), - ], - ), - ), - ], - ), - const SizedBox(height: 20), - - // Second Row: Domestic & International and Status - isDesktop - ? Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - flex: 2, - child: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.blueGrey, - blurRadius: 5, - offset: Offset(0, 2), - ), - ], + const SizedBox(height: 10), + // First Row: Toggle Buttons Row + Row( + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + Container( + height: 36, + decoration: BoxDecoration( + color: const Color(0xFFEAEAEA), + borderRadius: + BorderRadius.circular(20), + ), + child: Row( + children: [ + toggleChip("Today"), + toggleChip("This Week"), + ], + ), ), - padding: const EdgeInsets.all(15), - child: Row( + ], + ), + const SizedBox(height: 20), + + // Second Row: Domestic & International and Status + isDesktop + ? Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ - ...typeData.map((item) { - return Expanded( - child: Column( - children: [ - buildTopCard( - color: item['value'] == "Domestic" - ? Color(0xFF0DB04B) - : Color(0xFF004A8E), - label: item['value'], - count: item['count'], - bgColor: item['value'] == "Domestic" - ? const Color(0xFFD6FBE4) - : const Color(0xFFD9E8FF), + Expanded( + flex: 2, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.circular( + 12, + ), + boxShadow: [ + BoxShadow( + color: Colors.blueGrey, + blurRadius: 5, + offset: Offset(0, 2), ), ], ), - ); - }).toList(), - ], - ), - ), - ), - const SizedBox(width: 20), - Expanded( - flex: 3, - child: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.blueGrey, - blurRadius: 5, - offset: Offset(0, 2), - ), - ], - ), - padding: const EdgeInsets.all(15), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Status", - style: GoogleFonts.poppins( - fontSize: 19, - color: Colors.black87, - fontWeight: FontWeight.bold, + padding: const EdgeInsets.all( + 15, + ), + child: Row( + children: [ + ...typeData.map((item) { + return Expanded( + child: Column( + children: [ + buildTopCard( + color: + item['value'] == + "Domestic" + ? Color( + 0xFF0DB04B, + ) + : Color( + 0xFF004A8E, + ), + label: + item['value'], + count: + item['count'], + bgColor: + item['value'] == + "Domestic" + ? const Color( + 0xFFD6FBE4, + ) + : const Color( + 0xFFD9E8FF, + ), + ), + ], + ), + ); + }).toList(), + ], + ), ), ), - const SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - ...statusData.map((item) => statusCard(item['value'], item['count'], isDesktop)).toList(), - ], + const SizedBox(width: 20), + Expanded( + flex: 3, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.circular( + 12, + ), + boxShadow: [ + BoxShadow( + color: Colors.blueGrey, + blurRadius: 5, + offset: Offset(0, 2), + ), + ], + ), + padding: const EdgeInsets.all( + 15, + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text( + "Status", + style: + GoogleFonts.poppins( + fontSize: 19, + color: + Colors + .black87, + fontWeight: + FontWeight + .bold, + ), + ), + const SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: + MainAxisAlignment + .spaceAround, + children: [ + ...statusData + .map( + ( + item, + ) => statusCard( + item['value'], + item['count'], + isDesktop, + ), + ) + .toList(), + ], + ), + ], + ), + ), ), ], - ), - ), - ), - ], - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.blueGrey, - blurRadius: 5, - offset: Offset(0, 2), - ), - ], - ), - padding: const EdgeInsets.all(15), - child: Row( - children: [ - ...typeData.map((item) { - return Expanded( - child: Column( - children: [ - buildTopCard( - color: item['value'] == "Domestic" - ? const Color(0xFF0DB04B) - : const Color(0xFF004A8E), - label: item['value'], - count: item['count'], - bgColor: item['value'] == "Domestic" - ? const Color(0xFFD6FBE4) - : const Color(0xFFD9E8FF), + ) + : Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.blueGrey, + blurRadius: 5, + offset: Offset(0, 2), ), ], ), - ); - }).toList(), - ], - ), - ), - const SizedBox(height: 20), - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.blueGrey, - blurRadius: 5, - offset: Offset(0, 2), - ), - ], - ), - padding: const EdgeInsets.all(15), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Status", - style: GoogleFonts.poppins( - fontSize: 19, - color: Colors.black87, - fontWeight: FontWeight.bold, + padding: const EdgeInsets.all( + 15, + ), + child: Row( + children: [ + ...typeData.map((item) { + return Expanded( + child: Column( + children: [ + buildTopCard( + color: + item['value'] == + "Domestic" + ? const Color( + 0xFF0DB04B, + ) + : const Color( + 0xFF004A8E, + ), + label: + item['value'], + count: + item['count'], + bgColor: + item['value'] == + "Domestic" + ? const Color( + 0xFFD6FBE4, + ) + : const Color( + 0xFFD9E8FF, + ), + ), + ], + ), + ); + }).toList(), + ], + ), ), - ), - const SizedBox(height: 23), - Wrap( - spacing: 10, - runSpacing: 10, - children: [ - ...statusData.map((item) => statusCard(item['value'], item['count'], isDesktop)).toList(), - ], - ), - ], - ), - ), - ], - ), + const SizedBox(height: 20), + Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.blueGrey, + blurRadius: 5, + offset: Offset(0, 2), + ), + ], + ), + padding: const EdgeInsets.all( + 15, + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Status", + style: + GoogleFonts.poppins( + fontSize: 19, + color: + Colors.black87, + fontWeight: + FontWeight.bold, + ), + ), + const SizedBox(height: 23), + Wrap( + spacing: 10, + runSpacing: 10, + children: [ + ...statusData + .map( + ( + item, + ) => statusCard( + item['value'], + item['count'], + isDesktop, + ), + ) + .toList(), + ], + ), + ], + ), + ), + ], + ), - const SizedBox(height: 20), + const SizedBox(height: 20), - // Third Row: Flight, Accommodation, Forex - isDesktop - ? Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded(child: buildCategoryCard("Flight", Icons.flight, statusLabels, flightData)), - const SizedBox(width: 10), - Expanded(child: buildCategoryCard("Accomodation", Icons.hotel_outlined, statusLabels, accommodationData)), - const SizedBox(width: 10), - Expanded(child: buildCategoryCard("Forex", Icons.attach_money, statusLabels, forexData)), + // Third Row: Flight, Accommodation, Forex + isDesktop + ? Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Expanded( + child: buildCategoryCard( + "Flight", + Icons.flight, + statusLabels, + flightData, + ), + ), + const SizedBox(width: 10), + Expanded( + child: buildCategoryCard( + "Accomodation", + Icons.hotel_outlined, + statusLabels, + accommodationData, + ), + ), + const SizedBox(width: 10), + Expanded( + child: buildCategoryCard( + "Forex", + Icons.attach_money, + statusLabels, + forexData, + ), + ), + ], + ) + : Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: buildCategoryCard( + "Flight", + Icons.flight, + statusLabels, + flightData, + ), + ), + ], + ), + const SizedBox(height: 20), + Row( + children: [ + Expanded( + child: buildCategoryCard( + "Accomodation", + Icons.hotel_outlined, + statusLabels, + accommodationData, + ), + ), + ], + ), + const SizedBox(height: 20), + Row( + children: [ + Expanded( + child: buildCategoryCard( + "Forex", + Icons.attach_money, + statusLabels, + forexData, + ), + ), + ], + ), + const SizedBox(height: 20), + ], + ), ], - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded(child: buildCategoryCard("Flight", Icons.flight, statusLabels, flightData)), - ], - ), - const SizedBox(height: 20), - Row( - children: [ - Expanded(child: buildCategoryCard("Accomodation", Icons.hotel_outlined, statusLabels, accommodationData)), - ], - ), - const SizedBox(height: 20), - Row( - children: [ - Expanded(child: buildCategoryCard("Forex", Icons.attach_money, statusLabels, forexData)), - ], - ), - const SizedBox(height: 20), - ], - ), - ], - ); - }, - ) , + ); + }, + ), ], ), ), diff --git a/lib/Screens/itnerary/flights.dart b/lib/Screens/itnerary/flights.dart index f30cb2c..3828f58 100644 --- a/lib/Screens/itnerary/flights.dart +++ b/lib/Screens/itnerary/flights.dart @@ -45,6 +45,7 @@ class FlightScreenState extends State { ApiService apiService = ApiService(); final GlobalKey _formKey = GlobalKey(); + String plantripType = ""; bool isCountryLoading = true; late Map countryMap; late Map countryCodeMap; @@ -102,6 +103,10 @@ class FlightScreenState extends State { }); print("TripType - ${widget.tripType}"); + setState(() { + plantripType = widget.tripType!; + }); + // final newTripType = widget.tripTypeNotifier.value; // print("TripType1 - $newTripType"); @@ -459,7 +464,7 @@ class FlightScreenState extends State { Map data = { "trip_type": selectedTripType, "comments": textControllers["_comments1Controller"]?.text ?? "", - "visa_available": selectedvisa_available, + "visa_available": selectedvisa_available ?? "", "created_by": widget.loginUser, "updated_by": widget.loginUser, "trips": trips, @@ -655,7 +660,7 @@ class FlightScreenState extends State { errorMessages["date_$i"] = "Required"; } - if( selectedClasses[i] == null ) { + if (selectedClasses[i] == null) { errorMessages["class_$i"] = "Required"; } if (textControllers["_time${i}Controller"]?.text.trim().isEmpty ?? true) { @@ -926,9 +931,10 @@ class FlightScreenState extends State { alignment: Alignment.centerRight, child: ElevatedButton( style: ElevatedButton.styleFrom( - minimumSize: !isDesktop - ? const Size.fromHeight(48) - : null, // No min height on desktop // height + minimumSize: + !isDesktop + ? const Size.fromHeight(48) + : null, // No min height on desktop // height backgroundColor: Colors.green, foregroundColor: Colors.white, shape: RoundedRectangleBorder( @@ -977,7 +983,7 @@ class FlightScreenState extends State { ), ), ), - + if (selectedTripType == "Multitrip") SizedBox(height: 10), // ...buildResponsiveRow(_buildvisa(isDesktop)), ...buildResponsiveRow(_buildThirdRow(isDesktop)), // Actions row remains a Row @@ -1184,99 +1190,1474 @@ class FlightScreenState extends State { ), ), ), - - // DropdownButtonFormField( - // isExpanded: true, - // // focusNode: _tripTypeFocusNode, // Assign the correct focus node - // focusNode: focusNodes["_tripType1FocusNode"], - // value: selectedTripType, - // style: TextStyle(fontSize: 12), - // isDense: true, - // dropdownColor: Colors.white, - // decoration: InputDecoration( - // border: InputBorder.none, - // contentPadding: - // EdgeInsets.symmetric(horizontal: 10), // Proper padding - // ), - // onChanged: purposeList.isNotEmpty - // ? (newValue) { - // setState(() { - // selectedTripType = newValue; - // // selectedTripType = "Oneway"; - // // Reset `multiTripRowCount` when switching away from Multitrip - // if (selectedTripType != "Multitrip") { - // multiTripRowCount = 1; - // } - // errorMessages.clear(); - // }); - // print( - // "Updating form data: Flight -> trip_type -> $selectedTripType"); - // _initializeFields(); - // - // // _initializeRows(); - // } - // : null, - // - // items: dropdownItems, - // ), ), ), ]; } - // Widget _buildDelete(bool isDesktop, int index) { - // return Container( - // color: Colors.blueAccent, - // child: Row( - // mainAxisAlignment: MainAxisAlignment.start, - // children: [ - // Text( - // "Trip ${index}", - // style: TextStyle( - // fontSize: 14, - // fontWeight: FontWeight.w600, - // color: Color(0xFF575A74), - // ), - // ), - // SizedBox( - // width: isDesktop - // ? MediaQuery.of(context).size.width * 0.38 - // : MediaQuery.of(context).size.width * 0.3, - // child: Stack( - // alignment: Alignment.center, // Centers the icon - // children: [ - // Divider( - // color: Color(0xFF8B8FB2), - // thickness: 0.5, - // height: 20, - // ), - // Container( - // // padding: EdgeInsets.all(4), - // color: Colors.white, // Background to avoid overlapping - // child: Row( - // mainAxisSize: - // MainAxisSize.min, // Prevents row from taking full width - // children: [ - // Icon(Icons.add_circle_sharp, - // color: Colors.blue, size: 28), - // ], - // ), - // ), - // ], - // ), - // ), - // IconButton( - // onPressed: () { - // removeTrip(index); - // }, - // icon: Icon(Icons.delete), - // color: Colors.red, - // iconSize: 20, - // ) - // ], - // ), - // ); - // } + List _buildSecondRow(bool isDesktop, int index) { + return isDesktop + ? [ + _buildFrom(isDesktop, index), + Spacer(), + _buildTo(isDesktop, index), + Spacer(), + _buildClass(isDesktop, index), + Spacer(), + _buildDate(isDesktop, index), + Spacer(), + _buildTime(isDesktop, index), + Spacer(), + if (selectedTripType == "Multitrip") + Container( + // color: Colors.blueGrey, + // padding: const EdgeInsets.only(top: 50, bottom: 50), + child: IconButton( + onPressed: () { + removeTrip(index); + }, + icon: Icon(Icons.close, color: Colors.redAccent, size: 20), + ), + ), + ] + : [ + Card( + elevation: 1, + margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + color: const Color(0xFFF5F5F5), // Light grey + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + children: [ + _buildFrom(isDesktop, index), + SizedBox(height: 8), + _buildTo(isDesktop, index), + SizedBox(height: 8), + _buildClass(isDesktop, index), + SizedBox(height: 8), + _buildDate(isDesktop, index), + SizedBox(height: 8), + _buildTime(isDesktop, index), + + SizedBox(height: 8), + + if (selectedTripType == "Multitrip") + if (multiTripRowCount > 1) + Padding( + padding: const EdgeInsets.only(top: 10), + child: SizedBox( + width: double.infinity, // ensure full width + child: ElevatedButton( + style: ElevatedButton.styleFrom( + minimumSize: const Size.fromHeight( + 48, + ), // set height + backgroundColor: Colors.red, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + onPressed: () { + print("Pressed: $index"); + removeTrip(index); + }, + child: const Text( + "Remove", + style: TextStyle(fontSize: 14), + ), + ), + ), + ), + if (selectedTripType == "Multitrip") SizedBox(height: 8), + ], + ), + ), + ), + ]; + } + + Widget _buildFrom(bool isDesktop, int index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "From*", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + // isFocused: _fromFocus, + // isFocused: focusStates["_from${index}Focused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), + // isFocused: focusStates["_from${fieldIndex}Focused"] ?? false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: + isCountryLoading + ? Center(child: CircularProgressIndicator()) + : Focus( + focusNode: focusNodes["_from${index}FocusNode"], + onFocusChange: (hasFocus) { + setState(() { + focusStates["_from${index}Focused"] = hasFocus; + }); + }, + child: GestureDetector( + // + onTap: () { + // Request focus when user taps + focusNodes["_from${index}FocusNode"]?.requestFocus(); + }, + child: DropdownSearch( + enabled: + !(selectedTripType == "Roundtrip" && index == 2), + selectedItem: + selectedFrom[index] != null + ? countryMap[selectedFrom[index]] + : null, + items: countryMap.values.toList(), + // asyncItems: (String filter) async { + // final allItems = countryMap.values.toSet().toList(); + // print("Original items: ${allItems.length}"); + // final filtered = filterAndSortCountryList(allItems, filter); + // // print("Filtered items: ${filtered.length} -> $filtered"); + // return filtered; + // }, + popupProps: PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 220), + showSearchBox: true, // Enables search functionality + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search...", + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 1, + ), + ), + style: TextStyle(fontSize: 12), + ), + menuProps: MenuProps(backgroundColor: Colors.white), + itemBuilder: (context, item, isSelected) { + final parts = item.split('\n'); + final cityAndCode = parts[0]; + final airport = parts.length > 1 ? parts[1] : ''; + + // Extract city and code from "City (CODE)" + final cityMatch = RegExp( + r'^(.*)\s+\(([^)]+)\)$', + ).firstMatch(cityAndCode); + final city = cityMatch?.group(1) ?? ''; + final code = cityMatch?.group(2) ?? ''; + + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 6.0, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + city, + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ), + Text( + code, + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + const SizedBox(height: 1), + Text( + airport, + style: const TextStyle( + fontSize: 11, + color: Colors.grey, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ); + }, + + // itemBuilder: + // (context, item, isSelected) => Padding( + // padding: const EdgeInsets.symmetric( + // horizontal: 8.0, + // vertical: 6.0, + // ), + // child: Text( + // item, + // style: TextStyle( + // fontSize: 13, + // ), // 👈 Set your desired text size here + // ), + // ), + ), + // items: countryMap.values.toList(), + // filterFn: (item, filter) { + // final lowerFilter = filter.toLowerCase(); + // + // final parts = item.split('\n'); + // final cityAndCode = parts[0]; + // final airport = parts.length > 1 ? parts[1].toLowerCase() : ''; + // + // // Extract city and code from "City (CODE)" + // final cityMatch = RegExp(r'^(.*)\s+\(([^)]+)\)$').firstMatch(cityAndCode); + // final city = cityMatch?.group(1)?.toLowerCase() ?? ''; + // final code = cityMatch?.group(2)?.toLowerCase() ?? ''; + // + // // Priority: Code > City > Airport + // return code.contains(lowerFilter) || + // city.contains(lowerFilter) || + // airport.contains(lowerFilter); + // }, + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["_from${index}Focused"] ?? + false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["_from${index}Focused"] ?? + false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: layoutColor, + width: 1, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), + ), + ), + dropdownBuilder: (context, selectedItem) { + if (selectedItem == null) { + return Align( + alignment: Alignment.centerLeft, + child: const Text( + "Select", + style: TextStyle(fontSize: 12), + ), + ); + } + + final parts = selectedItem.split('\n'); + final cityAndCode = parts[0]; + final airport = parts.length > 1 ? parts[1] : ''; + + return Align( + alignment: Alignment.centerLeft, + child: Text( + cityAndCode ?? "Select", + style: const TextStyle(fontSize: 12), + ), + ); + }, + + // dropdownBuilder: + // (context, selectedItem) => Align( + // alignment: Alignment.centerLeft, + // child: Text( + // selectedItem ?? "Select", + // style: TextStyle(fontSize: 12), + // ), + // ), + onChanged: (String? newValue) { + setState(() { + errorMessages.remove("from_place_$index"); + // selectedFrom[index] = countryMap.entries + // .firstWhere((entry) => entry.value == newValue) + // .key; + + selectedFrom[index] = + countryMap.entries + .firstWhere( + (entry) => entry.value == newValue, + ) + .key; + if (selectedTripType == "Roundtrip") { + print('rounfTo${selectedFrom[index]}'); + // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; + selectedTo[2] = selectedFrom[index]!; + } + }); + }, + ), + ), + ), + ), + + // child: SizedBox( + // height: 40, + // child: TextField( + // // focusNode: _fromFocusNode, + // focusNode: focusNodes["_from${index}FocusNode"], + // controller: textControllers["_from${index}Controller"], + // style: const TextStyle(fontSize: 12), + // decoration: const InputDecoration( + // labelText: "From", + // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + // floatingLabelBehavior: FloatingLabelBehavior.never, + // border: InputBorder.none, + // contentPadding: EdgeInsets.symmetric(vertical: 16), + // ), + // ), + // ), + ), + if (errorMessages["from_place_$index"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["from_place_$index"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ); + } + + Widget _buildTo(bool isDesktop, int index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "To*", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + // isFocused: focusStates["_to${index}Focused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: + isCountryLoading + ? Center(child: CircularProgressIndicator()) + : Focus( + focusNode: focusNodes["_to${index}FocusNode"], + onFocusChange: (hasFocus) { + setState(() { + focusStates["_to${index}Focused"] = hasFocus; + }); + }, + child: GestureDetector( + // + onTap: () { + // Request focus when user taps + focusNodes["_to${index}FocusNode"]?.requestFocus(); + }, + child: DropdownSearch( + enabled: + !(selectedTripType == "Roundtrip" && index == 2), + selectedItem: + selectedTo[index] != null + ? countryMap[selectedTo[index]] + : null, + popupProps: PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 220), + showSearchBox: true, // Enables search functionality + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search...", + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 1, + ), + ), + style: TextStyle(fontSize: 12), + ), + menuProps: MenuProps(backgroundColor: Colors.white), + itemBuilder: (context, item, isSelected) { + final parts = item.split('\n'); + final cityAndCode = parts[0]; + final airport = parts.length > 1 ? parts[1] : ''; + + // Extract city and code from "City (CODE)" + final cityMatch = RegExp( + r'^(.*)\s+\(([^)]+)\)$', + ).firstMatch(cityAndCode); + final city = cityMatch?.group(1) ?? ''; + final code = cityMatch?.group(2) ?? ''; + + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 6.0, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + city, + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ), + Text( + code, + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + const SizedBox(height: 1), + Text( + airport, + style: const TextStyle( + fontSize: 11, + color: Colors.grey, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ); + }, + // itemBuilder: + // (context, item, isSelected) => Padding( + // padding: const EdgeInsets.symmetric( + // horizontal: 8.0, + // vertical: 6.0, + // ), + // child: Text( + // item, + // style: TextStyle( + // fontSize: 13, + // ), // 👈 Set your desired text size here + // ), + // ), + ), + items: countryMap.values.toList(), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["_to${index}Focused"] ?? + false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["_to${index}Focused"] ?? + false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: layoutColor, + width: 1, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), + ), + ), + + // dropdownBuilder: + // (context, selectedItem) => Align( + // alignment: Alignment.centerLeft, + // child: Text( + // selectedItem ?? "Select Country", + // style: TextStyle(fontSize: 12), + // ), + // ), + dropdownBuilder: (context, selectedItem) { + if (selectedItem == null) { + return Align( + alignment: Alignment.centerLeft, + child: const Text( + "Select", + style: TextStyle(fontSize: 12), + ), + ); + } + + final parts = selectedItem.split('\n'); + final cityAndCode = parts[0]; + final airport = parts.length > 1 ? parts[1] : ''; + + return Align( + alignment: Alignment.centerLeft, + child: Text( + cityAndCode ?? "Select", + style: const TextStyle(fontSize: 12), + ), + ); + }, + onChanged: (String? newValue) { + setState(() { + errorMessages.remove("to_place_$index"); + selectedTo[index] = + countryMap.entries + .firstWhere( + (entry) => entry.value == newValue, + ) + .key; + + print(selectedTo[index]); + + if (selectedTripType == "Roundtrip") { + print('rounfTo${selectedTo[index]}'); + // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; + selectedFrom[2] = selectedTo[index]!; + } + }); + }, + ), + ), + ), + ), + ), + if (errorMessages["to_place_$index"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["to_place_$index"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ); + } + + Widget _buildClass(bool isDesktop, int index) { + List purposeList = widget.apiDataForClass?['flight_class'] ?? []; + + List> dropdownItems = + purposeList + .map( + (item) => DropdownMenuItem( + value: item['dropdown_key'], + child: Text(item['dropdown_value']), + ), + ) + .toList(); + + if (dropdownItems.isEmpty) { + dropdownItems.add( + DropdownMenuItem( + value: null, + child: Text( + "No options available", + style: TextStyle(color: Colors.grey), + ), + ), + ); + } + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Class *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + // isFocused: focusStates["_class${index}Focused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), + isDesktop: isDesktop, + child: SizedBox( + height: 40, + width: double.infinity, + child: Focus( + focusNode: focusNodes["_class${index}FocusNode"], + + onFocusChange: (hasFocus) { + setState(() { + focusStates["_class${index}Focused"] = hasFocus; + }); + }, + child: GestureDetector( + // + onTap: () { + // Request focus when user taps + focusNodes["_class${index}FocusNode"]?.requestFocus(); + }, + child: DropdownSearch>( + items: purposeList.cast>(), + key: + selectedClasses[index] == null + ? UniqueKey() + : ValueKey(selectedClasses[index]), + // selectedItem: purposeList.firstWhere( + // (item) => item['dropdown_key'] == selectedClasses[index], + // orElse: () => {}, + // ), + selectedItem: + selectedClasses[index] != null + ? purposeList.firstWhere( + (item) => + item['dropdown_key'] == selectedClasses[index], + orElse: () => {}, + ) + : null, + itemAsString: (item) => item['dropdown_value'] ?? '', + popupProps: PopupProps.menu( + showSearchBox: false, + fit: FlexFit.loose, + menuProps: const MenuProps(backgroundColor: Colors.white), + itemBuilder: (context, item, isSelected) { + final bool isNotAllowed = item['is_allowed'] == 'No'; + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 8, + ), + child: Text( + item['dropdown_value'] ?? '', + style: GoogleFonts.poppins( + fontSize: 12, + color: + isNotAllowed ? Colors.redAccent : Colors.black, + ), + ), + ); + }, + ), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["_class${index}Focused"] ?? false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["_class${index}Focused"] ?? false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: layoutColor, width: 1), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), + ), + ), + dropdownBuilder: (context, selectedItem) { + if (selectedItem == null || selectedItem.isEmpty) { + return Text( + "Select Class", + style: GoogleFonts.poppins( + color: Colors.grey, + fontSize: 13, + ), + ); + } + return Text( + selectedItem['dropdown_value'] ?? '', + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ); + }, + onChanged: + purposeList.isNotEmpty + ? (Map? newValue) async { + // if (newValue != null && + // newValue['is_allowed'] == 'No') { + // print('not allowed'); + // + // exceptionalClass[index] = "1"; + // } else if (newValue != null && + // newValue['is_allowed'] == 'yes') { + // print('not allowed'); + // + // exceptionalClass[index] = "0"; + // } + // + // setState(() { + // selectedClasses[index] = + // newValue?['dropdown_key']; + // print( + // "Selected Class: ${selectedClasses[index]}", + // ); + // }); + + if (newValue != null && + newValue['is_allowed'] == 'No') { + final confirm = await showNotAllowedDialog( + context, + message: + "You are not entitled for this service. If you wish to continue with this service, you may require another approval.", + ); + + if (confirm) { + setState(() { + exceptionalClass[index] = "1"; + selectedClasses[index] = + newValue['dropdown_key']; + }); + print( + "Selected Purpose: ${selectedClasses[index]}", + ); + } else { + setState(() { + exceptionalClass[index] = "0"; + selectedClasses[index] = + null; // ❌ Clear selection if user cancels + }); + print( + "selectedItem resolved to: ${selectedClasses[index]}", + ); + } + + return; + } else if (newValue != null && + newValue['is_allowed'] == 'yes') { + setState(() { + exceptionalClass[index] = "0"; + selectedClasses[index] = + newValue?['dropdown_key']; + print( + "Selected Purpose: ${selectedClasses[index]}", + ); + }); + } + } + : null, + ), + ), + ), + ), + ), + if (errorMessages["class_$index"] != null) + Padding( + padding: const EdgeInsets.only(top: 4), + child: Text( + errorMessages["class_$index"]!, + style: GoogleFonts.poppins(fontSize: 12, color: Colors.red), + ), + ), + ], + ); + } + + Widget _buildDate(bool isDesktop, int index) { + DateTime? _selectedCheckOutDate; + TimeOfDay? _selectedCheckOutTime; + + Future _selectCheckOutDate(BuildContext context) async { + DateTime now = DateTime.now(); + DateTime today = DateTime(now.year, now.month, now.day); + // Determine the minimum date (firstDate) based on previous index if available + DateTime firstDate = today; + + if (index == 1 && + flightLastTripDateNotifier.value != null && + flightLastTripDateNotifier.value!.isNotEmpty) { + try { + final tripDate = DateFormat( + 'dd-MM-yyyy', + ).parseStrict(flightLastTripDateNotifier.value!); + if (tripDate.isAfter(today)) { + firstDate = tripDate; + } + } catch (_) { + // handle parse error if needed + } + } else if (index > 1) { + final previousDateString = + textControllers["_date${index - 1}Controller"]?.text; + if (previousDateString != null && previousDateString.isNotEmpty) { + try { + final previousDate = DateFormat( + 'dd-MM-yyyy', + ).parseStrict(previousDateString); + if (previousDate.isAfter(today)) { + firstDate = previousDate; + } + } catch (_) { + // handle parse error if necessary + } + } + } + + DateTime initialDate = + _selectedCheckOutDate != null && + _selectedCheckOutDate!.isAfter(firstDate) + ? _selectedCheckOutDate! + : firstDate; + + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: initialDate, + firstDate: firstDate, + lastDate: DateTime(2100), + initialEntryMode: DatePickerEntryMode.calendarOnly, + ); + + if (pickedDate != null && pickedDate != _selectedCheckOutDate) { + setState(() { + _selectedCheckOutDate = pickedDate; + // _dateController.text = DateFormat('yyyy-MM-dd').format(pickedDate); + textControllers["_date${index}Controller"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + }); + } + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Date*", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + isFocused: focusStates["_date${index}Focused"] ?? false, + + isDesktop: isDesktop, + width: isDesktop ? MediaQuery.of(context).size.width * 0.11 : null, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () { + focusNodes["_date${index}FocusNode"]?.requestFocus(); + _selectCheckOutDate(context); + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["_date${index}FocusNode"], + // controller: _dateController, + controller: textControllers["_date${index}Controller"], + readOnly: true, + style: const TextStyle(fontSize: 12), + decoration: InputDecoration( + labelText: "Select Date", + labelStyle: const TextStyle( + fontSize: 12, + color: Colors.grey, + ), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + + suffixIcon: const Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["date_$index"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["date_$index"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ); + } + + Widget _buildTime(bool isDesktop, int index) { + TimeOfDay? _selectedCheckOutTime; + Future _selectCheckOutTime( + BuildContext context, + int index, + VoidCallback onPicked, + ) async { + TimeOfDay? pickedTime = await showTimePicker( + context: context, + initialTime: _selectedCheckOutTime ?? TimeOfDay.now(), + ); + + if (pickedTime != null) { + final now = DateTime.now(); + + // Parse the selected date + final dateText = textControllers["_date${index}Controller"]?.text ?? ""; + final selectedDate = DateFormat( + 'dd-MM-yyyy', + ).parse(dateText); // or 'yyyy-MM-dd' depending on your format + + final selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + pickedTime.hour, + pickedTime.minute, + ); + + // ✅ Only validate past time if date is today + final isToday = + selectedDate.year == now.year && + selectedDate.month == now.month && + selectedDate.day == now.day; + + bool isPastTime = selectedDateTime.isBefore(now); + + if (isToday && isPastTime) { + setState(() { + errorMessages["time_$index"] = "You can't select a past time."; + }); + return; + } + + // ✅ Valid time selection + setState(() { + _selectedCheckOutTime = pickedTime; + + final formattedTime = DateFormat('HH:mm').format(selectedDateTime); + textControllers["_time${index}Controller"]?.text = formattedTime; + // errorMessages["time_$index"] = ""; // clear previous error + errorMessages.remove("time_$index"); + onPicked(); // Trigger callback + }); + } + + // if (pickedTime != null && pickedTime != _selectedCheckOutTime) { + // setState(() { + // _selectedCheckOutTime = pickedTime; + // // Formatting time to HH:mm (24-hour format) + // final now = DateTime.now(); + // final formattedTime = DateFormat('HH:mm').format( + // DateTime( + // now.year, + // now.month, + // now.day, + // pickedTime.hour, + // pickedTime.minute, + // ), + // ); + // + // // _timeController.text = formattedTime; + // textControllers["_time${index}Controller"]?.text = formattedTime; + // + // onPicked(); + // }); + // } + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Time*", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + isFocused: focusStates["_time${index}Focused"] ?? false, + isDesktop: isDesktop, + width: isDesktop ? MediaQuery.of(context).size.width * 0.1 : null, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () { + focusNodes["_time${index}FocusNode"]?.requestFocus(); + textControllers["_time${index}Controller"]?.text = ""; + _clearError("time_$index"); + // validateTimeDifference(index); + // _selectCheckOutTime(context); + + _selectCheckOutTime(context, index, () { + validateTimeDifference(index); + setState( + () {}, + ); // ✅ Force rebuild to show the error immediately + }); + }, + + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["_time${index}FocusNode"], + // controller: _timeController, + controller: textControllers["_time${index}Controller"], + readOnly: true, + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Time", + labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + suffixIcon: Icon( + Icons.access_time, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + // Focus( + // focusNode: focusNodes["_time${index}FocusNode"], + // onFocusChange: (hasFocus) { + // setState(() { + // focusStates["_time${index}Focused"] = hasFocus; + // }); + // }, + // child: GestureDetector( + // // + // onTap: () { + // // Request focus when user taps + // focusNodes["_time${index}FocusNode"]?.requestFocus(); + // }, + ), + ), + ), + if (errorMessages["time_$index"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["time_$index"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ); + } + + List _buildThirdRow(bool isDesktop) { + return isDesktop + ? [ + if (plantripType == "2") _buildVisaRequired(isDesktop), + if (plantripType == "2") SizedBox(width: 20), + _buildComments(isDesktop), + if (isDesktop) Spacer(), + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: _handleAction(isDesktop), + ), + ], + ), + ] + : [ + if (plantripType == "2") _buildVisaRequired(isDesktop), + if (plantripType == "2") SizedBox(height: 5), + _buildComments(isDesktop), + SizedBox(height: 5), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: _handleAction(isDesktop), + ), + ]; + } + + Widget _buildVisaRequired(bool isDesktop) { + List visa_available = + widget.apiData?['flight_visa_available'] ?? []; + // Default selected value + + List> dropdownItems = + visa_available + .map( + (item) => DropdownMenuItem( + value: item['dropdown_key'], + child: Text(item['dropdown_value']), + ), + ) + .toList(); + + selectedvisa_available ??= + dropdownItems.isNotEmpty ? dropdownItems.first.value : null; + + if (dropdownItems.isEmpty) { + dropdownItems.add( + DropdownMenuItem( + value: null, + child: Text( + "No options available", + style: TextStyle(color: Colors.grey), + ), + ), + ); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Visa Required", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + // use same wrapper as class + // isFocused: focusStates["_visa1Focused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), + isDesktop: isDesktop, + child: SizedBox( + height: 35, + width: double.infinity, + child: Focus( + focusNode: focusNodes["_visa1FocusNode"], + onFocusChange: (hasFocus) { + setState(() { + focusStates["_visa1Focused"] = hasFocus; + }); + }, + child: GestureDetector( + // + onTap: () { + // Request focus when user taps + focusNodes["_visa1FocusNode"]?.requestFocus(); + }, + child: DropdownSearch>( + items: visa_available.cast>(), + selectedItem: visa_available.firstWhere( + (item) => item['dropdown_key'] == selectedvisa_available, + orElse: () => {}, + ), + itemAsString: (item) => item['dropdown_value'] ?? '', + popupProps: PopupProps.menu( + showSearchBox: false, + fit: FlexFit.loose, + menuProps: const MenuProps(backgroundColor: Colors.white), + itemBuilder: (context, item, isSelected) { + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 8, + ), + child: Text( + item['dropdown_value'] ?? '', + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ), + ); + }, + ), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["_visa1Focused"] ?? false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["_visa1Focused"] ?? false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: layoutColor, width: 1), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), + ), + ), + dropdownBuilder: (context, selectedItem) { + if (selectedItem == null || selectedItem.isEmpty) { + return Text( + "Select Option", + style: GoogleFonts.poppins( + color: Colors.grey, + fontSize: 13, + ), + ); + } + return Text( + selectedItem['dropdown_value'] ?? '', + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ); + }, + onChanged: + visa_available.isNotEmpty + ? (Map? newValue) { + setState(() { + selectedvisa_available = + newValue?['dropdown_key']; + print("Selected Visa: $selectedvisa_available"); + }); + } + : null, + ), + ), + ), + ), + ), + ], + ); + } + + Widget _buildComments(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Comments", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + isFocused: focusStates["_comments1Focused"] ?? false, + isDesktop: isDesktop, + width: isDesktop ? MediaQuery.of(context).size.width * 0.32 : null, + child: TextField( + focusNode: focusNodes["_comments1FocusNode"], + // controller: _commentsController, + controller: textControllers["_comments1Controller"], + // maxLines: 6, + // keyboardType: TextInputType.multiline, + style: TextStyle(fontSize: 12), + decoration: InputDecoration( + labelText: "Comments", + labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + // contentPadding: EdgeInsets.symmetric(vertical: 1), + ), + ), + ), + ], + ); + } + + List _handleAction(bool isDesktop) { + return [ + // Close Button + ElevatedButton( + onPressed: () { + widget.onClose("Flight", false); + // widget.onClose(false); // Close the dialog or screen + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.grey[400], // Light grey color + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + ), + child: Text( + "Close", + style: GoogleFonts.poppins(color: Colors.white, fontSize: 12), + ), + ), + SizedBox(width: 10), // Space between buttons + // Save Changes Button + ElevatedButton( + onPressed: () { + handleSave(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF114D8B), // Primary color for save + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + ), + child: Text( + "Save Changes", + style: GoogleFonts.poppins(color: Colors.white, fontSize: 12), + ), + ), + ]; + } + + List _buildvisa(bool isDesktop) { + List visa_available = + widget.apiData?['flight_visa_available'] ?? []; + // Default selected value + + List> dropdownItems = + visa_available + .map( + (item) => DropdownMenuItem( + value: item['dropdown_key'], + child: Text(item['dropdown_value']), + ), + ) + .toList(); + + selectedvisa_available ??= + dropdownItems.isNotEmpty ? dropdownItems.first.value : null; + + if (dropdownItems.isEmpty) { + dropdownItems.add( + DropdownMenuItem( + value: null, + child: Text( + "No options available", + style: TextStyle(color: Colors.grey), + ), + ), + ); + } + + return [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Visa Required", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + // isFocused: _tripTypeFocused, + isFocused: focusStates["_visa1Focused"] ?? false, + isDesktop: isDesktop, + // width: + // isDesktop + // ? MediaQuery.of(context).size.width * 0.34 + // : MediaQuery.of(context).size.width * 0.66, + child: SizedBox( + height: 40, + child: DropdownButtonFormField( + // focusNode: _tripTypeFocusNode, // Assign the correct focus node + focusNode: focusNodes["_visa1FocusNode"], + value: selectedvisa_available, + style: TextStyle(fontSize: 12), + decoration: InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + ), // Proper padding + ), + onChanged: + visa_available.isNotEmpty + ? (newValue) { + setState(() { + selectedvisa_available = newValue; + // selectedTripType = "Oneway"; + // Reset `multiTripRowCount` when switching away from Multitrip + }); + print( + "Updating form data: Flight -> trip_type -> $selectedvisa_available", + ); + + // _initializeRows(); + } + : null, + + items: dropdownItems, + ), + ), + ), + ], + ), + ]; + } List _buildDelete(bool isDesktop, int index) { return [ @@ -1359,7 +2740,7 @@ class FlightScreenState extends State { ]; } - List _buildSecondRow(bool isDesktop, int index) { + List _buildSecondRow1(bool isDesktop, int index) { bool isFlightClassLoading = widget.apiDataForClass?['flight_class'] == null; List purposeList = widget.apiDataForClass?['flight_class'] ?? []; @@ -1534,1880 +2915,964 @@ class FlightScreenState extends State { return isDesktop ? [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "From*", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // isFocused: _fromFocus, - // isFocused: focusStates["_from${index}Focused"] ?? false, - isFocused: false, - padding: const EdgeInsets.symmetric(horizontal: 0), - // isFocused: focusStates["_from${fieldIndex}Focused"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "From*", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + // isFocused: _fromFocus, + // isFocused: focusStates["_from${index}Focused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), + // isFocused: focusStates["_from${fieldIndex}Focused"] ?? false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: isCountryLoading ? Center(child: CircularProgressIndicator()) : Focus( - focusNode: focusNodes["_from${index}FocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["_from${index}Focused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["_from${index}FocusNode"] - ?.requestFocus(); - }, - child: DropdownSearch( - enabled: - !(selectedTripType == "Roundtrip" && - index == 2), - selectedItem: - selectedFrom[index] != null - ? countryMap[selectedFrom[index]] - : null, - items: countryMap.values.toList(), - // asyncItems: (String filter) async { - // final allItems = countryMap.values.toSet().toList(); - // print("Original items: ${allItems.length}"); - // final filtered = filterAndSortCountryList(allItems, filter); - // // print("Filtered items: ${filtered.length} -> $filtered"); - // return filtered; - // }, - popupProps: PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 220), - showSearchBox: - true, // Enables search functionality - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search...", - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 1, + focusNode: focusNodes["_from${index}FocusNode"], + onFocusChange: (hasFocus) { + setState(() { + focusStates["_from${index}Focused"] = hasFocus; + }); + }, + child: GestureDetector( + // + onTap: () { + // Request focus when user taps + focusNodes["_from${index}FocusNode"] + ?.requestFocus(); + }, + child: DropdownSearch( + enabled: + !(selectedTripType == "Roundtrip" && + index == 2), + selectedItem: + selectedFrom[index] != null + ? countryMap[selectedFrom[index]] + : null, + items: countryMap.values.toList(), + // asyncItems: (String filter) async { + // final allItems = countryMap.values.toSet().toList(); + // print("Original items: ${allItems.length}"); + // final filtered = filterAndSortCountryList(allItems, filter); + // // print("Filtered items: ${filtered.length} -> $filtered"); + // return filtered; + // }, + popupProps: PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 220), + showSearchBox: + true, // Enables search functionality + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search...", + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 1, + ), + ), + style: TextStyle(fontSize: 12), ), - ), - style: TextStyle(fontSize: 12), - ), - menuProps: MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: (context, item, isSelected) { - final parts = item.split('\n'); - final cityAndCode = parts[0]; - final airport = - parts.length > 1 ? parts[1] : ''; - - // Extract city and code from "City (CODE)" - final cityMatch = RegExp( - r'^(.*)\s+\(([^)]+)\)$', - ).firstMatch(cityAndCode); - final city = cityMatch?.group(1) ?? ''; - final code = cityMatch?.group(2) ?? ''; - - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 6.0, + menuProps: MenuProps( + backgroundColor: Colors.white, ), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + itemBuilder: (context, item, isSelected) { + final parts = item.split('\n'); + final cityAndCode = parts[0]; + final airport = + parts.length > 1 ? parts[1] : ''; + + // Extract city and code from "City (CODE)" + final cityMatch = RegExp( + r'^(.*)\s+\(([^)]+)\)$', + ).firstMatch(cityAndCode); + final city = cityMatch?.group(1) ?? ''; + final code = cityMatch?.group(2) ?? ''; + + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 6.0, + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Text( - city, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + city, + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ), + Text( + code, + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ), + ], ), + const SizedBox(height: 1), Text( - code, + airport, style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, + fontSize: 11, + color: Colors.grey, + overflow: TextOverflow.ellipsis, ), ), ], ), - const SizedBox(height: 1), - Text( - airport, - style: const TextStyle( - fontSize: 11, - color: Colors.grey, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ); - }, + ); + }, - // itemBuilder: - // (context, item, isSelected) => Padding( - // padding: const EdgeInsets.symmetric( - // horizontal: 8.0, - // vertical: 6.0, - // ), - // child: Text( - // item, - // style: TextStyle( - // fontSize: 13, - // ), // 👈 Set your desired text size here - // ), - // ), - ), - // items: countryMap.values.toList(), - // filterFn: (item, filter) { - // final lowerFilter = filter.toLowerCase(); - // - // final parts = item.split('\n'); - // final cityAndCode = parts[0]; - // final airport = parts.length > 1 ? parts[1].toLowerCase() : ''; - // - // // Extract city and code from "City (CODE)" - // final cityMatch = RegExp(r'^(.*)\s+\(([^)]+)\)$').firstMatch(cityAndCode); - // final city = cityMatch?.group(1)?.toLowerCase() ?? ''; - // final code = cityMatch?.group(2)?.toLowerCase() ?? ''; - // - // // Priority: Code > City > Airport - // return code.contains(lowerFilter) || - // city.contains(lowerFilter) || - // airport.contains(lowerFilter); - // }, - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["_from${index}Focused"] ?? - false) - ? layoutColor! - : Colors.white, - width: 0.5, + // itemBuilder: + // (context, item, isSelected) => Padding( + // padding: const EdgeInsets.symmetric( + // horizontal: 8.0, + // vertical: 6.0, + // ), + // child: Text( + // item, + // style: TextStyle( + // fontSize: 13, + // ), // 👈 Set your desired text size here + // ), + // ), + ), + // items: countryMap.values.toList(), + // filterFn: (item, filter) { + // final lowerFilter = filter.toLowerCase(); + // + // final parts = item.split('\n'); + // final cityAndCode = parts[0]; + // final airport = parts.length > 1 ? parts[1].toLowerCase() : ''; + // + // // Extract city and code from "City (CODE)" + // final cityMatch = RegExp(r'^(.*)\s+\(([^)]+)\)$').firstMatch(cityAndCode); + // final city = cityMatch?.group(1)?.toLowerCase() ?? ''; + // final code = cityMatch?.group(2)?.toLowerCase() ?? ''; + // + // // Priority: Code > City > Airport + // return code.contains(lowerFilter) || + // city.contains(lowerFilter) || + // airport.contains(lowerFilter); + // }, + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["_from${index}Focused"] ?? + false) + ? layoutColor! + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["_from${index}Focused"] ?? + false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: layoutColor, + width: 1, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), ), ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["_from${index}Focused"] ?? - false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: layoutColor, - width: 1, - ), - ), - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), + dropdownBuilder: (context, selectedItem) { + if (selectedItem == null) { + return Align( + alignment: Alignment.centerLeft, + child: const Text( + "Select", + style: TextStyle(fontSize: 12), + ), + ); + } + + final parts = selectedItem.split('\n'); + final cityAndCode = parts[0]; + final airport = + parts.length > 1 ? parts[1] : ''; + + return Align( + alignment: Alignment.centerLeft, + child: Text( + cityAndCode ?? "Select", + style: const TextStyle(fontSize: 12), + ), + ); + }, + + // dropdownBuilder: + // (context, selectedItem) => Align( + // alignment: Alignment.centerLeft, + // child: Text( + // selectedItem ?? "Select", + // style: TextStyle(fontSize: 12), + // ), + // ), + onChanged: (String? newValue) { + setState(() { + errorMessages.remove("from_place_$index"); + // selectedFrom[index] = countryMap.entries + // .firstWhere((entry) => entry.value == newValue) + // .key; + + selectedFrom[index] = + countryMap.entries + .firstWhere( + (entry) => + entry.value == newValue, + ) + .key; + if (selectedTripType == "Roundtrip") { + print('rounfTo${selectedFrom[index]}'); + // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; + selectedTo[2] = selectedFrom[index]!; + } + }); + }, ), ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null) { - return Align( - alignment: Alignment.centerLeft, - child: const Text( - "Select", - style: TextStyle(fontSize: 12), - ), - ); - } - - final parts = selectedItem.split('\n'); - final cityAndCode = parts[0]; - final airport = parts.length > 1 ? parts[1] : ''; - - return Align( - alignment: Alignment.centerLeft, - child: Text( - cityAndCode ?? "Select", - style: const TextStyle(fontSize: 12), - ), - ); - }, - - // dropdownBuilder: - // (context, selectedItem) => Align( - // alignment: Alignment.centerLeft, - // child: Text( - // selectedItem ?? "Select", - // style: TextStyle(fontSize: 12), - // ), - // ), - onChanged: (String? newValue) { - setState(() { - errorMessages.remove("from_place_$index"); - // selectedFrom[index] = countryMap.entries - // .firstWhere((entry) => entry.value == newValue) - // .key; - - selectedFrom[index] = - countryMap.entries - .firstWhere( - (entry) => entry.value == newValue, - ) - .key; - if (selectedTripType == "Roundtrip") { - print('rounfTo${selectedFrom[index]}'); - // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; - selectedTo[2] = selectedFrom[index]!; - } - }); - }, ), - ), - ), - ), + ), - // child: SizedBox( - // height: 40, - // child: TextField( - // // focusNode: _fromFocusNode, - // focusNode: focusNodes["_from${index}FocusNode"], - // controller: textControllers["_from${index}Controller"], - // style: const TextStyle(fontSize: 12), - // decoration: const InputDecoration( - // labelText: "From", - // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - // floatingLabelBehavior: FloatingLabelBehavior.never, - // border: InputBorder.none, - // contentPadding: EdgeInsets.symmetric(vertical: 16), - // ), - // ), - // ), - ), - if (errorMessages["from_place_$index"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["from_place_$index"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], + // child: SizedBox( + // height: 40, + // child: TextField( + // // focusNode: _fromFocusNode, + // focusNode: focusNodes["_from${index}FocusNode"], + // controller: textControllers["_from${index}Controller"], + // style: const TextStyle(fontSize: 12), + // decoration: const InputDecoration( + // labelText: "From", + // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + // floatingLabelBehavior: FloatingLabelBehavior.never, + // border: InputBorder.none, + // contentPadding: EdgeInsets.symmetric(vertical: 16), + // ), + // ), + // ), ), - if (isDesktop) SizedBox(width: 20) else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "To*", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // isFocused: focusStates["_to${index}Focused"] ?? false, - isFocused: false, - padding: const EdgeInsets.symmetric(horizontal: 0), - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: + if (errorMessages["from_place_$index"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["from_place_$index"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ), + if (isDesktop) SizedBox(width: 20) else SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "To*", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + // isFocused: focusStates["_to${index}Focused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: isCountryLoading ? Center(child: CircularProgressIndicator()) : Focus( - focusNode: focusNodes["_to${index}FocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["_to${index}Focused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["_to${index}FocusNode"]?.requestFocus(); - }, - child: DropdownSearch( - enabled: - !(selectedTripType == "Roundtrip" && - index == 2), - selectedItem: - selectedTo[index] != null - ? countryMap[selectedTo[index]] - : null, - popupProps: PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 220), - showSearchBox: - true, // Enables search functionality - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search...", - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 1, + focusNode: focusNodes["_to${index}FocusNode"], + onFocusChange: (hasFocus) { + setState(() { + focusStates["_to${index}Focused"] = hasFocus; + }); + }, + child: GestureDetector( + // + onTap: () { + // Request focus when user taps + focusNodes["_to${index}FocusNode"] + ?.requestFocus(); + }, + child: DropdownSearch( + enabled: + !(selectedTripType == "Roundtrip" && + index == 2), + selectedItem: + selectedTo[index] != null + ? countryMap[selectedTo[index]] + : null, + popupProps: PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 220), + showSearchBox: + true, // Enables search functionality + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search...", + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 1, + ), + ), + style: TextStyle(fontSize: 12), ), - ), - style: TextStyle(fontSize: 12), - ), - menuProps: MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: (context, item, isSelected) { - final parts = item.split('\n'); - final cityAndCode = parts[0]; - final airport = - parts.length > 1 ? parts[1] : ''; - - // Extract city and code from "City (CODE)" - final cityMatch = RegExp( - r'^(.*)\s+\(([^)]+)\)$', - ).firstMatch(cityAndCode); - final city = cityMatch?.group(1) ?? ''; - final code = cityMatch?.group(2) ?? ''; - - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 6.0, + menuProps: MenuProps( + backgroundColor: Colors.white, ), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + itemBuilder: (context, item, isSelected) { + final parts = item.split('\n'); + final cityAndCode = parts[0]; + final airport = + parts.length > 1 ? parts[1] : ''; + + // Extract city and code from "City (CODE)" + final cityMatch = RegExp( + r'^(.*)\s+\(([^)]+)\)$', + ).firstMatch(cityAndCode); + final city = cityMatch?.group(1) ?? ''; + final code = cityMatch?.group(2) ?? ''; + + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 6.0, + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Text( - city, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + city, + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ), + Text( + code, + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ), + ], ), + const SizedBox(height: 1), Text( - code, + airport, style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, + fontSize: 11, + color: Colors.grey, + overflow: TextOverflow.ellipsis, ), ), ], ), - const SizedBox(height: 1), - Text( - airport, - style: const TextStyle( - fontSize: 11, - color: Colors.grey, - overflow: TextOverflow.ellipsis, - ), + ); + }, + // itemBuilder: + // (context, item, isSelected) => Padding( + // padding: const EdgeInsets.symmetric( + // horizontal: 8.0, + // vertical: 6.0, + // ), + // child: Text( + // item, + // style: TextStyle( + // fontSize: 13, + // ), // 👈 Set your desired text size here + // ), + // ), + ), + items: countryMap.values.toList(), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["_to${index}Focused"] ?? + false) + ? layoutColor! + : Colors.white, + width: 0.5, ), - ], - ), - ); - }, - // itemBuilder: - // (context, item, isSelected) => Padding( - // padding: const EdgeInsets.symmetric( - // horizontal: 8.0, - // vertical: 6.0, - // ), - // child: Text( - // item, - // style: TextStyle( - // fontSize: 13, - // ), // 👈 Set your desired text size here - // ), - // ), - ), - items: countryMap.values.toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["_to${index}Focused"] ?? - false) - ? layoutColor! - : Colors.white, - width: 0.5, + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["_to${index}Focused"] ?? + false) + ? layoutColor + : Colors.white, + // : const Color(0xFFD6D5E6), + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: layoutColor, + width: 1, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), ), ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["_to${index}Focused"] ?? - false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: layoutColor, - width: 1, - ), - ), - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), + + // dropdownBuilder: + // (context, selectedItem) => Align( + // alignment: Alignment.centerLeft, + // child: Text( + // selectedItem ?? "Select Country", + // style: TextStyle(fontSize: 12), + // ), + // ), + dropdownBuilder: (context, selectedItem) { + if (selectedItem == null) { + return Align( + alignment: Alignment.centerLeft, + child: const Text( + "Select", + style: TextStyle(fontSize: 12), + ), + ); + } + + final parts = selectedItem.split('\n'); + final cityAndCode = parts[0]; + final airport = + parts.length > 1 ? parts[1] : ''; + + return Align( + alignment: Alignment.centerLeft, + child: Text( + cityAndCode ?? "Select", + style: const TextStyle(fontSize: 12), + ), + ); + }, + onChanged: (String? newValue) { + setState(() { + errorMessages.remove("to_place_$index"); + selectedTo[index] = + countryMap.entries + .firstWhere( + (entry) => + entry.value == newValue, + ) + .key; + + print(selectedTo[index]); + + if (selectedTripType == "Roundtrip") { + print('rounfTo${selectedTo[index]}'); + // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; + selectedFrom[2] = selectedTo[index]!; + } + }); + }, ), ), - - // dropdownBuilder: - // (context, selectedItem) => Align( - // alignment: Alignment.centerLeft, - // child: Text( - // selectedItem ?? "Select Country", - // style: TextStyle(fontSize: 12), - // ), - // ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null) { - return Align( - alignment: Alignment.centerLeft, - child: const Text( - "Select", - style: TextStyle(fontSize: 12), - ), - ); - } - - final parts = selectedItem.split('\n'); - final cityAndCode = parts[0]; - final airport = parts.length > 1 ? parts[1] : ''; - - return Align( - alignment: Alignment.centerLeft, - child: Text( - cityAndCode ?? "Select", - style: const TextStyle(fontSize: 12), - ), - ); - }, - onChanged: (String? newValue) { - setState(() { - errorMessages.remove("to_place_$index"); - selectedTo[index] = - countryMap.entries - .firstWhere( - (entry) => entry.value == newValue, - ) - .key; - - print(selectedTo[index]); - - if (selectedTripType == "Roundtrip") { - print('rounfTo${selectedTo[index]}'); - // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; - selectedFrom[2] = selectedTo[index]!; - } - }); - }, ), - ), - ), - ), - ), - if (errorMessages["to_place_$index"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["to_place_$index"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], + ), ), - if (isDesktop) Spacer() else SizedBox(height: 8), + if (errorMessages["to_place_$index"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["to_place_$index"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ), + if (isDesktop) Spacer() else SizedBox(height: 8), - // Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Text( - // "Class *", - // style: GoogleFonts.poppins( - // fontSize: 12, - // fontWeight: FontWeight.w600, - // color: Color(0xFF575A74), - // ), - // ), - // SizedBox(height: 5), - // CustomTextFieldItnerarySubWrapper( - // isFocused: focusStates["_class${index}Focused"] ?? false, - // isDesktop: isDesktop, - // // width: isDesktop - // // ? MediaQuery.of(context).size.width * 0.34 - // // : MediaQuery.of(context).size.width * 0.66, - // child: SizedBox( - // height: 40, - // child: - // isFlightClassLoading - // ? const Center(child: CircularProgressIndicator()) - // : DropdownButtonFormField( - // focusNode: focusNodes["_class${index}FocusNode"], - // // focusNode: _tripTypeFocusNode, // Assign the correct focus node - // // controller: _hotelNameController, - // value: selectedClasses[index], - // - // style: TextStyle(fontSize: 12), - // decoration: InputDecoration( - // border: InputBorder.none, - // contentPadding: EdgeInsets.symmetric( - // horizontal: 10, - // ), // Proper padding - // ), - // onChanged: - // purposeList.isNotEmpty - // ? (newValue) { - // setState(() { - // selectedClasses[index] = newValue; - // }); - // - // print(selectedClasses[index]); - // } - // : null, - // items: dropdownItems, - // ), - // ), - // ), - // ], - // ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Class *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // isFocused: focusStates["_class${index}Focused"] ?? false, - isFocused: false, - padding: const EdgeInsets.symmetric(horizontal: 0), - isDesktop: isDesktop, - child: SizedBox( - height: 40, - width: double.infinity, - child: Focus( - focusNode: focusNodes["_class${index}FocusNode"], + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Class *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + // isFocused: focusStates["_class${index}Focused"] ?? false, + isFocused: false, + padding: const EdgeInsets.symmetric(horizontal: 0), + isDesktop: isDesktop, + child: SizedBox( + height: 40, + width: double.infinity, + child: Focus( + focusNode: focusNodes["_class${index}FocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["_class${index}Focused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["_class${index}FocusNode"]?.requestFocus(); - }, - child: DropdownSearch>( - items: purposeList.cast>(), - key: + onFocusChange: (hasFocus) { + setState(() { + focusStates["_class${index}Focused"] = hasFocus; + }); + }, + child: GestureDetector( + // + onTap: () { + // Request focus when user taps + focusNodes["_class${index}FocusNode"]?.requestFocus(); + }, + child: DropdownSearch>( + items: purposeList.cast>(), + key: selectedClasses[index] == null ? UniqueKey() : ValueKey(selectedClasses[index]), - // selectedItem: purposeList.firstWhere( - // (item) => item['dropdown_key'] == selectedClasses[index], - // orElse: () => {}, - // ), - selectedItem: + // selectedItem: purposeList.firstWhere( + // (item) => item['dropdown_key'] == selectedClasses[index], + // orElse: () => {}, + // ), + selectedItem: selectedClasses[index] != null ? purposeList.firstWhere( (item) => - item['dropdown_key'] == - selectedClasses[index], - orElse: () => {}, - ) + item['dropdown_key'] == + selectedClasses[index], + orElse: () => {}, + ) : null, - itemAsString: (item) => item['dropdown_value'] ?? '', - popupProps: PopupProps.menu( - showSearchBox: false, - fit: FlexFit.loose, - menuProps: const MenuProps(backgroundColor: Colors.white), - itemBuilder: (context, item, isSelected) { - final bool isNotAllowed = item['is_allowed'] == 'No'; - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 8, - ), - child: Text( - item['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: + itemAsString: (item) => item['dropdown_value'] ?? '', + popupProps: PopupProps.menu( + showSearchBox: false, + fit: FlexFit.loose, + menuProps: const MenuProps( + backgroundColor: Colors.white, + ), + itemBuilder: (context, item, isSelected) { + final bool isNotAllowed = + item['is_allowed'] == 'No'; + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 8, + ), + child: Text( + item['dropdown_value'] ?? '', + style: GoogleFonts.poppins( + fontSize: 12, + color: isNotAllowed ? Colors.redAccent : Colors.black, - ), - ), - ); - }, - ), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["_class${index}Focused"] ?? false) + ), + ), + ); + }, + ), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["_class${index}Focused"] ?? + false) ? layoutColor! : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["_class${index}Focused"] ?? false) + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["_class${index}Focused"] ?? + false) ? layoutColor : Colors.white, - // : const Color(0xFFD6D5E6), - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: layoutColor, width: 1), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), + // : const Color(0xFFD6D5E6), + width: 0.5, + // const Color(0xFFD6D5E6), ), ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null || selectedItem.isEmpty) { - return Text( - "Select Class", - style: GoogleFonts.poppins( - color: Colors.grey, - fontSize: 13, - ), - ); - } - return Text( - selectedItem['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ); - }, - onChanged: + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: layoutColor, + width: 1, + ), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), + ), + ), + dropdownBuilder: (context, selectedItem) { + if (selectedItem == null || selectedItem.isEmpty) { + return Text( + "Select Class", + style: GoogleFonts.poppins( + color: Colors.grey, + fontSize: 13, + ), + ); + } + return Text( + selectedItem['dropdown_value'] ?? '', + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ); + }, + onChanged: purposeList.isNotEmpty ? (Map? newValue) async { - // if (newValue != null && - // newValue['is_allowed'] == 'No') { - // print('not allowed'); - // - // exceptionalClass[index] = "1"; - // } else if (newValue != null && - // newValue['is_allowed'] == 'yes') { - // print('not allowed'); - // - // exceptionalClass[index] = "0"; - // } - // - // setState(() { - // selectedClasses[index] = - // newValue?['dropdown_key']; - // print( - // "Selected Class: ${selectedClasses[index]}", - // ); - // }); - - if (newValue != null && - newValue['is_allowed'] == 'No') { - final confirm = await showNotAllowedDialog( - context, - message: - "You are not entitled for this service. If you wish to continue with this service, you may require another approval.", - ); - - if (confirm) { - setState(() { - exceptionalClass[index] = "1"; - selectedClasses[index] = - newValue['dropdown_key']; - }); - print( - "Selected Purpose: ${selectedClasses[index]}", - ); - } else { - setState(() { - exceptionalClass[index] = "0"; - selectedClasses[index] = - null; // ❌ Clear selection if user cancels - }); - print( - "selectedItem resolved to: ${selectedClasses[index]}", - ); - } - - return; - } else if (newValue != null && - newValue['is_allowed'] == 'yes') { - setState(() { - exceptionalClass[index] = "0"; - selectedClasses[index] = - newValue?['dropdown_key']; - print( - "Selected Purpose: ${selectedClasses[index]}", - ); - }); - } - } - : null, - ), - ), - ), - ), - ), - if (errorMessages["class_$index"] != null) - Padding( - padding: const EdgeInsets.only(top: 4), - child: Text( - errorMessages["class_$index"]!, - style: GoogleFonts.poppins(fontSize: 12, color: Colors.red), - ), - ), - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Date*", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - isFocused: focusStates["_date${index}Focused"] ?? false, - - isDesktop: isDesktop, - width: isDesktop ? MediaQuery.of(context).size.width * 0.11 : null, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () { - focusNodes["_date${index}FocusNode"]?.requestFocus(); - _selectCheckOutDate(context); - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["_date${index}FocusNode"], - // controller: _dateController, - controller: textControllers["_date${index}Controller"], - readOnly: true, - style: const TextStyle(fontSize: 12), - decoration: InputDecoration( - labelText: "Select Date", - labelStyle: const TextStyle( - fontSize: 12, - color: Colors.grey, - ), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - // border: OutlineInputBorder( - // borderRadius: BorderRadius.circular(8), - // borderSide: BorderSide( - // color: - // (focusStates["_date${index}Focused"] ?? false) - // ? layoutColor! - // : Colors.white, - // width: 0.5, - // ), - // ), - // enabledBorder: OutlineInputBorder( - // borderSide: BorderSide( - // color: - // (focusStates["_date${index}Focused"] ?? false) - // ? layoutColor - // : Colors.white, - // // : const Color(0xFFD6D5E6), - // width: 0.5, - // // const Color(0xFFD6D5E6), - // ), - // ), - // focusedBorder: OutlineInputBorder( - // borderSide: BorderSide(color: layoutColor, width: 1), - // ), - // contentPadding: const EdgeInsets.symmetric( - // horizontal: 10, - // vertical: 5, - // ), - suffixIcon: const Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["date_$index"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["date_$index"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Time*", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - isFocused: focusStates["_time${index}Focused"] ?? false, - isDesktop: isDesktop, - width: isDesktop ? MediaQuery.of(context).size.width * 0.1 : null, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () { - focusNodes["_time${index}FocusNode"]?.requestFocus(); - textControllers["_time${index}Controller"]?.text = ""; - _clearError("time_$index"); - // validateTimeDifference(index); - // _selectCheckOutTime(context); - - _selectCheckOutTime(context, index, () { - validateTimeDifference(index); - setState( - () {}, - ); // ✅ Force rebuild to show the error immediately - }); - }, - - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["_time${index}FocusNode"], - // controller: _timeController, - controller: textControllers["_time${index}Controller"], - readOnly: true, - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Time", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - suffixIcon: Icon( - Icons.access_time, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - // Focus( - // focusNode: focusNodes["_time${index}FocusNode"], - // onFocusChange: (hasFocus) { - // setState(() { - // focusStates["_time${index}Focused"] = hasFocus; - // }); - // }, - // child: GestureDetector( - // // - // onTap: () { - // // Request focus when user taps - // focusNodes["_time${index}FocusNode"]?.requestFocus(); - // }, - ), - ), - ), - if (errorMessages["time_$index"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["time_$index"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (selectedTripType == "Multitrip") - Container( - // color: Colors.blueGrey, - // padding: const EdgeInsets.only(top: 50, bottom: 50), - child: IconButton( - onPressed: () { - removeTrip(index); - }, - icon: Icon(Icons.close, color: Colors.redAccent, size: 20), - ), - ), - ] - : [ - // For mobile, wrap inside a card with padding and grey background - Card( - elevation: 1, - margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), - color: const Color(0xFFF5F5F5), // Light grey - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), - child: Padding( - padding: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "From*", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // isFocused: _fromFocus, - // isFocused: focusStates["_from${index}Focused"] ?? false, - isFocused: false, - padding: const EdgeInsets.symmetric(horizontal: 0), - // isFocused: focusStates["_from${fieldIndex}Focused"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: - isCountryLoading - ? Center(child: CircularProgressIndicator()) - : Focus( - focusNode: focusNodes["_from${index}FocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["_from${index}Focused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["_from${index}FocusNode"] - ?.requestFocus(); - }, - child: DropdownSearch( - enabled: - !(selectedTripType == "Roundtrip" && - index == 2), - selectedItem: - selectedFrom[index] != null - ? countryMap[selectedFrom[index]] - : null, - items: countryMap.values.toList(), - // asyncItems: (String filter) async { - // final allItems = countryMap.values.toSet().toList(); - // print("Original items: ${allItems.length}"); - // final filtered = filterAndSortCountryList(allItems, filter); - // // print("Filtered items: ${filtered.length} -> $filtered"); - // return filtered; - // }, - popupProps: PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 220), - showSearchBox: - true, // Enables search functionality - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search...", - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 1, - ), - ), - style: TextStyle(fontSize: 12), - ), - menuProps: MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: (context, item, isSelected) { - final parts = item.split('\n'); - final cityAndCode = parts[0]; - final airport = - parts.length > 1 ? parts[1] : ''; - - // Extract city and code from "City (CODE)" - final cityMatch = RegExp( - r'^(.*)\s+\(([^)]+)\)$', - ).firstMatch(cityAndCode); - final city = cityMatch?.group(1) ?? ''; - final code = cityMatch?.group(2) ?? ''; - - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 6.0, - ), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - city, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - Text( - code, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 1), - Text( - airport, - style: const TextStyle( - fontSize: 11, - color: Colors.grey, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ); - }, - - // itemBuilder: - // (context, item, isSelected) => Padding( - // padding: const EdgeInsets.symmetric( - // horizontal: 8.0, - // vertical: 6.0, - // ), - // child: Text( - // item, - // style: TextStyle( - // fontSize: 13, - // ), // 👈 Set your desired text size here - // ), - // ), - ), - // items: countryMap.values.toList(), - // filterFn: (item, filter) { - // final lowerFilter = filter.toLowerCase(); + // if (newValue != null && + // newValue['is_allowed'] == 'No') { + // print('not allowed'); // - // final parts = item.split('\n'); - // final cityAndCode = parts[0]; - // final airport = parts.length > 1 ? parts[1].toLowerCase() : ''; + // exceptionalClass[index] = "1"; + // } else if (newValue != null && + // newValue['is_allowed'] == 'yes') { + // print('not allowed'); // - // // Extract city and code from "City (CODE)" - // final cityMatch = RegExp(r'^(.*)\s+\(([^)]+)\)$').firstMatch(cityAndCode); - // final city = cityMatch?.group(1)?.toLowerCase() ?? ''; - // final code = cityMatch?.group(2)?.toLowerCase() ?? ''; + // exceptionalClass[index] = "0"; + // } // - // // Priority: Code > City > Airport - // return code.contains(lowerFilter) || - // city.contains(lowerFilter) || - // airport.contains(lowerFilter); - // }, - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["_from${index}Focused"] ?? - false) - ? layoutColor! - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["_from${index}Focused"] ?? - false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: layoutColor, - width: 1, - ), - ), - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), - ), - ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null) { - return Align( - alignment: Alignment.centerLeft, - child: const Text( - "Select", - style: TextStyle(fontSize: 12), - ), - ); - } + // setState(() { + // selectedClasses[index] = + // newValue?['dropdown_key']; + // print( + // "Selected Class: ${selectedClasses[index]}", + // ); + // }); - final parts = selectedItem.split('\n'); - final cityAndCode = parts[0]; - final airport = parts.length > 1 ? parts[1] : ''; - - return Align( - alignment: Alignment.centerLeft, - child: Text( - cityAndCode ?? "Select", - style: const TextStyle(fontSize: 12), - ), + if (newValue != null && + newValue['is_allowed'] == 'No') { + final confirm = await showNotAllowedDialog( + context, + message: + "You are not entitled for this service. If you wish to continue with this service, you may require another approval.", ); - }, - // dropdownBuilder: - // (context, selectedItem) => Align( - // alignment: Alignment.centerLeft, - // child: Text( - // selectedItem ?? "Select", - // style: TextStyle(fontSize: 12), - // ), - // ), - onChanged: (String? newValue) { - setState(() { - errorMessages.remove("from_place_$index"); - // selectedFrom[index] = countryMap.entries - // .firstWhere((entry) => entry.value == newValue) - // .key; - - selectedFrom[index] = - countryMap.entries - .firstWhere( - (entry) => entry.value == newValue, - ) - .key; - if (selectedTripType == "Roundtrip") { - print('rounfTo${selectedFrom[index]}'); - // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; - selectedTo[2] = selectedFrom[index]!; - } - }); - }, - ), - ), - ), - ), - - // child: SizedBox( - // height: 40, - // child: TextField( - // // focusNode: _fromFocusNode, - // focusNode: focusNodes["_from${index}FocusNode"], - // controller: textControllers["_from${index}Controller"], - // style: const TextStyle(fontSize: 12), - // decoration: const InputDecoration( - // labelText: "From", - // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - // floatingLabelBehavior: FloatingLabelBehavior.never, - // border: InputBorder.none, - // contentPadding: EdgeInsets.symmetric(vertical: 16), - // ), - // ), - // ), - ), - if (errorMessages["from_place_$index"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["from_place_$index"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) SizedBox(width: 20) else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "To*", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // isFocused: focusStates["_to${index}Focused"] ?? false, - isFocused: false, - padding: const EdgeInsets.symmetric(horizontal: 0), - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: - isCountryLoading - ? Center(child: CircularProgressIndicator()) - : Focus( - focusNode: focusNodes["_to${index}FocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["_to${index}Focused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["_to${index}FocusNode"]?.requestFocus(); - }, - child: DropdownSearch( - enabled: - !(selectedTripType == "Roundtrip" && - index == 2), - selectedItem: - selectedTo[index] != null - ? countryMap[selectedTo[index]] - : null, - popupProps: PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 220), - showSearchBox: - true, // Enables search functionality - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search...", - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 1, - ), - ), - style: TextStyle(fontSize: 12), - ), - menuProps: MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: (context, item, isSelected) { - final parts = item.split('\n'); - final cityAndCode = parts[0]; - final airport = - parts.length > 1 ? parts[1] : ''; - - // Extract city and code from "City (CODE)" - final cityMatch = RegExp( - r'^(.*)\s+\(([^)]+)\)$', - ).firstMatch(cityAndCode); - final city = cityMatch?.group(1) ?? ''; - final code = cityMatch?.group(2) ?? ''; - - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 6.0, - ), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - city, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - Text( - code, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 1), - Text( - airport, - style: const TextStyle( - fontSize: 11, - color: Colors.grey, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), + if (confirm) { + setState(() { + exceptionalClass[index] = "1"; + selectedClasses[index] = + newValue['dropdown_key']; + }); + print( + "Selected Purpose: ${selectedClasses[index]}", ); - }, - // itemBuilder: - // (context, item, isSelected) => Padding( - // padding: const EdgeInsets.symmetric( - // horizontal: 8.0, - // vertical: 6.0, - // ), - // child: Text( - // item, - // style: TextStyle( - // fontSize: 13, - // ), // 👈 Set your desired text size here - // ), - // ), - ), - items: countryMap.values.toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["_to${index}Focused"] ?? - false) - ? layoutColor! - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["_to${index}Focused"] ?? - false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: layoutColor, - width: 1, - ), - ), - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), - ), - ), - - // dropdownBuilder: - // (context, selectedItem) => Align( - // alignment: Alignment.centerLeft, - // child: Text( - // selectedItem ?? "Select Country", - // style: TextStyle(fontSize: 12), - // ), - // ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null) { - return Align( - alignment: Alignment.centerLeft, - child: const Text( - "Select", - style: TextStyle(fontSize: 12), - ), - ); - } - - final parts = selectedItem.split('\n'); - final cityAndCode = parts[0]; - final airport = parts.length > 1 ? parts[1] : ''; - - return Align( - alignment: Alignment.centerLeft, - child: Text( - cityAndCode ?? "Select", - style: const TextStyle(fontSize: 12), - ), - ); - }, - onChanged: (String? newValue) { - setState(() { - errorMessages.remove("to_place_$index"); - selectedTo[index] = - countryMap.entries - .firstWhere( - (entry) => entry.value == newValue, - ) - .key; - - print(selectedTo[index]); - - if (selectedTripType == "Roundtrip") { - print('rounfTo${selectedTo[index]}'); - // textControllers["_to${index+1}Controller"]?.text = selectedFrom[index]!; - selectedFrom[2] = selectedTo[index]!; - } - }); - }, - ), - ), - ), - ), - ), - if (errorMessages["to_place_$index"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["to_place_$index"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Class *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // isFocused: focusStates["_class${index}Focused"] ?? false, - isFocused: false, - padding: const EdgeInsets.symmetric(horizontal: 0), - isDesktop: isDesktop, - child: SizedBox( - height: 40, - width: double.infinity, - child: Focus( - focusNode: focusNodes["_class${index}FocusNode"], - - onFocusChange: (hasFocus) { - setState(() { - focusStates["_class${index}Focused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["_class${index}FocusNode"]?.requestFocus(); - }, - child: DropdownSearch>( - items: purposeList.cast>(), - key: - selectedClasses[index] == null - ? UniqueKey() - : ValueKey(selectedClasses[index]), - // selectedItem: purposeList.firstWhere( - // (item) => item['dropdown_key'] == selectedClasses[index], - // orElse: () => {}, - // ), - selectedItem: - selectedClasses[index] != null - ? purposeList.firstWhere( - (item) => - item['dropdown_key'] == - selectedClasses[index], - orElse: () => {}, - ) - : null, - itemAsString: (item) => item['dropdown_value'] ?? '', - popupProps: PopupProps.menu( - showSearchBox: false, - fit: FlexFit.loose, - menuProps: const MenuProps(backgroundColor: Colors.white), - itemBuilder: (context, item, isSelected) { - final bool isNotAllowed = item['is_allowed'] == 'No'; - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 8, - ), - child: Text( - item['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: - isNotAllowed - ? Colors.redAccent - : Colors.black, - ), - ), - ); - }, - ), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["_class${index}Focused"] ?? false) - ? layoutColor! - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["_class${index}Focused"] ?? false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: layoutColor, width: 1), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), - ), - ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null || selectedItem.isEmpty) { - return Text( - "Select Class", - style: GoogleFonts.poppins( - color: Colors.grey, - fontSize: 13, - ), - ); - } - return Text( - selectedItem['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ); - }, - onChanged: - purposeList.isNotEmpty - ? (Map? newValue) async { - // if (newValue != null && - // newValue['is_allowed'] == 'No') { - // print('not allowed'); - // - // exceptionalClass[index] = "1"; - // } else if (newValue != null && - // newValue['is_allowed'] == 'yes') { - // print('not allowed'); - // - // exceptionalClass[index] = "0"; - // } - // - // setState(() { - // selectedClasses[index] = - // newValue?['dropdown_key']; - // print( - // "Selected Class: ${selectedClasses[index]}", - // ); - // }); - - if (newValue != null && - newValue['is_allowed'] == 'No') { - final confirm = await showNotAllowedDialog( - context, - message: - "You are not entitled for this service. If you wish to continue with this service, you may require another approval.", - ); - - if (confirm) { - setState(() { - exceptionalClass[index] = "1"; - selectedClasses[index] = - newValue['dropdown_key']; - }); - print( - "Selected Purpose: ${selectedClasses[index]}", - ); - } else { - setState(() { - exceptionalClass[index] = "0"; - selectedClasses[index] = - null; // ❌ Clear selection if user cancels - }); - print( - "selectedItem resolved to: ${selectedClasses[index]}", - ); - } - - return; - } else if (newValue != null && - newValue['is_allowed'] == 'yes') { + } else { setState(() { exceptionalClass[index] = "0"; selectedClasses[index] = - newValue?['dropdown_key']; - print( - "Selected Purpose: ${selectedClasses[index]}", - ); + null; // ❌ Clear selection if user cancels }); + print( + "selectedItem resolved to: ${selectedClasses[index]}", + ); } - } - : null, - ), - ), - ), - ), - ), - if (errorMessages["class_$index"] != null) - Padding( - padding: const EdgeInsets.only(top: 4), - child: Text( - errorMessages["class_$index"]!, - style: GoogleFonts.poppins(fontSize: 12, color: Colors.red), - ), - ), - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Date*", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - isFocused: focusStates["_date${index}Focused"] ?? false, - isDesktop: isDesktop, - width: isDesktop ? MediaQuery.of(context).size.width * 0.11 : null, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () { - focusNodes["_date${index}FocusNode"]?.requestFocus(); - _selectCheckOutDate(context); - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["_date${index}FocusNode"], - // controller: _dateController, - controller: textControllers["_date${index}Controller"], - readOnly: true, - style: const TextStyle(fontSize: 12), - decoration: InputDecoration( - labelText: "Select Date", - labelStyle: const TextStyle( - fontSize: 12, - color: Colors.grey, - ), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - // border: OutlineInputBorder( - // borderRadius: BorderRadius.circular(8), - // borderSide: BorderSide( - // color: - // (focusStates["_date${index}Focused"] ?? false) - // ? layoutColor! - // : Colors.white, - // width: 0.5, - // ), - // ), - // enabledBorder: OutlineInputBorder( - // borderSide: BorderSide( - // color: - // (focusStates["_date${index}Focused"] ?? false) - // ? layoutColor - // : Colors.white, - // // : const Color(0xFFD6D5E6), - // width: 0.5, - // // const Color(0xFFD6D5E6), - // ), - // ), - // focusedBorder: OutlineInputBorder( - // borderSide: BorderSide(color: layoutColor, width: 1), - // ), - // contentPadding: const EdgeInsets.symmetric( - // horizontal: 10, - // vertical: 5, - // ), - suffixIcon: const Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["date_$index"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["date_$index"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Time*", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - isFocused: focusStates["_time${index}Focused"] ?? false, - isDesktop: isDesktop, - width: isDesktop ? MediaQuery.of(context).size.width * 0.1 : null, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () { - focusNodes["_time${index}FocusNode"]?.requestFocus(); - textControllers["_time${index}Controller"]?.text = ""; - _clearError("time_$index"); - // validateTimeDifference(index); - // _selectCheckOutTime(context); - - _selectCheckOutTime(context, index, () { - validateTimeDifference(index); - setState( - () {}, - ); // ✅ Force rebuild to show the error immediately + return; + } else if (newValue != null && + newValue['is_allowed'] == 'yes') { + setState(() { + exceptionalClass[index] = "0"; + selectedClasses[index] = + newValue?['dropdown_key']; + print( + "Selected Purpose: ${selectedClasses[index]}", + ); }); - }, + } + } + : null, + ), + ), + ), + ), + ), + if (errorMessages["class_$index"] != null) + Padding( + padding: const EdgeInsets.only(top: 4), + child: Text( + errorMessages["class_$index"]!, + style: GoogleFonts.poppins(fontSize: 12, color: Colors.red), + ), + ), + ], + ), + if (isDesktop) Spacer() else SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Date*", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + isFocused: focusStates["_date${index}Focused"] ?? false, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["_time${index}FocusNode"], - // controller: _timeController, - controller: textControllers["_time${index}Controller"], - readOnly: true, - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Time", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - suffixIcon: Icon( - Icons.access_time, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - // Focus( - // focusNode: focusNodes["_time${index}FocusNode"], - // onFocusChange: (hasFocus) { - // setState(() { - // focusStates["_time${index}Focused"] = hasFocus; - // }); - // }, - // child: GestureDetector( - // // - // onTap: () { - // // Request focus when user taps - // focusNodes["_time${index}FocusNode"]?.requestFocus(); - // }, - ), - ), - ), - if (errorMessages["time_$index"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["time_$index"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], + isDesktop: isDesktop, + width: + isDesktop ? MediaQuery.of(context).size.width * 0.11 : null, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () { + focusNodes["_date${index}FocusNode"]?.requestFocus(); + _selectCheckOutDate(context); + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["_date${index}FocusNode"], + // controller: _dateController, + controller: textControllers["_date${index}Controller"], + readOnly: true, + style: const TextStyle(fontSize: 12), + decoration: InputDecoration( + labelText: "Select Date", + labelStyle: const TextStyle( + fontSize: 12, + color: Colors.grey, + ), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + // border: OutlineInputBorder( + // borderRadius: BorderRadius.circular(8), + // borderSide: BorderSide( + // color: + // (focusStates["_date${index}Focused"] ?? false) + // ? layoutColor! + // : Colors.white, + // width: 0.5, + // ), + // ), + // enabledBorder: OutlineInputBorder( + // borderSide: BorderSide( + // color: + // (focusStates["_date${index}Focused"] ?? false) + // ? layoutColor + // : Colors.white, + // // : const Color(0xFFD6D5E6), + // width: 0.5, + // // const Color(0xFFD6D5E6), + // ), + // ), + // focusedBorder: OutlineInputBorder( + // borderSide: BorderSide(color: layoutColor, width: 1), + // ), + // contentPadding: const EdgeInsets.symmetric( + // horizontal: 10, + // vertical: 5, + // ), + suffixIcon: const Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), ), - if (selectedTripType == "Multitrip") - if(multiTripRowCount > 1) - Padding( + ), + ), + ), + ), + ), + if (errorMessages["date_$index"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["date_$index"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ), + if (isDesktop) Spacer() else SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Time*", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldItnerarySubWrapper( + isFocused: focusStates["_time${index}Focused"] ?? false, + isDesktop: isDesktop, + width: + isDesktop ? MediaQuery.of(context).size.width * 0.1 : null, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () { + focusNodes["_time${index}FocusNode"]?.requestFocus(); + textControllers["_time${index}Controller"]?.text = ""; + _clearError("time_$index"); + // validateTimeDifference(index); + // _selectCheckOutTime(context); + + _selectCheckOutTime(context, index, () { + validateTimeDifference(index); + setState( + () {}, + ); // ✅ Force rebuild to show the error immediately + }); + }, + + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["_time${index}FocusNode"], + // controller: _timeController, + controller: textControllers["_time${index}Controller"], + readOnly: true, + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Time", + labelStyle: TextStyle( + fontSize: 12, + color: Colors.grey, + ), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + suffixIcon: Icon( + Icons.access_time, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + // Focus( + // focusNode: focusNodes["_time${index}FocusNode"], + // onFocusChange: (hasFocus) { + // setState(() { + // focusStates["_time${index}Focused"] = hasFocus; + // }); + // }, + // child: GestureDetector( + // // + // onTap: () { + // // Request focus when user taps + // focusNodes["_time${index}FocusNode"]?.requestFocus(); + // }, + ), + ), + ), + if (errorMessages["time_$index"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["time_$index"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ), + if (selectedTripType == "Multitrip") + Container( + // color: Colors.blueGrey, + // padding: const EdgeInsets.only(top: 50, bottom: 50), + child: IconButton( + onPressed: () { + removeTrip(index); + }, + icon: Icon(Icons.close, color: Colors.redAccent, size: 20), + ), + ), + ] + : [ + // For mobile, wrap inside a card with padding and grey background + Card( + elevation: 1, + margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + color: const Color(0xFFF5F5F5), // Light grey + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (isDesktop) SizedBox(width: 20) else SizedBox(height: 8), + + if (isDesktop) Spacer() else SizedBox(height: 8), + + if (isDesktop) Spacer() else SizedBox(height: 8), + + if (isDesktop) Spacer() else SizedBox(height: 8), + + if (selectedTripType == "Multitrip") + if (multiTripRowCount > 1) + Padding( padding: const EdgeInsets.only(top: 10), child: SizedBox( width: double.infinity, // ensure full width child: ElevatedButton( style: ElevatedButton.styleFrom( - minimumSize: const Size.fromHeight(48), // set height + minimumSize: const Size.fromHeight( + 48, + ), // set height backgroundColor: Colors.red, foregroundColor: Colors.white, shape: RoundedRectangleBorder( @@ -3425,601 +3890,10 @@ class FlightScreenState extends State { ), ), ), - // Container( - // // color: Colors.blueGrey, - // // padding: const EdgeInsets.only(top: 50, bottom: 50), - // child: IconButton( - // onPressed: () { - // removeTrip(index); - // }, - // icon: Icon(Icons.close, color: Colors.redAccent, size: 20), - // ), - // ), - ], - ), - ), - ), - ]; - } - - List _buildThirdRow(bool isDesktop) { - List visa_available = - widget.apiData?['flight_visa_available'] ?? []; - // Default selected value - - List> dropdownItems = - visa_available - .map( - (item) => DropdownMenuItem( - value: item['dropdown_key'], - child: Text(item['dropdown_value']), - ), - ) - .toList(); - - selectedvisa_available ??= - dropdownItems.isNotEmpty ? dropdownItems.first.value : null; - - if (dropdownItems.isEmpty) { - dropdownItems.add( - DropdownMenuItem( - value: null, - child: Text( - "No options available", - style: TextStyle(color: Colors.grey), - ), - ), - ); - } - // Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Text( - // "Visa Required", - // style: GoogleFonts.poppins( - // fontSize: 12, - // fontWeight: FontWeight.w600, - // color: Color(0xFF575A74), - // ), - // ), - // SizedBox(height: 5), - // CustomTextFieldItnerarySubWrapper( - // // isFocused: _tripTypeFocused, - // isFocused: focusStates["_visa1Focused"] ?? false, - // isDesktop: isDesktop, - // // width: isDesktop - // // ? MediaQuery.of(context).size.width * 0.34 - // // : MediaQuery.of(context).size.width * 0.66, - // child: SizedBox( - // height: 40, - // child: DropdownButtonFormField( - // // focusNode: _tripTypeFocusNode, // Assign the correct focus node - // focusNode: focusNodes["_visa1FocusNode"], - // value: selectedvisa_available, - // style: TextStyle(fontSize: 12), - // decoration: InputDecoration( - // border: InputBorder.none, - // contentPadding: EdgeInsets.symmetric( - // horizontal: 10, - // ), // Proper padding - // ), - // onChanged: - // visa_available.isNotEmpty - // ? (newValue) { - // setState(() { - // selectedvisa_available = newValue; - // // selectedTripType = "Oneway"; - // // Reset `multiTripRowCount` when switching away from Multitrip - // }); - // print( - // "Updating form data: Flight -> trip_type -> $selectedvisa_available", - // ); - // - // // _initializeRows(); - // } - // : null, - // - // items: dropdownItems, - // ), - // ), - // ), - // ], - // ), - //********// - return isDesktop - ? [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Visa Required", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // use same wrapper as class - // isFocused: focusStates["_visa1Focused"] ?? false, - isFocused: false, - padding: const EdgeInsets.symmetric(horizontal: 0), - isDesktop: isDesktop, - child: SizedBox( - height: 35, - width: double.infinity, - child: Focus( - focusNode: focusNodes["_visa1FocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["_visa1Focused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["_visa1FocusNode"]?.requestFocus(); - }, - child: DropdownSearch>( - items: visa_available.cast>(), - selectedItem: visa_available.firstWhere( - (item) => item['dropdown_key'] == selectedvisa_available, - orElse: () => {}, - ), - itemAsString: (item) => item['dropdown_value'] ?? '', - popupProps: PopupProps.menu( - showSearchBox: false, - fit: FlexFit.loose, - menuProps: const MenuProps(backgroundColor: Colors.white), - itemBuilder: (context, item, isSelected) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 8, - ), - child: Text( - item['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ), - ); - }, - ), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["_visa1Focused"] ?? false) - ? layoutColor! - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["_visa1Focused"] ?? false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: layoutColor, width: 1), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), - ), - ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null || selectedItem.isEmpty) { - return Text( - "Select Option", - style: GoogleFonts.poppins( - color: Colors.grey, - fontSize: 13, - ), - ); - } - return Text( - selectedItem['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ); - }, - onChanged: - visa_available.isNotEmpty - ? (Map? newValue) { - setState(() { - selectedvisa_available = - newValue?['dropdown_key']; - print("Selected Visa: $selectedvisa_available"); - }); - } - : null, - ), - ), - ), - ), - ), - ], - ), - if (isDesktop) SizedBox(width: 20), - SizedBox(height: 5), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Comments", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - isFocused: focusStates["_comments1Focused"] ?? false, - isDesktop: isDesktop, - width: isDesktop ? MediaQuery.of(context).size.width * 0.32 : null, - child: TextField( - focusNode: focusNodes["_comments1FocusNode"], - // controller: _commentsController, - controller: textControllers["_comments1Controller"], - // maxLines: 6, - // keyboardType: TextInputType.multiline, - style: TextStyle(fontSize: 12), - decoration: InputDecoration( - labelText: "Comments", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - // contentPadding: EdgeInsets.symmetric(vertical: 1), - ), - ), - ), - ], - ), - if (isDesktop) Spacer(), - SizedBox(height: 5), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: _handleAction(isDesktop), - ), - ], - ), - ] - : [ - Card( - elevation: 1, - margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), - color: const Color(0xFFF5F5F5), // Light grey - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), - child: Padding( - padding: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Visa Required", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // use same wrapper as class - // isFocused: focusStates["_visa1Focused"] ?? false, - isFocused: false, - padding: const EdgeInsets.symmetric(horizontal: 0), - isDesktop: isDesktop, - child: SizedBox( - height: 35, - width: double.infinity, - child: Focus( - focusNode: focusNodes["_visa1FocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["_visa1Focused"] = hasFocus; - }); - }, - child: GestureDetector( - // - onTap: () { - // Request focus when user taps - focusNodes["_visa1FocusNode"]?.requestFocus(); - }, - child: DropdownSearch>( - items: visa_available.cast>(), - selectedItem: visa_available.firstWhere( - (item) => item['dropdown_key'] == selectedvisa_available, - orElse: () => {}, - ), - itemAsString: (item) => item['dropdown_value'] ?? '', - popupProps: PopupProps.menu( - showSearchBox: false, - fit: FlexFit.loose, - menuProps: const MenuProps(backgroundColor: Colors.white), - itemBuilder: (context, item, isSelected) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 8, - ), - child: Text( - item['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ), - ); - }, - ), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["_visa1Focused"] ?? false) - ? layoutColor! - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["_visa1Focused"] ?? false) - ? layoutColor - : Colors.white, - // : const Color(0xFFD6D5E6), - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: layoutColor, width: 1), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), - ), - ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null || selectedItem.isEmpty) { - return Text( - "Select Option", - style: GoogleFonts.poppins( - color: Colors.grey, - fontSize: 13, - ), - ); - } - return Text( - selectedItem['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ); - }, - onChanged: - visa_available.isNotEmpty - ? (Map? newValue) { - setState(() { - selectedvisa_available = - newValue?['dropdown_key']; - print("Selected Visa: $selectedvisa_available"); - }); - } - : null, - ), - ), - ), - ), - ), - ], - ), - if (isDesktop) SizedBox(width: 20), - SizedBox(height: 5), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Comments", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - isFocused: focusStates["_comments1Focused"] ?? false, - isDesktop: isDesktop, - width: isDesktop ? MediaQuery.of(context).size.width * 0.32 : null, - child: TextField( - focusNode: focusNodes["_comments1FocusNode"], - // controller: _commentsController, - controller: textControllers["_comments1Controller"], - // maxLines: 6, - // keyboardType: TextInputType.multiline, - style: TextStyle(fontSize: 12), - decoration: InputDecoration( - labelText: "Comments", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - // contentPadding: EdgeInsets.symmetric(vertical: 1), - ), - ), - ), - ], - ), - ], - ), - ), - ), - if (isDesktop) Spacer(), - SizedBox(height: 10), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: _handleAction(isDesktop), - ), - ], - ), - ]; - } - - List _buildvisa(bool isDesktop) { - List visa_available = - widget.apiData?['flight_visa_available'] ?? []; - // Default selected value - - List> dropdownItems = - visa_available - .map( - (item) => DropdownMenuItem( - value: item['dropdown_key'], - child: Text(item['dropdown_value']), - ), - ) - .toList(); - - selectedvisa_available ??= - dropdownItems.isNotEmpty ? dropdownItems.first.value : null; - - if (dropdownItems.isEmpty) { - dropdownItems.add( - DropdownMenuItem( - value: null, - child: Text( - "No options available", - style: TextStyle(color: Colors.grey), - ), - ), - ); - } - - return [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Visa Required", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldItnerarySubWrapper( - // isFocused: _tripTypeFocused, - isFocused: focusStates["_visa1Focused"] ?? false, - isDesktop: isDesktop, - // width: - // isDesktop - // ? MediaQuery.of(context).size.width * 0.34 - // : MediaQuery.of(context).size.width * 0.66, - child: SizedBox( - height: 40, - child: DropdownButtonFormField( - // focusNode: _tripTypeFocusNode, // Assign the correct focus node - focusNode: focusNodes["_visa1FocusNode"], - value: selectedvisa_available, - style: TextStyle(fontSize: 12), - decoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - ), // Proper padding - ), - onChanged: - visa_available.isNotEmpty - ? (newValue) { - setState(() { - selectedvisa_available = newValue; - // selectedTripType = "Oneway"; - // Reset `multiTripRowCount` when switching away from Multitrip - }); - print( - "Updating form data: Flight -> trip_type -> $selectedvisa_available", - ); - - // _initializeRows(); - } - : null, - - items: dropdownItems, + ], ), ), ), - ], - ), - ]; - } - - List _handleAction(bool isDesktop) { - return [ - // Close Button - ElevatedButton( - onPressed: () { - widget.onClose("Flight", false); - // widget.onClose(false); // Close the dialog or screen - }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.grey[400], // Light grey color - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - ), - child: Text( - "Close", - style: GoogleFonts.poppins(color: Colors.white, fontSize: 12), - ), - ), - SizedBox(width: 10), // Space between buttons - // Save Changes Button - ElevatedButton( - onPressed: () { - handleSave(); - }, - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF114D8B), // Primary color for save - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - ), - child: Text( - "Save Changes", - style: GoogleFonts.poppins(color: Colors.white, fontSize: 12), - ), - ), - ]; + ]; } } diff --git a/lib/Screens/itnerary/forex.dart b/lib/Screens/itnerary/forex.dart index dc31c7c..05e1ca1 100644 --- a/lib/Screens/itnerary/forex.dart +++ b/lib/Screens/itnerary/forex.dart @@ -1530,7 +1530,8 @@ class _ForexScreenState extends State { else SizedBox(height: 8), Column( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: + isDesktop ? CrossAxisAlignment.center : CrossAxisAlignment.start, children: [ Text( "Currency *", @@ -1552,19 +1553,24 @@ class _ForexScreenState extends State { height: 40, child: Padding( padding: const EdgeInsets.all(8.0), - child: Center( - child: Text( - // "cur", - // "${selectedCurrency}", - selectedCurrency ?? "Currency", - // selectedCurrency?.isNotEmpty == true ? selectedCurrency! : "Currency", - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - ), + child: + isDesktop + ? Center(child: currencyText()) + : Container(child: currencyText()), + // child: Center + // ( + // child: Text( + // // "cur", + // // "${selectedCurrency}", + // selectedCurrency ?? "Currency", + // // selectedCurrency?.isNotEmpty == true ? selectedCurrency! : "Currency", + // style: const TextStyle( + // fontSize: 12, + // fontWeight: FontWeight.w600, + // color: Color(0xFF575A74), + // ), + // ), + // ), ), ), ), @@ -1632,6 +1638,14 @@ class _ForexScreenState extends State { ]; } + Widget currencyText() => Text( + selectedCurrency ?? "Currency", + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ); List _buildSecondRow(bool isDesktop) { return [ if (isDesktop) Spacer(), @@ -2344,7 +2358,8 @@ class _ForexScreenState extends State { children: [ Row( crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: isDesktop ? MainAxisAlignment.center : MainAxisAlignment.start, + mainAxisAlignment: + isDesktop ? MainAxisAlignment.center : MainAxisAlignment.start, children: [ Container( alignment: Alignment.bottomLeft, diff --git a/lib/Screens/itnerary_list/accomodation_list.dart b/lib/Screens/itnerary_list/accomodation_list.dart index 4eb8b3b..0096465 100644 --- a/lib/Screens/itnerary_list/accomodation_list.dart +++ b/lib/Screens/itnerary_list/accomodation_list.dart @@ -2,11 +2,12 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; -class AccomodationListWidget extends StatelessWidget { +import '../../utils/auth_utils.dart'; + +class AccomodationListWidget extends StatefulWidget { final List> accommodationList; final Function(bool, Map, String) onOpen; final Function(Map) onDeleteAccommodation; - final Function(String, bool) onAddNew; final bool isViewMode; @@ -19,12 +20,57 @@ class AccomodationListWidget extends StatelessWidget { required this.isViewMode, }); + @override + State createState() => _AccomodationListWidgetState(); +} + +class _AccomodationListWidgetState extends State { + Color? layoutColor; + Color? secondColor; + Color? thridColor; + + @override + void initState() { + super.initState(); + loadInitialData(); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? secondString = await getSecondaryColor(); + String? thridString = await getTernaryColor(); + + // String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + secondColor = + layoutString != null + ? Color(int.parse(secondString!)) + : Colors.orange; + + thridColor = + layoutString != null + ? Color(int.parse(thridString!)) + : Colors.orangeAccent; + // bodyColor = + // bodyStringColor != null + // ? Color(int.parse(bodyStringColor)) + // : Colors.white; + }); + } + @override Widget build(BuildContext context) { final isDesktop = MediaQuery.of(context).size.width > 1024; return Padding( - padding: const EdgeInsets.all(16.0), + padding: + isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0), child: Container( margin: const EdgeInsets.only(top: 16.0), child: Column( @@ -34,7 +80,7 @@ class AccomodationListWidget extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if ((!isDesktop) && accommodationList.isNotEmpty) + if ((!isDesktop) && widget.accommodationList.isNotEmpty) Text( " ", style: const TextStyle( @@ -44,17 +90,19 @@ class AccomodationListWidget extends StatelessWidget { ), MouseRegion( - cursor: isViewMode - ? SystemMouseCursors.forbidden - : SystemMouseCursors.click, + cursor: + widget.isViewMode + ? SystemMouseCursors.forbidden + : SystemMouseCursors.click, child: GestureDetector( - onTap: isViewMode - ? null - : () { - print("New data"); - onAddNew("Accomodation", true); - }, + onTap: + widget.isViewMode + ? null + : () { + print("New data"); + widget.onAddNew("Accomodation", true); + }, child: Row( mainAxisSize: MainAxisSize.min, // Ensures content fits nicely @@ -68,7 +116,7 @@ class AccomodationListWidget extends StatelessWidget { Icons.add_circle_sharp, size: 30, color: Color(0xFF114D8B), - ) + ), // Container( // decoration: BoxDecoration( // shape: BoxShape.circle, @@ -147,9 +195,9 @@ class AccomodationListWidget extends StatelessWidget { ], ), const SizedBox(height: 16), - // Scroll behavior based on device - _buildData(context, isDesktop) + // Scroll behavior based on device + _buildData(context, isDesktop), ], ), ), @@ -158,7 +206,9 @@ class AccomodationListWidget extends StatelessWidget { Widget _buildData(BuildContext context, bool isDesktop) { List> filteredList = - accommodationList.where((item) => item["is_active"] == "1").toList(); + widget.accommodationList + .where((item) => item["is_active"] == "1") + .toList(); print("filteredList- $filteredList"); // String formatDate(String dateString) { @@ -191,8 +241,11 @@ class AccomodationListWidget extends StatelessWidget { if (hour == 24 && minute == 0) { // 24:00 is treated as 00:00 on the next day - dateTime = DateTime(now.year, now.month, now.day) - .add(const Duration(days: 1)); + dateTime = DateTime( + now.year, + now.month, + now.day, + ).add(const Duration(days: 1)); } else { if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { throw FormatException("Invalid hour or minute"); @@ -235,14 +288,18 @@ class AccomodationListWidget extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), // color: Colors.orange.shade50, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 3, - offset: Offset(0, 1), - ), - ], + color: isDesktop ? Colors.white : thridColor, + // color: Colors.white, + boxShadow: + isDesktop + ? [ + BoxShadow( + color: Colors.black12, + blurRadius: 3, + offset: Offset(0, 1), + ), + ] + : [], border: Border( top: BorderSide( color: Colors.white70, // Change color to match your theme @@ -251,36 +308,38 @@ class AccomodationListWidget extends StatelessWidget { ), ), child: Padding( - padding: EdgeInsets.all(12), + padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( - mainAxisAlignment: MainAxisAlignment.end, + // mainAxisAlignment: MainAxisAlignment.end, children: [ Text( item["hotel_name"]!, style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w800, - color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74),) + fontSize: 14, + fontWeight: + isDesktop ? FontWeight.w800 : FontWeight.w600, + color: !isDesktop ? Colors.black : Color(0xFF575A74), + ), ), Spacer(), GestureDetector( - onTap: () => onOpen(true, item, "Accomodation"), + onTap: () => widget.onOpen(true, item, "Accomodation"), child: Tooltip( message: 'Edit Accomodation Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, height: 15, - color: Color(0xFF114D8B), + color: isDesktop ? Color(0xFF114D8B) : Colors.black87, ), ), ), SizedBox(width: 10), GestureDetector( - onTap: () => onDeleteAccommodation(item), + onTap: () => widget.onDeleteAccommodation(item), child: Tooltip( message: 'Delete Accommodation Details', child: Image.asset( @@ -293,170 +352,175 @@ class AccomodationListWidget extends StatelessWidget { ), ], ), - Divider( - color: Colors.blueGrey.shade50, - ), + // Divider(color: Colors.blueGrey.shade50), SizedBox(height: 4), isDesktop ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - " DestinationCity", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Check (in) ", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Check (out) ", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Comments", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - ], - ) + children: [ + Expanded( + flex: 2, + child: Text( + " DestinationCity", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Check (in) ", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Check (out) ", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Comments", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + ], + ) : SizedBox.shrink(), + SizedBox(height: 8), isDesktop ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - item["destination_city"], - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), + children: [ + Expanded( + flex: 2, + child: Text( + item["destination_city"], + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, ), ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - "${formatDate(item["checkin_date"]!)} ${formatTime(item["checkin_time"]!)}", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + "${formatDate(item["checkin_date"]!)} ${formatTime(item["checkin_time"]!)}", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, ), ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - "${formatDate(item["checkout_date"]!)} ${formatTime(item["checkout_time"]!)}", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + "${formatDate(item["checkout_date"]!)} ${formatTime(item["checkout_time"]!)}", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, ), ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: _buildComments( - "Comments:", item["comments"] ?? "N/A"), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: _buildComments( + "Comments:", + item["comments"] ?? "N/A", ), - ], - ) - : Column( + ), + ], + ) + : Container( + color: Colors.white, + padding: EdgeInsets.all(8.0), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Wrap( - spacing: 20, // horizontal space between items - runSpacing: 10, // vertical space between rows - children: [ - _buildInfoColumn("City", item["destination_city"]), - _buildInfoColumn("Check (In)", "${formatDate(item["checkin_date"]!)} ${formatTime(item["checkin_time"]!)}"), - _buildInfoColumn("Check (Out)", "${formatDate(item["checkout_date"]!)} ${formatTime(item["checkout_time"]!)}"), - // City - long name handled with flexible space - // Expanded( - // flex: 3, - // child: _buildInfoColumn("City", item["destination_city"]), - // ), - - // SizedBox(width: 8), - - // Check In and Check Out stacked right side - // Expanded( - // flex: 4, - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.end, - // children: [ - // _buildInfoColumn( - // "Check In", - // "${formatDate(item["checkin_date"]!)} ${formatTime(item["checkin_time"]!)}", - // ), - // SizedBox(height: 6), - // _buildInfoColumn( - // "Check Out", - // "${formatDate(item["checkout_date"]!)} ${formatTime(item["checkout_time"]!)}", - // ), - // ], - // ), - // ), - ], + _buildRow( + "Destination City", + item["destination_city"], ), - const SizedBox(height: 10), - const Text( - "Comment", - style: TextStyle(fontWeight: FontWeight.w500), + SizedBox(height: 5), + _buildRow( + "Check (in)", + "${formatDate(item["checkin_date"]!)} ${formatTime(item["checkin_time"]!)}", ), - const SizedBox(height: 5), - if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) - Container( - width: double.infinity, - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - border: Border.all(color: Color(0xFF7098DD), width: 1), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - item["comments"], - style: const TextStyle(fontSize: 12), - ), - ) - else - const Text( "N/A", style: TextStyle(fontSize: 12), ), - ], - ) - // Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // _buildRow("City:", item["destination_city"]), - // SizedBox(width: 10), - // SizedBox(width: 10), - // _buildDateTimeRow( - // "Check-in:", - // formatDate(item["checkin_date"]!), - // item["checkin_time"]!, - // ), - // SizedBox(width: 10), - // _buildRow( - // "Date(out):", formatDate(item["checkout_date"]!)), - // SizedBox(width: 10), - // _buildRow("Comments:", item["comments"] ?? "N/A"), - // ], - // ) + SizedBox(height: 5), + _buildRow( + "Check (out)", + "${formatDate(item["checkout_date"]!)} ${formatTime(item["checkout_time"]!)}", + ), + SizedBox(height: 5), + _buildRow("Comments:", item["comments"] ?? "N/A"), + ], + ), + ), + + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Wrap( + // spacing: 20, // horizontal space between items + // runSpacing: 10, // vertical space between rows + // children: [ + // _buildInfoColumn("City", item["destination_city"]), + // _buildInfoColumn("Check (In)", "${formatDate(item["checkin_date"]!)} ${formatTime(item["checkin_time"]!)}"), + // _buildInfoColumn("Check (Out)", "${formatDate(item["checkout_date"]!)} ${formatTime(item["checkout_time"]!)}"), + // // City - long name handled with flexible space + // // Expanded( + // // flex: 3, + // // child: _buildInfoColumn("City", item["destination_city"]), + // // ), + // + // // SizedBox(width: 8), + // + // // Check In and Check Out stacked right side + // // Expanded( + // // flex: 4, + // // child: Column( + // // crossAxisAlignment: CrossAxisAlignment.end, + // // children: [ + // // _buildInfoColumn( + // // "Check In", + // // "${formatDate(item["checkin_date"]!)} ${formatTime(item["checkin_time"]!)}", + // // ), + // // SizedBox(height: 6), + // // _buildInfoColumn( + // // "Check Out", + // // "${formatDate(item["checkout_date"]!)} ${formatTime(item["checkout_time"]!)}", + // // ), + // // ], + // // ), + // // ), + // ], + // ), + // const SizedBox(height: 10), + // const Text( + // "Comment", + // style: TextStyle(fontWeight: FontWeight.w500), + // ), + // const SizedBox(height: 5), + // if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) + // Container( + // width: double.infinity, + // padding: const EdgeInsets.all(8), + // decoration: BoxDecoration( + // border: Border.all(color: Color(0xFF7098DD), width: 1), + // borderRadius: BorderRadius.circular(6), + // ), + // child: Text( + // item["comments"], + // style: const TextStyle(fontSize: 12), + // ), + // ) + // else + // const Text( "N/A", style: TextStyle(fontSize: 12), ), + // ], + // ) ], ), ), @@ -485,31 +549,35 @@ class AccomodationListWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: - TextStyle(color: Colors.black), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text(value.substring(0, limit) + "...", + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w600, ), - overflow: TextOverflow.ellipsis), - ) - : Text( - value, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, + overflow: TextOverflow.ellipsis, + ), + ) + : Text( + value, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), ), - ), ), ], ); @@ -531,87 +599,90 @@ class AccomodationListWidget extends StatelessWidget { SizedBox(height: 4), Text( value, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black87, - ), + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), ), ], ); } - // Widget _buildRow(String title, String value) { - // // Define character limits based on title - // Map limits = { - // // "Special Request:": 30, - // "Comments:": 10, - // // Add more keys and limits if needed - // }; - // - // int limit = limits[title] ?? 50; // Default limit if title not found - // bool exceedsLimit = value.length > limit; - // - // String wrapText(String text, int maxLineLength) { - // final pattern = RegExp('.{1,$maxLineLength}(\\s+|\$)'); - // return pattern.allMatches(text).map((m) => m.group(0)!).join('\n'); - // } - // - // return Row( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Text( - // title, - // style: GoogleFonts.poppins( - // fontSize: 12, - // ), - // ), - // SizedBox(width: 8), - // Expanded( - // child: exceedsLimit - // ? Tooltip( - // message: wrapText(value, 50), - // decoration: BoxDecoration( - // color: Colors.grey.shade200, // Black background - // borderRadius: BorderRadius.circular(6), - // ), - // textStyle: - // TextStyle(color: Colors.black), // Tooltip text color - // padding: EdgeInsets.all(8), - // preferBelow: false, - // child: Text(value.substring(0, limit) + "...", - // style: TextStyle(fontSize: 12), - // overflow: TextOverflow.ellipsis), - // ) - // : Text( - // value, - // style: TextStyle(fontSize: 12), - // ), - // ), - // ], - // ); - // } + Widget _buildRow(String title, String value) { + // Define character limits based on title + Map limits = { + // "Special Request:": 30, + "Comments:": 10, + // Add more keys and limits if needed + }; - // Widget _buildDateTimeRow(String title, String date, String time) { - // return Row( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Text( - // title, - // style: GoogleFonts.poppins( - // fontSize: 12, - // fontWeight: FontWeight.w600, - // ), - // ), - // SizedBox(width: 8), - // Expanded( - // child: Text( - // "$date, $time", - // style: GoogleFonts.poppins( - // fontSize: 12, - // ), - // ), - // ), - // ], - // ); - // } + int limit = limits[title] ?? 50; // Default limit if title not found + bool exceedsLimit = value.length > limit; + + String wrapText(String text, int maxLineLength) { + final pattern = RegExp('.{1,$maxLineLength}(\\s+|\$)'); + return pattern.allMatches(text).map((m) => m.group(0)!).join('\n'); + } + + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + + children: [ + SizedBox( + // color: Colors.yellowAccent.shade100, + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 5), + // Expanded(child: Text(value, style: TextStyle(fontSize: 12))), + Expanded( + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", + style: TextStyle(fontSize: 12), + overflow: TextOverflow.ellipsis, + ), + ) + : Text(value, style: TextStyle(fontSize: 12)), + ), + ], + ); + } + + Widget _buildDateTimeRow(String title, String date, String time) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 5), + Expanded( + child: Text("$date, $time", style: GoogleFonts.poppins(fontSize: 12)), + ), + ], + ); + } } diff --git a/lib/Screens/itnerary_list/bus_list.dart b/lib/Screens/itnerary_list/bus_list.dart index 68791dc..5b5b380 100644 --- a/lib/Screens/itnerary_list/bus_list.dart +++ b/lib/Screens/itnerary_list/bus_list.dart @@ -8,8 +8,9 @@ import 'package:shared_preferences/shared_preferences.dart'; import '../../config/apiUrl.dart'; import '../../data/models/plan.dart'; +import '../../utils/auth_utils.dart'; -class BusListWidget extends StatelessWidget { +class BusListWidget extends StatefulWidget { final List> busList; final Function(bool, Map, String) onOpen; final Function(Map) onDeleteBus; @@ -17,20 +18,66 @@ class BusListWidget extends StatelessWidget { final Function(String, bool) onAddNew; final bool isViewMode; - const BusListWidget( - {super.key, - required this.busList, - required this.onOpen, - required this.onDeleteBus, - required this.onAddNew, - required this.isViewMode}); + const BusListWidget({ + super.key, + required this.busList, + required this.onOpen, + required this.onDeleteBus, + required this.onAddNew, + required this.isViewMode, + }); + + @override + State createState() => _BusListWidgetState(); +} + +class _BusListWidgetState extends State { + Color? layoutColor; + Color? secondColor; + Color? thridColor; + + @override + void initState() { + super.initState(); + loadInitialData(); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? secondString = await getSecondaryColor(); + String? thridString = await getTernaryColor(); + + // String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + secondColor = + layoutString != null + ? Color(int.parse(secondString!)) + : Colors.orange; + + thridColor = + layoutString != null + ? Color(int.parse(thridString!)) + : Colors.orangeAccent; + // bodyColor = + // bodyStringColor != null + // ? Color(int.parse(bodyStringColor)) + // : Colors.white; + }); + } @override Widget build(BuildContext context) { final isDesktop = MediaQuery.of(context).size.width > 1024; return Padding( - padding: const EdgeInsets.all(16.0), + padding: + isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0), child: Container( margin: const EdgeInsets.only(top: 16.0), child: Column( @@ -40,7 +87,7 @@ class BusListWidget extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if ((!isDesktop) && busList.isNotEmpty) + if ((!isDesktop) && widget.busList.isNotEmpty) Text( " ", style: const TextStyle( @@ -50,16 +97,18 @@ class BusListWidget extends StatelessWidget { ), MouseRegion( - cursor: isViewMode - ? SystemMouseCursors.forbidden - : SystemMouseCursors.click, + cursor: + widget.isViewMode + ? SystemMouseCursors.forbidden + : SystemMouseCursors.click, child: GestureDetector( - onTap: isViewMode - ? null - : () { - print("New data"); - onAddNew("Bus", true); - }, + onTap: + widget.isViewMode + ? null + : () { + print("New data"); + widget.onAddNew("Bus", true); + }, child: Row( mainAxisSize: MainAxisSize.min, // Ensures content fits nicely @@ -73,7 +122,7 @@ class BusListWidget extends StatelessWidget { Icons.add_circle_sharp, size: 30, color: Color(0xFF114D8B), - ) + ), // Container( // decoration: BoxDecoration( // shape: BoxShape.circle, @@ -130,9 +179,9 @@ class BusListWidget extends StatelessWidget { ], ), const SizedBox(height: 16), - // Scroll behavior based on device - _buildData(context, isDesktop) + // Scroll behavior based on device + _buildData(context, isDesktop), ], ), ), @@ -141,7 +190,7 @@ class BusListWidget extends StatelessWidget { Widget _buildData(BuildContext context, bool isDesktop) { List> filteredList = - busList.where((item) => item["is_active"] == "1").toList(); + widget.busList.where((item) => item["is_active"] == "1").toList(); print("filteredList- $filteredList"); // String formatDate(String dateString) { @@ -191,8 +240,11 @@ class BusListWidget extends StatelessWidget { if (hour == 24 && minute == 0) { // 24:00 is treated as 00:00 on the next day - dateTime = DateTime(now.year, now.month, now.day) - .add(const Duration(days: 1)); + dateTime = DateTime( + now.year, + now.month, + now.day, + ).add(const Duration(days: 1)); } else { if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { throw FormatException("Invalid hour or minute"); @@ -218,14 +270,17 @@ class BusListWidget extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), // color: Colors.orange.shade50, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 3, - offset: Offset(0, 1), - ), - ], + color: isDesktop ? Colors.white : thridColor, + boxShadow: + isDesktop + ? [ + BoxShadow( + color: Colors.black12, + blurRadius: 3, + offset: Offset(0, 1), + ), + ] + : [], border: Border( top: BorderSide( color: Colors.white70, // Change color to match your theme @@ -234,7 +289,7 @@ class BusListWidget extends StatelessWidget { ), ), child: Padding( - padding: EdgeInsets.all(12), + padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -246,25 +301,27 @@ class BusListWidget extends StatelessWidget { style: GoogleFonts.poppins( fontSize: 14, fontWeight: FontWeight.w800, + color: + !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74), ), ), Spacer(), GestureDetector( - onTap: () => onOpen(true, item, "Bus"), + onTap: () => widget.onOpen(true, item, "Bus"), child: Tooltip( - message: 'Delete Edit Details', + message: 'Edit Bus Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, height: 15, // color: Color(0xFF114D8B), - color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) + color: !isDesktop ? Colors.black : Color(0xFF575A74), ), ), ), SizedBox(width: 10), GestureDetector( - onTap: () => onDeleteBus(item), + onTap: () => widget.onDeleteBus(item), child: Tooltip( message: 'Delete Bus Details', child: Image.asset( @@ -277,137 +334,149 @@ class BusListWidget extends StatelessWidget { ), ], ), - Divider( - color: Colors.blueGrey.shade50, - ), + // Divider(color: Colors.blueGrey.shade50), SizedBox(height: 4), isDesktop ? Row( - children: [ - Expanded( - flex: 3, - child: Text( - " Planned Trips", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 3, - child: Text( - " Date", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 3, - child: Text( - " Comments", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - ], - ) - : SizedBox.shrink(), - SizedBox(height: 4), - isDesktop - ? Row( - children: [ - Expanded( - flex: 3, - child: Text( - "${item["from"]} - ${item["to"]} ", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 3, - child: Text( - "${formatDate(item["date"]!)} ${formatTime(item["time"]!)}", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 3, - child: _buildComments( - "Comments:", item["comments"] ?? "N/A"), - ), - ], - ) - : - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Top Row (Country, Currency, Total) - Wrap( - spacing: 20, // horizontal space between items - runSpacing: 10, // vertical space between rows - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - _infoBlock("From", item["from"] ?? "N/A"), - _infoBlock("To", item["to"]! ?? "N/A"), - _infoBlock("Date", - (item["date"] != null && item["time"] != null) - ? "${formatDate(item["date"]!)} ${formatTime(item["time"]!)}" - : "N/A", + Expanded( + flex: 3, + child: Text( + "Planned Trips", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 3, + child: Text( + " Date", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 3, + child: Text( + " Comments", + style: GoogleFonts.poppins(fontSize: 11), + ), ), - ], - ), - const SizedBox(height: 16), - - // Comment label - Text( - "Comment", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, + ) + : SizedBox.shrink(), + SizedBox(height: 8), + isDesktop + ? Row( + children: [ + Expanded( + flex: 3, + child: Text( + "${item["from"]} - ${item["to"]} ", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 3, + child: Text( + "${formatDate(item["date"]!)} ${formatTime(item["time"]!)}", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 3, + child: _buildComments( + "Comments:", + item["comments"] ?? "N/A", + ), + ), + ], + ) + : Container( + color: Colors.white, + padding: const EdgeInsets.all(4.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildRow( + "PlannedTrips", + '${item["from"]!} - ${item["to"]!}', + ), + SizedBox(height: 5), + // _buildRow("To", item["to"]!), + // SizedBox(width: 10), + _buildDateTimeRow( + "Date", + formatDate(item["date"]!), + formatTime(item["time"]!), + ), + SizedBox(height: 5), + _buildRow("Comments", item["comments"] ?? "N/A"), + ], ), ), - const SizedBox(height: 8), - if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - border: Border.all(color: const Color(0xFF7098DD), width: 1), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - item["comments"] ?? "N/A", - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), - ), - ) - else - const Text( "N/A", style: TextStyle(fontSize: 12), ), - ], - ), + // Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // _buildRow("From:", item["from"]), - // SizedBox(width: 10), - // _buildRow("To:", item["to"]!), - // SizedBox(width: 10), - // _buildDateTimeRow( - // "Date:", - // formatDate(item["date"]!), - // formatTime(item["time"]!), + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // // Top Row (Country, Currency, Total) + // Wrap( + // spacing: 20, // horizontal space between items + // runSpacing: 10, // vertical space between rows + // // Row( + // // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // _infoBlock("From", item["from"] ?? "N/A"), + // _infoBlock("To", item["to"]! ?? "N/A"), + // _infoBlock( + // "Date", + // (item["date"] != null && item["time"] != null) + // ? "${formatDate(item["date"]!)} ${formatTime(item["time"]!)}" + // : "N/A", + // ), + // ], + // ), + // const SizedBox(height: 16), + // + // // Comment label + // Text( + // "Comment", + // style: GoogleFonts.poppins( + // fontSize: 14, + // fontWeight: FontWeight.w600, // ), - // _buildRow("Comments:", item["comments"] ?? "N/A"), - // ], - // ) + // ), + // const SizedBox(height: 8), + // if (item["comments"] != null && + // item["comments"].toString().trim().isNotEmpty) + // Container( + // width: double.infinity, + // padding: const EdgeInsets.all(12), + // decoration: BoxDecoration( + // border: Border.all( + // color: const Color(0xFF7098DD), + // width: 1, + // ), + // borderRadius: BorderRadius.circular(6), + // ), + // child: Text( + // item["comments"] ?? "N/A", + // style: GoogleFonts.poppins( + // fontSize: 12, + // color: Colors.black87, + // ), + // ), + // ) + // else + // const Text("N/A", style: TextStyle(fontSize: 12)), + // ], + // ), ], ), ), @@ -434,16 +503,14 @@ class BusListWidget extends StatelessWidget { const SizedBox(height: 4), Text( value, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black87, - ), + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), ), ], ), ), ); } + Widget _buildComments(String title, String value) { // Define character limits based on title Map limits = { @@ -464,31 +531,35 @@ class BusListWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: - TextStyle(color: Colors.black), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text(value.substring(0, limit) + "...", + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w600, ), - overflow: TextOverflow.ellipsis), - ) - : Text( - value, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, + overflow: TextOverflow.ellipsis, + ), + ) + : Text( + value, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), ), - ), ), ], ); @@ -513,36 +584,38 @@ class BusListWidget extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, + SizedBox( + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), ), ), SizedBox(width: 8), Expanded( - child: exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: - TextStyle(color: Colors.black), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text(value.substring(0, limit) + "...", + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", style: TextStyle(fontSize: 12), - overflow: TextOverflow.ellipsis), - ) - : Text( - value, - style: GoogleFonts.poppins( - fontSize: 12, - ), - ), + overflow: TextOverflow.ellipsis, + ), + ) + : Text(value, style: GoogleFonts.poppins(fontSize: 12)), ), ], ); @@ -552,21 +625,19 @@ class BusListWidget extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, + SizedBox( + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), ), ), SizedBox(width: 8), Expanded( - child: Text( - "$date, $time", - style: GoogleFonts.poppins( - fontSize: 12, - ), - ), + child: Text("$date, $time", style: GoogleFonts.poppins(fontSize: 12)), ), ], ); diff --git a/lib/Screens/itnerary_list/flight_list.dart b/lib/Screens/itnerary_list/flight_list.dart index 79d886e..3c4606b 100644 --- a/lib/Screens/itnerary_list/flight_list.dart +++ b/lib/Screens/itnerary_list/flight_list.dart @@ -3,6 +3,7 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; import '../../services/apiService.dart'; +import '../../utils/auth_utils.dart'; class FlightListWidget extends StatefulWidget { final bool hasAction; @@ -32,6 +33,9 @@ class FlightListWidget extends StatefulWidget { class _FlightListWidgetState extends State { ApiService apiService = ApiService(); + Color? layoutColor; + Color? secondColor; + Color? thridColor; // late Map countryMap; Map countryMap = {}; @@ -40,6 +44,36 @@ class _FlightListWidgetState extends State { void initState() { super.initState(); loadCountryList(); // Call your method here + loadInitialData(); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? secondString = await getSecondaryColor(); + String? thridString = await getTernaryColor(); + + // String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + secondColor = + layoutString != null + ? Color(int.parse(secondString!)) + : Colors.orange; + + thridColor = + layoutString != null + ? Color(int.parse(thridString!)) + : Colors.orangeAccent; + // bodyColor = + // bodyStringColor != null + // ? Color(int.parse(bodyStringColor)) + // : Colors.white; + }); } Future loadCountryList() async { @@ -169,7 +203,8 @@ class _FlightListWidgetState extends State { // ); return Padding( - padding: const EdgeInsets.all(16.0), + padding: + isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0), child: Container( margin: const EdgeInsets.only(top: 16.0), child: Column( @@ -192,16 +227,18 @@ class _FlightListWidgetState extends State { // Right side: either "Add" icon or nothing if (widget.flightList.isNotEmpty) MouseRegion( - cursor: widget.isViewMode - ? SystemMouseCursors.forbidden - : SystemMouseCursors.click, + cursor: + widget.isViewMode + ? SystemMouseCursors.forbidden + : SystemMouseCursors.click, child: GestureDetector( - onTap: widget.isViewMode - ? null - : () { - widget.onAddNew("Flight", true); - print("New data"); - }, + onTap: + widget.isViewMode + ? null + : () { + widget.onAddNew("Flight", true); + print("New data"); + }, child: Icon( Icons.add_circle_sharp, size: 30, @@ -210,21 +247,20 @@ class _FlightListWidgetState extends State { ), ) else if (!isDesktop) - // Centered "No Data Found" message for mobile and empty list + // Centered "No Data Found" message for mobile and empty list Expanded( child: Center( child: Text( "No Data Found", textAlign: TextAlign.center, style: GoogleFonts.poppins( - fontSize: 20, - fontWeight: FontWeight.bold, + fontSize: 18, + fontWeight: FontWeight.w500, color: Colors.grey, ), ), ), - ) - + ), ], ), const SizedBox(height: 16), @@ -235,7 +271,6 @@ class _FlightListWidgetState extends State { ), ), ); - } Widget _buildData(BuildContext context, bool isDesktop) { @@ -347,22 +382,26 @@ class _FlightListWidgetState extends State { margin: EdgeInsets.symmetric(horizontal: 8, vertical: 6), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), + // color: isDesktop ? Colors.white : Color(0xFFFFF0F5), + color: isDesktop ? Colors.white : thridColor, // color: Colors.orange.shade50, - color: Colors.white, - - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 2, - offset: Offset(0, 2), // down - ), - // Top shadow - BoxShadow( - color: Colors.black12, - blurRadius: 0.5, - offset: Offset(0, -1), // up - ), - ], + // color: Colors.white, + boxShadow: + isDesktop + ? [ + BoxShadow( + color: Colors.black12, + blurRadius: 2, + offset: Offset(0, 2), // down + ), + // Top shadow + BoxShadow( + color: Colors.black12, + blurRadius: 0.5, + offset: Offset(0, -1), // up + ), + ] + : [], border: Border( top: BorderSide( color: Colors.white70, // Change color to match your theme @@ -371,49 +410,56 @@ class _FlightListWidgetState extends State { ), ), child: Padding( - padding: EdgeInsets.all(12), + padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(5), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - Text( - tripTypeName ?? "N/A", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w800, - color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74), - ), - ), - Spacer(), - GestureDetector( - onTap: () => widget.onOpen(true, item, "Flight"), - child: Tooltip( - message: 'Edit Flight Details', - child: Image.asset( - 'assets/images/IconsImg/edit.png', - width: 20, - height: 15, - color: Color(0xFF114D8B), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 2), + child: Row( + children: [ + Text( + tripTypeName ?? "N/A", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: + isDesktop ? FontWeight.w800 : FontWeight.w600, + color: !isDesktop ? Colors.black : Color(0xFF575A74), + + // Color(0xFF114D8B) ), ), - ), - SizedBox(width: 10), - GestureDetector( - onTap: () => widget.onDeleteFlight(item), - child: Tooltip( - message: 'Delete Flight Details', - child: Image.asset( - 'assets/images/IconsImg/delete.png', - width: 20, - height: 15, - color: Colors.red, + Spacer(), + GestureDetector( + onTap: () => widget.onOpen(true, item, "Flight"), + child: Tooltip( + message: 'Edit Flight Details', + child: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + color: + isDesktop ? Color(0xFF114D8B) : Colors.black87, + ), ), ), - ), - ], + SizedBox(width: 10), + GestureDetector( + onTap: () => widget.onDeleteFlight(item), + child: Tooltip( + message: 'Delete Flight Details', + child: Image.asset( + 'assets/images/IconsImg/delete.png', + width: 20, + height: 15, + color: Colors.red, + ), + ), + ), + ], + ), ), - Divider(color: Colors.blueGrey.shade50), + // Divider(color: Colors.blueGrey.shade50), SizedBox(height: 4), if (isDesktop) Row( @@ -600,10 +646,9 @@ class _FlightListWidgetState extends State { item["trips"] != null && item["trips"].isNotEmpty) ...item["trips"].map((trip) { - String fromPlaceCountry = countryMap[trip["from_place"]?.toString()] ?? - "Unknown Country"; + "Unknown Country"; final parts = fromPlaceCountry.split('\n'); final cityAndCode = parts[0]; @@ -618,7 +663,7 @@ class _FlightListWidgetState extends State { String toPlaceCountry = countryMap[trip["to_place"]?.toString()] ?? - "Unknown Country"; + "Unknown Country"; final toparts = toPlaceCountry.split('\n'); final tocityAndCode = toparts[0]; @@ -631,41 +676,44 @@ class _FlightListWidgetState extends State { final tocity = tocityMatch?.group(1) ?? ''; final tocode = tocityMatch?.group(2) ?? ''; - // return Padding( - // padding: const EdgeInsets.symmetric(vertical: 6.0), - // child: Container( - // decoration: BoxDecoration( - // border: Border.all(color: Colors.grey.shade300), - // borderRadius: BorderRadius.circular(6), - // color: Colors.grey.shade50, - // ), - // padding: const EdgeInsets.all(8), - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // _buildKeyValueRow( - // "Class", - // getRequestForClass(trip["class"].toString()) ?? - // "N/A", - // ), - // _buildKeyValueRow( - // "Sector", - // "$fromcity ($fromcode), $fromairport → $tocity ($tocode), $toairport", - // ), - // - // _buildKeyValueRow( - // "Date", - // formatDate(trip["date"] ?? ""), - // ), - // _buildKeyValueRow( - // "Time", - // formatTime(trip["time"] ?? ""), - // ), - // ], - // ), - // ), - // ); + return Padding( + padding: const EdgeInsets.symmetric(vertical: 6.0), + child: Container( + decoration: BoxDecoration( + border: Border.all(color: Colors.grey.shade300), + borderRadius: BorderRadius.circular(6), + color: Colors.grey.shade50, + ), + padding: const EdgeInsets.all(8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildKeyValueRow( + "Class", + getRequestForClass(trip["class"].toString()) ?? + "N/A", + ), + _buildKeyValueRow( + "From", + "$fromcity ($fromcode), $fromairport ", + ), + _buildKeyValueRow( + "To", + "$tocity ($tocode), $toairport", + ), + _buildKeyValueRow( + "Date", + formatDate(trip["date"] ?? ""), + ), + _buildKeyValueRow( + "Time", + formatTime(trip["time"] ?? ""), + ), + ], + ), + ), + ); // return Padding( // padding: const EdgeInsets.symmetric(vertical: 6.0), @@ -701,9 +749,13 @@ class _FlightListWidgetState extends State { // ), // ), // const Padding( - // padding: EdgeInsets.symmetric(horizontal: 6), + // padding: EdgeInsets.symmetric( + // horizontal: 6, + // ), // child: Image( - // image: AssetImage('assets/images/IconsImg/Frame.png'), + // image: AssetImage( + // 'assets/images/IconsImg/Frame.png', + // ), // width: 18, // height: 18, // ), @@ -738,68 +790,67 @@ class _FlightListWidgetState extends State { // ), // ); - return Padding( - padding: const EdgeInsets.symmetric(vertical: 6.0), - child: Container( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Wrap( - crossAxisAlignment: WrapCrossAlignment.center, - spacing: 4, - runSpacing: 4, - children: [ - Text( - '${getRequestForClass(trip["class"].toString()) ?? "N/A"} (', - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: Colors.black87, - ), - ), - Text( - fromcode, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: Colors.black87, - ), - ), - const Padding( - padding: EdgeInsets.symmetric(horizontal: 4), - child: Image( - image: AssetImage('assets/images/IconsImg/Frame.png'), - width: 18, - height: 18, - ), - ), - Text( - '$tocode)', - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: Colors.black87, - ), - ), - ], - ), - const SizedBox(height: 6), - Align( - alignment: Alignment.centerRight, - child: Text( - '${formatDate(trip["date"] ?? "")} ${formatTime(trip["time"] ?? "")}', - textAlign: TextAlign.right, - style: const TextStyle( - fontSize: 13, - color: Colors.black87, - ), - ), - ), - ], - ), - ), - ); - + // return Padding( + // padding: const EdgeInsets.symmetric(vertical: 6.0), + // child: Container( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Wrap( + // crossAxisAlignment: WrapCrossAlignment.center, + // spacing: 4, + // runSpacing: 4, + // children: [ + // Text( + // '${getRequestForClass(trip["class"].toString()) ?? "N/A"} (', + // style: const TextStyle( + // fontWeight: FontWeight.bold, + // fontSize: 14, + // color: Colors.black87, + // ), + // ), + // Text( + // fromcode, + // style: const TextStyle( + // fontWeight: FontWeight.bold, + // fontSize: 14, + // color: Colors.black87, + // ), + // ), + // const Padding( + // padding: EdgeInsets.symmetric(horizontal: 4), + // child: Image( + // image: AssetImage('assets/images/IconsImg/Frame.png'), + // width: 18, + // height: 18, + // ), + // ), + // Text( + // '$tocode)', + // style: const TextStyle( + // fontWeight: FontWeight.bold, + // fontSize: 14, + // color: Colors.black87, + // ), + // ), + // ], + // ), + // const SizedBox(height: 6), + // Align( + // alignment: Alignment.centerRight, + // child: Text( + // '${formatDate(trip["date"] ?? "")} ${formatTime(trip["time"] ?? "")}', + // textAlign: TextAlign.right, + // style: const TextStyle( + // fontSize: 13, + // color: Colors.black87, + // ), + // ), + // ), + // ], + // ), + // ), + // ); }).toList(), ], ), @@ -816,12 +867,12 @@ class _FlightListWidgetState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( - width: 80, // adjust width as needed + width: 70, // adjust width as needed child: Text( - "$key:", + "$key", style: GoogleFonts.poppins( fontSize: 12, - fontWeight: FontWeight.w700, + fontWeight: FontWeight.w600, ), ), ), diff --git a/lib/Screens/itnerary_list/forex_list.dart b/lib/Screens/itnerary_list/forex_list.dart index 97014ec..0f52467 100644 --- a/lib/Screens/itnerary_list/forex_list.dart +++ b/lib/Screens/itnerary_list/forex_list.dart @@ -5,8 +5,9 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import '../../services/apiService.dart'; +import '../../utils/auth_utils.dart'; -class ForexListWidget extends StatelessWidget { +class ForexListWidget extends StatefulWidget { final List> forexList; final Function(bool, Map, String) onOpen; final Function(Map) onDeleteForex; @@ -16,15 +17,60 @@ class ForexListWidget extends StatelessWidget { final Function(String, bool) onAddNew; final bool isViewMode; - const ForexListWidget( - {super.key, - required this.forexList, - required this.onOpen, - required this.onDeleteForex, - required this.apiCountryData, - required this.onAddNew, - required this.apiData, - required this.isViewMode}); + const ForexListWidget({ + super.key, + required this.forexList, + required this.onOpen, + required this.onDeleteForex, + required this.apiCountryData, + required this.onAddNew, + required this.apiData, + required this.isViewMode, + }); + + @override + State createState() => _ForexListWidgetState(); +} + +class _ForexListWidgetState extends State { + Color? layoutColor; + Color? secondColor; + Color? thridColor; + + @override + void initState() { + super.initState(); + loadInitialData(); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? secondString = await getSecondaryColor(); + String? thridString = await getTernaryColor(); + + // String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + secondColor = + layoutString != null + ? Color(int.parse(secondString!)) + : Colors.orange; + + thridColor = + layoutString != null + ? Color(int.parse(thridString!)) + : Colors.orangeAccent; + // bodyColor = + // bodyStringColor != null + // ? Color(int.parse(bodyStringColor)) + // : Colors.white; + }); + } @override Widget build(BuildContext context) { @@ -32,7 +78,8 @@ class ForexListWidget extends StatelessWidget { final ApiService apiService = ApiService(); return Padding( - padding: const EdgeInsets.all(16.0), + padding: + isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0), child: Container( margin: const EdgeInsets.only(top: 16.0), child: Column( @@ -134,27 +181,24 @@ class ForexListWidget extends StatelessWidget { // // ), // ], // ), - const SizedBox(height: 16), - // Scroll behavior based on device + SizedBox(height: isDesktop ? 16 : 4), - _buildData(context, isDesktop) + // Scroll behavior based on device + _buildData(context, isDesktop), ], ), ), ); } - Widget _buildData( - BuildContext context, - bool isDesktop, - ) { + Widget _buildData(BuildContext context, bool isDesktop) { final ApiService apiService = ApiService(); List> filteredList = - forexList.where((item) => item["is_active"] == "1").toList(); + widget.forexList.where((item) => item["is_active"] == "1").toList(); print("filteredList- $filteredList"); - List visatypeList = apiData?['visa_type_of_visa'] ?? []; - List countryList = apiCountryData ?? []; + List visatypeList = widget.apiData?['visa_type_of_visa'] ?? []; + List countryList = widget.apiCountryData ?? []; String getRequestForVisa(String? specialRequestKey) { if (specialRequestKey == null) return "N/A"; @@ -209,8 +253,11 @@ class ForexListWidget extends StatelessWidget { if (hour == 24 && minute == 0) { // 24:00 is treated as 00:00 on the next day - dateTime = DateTime(now.year, now.month, now.day) - .add(const Duration(days: 1)); + dateTime = DateTime( + now.year, + now.month, + now.day, + ).add(const Duration(days: 1)); } else { if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { throw FormatException("Invalid hour or minute"); @@ -231,27 +278,34 @@ class ForexListWidget extends StatelessWidget { itemBuilder: (context, index) { final item = filteredList[index]; final double transport = double.tryParse(item["transport"] ?? "0") ?? 0; - final double accommodation = double.tryParse(item["accommodation"] ?? "0") ?? 0; + final double accommodation = + double.tryParse(item["accommodation"] ?? "0") ?? 0; final double telephone = double.tryParse(item["telephone"] ?? "0") ?? 0; - final double perdiemAmount = double.tryParse(item["perdiem_amount"] ?? "0") ?? 0; + final double perdiemAmount = + double.tryParse(item["perdiem_amount"] ?? "0") ?? 0; final double calculatedValue = transport + accommodation + telephone; - final String calculatedOtherExpenses = calculatedValue.toStringAsFixed(0); + final String calculatedOtherExpenses = calculatedValue.toStringAsFixed( + 0, + ); final double finalTotal = calculatedValue + perdiemAmount; - return Container( margin: EdgeInsets.symmetric(horizontal: 8, vertical: 6), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), // color: Colors.orange.shade50, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 3, - offset: Offset(0, 1), - ), - ], + // color: Colors.white, + color: isDesktop ? Colors.white : thridColor, + boxShadow: + isDesktop + ? [ + BoxShadow( + color: Colors.black12, + blurRadius: 3, + offset: Offset(0, 1), + ), + ] + : [], border: Border( top: BorderSide( color: Colors.white70, // Change color to match your theme @@ -260,23 +314,28 @@ class ForexListWidget extends StatelessWidget { ), ), child: Padding( - padding: EdgeInsets.all(12), + padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( - mainAxisAlignment: MainAxisAlignment.end, + // mainAxisAlignment: MainAxisAlignment.end, children: [ - Text( - getRequestForCountry(item["country_code"]!.toString()), - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w700, + Expanded( + flex: 1, + child: Text( + getRequestForCountry(item["country_code"]!.toString()), + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: + isDesktop ? FontWeight.w800 : FontWeight.w600, + color: !isDesktop ? Colors.black : Color(0xFF575A74), + ), ), ), Spacer(), GestureDetector( - onTap: () => onOpen(true, item, "Forex"), + onTap: () => widget.onOpen(true, item, "Forex"), child: Tooltip( message: 'Edit Forex Details', child: Image.asset( @@ -284,306 +343,327 @@ class ForexListWidget extends StatelessWidget { width: 20, height: 15, // color: Color(0xFF114D8B), - color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) + color: !isDesktop ? Colors.black : Color(0xFF575A74), + ), + ), + ), + SizedBox(width: 10), + GestureDetector( + onTap: () => widget.onDeleteForex(item), + child: Tooltip( + message: 'Delete Forex Details', + child: Image.asset( + 'assets/images/IconsImg/delete.png', + width: 20, + height: 15, + color: Colors.red, ), ), ), - // SizedBox(width: 10), - // GestureDetector( - // onTap: () => onDeleteForex(item), - // child: Tooltip( - // message: 'Delete Forex Details', - // child: Image.asset( - // 'assets/images/IconsImg/delete.png', - // width: 20, - // height: 15, - // color: Colors.red, - // ), - // ), - // ), item['forex_id'] != null ? IconButton( - icon: Icon(Icons.download, - color: Color(0xFF114D8B), size: 18), - onPressed: () { - print("PDF- ${item['forex_id']}"); - final forexIdString = item['forex_id']; - final id = int.tryParse(forexIdString ?? ''); + icon: Icon( + Icons.download, + color: Color(0xFF114D8B), + size: 18, + ), + onPressed: () { + print("PDF- ${item['forex_id']}"); + final forexIdString = item['forex_id']; + final id = int.tryParse(forexIdString ?? ''); - if (id != null) { - apiService.getForexPdfDownload(id); - } else { - print("Invalid forex_id: $forexIdString"); - } - }, - ) + if (id != null) { + apiService.getForexPdfDownload(id); + } else { + print("Invalid forex_id: $forexIdString"); + } + }, + ) : SizedBox.shrink(), // or Container() ], ), - Divider( - color: Colors.blueGrey.shade50, - ), - SizedBox(height: 4), + // Divider(color: Colors.blueGrey.shade50), + // SizedBox(height: 4), isDesktop ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - "Currency", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Duration", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Time Period ", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - // Expanded( - // flex: 2, - // child: Text( - // " Total ", - // style: TextStyle( - // fontSize: 11, fontFamily: "Archivo"), - // )), - Expanded( - flex: 2, - child: Text( - " Perdiem ", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Others ", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Total ", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Cash ", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Card ", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Comments", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - ], - ) - : SizedBox.shrink(), - isDesktop - ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - item["currency"], - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - item["duration"], - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - "${formatDate(item["start_date"]!)} - ${formatDate(item["end_date"]!)}", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - "$perdiemAmount", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - "$calculatedOtherExpenses", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - "$finalTotal", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - item["deposit_on_cash"], - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - item["deposit_on_card"], - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: _buildComments( - "Comments:", item["comments"] ?? "N/A"), - ), - ], - ): Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Top Row (Country, Currency, Total) - Wrap( - spacing: 20, // horizontal space between items - runSpacing: 10, // vertical space between rows - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - _infoBlock("Country code", item["country_code"] ?? "N/A"), - _infoBlock("Currency", item["currency"] ?? "N/A"), - _infoBlock("Total Amount", item["total_amount"]?.toString() ?? "0"), + Expanded( + flex: 2, + child: Text( + "Currency", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Duration", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Time Period ", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + // Expanded( + // flex: 2, + // child: Text( + // " Total ", + // style: TextStyle( + // fontSize: 11, fontFamily: "Archivo"), + // )), + Expanded( + flex: 2, + child: Text( + " Perdiem ", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Others ", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Total ", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Cash ", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Card ", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Comments", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), ], - ), - const SizedBox(height: 12), - - // Second Row (Start Date, End Date, Duration) - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _infoBlock("Start Date", item["start_date"] ?? "N/A"), - _infoBlock("End Date", item["end_date"] ?? "N/A"), - _infoBlock("Duration", item["duration"]?.toString() ?? "N/A"), - ], - ), - const SizedBox(height: 16), - - // Comment label - Text( - "Comment", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 8), - if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - border: Border.all(color: const Color(0xFF7098DD), width: 1), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - item["comments"] ?? "N/A", - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), - ), ) - else - const Text( "N/A", style: TextStyle(fontSize: 12), ), - ], - ), - // old code - // : Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // _buildRow( - // "Currency:", - // item["currency"], - // ), - // // SizedBox(height: 6), - // _buildRow( - // "Duration:", - // item["duration"], - // ), - // // SizedBox(height: 6), - // _buildRow("StartDate:", item["start_date"]!), - // _buildRow("EndDate:", item["end_date"]!), - // _buildRow("Perdiem:", "$perdiemAmount",), - // _buildRow("Others:", "$calculatedOtherExpenses"), - // _buildRow("Total:", "$finalTotal"), - // _buildRow("Cash:", item["deposit_on_cash"]!), - // _buildRow("Card:", item["deposit_on_card"]!), - // _buildRow("Comments:", item["comments"] ?? "N/A"), - // ], - // ), + : SizedBox.shrink(), + SizedBox(height: 8), + isDesktop + ? Row( + children: [ + Expanded( + flex: 2, + child: Text( + item["currency"], + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + item["duration"], + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + "${formatDate(item["start_date"]!)} - ${formatDate(item["end_date"]!)}", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + "$perdiemAmount", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + "$calculatedOtherExpenses", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + "$finalTotal", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + item["deposit_on_cash"], + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + item["deposit_on_card"], + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: _buildComments( + "Comments:", + item["comments"] ?? "N/A", + ), + ), + ], + ) + : Container( + color: Colors.white, + padding: const EdgeInsets.all(4.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildRow("Currency", item["currency"]), + SizedBox(height: 2), + _buildRow("Duration", item["duration"]), + SizedBox(height: 2), + _buildRow( + "Time Period", + "${formatDate(item["start_date"]!)} - ${formatDate(item["end_date"]!)}", + // "${item["start_date"]!} - ${item["end_date"]!}", + ), + SizedBox(height: 2), + _buildRow("Perdiem", "$perdiemAmount"), + SizedBox(height: 2), + _buildRow("Others", "$calculatedOtherExpenses"), + SizedBox(height: 2), + _buildRow("Total", "$finalTotal"), + SizedBox(height: 2), + _buildRow("Cash", item["deposit_on_cash"]!), + SizedBox(height: 2), + _buildRow("Card", item["deposit_on_card"]!), + SizedBox(height: 2), + _buildRow("Comments", item["comments"] ?? "N/A"), + ], + ), + ), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // // Top Row (Country, Currency, Total) + // Wrap( + // spacing: 20, // horizontal space between items + // runSpacing: 10, // vertical space between rows + // // Row( + // // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // _infoBlock( + // "Country code", + // item["country_code"] ?? "N/A", + // ), + // _infoBlock("Currency", item["currency"] ?? "N/A"), + // _infoBlock( + // "Total Amount", + // item["total_amount"]?.toString() ?? "0", + // ), + // ], + // ), + // const SizedBox(height: 12), + // + // // Second Row (Start Date, End Date, Duration) + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // _infoBlock( + // "Start Date", + // item["start_date"] ?? "N/A", + // ), + // _infoBlock("End Date", item["end_date"] ?? "N/A"), + // _infoBlock( + // "Duration", + // item["duration"]?.toString() ?? "N/A", + // ), + // ], + // ), + // const SizedBox(height: 16), + // + // // Comment label + // Text( + // "Comment", + // style: GoogleFonts.poppins( + // fontSize: 14, + // fontWeight: FontWeight.w600, + // ), + // ), + // const SizedBox(height: 8), + // if (item["comments"] != null && + // item["comments"].toString().trim().isNotEmpty) + // Container( + // width: double.infinity, + // padding: const EdgeInsets.all(12), + // decoration: BoxDecoration( + // border: Border.all( + // color: const Color(0xFF7098DD), + // width: 1, + // ), + // borderRadius: BorderRadius.circular(6), + // ), + // child: Text( + // item["comments"] ?? "N/A", + // style: GoogleFonts.poppins( + // fontSize: 12, + // color: Colors.black87, + // ), + // ), + // ) + // else + // const Text("N/A", style: TextStyle(fontSize: 12)), + // ], + // ), ], ), ), @@ -612,31 +692,35 @@ class ForexListWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: - TextStyle(color: Colors.black), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text(value.substring(0, limit) + "...", + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w600, ), - overflow: TextOverflow.ellipsis), - ) - : Text( - value, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, + overflow: TextOverflow.ellipsis, + ), + ) + : Text( + value, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), ), - ), ), ], ); @@ -660,10 +744,7 @@ class ForexListWidget extends StatelessWidget { const SizedBox(height: 4), Text( value, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black87, - ), + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), ), ], ), @@ -671,60 +752,59 @@ class ForexListWidget extends StatelessWidget { ); } - // Widget _buildRow(String title, String value) { - // // Define character limits based on title - // Map limits = { - // // "Special Request:": 30, - // "Comments:": 10, - // // Add more keys and limits if needed - // }; - // - // int limit = limits[title] ?? 50; // Default limit if title not found - // bool exceedsLimit = value.length > limit; - // - // String wrapText(String text, int maxLineLength) { - // final pattern = RegExp('.{1,$maxLineLength}(\\s+|\$)'); - // return pattern.allMatches(text).map((m) => m.group(0)!).join('\n'); - // } - // - // return Row( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Text( - // title, - // style: GoogleFonts.poppins( - // fontSize: 12, - // fontWeight: FontWeight.w600, - // ), - // ), - // SizedBox(width: 8), - // Expanded( - // child: exceedsLimit - // ? Tooltip( - // message: wrapText(value, 50), - // decoration: BoxDecoration( - // color: Colors.grey.shade200, // Black background - // borderRadius: BorderRadius.circular(6), - // ), - // textStyle: - // TextStyle(color: Colors.black), // Tooltip text color - // padding: EdgeInsets.all(8), - // preferBelow: false, - // child: Text(value.substring(0, limit) + "...", - // style: GoogleFonts.poppins( - // fontSize: 12, - // ), - // overflow: TextOverflow.ellipsis), - // ) - // : Text( - // value, - // style: GoogleFonts.poppins( - // fontSize: 12, - // ), - // ), - // ), - // ], - // ); - // } + Widget _buildRow(String title, String value) { + // Define character limits based on title + Map limits = { + // "Special Request:": 30, + "Comments:": 10, + // Add more keys and limits if needed + }; + int limit = limits[title] ?? 50; // Default limit if title not found + bool exceedsLimit = value.length > limit; + + String wrapText(String text, int maxLineLength) { + final pattern = RegExp('.{1,$maxLineLength}(\\s+|\$)'); + return pattern.allMatches(text).map((m) => m.group(0)!).join('\n'); + } + + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 8), + Expanded( + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", + style: GoogleFonts.poppins(fontSize: 12), + overflow: TextOverflow.ellipsis, + ), + ) + : Text(value, style: GoogleFonts.poppins(fontSize: 12)), + ), + ], + ); + } } diff --git a/lib/Screens/itnerary_list/insurance_list.dart b/lib/Screens/itnerary_list/insurance_list.dart index c4e3d4f..f5f9b37 100644 --- a/lib/Screens/itnerary_list/insurance_list.dart +++ b/lib/Screens/itnerary_list/insurance_list.dart @@ -4,7 +4,9 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; -class InsuranceListWidget extends StatelessWidget { +import '../../utils/auth_utils.dart'; + +class InsuranceListWidget extends StatefulWidget { final List> insuranceList; final Function(bool, Map, String) onOpen; final Function(Map) onDeleteInsurance; @@ -13,21 +15,67 @@ class InsuranceListWidget extends StatelessWidget { final Function(String, bool) onAddNew; final bool isViewMode; - const InsuranceListWidget( - {super.key, - required this.insuranceList, - required this.onOpen, - required this.apiData, - required this.onDeleteInsurance, - required this.onAddNew, - required this.isViewMode}); + const InsuranceListWidget({ + super.key, + required this.insuranceList, + required this.onOpen, + required this.apiData, + required this.onDeleteInsurance, + required this.onAddNew, + required this.isViewMode, + }); + + @override + State createState() => _InsuranceListWidgetState(); +} + +class _InsuranceListWidgetState extends State { + Color? layoutColor; + Color? secondColor; + Color? thridColor; + + @override + void initState() { + super.initState(); + loadInitialData(); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? secondString = await getSecondaryColor(); + String? thridString = await getTernaryColor(); + + // String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + secondColor = + layoutString != null + ? Color(int.parse(secondString!)) + : Colors.orange; + + thridColor = + layoutString != null + ? Color(int.parse(thridString!)) + : Colors.orangeAccent; + // bodyColor = + // bodyStringColor != null + // ? Color(int.parse(bodyStringColor)) + // : Colors.white; + }); + } @override Widget build(BuildContext context) { final isDesktop = MediaQuery.of(context).size.width > 1024; return Padding( - padding: const EdgeInsets.all(16.0), + padding: + isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0), child: Container( margin: const EdgeInsets.only(top: 16.0), child: Column( @@ -107,10 +155,10 @@ class InsuranceListWidget extends StatelessWidget { // ), // ], // ), - const SizedBox(height: 16), - // Scroll behavior based on device + // const SizedBox(height: 16), - _buildData(context, isDesktop) + // Scroll behavior based on device + _buildData(context, isDesktop), ], ), ), @@ -119,11 +167,11 @@ class InsuranceListWidget extends StatelessWidget { Widget _buildData(BuildContext context, bool isDesktop) { List> filteredList = - insuranceList.where((item) => item["is_active"] == "1").toList(); + widget.insuranceList.where((item) => item["is_active"] == "1").toList(); print("filteredList- $filteredList"); List insurancetypeList = - apiData?['insurance_type_of_insurance'] ?? []; + widget.apiData?['insurance_type_of_insurance'] ?? []; String getRequestForInsuranceType(String? specialRequestKey) { if (specialRequestKey == null) return "N/A"; @@ -146,7 +194,7 @@ class InsuranceListWidget extends StatelessWidget { String getRequestValue(String? specialRequestKey) { if (specialRequestKey == null) return "N/A"; - return (apiData?['miscellaneous_special_request'] ?? []) + return (widget.apiData?['miscellaneous_special_request'] ?? []) .firstWhere( (element) => element["dropdown_key"].toString() == specialRequestKey, @@ -177,14 +225,18 @@ class InsuranceListWidget extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), // color: Colors.orange.shade50, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 3, - offset: Offset(0, 1), - ), - ], + // color: Colors.white, + color: isDesktop ? Colors.white : thridColor, + boxShadow: + isDesktop + ? [ + BoxShadow( + color: Colors.black12, + blurRadius: 3, + offset: Offset(0, 1), + ), + ] + : [], border: Border( top: BorderSide( color: Colors.white70, // Change color to match your theme @@ -193,176 +245,207 @@ class InsuranceListWidget extends StatelessWidget { ), ), child: Padding( - padding: EdgeInsets.all(12), + padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - Text( - getRequestForInsuranceType(item["type_of_insurance"]!.toString()), - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w800, - color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) + Expanded( + flex: 1, + child: Text( + getRequestForInsuranceType( + item["type_of_insurance"]!.toString(), + ), + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: + isDesktop ? FontWeight.w800 : FontWeight.w600, + color: !isDesktop ? Colors.black : Color(0xFF575A74), + ), ), ), Spacer(), GestureDetector( - onTap: () => onOpen(true, item, "Insurance"), + onTap: () => widget.onOpen(true, item, "Insurance"), child: Tooltip( message: 'Edit Insurance Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, height: 15, - color: Color(0xFF114D8B), + color: isDesktop ? Color(0xFF114D8B) : Colors.black, + ), + ), + ), + SizedBox(width: 10), + GestureDetector( + onTap: () => widget.onDeleteInsurance(item), + child: Tooltip( + message: 'Delete Insurance Details', + child: Image.asset( + 'assets/images/IconsImg/delete.png', + width: 20, + height: 15, + color: Colors.red, ), ), ), - // SizedBox(width: 10), - // GestureDetector( - // onTap: () => onDeleteInsurance(item), - // child: Tooltip( - // message: 'Delete Insurance Details', - // child: Image.asset( - // 'assets/images/IconsImg/delete.png', - // width: 20, - // height: 15, - // color: Colors.red, - // ), - // ), - // ), ], ), SizedBox(height: 4), - Divider( - color: Colors.blueGrey.shade50, - ), - SizedBox(height: 4), + // Divider(color: Colors.blueGrey.shade50), + // SizedBox(height: 4), isDesktop ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - " InsuranceType", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Time Period ", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Comments", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - ], - ) - : SizedBox.shrink(), - isDesktop - ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - getRequestForInsuranceType( - item["type_of_insurance"]!.toString()), - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - "${formatDate(item["start_date"]!)} - ${formatDate(item["end_date"]!)}", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: _buildComments( - "Comments:", item["comments"] ?? "N/A"), - ), - ], - ) - : - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Top Row (Country, Currency, Total) - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - Wrap( - spacing: 20, // horizontal space between items - runSpacing: 10, // vertical space between rows children: [ - _infoBlock("Insurance Type", getRequestForInsuranceType(item["type_of_insurance"]!.toString()) ?? "N/A"), - _infoBlock("Start Date", formatDate(item["start_date"]!) ?? "N/A"), - _infoBlock("End Date", formatDate(item["end_date"]) ?? "N/A"), + Expanded( + flex: 2, + child: Text( + " InsuranceType", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Time Period ", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Comments", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), ], - ), - const SizedBox(height: 16), + ) + : SizedBox.shrink(), + SizedBox(height: 8), + isDesktop + ? Row( + children: [ + Expanded( + flex: 2, + child: Text( + getRequestForInsuranceType( + item["type_of_insurance"]!.toString(), + ), + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + "${formatDate(item["start_date"]!)} - ${formatDate(item["end_date"]!)}", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: _buildComments( + "Comments:", + item["comments"] ?? "N/A", + ), + ), + ], + ) + : Container( + color: Colors.white, + padding: const EdgeInsets.all(4.0), + child: Column( + children: [ + _buildRow( + "InsuranceType", + getRequestForInsuranceType( + item["type_of_insurance"]!.toString(), + ), + ), + SizedBox(width: 10), + _buildRow( + "TimePeriod", + '${formatDate(item["start_date"]!)} - ${formatDate(item["end_date"])} ', + ), - // Comment label - Text( - "Comment", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, + SizedBox(width: 10), + _buildRow("Comments", item["comments"] ?? "N/A"), + ], ), ), - const SizedBox(height: 8), - if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - border: Border.all(color: const Color(0xFF7098DD), width: 1), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - item["comments"] ?? "N/A", - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), - ), - ) - else - const Text( "N/A", style: TextStyle(fontSize: 12), ), - ], - ), + // Column( - // children: [ - // _buildRow( - // "InsuranceType:", - // getRequestForInsuranceType( - // item["type_of_insurance"]!.toString())), - // SizedBox(width: 10), - // _buildRow( - // "StartDate:", formatDate(item["start_date"]!)), - // SizedBox(width: 10), - // _buildRow("EndDate:", formatDate(item["end_date"])), - // SizedBox(width: 10), - // _buildRow("Comments:", item["comments"] ?? "N/A"), - // ], + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // // Top Row (Country, Currency, Total) + // // Row( + // // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // Wrap( + // spacing: 20, // horizontal space between items + // runSpacing: 10, // vertical space between rows + // children: [ + // _infoBlock( + // "Insurance Type", + // getRequestForInsuranceType( + // item["type_of_insurance"]!.toString(), + // ) ?? + // "N/A", + // ), + // _infoBlock( + // "Start Date", + // formatDate(item["start_date"]!) ?? "N/A", + // ), + // _infoBlock( + // "End Date", + // formatDate(item["end_date"]) ?? "N/A", + // ), + // ], + // ), + // const SizedBox(height: 16), + // + // // Comment label + // Text( + // "Comment", + // style: GoogleFonts.poppins( + // fontSize: 14, + // fontWeight: FontWeight.w600, // ), + // ), + // const SizedBox(height: 8), + // if (item["comments"] != null && + // item["comments"].toString().trim().isNotEmpty) + // Container( + // width: double.infinity, + // padding: const EdgeInsets.all(12), + // decoration: BoxDecoration( + // border: Border.all( + // color: const Color(0xFF7098DD), + // width: 1, + // ), + // borderRadius: BorderRadius.circular(6), + // ), + // child: Text( + // item["comments"] ?? "N/A", + // style: GoogleFonts.poppins( + // fontSize: 12, + // color: Colors.black87, + // ), + // ), + // ) + // else + // const Text("N/A", style: TextStyle(fontSize: 12)), + // ], + // ), ], ), ), @@ -391,31 +474,35 @@ class InsuranceListWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: - TextStyle(color: Colors.black), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text(value.substring(0, limit) + "...", + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w600, ), - overflow: TextOverflow.ellipsis), - ) - : Text( - value, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, + overflow: TextOverflow.ellipsis, + ), + ) + : Text( + value, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), ), - ), ), ], ); @@ -439,16 +526,14 @@ class InsuranceListWidget extends StatelessWidget { const SizedBox(height: 4), Text( value, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black87, - ), + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), ), ], ), ), ); } + Widget _buildRow(String title, String value) { // Define character limits based on title Map limits = { @@ -468,40 +553,39 @@ class InsuranceListWidget extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, + SizedBox( + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), ), ), SizedBox(width: 8), Expanded( - child: exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: TextStyle( - color: Colors.black, fontSize: 12), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text( - value.substring(0, limit) + "...", - style: GoogleFonts.poppins( - fontSize: 12, + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), ), - overflow: TextOverflow.ellipsis, - ), - ) - : Text( - value, - style: GoogleFonts.poppins( - fontSize: 12, - ), - ), + textStyle: TextStyle( + color: Colors.black, + fontSize: 12, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", + style: GoogleFonts.poppins(fontSize: 12), + overflow: TextOverflow.ellipsis, + ), + ) + : Text(value, style: GoogleFonts.poppins(fontSize: 12)), ), ], ); @@ -509,11 +593,11 @@ class InsuranceListWidget extends StatelessWidget { List _buildDataRows() { List> filteredList = - insuranceList.where((item) => item["is_active"] == "1").toList(); + widget.insuranceList.where((item) => item["is_active"] == "1").toList(); print("filteredList- $filteredList"); List insurancetypeList = - apiData?['insurance_type_of_insurance'] ?? []; + widget.apiData?['insurance_type_of_insurance'] ?? []; String getRequestForInsuranceType(String? specialRequestKey) { if (specialRequestKey == null) return "N/A"; @@ -529,47 +613,55 @@ class InsuranceListWidget extends StatelessWidget { return filteredList.asMap().entries.map((entry) { Map item = entry.value; - return DataRow(cells: [ - // DataCell(Text(item["indx"]?.toString() ?? "N/A")), // Index column - // DataCell(Text(item["type_of_insurance"]!)), - DataCell(Text( - getRequestForInsuranceType(item["type_of_insurance"]!.toString()))), - DataCell(Text(item["start_date"]!)), - DataCell(Text(item["end_date"]!)), - DataCell(Row( - children: [ - GestureDetector( - onTap: () => onOpen(true, item, "Insurance"), - child: Tooltip( - message: 'Edit Insurance Details', - child: Image.asset( - 'assets/images/IconsImg/edit.png', - width: 20, - height: 15, + return DataRow( + cells: [ + // DataCell(Text(item["indx"]?.toString() ?? "N/A")), // Index column + // DataCell(Text(item["type_of_insurance"]!)), + DataCell( + Text( + getRequestForInsuranceType(item["type_of_insurance"]!.toString()), + ), + ), + DataCell(Text(item["start_date"]!)), + DataCell(Text(item["end_date"]!)), + DataCell( + Row( + children: [ + GestureDetector( + onTap: () => widget.onOpen(true, item, "Insurance"), + child: Tooltip( + message: 'Edit Insurance Details', + child: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ), + ), ), - ), - ), - SizedBox(width: 10), - GestureDetector( - onTap: () => onDeleteInsurance(item), - child: Tooltip( - message: 'Delete Insurance Details', - child: Image.asset( - 'assets/images/IconsImg/delete.png', - width: 20, - height: 15, + SizedBox(width: 10), + GestureDetector( + onTap: () => widget.onDeleteInsurance(item), + child: Tooltip( + message: 'Delete Insurance Details', + child: Image.asset( + 'assets/images/IconsImg/delete.png', + width: 20, + height: 15, + ), + ), ), - ), + IconButton( + icon: Icon( + Icons.keyboard_arrow_down_outlined, + size: 28, + color: Color(0xFF475569), + ), + onPressed: () { + // Expand logic + }, + ), + ], ), - IconButton( - icon: Icon(Icons.keyboard_arrow_down_outlined, - size: 28, color: Color(0xFF475569)), - onPressed: () { - // Expand logic - }, - ), - ], - ) // Row( // children: [ @@ -593,9 +685,9 @@ class InsuranceListWidget extends StatelessWidget { // ), // ], // ) - - ), - ]); + ), + ], + ); }).toList(); } } diff --git a/lib/Screens/itnerary_list/miscellaneous_list.dart b/lib/Screens/itnerary_list/miscellaneous_list.dart index 48b79fc..50277f4 100644 --- a/lib/Screens/itnerary_list/miscellaneous_list.dart +++ b/lib/Screens/itnerary_list/miscellaneous_list.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -class MiscellaneousListWidget extends StatelessWidget { +import '../../utils/auth_utils.dart'; + +class MiscellaneousListWidget extends StatefulWidget { final List> miscellaneousList; final Function(bool, Map, String) onOpen; final Function(Map) onDeleteMiscellaneous; @@ -19,12 +21,58 @@ class MiscellaneousListWidget extends StatelessWidget { required this.isViewMode, }); + @override + State createState() => + _MiscellaneousListWidgetState(); +} + +class _MiscellaneousListWidgetState extends State { + Color? layoutColor; + Color? secondColor; + Color? thridColor; + + @override + void initState() { + super.initState(); + loadInitialData(); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? secondString = await getSecondaryColor(); + String? thridString = await getTernaryColor(); + + // String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + secondColor = + layoutString != null + ? Color(int.parse(secondString!)) + : Colors.orange; + + thridColor = + layoutString != null + ? Color(int.parse(thridString!)) + : Colors.orangeAccent; + // bodyColor = + // bodyStringColor != null + // ? Color(int.parse(bodyStringColor)) + // : Colors.white; + }); + } + @override Widget build(BuildContext context) { final isDesktop = MediaQuery.of(context).size.width > 1024; return Padding( - padding: const EdgeInsets.all(16.0), + padding: + isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0), child: Container( margin: const EdgeInsets.only(top: 16.0), child: Column( @@ -34,7 +82,7 @@ class MiscellaneousListWidget extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if ((!isDesktop) && miscellaneousList.isNotEmpty) + if ((!isDesktop) && widget.miscellaneousList.isNotEmpty) Text( " ", style: const TextStyle( @@ -44,20 +92,20 @@ class MiscellaneousListWidget extends StatelessWidget { ), MouseRegion( cursor: - isViewMode - ? SystemMouseCursors.forbidden - : SystemMouseCursors.click, + widget.isViewMode + ? SystemMouseCursors.forbidden + : SystemMouseCursors.click, child: GestureDetector( onTap: - isViewMode - ? null - : () { - print("New data"); - onAddNew("Miscellaneous", true); - }, + widget.isViewMode + ? null + : () { + print("New data"); + widget.onAddNew("Miscellaneous", true); + }, child: Row( mainAxisSize: - MainAxisSize.min, // Ensures content fits nicely + MainAxisSize.min, // Ensures content fits nicely children: [ // Text( // "Add New", @@ -133,7 +181,9 @@ class MiscellaneousListWidget extends StatelessWidget { Widget _buildData(BuildContext context, bool isDesktop) { List> filteredList = - miscellaneousList.where((item) => item["is_active"] == "1").toList(); + widget.miscellaneousList + .where((item) => item["is_active"] == "1") + .toList(); return ListView.builder( shrinkWrap: true, @@ -144,12 +194,12 @@ class MiscellaneousListWidget extends StatelessWidget { String getRequestValue(String? specialRequestKey) { if (specialRequestKey == null) return "N/A"; - return (apiData?['miscellaneous_special_request'] ?? []) + return (widget.apiData?['miscellaneous_special_request'] ?? []) .firstWhere( (element) => - element["dropdown_key"].toString() == specialRequestKey, - orElse: () => {"dropdown_value": "N/A"}, - )["dropdown_value"] + element["dropdown_key"].toString() == specialRequestKey, + orElse: () => {"dropdown_value": "N/A"}, + )["dropdown_value"] .toString(); } @@ -158,14 +208,17 @@ class MiscellaneousListWidget extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), // color: Colors.yellow.shade50, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 3, - offset: Offset(0, 1), - ), - ], + color: isDesktop ? Colors.white : thridColor, + boxShadow: + isDesktop + ? [ + BoxShadow( + color: Colors.black12, + blurRadius: 3, + offset: Offset(0, 1), + ), + ] + : [], border: Border( top: BorderSide( color: Colors.white70, // Change color to match your theme @@ -174,7 +227,7 @@ class MiscellaneousListWidget extends StatelessWidget { ), ), child: Padding( - padding: EdgeInsets.all(12), + padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -185,26 +238,28 @@ class MiscellaneousListWidget extends StatelessWidget { getRequestValue(item["special_request"]?.toString()), style: GoogleFonts.poppins( fontSize: 14, - fontWeight: FontWeight.w800, + fontWeight: + isDesktop ? FontWeight.w800 : FontWeight.w600, + color: !isDesktop ? Colors.black : Color(0xFF575A74), ), ), Spacer(), GestureDetector( - onTap: () => onOpen(true, item, "Miscellaneous"), + onTap: () => widget.onOpen(true, item, "Miscellaneous"), child: Tooltip( message: 'Edit Miscellaneous Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, height: 15, - color: Color(0xFF114D8B), + color: isDesktop ? Color(0xFF114D8B) : Colors.black, ), ), ), SizedBox(width: 10), GestureDetector( // onTap: () => onOpen(true, item, "Miscellaneous"), - onTap: () => onDeleteMiscellaneous(item), + onTap: () => widget.onDeleteMiscellaneous(item), child: Tooltip( message: 'Delete Miscellaneous Details', child: Image.asset( @@ -217,95 +272,70 @@ class MiscellaneousListWidget extends StatelessWidget { ), ], ), - Divider(color: Colors.blueGrey.shade50), + // Divider(color: Colors.blueGrey.shade50), SizedBox(height: 4), isDesktop ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - "Special Request", - style: GoogleFonts.poppins(fontSize: 11), - ), - ), - Expanded( - flex: 3, - child: Text( - " Comments", - style: GoogleFonts.poppins(fontSize: 11), - ), - ), - ], - ) - // : SizedBox.shrink(), - // isDesktop - // ? Row( - // children: [ - // Expanded( - // flex: 2, - // child: Text( - // getRequestValue( - // item["special_request"]?.toString(), - // ), - // style: GoogleFonts.poppins( - // fontSize: 12, - // fontWeight: FontWeight.w600, - // ), - // ), - // ), - // Expanded( - // flex: 3, - // child: Text( - // item["comments"], - // style: GoogleFonts.poppins( - // fontSize: 12, - // fontWeight: FontWeight.w600, - // ), - // ), - // ), - // ], - // ) - : - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Comment label - Text( - "Comment", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 8), - if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - border: Border.all(color: const Color(0xFF7098DD), width: 1), - borderRadius: BorderRadius.circular(6), + children: [ + Expanded( + flex: 2, + child: Text( + "Special Request", + style: GoogleFonts.poppins(fontSize: 11), + ), ), - child: Text( - item["comments"] ?? "N/A", - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), + Expanded( + flex: 3, + child: Text( + " Comments", + style: GoogleFonts.poppins(fontSize: 11), + ), ), - ) - else - const Text( "N/A", style: TextStyle(fontSize: 12), ), - ], - ), - // Column( - // children: [ - // _buildRow( - // "Special Request:", - // getRequestValue(item["special_request"]?.toString()), - // ), - // SizedBox(width: 10), - // _buildRow("Comments:", item["comments"] ?? "N/A"), - // ], - // ), + ], + ) + : SizedBox.shrink(), + SizedBox(height: 8), + isDesktop + ? Row( + children: [ + Expanded( + flex: 2, + child: Text( + getRequestValue( + item["special_request"]?.toString(), + ), + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + Expanded( + flex: 3, + child: Text( + item["comments"], + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ) + : Container( + color: Colors.white, + padding: const EdgeInsets.all(4.0), + child: Column( + children: [ + // _buildRow( + // "Special Request", + // getRequestValue(item["special_request"]?.toString()), + // ), + SizedBox(width: 10), + _buildRow("Comments", item["comments"] ?? "N/A"), + ], + ), + ), ], ), ), @@ -335,34 +365,34 @@ class MiscellaneousListWidget extends StatelessWidget { children: [ Expanded( child: - exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: TextStyle( - color: Colors.black, - ), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text( - value.substring(0, limit) + "...", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - overflow: TextOverflow.ellipsis, - ), - ) - : Text( - value, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + overflow: TextOverflow.ellipsis, + ), + ) + : Text( + value, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), ), ], ); @@ -387,102 +417,108 @@ class MiscellaneousListWidget extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600), + SizedBox( + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), ), SizedBox(width: 8), Expanded( child: - exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: TextStyle( - color: Colors.black, - fontSize: 12, - ), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text( - value.substring(0, limit) + "...", - overflow: TextOverflow.ellipsis, - ), - ) - : Text(value), + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + fontSize: 12, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", + overflow: TextOverflow.ellipsis, + ), + ) + : Text(value), ), ], ); } -// -// Widget _buildData(BuildContext context) { -// return Container( -// width: MediaQuery.of(context).size.width, -// child: DataTable( -// border: TableBorder( -// bottom: BorderSide(color: Colors.black12), -// horizontalInside: BorderSide(color: Colors.black12), -// ), -// columns: const [ -// DataColumn(label: Text('Special Request')), -// DataColumn(label: Text('Comments')), -// DataColumn(label: Text('Actions')), -// ], -// rows: _buildDataRows(), -// ), -// ); -// } -// -// List _buildDataRows() { -// List purposeList = apiData?['miscellaneous_special_request'] ?? []; -// -// String getRequestValue(String? specialRequestKey) { -// if (specialRequestKey == null) return "N/A"; -// return purposeList -// .firstWhere( -// (element) => -// element["dropdown_key"].toString() == specialRequestKey, -// orElse: () => {"dropdown_value": "N/A"}, -// )["dropdown_value"] -// .toString(); -// } -// -// List> filteredList = -// miscellaneousList.where((item) => item["is_active"] == "1").toList(); -// -// return filteredList.asMap().entries.map((entry) { -// Map item = entry.value; -// -// return DataRow(cells: [ -// DataCell(Text(getRequestValue(item["special_request"]?.toString()))), -// DataCell(Text(item["comments"] ?? "N/A")), -// DataCell(Row( -// children: [ -// GestureDetector( -// onTap: () => onOpen(true, item, "Miscellaneous"), -// child: Image.asset('assets/images/IconsImg/edit.png', -// width: 20, height: 15), -// ), -// SizedBox(width: 10), -// GestureDetector( -// onTap: () => onOpen(true, item, "Miscellaneous"), -// child: Image.asset('assets/images/IconsImg/delete.png', -// width: 20, height: 15), -// ), -// IconButton( -// icon: Icon(Icons.keyboard_arrow_down_outlined, -// size: 28, color: Color(0xFF475569)), -// onPressed: () { -// // Expand logic (optional) -// }, -// ), -// ], -// )), -// ]); -// }).toList(); -// } -} \ No newline at end of file + // + // Widget _buildData(BuildContext context) { + // return Container( + // width: MediaQuery.of(context).size.width, + // child: DataTable( + // border: TableBorder( + // bottom: BorderSide(color: Colors.black12), + // horizontalInside: BorderSide(color: Colors.black12), + // ), + // columns: const [ + // DataColumn(label: Text('Special Request')), + // DataColumn(label: Text('Comments')), + // DataColumn(label: Text('Actions')), + // ], + // rows: _buildDataRows(), + // ), + // ); + // } + // + // List _buildDataRows() { + // List purposeList = apiData?['miscellaneous_special_request'] ?? []; + // + // String getRequestValue(String? specialRequestKey) { + // if (specialRequestKey == null) return "N/A"; + // return purposeList + // .firstWhere( + // (element) => + // element["dropdown_key"].toString() == specialRequestKey, + // orElse: () => {"dropdown_value": "N/A"}, + // )["dropdown_value"] + // .toString(); + // } + // + // List> filteredList = + // miscellaneousList.where((item) => item["is_active"] == "1").toList(); + // + // return filteredList.asMap().entries.map((entry) { + // Map item = entry.value; + // + // return DataRow(cells: [ + // DataCell(Text(getRequestValue(item["special_request"]?.toString()))), + // DataCell(Text(item["comments"] ?? "N/A")), + // DataCell(Row( + // children: [ + // GestureDetector( + // onTap: () => onOpen(true, item, "Miscellaneous"), + // child: Image.asset('assets/images/IconsImg/edit.png', + // width: 20, height: 15), + // ), + // SizedBox(width: 10), + // GestureDetector( + // onTap: () => onOpen(true, item, "Miscellaneous"), + // child: Image.asset('assets/images/IconsImg/delete.png', + // width: 20, height: 15), + // ), + // IconButton( + // icon: Icon(Icons.keyboard_arrow_down_outlined, + // size: 28, color: Color(0xFF475569)), + // onPressed: () { + // // Expand logic (optional) + // }, + // ), + // ], + // )), + // ]); + // }).toList(); + // } +} diff --git a/lib/Screens/itnerary_list/taxi_list.dart b/lib/Screens/itnerary_list/taxi_list.dart index 3c960f3..a306df9 100644 --- a/lib/Screens/itnerary_list/taxi_list.dart +++ b/lib/Screens/itnerary_list/taxi_list.dart @@ -2,7 +2,9 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; -class TaxiListWidget extends StatelessWidget { +import '../../utils/auth_utils.dart'; + +class TaxiListWidget extends StatefulWidget { final List> taxiList; final Function(bool, Map, String) onOpen; final Function(Map) onDeleteTaxi; @@ -21,12 +23,57 @@ class TaxiListWidget extends StatelessWidget { required this.isViewMode, }); + @override + State createState() => _TaxiListWidgetState(); +} + +class _TaxiListWidgetState extends State { + Color? layoutColor; + Color? secondColor; + Color? thridColor; + + @override + void initState() { + super.initState(); + loadInitialData(); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? secondString = await getSecondaryColor(); + String? thridString = await getTernaryColor(); + + // String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + secondColor = + layoutString != null + ? Color(int.parse(secondString!)) + : Colors.orange; + + thridColor = + layoutString != null + ? Color(int.parse(thridString!)) + : Colors.orangeAccent; + // bodyColor = + // bodyStringColor != null + // ? Color(int.parse(bodyStringColor)) + // : Colors.white; + }); + } + @override Widget build(BuildContext context) { final isDesktop = MediaQuery.of(context).size.width > 1024; return Padding( - padding: const EdgeInsets.all(16.0), + padding: + isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0), child: Container( margin: const EdgeInsets.only(top: 16.0), child: Column( @@ -36,7 +83,7 @@ class TaxiListWidget extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if ((!isDesktop) && taxiList.isNotEmpty) + if ((!isDesktop) && widget.taxiList.isNotEmpty) Text( " ", style: const TextStyle( @@ -46,17 +93,17 @@ class TaxiListWidget extends StatelessWidget { ), MouseRegion( cursor: - isViewMode + widget.isViewMode ? SystemMouseCursors.forbidden : SystemMouseCursors.click, child: GestureDetector( onTap: - isViewMode + widget.isViewMode ? null : () { print("New data"); - onAddNew("Taxi", true); + widget.onAddNew("Taxi", true); }, child: Row( mainAxisSize: @@ -121,11 +168,12 @@ class TaxiListWidget extends StatelessWidget { Widget _buildData(BuildContext context, bool isDesktop) { List> filteredList = - taxiList.where((item) => item["is_active"] == "1").toList(); + widget.taxiList.where((item) => item["is_active"] == "1").toList(); print("filteredList- $filteredList"); - List taxiClassList = apiData?['taxt_car_type'] ?? []; - List taxirequiredFor = apiData?['taxi_car_required_for'] ?? []; + List taxiClassList = widget.apiData?['taxt_car_type'] ?? []; + List taxirequiredFor = + widget.apiData?['taxi_car_required_for'] ?? []; String getRequestForTaxiClass(String? specialRequestKey) { if (specialRequestKey == null) return "N/A"; @@ -228,14 +276,17 @@ class TaxiListWidget extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), // color: Colors.orange.shade50, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 3, - offset: Offset(0, 1), - ), - ], + color: isDesktop ? Colors.white : thridColor, + boxShadow: + isDesktop + ? [ + BoxShadow( + color: Colors.black12, + blurRadius: 3, + offset: Offset(0, 1), + ), + ] + : [], border: Border( top: BorderSide( color: Colors.white70, // Change color to match your theme @@ -244,37 +295,41 @@ class TaxiListWidget extends StatelessWidget { ), ), child: Padding( - padding: EdgeInsets.all(12), + padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - Text( - "${getRequestForTaxiClass(item["car_type"]!.toString())} For ${item["no_of_passengers"]!} Passenger", - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w800, - color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) + Expanded( + flex: 1, + child: Text( + "${getRequestForTaxiClass(item["car_type"]!.toString())} For ${item["no_of_passengers"]!} Passenger", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: + isDesktop ? FontWeight.w800 : FontWeight.w600, + color: !isDesktop ? Colors.black : Color(0xFF575A74), + ), ), ), Spacer(), GestureDetector( - onTap: () => onOpen(true, item, "Taxi"), + onTap: () => widget.onOpen(true, item, "Taxi"), child: Tooltip( message: 'Edit Taxi Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, height: 15, - color: Color(0xFF114D8B), + color: isDesktop ? Color(0xFF114D8B) : Colors.black, ), ), ), SizedBox(width: 10), GestureDetector( - onTap: () => onDeleteTaxi(item), + onTap: () => widget.onDeleteTaxi(item), child: Tooltip( message: 'Delete Taxi Details', child: Image.asset( @@ -287,7 +342,7 @@ class TaxiListWidget extends StatelessWidget { ), ], ), - Divider(color: Colors.blueGrey.shade50), + // Divider(color: Colors.blueGrey.shade50), SizedBox(height: 4), isDesktop ? Row( @@ -323,7 +378,8 @@ class TaxiListWidget extends StatelessWidget { ], ) : SizedBox.shrink(), - SizedBox(height: 4), + SizedBox(height: 8), + isDesktop ? Row( children: [ @@ -369,72 +425,75 @@ class TaxiListWidget extends StatelessWidget { ), ], ) - : - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // First row: City & Location - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _infoColumn("City", item["destination_city"] ?? "N/A"), - _infoColumn("Location", item["location_of_pickup"] ?? "N/A",alignEnd: true), - ], + : Container( + color: Colors.white, + padding: const EdgeInsets.all(4.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildRow("City", item["destination_city"]), + SizedBox(width: 10), + _buildRow("Location", item["location_of_pickup"]!), + SizedBox(width: 10), + _buildDateTimeRow( + "Date", + formatDate(item["date"]!), + formatTime(item["time"]!), ), - const SizedBox(height: 16), + _buildRow("Comments", item["comments"] ?? "N/A"), + ], + ), - // Second row: Date & Time - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _infoColumn("Date", "${formatDate(item["date"]!)}" ?? "N/A"), - _infoColumn("Time", "${formatTime(item["time"]!)}" ?? "N/A",alignEnd: true), - ], - ), - const SizedBox(height: 16), - - // Comment label - Text( - "Comment", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 8), - - // Comment box - if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - border: Border.all(color: const Color(0xFF7098DD), width: 1), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - item["comments"] ?? "N/A", - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), - ), - )else const Text( "N/A", style: TextStyle(fontSize: 12), ), - - ] ) - // Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // _buildRow("City:", item["destination_city"]), - // SizedBox(width: 10), - // _buildRow("Pickup:", item["location_of_pickup"]!), - // SizedBox(width: 10), - // _buildDateTimeRow( - // "Date:", - // formatDate(item["date"]!), - // formatTime(item["time"]!), - // ), - // _buildRow("TaxiFor:", item["car_required_for"]!), - // _buildRow("Comments:", item["comments"] ?? "N/A"), - // ], - // ), + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // // First row: City & Location + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // _infoColumn("City", item["destination_city"] ?? "N/A"), + // _infoColumn("Location", item["location_of_pickup"] ?? "N/A",alignEnd: true), + // ], + // ), + // const SizedBox(height: 16), + // + // // Second row: Date & Time + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // _infoColumn("Date", "${formatDate(item["date"]!)}" ?? "N/A"), + // _infoColumn("Time", "${formatTime(item["time"]!)}" ?? "N/A",alignEnd: true), + // ], + // ), + // const SizedBox(height: 16), + // + // // Comment label + // Text( + // "Comment", + // style: GoogleFonts.poppins( + // fontSize: 14, + // fontWeight: FontWeight.w600, + // ), + // ), + // const SizedBox(height: 8), + // + // // Comment box + // if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) + // Container( + // width: double.infinity, + // padding: const EdgeInsets.all(12), + // decoration: BoxDecoration( + // border: Border.all(color: const Color(0xFF7098DD), width: 1), + // borderRadius: BorderRadius.circular(6), + // ), + // child: Text( + // item["comments"] ?? "N/A", + // style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), + // ), + // )else const Text( "N/A", style: TextStyle(fontSize: 12), ), + // + // ] ), + ), ], ), ), @@ -516,9 +575,12 @@ class TaxiListWidget extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: TextStyle(fontWeight: FontWeight.w600, fontSize: 12), + SizedBox( + width: 100, + child: Text( + title, + style: TextStyle(fontWeight: FontWeight.w600, fontSize: 12), + ), ), SizedBox(width: 8), Expanded( @@ -551,9 +613,15 @@ class TaxiListWidget extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600), + SizedBox( + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), ), SizedBox(width: 8), Expanded( @@ -562,30 +630,27 @@ class TaxiListWidget extends StatelessWidget { ], ); } - Widget _infoColumn(String label, String value, {bool alignEnd = false}) { - return Column( - // crossAxisAlignment: CrossAxisAlignment.start, - crossAxisAlignment: - alignEnd ? CrossAxisAlignment.end : CrossAxisAlignment.start, - children: [ - Text( - label, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Colors.black87, - ), - ), - const SizedBox(height: 4), - Text( - value, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black87, - ), - ), - ], - ); - } + Widget _infoColumn(String label, String value, {bool alignEnd = false}) { + return Column( + // crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + alignEnd ? CrossAxisAlignment.end : CrossAxisAlignment.start, + children: [ + Text( + label, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Colors.black87, + ), + ), + const SizedBox(height: 4), + Text( + value, + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), + ), + ], + ); + } } diff --git a/lib/Screens/itnerary_list/train_list.dart b/lib/Screens/itnerary_list/train_list.dart index d4f039f..5c422ee 100644 --- a/lib/Screens/itnerary_list/train_list.dart +++ b/lib/Screens/itnerary_list/train_list.dart @@ -3,6 +3,7 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; import '../../services/apiService.dart'; +import '../../utils/auth_utils.dart'; class TrainListWidget extends StatefulWidget { final bool hasAction; @@ -36,12 +37,46 @@ class _TrainListWidgetState extends State { // late Map countryMap; Map countryMap = {}; + Color? layoutColor; + Color? secondColor; + Color? thridColor; + @override void initState() { super.initState(); + loadInitialData(); loadCountryList(); // Call your method here } + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? secondString = await getSecondaryColor(); + String? thridString = await getTernaryColor(); + + // String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + secondColor = + layoutString != null + ? Color(int.parse(secondString!)) + : Colors.orange; + + thridColor = + layoutString != null + ? Color(int.parse(thridString!)) + : Colors.orangeAccent; + // bodyColor = + // bodyStringColor != null + // ? Color(int.parse(bodyStringColor)) + // : Colors.white; + }); + } + void checkClass() { if (widget.hasAction) { if (widget.tripType?.isNotEmpty == true) { @@ -99,7 +134,8 @@ class _TrainListWidgetState extends State { final isDesktop = MediaQuery.of(context).size.width > 1024; return Padding( - padding: const EdgeInsets.all(16.0), + padding: + isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0), child: Container( margin: const EdgeInsets.only(top: 16.0), child: Column( @@ -315,14 +351,17 @@ class _TrainListWidgetState extends State { decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), // color: Colors.orange.shade50, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 3, - offset: Offset(0, 1), - ), - ], + color: isDesktop ? Colors.white : thridColor, + boxShadow: + isDesktop + ? [ + BoxShadow( + color: Colors.black12, + blurRadius: 3, + offset: Offset(0, 1), + ), + ] + : [], border: Border( top: BorderSide( color: Colors.white70, // Change color to match your theme @@ -331,7 +370,7 @@ class _TrainListWidgetState extends State { ), ), child: Padding( - padding: EdgeInsets.all(12), + padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -343,7 +382,8 @@ class _TrainListWidgetState extends State { style: GoogleFonts.poppins( fontSize: 14, fontWeight: FontWeight.w800, - color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) + color: + !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74), ), ), Spacer(), @@ -355,7 +395,7 @@ class _TrainListWidgetState extends State { 'assets/images/IconsImg/edit.png', width: 20, height: 15, - color: Color(0xFF114D8B), + color: isDesktop ? Color(0xFF114D8B) : Colors.black, ), ), ), @@ -374,7 +414,7 @@ class _TrainListWidgetState extends State { ), ], ), - Divider(color: Colors.blueGrey.shade50), + // Divider(color: Colors.blueGrey.shade50), SizedBox(height: 4), isDesktop ? Row( @@ -382,7 +422,7 @@ class _TrainListWidgetState extends State { Expanded( flex: 2, child: Text( - " Class", + "Class", style: GoogleFonts.poppins(fontSize: 11), ), ), @@ -410,7 +450,7 @@ class _TrainListWidgetState extends State { ], ) : SizedBox.shrink(), - SizedBox(height: 4), + SizedBox(height: 8), isDesktop ? Row( children: [ @@ -539,72 +579,102 @@ class _TrainListWidgetState extends State { ), ], ) - : - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // First row: City & Location - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + : Container( + color: Colors.white, + padding: const EdgeInsets.all(4.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - _infoColumn("Class", getRequestForTrainClass(item["class"]!.toString()) ?? "N/A"), - _infoColumn("From", item["from_station"]! ?? "N/A"), - _infoColumn("To", item["to_station"]! ?? "N/A",alignEnd: true), + _buildRow( + "Class", + getRequestForTrainClass(item["class"]!.toString()), + ), + _buildRow("From", item["from_station"]!), + _buildRow("To", item["to_station"]!), + _buildDateTimeRow( + "Date", + formatDate(item["date"]!), + formatTime(item["time"]!), + ), + _buildRow("Comments", item["comments"] ?? "N/A"), ], ), - const SizedBox(height: 16), + ), - // Second row: Date & Time - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _infoColumn("Date", "${formatDate(item["date"]!)}" ?? "N/A"), - _infoColumn("Time", "${formatTime(item["time"]!)}" ?? "N/A",alignEnd: true), - ], - ), - const SizedBox(height: 16), - - // Comment label - Text( - "Comment", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 8), - - // Comment box - if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - border: Border.all(color: const Color(0xFF7098DD), width: 1), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - item["comments"] ?? "N/A", - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), - ), - )else const Text( "N/A", style: TextStyle(fontSize: 12), ), - - ] ) // Column( // crossAxisAlignment: CrossAxisAlignment.start, // children: [ - // _buildRow( - // "Class:", - // getRequestForTrainClass(item["class"]!.toString()), + // // First row: City & Location + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // _infoColumn( + // "Class", + // getRequestForTrainClass( + // item["class"]!.toString(), + // ) ?? + // "N/A", + // ), + // _infoColumn("From", item["from_station"]! ?? "N/A"), + // _infoColumn( + // "To", + // item["to_station"]! ?? "N/A", + // alignEnd: true, + // ), + // ], // ), - // _buildRow("From:", item["from_station"]!), - // _buildRow("To:", item["to_station"]!), - // _buildDateTimeRow( - // "Date:", - // formatDate(item["date"]!), - // formatTime(item["time"]!), + // const SizedBox(height: 16), + // + // // Second row: Date & Time + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // _infoColumn( + // "Date", + // "${formatDate(item["date"]!)}" ?? "N/A", + // ), + // _infoColumn( + // "Time", + // "${formatTime(item["time"]!)}" ?? "N/A", + // alignEnd: true, + // ), + // ], // ), - // _buildRow("Comments:", item["comments"] ?? "N/A"), + // const SizedBox(height: 16), + // + // // Comment label + // Text( + // "Comment", + // style: GoogleFonts.poppins( + // fontSize: 14, + // fontWeight: FontWeight.w600, + // ), + // ), + // const SizedBox(height: 8), + // + // // Comment box + // if (item["comments"] != null && + // item["comments"].toString().trim().isNotEmpty) + // Container( + // width: double.infinity, + // padding: const EdgeInsets.all(12), + // decoration: BoxDecoration( + // border: Border.all( + // color: const Color(0xFF7098DD), + // width: 1, + // ), + // borderRadius: BorderRadius.circular(6), + // ), + // child: Text( + // item["comments"] ?? "N/A", + // style: GoogleFonts.poppins( + // fontSize: 12, + // color: Colors.black87, + // ), + // ), + // ) + // else + // const Text("N/A", style: TextStyle(fontSize: 12)), // ], // ), ], @@ -690,9 +760,15 @@ class _TrainListWidgetState extends State { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600), + SizedBox( + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), ), SizedBox(width: 8), Expanded( @@ -725,7 +801,7 @@ class _TrainListWidgetState extends State { return Column( // crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: - alignEnd ? CrossAxisAlignment.end : CrossAxisAlignment.start, + alignEnd ? CrossAxisAlignment.end : CrossAxisAlignment.start, children: [ Text( label, @@ -738,21 +814,22 @@ class _TrainListWidgetState extends State { const SizedBox(height: 4), Text( value, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black87, - ), + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), ), ], ); } + Widget _buildDateTimeRow(String title, String date, String time) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: TextStyle(fontWeight: FontWeight.w600, fontSize: 12), + SizedBox( + width: 100, + child: Text( + title, + style: TextStyle(fontWeight: FontWeight.w600, fontSize: 12), + ), ), SizedBox(width: 8), Expanded(child: Text("$date, $time", style: TextStyle(fontSize: 12))), diff --git a/lib/Screens/itnerary_list/visa_list.dart b/lib/Screens/itnerary_list/visa_list.dart index 93f1a31..d575628 100644 --- a/lib/Screens/itnerary_list/visa_list.dart +++ b/lib/Screens/itnerary_list/visa_list.dart @@ -2,7 +2,9 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; -class VisaListWidget extends StatelessWidget { +import '../../utils/auth_utils.dart'; + +class VisaListWidget extends StatefulWidget { final List> visaList; final Function(bool, Map, String) onOpen; final Function(Map) onDeleteMiscellaneous; @@ -12,91 +14,138 @@ class VisaListWidget extends StatelessWidget { final Function(String, bool) onAddNew; final bool isViewMode; - const VisaListWidget( - {super.key, - required this.visaList, - required this.onOpen, - required this.onDeleteMiscellaneous, - required this.apiData, - required this.apiCountryData, - required this.onAddNew, - required this.isViewMode}); + const VisaListWidget({ + super.key, + required this.visaList, + required this.onOpen, + required this.onDeleteMiscellaneous, + required this.apiData, + required this.apiCountryData, + required this.onAddNew, + required this.isViewMode, + }); + + State createState() => _VisaListWidgetState(); +} + +class _VisaListWidgetState extends State { + Color? layoutColor; + Color? secondColor; + Color? thridColor; + + @override + void initState() { + super.initState(); + loadInitialData(); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? secondString = await getSecondaryColor(); + String? thridString = await getTernaryColor(); + + // String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + secondColor = + layoutString != null + ? Color(int.parse(secondString!)) + : Colors.orange; + + thridColor = + layoutString != null + ? Color(int.parse(thridString!)) + : Colors.orangeAccent; + // bodyColor = + // bodyStringColor != null + // ? Color(int.parse(bodyStringColor)) + // : Colors.white; + }); + } @override Widget build(BuildContext context) { final isDesktop = MediaQuery.of(context).size.width > 1024; return Padding( - padding: const EdgeInsets.all(16.0), + padding: + isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0), child: Container( margin: const EdgeInsets.only(top: 16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Header with title and button - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if ((!isDesktop) && visaList.isNotEmpty) - Text( - " ", - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - MouseRegion( - cursor: isViewMode - ? SystemMouseCursors.forbidden - : SystemMouseCursors.click, + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // if ((!isDesktop) && widget.visaList.isNotEmpty) + // Text( + // " ", + // style: const TextStyle( + // fontSize: 18, + // fontWeight: FontWeight.bold, + // ), + // ), + // MouseRegion( + // cursor: + // widget.isViewMode + // ? SystemMouseCursors.forbidden + // : SystemMouseCursors.click, + // + // child: GestureDetector( + // onTap: + // widget.isViewMode + // ? null + // : () { + // print("New data"); + // widget.onAddNew("Visa", true); + // }, + // child: Row( + // mainAxisSize: + // MainAxisSize.min, // Ensures content fits nicely + // children: [ + // // Text( + // // "Add New", + // // style: TextStyle(fontSize: 13), + // // ), + // // SizedBox(width: 8), // spacing between icon and text + // // Icon( + // // Icons.add_circle_sharp, + // // size: 30, + // // color: Color(0xFF114D8B), + // // ) + // ], + // ), + // ), + // // onPressed: isViewMode + // // ? null + // // : () { + // // print("New data"); + // // + // // }, + // // child: Row( + // // mainAxisSize: MainAxisSize.min, + // // children: [ + // // Icon( + // // Icons.add_circle_sharp, + // // size: 30, + // // color: Color(0xFF114D8B), + // // ) + // // ], + // // ), + // ), + // ], + // ), + // const SizedBox(height: 16), - child: GestureDetector( - onTap: isViewMode - ? null - : () { - print("New data"); - onAddNew("Visa", true); - }, - child: Row( - mainAxisSize: - MainAxisSize.min, // Ensures content fits nicely - children: [ - // Text( - // "Add New", - // style: TextStyle(fontSize: 13), - // ), - // SizedBox(width: 8), // spacing between icon and text - // Icon( - // Icons.add_circle_sharp, - // size: 30, - // color: Color(0xFF114D8B), - // ) - ], - ), - ), - // onPressed: isViewMode - // ? null - // : () { - // print("New data"); - // - // }, - // child: Row( - // mainAxisSize: MainAxisSize.min, - // children: [ - // Icon( - // Icons.add_circle_sharp, - // size: 30, - // color: Color(0xFF114D8B), - // ) - // ], - // ), - ), - ], - ), - const SizedBox(height: 16), // Scroll behavior based on device - - _buildData(context, isDesktop) + _buildData(context, isDesktop), ], ), ), @@ -191,11 +240,11 @@ class VisaListWidget extends StatelessWidget { Widget _buildData(BuildContext context, bool isDesktop) { List> filteredList = - visaList.where((item) => item["is_active"] == "1").toList(); + widget.visaList.where((item) => item["is_active"] == "1").toList(); print("filteredList- $filteredList"); - List visatypeList = apiData?['visa_type_of_visa'] ?? []; - List countryList = apiCountryData ?? []; + List visatypeList = widget.apiData?['visa_type_of_visa'] ?? []; + List countryList = widget.apiCountryData ?? []; String getRequestForVisa(String? specialRequestKey) { if (specialRequestKey == null) return "N/A"; @@ -249,8 +298,11 @@ class VisaListWidget extends StatelessWidget { if (hour == 24 && minute == 0) { // 24:00 is treated as 00:00 on the next day - dateTime = DateTime(now.year, now.month, now.day) - .add(const Duration(days: 1)); + dateTime = DateTime( + now.year, + now.month, + now.day, + ).add(const Duration(days: 1)); } else { if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { throw FormatException("Invalid hour or minute"); @@ -276,14 +328,17 @@ class VisaListWidget extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), // color: Colors.orange.shade50, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 3, - offset: Offset(0, 1), - ), - ], + color: isDesktop ? Colors.white : thridColor, + boxShadow: + isDesktop + ? [ + BoxShadow( + color: Colors.black12, + blurRadius: 3, + offset: Offset(0, 1), + ), + ] + : [], border: Border( top: BorderSide( color: Colors.white70, // Change color to match your theme @@ -292,7 +347,7 @@ class VisaListWidget extends StatelessWidget { ), ), child: Padding( - padding: EdgeInsets.all(12), + padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -303,26 +358,27 @@ class VisaListWidget extends StatelessWidget { getRequestForVisa(item["type_of_visa"]!.toString()), style: GoogleFonts.poppins( fontSize: 14, - fontWeight: FontWeight.w800, - color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) + fontWeight: + isDesktop ? FontWeight.w800 : FontWeight.w600, + color: !isDesktop ? Colors.black : Color(0xFF575A74), ), ), Spacer(), GestureDetector( - onTap: () => onOpen(true, item, "Visa"), + onTap: () => widget.onOpen(true, item, "Visa"), child: Tooltip( message: 'Edit Visa Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, height: 15, - color: Color(0xFF114D8B), + color: isDesktop ? Color(0xFF114D8B) : Colors.black, ), ), ), SizedBox(width: 10), GestureDetector( - onTap: () => onDeleteMiscellaneous(item), + onTap: () => widget.onDeleteMiscellaneous(item), child: Tooltip( message: 'Delete Visa Details', child: Image.asset( @@ -335,155 +391,180 @@ class VisaListWidget extends StatelessWidget { ), ], ), - Divider( - color: Colors.blueGrey.shade50, - ), + // Divider(color: Colors.blueGrey.shade50), SizedBox(height: 4), isDesktop ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - " Country", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Visa Type", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Date", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - Expanded( - flex: 2, - child: Text( - " Comments", - style: GoogleFonts.poppins( - fontSize: 11, - ), - )), - ], - ) + children: [ + Expanded( + flex: 2, + child: Text( + " Country", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Visa Type", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Date", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + Expanded( + flex: 2, + child: Text( + " Comments", + style: GoogleFonts.poppins(fontSize: 11), + ), + ), + ], + ) : SizedBox.shrink(), + SizedBox(height: 8), isDesktop ? Row( - children: [ - Expanded( - flex: 2, - child: Text( - getRequestForCountry( - item["country_code"]!.toString()), - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - getRequestForVisa( - item["type_of_visa"]!.toString()), - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: Text( - formatDate(item["start_date"]!), - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - SizedBox(width: 10), - Expanded( - flex: 2, - child: _buildComments( - "Comments:", item["comments"] ?? "N/A"), - ), - ], - ) - : - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Top Row (Country, Currency, Total) - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - Wrap( - spacing: 20, // horizontal space between items - runSpacing: 10, // vertical space between rows children: [ - _infoBlock("Visa Type", getRequestForCountry(item["country_code"]!.toString()) ?? "N/A"), - _infoBlock("Country", getRequestForCountry(item["country_code"]!.toString()) ?? "N/A"), - _infoBlock("Start Date", formatDate(item["start_date"]!) ?? "N/A"), + Expanded( + flex: 2, + child: Text( + getRequestForCountry( + item["country_code"]!.toString(), + ), + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + getRequestForVisa(item["type_of_visa"]!.toString()), + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: Text( + formatDate(item["start_date"]!), + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox(width: 10), + Expanded( + flex: 2, + child: _buildComments( + "Comments:", + item["comments"] ?? "N/A", + ), + ), ], - ), - const SizedBox(height: 16), - - // Comment label - Text( - "Comment", - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, + ) + : Container( + color: Colors.white, + padding: const EdgeInsets.all(4.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildRow( + "VisaType", + getRequestForVisa(item["type_of_visa"]!.toString()), + ), + SizedBox(height: 6), + _buildRow( + "Country", + getRequestForCountry( + item["country_code"]!.toString(), + ), + ), + SizedBox(height: 6), + _buildRow("StartDate", item["start_date"]!), + SizedBox(height: 6), + _buildRow("Comments", item["comments"] ?? "N/A"), + ], ), ), - const SizedBox(height: 8), - if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty) - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - border: Border.all(color: const Color(0xFF7098DD), width: 1), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - item["comments"] ?? "N/A", - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), - ), - ) - else - const Text( "N/A", style: TextStyle(fontSize: 12), ), - ], - ), + // Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // _buildRow( - // "VisaType:", - // getRequestForVisa( - // item["type_of_visa"]!.toString())), - // SizedBox(height: 6), - // _buildRow( - // "Country:", - // getRequestForCountry( - // item["country_code"]!.toString())), - // SizedBox(height: 6), - // _buildRow("StartDate:", item["start_date"]!), - // SizedBox(height: 6), - // _buildRow("Comments:", item["comments"] ?? "N/A"), - // ], + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // // Top Row (Country, Currency, Total) + // // Row( + // // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // Wrap( + // spacing: 20, // horizontal space between items + // runSpacing: 10, // vertical space between rows + // children: [ + // _infoBlock( + // "Visa Type", + // getRequestForCountry( + // item["country_code"]!.toString(), + // ) ?? + // "N/A", + // ), + // _infoBlock( + // "Country", + // getRequestForCountry( + // item["country_code"]!.toString(), + // ) ?? + // "N/A", + // ), + // _infoBlock( + // "Start Date", + // formatDate(item["start_date"]!) ?? "N/A", + // ), + // ], + // ), + // const SizedBox(height: 16), + // + // // Comment label + // Text( + // "Comment", + // style: GoogleFonts.poppins( + // fontSize: 14, + // fontWeight: FontWeight.w600, // ), + // ), + // const SizedBox(height: 8), + // if (item["comments"] != null && + // item["comments"].toString().trim().isNotEmpty) + // Container( + // width: double.infinity, + // padding: const EdgeInsets.all(12), + // decoration: BoxDecoration( + // border: Border.all( + // color: const Color(0xFF7098DD), + // width: 1, + // ), + // borderRadius: BorderRadius.circular(6), + // ), + // child: Text( + // item["comments"] ?? "N/A", + // style: GoogleFonts.poppins( + // fontSize: 12, + // color: Colors.black87, + // ), + // ), + // ) + // else + // const Text("N/A", style: TextStyle(fontSize: 12)), + // ], + // ), ], ), ), @@ -512,31 +593,37 @@ class VisaListWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: - TextStyle(color: Colors.black), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text(value.substring(0, limit) + "...", + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - fontFamily: "Archivo"), - overflow: TextOverflow.ellipsis), - ) - : Text( - value, - style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + fontFamily: "Archivo", + ), + overflow: TextOverflow.ellipsis, + ), + ) + : Text( + value, + style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, - fontFamily: "Archivo"), - ), + fontFamily: "Archivo", + ), + ), ), ], ); @@ -560,16 +647,14 @@ class VisaListWidget extends StatelessWidget { const SizedBox(height: 4), Text( value, - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black87, - ), + style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), ), ], ), ), ); } + Widget _buildRow(String title, String value) { // Define character limits based on title Map limits = { @@ -589,34 +674,38 @@ class VisaListWidget extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - title, - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, + SizedBox( + width: 100, + child: Text( + title, + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + ), ), ), SizedBox(width: 8), Expanded( - child: exceedsLimit - ? Tooltip( - message: wrapText(value, 50), - decoration: BoxDecoration( - color: Colors.grey.shade200, // Black background - borderRadius: BorderRadius.circular(6), - ), - textStyle: - TextStyle(color: Colors.black), // Tooltip text color - padding: EdgeInsets.all(8), - preferBelow: false, - child: Text(value.substring(0, limit) + "...", + child: + exceedsLimit + ? Tooltip( + message: wrapText(value, 50), + decoration: BoxDecoration( + color: Colors.grey.shade200, // Black background + borderRadius: BorderRadius.circular(6), + ), + textStyle: TextStyle( + color: Colors.black, + ), // Tooltip text color + padding: EdgeInsets.all(8), + preferBelow: false, + child: Text( + value.substring(0, limit) + "...", style: TextStyle(fontSize: 12), - overflow: TextOverflow.ellipsis), - ) - : Text( - value, - style: TextStyle(fontSize: 12), - ), + overflow: TextOverflow.ellipsis, + ), + ) + : Text(value, style: TextStyle(fontSize: 12)), ), ], ); diff --git a/lib/Screens/myTemplates/templateForex.dart b/lib/Screens/myTemplates/templateForex.dart index 8dfb1af..9fa8287 100644 --- a/lib/Screens/myTemplates/templateForex.dart +++ b/lib/Screens/myTemplates/templateForex.dart @@ -578,8 +578,6 @@ class TemplateForexState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - - Row( children: [ Container( @@ -587,15 +585,13 @@ class TemplateForexState extends State { isDesktop: isDesktop, breadcrumbItems: [ BreadcrumbItem( - title: 'Org Settings', - tooltip: 'Go To Organization Settings', - onTap: (context) { - context.go("/OrganizationSettings"); - } - ), - BreadcrumbItem( - title: 'Forex', + title: 'Org Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + }, ), + BreadcrumbItem(title: 'Forex'), ], ), ), @@ -788,7 +784,7 @@ class TemplateForexState extends State { ), Container( padding: const EdgeInsets.all(16), - height: MediaQuery.of(context).size.height * 0.5, + height: MediaQuery.of(context).size.height * 0.45, decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), border: Border.all(color: Color(0xFFD6D5E6), width: 0.5), @@ -862,17 +858,18 @@ class TemplateForexState extends State { SizedBox(width: 10), SizedBox( child: ElevatedButton( - onPressed: isDisable - ? null - : () async { - setState(() { - isDisable = true; - }); + onPressed: + isDisable + ? null + : () async { + setState(() { + isDisable = true; + }); - await handleSubmit(); - // You can get text from commentController.text - // Navigator.of(context).pop(); // Close the modal - }, + await handleSubmit(); + // You can get text from commentController.text + // Navigator.of(context).pop(); // Close the modal + }, style: ElevatedButton.styleFrom( backgroundColor: layoutColor, // backgroundColor: widget.layoutColor, diff --git a/lib/Screens/organization/orgSetup.dart b/lib/Screens/organization/orgSetup.dart index 4eb929d..096d91f 100644 --- a/lib/Screens/organization/orgSetup.dart +++ b/lib/Screens/organization/orgSetup.dart @@ -1131,7 +1131,7 @@ class _OrgSetUpState extends State { padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), onPressed: () { - context.go('/listPlan'); + context.go('/OrganizationSettings'); }, child: Text("Cancel", style: GoogleFonts.poppins(fontSize: 12)), ), diff --git a/lib/Screens/organization/themeColor.dart b/lib/Screens/organization/themeColor.dart index 524ce0f..6317ae9 100644 --- a/lib/Screens/organization/themeColor.dart +++ b/lib/Screens/organization/themeColor.dart @@ -58,6 +58,21 @@ class _ColorThemePickerWidgetState extends State { ]; final List layoutTertiaryColors = [ + Color(0xFFE5EFFF), // Very Light Blue + Color(0xFFE6FDFF), // Very Light Teal + Color(0xFFE8FDEF), // Mint Green + Color(0xFFFFE7E6), // Light Coral/Red + Color(0xFFFDE9E7), // Peach + Color(0xFFFFF5E5), // Lightest Orange + Color(0xFFECEEF8), // Very Light Rose + Color(0xFFE5FFFC), // Pastel Pink + Color(0xFFFEE6F3), // Light Lavender + Color(0xFFF9EBF3), // Soft Purple Grey + Color(0xFFF8EAFA), // Near-white Neutral + Color(0xFFF4EDF7), // Near-white Neutral + ]; + + final List layoutTertiaryColors1 = [ Color(0xFFE3F2FD), // Very Light Blue Color(0xFFE0F7FA), // Very Light Teal Color(0xFFC8E6C9), // Mint Green @@ -67,7 +82,7 @@ class _ColorThemePickerWidgetState extends State { Color(0xFFFFEBEE), // Very Light Rose Color(0xFFFCE4EC), // Pastel Pink Color(0xFFF3E5F5), // Light Lavender - Color(0xFFEDE7F6), // Soft Purple Grey + Color(0xFFF9EBF3), // Soft Purple Grey Color(0xFFF8F9FA), // Near-white Neutral ]; diff --git a/lib/Screens/plans/create_plans.dart b/lib/Screens/plans/create_plans.dart index 360f918..35b6cb5 100644 --- a/lib/Screens/plans/create_plans.dart +++ b/lib/Screens/plans/create_plans.dart @@ -446,10 +446,12 @@ class CreateNewPlansState extends State { String? _selectedIsBillable; String? selectedFuncDept; String? selectedPurpose; + bool hasUpdateVal = false; Map validationErrors = {}; - List> miscellaneousList = []; + // List> miscellaneousList = [{"special_request": 1, "comments": "posta", "indx": 1}]; + List> miscellaneousList = []; List> visaList = []; List> insuranceList = []; List> accommodationList = []; @@ -562,6 +564,10 @@ class CreateNewPlansState extends State { loadInitialData(); }); + // if (widget.selectedPlanData != null) { + // hasUpdateVal = true; + // } + if (widget.approverStatus == "Approval pending") { print("Status approver - Approval Pending"); } @@ -656,6 +662,8 @@ class CreateNewPlansState extends State { planTravlrId = travellerId; _selectedOption = "Option 3"; otherUserName = travellerName; + + hasUpdateVal = true; } else if (userId.isNotEmpty && userId != "0") { print("TestplanUsrId : $userId"); print("TestplanUsrIdSelf : $selfId"); @@ -663,6 +671,7 @@ class CreateNewPlansState extends State { print("TestplanUsrId2 : $planUsrId"); _selectedOption = (selfId != userId) ? "Option 2" : "Option 1"; otherUserName = userName; + hasUpdateVal = true; } }); } @@ -1316,6 +1325,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 +1909,7 @@ class CreateNewPlansState extends State { onItineraryUpdate: handleItineraryUpdate, onExeptionalClass: handleExcentionalClass, loginUser: selfId, + selectedPlanData: planData, isViewMode: widget.isViewMode, ), @@ -1945,12 +2005,49 @@ class CreateNewPlansState extends State { focusStates["trip_typeFocused"] = hasFocus; }); }, + 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; + }, + enabled: !hasUpdateVal, popupProps: PopupProps.menu( showSearchBox: false, // Optionally enable search fit: FlexFit.loose, @@ -2045,6 +2142,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 = @@ -2058,6 +2165,7 @@ class CreateNewPlansState extends State { fetchTrainFlightClass( int.parse(_selectedTripType!), ); + dynamicItineraryKey.currentState ?.updateSelectedServices(); }); @@ -3073,6 +3181,7 @@ class CreateNewPlansState extends State { {"title": "Others (Non Employee)", "value": "Option 3"}, ]; + print("isViewModeYY: ${widget.isViewMode}, hasUpdateVal: $hasUpdateVal"); return [ CustomTextFieldWrapper( // isFocused: focusStates["trip_plannedFocused"] ?? false, @@ -3099,12 +3208,14 @@ class CreateNewPlansState extends State { // Request focus when user taps focusNodes["trip_plannedFocusNode"]?.requestFocus(); }, + child: DropdownSearch( selectedItem: options.firstWhere( (opt) => opt['value'] == _selectedOption, )['title'], - enabled: !widget.isViewMode, + enabled: !hasUpdateVal, + // enabled: || !hasUpdateVal, items: options.map((opt) => opt['title']!).toList(), popupProps: PopupProps.menu( showSearchBox: false, diff --git a/lib/Screens/plans/dynamic_itinerary_stepper.dart b/lib/Screens/plans/dynamic_itinerary_stepper.dart index 13c5159..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"); @@ -856,7 +868,7 @@ class DynamicItineraryState extends State { margin: EdgeInsets.only( top: 40, ), // Push it down to make room for the tab bar - padding: EdgeInsets.all(12), + padding: EdgeInsets.only(top: 12, bottom: 12, left: 3, right: 3), decoration: BoxDecoration( color: Colors.white, // Card background // color: Colors.yellow.shade50, // Card background diff --git a/lib/Screens/plans/list_plans.dart b/lib/Screens/plans/list_plans.dart index 147280a..f537169 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 @@ -676,169 +679,176 @@ class _ListPlansState extends State { // thickness: 0.2, // how "thick" the line is // color: Colors.grey, // optional // ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text( - 'My Trips', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ), - // style: TextStyle( - // fontFamily: "Inter", - // fontSize: isDesktop ? 16 : 14, - // fontWeight: FontWeight.w600, - // color: Color(0xFF212121)) - ), - ], - ), - - // Spacer(), - SizedBox(width: MediaQuery.of(context).size.width * 0.23), - if (isDesktop) - Container( - width: MediaQuery.of(context).size.width * 0.2, - height: 40, - child: TextField( - controller: searchController, - onChanged: filterPlans, - 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), - if (isDesktop) Spacer(), - - // ElevatedButton( - // style: ElevatedButton.styleFrom( - // foregroundColor: Colors.white, - // backgroundColor: Colors.blueAccent, - // ), - // onPressed: () { - // context.go('/createPlan', extra: { - // 'orgId': orgId, - // }); - // if (!isDesktop) Navigator.pop(context); - // }, - // child: Row( - // children: [ - // Icon(Icons.add_circle, color: Colors.white), - // SizedBox(width: 5), - // Text('NewPlan'), - // - // ], - // ), - // ), - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF114D8B), - foregroundColor: Colors.white, - disabledBackgroundColor: Color(0xFF114D8B), - disabledForegroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: BorderSide(color: Color(0xFF114D8B), width: 2), - ), - padding: - isDesktop - ? EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ) - : EdgeInsets.symmetric( - horizontal: 15, - vertical: 10, - ), - ), - onPressed: () { - if (TripPlanAction == "Plan Creation Not Allowed") { - showDialog( - context: context, - builder: - (context) => AlertDialog( - title: Text( - "Action Not Allowed", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - content: Text( - "Plan Creation Not Allowed For This User.", - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text( - "OK", - style: TextStyle(color: layoutColor), - ), - ), - ], - ), - ); - } else { - context.go('/createPlan', extra: {'orgId': orgId}); - if (!isDesktop) Navigator.pop(context); - } - }, - child: Row( - mainAxisSize: - MainAxisSize.min, // Ensures content fits nicely + Padding( + padding: + isDesktop + ? const EdgeInsets.all(8.0) + : const EdgeInsets.symmetric(horizontal: 14.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( children: [ Text( - "Add New Trip", + 'My Trips', style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, + fontSize: isDesktop ? 16 : 14, + fontWeight: FontWeight.w600, + color: Colors.black, ), - ), - SizedBox(width: 8), // spacing between icon and text - Icon( - Icons.add_circle_outline_rounded, - size: 15, - color: Colors.white, + // style: TextStyle( + // fontFamily: "Inter", + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + // color: Color(0xFF212121)) ), ], ), - ), - ], + + // Spacer(), + SizedBox(width: MediaQuery.of(context).size.width * 0.23), + if (isDesktop) + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchController, + onChanged: filterPlans, + 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), + if (isDesktop) Spacer(), + + // ElevatedButton( + // style: ElevatedButton.styleFrom( + // foregroundColor: Colors.white, + // backgroundColor: Colors.blueAccent, + // ), + // onPressed: () { + // context.go('/createPlan', extra: { + // 'orgId': orgId, + // }); + // if (!isDesktop) Navigator.pop(context); + // }, + // child: Row( + // children: [ + // Icon(Icons.add_circle, color: Colors.white), + // SizedBox(width: 5), + // Text('NewPlan'), + // + // ], + // ), + // ), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF114D8B), + foregroundColor: Colors.white, + disabledBackgroundColor: Color(0xFF114D8B), + disabledForegroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(color: Color(0xFF114D8B), width: 2), + ), + padding: + isDesktop + ? EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ) + : EdgeInsets.symmetric( + horizontal: 15, + vertical: 10, + ), + ), + onPressed: () { + if (TripPlanAction == "Plan Creation Not Allowed") { + showDialog( + context: context, + builder: + (context) => AlertDialog( + title: Text( + "Action Not Allowed", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + content: Text( + "Plan Creation Not Allowed For This User.", + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text( + "OK", + style: TextStyle(color: layoutColor), + ), + ), + ], + ), + ); + } else { + context.go('/createPlan', extra: {'orgId': orgId}); + if (!isDesktop) Navigator.pop(context); + } + }, + child: Row( + mainAxisSize: + MainAxisSize.min, // Ensures content fits nicely + children: [ + Text( + "Add New Trip", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + ), + ), + SizedBox(width: 8), // spacing between icon and text + Icon( + Icons.add_circle_outline_rounded, + size: 15, + color: Colors.white, + ), + ], + ), + ), + ], + ), ), if (!isDesktop) const SizedBox(height: 10), if (!isDesktop) Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: MediaQuery.of(context).size.width * 0.85, @@ -961,416 +971,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 + .getForexPdfDownload( + 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 +1458,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 +1468,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 +1481,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 +1509,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 + .getForexPdfDownload( + 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 +1686,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/Screens/policy/policy.dart b/lib/Screens/policy/policy.dart index bfff630..ca3524d 100644 --- a/lib/Screens/policy/policy.dart +++ b/lib/Screens/policy/policy.dart @@ -40,7 +40,7 @@ class Policy extends StatefulWidget { class _PolicyState extends State { final GlobalKey policyCriteriaKey = - GlobalKey(); + GlobalKey(); final ApiService apiService = ApiService(); @@ -86,23 +86,22 @@ class _PolicyState extends State { Map get policyData { List> policyDetails = - policy_details!.where((service) { - // Only check these specific fields for emptiness - final fieldsToCheck = [ - 'cost', - 'class', - 'a1_action', - 'a2_action', - 'a3_action', - ]; - - // If any of the important fields has a value, keep it - return fieldsToCheck.any((field) { - final value = service[field]; - return value != null && value.toString().trim().isNotEmpty; - }); - }).toList(); + policy_details!.where((service) { + // Only check these specific fields for emptiness + final fieldsToCheck = [ + 'cost', + 'class', + 'a1_action', + 'a2_action', + 'a3_action', + ]; + // If any of the important fields has a value, keep it + return fieldsToCheck.any((field) { + final value = service[field]; + return value != null && value.toString().trim().isNotEmpty; + }); + }).toList(); Map data = { "name": _policyController.text, @@ -155,6 +154,7 @@ class _PolicyState extends State { // } // }); } + void _addFocusListener(FocusNode node, Function(bool) updateState) { node.addListener(() { setState(() { @@ -162,6 +162,7 @@ class _PolicyState extends State { }); }); } + void _checkAuthAndLoadData() async { final String? token = await getToken(); // Your async function to get token @@ -181,9 +182,6 @@ class _PolicyState extends State { loadInitialData(); - - - WidgetsBinding.instance.addPostFrameCallback((_) { if (widget.policy != null) { final details = List>.from( @@ -193,7 +191,6 @@ class _PolicyState extends State { } }); - // if (widget.policy != null) { // print("185"); // final details = List>.from( @@ -214,14 +211,14 @@ class _PolicyState 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; }); } @@ -253,9 +250,9 @@ class _PolicyState extends State { try { List decoded = json.decode(rawServices); List> formatted = - decoded - .map((e) => {"service_id": e['service_id'].toString()}) - .toList(); + decoded + .map((e) => {"service_id": e['service_id'].toString()}) + .toList(); setState(() { selectedOrgServiceIds = formatted; @@ -281,7 +278,7 @@ class _PolicyState extends State { await loadOrgSelectedAlServices(); print("III-end"); final selectedIds = - selectedOrgServiceIds.map((e) => e['service_id']).toSet(); + selectedOrgServiceIds.map((e) => e['service_id']).toSet(); if (widget.policy != null) { print("inside if"); @@ -301,42 +298,41 @@ class _PolicyState extends State { print("exisitingService ${exisitingService}"); final filtered = - exisitingService! - .where( - (service) => - selectedIds.contains(service['service_id'].toString()), - ) - .toList(); + exisitingService! + .where( + (service) => + selectedIds.contains(service['service_id'].toString()), + ) + .toList(); setState(() { ServicesChoosed = filtered; }); print("298 ServicesChoosed ${ServicesChoosed}"); - - if (ServicesChoosed!.isNotEmpty) { print("Filtered Selected Services ChooesedIpfa1: $ServicesChoosed"); - ServicesChoosed!.sort( - (a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0), + (a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0), ); String firstServiceName = ServicesChoosed?.first['name']; String firstServiceId = ServicesChoosed?.first['service_id']; - print("✅ 306 First service name selected for filter: $firstServiceName - $firstServiceId"); + print( + "✅ 306 First service name selected for filter: $firstServiceName - $firstServiceId", + ); selectedService = firstServiceName; if (selectedServiceDBValue.value == "0") { setState(() { selectedServiceDBValue.value = firstServiceId.toString(); }); } - List serviceDBvalue = ServicesChoosed! - .map((item) => int.parse(item['service_id'].toString())) - .toList(); + List serviceDBvalue = + ServicesChoosed! + .map((item) => int.parse(item['service_id'].toString())) + .toList(); serviceDBValueList = serviceDBvalue; - } print(widget.policy); // updateData(); @@ -348,30 +344,26 @@ class _PolicyState extends State { List>.from(decoded) .map( (service) => { - 'service_id': service['service_id'].toString(), - 'name': service['name'].toString(), - 'order': service['order'].toString(), - }, - ) + 'service_id': service['service_id'].toString(), + 'name': service['name'].toString(), + 'order': service['order'].toString(), + }, + ) .toList(); }); print("✅ Loaded services from policy (decoded): $services"); - - } print("Filtered Selected Services Added to Policy: $ServicesChoosed"); - - } - else { + } else { final filtered = - selectedAllServices! - .where( - (service) => - selectedIds.contains(service['service_id'].toString()), - ) - .toList(); + selectedAllServices! + .where( + (service) => + selectedIds.contains(service['service_id'].toString()), + ) + .toList(); print("ServicesChoosedYY: $ServicesChoosed"); setState(() { @@ -386,12 +378,12 @@ class _PolicyState extends State { ServicesChoosed! .map( (service) => { - 'service_id': service['service_id'].toString(), - 'name': - service['name'].toString(), // ✅ no space before 'name' - 'order': service['order'].toString(), - }, - ) + 'service_id': service['service_id'].toString(), + 'name': + service['name'].toString(), // ✅ no space before 'name' + 'order': service['order'].toString(), + }, + ) .toList(); }); @@ -400,11 +392,13 @@ class _PolicyState extends State { if (ServicesChoosed!.isNotEmpty) { policyCriteriaKey.currentState?.fetchTrainFlightClass(); ServicesChoosed!.sort( - (a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0), + (a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0), ); String firstServiceName = ServicesChoosed?.first['name']; String firstServiceId = ServicesChoosed?.first['service_id']; - print("✅ 363 First service name selected for filter: $firstServiceName - $firstServiceId"); + print( + "✅ 363 First service name selected for filter: $firstServiceName - $firstServiceId", + ); selectedService = firstServiceName; if (selectedServiceDBValue.value == "0") { setState(() { @@ -412,12 +406,11 @@ class _PolicyState extends State { }); } - List serviceDBvalue = ServicesChoosed! - .map((item) => int.parse(item['service_id'].toString())) - .toList(); + List serviceDBvalue = + ServicesChoosed! + .map((item) => int.parse(item['service_id'].toString())) + .toList(); serviceDBValueList = serviceDBvalue; - - } } } @@ -525,7 +518,6 @@ class _PolicyState extends State { }); } - bool isValidData(Map data) { errorMessages.clear(); // Reset previous errors @@ -544,7 +536,7 @@ class _PolicyState extends State { if (domestic != "1" && international != "1") { errorMessages["trip_type"] = - "Required"; // "Please select Domestic or International."; + "Required"; // "Please select Domestic or International."; } // Validate at least one policy_detail with valid content @@ -566,7 +558,7 @@ class _PolicyState extends State { if (!hasAtLeastOneDetail) { errorMessages["policy_details"] = - "Required"; // "At least one valid policy detail is required."; + "Required"; // "At least one valid policy detail is required."; } return errorMessages.isEmpty; @@ -635,16 +627,16 @@ class _PolicyState 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(8), + 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(8), child: Column( children: [ Expanded( @@ -730,15 +722,15 @@ class _PolicyState extends State { color: Colors.white, padding: const EdgeInsets.all(8.0), child: - isDesktop - ? Row( - mainAxisAlignment: MainAxisAlignment.end, - children: _buildSubmit(isDesktop), - ) - : Row( - mainAxisAlignment: MainAxisAlignment.center, - children: _buildSubmit(isDesktop), - ), + isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.end, + children: _buildSubmit(isDesktop), + ) + : Row( + mainAxisAlignment: MainAxisAlignment.center, + children: _buildSubmit(isDesktop), + ), ), ], ), @@ -751,9 +743,9 @@ class _PolicyState extends State { // ? EdgeInsets.all(10.0) // : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.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( @@ -802,23 +794,23 @@ class _PolicyState extends State { Container( padding: isDesktop ? const EdgeInsets.only(left: 35) : null, child: - isDesktop - ? Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded(child: _buildPolicyNameField(isDesktop)), - Spacer(), - Expanded(child: _buildPolicyTypeField(isDesktop)), - ], - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildPolicyNameField(isDesktop), - SizedBox(height: 20), - _buildPolicyTypeField(isDesktop), - ], - ), + isDesktop + ? Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded(child: _buildPolicyNameField(isDesktop)), + Spacer(), + Expanded(child: _buildPolicyTypeField(isDesktop)), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildPolicyNameField(isDesktop), + SizedBox(height: 20), + _buildPolicyTypeField(isDesktop), + ], + ), ), SizedBox(height: 10), Divider(thickness: 0.1, color: Colors.grey), @@ -831,66 +823,66 @@ class _PolicyState extends State { ], isDesktop ? Padding( - padding: const EdgeInsets.only(left: 30.0, right: 98.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Approval Criteria", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), + padding: const EdgeInsets.only(left: 30.0, right: 98.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Approval Criteria", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + Text( + "Service Priority", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + ], ), - Text( - "Service Priority", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - ], - ), - ) + ) : SizedBox.shrink(), isDesktop ? Container( - // color: Colors.yellow.shade50, - height: MediaQuery.of(context).size.height * 0.54, - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( + // color: Colors.yellow.shade50, + height: MediaQuery.of(context).size.height * 0.56, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildPolicyOrdering(isDesktop), - _buildPolicyCategory(isDesktop), + Column( + children: [ + _buildPolicyOrdering(isDesktop), + _buildPolicyCategory(isDesktop), + ], + ), + Column(children: [_buildPolicyCategoryList(isDesktop)]), ], ), - Column(children: [_buildPolicyCategoryList(isDesktop)]), - ], - ), - ), - ) + ), + ) : Expanded( - child: Container( - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Column( - children: [ - _buildPolicyCategoryList(isDesktop), - _buildPolicyOrdering(isDesktop), - _buildPolicyCategory(isDesktop), - ], + child: Container( + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + children: [ + _buildPolicyCategoryList(isDesktop), + _buildPolicyOrdering(isDesktop), + _buildPolicyCategory(isDesktop), + ], + ), + ), ), ), - ), - ), // isDesktop // ? Expanded( // child: Row( @@ -1004,28 +996,28 @@ class _PolicyState extends State { border: Border.all(color: Colors.blueGrey.shade100, width: 0.35), ), child: - isDesktop - ? Padding( - padding: const EdgeInsets.all(10.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.start, - children: [_buildPolicySubCategoryList(isDesktop)], - ), - ) - : Column( - children: [ - Container( - // color: Colors.amber, - child: _buildPolicySubCategoryList(isDesktop), - // child: Text("FAta"), - // child: Row( - // mainAxisAlignment: MainAxisAlignment.start, - // children: [_buildPolicySubCategoryList(isDesktop)], - // ), - ), - ], - ), + isDesktop + ? Padding( + padding: const EdgeInsets.all(10.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [_buildPolicySubCategoryList(isDesktop)], + ), + ) + : Column( + children: [ + Container( + // color: Colors.amber, + child: _buildPolicySubCategoryList(isDesktop), + // child: Text("FAta"), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.start, + // children: [_buildPolicySubCategoryList(isDesktop)], + // ), + ), + ], + ), ); } @@ -1182,21 +1174,21 @@ class _PolicyState extends State { width: isDesktop ? MediaQuery.of(context).size.width * 0.62 : null, // width: isDesktop ? MediaQuery.of(context).size.width * 0.75 : null, child: - isDesktop - ? Container( - // color: Colors.amber, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [_buildPolicyServiceOrdering(isDesktop)], - ), - ) - : Container( - // color: Colors.amber, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [_buildPolicyServiceOrdering(isDesktop)], - ), - ), + isDesktop + ? Container( + // color: Colors.amber, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [_buildPolicyServiceOrdering(isDesktop)], + ), + ) + : Container( + // color: Colors.amber, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [_buildPolicyServiceOrdering(isDesktop)], + ), + ), ); } @@ -1207,18 +1199,18 @@ class _PolicyState extends State { // Sort services by 'order' ServicesChoosed!.sort( - (a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0), + (a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0), ); List services = - ServicesChoosed!.map((service) => service['name'].toString()).toList(); + ServicesChoosed!.map((service) => service['name'].toString()).toList(); // List serviceDBvalue = // ServicesChoosed!.map((service) => int.parse(service['service_id'].toString())).toList(); - List serviceDBvalue = ServicesChoosed! - .map((item) => int.parse(item['service_id'].toString())) - .toList(); - + List serviceDBvalue = + ServicesChoosed! + .map((item) => int.parse(item['service_id'].toString())) + .toList(); print("1093"); print(services); @@ -1230,109 +1222,111 @@ class _PolicyState extends State { child: Flex( direction: Axis.horizontal, children: - services.asMap().entries.map((entry) { - print("1182 ${entry}"); - int i = entry.key; - int index = i + 1; - String service = entry.value; - int serviceId = serviceDBvalue[i]; + services.asMap().entries.map((entry) { + print("1182 ${entry}"); + int i = entry.key; + int index = i + 1; + String service = entry.value; + int serviceId = serviceDBvalue[i]; - bool isSelected = - selectedServiceIndex.value == index.toString(); + bool isSelected = + selectedServiceIndex.value == index.toString(); - return SizedBox( - // width: isDesktop ? 40 : null, - height: - isDesktop - ? max( - (MediaQuery.of(context).size.height * 0.075), - 10, - ) - : 45, + return SizedBox( + // width: isDesktop ? 40 : null, + height: + isDesktop + ? max( + (MediaQuery.of(context).size.height * 0.075), + 10, + ) + : 45, - // max((MediaQuery.of(context).size.height * 0.09), 10) - child: GestureDetector( - onTap: () { - print("1201 Selected Services - $service - Tab Index - $index Service Id- $serviceId"); - setState(() { - selectedServiceIndex.value = index.toString(); - selectedServiceDBValue.value = serviceId.toString(); - selectedService = service; + // max((MediaQuery.of(context).size.height * 0.09), 10) + child: GestureDetector( + onTap: () { + print( + "1201 Selected Services - $service - Tab Index - $index Service Id- $serviceId", + ); + setState(() { + selectedServiceIndex.value = index.toString(); + selectedServiceDBValue.value = serviceId.toString(); + selectedService = service; - print( - " selectedServiceIndex.value - ${selectedServiceIndex.value}", - ); + print( + " selectedServiceIndex.value - ${selectedServiceIndex.value}", + ); - - // policyCriteriaKey.currentState?.fieldForPolicy(); - // policyCriteriaKey.currentState - // ?.addOrUpdatePolicy(selectedServiceIndex.value); - print("policyselectedService - $selectedService"); - if (selectedService == "Flight" || - selectedService == "Train" || selectedService == "Accomodation") { - showClass = true; - showCost = false; - // int serviceCode = selectedService == "Flight" ? 1 : 2; - print("policyselectedService1 - $selectedService"); - policyCriteriaKey.currentState - ?.fetchTrainFlightClass(); - } - // else if (selectedService == "Accommodation") { - // showClass = true; - // showCost = false; - // } - else { - showClass = false; - showCost = false; - } - }); - }, - child: Container( - margin: const EdgeInsets.all(5), - padding: - isDesktop - ? const EdgeInsets.all(8) - : const EdgeInsets.symmetric( - horizontal: 8, - vertical: 3, - ), - alignment: Alignment.center, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - service, - style: GoogleFonts.poppins( - color: - isSelected - ? const Color(0xFF114D8B) - : Colors.black87, - fontSize: 13, - fontWeight: - isSelected - ? FontWeight.bold - : FontWeight.w500, - decoration: - TextDecoration - .none, // remove built-in underline - ), + // policyCriteriaKey.currentState?.fieldForPolicy(); + // policyCriteriaKey.currentState + // ?.addOrUpdatePolicy(selectedServiceIndex.value); + print("policyselectedService - $selectedService"); + if (selectedService == "Flight" || + selectedService == "Train" || + selectedService == "Accomodation") { + showClass = true; + showCost = false; + // int serviceCode = selectedService == "Flight" ? 1 : 2; + print("policyselectedService1 - $selectedService"); + policyCriteriaKey.currentState + ?.fetchTrainFlightClass(); + } + // else if (selectedService == "Accommodation") { + // showClass = true; + // showCost = false; + // } + else { + showClass = false; + showCost = false; + } + }); + }, + child: Container( + margin: const EdgeInsets.all(5), + padding: + isDesktop + ? const EdgeInsets.all(8) + : const EdgeInsets.symmetric( + horizontal: 8, + vertical: 3, + ), + alignment: Alignment.center, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + service, + style: GoogleFonts.poppins( + color: + isSelected + ? const Color(0xFF114D8B) + : Colors.black87, + fontSize: 13, + fontWeight: + isSelected + ? FontWeight.bold + : FontWeight.w500, + decoration: + TextDecoration + .none, // remove built-in underline + ), + ), + if (isSelected) + const SizedBox( + height: 1, + ), // spacing between text and underline + if (isSelected) + Container( + height: 2, + width: 30, // or based on text width + color: const Color(0xFF114D8B), + ), + ], ), - if (isSelected) - const SizedBox( - height: 1, - ), // spacing between text and underline - if (isSelected) - Container( - height: 2, - width: 30, // or based on text width - color: const Color(0xFF114D8B), - ), - ], + ), ), - ), - ), - ); - }).toList(), + ); + }).toList(), ), ), ); @@ -1356,7 +1350,7 @@ class _PolicyState extends State { } List services = - ServicesChoosed!.map((service) => service['name'].toString()).toList(); + ServicesChoosed!.map((service) => service['name'].toString()).toList(); return Expanded( child: SingleChildScrollView( @@ -1364,88 +1358,88 @@ class _PolicyState extends State { child: Flex( direction: isDesktop ? Axis.vertical : Axis.horizontal, children: - services.asMap().entries.map((entry) { - int index = entry.key + 1; - String service = entry.value; - bool isSelected = - selectedServiceIndex.value == index.toString(); + services.asMap().entries.map((entry) { + int index = entry.key + 1; + String service = entry.value; + bool isSelected = + selectedServiceIndex.value == index.toString(); - return SizedBox( - width: isDesktop ? 180 : null, - height: - isDesktop - ? max( - (MediaQuery.of(context).size.height * 0.075), - 10, - ) - : 45, + return SizedBox( + width: isDesktop ? 180 : null, + height: + isDesktop + ? max( + (MediaQuery.of(context).size.height * 0.075), + 10, + ) + : 45, - // max((MediaQuery.of(context).size.height * 0.09), 10) - child: GestureDetector( - onTap: () { - print("Selected Services - $service - $index"); - setState(() { - // selectedServiceIndex.value = index.toString(); - // selectedService = service; - // - // if (selectedService == "Flight" || - // selectedService == "Train") { - // showClass = true; - // showCost = true; - // int serviceCode = selectedService == "Flight" ? 1 : 2; - // policyCriteriaKey.currentState?.fetchTrainFlightClass(); - // } else if (selectedService == "Accommodation") { - // showClass = true; - // showCost = false; - // } else { - // showClass = false; - // showCost = false; - // } - }); - }, - child: Container( - margin: EdgeInsets.all(5), - padding: - isDesktop - ? EdgeInsets.all(8) - : EdgeInsets.only( - top: 3, - bottom: 3, - left: 8, - right: 8, - ), - decoration: BoxDecoration( - // color: Colors.blue, - color: isSelected ? Color(0xFF114D8B) : Colors.white, - // : Color(0xFFEBEBF7), - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: Colors.white, // Light grey border - width: 1, - ), - boxShadow: [ - BoxShadow( - color: Colors.grey.withAlpha(90), // Shadow color - blurRadius: 1, // Blur radius - spreadRadius: 1, // Spread radius - offset: Offset(0, 1), // Shadow position + // max((MediaQuery.of(context).size.height * 0.09), 10) + child: GestureDetector( + onTap: () { + print("Selected Services - $service - $index"); + setState(() { + // selectedServiceIndex.value = index.toString(); + // selectedService = service; + // + // if (selectedService == "Flight" || + // selectedService == "Train") { + // showClass = true; + // showCost = true; + // int serviceCode = selectedService == "Flight" ? 1 : 2; + // policyCriteriaKey.currentState?.fetchTrainFlightClass(); + // } else if (selectedService == "Accommodation") { + // showClass = true; + // showCost = false; + // } else { + // showClass = false; + // showCost = false; + // } + }); + }, + child: Container( + margin: EdgeInsets.all(5), + padding: + isDesktop + ? EdgeInsets.all(8) + : EdgeInsets.only( + top: 3, + bottom: 3, + left: 8, + right: 8, + ), + decoration: BoxDecoration( + // color: Colors.blue, + color: isSelected ? Color(0xFF114D8B) : Colors.white, + // : Color(0xFFEBEBF7), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: Colors.white, // Light grey border + width: 1, + ), + boxShadow: [ + BoxShadow( + color: Colors.grey.withAlpha(90), // Shadow color + blurRadius: 1, // Blur radius + spreadRadius: 1, // Spread radius + offset: Offset(0, 1), // Shadow position + ), + ], + ), + alignment: Alignment.center, + child: Text( + service, + style: GoogleFonts.poppins( + color: isSelected ? Colors.white : Colors.black87, + fontSize: 13, + fontWeight: + isSelected ? FontWeight.bold : FontWeight.w100, + ), ), - ], - ), - alignment: Alignment.center, - child: Text( - service, - style: GoogleFonts.poppins( - color: isSelected ? Colors.white : Colors.black87, - fontSize: 13, - fontWeight: - isSelected ? FontWeight.bold : FontWeight.w100, ), ), - ), - ), - ); - }).toList(), + ); + }).toList(), ), ), ); @@ -1460,28 +1454,31 @@ class _PolicyState extends State { // color: Colors.brown.shade100, // child: Text("data"), // color: Colors.white60, - child: (selectedService != null && selectedServiceDBValue.value != "0") - ? PolicyCriteria( - key: policyCriteriaKey, - isDesktop: isDesktop, - isClass: showClass, - isCost: showCost, - selectedTabNotifier: selectedServiceIndex, - selectedIdNotifier: selectedServiceDBValue, - selectedService: selectedService!, - serviceDBValueList: serviceDBValueList, // 👈 Pass the array here - userId: userId, - onPolicyDataChanged: (List>? policyData) { - print("🟢 policyData received from child: $policyData"); + child: + (selectedService != null && selectedServiceDBValue.value != "0") + ? PolicyCriteria( + key: policyCriteriaKey, + isDesktop: isDesktop, + isClass: showClass, + isCost: showCost, + selectedTabNotifier: selectedServiceIndex, + selectedIdNotifier: selectedServiceDBValue, + selectedService: selectedService!, + serviceDBValueList: + serviceDBValueList, // 👈 Pass the array here + userId: userId, + onPolicyDataChanged: (List>? policyData) { + print("🟢 policyData received from child: $policyData"); - WidgetsBinding.instance.addPostFrameCallback((_) { - setState(() { - policy_details = policyData; - _clearError("policy_details"); - }); - }); - }, - ) : const Center(child: CircularProgressIndicator()), + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + policy_details = policyData; + _clearError("policy_details"); + }); + }); + }, + ) + : const Center(child: CircularProgressIndicator()), ); } @@ -1528,14 +1525,14 @@ class _PolicyState extends State { borderRadius: BorderRadius.circular(4), // Rounded rectangle border: Border.all( color: - _selectedTripType == "1" ? Colors.green : Colors.black, + _selectedTripType == "1" ? Colors.green : Colors.black, width: _selectedTripType == "1" ? 2 : 1, ), ), child: - _selectedTripType == "1" - ? Icon(Icons.rectangle, size: 8, color: Colors.green) - : null, // Add checkmark if selected + _selectedTripType == "1" + ? Icon(Icons.rectangle, size: 8, color: Colors.green) + : null, // Add checkmark if selected ), ), ], @@ -1584,14 +1581,14 @@ class _PolicyState extends State { borderRadius: BorderRadius.circular(4), // Rounded rectangle border: Border.all( color: - _selectedTripType == "2" ? Colors.green : Colors.black, + _selectedTripType == "2" ? Colors.green : Colors.black, width: _selectedTripType == "2" ? 2 : 1, ), ), child: - _selectedTripType == "2" - ? Icon(Icons.rectangle, size: 8, color: Colors.green) - : null, // Add checkmark if selected + _selectedTripType == "2" + ? Icon(Icons.rectangle, size: 8, color: Colors.green) + : null, // Add checkmark if selected ), ), ], @@ -1636,17 +1633,17 @@ class _PolicyState extends State { SizedBox(width: 20), MouseRegion( cursor: - isViewMode - ? SystemMouseCursors.forbidden - : SystemMouseCursors.click, + isViewMode + ? SystemMouseCursors.forbidden + : SystemMouseCursors.click, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: - isViewMode ? layoutColor : layoutColor, // Keep original color + isViewMode ? layoutColor : layoutColor, // Keep original color foregroundColor: - isViewMode ? Colors.white : Colors.white, // Keep original color + isViewMode ? Colors.white : Colors.white, // Keep original color disabledBackgroundColor: - layoutColor, // Ensure color remains when disabled + layoutColor, // Ensure color remains when disabled disabledForegroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), @@ -1655,8 +1652,8 @@ class _PolicyState extends State { padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), onPressed: - // isViewMode ? null : handleSubmit, // Disable when in view mode - isViewMode || isDisable ? null : handleSubmit, + // isViewMode ? null : handleSubmit, // Disable when in view mode + isViewMode || isDisable ? null : handleSubmit, child: Text("Submit", style: GoogleFonts.poppins(fontSize: 10)), ), ), @@ -1728,4 +1725,4 @@ class _PolicyState extends State { ), ]; } -} \ No newline at end of file +} diff --git a/lib/Screens/policy/policyCriteria.dart b/lib/Screens/policy/policyCriteria.dart index 8bec508..440eb43 100644 --- a/lib/Screens/policy/policyCriteria.dart +++ b/lib/Screens/policy/policyCriteria.dart @@ -40,7 +40,7 @@ class PolicyCriteria extends StatefulWidget { } class PolicyCriteriaState extends State { - String? ServiceId;// = "1"; + String? ServiceId; // = "1"; String? ServiceIndxId = "1"; String? orgId; @@ -103,7 +103,6 @@ class PolicyCriteriaState extends State { @override void initState() { - super.initState(); fetchTrainFlightClass(); @@ -156,7 +155,7 @@ class PolicyCriteriaState extends State { // Step 2: Collect existing service_ids from policyData final existingServiceIds = - policyData?.map((e) => e['service_id'].toString()).toSet(); + policyData?.map((e) => e['service_id'].toString()).toSet(); // Step 3: Loop through all service definitions for (var service in services) { @@ -200,7 +199,7 @@ class PolicyCriteriaState extends State { "a3_exceptional_action": ThirdExceptionalApproverAction[id], "a4_exceptional_action": FourthExceptionalApproverAction[id], "exceptional_parallel_process_from": - SelectedParallelExceptionalProcess[id], + SelectedParallelExceptionalProcess[id], "a1_amendment_action": FirstAmendApproverAction[id], "a2_amendment_action": SecondAmendApproverAction[id], "a3_amendment_action": ThirdAmendApproverAction[id], @@ -216,7 +215,6 @@ class PolicyCriteriaState extends State { // To set the data (update) void loadPolicyDetails(List> details) { - print("loadPolicyDetails"); for (var item in details) { final serviceId = item['service_id'].toString(); @@ -284,7 +282,7 @@ class PolicyCriteriaState extends State { print("addOrUpdatePolicyserviceId - $serviceId"); // 1. First, find existing item if any final existingIndex = policyData!.indexWhere( - (item) => item["service_id"] == serviceId, + (item) => item["service_id"] == serviceId, ); print(FirstApproverAction); @@ -302,13 +300,13 @@ class PolicyCriteriaState extends State { "a3_exceptional_action": ThirdExceptionalApproverAction[serviceId], "a4_exceptional_action": FourthExceptionalApproverAction[serviceId], "exceptional_parallel_process_from": - SelectedParallelExceptionalProcess[serviceId], + SelectedParallelExceptionalProcess[serviceId], "a1_amendment_action": FirstAmendApproverAction[serviceId], "a2_amendment_action": SecondAmendApproverAction[serviceId], "a3_amendment_action": ThirdAmendApproverAction[serviceId], "a4_amendment_action": FourthAmendApproverAction[serviceId], "amendment_parallel_process_from": - SelectedParallelAmendProcess[serviceId], + SelectedParallelAmendProcess[serviceId], "created_by": widget.userId, }; @@ -337,17 +335,19 @@ class PolicyCriteriaState extends State { bool allActionsNull = a1 == null && a2 == null && a3 == null; bool someActionsMissing = [a1, a2, a3].where((a) => a != null).length > 0 && - [a1, a2, a3].where((a) => a == null).length > 0; + [a1, a2, a3].where((a) => a == null).length > 0; - bool allExceptionalActionsNull = ae1 == null && ae2 == null && ae3 == null && ae4 == null; + bool allExceptionalActionsNull = + ae1 == null && ae2 == null && ae3 == null && ae4 == null; bool someExceptionalActionsMissing = [ae1, ae2, ae3, ae4].where((a) => a != null).length > 0 && - [ae1, ae2, ae3, ae4].where((a) => a == null).length > 0; + [ae1, ae2, ae3, ae4].where((a) => a == null).length > 0; - bool allAmendActionsNull = aa1 == null && aa2 == null && aa3 == null && aa4 == null; + bool allAmendActionsNull = + aa1 == null && aa2 == null && aa3 == null && aa4 == null; bool someAmendActionsMissing = [aa1, aa2, aa3, aa4].where((a) => a != null).length > 0 && - [aa1, aa2, aa3, aa4].where((a) => a == null).length > 0; + [aa1, aa2, aa3, aa4].where((a) => a == null).length > 0; if (someActionsMissing) { validationErrors[serviceId] = "All 3 approver actions must be selected."; @@ -355,12 +355,12 @@ class PolicyCriteriaState extends State { } if (someExceptionalActionsMissing) { validationErrors[serviceId] = - "All 4 exceptional approver actions must be selected."; + "All 4 exceptional approver actions must be selected."; return; } if (someAmendActionsMissing) { validationErrors[serviceId] = - "All 4 amendment approver actions must be selected."; + "All 4 amendment approver actions must be selected."; return; } @@ -477,7 +477,6 @@ class PolicyCriteriaState extends State { void fieldForPolicy() { print("fieldForPolicy - ${widget.selectedTabNotifier.value}"); - // Save current input to policyData before switching if (ServiceId != null) { print("Calling addOrUpdatePolicy"); @@ -495,11 +494,12 @@ class PolicyCriteriaState extends State { print(" db - ${widget.serviceDBValueList.length}"); print(" db list - ${widget.serviceDBValueList}"); - if (tabIndex != null && tabIndex >= 0 && tabIndex <= widget.serviceDBValueList.length) { - ServiceId = widget.serviceDBValueList[tabIndex-1].toString(); + if (tabIndex != null && + tabIndex >= 0 && + tabIndex <= widget.serviceDBValueList.length) { + ServiceId = widget.serviceDBValueList[tabIndex - 1].toString(); print('✅ 484 Selected ServiceId: $ServiceId'); - } - else { + } else { print('❌ Invalid tab index or out of range'); } print("502 ServiceId $ServiceId"); @@ -560,9 +560,9 @@ class PolicyCriteriaState extends State { widget.isDesktop ? SizedBox(height: 1) : SizedBox(height: 1), Padding( padding: - widget.isDesktop - ? const EdgeInsets.only(left: 0.0) - : const EdgeInsets.only(left: 0), + widget.isDesktop + ? const EdgeInsets.only(left: 0.0) + : const EdgeInsets.only(left: 0), child: Row( children: [ Container( @@ -574,27 +574,27 @@ class PolicyCriteriaState extends State { right: 5, ), child: - widget.isDesktop - ? Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (widget.isClass) - buildClassWidget(widget.isDesktop), - SizedBox(width: 45), - if (widget.isCost!) - buildCostWidget(widget.isDesktop), - ], - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (widget.isClass!) - buildClassWidget(widget.isDesktop), - SizedBox(height: 10), - if (widget.isCost!) - buildCostWidget(widget.isDesktop), - ], - ), + widget.isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (widget.isClass) + buildClassWidget(widget.isDesktop), + SizedBox(width: 45), + if (widget.isCost!) + buildCostWidget(widget.isDesktop), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (widget.isClass!) + buildClassWidget(widget.isDesktop), + SizedBox(height: 10), + if (widget.isCost!) + buildCostWidget(widget.isDesktop), + ], + ), ), ], ), @@ -632,13 +632,13 @@ class PolicyCriteriaState extends State { Container( // color: Colors.yellow, width: - widget.isDesktop - ? MediaQuery.of(context).size.width * 0.18 - : 600, + widget.isDesktop + ? MediaQuery.of(context).size.width * 0.18 + : 600, height: - widget.isDesktop - ? MediaQuery.of(context).size.height * 0.56 - : null, + widget.isDesktop + ? MediaQuery.of(context).size.height * 0.56 + : null, child: Column( children: [ Container( @@ -657,9 +657,9 @@ class PolicyCriteriaState extends State { ), child: Row( mainAxisAlignment: - widget.isDesktop - ? MainAxisAlignment.spaceAround - : MainAxisAlignment.spaceBetween, + widget.isDesktop + ? MainAxisAlignment.spaceAround + : MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 3, @@ -707,11 +707,11 @@ class PolicyCriteriaState extends State { border: Border( right: BorderSide( color: - Colors - .blueGrey - .shade50, // Change this to your desired color + Colors + .blueGrey + .shade50, // Change this to your desired color width: - 1.0, // Change this to your desired width + 1.0, // Change this to your desired width ), ), ), @@ -735,9 +735,9 @@ class PolicyCriteriaState extends State { Spacer(), CustomTextFieldUserWrapper( width: - MediaQuery.of( - context, - ).size.width * + MediaQuery.of( + context, + ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, @@ -745,38 +745,38 @@ class PolicyCriteriaState extends State { height: 35, child: DropdownSearch( selectedItem: - FirstApproverAction[ServiceId], + FirstApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: - FlexFit - .loose, // Allows flexible height + FlexFit + .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( - context, - item, - isSelected, + context, + item, + isSelected, ) => Padding( - padding: - const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: Text( - item, - style: GoogleFonts.poppins( - fontSize: - 12, // 👈 Smaller text size here - color: - Colors - .black, // You can customize this + padding: + const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: Text( + item, + style: GoogleFonts.poppins( + fontSize: + 12, // 👈 Smaller text size here + color: + Colors + .black, // You can customize this + ), + ), ), - ), - ), ), items: [ "Approval", @@ -784,29 +784,29 @@ class PolicyCriteriaState extends State { "None", ], dropdownDecoratorProps: - DropDownDecoratorProps( - dropdownSearchDecoration: - InputDecoration( - border: - InputBorder.none, - contentPadding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 5, + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: + InputBorder.none, + contentPadding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 5, + ), + ), ), - ), - ), dropdownBuilder: ( - context, - selectedItem, + context, + selectedItem, ) => Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, - color: Color(0xFF114D8B), - ), - ), + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + color: Color(0xFF114D8B), + ), + ), onChanged: (String? newValue) { setState(() { @@ -829,42 +829,74 @@ class PolicyCriteriaState extends State { onTap: () { setState(() { SelectedParallelProcess[ServiceId!] = - "1"; + "1"; }); print( "SelectedParallelProcess - $SelectedParallelProcess", ); }, - child: Container( - height: 25, - width: 25, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: - (SelectedParallelProcess[ServiceId] == - "1") - ? Colors.green - : Colors.grey, - width: 2, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Circle icon + Container( + height: 25, + width: 25, + child: Icon( + Icons.circle, + size: 15, + color: + (SelectedParallelProcess[ServiceId] == + "1") + ? Colors.green + : Colors.grey, + ), ), - ), - child: Icon( - Icons.check_circle, - size: 20, - color: - (SelectedParallelProcess[ServiceId] == - "1") - ? Colors.green - : Colors.grey, - // color: Colors.grey, - ), + Icon( + Icons.arrow_downward, + size: 16, + color: + (SelectedParallelProcess[ServiceId] == + "1") + ? Colors.green + : Colors.grey, + ), + + // Bottom line + ], ), + + // child: Container( + // height: 25, + // width: 25, + // // decoration: BoxDecoration( + // // shape: BoxShape.circle, + // // border: Border.all( + // // color: + // // (SelectedParallelProcess[ServiceId] == + // // "1") + // // ? Colors.green + // // : Colors.grey, + // // width: 2, + // // ), + // // ), + // child: Icon( + // Icons.circle, + // size: 20, + // color: + // (SelectedParallelProcess[ServiceId] == + // "1") + // ? Colors.green + // : Colors.grey, + // // color: Colors.grey, + // ), + // ), ), ], ), ), + Container( padding: const EdgeInsets.all(10), child: Row( @@ -880,9 +912,9 @@ class PolicyCriteriaState extends State { Spacer(), CustomTextFieldUserWrapper( width: - MediaQuery.of( - context, - ).size.width * + MediaQuery.of( + context, + ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, @@ -890,38 +922,38 @@ class PolicyCriteriaState extends State { height: 35, child: DropdownSearch( selectedItem: - SecondApproverAction[ServiceId], + SecondApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: - FlexFit - .loose, // Allows flexible height + FlexFit + .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( - context, - item, - isSelected, + context, + item, + isSelected, ) => Padding( - padding: - const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: Text( - item, - style: TextStyle( - fontSize: - 12, // 👈 Smaller text size here - color: - Colors - .black, // You can customize this + padding: + const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: Text( + item, + style: TextStyle( + fontSize: + 12, // 👈 Smaller text size here + color: + Colors + .black, // You can customize this + ), + ), ), - ), - ), ), items: [ "Approval", @@ -929,29 +961,29 @@ class PolicyCriteriaState extends State { "None", ], dropdownDecoratorProps: - DropDownDecoratorProps( - dropdownSearchDecoration: - InputDecoration( - border: - InputBorder.none, - contentPadding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 5, + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: + InputBorder.none, + contentPadding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 5, + ), + ), ), - ), - ), dropdownBuilder: ( - context, - selectedItem, + context, + selectedItem, ) => Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, - color: Color(0xFF114D8B), - ), - ), + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + color: Color(0xFF114D8B), + ), + ), onChanged: (String? newValue) { setState(() { @@ -974,42 +1006,77 @@ class PolicyCriteriaState extends State { onTap: () { setState(() { SelectedParallelProcess[ServiceId!] = - "2"; + "2"; }); print( "SelectedParallelProcess - $SelectedParallelProcess", ); }, - child: Container( - height: 25, - width: 25, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: - ((SelectedParallelProcess[ServiceId] == - "1") || - (SelectedParallelProcess[ServiceId] == - "2")) - ? Colors.green - : Colors.grey, - width: 2, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Circle icon + Container( + height: 25, + width: 25, + child: Icon( + Icons.circle, + size: 15, + color: + ((SelectedParallelProcess[ServiceId] == + "1") || + (SelectedParallelProcess[ServiceId] == + "2")) + ? Colors.green + : Colors.grey, + ), ), - ), - child: Icon( - Icons.check_circle, - size: 20, - color: - ((SelectedParallelProcess[ServiceId] == - "1") || - (SelectedParallelProcess[ServiceId] == - "2")) - ? Colors.green - : Colors.grey, - // color: Colors.grey, - ), + Icon( + Icons.arrow_downward_sharp, + size: 16, + color: + ((SelectedParallelProcess[ServiceId] == + "1") || + (SelectedParallelProcess[ServiceId] == + "2")) + ? Colors.green + : Colors.grey, + ), + + // Bottom line + ], ), + + // child: Container( + // height: 25, + // width: 25, + // // decoration: BoxDecoration( + // // shape: BoxShape.circle, + // // border: Border.all( + // // color: + // // ((SelectedParallelProcess[ServiceId] == + // // "1") || + // // (SelectedParallelProcess[ServiceId] == + // // "2")) + // // ? Colors.green + // // : Colors.grey, + // // width: 2, + // // ), + // // ), + // child: Icon( + // Icons.circle, + // size: 20, + // color: + // ((SelectedParallelProcess[ServiceId] == + // "1") || + // (SelectedParallelProcess[ServiceId] == + // "2")) + // ? Colors.green + // : Colors.grey, + // // color: Colors.grey, + // ), + // ), ), ], ), @@ -1028,9 +1095,9 @@ class PolicyCriteriaState extends State { Spacer(), CustomTextFieldUserWrapper( width: - MediaQuery.of( - context, - ).size.width * + MediaQuery.of( + context, + ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, @@ -1038,38 +1105,38 @@ class PolicyCriteriaState extends State { height: 35, child: DropdownSearch( selectedItem: - ThirdApproverAction[ServiceId], + ThirdApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: - FlexFit - .loose, // Allows flexible height + FlexFit + .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( - context, - item, - isSelected, + context, + item, + isSelected, ) => Padding( - padding: - const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: Text( - item, - style: GoogleFonts.poppins( - fontSize: - 12, // 👈 Smaller text size here - color: - Colors - .black, // You can customize this + padding: + const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: Text( + item, + style: GoogleFonts.poppins( + fontSize: + 12, // 👈 Smaller text size here + color: + Colors + .black, // You can customize this + ), + ), ), - ), - ), ), items: [ "Approval", @@ -1077,28 +1144,28 @@ class PolicyCriteriaState extends State { "None", ], dropdownDecoratorProps: - DropDownDecoratorProps( - dropdownSearchDecoration: - InputDecoration( - border: - InputBorder.none, - contentPadding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 5, + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: + InputBorder.none, + contentPadding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 5, + ), + ), ), - ), - ), dropdownBuilder: (context, selectedItem) => - // Center-align selected item - Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, - color: Color(0xFF114D8B), - ), - ), + // Center-align selected item + Text( + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + color: Color(0xFF114D8B), + ), + ), onChanged: (String? newValue) { setState(() { @@ -1121,45 +1188,69 @@ class PolicyCriteriaState extends State { onTap: () { setState(() { SelectedParallelProcess[ServiceId!] = - "3"; + "3"; }); print( "SelectedParallelProcess - $SelectedParallelProcess[ServiceId]", ); }, - child: Container( - height: 25, - width: 25, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: - ((SelectedParallelProcess[ServiceId] == - "1") || - (SelectedParallelProcess[ServiceId] == - "2") || - (SelectedParallelProcess[ServiceId] == - "3")) - ? Colors.green - : Colors.grey, - width: 2, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Top lin + // Circle icon + Container( + height: 25, + width: 25, + child: Icon( + Icons.circle, + size: 15, + color: + ((SelectedParallelProcess[ServiceId] == + "1") || + (SelectedParallelProcess[ServiceId] == + "2") || + (SelectedParallelProcess[ServiceId] == + "3")) + ? Colors.green + : Colors.grey, + ), ), - ), - child: Icon( - Icons.check_circle, - size: 20, - color: - ((SelectedParallelProcess[ServiceId] == - "1") || - (SelectedParallelProcess[ServiceId] == - "2") || - (SelectedParallelProcess[ServiceId] == - "3")) - ? Colors.green - : Colors.grey, - // color: Colors.grey, - ), + ], ), + // child: Container( + // height: 25, + // width: 25, + // // decoration: BoxDecoration( + // // shape: BoxShape.circle, + // // border: Border.all( + // // color: + // // ((SelectedParallelProcess[ServiceId] == + // // "1") || + // // (SelectedParallelProcess[ServiceId] == + // // "2") || + // // (SelectedParallelProcess[ServiceId] == + // // "3")) + // // ? Colors.green + // // : Colors.grey, + // // width: 2, + // // ), + // // ), + // child: Icon( + // Icons.circle, + // size: 20, + // color: + // ((SelectedParallelProcess[ServiceId] == + // "1") || + // (SelectedParallelProcess[ServiceId] == + // "2") || + // (SelectedParallelProcess[ServiceId] == + // "3")) + // ? Colors.green + // : Colors.grey, + // // color: Colors.grey, + // ), + // ), ), ], ), @@ -1179,13 +1270,13 @@ class PolicyCriteriaState extends State { children: [ Container( width: - widget.isDesktop - ? MediaQuery.of(context).size.width * 0.18 - : 600, + widget.isDesktop + ? MediaQuery.of(context).size.width * 0.18 + : 600, height: - widget.isDesktop - ? MediaQuery.of(context).size.height * 0.56 - : null, + widget.isDesktop + ? MediaQuery.of(context).size.height * 0.56 + : null, child: Column( children: [ Container( @@ -1204,9 +1295,9 @@ class PolicyCriteriaState extends State { ), child: Row( mainAxisAlignment: - widget.isDesktop - ? MainAxisAlignment.spaceAround - : MainAxisAlignment.spaceBetween, + widget.isDesktop + ? MainAxisAlignment.spaceAround + : MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 3, @@ -1254,11 +1345,11 @@ class PolicyCriteriaState extends State { border: Border( right: BorderSide( color: - Colors - .blueGrey - .shade50, // Change this to your desired color + Colors + .blueGrey + .shade50, // Change this to your desired color width: - 1.0, // Change this to your desired width + 1.0, // Change this to your desired width ), ), ), @@ -1268,7 +1359,10 @@ class PolicyCriteriaState extends State { children: [ Container( // padding: const EdgeInsets.all(10), - padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), + padding: const EdgeInsets.symmetric( + horizontal: 4.0, + vertical: 4.0, + ), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -1282,9 +1376,9 @@ class PolicyCriteriaState extends State { Spacer(), CustomTextFieldUserWrapper( width: - MediaQuery.of( - context, - ).size.width * + MediaQuery.of( + context, + ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, @@ -1292,38 +1386,38 @@ class PolicyCriteriaState extends State { height: 35, child: DropdownSearch( selectedItem: - FirstExceptionalApproverAction[ServiceId], + FirstExceptionalApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: - FlexFit - .loose, // Allows flexible height + FlexFit + .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( - context, - item, - isSelected, + context, + item, + isSelected, ) => Padding( - padding: - const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: Text( - item, - style: GoogleFonts.poppins( - fontSize: - 12, // 👈 Smaller text size here - color: - Colors - .black, // You can customize this + padding: + const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: Text( + item, + style: GoogleFonts.poppins( + fontSize: + 12, // 👈 Smaller text size here + color: + Colors + .black, // You can customize this + ), + ), ), - ), - ), ), items: [ "Approval", @@ -1331,29 +1425,29 @@ class PolicyCriteriaState extends State { "None", ], dropdownDecoratorProps: - DropDownDecoratorProps( - dropdownSearchDecoration: - InputDecoration( - border: - InputBorder.none, - contentPadding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 5, + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: + InputBorder.none, + contentPadding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 5, + ), + ), ), - ), - ), dropdownBuilder: ( - context, - selectedItem, + context, + selectedItem, ) => Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, - color: Color(0xFF114D8B), - ), - ), + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + color: Color(0xFF114D8B), + ), + ), onChanged: (String? newValue) { setState(() { @@ -1376,45 +1470,78 @@ class PolicyCriteriaState extends State { onTap: () { setState(() { SelectedParallelExceptionalProcess[ServiceId!] = - "1"; + "1"; }); print( "SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess", ); }, - child: Container( - height: 25, - width: 25, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: - (SelectedParallelExceptionalProcess[ServiceId] == - "1") - ? Colors.green - : Colors.grey, - width: 2, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Circle icon + Container( + height: 25, + width: 25, + child: Icon( + Icons.circle, + size: 15, + color: + (SelectedParallelExceptionalProcess[ServiceId] == + "1") + ? Colors.green + : Colors.grey, + ), ), - ), - child: Icon( - Icons.check_circle, - size: 20, - color: - (SelectedParallelExceptionalProcess[ServiceId] == - "1") - ? Colors.green - : Colors.grey, - // color: Colors.grey, - ), + Icon( + Icons.arrow_downward_sharp, + size: 16, + color: + (SelectedParallelExceptionalProcess[ServiceId] == + "1") + ? Colors.green + : Colors.grey, + ), + + // Bottom line + ], ), + // child: Container( + // height: 25, + // width: 25, + // // decoration: BoxDecoration( + // // shape: BoxShape.circle, + // // border: Border.all( + // // color: + // // (SelectedParallelExceptionalProcess[ServiceId] == + // // "1") + // // ? Colors.green + // // : Colors.grey, + // // width: 2, + // // ), + // // ), + // child: Icon( + // Icons.circle, + // size: 20, + // color: + // (SelectedParallelExceptionalProcess[ServiceId] == + // "1") + // ? Colors.green + // : Colors.grey, + // // color: Colors.grey, + // ), + // ), ), ], ), ), Container( // padding: const EdgeInsets.all(10), - padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), + padding: const EdgeInsets.symmetric( + horizontal: 4.0, + vertical: 4.0, + ), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -1428,9 +1555,9 @@ class PolicyCriteriaState extends State { Spacer(), CustomTextFieldUserWrapper( width: - MediaQuery.of( - context, - ).size.width * + MediaQuery.of( + context, + ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, @@ -1438,38 +1565,38 @@ class PolicyCriteriaState extends State { height: 35, child: DropdownSearch( selectedItem: - SecondExceptionalApproverAction[ServiceId], + SecondExceptionalApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: - FlexFit - .loose, // Allows flexible height + FlexFit + .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( - context, - item, - isSelected, + context, + item, + isSelected, ) => Padding( - padding: - const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: Text( - item, - style: TextStyle( - fontSize: - 12, // 👈 Smaller text size here - color: - Colors - .black, // You can customize this + padding: + const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: Text( + item, + style: TextStyle( + fontSize: + 12, // 👈 Smaller text size here + color: + Colors + .black, // You can customize this + ), + ), ), - ), - ), ), items: [ "Approval", @@ -1477,29 +1604,29 @@ class PolicyCriteriaState extends State { "None", ], dropdownDecoratorProps: - DropDownDecoratorProps( - dropdownSearchDecoration: - InputDecoration( - border: - InputBorder.none, - contentPadding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 5, + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: + InputBorder.none, + contentPadding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 5, + ), + ), ), - ), - ), dropdownBuilder: ( - context, - selectedItem, + context, + selectedItem, ) => Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, - color: Color(0xFF114D8B), - ), - ), + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + color: Color(0xFF114D8B), + ), + ), onChanged: (String? newValue) { setState(() { @@ -1522,49 +1649,86 @@ class PolicyCriteriaState extends State { onTap: () { setState(() { SelectedParallelExceptionalProcess[ServiceId!] = - "2"; + "2"; }); print( "SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess", ); }, - child: Container( - height: 25, - width: 25, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: - ((SelectedParallelExceptionalProcess[ServiceId] == - "1") || - (SelectedParallelExceptionalProcess[ServiceId] == - "2")) - ? Colors.green - : Colors.grey, - width: 2, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Circle icon + Container( + height: 25, + width: 25, + child: Icon( + Icons.circle, + size: 15, + color: + ((SelectedParallelExceptionalProcess[ServiceId] == + "1") || + (SelectedParallelExceptionalProcess[ServiceId] == + "2")) + ? Colors.green + : Colors.grey, + ), ), - ), - child: Icon( - Icons.check_circle, - size: 20, - color: - ((SelectedParallelExceptionalProcess[ServiceId] == - "1") || - (SelectedParallelExceptionalProcess[ServiceId] == - "2")) - ? Colors.green - : Colors.grey, - // color: Colors.grey, - ), + Icon( + Icons.arrow_downward_sharp, + size: 16, + color: + ((SelectedParallelExceptionalProcess[ServiceId] == + "1") || + (SelectedParallelExceptionalProcess[ServiceId] == + "2")) + ? Colors.green + : Colors.grey, + ), + + // Bottom line + ], ), + // child: Container( + // height: 25, + // width: 25, + // // decoration: BoxDecoration( + // // shape: BoxShape.circle, + // // border: Border.all( + // // color: + // // ((SelectedParallelExceptionalProcess[ServiceId] == + // // "1") || + // // (SelectedParallelExceptionalProcess[ServiceId] == + // // "2")) + // // ? Colors.green + // // : Colors.grey, + // // width: 2, + // // ), + // // ), + // child: Icon( + // Icons.circle, + // size: 20, + // color: + // ((SelectedParallelExceptionalProcess[ServiceId] == + // "1") || + // (SelectedParallelExceptionalProcess[ServiceId] == + // "2")) + // ? Colors.green + // : Colors.grey, + // // color: Colors.grey, + // ), + // ), ), ], ), ), Container( // padding: const EdgeInsets.all(10), - padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), + padding: const EdgeInsets.symmetric( + horizontal: 4.0, + vertical: 4.0, + ), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -1577,9 +1741,9 @@ class PolicyCriteriaState extends State { Spacer(), CustomTextFieldUserWrapper( width: - MediaQuery.of( - context, - ).size.width * + MediaQuery.of( + context, + ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, @@ -1587,38 +1751,38 @@ class PolicyCriteriaState extends State { height: 35, child: DropdownSearch( selectedItem: - ThirdExceptionalApproverAction[ServiceId], + ThirdExceptionalApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: - FlexFit - .loose, // Allows flexible height + FlexFit + .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( - context, - item, - isSelected, + context, + item, + isSelected, ) => Padding( - padding: - const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: Text( - item, - style: GoogleFonts.poppins( - fontSize: - 12, // 👈 Smaller text size here - color: - Colors - .black, // You can customize this + padding: + const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: Text( + item, + style: GoogleFonts.poppins( + fontSize: + 12, // 👈 Smaller text size here + color: + Colors + .black, // You can customize this + ), + ), ), - ), - ), ), items: [ "Approval", @@ -1626,28 +1790,28 @@ class PolicyCriteriaState extends State { "None", ], dropdownDecoratorProps: - DropDownDecoratorProps( - dropdownSearchDecoration: - InputDecoration( - border: - InputBorder.none, - contentPadding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 5, + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: + InputBorder.none, + contentPadding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 5, + ), + ), ), - ), - ), dropdownBuilder: (context, selectedItem) => - // Center-align selected item - Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, - color: Color(0xFF114D8B), - ), - ), + // Center-align selected item + Text( + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + color: Color(0xFF114D8B), + ), + ), onChanged: (String? newValue) { setState(() { @@ -1670,52 +1834,93 @@ class PolicyCriteriaState extends State { onTap: () { setState(() { SelectedParallelExceptionalProcess[ServiceId!] = - "3"; + "3"; }); print( "SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess[ServiceId]", ); }, - child: Container( - height: 25, - width: 25, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: - ((SelectedParallelExceptionalProcess[ServiceId] == - "1") || - (SelectedParallelExceptionalProcess[ServiceId] == - "2") || - (SelectedParallelExceptionalProcess[ServiceId] == - "3")) - ? Colors.green - : Colors.grey, - width: 2, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Circle icon + Container( + height: 25, + width: 25, + child: Icon( + Icons.circle, + size: 15, + color: + ((SelectedParallelExceptionalProcess[ServiceId] == + "1") || + (SelectedParallelExceptionalProcess[ServiceId] == + "2") || + (SelectedParallelExceptionalProcess[ServiceId] == + "3")) + ? Colors.green + : Colors.grey, + ), ), - ), - child: Icon( - Icons.check_circle, - size: 20, - color: - ((SelectedParallelExceptionalProcess[ServiceId] == - "1") || - (SelectedParallelExceptionalProcess[ServiceId] == - "2") || - (SelectedParallelExceptionalProcess[ServiceId] == - "3")) - ? Colors.green - : Colors.grey, - // color: Colors.grey, - ), + Icon( + Icons.arrow_downward_sharp, + size: 16, + color: + ((SelectedParallelExceptionalProcess[ServiceId] == + "1") || + (SelectedParallelExceptionalProcess[ServiceId] == + "2") || + (SelectedParallelExceptionalProcess[ServiceId] == + "3")) + ? Colors.green + : Colors.grey, + ), + + // Bottom line + ], ), + // child: Container( + // height: 25, + // width: 25, + // // decoration: BoxDecoration( + // // shape: BoxShape.circle, + // // border: Border.all( + // // color: + // // ((SelectedParallelExceptionalProcess[ServiceId] == + // // "1") || + // // (SelectedParallelExceptionalProcess[ServiceId] == + // // "2") || + // // (SelectedParallelExceptionalProcess[ServiceId] == + // // "3")) + // // ? Colors.green + // // : Colors.grey, + // // width: 2, + // // ), + // // ), + // child: Icon( + // Icons.circle, + // size: 20, + // color: + // ((SelectedParallelExceptionalProcess[ServiceId] == + // "1") || + // (SelectedParallelExceptionalProcess[ServiceId] == + // "2") || + // (SelectedParallelExceptionalProcess[ServiceId] == + // "3")) + // ? Colors.green + // : Colors.grey, + // // color: Colors.grey, + // ), + // ), ), ], ), ), Container( // padding: const EdgeInsets.all(10), - padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), + padding: const EdgeInsets.symmetric( + horizontal: 4.0, + vertical: 4.0, + ), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -1728,9 +1933,9 @@ class PolicyCriteriaState extends State { Spacer(), CustomTextFieldUserWrapper( width: - MediaQuery.of( - context, - ).size.width * + MediaQuery.of( + context, + ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, @@ -1738,38 +1943,38 @@ class PolicyCriteriaState extends State { height: 35, child: DropdownSearch( selectedItem: - FourthExceptionalApproverAction[ServiceId], + FourthExceptionalApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: - FlexFit - .loose, // Allows flexible height + FlexFit + .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( - context, - item, - isSelected, + context, + item, + isSelected, ) => Padding( - padding: - const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: Text( - item, - style: GoogleFonts.poppins( - fontSize: - 12, // 👈 Smaller text size here - color: - Colors - .black, // You can customize this + padding: + const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: Text( + item, + style: GoogleFonts.poppins( + fontSize: + 12, // 👈 Smaller text size here + color: + Colors + .black, // You can customize this + ), + ), ), - ), - ), ), items: [ "Approval", @@ -1777,28 +1982,28 @@ class PolicyCriteriaState extends State { "None", ], dropdownDecoratorProps: - DropDownDecoratorProps( - dropdownSearchDecoration: - InputDecoration( - border: - InputBorder.none, - contentPadding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 5, + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: + InputBorder.none, + contentPadding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 5, + ), + ), ), - ), - ), dropdownBuilder: (context, selectedItem) => - // Center-align selected item - Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, - color: Color(0xFF114D8B), - ), - ), + // Center-align selected item + Text( + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + color: Color(0xFF114D8B), + ), + ), onChanged: (String? newValue) { setState(() { @@ -1821,7 +2026,7 @@ class PolicyCriteriaState extends State { onTap: () { setState(() { SelectedParallelExceptionalProcess[ServiceId!] = - "4"; + "4"; }); print( "SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess[ServiceId]", @@ -1830,37 +2035,38 @@ class PolicyCriteriaState extends State { child: Container( height: 25, width: 25, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: - ((SelectedParallelExceptionalProcess[ServiceId] == - "1") || - (SelectedParallelExceptionalProcess[ServiceId] == - "2") || - (SelectedParallelExceptionalProcess[ServiceId] == - "3") || - (SelectedParallelExceptionalProcess[ServiceId] == - "4")) - ? Colors.green - : Colors.grey, - width: 2, - ), - ), + // decoration: BoxDecoration( + // shape: BoxShape.circle, + // border: Border.all( + // color: + // ((SelectedParallelExceptionalProcess[ServiceId] == + // "1") || + // (SelectedParallelExceptionalProcess[ServiceId] == + // "2") || + // (SelectedParallelExceptionalProcess[ServiceId] == + // "3") || + // (SelectedParallelExceptionalProcess[ServiceId] == + // "4")) + // ? Colors.green + // : Colors.grey, + // width: 2, + // ), + // ), child: Icon( - Icons.check_circle, - size: 20, + Icons.circle, + size: 15, + color: - ((SelectedParallelExceptionalProcess[ServiceId] == - "1") || - (SelectedParallelExceptionalProcess[ServiceId] == - "2") || - (SelectedParallelExceptionalProcess[ServiceId] == - "3") || - (SelectedParallelExceptionalProcess[ServiceId] == - "4")) - ? Colors.green - : Colors.grey, + ((SelectedParallelExceptionalProcess[ServiceId] == + "1") || + (SelectedParallelExceptionalProcess[ServiceId] == + "2") || + (SelectedParallelExceptionalProcess[ServiceId] == + "3") || + (SelectedParallelExceptionalProcess[ServiceId] == + "4")) + ? Colors.green + : Colors.grey, // color: Colors.grey, ), ), @@ -1883,13 +2089,13 @@ class PolicyCriteriaState extends State { Container( //color: Colors.grey.shade100, width: - widget.isDesktop - ? MediaQuery.of(context).size.width * 0.18 - : 600, + widget.isDesktop + ? MediaQuery.of(context).size.width * 0.18 + : 600, height: - widget.isDesktop - ? MediaQuery.of(context).size.height * 0.56 - : null, + widget.isDesktop + ? MediaQuery.of(context).size.height * 0.56 + : null, child: Column( children: [ Container( @@ -1908,9 +2114,9 @@ class PolicyCriteriaState extends State { ), child: Row( mainAxisAlignment: - widget.isDesktop - ? MainAxisAlignment.spaceAround - : MainAxisAlignment.spaceBetween, + widget.isDesktop + ? MainAxisAlignment.spaceAround + : MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 3, @@ -1960,7 +2166,10 @@ class PolicyCriteriaState extends State { children: [ Container( // padding: const EdgeInsets.all(10), - padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), + padding: const EdgeInsets.symmetric( + horizontal: 4.0, + vertical: 4.0, + ), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -1974,9 +2183,9 @@ class PolicyCriteriaState extends State { Spacer(), CustomTextFieldUserWrapper( width: - MediaQuery.of( - context, - ).size.width * + MediaQuery.of( + context, + ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, @@ -1984,38 +2193,38 @@ class PolicyCriteriaState extends State { height: 35, child: DropdownSearch( selectedItem: - FirstAmendApproverAction[ServiceId], + FirstAmendApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: - FlexFit - .loose, // Allows flexible height + FlexFit + .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( - context, - item, - isSelected, + context, + item, + isSelected, ) => Padding( - padding: - const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: Text( - item, - style: GoogleFonts.poppins( - fontSize: - 12, // 👈 Smaller text size here - color: - Colors - .black, // You can customize this + padding: + const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: Text( + item, + style: GoogleFonts.poppins( + fontSize: + 12, // 👈 Smaller text size here + color: + Colors + .black, // You can customize this + ), + ), ), - ), - ), ), items: [ "Approval", @@ -2023,29 +2232,29 @@ class PolicyCriteriaState extends State { "None", ], dropdownDecoratorProps: - DropDownDecoratorProps( - dropdownSearchDecoration: - InputDecoration( - border: - InputBorder.none, - contentPadding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 5, + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: + InputBorder.none, + contentPadding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 5, + ), + ), ), - ), - ), dropdownBuilder: ( - context, - selectedItem, + context, + selectedItem, ) => Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, - color: Color(0xFF114D8B), - ), - ), + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + color: Color(0xFF114D8B), + ), + ), onChanged: (String? newValue) { setState(() { @@ -2068,45 +2277,78 @@ class PolicyCriteriaState extends State { onTap: () { setState(() { SelectedParallelAmendProcess[ServiceId!] = - "1"; + "1"; }); print( "SelectedParallelAmendProcess - $SelectedParallelAmendProcess", ); }, - child: Container( - height: 25, - width: 25, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: - (SelectedParallelAmendProcess[ServiceId] == - "1") - ? Colors.green - : Colors.grey, - width: 2, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Circle icon + Container( + height: 25, + width: 25, + child: Icon( + Icons.circle, + size: 15, + color: + (SelectedParallelAmendProcess[ServiceId] == + "1") + ? Colors.green + : Colors.grey, + ), ), - ), - child: Icon( - Icons.check_circle, - size: 20, - color: - (SelectedParallelAmendProcess[ServiceId] == - "1") - ? Colors.green - : Colors.grey, - // color: Colors.grey, - ), + Icon( + Icons.arrow_downward_sharp, + size: 16, + color: + (SelectedParallelAmendProcess[ServiceId] == + "1") + ? Colors.green + : Colors.grey, + ), + + // Bottom line + ], ), + // child: Container( + // height: 25, + // width: 25, + // // decoration: BoxDecoration( + // // shape: BoxShape.circle, + // // border: Border.all( + // // color: + // // (SelectedParallelAmendProcess[ServiceId] == + // // "1") + // // ? Colors.green + // // : Colors.grey, + // // width: 2, + // // ), + // // ), + // child: Icon( + // Icons.circle, + // size: 20, + // color: + // (SelectedParallelAmendProcess[ServiceId] == + // "1") + // ? Colors.green + // : Colors.grey, + // // color: Colors.grey, + // ), + // ), ), ], ), ), Container( // padding: const EdgeInsets.all(10), - padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), + padding: const EdgeInsets.symmetric( + horizontal: 4.0, + vertical: 4.0, + ), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -2120,9 +2362,9 @@ class PolicyCriteriaState extends State { Spacer(), CustomTextFieldUserWrapper( width: - MediaQuery.of( - context, - ).size.width * + MediaQuery.of( + context, + ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, @@ -2130,38 +2372,38 @@ class PolicyCriteriaState extends State { height: 35, child: DropdownSearch( selectedItem: - SecondAmendApproverAction[ServiceId], + SecondAmendApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: - FlexFit - .loose, // Allows flexible height + FlexFit + .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( - context, - item, - isSelected, + context, + item, + isSelected, ) => Padding( - padding: - const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: Text( - item, - style: TextStyle( - fontSize: - 12, // 👈 Smaller text size here - color: - Colors - .black, // You can customize this + padding: + const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: Text( + item, + style: TextStyle( + fontSize: + 12, // 👈 Smaller text size here + color: + Colors + .black, // You can customize this + ), + ), ), - ), - ), ), items: [ "Approval", @@ -2169,29 +2411,29 @@ class PolicyCriteriaState extends State { "None", ], dropdownDecoratorProps: - DropDownDecoratorProps( - dropdownSearchDecoration: - InputDecoration( - border: - InputBorder.none, - contentPadding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 5, + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: + InputBorder.none, + contentPadding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 5, + ), + ), ), - ), - ), dropdownBuilder: ( - context, - selectedItem, + context, + selectedItem, ) => Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, - color: Color(0xFF114D8B), - ), - ), + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + color: Color(0xFF114D8B), + ), + ), onChanged: (String? newValue) { setState(() { @@ -2214,49 +2456,87 @@ class PolicyCriteriaState extends State { onTap: () { setState(() { SelectedParallelAmendProcess[ServiceId!] = - "2"; + "2"; }); print( "SelectedParallelAmendProcess - $SelectedParallelAmendProcess", ); }, - child: Container( - height: 25, - width: 25, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: - ((SelectedParallelAmendProcess[ServiceId] == - "1") || - (SelectedParallelAmendProcess[ServiceId] == - "2")) - ? Colors.green - : Colors.grey, - width: 2, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Circle icon + Container( + height: 25, + width: 25, + child: Icon( + Icons.circle, + size: 15, + color: + ((SelectedParallelAmendProcess[ServiceId] == + "1") || + (SelectedParallelAmendProcess[ServiceId] == + "2")) + ? Colors.green + : Colors.grey, + ), ), - ), - child: Icon( - Icons.check_circle, - size: 20, - color: - ((SelectedParallelAmendProcess[ServiceId] == - "1") || - (SelectedParallelAmendProcess[ServiceId] == - "2")) - ? Colors.green - : Colors.grey, - // color: Colors.grey, - ), + Icon( + Icons.arrow_downward_sharp, + size: 16, + color: + ((SelectedParallelAmendProcess[ServiceId] == + "1") || + (SelectedParallelAmendProcess[ServiceId] == + "2")) + ? Colors.green + : Colors.grey, + ), + + // Bottom line + ], ), + + // child: Container( + // height: 25, + // width: 25, + // // decoration: BoxDecoration( + // // shape: BoxShape.circle, + // // border: Border.all( + // // color: + // // ((SelectedParallelAmendProcess[ServiceId] == + // // "1") || + // // (SelectedParallelAmendProcess[ServiceId] == + // // "2")) + // // ? Colors.green + // // : Colors.grey, + // // width: 2, + // // ), + // // ), + // child: Icon( + // Icons.circle, + // size: 20, + // color: + // ((SelectedParallelAmendProcess[ServiceId] == + // "1") || + // (SelectedParallelAmendProcess[ServiceId] == + // "2")) + // ? Colors.green + // : Colors.grey, + // // color: Colors.grey, + // ), + // ), ), ], ), ), Container( // padding: const EdgeInsets.all(10), - padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), + padding: const EdgeInsets.symmetric( + horizontal: 4.0, + vertical: 4.0, + ), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -2269,9 +2549,9 @@ class PolicyCriteriaState extends State { Spacer(), CustomTextFieldUserWrapper( width: - MediaQuery.of( - context, - ).size.width * + MediaQuery.of( + context, + ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, @@ -2279,38 +2559,38 @@ class PolicyCriteriaState extends State { height: 35, child: DropdownSearch( selectedItem: - ThirdAmendApproverAction[ServiceId], + ThirdAmendApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: - FlexFit - .loose, // Allows flexible height + FlexFit + .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( - context, - item, - isSelected, + context, + item, + isSelected, ) => Padding( - padding: - const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: Text( - item, - style: GoogleFonts.poppins( - fontSize: - 12, // 👈 Smaller text size here - color: - Colors - .black, // You can customize this + padding: + const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: Text( + item, + style: GoogleFonts.poppins( + fontSize: + 12, // 👈 Smaller text size here + color: + Colors + .black, // You can customize this + ), + ), ), - ), - ), ), items: [ "Approval", @@ -2318,28 +2598,28 @@ class PolicyCriteriaState extends State { "None", ], dropdownDecoratorProps: - DropDownDecoratorProps( - dropdownSearchDecoration: - InputDecoration( - border: - InputBorder.none, - contentPadding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 5, + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: + InputBorder.none, + contentPadding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 5, + ), + ), ), - ), - ), dropdownBuilder: (context, selectedItem) => - // Center-align selected item - Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, - color: Color(0xFF114D8B), - ), - ), + // Center-align selected item + Text( + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + color: Color(0xFF114D8B), + ), + ), onChanged: (String? newValue) { setState(() { @@ -2362,52 +2642,93 @@ class PolicyCriteriaState extends State { onTap: () { setState(() { SelectedParallelAmendProcess[ServiceId!] = - "3"; + "3"; }); print( "SelectedParallelAmendProcess - $SelectedParallelAmendProcess[ServiceId]", ); }, - child: Container( - height: 25, - width: 25, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: - ((SelectedParallelAmendProcess[ServiceId] == - "1") || - (SelectedParallelAmendProcess[ServiceId] == - "2") || - (SelectedParallelAmendProcess[ServiceId] == - "3")) - ? Colors.green - : Colors.grey, - width: 2, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Circle icon + Container( + height: 25, + width: 25, + child: Icon( + Icons.circle, + size: 15, + color: + ((SelectedParallelAmendProcess[ServiceId] == + "1") || + (SelectedParallelAmendProcess[ServiceId] == + "2") || + (SelectedParallelAmendProcess[ServiceId] == + "3")) + ? Colors.green + : Colors.grey, + ), ), - ), - child: Icon( - Icons.check_circle, - size: 20, - color: - ((SelectedParallelAmendProcess[ServiceId] == - "1") || - (SelectedParallelAmendProcess[ServiceId] == - "2") || - (SelectedParallelAmendProcess[ServiceId] == - "3")) - ? Colors.green - : Colors.grey, - // color: Colors.grey, - ), + Icon( + Icons.arrow_downward_sharp, + size: 16, + color: + ((SelectedParallelAmendProcess[ServiceId] == + "1") || + (SelectedParallelAmendProcess[ServiceId] == + "2") || + (SelectedParallelAmendProcess[ServiceId] == + "3")) + ? Colors.green + : Colors.grey, + ), + + // Bottom line + ], ), + // child: Container( + // height: 25, + // width: 25, + // // decoration: BoxDecoration( + // // shape: BoxShape.circle, + // // border: Border.all( + // // color: + // // ((SelectedParallelAmendProcess[ServiceId] == + // // "1") || + // // (SelectedParallelAmendProcess[ServiceId] == + // // "2") || + // // (SelectedParallelAmendProcess[ServiceId] == + // // "3")) + // // ? Colors.green + // // : Colors.grey, + // // width: 2, + // // ), + // // ), + // child: Icon( + // Icons.circle, + // size: 20, + // color: + // ((SelectedParallelAmendProcess[ServiceId] == + // "1") || + // (SelectedParallelAmendProcess[ServiceId] == + // "2") || + // (SelectedParallelAmendProcess[ServiceId] == + // "3")) + // ? Colors.green + // : Colors.grey, + // // color: Colors.grey, + // ), + // ), ), ], ), ), Container( // padding: const EdgeInsets.all(10), - padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), + padding: const EdgeInsets.symmetric( + horizontal: 4.0, + vertical: 4.0, + ), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -2420,9 +2741,9 @@ class PolicyCriteriaState extends State { Spacer(), CustomTextFieldUserWrapper( width: - MediaQuery.of( - context, - ).size.width * + MediaQuery.of( + context, + ).size.width * 0.12, isFocused: false, isDesktop: widget.isDesktop, @@ -2430,38 +2751,38 @@ class PolicyCriteriaState extends State { height: 35, child: DropdownSearch( selectedItem: - FourthAmendApproverAction[ServiceId], + FourthAmendApproverAction[ServiceId], // enabled: !isViewMode, popupProps: PopupProps.menu( // showSearchBox: true, fit: - FlexFit - .loose, // Allows flexible height + FlexFit + .loose, // Allows flexible height constraints: BoxConstraints( maxHeight: 250, ), itemBuilder: ( - context, - item, - isSelected, + context, + item, + isSelected, ) => Padding( - padding: - const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: Text( - item, - style: GoogleFonts.poppins( - fontSize: - 12, // 👈 Smaller text size here - color: - Colors - .black, // You can customize this + padding: + const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: Text( + item, + style: GoogleFonts.poppins( + fontSize: + 12, // 👈 Smaller text size here + color: + Colors + .black, // You can customize this + ), + ), ), - ), - ), ), items: [ "Approval", @@ -2469,28 +2790,28 @@ class PolicyCriteriaState extends State { "None", ], dropdownDecoratorProps: - DropDownDecoratorProps( - dropdownSearchDecoration: - InputDecoration( - border: - InputBorder.none, - contentPadding: - EdgeInsets.symmetric( - horizontal: 1, - vertical: 5, + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: + InputBorder.none, + contentPadding: + EdgeInsets.symmetric( + horizontal: 1, + vertical: 5, + ), + ), ), - ), - ), dropdownBuilder: (context, selectedItem) => - // Center-align selected item - Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, - color: Color(0xFF114D8B), - ), - ), + // Center-align selected item + Text( + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + color: Color(0xFF114D8B), + ), + ), onChanged: (String? newValue) { setState(() { @@ -2513,7 +2834,7 @@ class PolicyCriteriaState extends State { onTap: () { setState(() { SelectedParallelAmendProcess[ServiceId!] = - "4"; + "4"; }); print( "SelectedParallelAmendProcess - $SelectedParallelAmendProcess[ServiceId]", @@ -2522,37 +2843,37 @@ class PolicyCriteriaState extends State { child: Container( height: 25, width: 25, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: - ((SelectedParallelAmendProcess[ServiceId] == - "1") || - (SelectedParallelAmendProcess[ServiceId] == - "2") || - (SelectedParallelAmendProcess[ServiceId] == - "3") || - (SelectedParallelAmendProcess[ServiceId] == - "4")) - ? Colors.green - : Colors.grey, - width: 2, - ), - ), + // decoration: BoxDecoration( + // shape: BoxShape.circle, + // border: Border.all( + // color: + // ((SelectedParallelAmendProcess[ServiceId] == + // "1") || + // (SelectedParallelAmendProcess[ServiceId] == + // "2") || + // (SelectedParallelAmendProcess[ServiceId] == + // "3") || + // (SelectedParallelAmendProcess[ServiceId] == + // "4")) + // ? Colors.green + // : Colors.grey, + // width: 2, + // ), + // ), child: Icon( - Icons.check_circle, - size: 20, + Icons.circle, + size: 15, color: - ((SelectedParallelAmendProcess[ServiceId] == - "1") || - (SelectedParallelAmendProcess[ServiceId] == - "2") || - (SelectedParallelAmendProcess[ServiceId] == - "3") || - (SelectedParallelAmendProcess[ServiceId] == - "4")) - ? Colors.green - : Colors.grey, + ((SelectedParallelAmendProcess[ServiceId] == + "1") || + (SelectedParallelAmendProcess[ServiceId] == + "2") || + (SelectedParallelAmendProcess[ServiceId] == + "3") || + (SelectedParallelAmendProcess[ServiceId] == + "4")) + ? Colors.green + : Colors.grey, // color: Colors.grey, ), ), @@ -2624,15 +2945,14 @@ class PolicyCriteriaState extends State { }); List> dropdownItems = - purposeList - .map( - (item) => DropdownMenuItem( - value: item['dropdown_key'], - child: Text(item['dropdown_value']), - ), - ) - .toList(); - + purposeList + .map( + (item) => DropdownMenuItem( + value: item['dropdown_key'], + child: Text(item['dropdown_value']), + ), + ) + .toList(); if (dropdownItems.isEmpty) { dropdownItems.add( @@ -2725,96 +3045,96 @@ class PolicyCriteriaState extends State { height: 40, width: double.infinity, child: - (ServiceId!) != null && (isLoading || dropdownItems.isEmpty) - ? const Center(child: CircularProgressIndicator()) - : DropdownSearch>( - key: - classAction[(ServiceId!)] == null - ? UniqueKey() - : ValueKey(classAction[(ServiceId!)]), - items: purposeList.cast>(), + (ServiceId!) != null && (isLoading || dropdownItems.isEmpty) + ? const Center(child: CircularProgressIndicator()) + : DropdownSearch>( + key: + classAction[(ServiceId!)] == null + ? UniqueKey() + : ValueKey(classAction[(ServiceId!)]), + items: purposeList.cast>(), - // selectedItem: purposeList.firstWhere( - // (item) => item['dropdown_key'] == selectedClass, - // orElse: () => {}, - // ), - selectedItem: - classAction[(ServiceId!)] != null - ? purposeList.firstWhere( - (item) => - item['dropdown_key'] == - classAction[(ServiceId!)], - orElse: () => {}, - ) - : null, - itemAsString: (item) => item['dropdown_value'] ?? '', - popupProps: PopupProps.menu( - showSearchBox: false, - fit: FlexFit.loose, - menuProps: const MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: (context, item, isSelected) { - final bool isNotAllowed = - item['is_allowed'] == 'No'; - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), - child: Text( - item['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: - isNotAllowed - ? Colors.redAccent - : Colors.black, + // selectedItem: purposeList.firstWhere( + // (item) => item['dropdown_key'] == selectedClass, + // orElse: () => {}, + // ), + selectedItem: + classAction[(ServiceId!)] != null + ? purposeList.firstWhere( + (item) => + item['dropdown_key'] == + classAction[(ServiceId!)], + orElse: () => {}, + ) + : null, + itemAsString: (item) => item['dropdown_value'] ?? '', + popupProps: PopupProps.menu( + showSearchBox: false, + fit: FlexFit.loose, + menuProps: const MenuProps( + backgroundColor: Colors.white, + ), + itemBuilder: (context, item, isSelected) { + final bool isNotAllowed = + item['is_allowed'] == 'No'; + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), + child: Text( + item['dropdown_value'] ?? '', + style: GoogleFonts.poppins( + fontSize: 12, + color: + isNotAllowed + ? Colors.redAccent + : Colors.black, + ), + ), + ); + }, ), + dropdownDecoratorProps: const DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), + ), + ), + dropdownBuilder: (context, selectedItem) { + if (selectedItem == null || selectedItem.isEmpty) { + return Text( + "Select ", + style: GoogleFonts.poppins( + color: Colors.grey, + fontSize: 13, + ), + ); + } + return Text( + selectedItem['dropdown_value'] ?? '', + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ); + }, + onChanged: + purposeList.isNotEmpty + ? (Map? newValue) async { + setState(() { + classAction[(ServiceId!)] = + newValue?['dropdown_key']; + print( + "Selected Purpose: ${classAction[(ServiceId!)]}", + ); + }); + } + : null, ), - ); - }, - ), - dropdownDecoratorProps: const DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 10, - ), - ), - ), - dropdownBuilder: (context, selectedItem) { - if (selectedItem == null || selectedItem.isEmpty) { - return Text( - "Select ", - style: GoogleFonts.poppins( - color: Colors.grey, - fontSize: 13, - ), - ); - } - return Text( - selectedItem['dropdown_value'] ?? '', - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ); - }, - onChanged: - purposeList.isNotEmpty - ? (Map? newValue) async { - setState(() { - classAction[(ServiceId!)] = - newValue?['dropdown_key']; - print( - "Selected Purpose: ${classAction[(ServiceId!)]}", - ); - }); - } - : null, - ), ), ), ], @@ -2868,4 +3188,4 @@ class PolicyCriteriaState extends State { ], ); } -} \ No newline at end of file +} diff --git a/lib/Screens/userManagement/create_traveller_agent/listTravelAgent.dart b/lib/Screens/userManagement/create_traveller_agent/listTravelAgent.dart index 2da32d5..5b77749 100644 --- a/lib/Screens/userManagement/create_traveller_agent/listTravelAgent.dart +++ b/lib/Screens/userManagement/create_traveller_agent/listTravelAgent.dart @@ -18,10 +18,10 @@ import '../../../services/apiService.dart'; import '../../../utils/pagination.dart'; import '../../../widgets/custom_breadcrumb_navigation.dart'; import '../../../widgets/popup_travelAgentList_action.dart'; + /// import '../../../widgets/custom_popup.dart'; /// import '../../../../widgets/popup_TravelAgentList_action.dart'; - class TravelAgentListScreen extends StatefulWidget { @override _TravelAgentListScreenState createState() => _TravelAgentListScreenState(); @@ -144,7 +144,8 @@ class _TravelAgentListScreenState extends State { Future> fetchUsers() async { // return []; orgId = await getOrgId(); - final String apiUrlData = '$apiUrl/api/agentList?org_id=$orgId&for=table_view'; + final String apiUrlData = + '$apiUrl/api/agentList?org_id=$orgId&for=table_view'; final String? token = await getToken(); print("Fetch Users"); @@ -459,15 +460,13 @@ class _TravelAgentListScreenState extends State { isDesktop: isDesktop, breadcrumbItems: [ BreadcrumbItem( - title: 'Org Settings', - tooltip: 'Go To Organization Settings', - onTap: (context) { - context.go("/OrganizationSettings"); - } - ), - BreadcrumbItem( - title: 'Travel Agent', + title: 'Org Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + }, ), + BreadcrumbItem(title: 'Travel Agent'), ], ), ), @@ -483,8 +482,8 @@ class _TravelAgentListScreenState extends State { ), if (isDesktop) SizedBox(width: MediaQuery.of(context).size.width * 0.03), - // SizedBox(width: MediaQuery.of(context).size.width * 0.23), - // SizedBox(width: MediaQuery.of(context).size.width * 0.15), + // SizedBox(width: MediaQuery.of(context).size.width * 0.23), + // SizedBox(width: MediaQuery.of(context).size.width * 0.15), if (isDesktop) Container( width: MediaQuery.of(context).size.width * 0.2, @@ -844,11 +843,12 @@ class _TravelAgentListScreenState extends State { DataCell( Row( mainAxisAlignment: - MainAxisAlignment.start, + MainAxisAlignment.start, children: [ GestureDetector( child: Tooltip( - message: 'Edit Travel Agent Details', + message: + 'Edit Travel Agent Details', child: Image.asset( 'assets/images/IconsImg/edit.png', width: 20, @@ -858,12 +858,18 @@ class _TravelAgentListScreenState extends State { onTap: () async { // Navigator.pop(context); // Close the menu // final userId = user['user_id']; - final userId = int.parse(user['user_id'].toString()); - final usersData = await apiService.getSingleUser(userId); - context.go("/CreateTravelAgent", extra: { - "selectedUser": usersData, - "isViewMode": false, - }); + final userId = int.parse( + user['user_id'].toString(), + ); + final usersData = await apiService + .getSingleUser(userId); + context.go( + "/CreateTravelAgent", + extra: { + "selectedUser": usersData, + "isViewMode": false, + }, + ); }, ), ], @@ -911,32 +917,48 @@ class _TravelAgentListScreenState extends State { ), ), - Row( - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - GestureDetector( - child: Tooltip( - message: 'Edit Travel Agent Details', - child: Image.asset( - 'assets/images/IconsImg/edit.png', - width: 20, - height: 15, - ), + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + GestureDetector( + child: Tooltip( + message: + 'Edit Travel Agent Details', + child: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, ), - onTap: () async { - Navigator.pop(context); // Close the menu - final userId = int.parse(user['user_id'].toString()); - final usersData = await apiService.getSingleUser(userId); - context.go("/CreateTravelAgent", extra: { + ), + onTap: () async { + // Navigator.pop(context); // Close the menu + // final userId = user['user_id']; + final userId = int.parse( + user['user_id'].toString(), + ); + final usersData = await apiService + .getSingleUser(userId); + context.go( + "/CreateTravelAgent", + extra: { "selectedUser": usersData, "isViewMode": false, - }); - }, - ), - ], - ), + }, + ); + }, + // onTap: () async { + // Navigator.pop(context); // Close the menu + // final userId = int.parse(user['user_id'].toString()); + // final usersData = await apiService.getSingleUser(userId); + // context.go("/CreateTravelAgent", extra: { + // "selectedUser": usersData, + // "isViewMode": false, + // }); + // }, + ), + ], + ), // UserActionsMenu( // user: user, // getUserDetails: @@ -1043,7 +1065,7 @@ class _TravelAgentListScreenState extends State { children: [ Column( crossAxisAlignment: - CrossAxisAlignment.start, + CrossAxisAlignment.start, children: [ Text( "${user['company_name'] ?? ''}", diff --git a/lib/Screens/userManagement/create_traveller_agent/personalDetailsTravelAgent.dart b/lib/Screens/userManagement/create_traveller_agent/personalDetailsTravelAgent.dart index 6b38e4f..28a6e02 100644 --- a/lib/Screens/userManagement/create_traveller_agent/personalDetailsTravelAgent.dart +++ b/lib/Screens/userManagement/create_traveller_agent/personalDetailsTravelAgent.dart @@ -806,7 +806,10 @@ class PersonalDetailsState extends State { CustomTextFieldUserWrapper( isFocused: focusStates["FnameFocused"] ?? false, isDesktop: widget.isDesktop, - width: MediaQuery.of(context).size.width * 0.12, + width: + widget.isDesktop + ? MediaQuery.of(context).size.width * 0.12 + : null, child: SizedBox( height: 40, child: TextField( @@ -858,7 +861,10 @@ class PersonalDetailsState extends State { CustomTextFieldUserWrapper( isFocused: focusStates["LnameFocused"] ?? false, isDesktop: widget.isDesktop, - width: MediaQuery.of(context).size.width * 0.12, + width: + widget.isDesktop + ? MediaQuery.of(context).size.width * 0.12 + : null, child: SizedBox( height: 40, child: TextField( @@ -1210,7 +1216,10 @@ class PersonalDetailsState extends State { CustomTextFieldUserWrapper( isFocused: focusStates["mobileNumberFocused"] ?? false, isDesktop: widget.isDesktop, - width: MediaQuery.of(context).size.width * 0.12, + width: + widget.isDesktop + ? MediaQuery.of(context).size.width * 0.12 + : null, child: SizedBox( height: 40, child: TextField( @@ -1274,7 +1283,10 @@ class PersonalDetailsState extends State { // isFocused: false, isFocused: focusStates["alternateMobileFocused"] ?? false, isDesktop: widget.isDesktop, - width: MediaQuery.of(context).size.width * 0.12, + width: + widget.isDesktop + ? MediaQuery.of(context).size.width * 0.12 + : null, child: SizedBox( height: 40, child: TextField( @@ -1353,161 +1365,175 @@ class PersonalDetailsState extends State { padding: const EdgeInsets.symmetric(horizontal: 0), isDesktop: widget.isDesktop, child: SizedBox( - height: 40, - width: double.infinity, - child: Focus( - focusNode: focusNodes["countryFocusNode"], - onFocusChange: (hasFocus) { - setState(() { - focusStates["countryFocused"] = hasFocus; - }); - }, - child: GestureDetector( - onTap: () { - // Request focus when user taps - focusNodes["countryFocusNode"]?.requestFocus(); - }, - child: DropdownSearch( - selectedItem: countryMap[selectedCountry], - enabled: !widget.isViewMode, - popupProps: PopupProps.menu( - showSearchBox: true, // Enables search functionality - fit: FlexFit.loose, // Allows flexible height - menuProps: const MenuProps(backgroundColor: Colors.white), - itemBuilder: - // (context, item, isSelected) => Container( - // padding: EdgeInsets.symmetric( - // horizontal: 10, - // vertical: 6, - // ), - // child: Text( - // item, - // style: GoogleFonts.poppins(fontSize: 11.5), - // ), - // ), - (context, item, isSelected) { - print("contryItem - $item"); - final match = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(item); - final countryName = match?.group(1) ?? ''; - final countryCode = match?.group(2) ?? ''; - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10.0, - vertical: 6.0, - ), - child: Padding( - // padding: const EdgeInsets.all(3.0), - padding: EdgeInsets.symmetric(horizontal: 2, vertical: 3), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - countryName, - style: GoogleFonts.poppins(fontSize: 11.5), - ), - Text( - countryCode, - style: GoogleFonts.poppins( - fontSize: 11.5, - color: Colors.grey, - ), - ), - ], - ), - ), - ); + height: 40, + width: double.infinity, + child: Focus( + focusNode: focusNodes["countryFocusNode"], + onFocusChange: (hasFocus) { + setState(() { + focusStates["countryFocused"] = hasFocus; + }); + }, + child: GestureDetector( + onTap: () { + // Request focus when user taps + focusNodes["countryFocusNode"]?.requestFocus(); }, - constraints: BoxConstraints(maxHeight: 180), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search Country...", - contentPadding: EdgeInsets.symmetric( - horizontal: 3, - vertical: 3, - ), - ), - ), - ), - items: countryMap.values.toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (focusStates["countryFocused"] ?? false) - ? (layoutColor ?? Colors.blue) - : Colors.white, - // width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (focusStates["countryFocused"] ?? false) - ? (layoutColor ?? Colors.blue) - : Colors.white, - // width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color : (layoutColor ?? Colors.grey), width: 1), - ), - contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0,), - // contentPadding: EdgeInsets.symmetric(horizontal: 1), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select Country", - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, + child: DropdownSearch( + selectedItem: countryMap[selectedCountry], + enabled: !widget.isViewMode, + popupProps: PopupProps.menu( + showSearchBox: true, // Enables search functionality + fit: FlexFit.loose, // Allows flexible height + menuProps: const MenuProps(backgroundColor: Colors.white), + itemBuilder: + // (context, item, isSelected) => Container( + // padding: EdgeInsets.symmetric( + // horizontal: 10, + // vertical: 6, + // ), + // child: Text( + // item, + // style: GoogleFonts.poppins(fontSize: 11.5), + // ), + // ), + (context, item, isSelected) { + print("contryItem - $item"); + final match = RegExp( + r'^(.*)\s\((.*)\)$', + ).firstMatch(item); + final countryName = match?.group(1) ?? ''; + final countryCode = match?.group(2) ?? ''; + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 6.0, + ), + child: Padding( + // padding: const EdgeInsets.all(3.0), + padding: EdgeInsets.symmetric( + horizontal: 2, + vertical: 3, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + countryName, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + Text( + countryCode, + style: GoogleFonts.poppins( + fontSize: 11.5, + color: Colors.grey, + ), + ), + ], + ), + ), + ); + }, + constraints: BoxConstraints(maxHeight: 180), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search Country...", + contentPadding: EdgeInsets.symmetric( + horizontal: 3, + vertical: 3, + ), ), ), ), + items: countryMap.values.toList(), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (focusStates["countryFocused"] ?? false) + ? (layoutColor ?? Colors.blue) + : Colors.white, + // width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (focusStates["countryFocused"] ?? false) + ? (layoutColor ?? Colors.blue) + : Colors.white, + // width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: (layoutColor ?? Colors.grey), + width: 1, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 8.0, + ), + // contentPadding: EdgeInsets.symmetric(horizontal: 1), + ), + ), + dropdownBuilder: + (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select Country", + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ), + ), - // onChanged: widget.isViewMode - // ? null - // : (String? newValue) { - // setState(() { - // // Find the country_code based on selected country_name - // selectedCountry = countryMap.entries - // .firstWhere((entry) => entry.value == newValue) - // .key; - // - // // if (selectedCountry!.isNotEmpty) { - // // errorMessages.remove("country_code"); - // // } - // }); - // widget.onCountryChanged?.call(newValue); - // }, - onChanged: - widget.isViewMode - ? null - : (String? newValue) { - if (newValue == null) return; + // onChanged: widget.isViewMode + // ? null + // : (String? newValue) { + // setState(() { + // // Find the country_code based on selected country_name + // selectedCountry = countryMap.entries + // .firstWhere((entry) => entry.value == newValue) + // .key; + // + // // if (selectedCountry!.isNotEmpty) { + // // errorMessages.remove("country_code"); + // // } + // }); + // widget.onCountryChanged?.call(newValue); + // }, + onChanged: + widget.isViewMode + ? null + : (String? newValue) { + if (newValue == null) return; - final countryCode = - countryMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; + final countryCode = + countryMap.entries + .firstWhere( + (entry) => entry.value == newValue, + ) + .key; - setState(() { - selectedCountry = countryCode; - }); + setState(() { + selectedCountry = countryCode; + }); - widget.onCountryChanged?.call( - countryCode, - ); // ✅ send code not name - }, - ),),), + widget.onCountryChanged?.call( + countryCode, + ); // ✅ send code not name + }, + ), + ), + ), ), ), ], diff --git a/lib/Screens/userManagement/create_user/create_user.dart b/lib/Screens/userManagement/create_user/create_user.dart index 9d811d5..b3033fc 100644 --- a/lib/Screens/userManagement/create_user/create_user.dart +++ b/lib/Screens/userManagement/create_user/create_user.dart @@ -181,7 +181,8 @@ class _CreateUserFormDetialsState extends State { "first_approver": selectedFirstApprover, "second_approver": selectedSecondApprover, "third_approver": selectedThirdApprover, - "exceptional_approver": selectedExceptionalApprover, + "fourth_approver": selectedExceptionalApprover, + // "exceptional_approver": selectedExceptionalApprover, "delegated_to_user_id": selectedSubstituteApprover, // "passport_number": controllers["passportNumber"]?.text, // "place_of_issue": controllers["placeOfIssue"]?.text, @@ -300,9 +301,14 @@ class _CreateUserFormDetialsState extends State { apiselectedUser?["third_approver"]?.toString() ?? ""; } - if (apiselectedUser?["exceptional_approver"] != null) { + // if (apiselectedUser?["exceptional_approver"] != null) { + // selectedExceptionalApprover = + // apiselectedUser?["exceptional_approver"]?.toString() ?? ""; + // } + + if (apiselectedUser?["fourth_approver"] != null) { selectedExceptionalApprover = - apiselectedUser?["exceptional_approver"]?.toString() ?? ""; + apiselectedUser?["fourth_approver"]?.toString() ?? ""; } if (apiselectedUser?["delegated_to_user_id"] != null) { @@ -1329,9 +1335,11 @@ class _CreateUserFormDetialsState extends State { print("📨 Response: ${response.body}"); - if(roleId == "4"){ context.go('/listPlan'); } - else{ context.go('/listUser'); } - + if (roleId == "4") { + context.go('/listPlan'); + } else { + context.go('/listUser'); + } } else { print("❌ Submission failed. Status: ${response.statusCode}"); print("📨 Body: ${response.body}"); diff --git a/lib/Screens/userManagement/create_user/office_details.dart b/lib/Screens/userManagement/create_user/office_details.dart index b9c53b4..c0271e5 100644 --- a/lib/Screens/userManagement/create_user/office_details.dart +++ b/lib/Screens/userManagement/create_user/office_details.dart @@ -191,18 +191,34 @@ class OfficeDetailsState extends State { fetchUsers(); fetchFindGroup(); - - _addFocusListener(_employeeCodeFocusNode, (focus) => _employeeCodeFocus = focus); - _addFocusListener(_departmentFocusNode, (focus) => _departmentFocus = focus); - _addFocusListener(_groupFocusNode, (focus) => _groupFocus = focus); - _addFocusListener(_firstApprovalFocusNode, (focus) => _firstApprovalFocus = focus); - _addFocusListener(_secondApprovalFocusNode, (focus) => _secondApprovalFocus = focus); - _addFocusListener(_thirdApprovalFocusNode, (focus) => _thirdApprovalFocus = focus); - _addFocusListener(_exceptionalApprovalFocusNode, (focus) => _exceptionalApprovalFocus = focus); - _addFocusListener(_delegateFocusNode, (focus) => _delegateFocus = focus); - _addFocusListener(_startDateFocusNode, (focus) => _startDateFocus = focus); - _addFocusListener(_endDateFocusNode, (focus) => _endDateFocus = focus); - + _addFocusListener( + _employeeCodeFocusNode, + (focus) => _employeeCodeFocus = focus, + ); + _addFocusListener( + _departmentFocusNode, + (focus) => _departmentFocus = focus, + ); + _addFocusListener(_groupFocusNode, (focus) => _groupFocus = focus); + _addFocusListener( + _firstApprovalFocusNode, + (focus) => _firstApprovalFocus = focus, + ); + _addFocusListener( + _secondApprovalFocusNode, + (focus) => _secondApprovalFocus = focus, + ); + _addFocusListener( + _thirdApprovalFocusNode, + (focus) => _thirdApprovalFocus = focus, + ); + _addFocusListener( + _exceptionalApprovalFocusNode, + (focus) => _exceptionalApprovalFocus = focus, + ); + _addFocusListener(_delegateFocusNode, (focus) => _delegateFocus = focus); + _addFocusListener(_startDateFocusNode, (focus) => _startDateFocus = focus); + _addFocusListener(_endDateFocusNode, (focus) => _endDateFocus = focus); } void _addFocusListener(FocusNode node, Function(bool) updateState) { @@ -219,14 +235,14 @@ class OfficeDetailsState 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; }); } @@ -372,32 +388,35 @@ class OfficeDetailsState extends State { ), ), ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 20), - _buildFirstRow(widget.isDesktop), - if (widget.isDesktop) SizedBox(height: 10), - _buildSecondRow(widget.isDesktop), - if (widget.isDesktop) SizedBox(height: 10), - _buildThirdRow(widget.isDesktop), - if (widget.isDesktop) SizedBox(height: 10), - Divider(thickness: 0.2, color: Colors.blueGrey.shade100), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Delegation", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w500, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 20), + _buildFirstRow(widget.isDesktop), + if (widget.isDesktop) SizedBox(height: 10), + _buildSecondRow(widget.isDesktop), + if (widget.isDesktop) SizedBox(height: 10), + _buildThirdRow(widget.isDesktop), + if (widget.isDesktop) SizedBox(height: 10), + Divider(thickness: 0.2, color: Colors.blueGrey.shade100), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Delegation", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w500, + ), ), - ), - ], - ), - SizedBox(height: 15), - _buildFourthRow(widget.isDesktop), - ], + ], + ), + SizedBox(height: 15), + _buildFourthRow(widget.isDesktop), + ], + ), ), ); } @@ -462,21 +481,18 @@ class OfficeDetailsState extends State { return Container( color: Colors.white, child: - widget.isDesktop - ? Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - buildExceptionApprover(isDesktop), - Spacer(), - ], - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - buildExceptionApprover(isDesktop), - SizedBox(height: 8), // Vertical space - ], - ), + widget.isDesktop + ? Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [buildExceptionApprover(isDesktop), Spacer()], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildExceptionApprover(isDesktop), + SizedBox(height: 8), // Vertical space + ], + ), ); } @@ -669,95 +685,100 @@ class OfficeDetailsState extends State { // Request focus when user taps _departmentFocusNode?.requestFocus(); }, - child: DropdownSearch( - selectedItem: departmentMap[selectedDepartment], - enabled: !widget.isViewMode, - popupProps: PopupProps.menu( - showSearchBox: true, - fit: FlexFit.loose, - menuProps: const MenuProps(backgroundColor: Colors.white), - itemBuilder: - (context, item, isSelected) => Container( - padding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 6, - ), - child: Text( - item, - style: GoogleFonts.poppins(fontSize: 11.5), + child: DropdownSearch( + selectedItem: departmentMap[selectedDepartment], + enabled: !widget.isViewMode, + popupProps: PopupProps.menu( + showSearchBox: true, + fit: FlexFit.loose, + menuProps: const MenuProps(backgroundColor: Colors.white), + itemBuilder: + (context, item, isSelected) => Container( + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + child: Text( + item, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + ), + constraints: BoxConstraints(maxHeight: 200), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search Department...", + contentPadding: EdgeInsets.symmetric(horizontal: 10), ), ), - constraints: BoxConstraints(maxHeight: 200), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search Department...", - contentPadding: EdgeInsets.symmetric(horizontal: 10), ), + items: departmentMap.values.toList(), + + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (_departmentFocus) ? (layoutColor) : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_departmentFocus) ? (layoutColor) : Colors.white, + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: (layoutColor ?? Colors.grey), + width: 0.5, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 8.0, + ), + // contentPadding: EdgeInsets.symmetric(horizontal: 1), + ), + ), + dropdownBuilder: + (context, selectedItem) => Align( + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select Department", + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), + ), + ), + onChanged: + widget.isViewMode + ? null + : (String? newValue) { + if (newValue == null) return; + + final departmentId = + departmentMap.entries + .firstWhere( + (entry) => entry.value == newValue, + ) + .key; + + setState(() { + selectedDepartment = departmentId; + }); + + widget.onDepartmentChanged?.call( + departmentId, + ); // Send department_id + }, ), ), - items: departmentMap.values.toList(), - - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (_departmentFocus) - ? (layoutColor) - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_departmentFocus) - ? (layoutColor) - : Colors.white, - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color : (layoutColor ?? Colors.grey), width: 0.5), - ), - contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0), - // contentPadding: EdgeInsets.symmetric(horizontal: 1), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select Department", - style: GoogleFonts.poppins( - fontSize: 12, - color: Colors.black, - ), - ), - ), - onChanged: - widget.isViewMode - ? null - : (String? newValue) { - if (newValue == null) return; - - final departmentId = - departmentMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; - - setState(() { - selectedDepartment = departmentId; - }); - - widget.onDepartmentChanged?.call( - departmentId, - ); // Send department_id - }, - ),),), + ), ), ), ], @@ -840,113 +861,121 @@ class OfficeDetailsState extends State { // Request focus when user taps _groupFocusNode?.requestFocus(); }, - child: - apiAllGroups == null - ? Center( - child: Transform.scale( - scale: 0.5, - child: CircularProgressIndicator(), - ), - ) - : DropdownSearch( - selectedItem: groupMap[selectedLevel], - enabled: !widget.isViewMode, + child: + apiAllGroups == null + ? Center( + child: Transform.scale( + scale: 0.5, + child: CircularProgressIndicator(), + ), + ) + : DropdownSearch( + selectedItem: groupMap[selectedLevel], + enabled: !widget.isViewMode, - popupProps: PopupProps.menu( - menuProps: const MenuProps( - backgroundColor: Colors.white, - ), - showSearchBox: true, - fit: FlexFit.loose, // Allows flexible height - itemBuilder: - (context, item, isSelected) => Container( - padding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 6, - ), - child: Text( - item, - style: GoogleFonts.poppins(fontSize: 11.5), + popupProps: PopupProps.menu( + menuProps: const MenuProps( + backgroundColor: Colors.white, + ), + showSearchBox: true, + fit: FlexFit.loose, // Allows flexible height + itemBuilder: + (context, item, isSelected) => Container( + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + child: Text( + item, + style: GoogleFonts.poppins(fontSize: 11.5), + ), + ), + constraints: BoxConstraints(maxHeight: 250), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search Group...", + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + ), ), ), - constraints: BoxConstraints(maxHeight: 250), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search Group...", - contentPadding: EdgeInsets.symmetric( - horizontal: 10, + ), + + // items: apiAllGroups!.map((group) { + // return "${group['name']} "; + // }).toList(), + items: + apiAllGroups!.map((group) { + return group['name'] + .toString() + .trim(); // <-- trim spaces + }).toList(), + + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide( + color: + (_groupFocus ?? false) + ? (layoutColor ?? Colors.white) + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_groupFocus ?? false) + ? (layoutColor ?? Colors.white) + : Colors.white, + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: (layoutColor ?? Colors.grey), + width: 0.5, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 8.0, + ), ), ), + dropdownBuilder: + (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select", + style: GoogleFonts.poppins(fontSize: 12), + ), + ), + + onChanged: (String? newValue) { + if (newValue == null) return; + + final levelId = + groupMap.entries + .firstWhere( + (entry) => entry.value == newValue, + ) + .key; + + setState(() { + selectedLevel = levelId; + }); + + widget.onLevelChanged?.call( + levelId, + ); // ✅ pass the ID not the name + }, ), - ), - - // items: apiAllGroups!.map((group) { - // return "${group['name']} "; - // }).toList(), - items: - apiAllGroups!.map((group) { - return group['name'] - .toString() - .trim(); // <-- trim spaces - }).toList(), - - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (_groupFocus ?? false) - ? (layoutColor ?? Colors.white) - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_groupFocus ?? false) - ? (layoutColor ?? Colors.white) - : Colors.white, - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color : (layoutColor ?? Colors.grey), width: 0.5), - ), - contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins(fontSize: 12), - ), - ), - - onChanged: (String? newValue) { - if (newValue == null) return; - - final levelId = - groupMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; - - setState(() { - selectedLevel = levelId; - }); - - widget.onLevelChanged?.call( - levelId, - ); // ✅ pass the ID not the name - }, - ), - ),), + ), + ), ), ), ], @@ -986,7 +1015,7 @@ class OfficeDetailsState extends State { focusNode: _firstApprovalFocusNode, onFocusChange: (hasFocus) { setState(() { - _firstApprovalFocus= hasFocus; + _firstApprovalFocus = hasFocus; }); }, child: GestureDetector( @@ -994,124 +1023,148 @@ class OfficeDetailsState extends State { // Request focus when user taps _firstApprovalFocusNode?.requestFocus(); }, - child: - apiUserData == null - ? Center( - child: Transform.scale( - scale: 0.5, - child: CircularProgressIndicator(), - ), - ) - : DropdownSearch( - selectedItem: userMap[selectedFirstApprover], - enabled: !widget.isViewMode, - popupProps: PopupProps.menu( - showSearchBox: true, - fit: FlexFit.loose, // Allows flexible height - menuProps: const MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: - (context, item, isSelected) => Container( - padding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 6, - ), - child: Text( - item, - style: GoogleFonts.poppins( - fontSize: 11.5, + child: + apiUserData == null + ? Center( + child: Transform.scale( + scale: 0.5, + child: CircularProgressIndicator(), + ), + ) + : DropdownSearch( + selectedItem: + userMap[selectedFirstApprover], + enabled: !widget.isViewMode, + popupProps: PopupProps.menu( + showSearchBox: true, + fit: + FlexFit + .loose, // Allows flexible height + menuProps: const MenuProps( + backgroundColor: Colors.white, + ), + itemBuilder: + (context, item, isSelected) => + Container( + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + child: Text( + item, + style: GoogleFonts.poppins( + fontSize: 11.5, + ), + ), + ), + constraints: BoxConstraints( + maxHeight: 250, + ), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search User...", + contentPadding: EdgeInsets.symmetric( + horizontal: 10, ), ), ), - constraints: BoxConstraints(maxHeight: 250), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search User...", - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - ), ), - ), - ), - items: - apiUserData!.map((user) { - return "${user['first_name']} ${user['last_name']}"; - }).toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (_firstApprovalFocus ?? false) - ? (layoutColor ?? Colors.white) - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_firstApprovalFocus ?? false) - ? (layoutColor ?? Colors.white) - : Colors.white, - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color : (layoutColor ?? Colors.grey), width: 0.5), - ), - contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, + items: + apiUserData!.map((user) { + return "${user['first_name']} ${user['last_name']}"; + }).toList(), + dropdownDecoratorProps: + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: OutlineInputBorder( + borderRadius: + BorderRadius.circular(8), + borderSide: BorderSide( + color: + (_firstApprovalFocus ?? + false) + ? (layoutColor ?? + Colors.white) + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_firstApprovalFocus ?? + false) + ? (layoutColor ?? + Colors.white) + : Colors.white, + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + (layoutColor ?? + Colors.grey), + width: 0.5, + ), + ), + contentPadding: + EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 8.0, + ), + ), + ), + dropdownBuilder: + (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + ), + ), ), - ), - ), - // onChanged: (String? newValue) { - // setState(() { - // selectedFirstApprover = userMap.entries - // .firstWhere( - // (entry) => entry.value == newValue) - // .key; - // - // // if (selectedCountry!.isNotEmpty) { - // // errorMessages.remove("country_code"); - // // } - // }); - // widget.onFirstApproverChanged?.call(newValue); - // }, - onChanged: (String? newValue) { - if (newValue == null) return; + // onChanged: (String? newValue) { + // setState(() { + // selectedFirstApprover = userMap.entries + // .firstWhere( + // (entry) => entry.value == newValue) + // .key; + // + // // if (selectedCountry!.isNotEmpty) { + // // errorMessages.remove("country_code"); + // // } + // }); + // widget.onFirstApproverChanged?.call(newValue); + // }, + onChanged: (String? newValue) { + if (newValue == null) return; - final approverId = - userMap.entries - .firstWhere( - (entry) => entry.value == newValue, - ) - .key; + final approverId = + userMap.entries + .firstWhere( + (entry) => + entry.value == newValue, + ) + .key; - setState(() { - selectedFirstApprover = approverId; - }); + setState(() { + selectedFirstApprover = approverId; + }); - widget.onFirstApproverChanged?.call( - approverId, - ); // ✅ not newValue, but approverId - }, - ), - ),), + widget.onFirstApproverChanged?.call( + approverId, + ); // ✅ not newValue, but approverId + }, + ), + ), + ), ), ), ], @@ -1166,123 +1219,147 @@ class OfficeDetailsState extends State { // Request focus when user taps _secondApprovalFocusNode?.requestFocus(); }, - child: - apiUserData == null - ? Center( - child: Transform.scale( - scale: 0.5, - child: CircularProgressIndicator(), - ), - ) - : DropdownSearch( - selectedItem: userMap[selectedSecondApprover], - enabled: !widget.isViewMode, - popupProps: PopupProps.menu( - showSearchBox: true, - fit: FlexFit.loose, // Allows flexible height - menuProps: const MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: - (context, item, isSelected) => Container( - padding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 6, - ), - child: Text( - item, - style: GoogleFonts.poppins( - fontSize: 11.5, + child: + apiUserData == null + ? Center( + child: Transform.scale( + scale: 0.5, + child: CircularProgressIndicator(), + ), + ) + : DropdownSearch( + selectedItem: + userMap[selectedSecondApprover], + enabled: !widget.isViewMode, + popupProps: PopupProps.menu( + showSearchBox: true, + fit: + FlexFit + .loose, // Allows flexible height + menuProps: const MenuProps( + backgroundColor: Colors.white, + ), + itemBuilder: + (context, item, isSelected) => + Container( + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + child: Text( + item, + style: GoogleFonts.poppins( + fontSize: 11.5, + ), + ), + ), + constraints: BoxConstraints( + maxHeight: 250, + ), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search User...", + contentPadding: EdgeInsets.symmetric( + horizontal: 10, ), ), ), - constraints: BoxConstraints(maxHeight: 250), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search User...", - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - ), ), - ), - ), - items: - apiUserData!.map((user) { - return "${user['first_name']} ${user['last_name']}"; - }).toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (_secondApprovalFocus ?? false) - ? (layoutColor ?? Colors.white) - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_secondApprovalFocus ?? false) - ? (layoutColor ?? Colors.white) - : Colors.white, - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color : (layoutColor ?? Colors.grey), width: 0.5), - ), - contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, + items: + apiUserData!.map((user) { + return "${user['first_name']} ${user['last_name']}"; + }).toList(), + dropdownDecoratorProps: + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: OutlineInputBorder( + borderRadius: + BorderRadius.circular(8), + borderSide: BorderSide( + color: + (_secondApprovalFocus ?? + false) + ? (layoutColor ?? + Colors.white) + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_secondApprovalFocus ?? + false) + ? (layoutColor ?? + Colors.white) + : Colors.white, + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + (layoutColor ?? + Colors.grey), + width: 0.5, + ), + ), + contentPadding: + EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 8.0, + ), + ), + ), + dropdownBuilder: + (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + ), + ), ), - ), - ), - onChanged: (String? newValue) { - if (newValue == null) return; + onChanged: (String? newValue) { + if (newValue == null) return; - final approverId = - userMap.entries - .firstWhere( - (entry) => entry.value == newValue, - ) - .key; + final approverId = + userMap.entries + .firstWhere( + (entry) => + entry.value == newValue, + ) + .key; - setState(() { - selectedSecondApprover = approverId; - }); + setState(() { + selectedSecondApprover = approverId; + }); - widget.onSecondApproverChanged?.call( - approverId, - ); // ✅ not newValue, but approverId - }, - // onChanged: (String? newValue) { - // setState(() { - // selectedSecondApprover = userMap.entries - // .firstWhere( - // (entry) => entry.value == newValue) - // .key; - // - // // if (selectedCountry!.isNotEmpty) { - // // errorMessages.remove("country_code"); - // // } - // }); - // }, - ), - ),), + widget.onSecondApproverChanged?.call( + approverId, + ); // ✅ not newValue, but approverId + }, + // onChanged: (String? newValue) { + // setState(() { + // selectedSecondApprover = userMap.entries + // .firstWhere( + // (entry) => entry.value == newValue) + // .key; + // + // // if (selectedCountry!.isNotEmpty) { + // // errorMessages.remove("country_code"); + // // } + // }); + // }, + ), + ), + ), ), ), ], @@ -1337,122 +1414,146 @@ class OfficeDetailsState extends State { // Request focus when user taps _thirdApprovalFocusNode?.requestFocus(); }, - child: - apiUserData == null - ? Center( - child: Transform.scale( - scale: 0.5, - child: CircularProgressIndicator(), - ), - ) - : DropdownSearch( - selectedItem: userMap[selectedThirdApprover], - enabled: !widget.isViewMode, - popupProps: PopupProps.menu( - showSearchBox: true, - fit: FlexFit.loose, // Allows flexible height - menuProps: const MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: - (context, item, isSelected) => Container( - padding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 6, - ), - child: Text( - item, - style: GoogleFonts.poppins( - fontSize: 11.5, + child: + apiUserData == null + ? Center( + child: Transform.scale( + scale: 0.5, + child: CircularProgressIndicator(), + ), + ) + : DropdownSearch( + selectedItem: + userMap[selectedThirdApprover], + enabled: !widget.isViewMode, + popupProps: PopupProps.menu( + showSearchBox: true, + fit: + FlexFit + .loose, // Allows flexible height + menuProps: const MenuProps( + backgroundColor: Colors.white, + ), + itemBuilder: + (context, item, isSelected) => + Container( + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + child: Text( + item, + style: GoogleFonts.poppins( + fontSize: 11.5, + ), + ), + ), + constraints: BoxConstraints( + maxHeight: 250, + ), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search User...", + contentPadding: EdgeInsets.symmetric( + horizontal: 10, ), ), ), - constraints: BoxConstraints(maxHeight: 250), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search User...", - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - ), ), - ), - ), - items: - apiUserData!.map((user) { - return "${user['first_name']} ${user['last_name']}"; - }).toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (_thirdApprovalFocus ?? false) - ? (layoutColor ?? Colors.white) - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_thirdApprovalFocus ?? false) - ? (layoutColor ?? Colors.white) - : Colors.white, - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color : (layoutColor ?? Colors.grey), width: 0.5), - ), - contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, + items: + apiUserData!.map((user) { + return "${user['first_name']} ${user['last_name']}"; + }).toList(), + dropdownDecoratorProps: + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: OutlineInputBorder( + borderRadius: + BorderRadius.circular(8), + borderSide: BorderSide( + color: + (_thirdApprovalFocus ?? + false) + ? (layoutColor ?? + Colors.white) + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_thirdApprovalFocus ?? + false) + ? (layoutColor ?? + Colors.white) + : Colors.white, + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + (layoutColor ?? + Colors.grey), + width: 0.5, + ), + ), + contentPadding: + EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 8.0, + ), + ), ), - ), - ), - onChanged: (String? newValue) { - if (newValue == null) return; + dropdownBuilder: + (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + ), + ), + ), + onChanged: (String? newValue) { + if (newValue == null) return; - final approverId = - userMap.entries - .firstWhere( - (entry) => entry.value == newValue, - ) - .key; + final approverId = + userMap.entries + .firstWhere( + (entry) => + entry.value == newValue, + ) + .key; - setState(() { - selectedThirdApprover = approverId; - }); + setState(() { + selectedThirdApprover = approverId; + }); - widget.onThirdApproverChanged?.call( - approverId, - ); // ✅ not newValue, but approverId - }, - // onChanged: (String? newValue) { - // setState(() { - // selectedThirdApprover = userMap.entries - // .firstWhere( - // (entry) => entry.value == newValue) - // .key; - // - // // if (selectedCountry!.isNotEmpty) { - // // errorMessages.remove("country_code"); - // // } - // }); - // }, - ), - ),), + widget.onThirdApproverChanged?.call( + approverId, + ); // ✅ not newValue, but approverId + }, + // onChanged: (String? newValue) { + // setState(() { + // selectedThirdApprover = userMap.entries + // .firstWhere( + // (entry) => entry.value == newValue) + // .key; + // + // // if (selectedCountry!.isNotEmpty) { + // // errorMessages.remove("country_code"); + // // } + // }); + // }, + ), + ), + ), ), ), ], @@ -1480,7 +1581,7 @@ class OfficeDetailsState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Exceptional Approver", + "Fourth Approver", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w600, @@ -1507,111 +1608,132 @@ class OfficeDetailsState extends State { // Request focus when user taps _exceptionalApprovalFocusNode?.requestFocus(); }, - child: - apiUserData == null - ? Center( - child: Transform.scale( - scale: 0.5, - child: CircularProgressIndicator(), - ), - ) - : DropdownSearch( - selectedItem: userMap[selectedExceptionalApprover], - enabled: !widget.isViewMode, - popupProps: PopupProps.menu( - showSearchBox: true, - fit: FlexFit.loose, // Allows flexible height - menuProps: const MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: - (context, item, isSelected) => Container( - padding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 6, - ), - child: Text( - item, - style: GoogleFonts.poppins( - fontSize: 11.5, - ), - ), - ), - constraints: BoxConstraints(maxHeight: 250), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search User...", - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - ), - ), - ), - ), - items: - apiUserData!.map((user) { - return "${user['first_name']} ${user['last_name']}"; - }).toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (_exceptionalApprovalFocus ?? false) - ? (layoutColor ?? Colors.white) - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_exceptionalApprovalFocus ?? false) - ? (layoutColor ?? Colors.white) - : Colors.white, - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color : (layoutColor ?? Colors.white), width: 0.5), - ), - contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, - ), - ), - ), + child: + apiUserData == null + ? Center( + child: Transform.scale( + scale: 0.5, + child: CircularProgressIndicator(), + ), + ) + : DropdownSearch( + selectedItem: + userMap[selectedExceptionalApprover], + enabled: !widget.isViewMode, + popupProps: PopupProps.menu( + showSearchBox: true, + fit: + FlexFit + .loose, // Allows flexible height + menuProps: const MenuProps( + backgroundColor: Colors.white, + ), + itemBuilder: + (context, item, isSelected) => + Container( + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + child: Text( + item, + style: GoogleFonts.poppins( + fontSize: 11.5, + ), + ), + ), + constraints: BoxConstraints( + maxHeight: 250, + ), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search User...", + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + ), + ), + ), + ), + items: + apiUserData!.map((user) { + return "${user['first_name']} ${user['last_name']}"; + }).toList(), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular( + 8, + ), + borderSide: BorderSide( + color: + (_exceptionalApprovalFocus ?? + false) + ? (layoutColor ?? + Colors.white) + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_exceptionalApprovalFocus ?? + false) + ? (layoutColor ?? + Colors.white) + : Colors.white, + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (layoutColor ?? Colors.white), + width: 0.5, + ), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 8.0, + ), + ), + ), + dropdownBuilder: + (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + ), + ), + ), - onChanged: (String? newValue) { - if (newValue == null) return; + onChanged: (String? newValue) { + if (newValue == null) return; - final approverId = - userMap.entries - .firstWhere( - (entry) => entry.value == newValue, - ) - .key; + final approverId = + userMap.entries + .firstWhere( + (entry) => + entry.value == newValue, + ) + .key; - setState(() { - selectedExceptionalApprover = approverId; - }); + setState(() { + selectedExceptionalApprover = + approverId; + }); - widget.onExceptionalApproverChanged?.call( - approverId, - ); // ✅ not newValue, but approverId - }, + widget.onExceptionalApproverChanged?.call( + approverId, + ); // ✅ not newValue, but approverId + }, + ), + ), ), - ),), ), ), ], @@ -1625,7 +1747,6 @@ class OfficeDetailsState extends State { ); } - Widget buildApproverSubstitute1(bool isDesktop) { return Container( color: Colors.white, @@ -1666,128 +1787,151 @@ class OfficeDetailsState extends State { onTap: () { _delegateFocusNode?.requestFocus(); }, - child: - apiUserData == null - ? Center( - child: Transform.scale( - scale: 0.5, - child: CircularProgressIndicator(), - ), - ) - : DropdownSearch( - // selectedItem: userMap[selectedSubstituteApprover], - selectedItem: - selectedSubstituteApprover != null - ? userMap[selectedSubstituteApprover] - : null, - enabled: !widget.isViewMode, - popupProps: PopupProps.menu( - showSearchBox: true, - fit: FlexFit.loose, // Allows flexible height - menuProps: const MenuProps( - backgroundColor: Colors.white, - ), - itemBuilder: - (context, item, isSelected) => Container( - padding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 6, - ), - child: Text( - item, - style: GoogleFonts.poppins( - fontSize: 11.5, + child: + apiUserData == null + ? Center( + child: Transform.scale( + scale: 0.5, + child: CircularProgressIndicator(), + ), + ) + : DropdownSearch( + // selectedItem: userMap[selectedSubstituteApprover], + selectedItem: + selectedSubstituteApprover != null + ? userMap[selectedSubstituteApprover] + : null, + enabled: !widget.isViewMode, + popupProps: PopupProps.menu( + showSearchBox: true, + fit: + FlexFit + .loose, // Allows flexible height + menuProps: const MenuProps( + backgroundColor: Colors.white, + ), + itemBuilder: + (context, item, isSelected) => + Container( + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + child: Text( + item, + style: GoogleFonts.poppins( + fontSize: 11.5, + ), + ), + ), + constraints: BoxConstraints( + maxHeight: 133, + ), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search User...", + contentPadding: EdgeInsets.symmetric( + horizontal: 10, ), ), ), - constraints: BoxConstraints(maxHeight: 133), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search User...", - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - ), ), - ), - ), - items: - apiUserData!.map((user) { - return "${user['first_name']} ${user['last_name']}"; - }).toList(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: - (_delegateFocus ?? false) - ? (layoutColor ?? Colors.white) - : Colors.white, - width: 0.5, - ), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: - (_delegateFocus ?? false) - ? (layoutColor ?? Colors.white) - : Colors.white, - width: 0.5, - // const Color(0xFFD6D5E6), - ), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color : (layoutColor ?? Colors.grey), width: 0.5), - ), - contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0), - ), - ), - dropdownBuilder: - (context, selectedItem) => Align( - // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select", - style: GoogleFonts.poppins( - fontSize: 12, + items: + apiUserData!.map((user) { + return "${user['first_name']} ${user['last_name']}"; + }).toList(), + dropdownDecoratorProps: + DropDownDecoratorProps( + dropdownSearchDecoration: + InputDecoration( + border: OutlineInputBorder( + borderRadius: + BorderRadius.circular(8), + borderSide: BorderSide( + color: + (_delegateFocus ?? + false) + ? (layoutColor ?? + Colors.white) + : Colors.white, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: + (_delegateFocus ?? + false) + ? (layoutColor ?? + Colors.white) + : Colors.white, + width: 0.5, + // const Color(0xFFD6D5E6), + ), + ), + focusedBorder: + OutlineInputBorder( + borderSide: BorderSide( + color: + (layoutColor ?? + Colors.grey), + width: 0.5, + ), + ), + contentPadding: + EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 8.0, + ), + ), + ), + dropdownBuilder: + (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select", + style: GoogleFonts.poppins( + fontSize: 12, + ), + ), ), - ), - ), - // onChanged: (String? newValue) { - // setState(() { - // selectedFirstApprover = userMap.entries - // .firstWhere( - // (entry) => entry.value == newValue) - // .key; - // - // // if (selectedCountry!.isNotEmpty) { - // // errorMessages.remove("country_code"); - // // } - // }); - // widget.onFirstApproverChanged?.call(newValue); - // }, - onChanged: (String? newValue) { - if (newValue == null) return; + // onChanged: (String? newValue) { + // setState(() { + // selectedFirstApprover = userMap.entries + // .firstWhere( + // (entry) => entry.value == newValue) + // .key; + // + // // if (selectedCountry!.isNotEmpty) { + // // errorMessages.remove("country_code"); + // // } + // }); + // widget.onFirstApproverChanged?.call(newValue); + // }, + onChanged: (String? newValue) { + if (newValue == null) return; - final approverId = - userMap.entries - .firstWhere( - (entry) => entry.value == newValue, - ) - .key; + final approverId = + userMap.entries + .firstWhere( + (entry) => + entry.value == newValue, + ) + .key; - setState(() { - selectedSubstituteApprover = approverId; - }); + setState(() { + selectedSubstituteApprover = approverId; + }); - widget.onFirstSubsApproverChanged?.call( - approverId, - ); // ✅ not newValue, but approverId - }, - ), - ),), + widget.onFirstSubsApproverChanged?.call( + approverId, + ); // ✅ not newValue, but approverId + }, + ), + ), + ), ), ), ], @@ -1869,7 +2013,7 @@ class OfficeDetailsState extends State { isDesktop: widget.isDesktop, child: SizedBox( height: 40, - child:Focus( + child: Focus( focusNode: _startDateFocusNode, onKeyEvent: (FocusNode node, KeyEvent event) { // Only act on KeyDown and when Enter is pressed @@ -1886,13 +2030,16 @@ class OfficeDetailsState extends State { behavior: HitTestBehavior.opaque, onTapDown: (details) { _startDateFocusNode?.requestFocus(); - _selectCheckOutDate(context); + _selectCheckOutDate(context); }, child: AbsorbPointer( child: TextField( controller: widget.controllers["delegationStartDate"], readOnly: true, - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), decoration: InputDecoration( labelText: "Select Date", labelStyle: GoogleFonts.poppins( @@ -2020,7 +2167,7 @@ class OfficeDetailsState extends State { isDesktop: widget.isDesktop, child: SizedBox( height: 40, - child:Focus( + child: Focus( focusNode: _endDateFocusNode, onKeyEvent: (FocusNode node, KeyEvent event) { // Only act on KeyDown and when Enter is pressed @@ -2041,7 +2188,7 @@ class OfficeDetailsState extends State { onTapDown: (details) { if (!widget.isViewMode) { _selectForexEndDate(context).then((_) { - _endDateFocusNode?.requestFocus(); + _endDateFocusNode?.requestFocus(); }); } }, @@ -2049,7 +2196,10 @@ class OfficeDetailsState extends State { child: TextField( controller: widget.controllers["delegationEndDate"], readOnly: true, - style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), + style: GoogleFonts.poppins( + fontSize: 12, + color: Colors.black, + ), decoration: InputDecoration( labelText: "Select Date", labelStyle: GoogleFonts.poppins( diff --git a/lib/Screens/userManagement/user_List.dart b/lib/Screens/userManagement/user_List.dart index bebdd02..2712a67 100644 --- a/lib/Screens/userManagement/user_List.dart +++ b/lib/Screens/userManagement/user_List.dart @@ -225,222 +225,294 @@ class _UserListScreenState extends State { print("handDel - $userId"); } - void _showConfirmationDialog(String subtitle, List successList, List> failedList) { + void _showConfirmationDialog( + String subtitle, + List successList, + List> failedList, + ) { _dialogShown = true; showDialog( context: context, - builder: (context) => AlertDialog( - // title: Text("User Details"), - title: Text("Upload Status - $subtitle", style: GoogleFonts.poppins( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Colors.black, - ), overflow: TextOverflow.ellipsis), - content: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Text(subtitle, style: TextStyle(fontWeight: FontWeight.bold)), - // - // SizedBox(height: 12), - Text("Success Report :", style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w400, + builder: + (context) => AlertDialog( + // title: Text("User Details"), + title: Text( + "Upload Status - $subtitle", + style: GoogleFonts.poppins( + fontSize: 18, + fontWeight: FontWeight.w600, color: Colors.black, - )), - // if (successList.isNotEmpty) - // ...successList.asMap().entries.map((entry) => Text("${entry.key + 1}) ${entry.value} created.")) - if (successList.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, - color: Colors.black, - ), - ), - ), - DataColumn( - label: Text( - 'Data', - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ), - ), - ) - ], - rows: successList.asMap().entries.map((entry) { - final newIndex = entry.key + 1; - final data = entry.value?.toString().trim().isNotEmpty == true - ? entry.value.toString() - : '-'; - - return DataRow( - cells: [ - DataCell( - Text( - '$newIndex', - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Colors.black, - ), - ), - ), - DataCell( - SizedBox( - width: 460, - child: Text( - data, - style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Colors.black, - ), - overflow: TextOverflow.ellipsis, - ), - ), - ), - ], - ); - }).toList(), + ), + overflow: TextOverflow.ellipsis, ), - ), - ), - ) - else - Text("-- no data. --",style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w200, - color: Colors.black, - )), - SizedBox(height: 12), - // Text("Failed Report :", style: TextStyle(fontWeight: FontWeight.bold)), - Text("Failed Report :", style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Colors.black, - )), - // if (failedList.isNotEmpty) - // ...failedList.asMap().entries.map((entry) { - // final data = entry.value["data"] ?? "-"; - // final reason = entry.value["reason"] ?? "Unknown error"; - // return Text("${entry.key + 1}) $data - unable to create due to \"$reason\"."); - // }) - - if (failedList.isNotEmpty) - SizedBox( - height: 250, // Vertical scroll height - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, // Enable horizontal scrolling - child: SingleChildScrollView( - scrollDirection: Axis.vertical, // Enable vertical scrolling - child: DataTable( - columns: [ - DataColumn(label: Text('S.No', style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ))), - DataColumn(label: Text('Data', style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ))), - DataColumn(label: Text('Reason', style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ))), - ], - rows: failedList.asMap().entries.map((entry) { - final index = entry.key + 1; - final rawData = entry.value['data']; - final data = (rawData == null || rawData.toString().trim().isEmpty) ? '-' : rawData.toString(); - final reason = entry.value['reason'] ?? 'Unknown error'; - - return DataRow(cells: [ - DataCell(Text('$index',style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Colors.black, - ))), - DataCell(SizedBox( - width: 180, - child: Text(data, style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Colors.black, - ), overflow: TextOverflow.ellipsis), - )), - DataCell(SizedBox( - width: 280, - child: Text(reason, style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Colors.black, - ),overflow: TextOverflow.ellipsis), - )), - ]); - }).toList(), - ), + content: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Text(subtitle, style: TextStyle(fontWeight: FontWeight.bold)), + // + // SizedBox(height: 12), + Text( + "Success Report :", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Colors.black, ), ), - ) - else - Text("-- no data. --",style: GoogleFonts.poppins( - fontSize: 14, - fontWeight: FontWeight.w200, - color: Colors.black, - )), + // if (successList.isNotEmpty) + // ...successList.asMap().entries.map((entry) => Text("${entry.key + 1}) ${entry.value} created.")) + if (successList.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, + color: Colors.black, + ), + ), + ), + DataColumn( + label: Text( + 'Data', + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + ), + ), + ], + rows: + successList.asMap().entries.map((entry) { + final newIndex = entry.key + 1; + final data = + entry.value + ?.toString() + .trim() + .isNotEmpty == + true + ? entry.value.toString() + : '-'; + + return DataRow( + cells: [ + DataCell( + Text( + '$newIndex', + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Colors.black, + ), + ), + ), + DataCell( + SizedBox( + width: 460, + child: Text( + data, + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Colors.black, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ), + ], + ); + }).toList(), + ), + ), + ), + ) + else + Text( + "-- no data. --", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w200, + color: Colors.black, + ), + ), + SizedBox(height: 12), + // Text("Failed Report :", style: TextStyle(fontWeight: FontWeight.bold)), + Text( + "Failed Report :", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Colors.black, + ), + ), + + // if (failedList.isNotEmpty) + // ...failedList.asMap().entries.map((entry) { + // final data = entry.value["data"] ?? "-"; + // final reason = entry.value["reason"] ?? "Unknown error"; + // return Text("${entry.key + 1}) $data - unable to create due to \"$reason\"."); + // }) + if (failedList.isNotEmpty) + SizedBox( + height: 250, // Vertical scroll height + child: SingleChildScrollView( + scrollDirection: + Axis.horizontal, // Enable horizontal scrolling + child: SingleChildScrollView( + scrollDirection: + Axis.vertical, // Enable vertical scrolling + child: DataTable( + columns: [ + DataColumn( + label: Text( + 'S.No', + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + ), + ), + DataColumn( + label: Text( + 'Data', + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + ), + ), + DataColumn( + label: Text( + 'Reason', + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + ), + ), + ], + rows: + failedList.asMap().entries.map((entry) { + final index = entry.key + 1; + final rawData = entry.value['data']; + final data = + (rawData == null || + rawData.toString().trim().isEmpty) + ? '-' + : rawData.toString(); + final reason = + entry.value['reason'] ?? 'Unknown error'; + + return DataRow( + cells: [ + DataCell( + Text( + '$index', + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Colors.black, + ), + ), + ), + DataCell( + SizedBox( + width: 180, + child: Text( + data, + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Colors.black, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ), + DataCell( + SizedBox( + width: 280, + child: Text( + reason, + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Colors.black, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ), + ], + ); + }).toList(), + ), + ), + ), + ) + else + Text( + "-- no data. --", + style: GoogleFonts.poppins( + fontSize: 14, + fontWeight: FontWeight.w200, + color: Colors.black, + ), + ), + ], + ), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + _dialogShown = false; + }, + child: Text("Close"), + ), ], ), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.pop(context); - _dialogShown = false; - }, - child: Text("Close"), - ), - ], - ), ); } - Future handleDownload() async { final result = await apiService.getDownloadUserTemplateForUpload(); - final String displayBackgroundColor = result['status'] ? '#28a745' : '#dc1c13'; - final Color displayColor = result['status'] ? Colors.green : Colors.redAccent; + final String displayBackgroundColor = + result['status'] ? '#28a745' : '#dc1c13'; + final Color displayColor = + result['status'] ? Colors.green : Colors.redAccent; final String displayMessage = result['message']; // final bool status = result['status'] == true; Fluttertoast.showToast( - msg: displayMessage , + msg: displayMessage, toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.CENTER, timeInSecForIosWeb: 2, backgroundColor: displayColor, textColor: Colors.white, fontSize: 18.0, - webBgColor: "linear-gradient(to right, $displayBackgroundColor, $displayBackgroundColor)", + webBgColor: + "linear-gradient(to right, $displayBackgroundColor, $displayBackgroundColor)", ); } + Future handleUpload() async { final Completer completer = Completer(); @@ -540,10 +612,15 @@ class _UserListScreenState extends State { final status = responseData['status'] ?? ''; final data = responseData['data'] ?? {}; - final List successList = List.from(data['successfulUsers'] ?? []); - final List> failedList = List>.from( - (data['failedUsers'] ?? []).map((item) => Map.from(item)), + final List successList = List.from( + data['successfulUsers'] ?? [], ); + final List> failedList = + List>.from( + (data['failedUsers'] ?? []).map( + (item) => Map.from(item), + ), + ); _showConfirmationDialog(message, successList, failedList); @@ -565,10 +642,10 @@ class _UserListScreenState extends State { // Refresh list if needed refreshUserList(); - } else { // For non-200 responses - final errorMsg = 'Failed to upload file: ${response.reasonPhrase}'; + final errorMsg = + 'Failed to upload file: ${response.reasonPhrase}'; Fluttertoast.showToast( msg: errorMsg, toastLength: Toast.LENGTH_SHORT, @@ -581,7 +658,6 @@ class _UserListScreenState extends State { ); print(errorMsg); } - } } return completer.future; // Wait for upload to finish before proceeding @@ -768,8 +844,7 @@ class _UserListScreenState extends State { @override Widget build(BuildContext context) { - return - ResponsiveBuilder( + return ResponsiveBuilder( builder: (context, sizingInfo) { bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop; @@ -958,32 +1033,33 @@ class _UserListScreenState extends State { // height: 25, // ), // tooltip: 'User Bulk Upload', - // onPressed: () { - // handleUpload(); - // }, + // onPressed: () { + // handleUpload(); + // }, // ), // UPLOAD BUTTON Align( alignment: Alignment.centerLeft, - child: _isUploading - ? const SizedBox( - width: 28, - height: 28, - child: CircularProgressIndicator(strokeWidth: 3), - ) - : IconButton( - icon: Image.asset( - 'assets/images/IconsImg/upload.png', - width: 25, - height: 25, - ), - tooltip: 'User Bulk Upload', - onPressed: () async { - setState(() => _isUploading = true); - await handleUpload(); - setState(() => _isUploading = false); - }, - ), + child: + _isUploading + ? const SizedBox( + width: 28, + height: 28, + child: CircularProgressIndicator(strokeWidth: 3), + ) + : IconButton( + icon: Image.asset( + 'assets/images/IconsImg/upload.png', + width: 25, + height: 25, + ), + tooltip: 'User Bulk Upload', + onPressed: () async { + setState(() => _isUploading = true); + await handleUpload(); + setState(() => _isUploading = false); + }, + ), ), // Spacer(), SizedBox(width: 5), @@ -1086,7 +1162,7 @@ class _UserListScreenState extends State { ], ), const SizedBox(height: 10), - FutureBuilder>( + FutureBuilder>( future: futureUsers, builder: (context, snapshot) { final adjHgt = MediaQuery.of(context).size.height; @@ -1283,7 +1359,7 @@ class _UserListScreenState extends State { DataCell( Row( mainAxisAlignment: - MainAxisAlignment.start, + MainAxisAlignment.start, children: [ GestureDetector( child: Tooltip( @@ -1297,199 +1373,205 @@ class _UserListScreenState extends State { onTap: () async { // Navigator.pop(context); // Close the menu // final userId = user['user_id']; - final userId = int.parse(user['user_id'].toString()); - final usersData = await apiService.getSingleUser(userId); - context.go("/CreateUserDetails", extra: { - "selectedUser": usersData, - "isViewMode": false, - }); + final userId = int.parse( + user['user_id'].toString(), + ); + final usersData = await apiService + .getSingleUser(userId); + context.go( + "/CreateUserDetails", + extra: { + "selectedUser": usersData, + "isViewMode": false, + }, + ); }, ), ], ), ), // DataCell( - // UserActionsMenu( - // user: user, - // getUserDetails: - // (id) => - // apiService.getSingleUser(id), - // ), - // 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), - // onPressed: () async { - // print( - // "USerDAta1 - $user"); - // // Fetch the user data properly with await - // Map - // usersData = - // await apiService - // .getSingleUser(user[ - // 'user_id'] - // is String - // ? int.parse(user[ - // 'user_id']) - // : user[ - // 'user_id']); - // - // print( - // "USerDAta2 - $usersData"); - // - // // userSingleData = - // // await apiService - // // .getSingleUser(user[ - // // 'user_id']); - // - // context.go( - // "/CreateUserDetails", - // extra: { - // "selectedUser": - // usersData, - // "isViewMode": true - // }, - // ); - // }), - // IconButton( - // icon: Image.asset( - // 'assets/images/IconsImg/edit.png', - // width: 20, - // height: 15), - // onPressed: () async { - // // Fetch the user data properly with await - // Map - // usersData = - // await apiService - // .getSingleUser(user[ - // 'user_id'] - // is String - // ? int.parse(user[ - // 'user_id']) - // : user[ - // 'user_id']); - // - // print( - // "USerDAta2 - $usersData"); - // context.go( - // "/CreateUserDetails", - // extra: { - // "selectedUser": - // usersData, - // "isViewMode": false - // }, - // ); - // }, - // ), - // ], - // ), - // ), - // ), - // ], - // ), - // Row( - // children: [ - // MouseRegion( - // cursor: user['is_active'] == "0" - // ? SystemMouseCursors.forbidden - // : SystemMouseCursors.click, - // child: IconButton( - // icon: Icon(Icons.remove_red_eye, - // size: 18, - // color: user['is_active'] == "0" - // ? Colors.grey - // : Color(0xFF475569)), - // onPressed: user['is_active'] == "0" - // ? null - // : () { - // context.go( - // "/CreateUserDetails", - // extra: { - // "selectedUser": user, - // "isViewMode": true - // }, - // ); - // }, - // ), - // ), - // - // MouseRegion( - // cursor: user['is_active'] == "0" - // ? SystemMouseCursors.forbidden - // : SystemMouseCursors.click, - // child: GestureDetector( - // onTap: user['is_active'] == "0" - // ? null - // : () { - // - // }, - // child: Image.asset( - // 'assets/images/IconsImg/edit.png', - // width: 20, - // height: 15), - // ), - // ), - // - // // MouseRegion( - // // cursor: user['is_active'] == "0" - // // ? SystemMouseCursors - // // .forbidden - // // : SystemMouseCursors.click, - // // child: IconButton( - // // icon: Icon(Icons.edit, - // // color: - // // user['is_active'] == - // // "0" - // // ? Colors.grey - // // : Colors.green), - // // onPressed: - // // user['is_active'] == "0" - // // ? null - // // : () { - // // print( - // // "USER: $user"); - // // - // // // final userJson = jsonEncode( - // // // user); // Convert user map to string - // // // final encodedUser = - // // // Uri.encodeComponent( - // // // userJson); - // // - // // context.go( - // // "/CreateUserDetails", - // // extra: { - // // "selectedUser": - // // user, - // // "isViewMode": - // // false - // // }, - // // ); - // // }, - // // ), - // // ), - // ], - // ), + // UserActionsMenu( + // user: user, + // getUserDetails: + // (id) => + // apiService.getSingleUser(id), + // ), + // 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), + // onPressed: () async { + // print( + // "USerDAta1 - $user"); + // // Fetch the user data properly with await + // Map + // usersData = + // await apiService + // .getSingleUser(user[ + // 'user_id'] + // is String + // ? int.parse(user[ + // 'user_id']) + // : user[ + // 'user_id']); + // + // print( + // "USerDAta2 - $usersData"); + // + // // userSingleData = + // // await apiService + // // .getSingleUser(user[ + // // 'user_id']); + // + // context.go( + // "/CreateUserDetails", + // extra: { + // "selectedUser": + // usersData, + // "isViewMode": true + // }, + // ); + // }), + // IconButton( + // icon: Image.asset( + // 'assets/images/IconsImg/edit.png', + // width: 20, + // height: 15), + // onPressed: () async { + // // Fetch the user data properly with await + // Map + // usersData = + // await apiService + // .getSingleUser(user[ + // 'user_id'] + // is String + // ? int.parse(user[ + // 'user_id']) + // : user[ + // 'user_id']); + // + // print( + // "USerDAta2 - $usersData"); + // context.go( + // "/CreateUserDetails", + // extra: { + // "selectedUser": + // usersData, + // "isViewMode": false + // }, + // ); + // }, + // ), + // ], + // ), + // ), + // ), + // ], + // ), + // Row( + // children: [ + // MouseRegion( + // cursor: user['is_active'] == "0" + // ? SystemMouseCursors.forbidden + // : SystemMouseCursors.click, + // child: IconButton( + // icon: Icon(Icons.remove_red_eye, + // size: 18, + // color: user['is_active'] == "0" + // ? Colors.grey + // : Color(0xFF475569)), + // onPressed: user['is_active'] == "0" + // ? null + // : () { + // context.go( + // "/CreateUserDetails", + // extra: { + // "selectedUser": user, + // "isViewMode": true + // }, + // ); + // }, + // ), + // ), + // + // MouseRegion( + // cursor: user['is_active'] == "0" + // ? SystemMouseCursors.forbidden + // : SystemMouseCursors.click, + // child: GestureDetector( + // onTap: user['is_active'] == "0" + // ? null + // : () { + // + // }, + // child: Image.asset( + // 'assets/images/IconsImg/edit.png', + // width: 20, + // height: 15), + // ), + // ), + // + // // MouseRegion( + // // cursor: user['is_active'] == "0" + // // ? SystemMouseCursors + // // .forbidden + // // : SystemMouseCursors.click, + // // child: IconButton( + // // icon: Icon(Icons.edit, + // // color: + // // user['is_active'] == + // // "0" + // // ? Colors.grey + // // : Colors.green), + // // onPressed: + // // user['is_active'] == "0" + // // ? null + // // : () { + // // print( + // // "USER: $user"); + // // + // // // final userJson = jsonEncode( + // // // user); // Convert user map to string + // // // final encodedUser = + // // // Uri.encodeComponent( + // // // userJson); + // // + // // context.go( + // // "/CreateUserDetails", + // // extra: { + // // "selectedUser": + // // user, + // // "isViewMode": + // // false + // // }, + // // ); + // // }, + // // ), + // // ), + // ], + // ), // ), ], ); @@ -1534,7 +1616,7 @@ class _UserListScreenState extends State { ), Row( mainAxisAlignment: - MainAxisAlignment.start, + MainAxisAlignment.start, children: [ GestureDetector( child: Tooltip( @@ -1546,14 +1628,31 @@ class _UserListScreenState extends State { ), ), onTap: () async { - Navigator.pop(context); // Close the menu - final userId = int.parse(user['user_id'].toString()); - final usersData = await apiService.getSingleUser(userId); - context.go("/CreateUserDetails", extra: { - "selectedUser": usersData, - "isViewMode": true, - }); + // Navigator.pop(context); // Close the menu + // final userId = user['user_id']; + final userId = int.parse( + user['user_id'].toString(), + ); + final usersData = await apiService + .getSingleUser(userId); + context.go( + "/CreateUserDetails", + extra: { + "selectedUser": usersData, + "isViewMode": false, + }, + ); }, + + // onTap: () async { + // Navigator.pop(context); // Close the menu + // final userId = int.parse(user['user_id'].toString()); + // final usersData = await apiService.getSingleUser(userId); + // context.go("/CreateUserDetails", extra: { + // "selectedUser": usersData, + // "isViewMode": true, + // }); + // }, ), ], ), 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/config/apiUrl.dart b/lib/config/apiUrl.dart index 94655bd..271a547 100644 --- a/lib/config/apiUrl.dart +++ b/lib/config/apiUrl.dart @@ -14,7 +14,6 @@ const String apiUrl = 'https://apitest.tripapprovaltool.com/tstat_be'; * Check File : App.dart -> line 37 need to comment it "SemanticsBinding" **/ // const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be'; - /** Note : Adfactor UAT BE URL * incase "aujas" or "tstat" href means changed to "adfactor" * File : web/index.html - change below 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,