diff --git a/lib/Screens/allTrips/list_all_plans.dart b/lib/Screens/allTrips/list_all_plans.dart index 81ff48b..223eee8 100644 --- a/lib/Screens/allTrips/list_all_plans.dart +++ b/lib/Screens/allTrips/list_all_plans.dart @@ -13,6 +13,7 @@ import 'package:shared_preferences/shared_preferences.dart'; import '../../routes/custom_appBar.dart'; import '../../routes/custom_drawer.dart'; +import '../../routes/mainLayout.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; @@ -69,16 +70,19 @@ class _ListAllPlansState extends State { print("allPlans before filtering: $allPlans"); final lowerQuery = query.toLowerCase(); setState(() { - filteredPlans = allPlans.where((plan) { - return (plan.planId?.toLowerCase().contains(lowerQuery) ?? false) || - (plan.employeeCode?.toLowerCase().contains(lowerQuery) ?? false) || - (plan.tripTitle?.toLowerCase().contains(lowerQuery) ?? false) || - (plan.userName?.toLowerCase().contains(lowerQuery) ?? false) || - (plan.travellerName?.toLowerCase().contains(lowerQuery) ?? false) || - (plan.tripType?.toLowerCase().contains(lowerQuery) ?? false) || - (plan.createdOn?.toLowerCase().contains(lowerQuery) ?? false) || - (plan.statusValue?.toLowerCase().contains(lowerQuery) ?? false); - }).toList(); + filteredPlans = + allPlans.where((plan) { + return (plan.planId?.toLowerCase().contains(lowerQuery) ?? false) || + (plan.employeeCode?.toLowerCase().contains(lowerQuery) ?? + false) || + (plan.tripTitle?.toLowerCase().contains(lowerQuery) ?? false) || + (plan.userName?.toLowerCase().contains(lowerQuery) ?? false) || + (plan.travellerName?.toLowerCase().contains(lowerQuery) ?? + false) || + (plan.tripType?.toLowerCase().contains(lowerQuery) ?? false) || + (plan.createdOn?.toLowerCase().contains(lowerQuery) ?? false) || + (plan.statusValue?.toLowerCase().contains(lowerQuery) ?? false); + }).toList(); }); print("filteredPlans: $filteredPlans"); } @@ -88,13 +92,15 @@ class _ListAllPlansState extends State { String? bodyStringColor = await getBodyColor(); setState(() { - layoutColor = layoutString != null - ? Color(int.parse(layoutString)) - : Colors.redAccent; + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; - bodyColor = bodyStringColor != null - ? Color(int.parse(bodyStringColor)) - : Colors.white; + bodyColor = + bodyStringColor != null + ? Color(int.parse(bodyStringColor)) + : Colors.white; }); } @@ -245,8 +251,10 @@ class _ListAllPlansState extends State { } void deletePlan(String planId) async { - bool confirmed = - await apiService.showCancelConfirmationDialog(context, layoutColor); + bool confirmed = await apiService.showCancelConfirmationDialog( + context, + layoutColor, + ); if (confirmed) { try { @@ -263,35 +271,48 @@ class _ListAllPlansState extends State { } Widget build(BuildContext context) { - return ResponsiveBuilder(builder: (context, sizingInfo) { - bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop; + return ResponsiveBuilder( + builder: (context, sizingInfo) { + bool isDesktop = + sizingInfo.deviceScreenType == DeviceScreenType.desktop; - return Scaffold( - backgroundColor: Color(0xFFf5f5f5), - // backgroundColor: Color(0xFFFCFCFC), - - // appBar: isDesktop ? null : const CustomAppBar(title: 'Home'), - // drawer: isDesktop ? null : CustomDrawer(isDesktop: false), - appBar: CustomAppBar(isDesktop: isDesktop), - 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), + return MainLayout( + isDesktop: isDesktop, child: Row( children: [ // if (isDesktop) CustomDrawer(isDesktop: true), - Expanded(child: buildGroupListLayout(isDesktop)) + Expanded(child: buildGroupListLayout(isDesktop)), ], ), - ), - ); - }); + ); + + // return Scaffold( + // backgroundColor: Color(0xFFf5f5f5), + // // backgroundColor: Color(0xFFFCFCFC), + // appBar: CustomAppBar(isDesktop: isDesktop), + // 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), + // child: Row( + // children: [ + // // if (isDesktop) CustomDrawer(isDesktop: true), + // Expanded(child: buildGroupListLayout(isDesktop)), + // ], + // ), + // ), + // ); + }, + ); } Widget buildGroupListLayout(bool isDesktop) { @@ -322,8 +343,9 @@ class _ListAllPlansState extends State { String _formatDate(String rawDate) { try { final dateTime = DateTime.parse(rawDate); - return DateFormat('dd, MMM yyyy HH:mm') - .format(dateTime); // 24-hour format + return DateFormat( + 'dd, MMM yyyy HH:mm', + ).format(dateTime); // 24-hour format } catch (e) { return rawDate; // fallback if parsing fails } @@ -332,17 +354,19 @@ class _ListAllPlansState extends State { return Container( margin: isDesktop ? EdgeInsets.all(10.0) : null, padding: const EdgeInsets.only(top: 15, bottom: 15, left: 20, right: 20), - height: isDesktop - ? MediaQuery.of(context).size.height * 0.98 - : MediaQuery.of(context).size.height, + 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, + border: + isDesktop + ? Border.all( + width: 2, + color: Colors.white, + // color: Color(0xFFF7F7FB), + ) + : null, color: isDesktop ? Colors.white : Color(0xFFFCFCFC), // color: Color(0xFFF7F7FB), @@ -382,9 +406,7 @@ class _ListAllPlansState extends State { ], ), - SizedBox( - width: 1, - ), + SizedBox(width: 1), Spacer(), if (isDesktop) Container( @@ -395,8 +417,10 @@ class _ListAllPlansState extends State { onChanged: filterPlans, decoration: InputDecoration( hintText: "Search...", - hintStyle: - TextStyle(fontSize: 12, color: Color(0xFF9E9DBD)), + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), prefixIcon: Icon( Icons.search, color: Color(0xFF9E9DBD), @@ -408,22 +432,23 @@ class _ListAllPlansState extends State { enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( - color: Colors.grey.shade200, width: 0.5), + color: Colors.grey.shade200, + width: 0.5, + ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( - color: Colors.grey.shade300, width: 1), + color: Colors.grey.shade300, + width: 1, + ), ), ), - style: GoogleFonts.poppins( - fontSize: 12, - ), + style: GoogleFonts.poppins(fontSize: 12), ), ), // SizedBox(width: 16), - Spacer(), // ElevatedButton( // style: ElevatedButton.styleFrom( @@ -521,8 +546,10 @@ class _ListAllPlansState extends State { onChanged: filterPlans, decoration: InputDecoration( hintText: "Search...", - hintStyle: - TextStyle(fontSize: 12, color: Color(0xFF9E9DBD)), + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), prefixIcon: Icon( Icons.search, color: Color(0xFF9E9DBD), @@ -534,17 +561,19 @@ class _ListAllPlansState extends State { enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( - color: Colors.grey.shade200, width: 0.5), + color: Colors.grey.shade200, + width: 0.5, + ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( - color: Colors.grey.shade300, width: 1), + color: Colors.grey.shade300, + width: 1, + ), ), ), - style: GoogleFonts.poppins( - fontSize: 12, - ), + style: GoogleFonts.poppins(fontSize: 12), ), ), ], @@ -579,16 +608,19 @@ class _ListAllPlansState extends State { "No Trips", textAlign: TextAlign.center, style: GoogleFonts.poppins( - fontSize: 20, - fontWeight: FontWeight.w600, - color: Colors.black54), + fontSize: 20, + fontWeight: FontWeight.w600, + color: Colors.black54, + ), ), const SizedBox(height: 10), Text( "Please Create Trip", textAlign: TextAlign.center, style: GoogleFonts.poppins( - fontSize: 12, color: Colors.grey), + fontSize: 12, + color: Colors.grey, + ), ), ], ), @@ -604,13 +636,16 @@ class _ListAllPlansState extends State { List plans = searchController.text.isEmpty ? allPlans : filteredPlans; - plans.sort((a, b) => - int.parse(b.planId).compareTo(int.parse(a.planId))); + plans.sort( + (a, b) => + int.parse(b.planId).compareTo(int.parse(a.planId)), + ); - List paginatedPlans = plans - .skip(currentPage * itemsPerPage) - .take(itemsPerPage) - .toList(); + List paginatedPlans = + plans + .skip(currentPage * itemsPerPage) + .take(itemsPerPage) + .toList(); Widget table = LayoutBuilder( builder: (context, constraints) { @@ -623,220 +658,324 @@ class _ListAllPlansState extends State { columnSpacing: isDesktop ? 24.0 : 16.0, border: TableBorder( horizontalInside: BorderSide( - width: 0.5, color: Colors.grey.shade200), + width: 0.5, + color: Colors.grey.shade200, + ), ), columns: [ DataColumn( - label: Text( - 'Trip ID', - style: GoogleFonts.poppins( - fontSize: 13, fontWeight: FontWeight.w600), - )), - 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( - '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", - ))), - DataCell(Text(plan.tripTitle, - style: TextStyle( - fontSize: 13, - fontFamily: "Inter", - ), - softWrap: true, - overflow: TextOverflow.ellipsis)), - 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( - 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), - ), - child: Text( - plan.statusValue, - textAlign: TextAlign.center, - style: TextStyle( - color: - getStatusTextColor(plan.statusValue), - fontSize: 12, - fontFamily: "Inter", - fontWeight: FontWeight.w400, - ), - ), + label: Text( + 'Trip ID', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, ), ), - DataCell( - Row( - children: [ - PopupMenuButton( - color: Colors.white, - padding: EdgeInsets.zero, - offset: Offset(0, 30), - icon: Icon( - Icons.more_vert, - color: Color(0xFF475569), - size: 14, + ), + 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( + '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", + ), ), - 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 Trips', - onPressed: () { - Navigator.pop( - context); // Close popup manually - ApiService.viewPlan( - context, plan.planId, - isViewMode: true); - }, - ), - IconButton( - icon: Image.asset( - 'assets/images/IconsImg/edit.png', - width: 20, - height: 15), - onPressed: () { - Navigator.pop(context); - ApiService.viewPlan( - context, plan.planId, - isViewMode: false); - }, - ), - IconButton( - icon: Icon( - Icons.cancel_rounded, - size: 18), - tooltip: 'Cancellation Trips', - onPressed: () { - Navigator.pop(context); - deletePlan(plan.planId); - }, - ), - IconButton( - icon: Icon(Icons.download, - color: Color(0xFF114D8B), - size: 18), - tooltip: 'Download Trips Detials', - onPressed: () { - Navigator.pop(context); - apiService.getPdfDownload( - plan.planId); - }, - ), - IconButton( - icon: const Icon( - Icons.comment, - color: Color(0xFF475569), - size: 11, - ), - tooltip: 'Trips Comments', - onPressed: () { - showDialog( - context: context, - builder: (context) => - CommentModalList( - // planId: plan.planId, - planId: plan - .planId - .toString(), - layoutColorForUser: - layoutColor!, - role: "Admin"), - ); - }), - ], - ), + ), + DataCell( + Text( + plan.tripTitle, + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + softWrap: true, + overflow: TextOverflow.ellipsis, + ), + ), + 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( + 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, ), ), - ], + 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 Trips', + onPressed: () { + Navigator.pop( + context, + ); // Close popup manually + ApiService.viewPlan( + context, + plan.planId, + isViewMode: + true, + ); + }, + ), + IconButton( + icon: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ), + onPressed: () { + Navigator.pop( + context, + ); + ApiService.viewPlan( + context, + plan.planId, + isViewMode: + false, + ); + }, + ), + IconButton( + icon: Icon( + Icons + .cancel_rounded, + size: 18, + ), + tooltip: + 'Cancellation Trips', + onPressed: () { + Navigator.pop( + context, + ); + deletePlan( + plan.planId, + ); + }, + ), + IconButton( + icon: Icon( + Icons.download, + color: Color( + 0xFF114D8B, + ), + size: 18, + ), + tooltip: + 'Download Trips Detials', + onPressed: () { + Navigator.pop( + context, + ); + apiService + .getPdfDownload( + plan.planId, + ); + }, + ), + IconButton( + icon: const Icon( + Icons.comment, + color: Color( + 0xFF475569, + ), + size: 11, + ), + tooltip: + 'Trips Comments', + onPressed: () { + showDialog( + context: + context, + builder: + ( + context, + ) => CommentModalList( + // planId: plan.planId, + planId: + plan.planId + .toString(), + layoutColorForUser: + layoutColor!, + role: + "Admin", + ), + ); + }, + ), + ], + ), + ), + ), + ], + ), + ], + ), ), ], - ), - ), - ]); - }).toList(), + ); + }).toList(), ), ); }, @@ -849,8 +988,10 @@ class _ListAllPlansState extends State { final plan = paginatedPlans[index]; return Card( color: Colors.white, - margin: - EdgeInsets.symmetric(horizontal: 12, vertical: 6), + margin: EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), @@ -875,18 +1016,23 @@ class _ListAllPlansState extends State { children: [ Container( padding: EdgeInsets.symmetric( - horizontal: 8, vertical: 4), + horizontal: 8, + vertical: 4, + ), decoration: BoxDecoration( color: getStatusColor( - plan.statusValue), - borderRadius: - BorderRadius.circular(8), + plan.statusValue, + ), + borderRadius: BorderRadius.circular( + 8, + ), ), child: Text( plan.statusValue, style: TextStyle( color: getStatusTextColor( - plan.statusValue), + plan.statusValue, + ), fontSize: 10, fontWeight: FontWeight.w600, ), @@ -915,11 +1061,14 @@ class _ListAllPlansState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(' ${plan.tripTitle}', - style: TextStyle( - fontSize: 12, - fontFamily: "Inter", - fontWeight: FontWeight.bold)), + Text( + ' ${plan.tripTitle}', + style: TextStyle( + fontSize: 12, + fontFamily: "Inter", + fontWeight: FontWeight.bold, + ), + ), ], ), ], @@ -934,24 +1083,28 @@ class _ListAllPlansState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(' ${plan.tripType}', - style: TextStyle( - fontSize: 9, - color: Colors.black87, - fontFamily: "Inter", - )), + Text( + ' ${plan.tripType}', + style: TextStyle( + fontSize: 9, + color: Colors.black87, + fontFamily: "Inter", + ), + ), ], ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('${_formatDate(plan.createdOn)}', - style: TextStyle( - fontSize: 9, - color: Colors.black87, - fontFamily: "Inter", - )), + Text( + '${_formatDate(plan.createdOn)}', + style: TextStyle( + fontSize: 9, + color: Colors.black87, + fontFamily: "Inter", + ), + ), ], ), ], @@ -969,9 +1122,10 @@ class _ListAllPlansState extends State { ? '${plan.userName}' : '${plan.travellerName}', style: TextStyle( - fontSize: 9, - fontFamily: "Inter", - color: Colors.black87), + fontSize: 9, + fontFamily: "Inter", + color: Colors.black87, + ), ), ], ), @@ -983,9 +1137,10 @@ class _ListAllPlansState extends State { Text( plan.employeeCode ?? 'No Data', style: TextStyle( - fontSize: 9, - fontFamily: "Inter", - color: Colors.black87), + fontSize: 9, + fontFamily: "Inter", + color: Colors.black87, + ), ), ], ), @@ -1005,30 +1160,35 @@ class _ListAllPlansState extends State { // mainAxisAlignment: MainAxisAlignment.spaceBetween, 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)), + 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)), // child: isDesktop // ? SingleChildScrollView( @@ -1058,7 +1218,7 @@ class _ListAllPlansState extends State { ), ); }, - ) + ), ], ), ), diff --git a/lib/Screens/approvals/approval_dialogs.dart b/lib/Screens/approvals/approval_dialogs.dart index 14c145e..d8b772c 100644 --- a/lib/Screens/approvals/approval_dialogs.dart +++ b/lib/Screens/approvals/approval_dialogs.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; Future showApprovalDialog( - BuildContext context, Color layoutColor) async { + BuildContext context, + Color layoutColor, +) async { String selectedAction = ""; // "", "accept", "reject" String remarks = ""; @@ -24,13 +26,12 @@ Future showApprovalDialog( Text( "To Approve or Reject Trip", style: TextStyle( - fontFamily: "Inter", fontWeight: FontWeight.w500), + fontFamily: "Inter", + fontWeight: FontWeight.w500, + ), ), IconButton( - icon: const Icon( - Icons.close, - size: 15, - ), + icon: const Icon(Icons.close, size: 15), onPressed: () { Navigator.pop(context, null); // Close the dialog }, @@ -45,12 +46,14 @@ Future showApprovalDialog( Expanded( child: ElevatedButton( style: ElevatedButton.styleFrom( - backgroundColor: selectedAction == "accept" - ? layoutColor - : Colors.grey.shade200, - foregroundColor: selectedAction == "accept" - ? Colors.white - : Colors.black, + backgroundColor: + selectedAction == "accept" + ? Colors.green + : Colors.grey.shade200, + foregroundColor: + selectedAction == "accept" + ? Colors.white + : Colors.black, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), @@ -68,12 +71,14 @@ Future showApprovalDialog( Expanded( child: ElevatedButton( style: ElevatedButton.styleFrom( - backgroundColor: selectedAction == "reject" - ? Colors.redAccent - : Colors.grey.shade200, - foregroundColor: selectedAction == "reject" - ? Colors.white - : Colors.black, + backgroundColor: + selectedAction == "reject" + ? Colors.redAccent + : Colors.grey.shade200, + foregroundColor: + selectedAction == "reject" + ? Colors.white + : Colors.black, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), @@ -122,12 +127,16 @@ Future showApprovalDialog( border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide( - color: Colors.blueGrey, width: 0.5), + color: Colors.blueGrey, + width: 0.5, + ), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), - borderSide: - BorderSide(color: Colors.blueGrey, width: 0.5), + borderSide: BorderSide( + color: Colors.blueGrey, + width: 0.5, + ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), @@ -135,7 +144,7 @@ Future showApprovalDialog( ), ), ), - ] + ], ], ), actionsAlignment: MainAxisAlignment.center, @@ -187,94 +196,14 @@ Future showApprovalDialog( Future showApproveDialog1(BuildContext context, Color layoutColor) { return showDialog( context: context, - builder: (context) => AlertDialog( - backgroundColor: Colors.white, - title: const Text( - "Confirm Approval", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - content: const Text("Are you sure you want to approve this plan?"), - actions: [ - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Colors.white, - foregroundColor: layoutColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: BorderSide(color: layoutColor, width: 2), - ), - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - ), - onPressed: () => Navigator.pop(context, false), - child: const Text("Cancel"), - ), - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: layoutColor, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: BorderSide(color: layoutColor, width: 2), - ), - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - ), - onPressed: () => Navigator.pop(context, true), - child: const Text("OK"), - ), - ], - ), - ); -} - -/// Show confirm dialog for rejection with remarks input -Future showRejectDialog1( - BuildContext context, Color layoutColor) async { - String remarks = ""; - - final confirmed = await showDialog( - context: context, - builder: (context) { - return StatefulBuilder( - builder: (context, setState) => AlertDialog( + builder: + (context) => AlertDialog( backgroundColor: Colors.white, - contentPadding: const EdgeInsets.all(36), - // title: const Text("Confirm Rejection"), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Text( - "Confirm Rejection", - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), - const Text("Please enter reason for rejection."), - const SizedBox(height: 10), - TextField( - maxLines: 3, - onChanged: (value) => remarks = value, - decoration: const InputDecoration( - hintText: "Remarks...", - hintStyle: TextStyle( - fontSize: 10, // 👈 Set your desired font size here - color: Colors.grey, - fontFamily: "Inter", // optional if you want consistent font - ), - border: OutlineInputBorder( - borderSide: BorderSide(color: Colors.blueGrey, width: 0.5), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.blueGrey, width: 0.5), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.grey, width: 1), - ), - ), - ), - ], + title: const Text( + "Confirm Approval", + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), + content: const Text("Are you sure you want to approve this plan?"), actions: [ ElevatedButton( style: ElevatedButton.styleFrom( @@ -299,14 +228,102 @@ Future showRejectDialog1( ), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), - onPressed: () { - if (remarks.trim().isEmpty) return; - Navigator.pop(context, true); - }, + onPressed: () => Navigator.pop(context, true), child: const Text("OK"), ), ], ), + ); +} + +/// Show confirm dialog for rejection with remarks input +Future showRejectDialog1( + BuildContext context, + Color layoutColor, +) async { + String remarks = ""; + + final confirmed = await showDialog( + context: context, + builder: (context) { + return StatefulBuilder( + builder: + (context, setState) => AlertDialog( + backgroundColor: Colors.white, + contentPadding: const EdgeInsets.all(36), + // title: const Text("Confirm Rejection"), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Text( + "Confirm Rejection", + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), + const Text("Please enter reason for rejection."), + const SizedBox(height: 10), + TextField( + maxLines: 3, + onChanged: (value) => remarks = value, + decoration: const InputDecoration( + hintText: "Remarks...", + hintStyle: TextStyle( + fontSize: 10, // 👈 Set your desired font size here + color: Colors.grey, + fontFamily: + "Inter", // optional if you want consistent font + ), + border: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.blueGrey, + width: 0.5, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.blueGrey, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: Colors.grey, width: 1), + ), + ), + ), + ], + ), + actions: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.white, + foregroundColor: layoutColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(color: layoutColor, width: 2), + ), + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + ), + onPressed: () => Navigator.pop(context, false), + child: const Text("Cancel"), + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: layoutColor, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(color: layoutColor, width: 2), + ), + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + ), + onPressed: () { + if (remarks.trim().isEmpty) return; + Navigator.pop(context, true); + }, + child: const Text("OK"), + ), + ], + ), ); }, ); diff --git a/lib/Screens/authentication/login/login_widget.dart b/lib/Screens/authentication/login/login_widget.dart index 5ccf7d7..9758778 100644 --- a/lib/Screens/authentication/login/login_widget.dart +++ b/lib/Screens/authentication/login/login_widget.dart @@ -11,12 +11,14 @@ import 'package:go_router/go_router.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher.dart'; +import '../../../services/apiService.dart'; + class LoginWidget extends StatefulWidget { final bool isDesktop; final bool isTablet; const LoginWidget({Key? key, required this.isDesktop, required this.isTablet}) - : super(key: key); + : super(key: key); @override _LoginWidgetState createState() => _LoginWidgetState(); @@ -25,6 +27,9 @@ class LoginWidget extends StatefulWidget { enum LoginStep { login, forgotEmail, otpReset } class _LoginWidgetState extends State { + final ApiService apiService = ApiService(); + bool _moved = false; + final _formKey = GlobalKey(); final TextEditingController _emailController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); @@ -39,6 +44,17 @@ class _LoginWidgetState extends State { // 🔹 Login Step Enum and State Variable LoginStep _loginStep = LoginStep.login; + @override + void initState() { + super.initState(); + + Future.delayed(Duration(milliseconds: 300), () { + setState(() { + _moved = true; + }); + }); + } + @override void dispose() { _emailController.dispose(); @@ -54,15 +70,18 @@ class _LoginWidgetState extends State { final parts = token.split('.'); if (parts.length != 3) throw Exception('Invalid token format'); - final payload = json - .decode(utf8.decode(base64Url.decode(base64Url.normalize(parts[1])))); + final payload = json.decode( + utf8.decode(base64Url.decode(base64Url.normalize(parts[1]))), + ); final userData = payload['data']; final prefs = await SharedPreferences.getInstance(); await prefs.setString('auth_token', token); await prefs.setString( - 'user_data', jsonEncode(userData)); // Store full user data + 'user_data', + jsonEncode(userData), + ); // Store full user data if (userData != null) { final pref = await SharedPreferences.getInstance(); @@ -75,6 +94,8 @@ class _LoginWidgetState extends State { print("userData11 - ${userData['role']}"); print("userData12 - $userRole"); } + + apiService.getOrganizationData(); } catch (e) { print('Error decoding token: $e'); } @@ -89,7 +110,7 @@ class _LoginWidgetState extends State { Uri.parse(url), headers: { 'Content-Type': 'application/json', - 'Accept': 'application/json' + 'Accept': 'application/json', }, body: jsonEncode({ 'email': _emailController.text.trim(), @@ -145,9 +166,9 @@ class _LoginWidgetState extends State { // ); } } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text("Error: $e")), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text("Error: $e"))); } } } @@ -175,19 +196,27 @@ class _LoginWidgetState extends State { // _clearAllFields(); }); ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text("OTP sent to your email")), + SnackBar( + content: Text("OTP sent to your email"), + backgroundColor: Colors.green, + ), ); } else { print(response); ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: - Text("${jsonDecode(response.body)['messages']['error']}")), + content: Text( + "${jsonDecode(response.body)['messages']['error']}", + ), + + backgroundColor: Colors.red, + ), ); } } catch (e) { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text("Error: $e"))); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Error: $e"), backgroundColor: Colors.red), + ); } } else if (!_isForgotPassword && _showOtpResetFields) { print('22'); @@ -214,20 +243,32 @@ class _LoginWidgetState extends State { _clearAllFields(); }); ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text("Password reset successfully")), + SnackBar( + content: Text("Password reset successfully"), + backgroundColor: Colors.green, + ), ); } else { print('23'); print('otp wrong'); + final responseBody = json.decode(response.body); + final errorMessage = + responseBody['messages']?['error'] ?? 'An unknown error occurred'; + print(errorMessage); ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text( - "Reset failed: ${jsonDecode(response.body)['message']}")), + content: Text( + "Reset failed: $errorMessage", + // "Reset failed: ${jsonDecode(response.body)['message']}", + ), + backgroundColor: Colors.red, + ), ); } } catch (e) { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text("Error: $e"))); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Error: $e"), backgroundColor: Colors.red), + ); } } else { // Login flow @@ -255,15 +296,15 @@ class _LoginWidgetState extends State { } @override - /// Layout Widget build(BuildContext context) { double formWidth = widget.isTablet ? 400 : 300; return Container( // color: Color(0xFF114D8B), - color: Color(0xFFf5f5f5), + color: Colors.white, + // color: Color(0xFFf5f5f5), padding: const EdgeInsets.all(10), child: Row( children: [ @@ -285,8 +326,9 @@ class _LoginWidgetState extends State { // color: Colors.white, borderRadius: BorderRadius.only( topRight: Radius.circular(250), // Rounded top-left corner - bottomRight: - Radius.circular(250), // Rounded bottom-left corner + bottomRight: Radius.circular( + 250, + ), // Rounded bottom-left corner ), ), // child: Padding( @@ -305,24 +347,29 @@ class _LoginWidgetState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Image.asset( - 'assets/images/login/logoNew.jpg', + // Image.asset( + // 'assets/images/login/logoNew.jpg', + // width: 200, // Optional: control size + // height: 100, + // fit: BoxFit.contain, + // ), + Container( width: 200, // Optional: control size height: 100, - fit: BoxFit.contain, ), Expanded( child: Container( child: Align( - // alignment: Alignment.bottomRight, - child: Image.asset( - 'assets/images/login/login_travel.png', - // width: 200, // Optional: control size - // height: 100, - fit: BoxFit.contain, - )), + // alignment: Alignment.bottomRight, + child: Image.asset( + 'assets/images/login/login_travel.png', + // width: 200, // Optional: control size + // height: 100, + fit: BoxFit.contain, + ), + ), ), - ) + ), ], ), ), @@ -332,17 +379,15 @@ class _LoginWidgetState extends State { child: Container( decoration: BoxDecoration( // color: Colors.white, - borderRadius: BorderRadius.only( topLeft: Radius.circular(25), // Rounded top-left corner bottomLeft: Radius.circular(25), // Rounded bottom-left corner ), ), - child: Center( - child: Padding( - padding: const EdgeInsets.all(40), - child: _buildForm(width: formWidth), // Fixed form width - ), + + child: Padding( + padding: const EdgeInsets.all(10), + child: _buildForm(width: formWidth), // Fixed form width ), ), ), @@ -353,436 +398,548 @@ class _LoginWidgetState extends State { /// **Reusable Login Form** Widget _buildForm({required double width}) { - return SizedBox( - width: width, - child: Form( - key: _formKey, - child: Column( - mainAxisSize: MainAxisSize.min, + return Column( + children: [ + // width: width, + Row( + mainAxisAlignment: MainAxisAlignment.end, children: [ - Text( - "Sign In", - style: GoogleFonts.poppins( - fontSize: 18, - fontWeight: FontWeight.w500, - color: Color(0xFF212121)), + Image.asset( + 'assets/images/login/logoNew.jpg', + width: 180, // Optional: control size + height: 70, + fit: BoxFit.contain, ), - const SizedBox(height: 2), - Text( - "Welcome To TripApprovalTool", - style: GoogleFonts.poppins( - fontSize: 11, - fontWeight: FontWeight.w400, - color: Color(0xFF212121)), - ), - const SizedBox(height: 18), + ], + ), - /// **Email Field** - if (!_isForgotPassword && !_showOtpResetFields) ...[ - _buildLabel("Email Address"), - TextFormField( - controller: _emailController, - style: GoogleFonts.poppins( - fontWeight: FontWeight.w600, fontSize: 11), - decoration: - _inputDecoration("Enter your email address").copyWith( - prefixIcon: Icon( - Icons.email_outlined, - size: 16, - ), - ), - validator: (value) => - value == null || value.isEmpty ? 'Required Email' : null, - ), - - const SizedBox(height: 16), - - /// **Password Field** - _buildLabel("Password"), - TextFormField( - controller: _passwordController, - style: GoogleFonts.poppins( - fontWeight: FontWeight.w600, fontSize: 11), - obscureText: _obscureText, - decoration: _inputDecoration("Enter your password").copyWith( - prefixIcon: Icon( - Icons.key, - size: 16, - ), - suffixIcon: IconButton( - icon: Icon( - _obscureText ? Icons.visibility_off : Icons.visibility, - color: Color(0xFF12B24B), - size: 16, - ), - onPressed: () => - setState(() => _obscureText = !_obscureText), - ), - ), - validator: (value) => - value == null || value.isEmpty ? 'Required Password' : null, - ), - - const SizedBox(height: 20), - - /// **Login Button** + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Expanded( - child: ElevatedButton( - onPressed: () => _login(context), - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF12B24B), // Button color - foregroundColor: Colors.white, // Text color - padding: const EdgeInsets.symmetric( - horizontal: 24, vertical: 12), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18)), - ), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 24, vertical: 10), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - "Sign In", + SizedBox( + width: width, + child: Form( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 2), + Text( + "Sign In", + style: GoogleFonts.poppins( + fontSize: widget.isDesktop ? 20 : 18, + fontWeight: FontWeight.w700, + color: Colors.green, + // color: Color(0xFF212121), + ), + ), + const SizedBox(height: 5), + Text( + "Welcome To TripApprovalTool", + style: GoogleFonts.poppins( + fontSize: 11, + fontWeight: FontWeight.w400, + + color: Color(0xFF212121), + ), + ), + const SizedBox(height: 10), + + /// **Email Field** + if (!_isForgotPassword && !_showOtpResetFields) ...[ + _buildLabel("Email Address"), + TextFormField( + controller: _emailController, style: GoogleFonts.poppins( - fontWeight: FontWeight.w800, fontSize: 15), + fontWeight: FontWeight.w600, + fontSize: 11, + ), + decoration: _inputDecoration( + "Enter your email address", + ).copyWith( + prefixIcon: Icon( + Icons.email_outlined, + size: 16, + ), + ), + validator: + (value) => + value == null || value.isEmpty + ? 'Required Email' + : null, ), - SizedBox( - width: 3, - ), - Icon( - Icons.arrow_forward_sharp, - color: Colors.white, - ) - ], - ), - ), - ), - ), - ], - ), - ] else if (_isForgotPassword && !_showOtpResetFields) ...[ - _buildLabel("Email Address"), - TextFormField( - controller: _emailController, - style: GoogleFonts.poppins( - fontWeight: FontWeight.w600, fontSize: 11), - decoration: - _inputDecoration("Enter your email address").copyWith( - prefixIcon: Icon( - Icons.email_outlined, - size: 16, - ), - ), - validator: (value) => - value == null || value.isEmpty ? 'Required Email' : null, - ), - const SizedBox(height: 20), - Row( - children: [ - Expanded( - child: ElevatedButton( - onPressed: () => _onSubmit(context), - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF12B24B), // Button color - foregroundColor: Colors.white, // Text color - padding: const EdgeInsets.symmetric( - horizontal: 24, vertical: 12), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18)), - ), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 24, vertical: 10), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - "Submit", + + const SizedBox(height: 10), + + /// **Password Field** + _buildLabel("Password"), + TextFormField( + controller: _passwordController, style: GoogleFonts.poppins( - fontWeight: FontWeight.w800, fontSize: 15), + fontWeight: FontWeight.w600, + fontSize: 11, + ), + obscureText: _obscureText, + decoration: _inputDecoration( + "Enter your password", + ).copyWith( + prefixIcon: Icon(Icons.key, size: 16), + suffixIcon: IconButton( + icon: Icon( + _obscureText + ? Icons.visibility_off + : Icons.visibility, + color: Color(0xFF12B24B), + size: 16, + ), + onPressed: + () => setState( + () => _obscureText = !_obscureText, + ), + ), + ), + validator: + (value) => + value == null || value.isEmpty + ? 'Required Password' + : null, ), - SizedBox( - width: 3, + + const SizedBox(height: 10), + + /// **Login Button** + Row( + children: [ + Expanded( + child: ElevatedButton( + onPressed: () => _login(context), + style: ElevatedButton.styleFrom( + backgroundColor: Color( + 0xFF12B24B, + ), // Button color + foregroundColor: + Colors.white, // Text color + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 12, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18), + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 5, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "Sign In", + style: GoogleFonts.poppins( + fontWeight: FontWeight.w800, + fontSize: 13.5, + ), + ), + SizedBox(width: 3), + Icon( + Icons.arrow_forward_sharp, + color: Colors.white, + ), + ], + ), + ), + ), + ), + ], ), - Icon( - Icons.arrow_forward_sharp, - color: Colors.white, - ) - ], - ), - ), - ), - ), - ], - ), - ] else ...[ - _buildLabel("Email Address"), - TextFormField( - controller: _emailController, - readOnly: true, - style: GoogleFonts.poppins( - fontWeight: FontWeight.w600, fontSize: 11), - decoration: - _inputDecoration("Enter your email address").copyWith( - prefixIcon: Icon( - Icons.email_outlined, - size: 16, - ), - ), - validator: (value) => - value == null || value.isEmpty ? 'Required Email' : null, - ), - const SizedBox(height: 16), - _buildLabel("OTP"), - TextFormField( - controller: _otpController, - style: GoogleFonts.poppins( - fontWeight: FontWeight.w600, fontSize: 11), - decoration: _inputDecoration("Enter your OTP").copyWith( - prefixIcon: Icon( - Icons.email_outlined, - size: 16, - ), - ), - validator: (value) => - value == null || value.isEmpty ? 'Required OTP' : null, - ), - const SizedBox(height: 16), - _buildLabel("New Password"), - TextFormField( - controller: _newPasswordController, - style: GoogleFonts.poppins( - fontWeight: FontWeight.w600, fontSize: 11), - obscureText: _obscureText, - decoration: - _inputDecoration("Enter your new password").copyWith( - prefixIcon: Icon( - Icons.key, - size: 16, - ), - suffixIcon: IconButton( - icon: Icon( - _obscureText ? Icons.visibility_off : Icons.visibility, - color: Color(0xFF12B24B), - size: 16, - ), - onPressed: () => - setState(() => _obscureText = !_obscureText), - ), - ), - validator: (value) => value == null || value.isEmpty - ? 'Required New Password' - : null, - ), - const SizedBox(height: 16), - _buildLabel("Confirm Password"), - TextFormField( - controller: _confirmPasswordController, - style: GoogleFonts.poppins( - fontWeight: FontWeight.w600, fontSize: 11), - obscureText: _obscureText, - decoration: - _inputDecoration("Enter your confirm password").copyWith( - prefixIcon: Icon( - Icons.key, - size: 16, - ), - suffixIcon: IconButton( - icon: Icon( - _obscureText ? Icons.visibility_off : Icons.visibility, - color: Color(0xFF12B24B), - size: 16, - ), - onPressed: () => - setState(() => _obscureText = !_obscureText), - ), - ), - validator: (value) { - if (value == null || value.isEmpty) { - return 'Required New Password'; - } - if (value != _newPasswordController.text) { - return 'Passwords do not match'; - } - return null; - }, - ), - const SizedBox(height: 20), - Row( - children: [ - Expanded( - child: ElevatedButton( - onPressed: () { - if (!_formKey.currentState!.validate()) return; - setState(() { - _isForgotPassword = false; - _showOtpResetFields = true; - _passwordController.clear(); - }); - _onSubmit(context); - }, - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF12B24B), // Button color - foregroundColor: Colors.white, // Text color - padding: const EdgeInsets.symmetric( - horizontal: 24, vertical: 12), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18)), - ), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 24, vertical: 10), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - "Submit", + ] else if (_isForgotPassword && + !_showOtpResetFields) ...[ + _buildLabel("Email Address"), + TextFormField( + controller: _emailController, style: GoogleFonts.poppins( - fontWeight: FontWeight.w800, fontSize: 15), + fontWeight: FontWeight.w600, + fontSize: 11, + ), + decoration: _inputDecoration( + "Enter your email address", + ).copyWith( + prefixIcon: Icon( + Icons.email_outlined, + size: 16, + ), + ), + validator: + (value) => + value == null || value.isEmpty + ? 'Required Email' + : null, ), - SizedBox( - width: 3, + const SizedBox(height: 10), + Row( + children: [ + Expanded( + child: ElevatedButton( + onPressed: () => _onSubmit(context), + style: ElevatedButton.styleFrom( + backgroundColor: Color( + 0xFF12B24B, + ), // Button color + foregroundColor: + Colors.white, // Text color + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 12, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18), + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 5, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "Submit", + style: GoogleFonts.poppins( + fontWeight: FontWeight.w800, + fontSize: 13.5, + ), + ), + SizedBox(width: 3), + Icon( + Icons.arrow_forward_sharp, + color: Colors.white, + ), + ], + ), + ), + ), + ), + ], + ), + ] else ...[ + _buildLabel("Email Address"), + TextFormField( + controller: _emailController, + readOnly: true, + style: GoogleFonts.poppins( + fontWeight: FontWeight.w600, + fontSize: 11, + ), + decoration: _inputDecoration( + "Enter your email address", + ).copyWith( + prefixIcon: Icon( + Icons.email_outlined, + size: 16, + ), + ), + validator: + (value) => + value == null || value.isEmpty + ? 'Required Email' + : null, + ), + const SizedBox(height: 10), + _buildLabel("OTP"), + TextFormField( + controller: _otpController, + style: GoogleFonts.poppins( + fontWeight: FontWeight.w600, + fontSize: 11, + ), + decoration: _inputDecoration( + "Enter your OTP", + ).copyWith( + prefixIcon: Icon( + Icons.email_outlined, + size: 16, + ), + ), + validator: + (value) => + value == null || value.isEmpty + ? 'Required OTP' + : null, + ), + const SizedBox(height: 10), + _buildLabel("New Password"), + TextFormField( + controller: _newPasswordController, + style: GoogleFonts.poppins( + fontWeight: FontWeight.w600, + fontSize: 11, + ), + obscureText: _obscureText, + decoration: _inputDecoration( + "Enter your new password", + ).copyWith( + prefixIcon: Icon(Icons.key, size: 16), + suffixIcon: IconButton( + icon: Icon( + _obscureText + ? Icons.visibility_off + : Icons.visibility, + color: Color(0xFF12B24B), + size: 16, + ), + onPressed: + () => setState( + () => _obscureText = !_obscureText, + ), + ), + ), + validator: + (value) => + value == null || value.isEmpty + ? 'Required New Password' + : null, + ), + const SizedBox(height: 10), + _buildLabel("Confirm Password"), + TextFormField( + controller: _confirmPasswordController, + style: GoogleFonts.poppins( + fontWeight: FontWeight.w600, + fontSize: 11, + ), + obscureText: _obscureText, + decoration: _inputDecoration( + "Enter your confirm password", + ).copyWith( + prefixIcon: Icon(Icons.key, size: 16), + suffixIcon: IconButton( + icon: Icon( + _obscureText + ? Icons.visibility_off + : Icons.visibility, + color: Color(0xFF12B24B), + size: 16, + ), + onPressed: + () => setState( + () => _obscureText = !_obscureText, + ), + ), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Required New Password'; + } + if (value != _newPasswordController.text) { + return 'Passwords do not match'; + } + return null; + }, + ), + const SizedBox(height: 10), + Row( + children: [ + Expanded( + child: ElevatedButton( + onPressed: () { + if (!_formKey.currentState!.validate()) + return; + setState(() { + _isForgotPassword = false; + _showOtpResetFields = true; + _passwordController.clear(); + }); + _onSubmit(context); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Color( + 0xFF12B24B, + ), // Button color + foregroundColor: + Colors.white, // Text color + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 12, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18), + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 10, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "Submit", + style: GoogleFonts.poppins( + fontWeight: FontWeight.w800, + fontSize: 13.5, + ), + ), + SizedBox(width: 3), + Icon( + Icons.arrow_forward_sharp, + color: Colors.white, + ), + ], + ), + ), + ), + ), + ], ), - Icon( - Icons.arrow_forward_sharp, - color: Colors.white, - ) ], - ), + const SizedBox(height: 10), + if (!_isForgotPassword && !_showOtpResetFields) + Center( + child: TextButton( + onPressed: () { + setState(() { + _isForgotPassword = true; + _showOtpResetFields = false; + _passwordController.clear(); + }); + }, + child: Text( + "Forgot Password", + style: GoogleFonts.poppins( + fontSize: 11, + fontWeight: FontWeight.w300, + + color: Color(0xFF212121), // Text color + decoration: + TextDecoration + .underline, // Underline the text + ), + ), + ), + ), + if (_isForgotPassword || _showOtpResetFields) + Center( + child: TextButton( + onPressed: () { + setState(() { + _isForgotPassword = false; + _showOtpResetFields = false; + _clearAllFields(); + }); + }, + child: Text( + "Back to Login", + style: GoogleFonts.poppins( + fontSize: 11, + fontWeight: FontWeight.w300, + + color: Color(0xFF212121), // Text color + decoration: + TextDecoration + .underline, // Underline the text + ), + ), + ), + ), + + const SizedBox(height: 10), + if (!_isForgotPassword && !_showOtpResetFields) + Row( + children: [ + Expanded( + child: ElevatedButton( + onPressed: () { + handleMS(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: + Colors.white, // Button color + foregroundColor: + Colors.black, // Text color + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 5, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18), + side: BorderSide( + color: Colors.black, // Border color + width: 0.5, // Border width + ), + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 3, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "Sign In With Microsoft", + style: GoogleFonts.poppins( + fontWeight: FontWeight.w500, + fontSize: 13, + ), + ), + SizedBox(width: 3), + Image.asset( + 'assets/images/login/microsoft.png', + width: 30, // Optional: control size + height: 30, + fit: BoxFit.contain, + ), + ], + ), + ), + ), + ), + ], + ), + // Row( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Container( + // width: 30, // Adjust size + // height: 30, + // decoration: BoxDecoration( + // // Background color + // shape: BoxShape.rectangle, + // borderRadius: BorderRadius.all(Radius.circular(15)), + // border: Border.all( + // color: Color(0xFF9E9DBD), width: 1), // Grey outline + // ), + // + // child: Center( + // child: Image.asset( + // 'assets/images/login/VectorG.png', + // width: 20, // Optional: control size + // height: 20, + // fit: BoxFit.contain, + // )), + // ), + // ], + // ), + ], ), ), ), ], ), ], - const SizedBox(height: 20), - if (!_isForgotPassword && !_showOtpResetFields) - Center( - child: TextButton( - onPressed: () { - setState(() { - _isForgotPassword = true; - _showOtpResetFields = false; - _passwordController.clear(); - }); - }, - child: Text( - "Forgot Password", - style: GoogleFonts.poppins( - fontSize: 11, - fontWeight: FontWeight.w300, - - color: Color(0xFF212121), // Text color - decoration: - TextDecoration.underline, // Underline the text - ), - ), - ), - ), - if (_isForgotPassword || _showOtpResetFields) - Center( - child: TextButton( - onPressed: () { - setState(() { - _isForgotPassword = false; - _showOtpResetFields = false; - _clearAllFields(); - }); - }, - child: Text( - "Back to Login", - style: GoogleFonts.poppins( - fontSize: 11, - fontWeight: FontWeight.w300, - - color: Color(0xFF212121), // Text color - decoration: - TextDecoration.underline, // Underline the text - ), - ), - ), - ), - - const SizedBox(height: 20), - if (!_isForgotPassword && !_showOtpResetFields) - Row( - children: [ - Expanded( - child: ElevatedButton( - onPressed: () { - handleMS(); - }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.white, // Button color - foregroundColor: Colors.black, // Text color - padding: const EdgeInsets.symmetric( - horizontal: 24, vertical: 5), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18), - side: BorderSide( - color: Colors.black, // Border color - width: 0.5, // Border width - ), - ), - ), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 24, vertical: 5), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - "Sign In With Microsoft", - style: GoogleFonts.poppins( - fontWeight: FontWeight.w500, fontSize: 14), - ), - SizedBox( - width: 3, - ), - Image.asset( - 'assets/images/login/microsoft.png', - width: 30, // Optional: control size - height: 30, - fit: BoxFit.contain, - ), - ], - ), - ), - ), - ), - ], - ), - // Row( - // mainAxisAlignment: MainAxisAlignment.center, - // children: [ - // Container( - // width: 30, // Adjust size - // height: 30, - // decoration: BoxDecoration( - // // Background color - // shape: BoxShape.rectangle, - // borderRadius: BorderRadius.all(Radius.circular(15)), - // border: Border.all( - // color: Color(0xFF9E9DBD), width: 1), // Grey outline - // ), - // - // child: Center( - // child: Image.asset( - // 'assets/images/login/VectorG.png', - // width: 20, // Optional: control size - // height: 20, - // fit: BoxFit.contain, - // )), - // ), - // ], - // ), - ], + ), ), - ), + ], ); } @@ -795,9 +952,10 @@ class _LoginWidgetState extends State { child: Text( text, style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF212121)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF212121), + ), ), ), ); @@ -826,8 +984,10 @@ class _LoginWidgetState extends State { final url = '$apiUrl/auth/mslogin'; print(url); try { - final response = await http - .get(Uri.parse(url), headers: {'Content-Type': 'application/json'}); + final response = await http.get( + Uri.parse(url), + headers: {'Content-Type': 'application/json'}, + ); print("inside try method"); if (response.statusCode == 200) { final authUrl = json.decode(response.body)['auth_url']; diff --git a/lib/Screens/itnerary/forex.dart b/lib/Screens/itnerary/forex.dart index 1368b1b..bef348b 100644 --- a/lib/Screens/itnerary/forex.dart +++ b/lib/Screens/itnerary/forex.dart @@ -24,14 +24,15 @@ class ForexScreen extends StatefulWidget { final Function(Map) onSaveForex; final String? loginUser; - ForexScreen( - {required this.onClose, - this.apiData, - required this.selectedItem, - required this.apiCountryData, - required this.onSaveForex, - required this.loginUser, - required this.flightData}); + ForexScreen({ + required this.onClose, + this.apiData, + required this.selectedItem, + required this.apiCountryData, + required this.onSaveForex, + required this.loginUser, + required this.flightData, + }); @override _ForexScreenState createState() => _ForexScreenState(); @@ -75,16 +76,18 @@ class _ForexScreenState extends State { "_cash", "_checkForex", "_deliveryLocation", - "_comments" + "_comments", ]; String _formatDate(String? date) { if (date == null || date.isEmpty) return ""; try { - DateTime parsedDate = - DateTime.parse(date); // Assuming input is YYYY-MM-DD - return DateFormat("dd-MM-yyyy") - .format(parsedDate); // Convert to DD-MM-YYYY + DateTime parsedDate = DateTime.parse( + date, + ); // Assuming input is YYYY-MM-DD + return DateFormat( + "dd-MM-yyyy", + ).format(parsedDate); // Convert to DD-MM-YYYY } catch (e) { print("Error formatting date: $e"); return date; // Return as is if parsing fails @@ -146,7 +149,7 @@ class _ForexScreenState extends State { "country_code": selectedCountry, "start_date": _formatDate(textControllers["_forexStartDate"]?.text), "end_date": _formatDate(textControllers["_forexEndDate"]?.text), - "user_id": tripuserId + "user_id": tripuserId, // "currency": selectedCurrency ?? "", }; } @@ -195,10 +198,12 @@ class _ForexScreenState extends State { selectedDuration = responseData["duration"]?.toString() ?? ""; selectedQuotedAmount = responseData["perdiem_amount"]?.toString() ?? ""; - selectedCardPercent = - int.tryParse(responseData["card_percentage"]?.toString() ?? ""); - selectedCashPercent = - int.tryParse(responseData["cash_percentage"]?.toString() ?? ""); + selectedCardPercent = int.tryParse( + responseData["card_percentage"]?.toString() ?? "", + ); + selectedCashPercent = int.tryParse( + responseData["cash_percentage"]?.toString() ?? "", + ); textControllers["_cardNumber"]?.text = responseData["forex_card_no"]?.toString() ?? ""; @@ -249,17 +254,16 @@ class _ForexScreenState extends State { } Map getFlightTripDateRange( - List> flightData) { - final allTrips = flightData - .expand((flight) => flight['trips'] ?? []) - .whereType>() - .toList(); + List> flightData, + ) { + final allTrips = + flightData + .expand((flight) => flight['trips'] ?? []) + .whereType>() + .toList(); if (allTrips.isEmpty) { - return { - 'firstTripDate': null, - 'lastTripDate': null, - }; + return {'firstTripDate': null, 'lastTripDate': null}; } allTrips.sort((a, b) { @@ -352,18 +356,22 @@ class _ForexScreenState extends State { // ✅ Only set controller after value is updated // final parsedDate = // DateTime.tryParse(flightFirstTripDateNotifier.value ?? ''); - final parsedDate = DateFormat("dd-MM-yyyy") - .parse(flightFirstTripDateNotifier.value ?? ''); + final parsedDate = DateFormat( + "dd-MM-yyyy", + ).parse(flightFirstTripDateNotifier.value ?? ''); if (parsedDate != null) { - textControllers["_forexStartDate"]?.text = - DateFormat('dd-MM-yyyy').format(parsedDate); + textControllers["_forexStartDate"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(parsedDate); } - final parsedEndDate = DateFormat("dd-MM-yyyy") - .parse(flightLastTripDateNotifier.value ?? ''); + final parsedEndDate = DateFormat( + "dd-MM-yyyy", + ).parse(flightLastTripDateNotifier.value ?? ''); if (parsedEndDate != null) { - textControllers["_forexEndDate"]?.text = - DateFormat('dd-MM-yyyy').format(parsedEndDate); + textControllers["_forexEndDate"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(parsedEndDate); } }); } @@ -392,8 +400,9 @@ class _ForexScreenState extends State { textControllers["_cardNumber"] = initController("card_number"); textControllers["_card"] = initController("deposit_on_card"); textControllers["_cash"] = initController("deposit_on_cash"); - textControllers["_deliveryLocation"] = - initController("delivery_location"); + textControllers["_deliveryLocation"] = initController( + "delivery_location", + ); textControllers["_comments"] = initController("comments"); // Set dropdown values @@ -401,9 +410,11 @@ class _ForexScreenState extends State { selectedCurrency = widget.selectedItem!["currency"] as String?; selectedDuration = widget.selectedItem!["duration"] as String?; selectedCardPercent = int.tryParse( - widget.selectedItem!["card_percentage"]?.toString() ?? ""); + widget.selectedItem!["card_percentage"]?.toString() ?? "", + ); selectedCashPercent = int.tryParse( - widget.selectedItem!["cash_percentage"]?.toString() ?? ""); + widget.selectedItem!["cash_percentage"]?.toString() ?? "", + ); selectedPerdiemAmount = widget.selectedItem!["perdiem_amount"] as String?; isChecked = widget.selectedItem!["have_card"] == "1"; // Convert string to bool @@ -473,7 +484,8 @@ class _ForexScreenState extends State { if (startDateString == null || endDateString == null) return; print( - "Calculate 3 - StarrtDAte: $startDateString --EndDate: $endDateString"); + "Calculate 3 - StarrtDAte: $startDateString --EndDate: $endDateString", + ); try { // Parse the dates from string @@ -548,7 +560,8 @@ class _ForexScreenState extends State { if (quotedAmount != null) { // fifteenPercent = (quotedAmount * 15) ~/ 100; print("selectedCardPercent - $selectedCashPercent"); - fifteenPercent = (quotedAmount * selectedCashPercent!) ~/ + fifteenPercent = + (quotedAmount * selectedCashPercent!) ~/ 100; // Calculate 15% (integer division) remainingAmount = quotedAmount - fifteenPercent; // Subtract from total @@ -587,10 +600,12 @@ class _ForexScreenState extends State { int checkValidAmount = cashAmount + enteredAmount; print( - "checkValidAmount - $checkValidAmount - $enteredAmount - $cashAmount"); + "checkValidAmount - $checkValidAmount - $enteredAmount - $cashAmount", + ); print( - "CAsh - $cashAmount- CaRd- $enteredAmount - $calculateAmnt - selectedQuotedAmount - $qouteAmount"); + "CAsh - $cashAmount- CaRd- $enteredAmount - $calculateAmnt - selectedQuotedAmount - $qouteAmount", + ); if (enteredAmount == null || calculateAmnt > qouteAmount!) { errorMessages["deposit_on_card"] = "Amount cannot exceed $qouteAmount"; @@ -619,19 +634,20 @@ class _ForexScreenState extends State { int checkValidAmount = cardAmount! + enteredAmount; print( - "checkValidAmountCash - $checkValidAmount -cash- $enteredAmount -Card - $cardAmount - quotedAmount- $quotedAmount"); + "checkValidAmountCash - $checkValidAmount -cash- $enteredAmount -Card - $cardAmount - quotedAmount- $quotedAmount", + ); print("Difference - $difference"); print('CardAmount - $cardAmount'); textControllers["_card"]?.text = difference.toString(); - // if (enteredAmount > fifteenPercent) { - // errorMessages["deposit_on_cash"] = "Amount cannot exceed $fifteenPercent"; - // } else if (checkValidAmount == quotedAmount) { - // errorMessages["deposit_on_card"] = " "; // Clear error if valid - // } else { - // errorMessages["deposit_on_cash"] = ""; // Clear error if valid - // } + if (enteredAmount > fifteenPercent) { + errorMessages["deposit_on_cash"] = "Amount cannot exceed $fifteenPercent"; + } else if (checkValidAmount == quotedAmount) { + errorMessages["deposit_on_card"] = " "; // Clear error if valid + } else { + errorMessages["deposit_on_cash"] = ""; // Clear error if valid + } // Refresh UI if using StatefulWidget setState(() {}); @@ -653,10 +669,12 @@ class _ForexScreenState extends State { void _validateDates() { print("VALiDATING DATES"); - DateTime? startDate = - _parseDate(textControllers["_forexStartDate"]?.text ?? ""); - DateTime? endDate = - _parseDate(textControllers["_forexEndDate"]?.text ?? ""); + DateTime? startDate = _parseDate( + textControllers["_forexStartDate"]?.text ?? "", + ); + DateTime? endDate = _parseDate( + textControllers["_forexEndDate"]?.text ?? "", + ); if (startDate != null && endDate != null && endDate.isBefore(startDate)) { setState(() { @@ -672,30 +690,33 @@ class _ForexScreenState extends State { @override Widget build(BuildContext context) { - return ResponsiveBuilder(builder: (context, sizingInfo) { - bool isMobile = sizingInfo.isMobile; - bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop; + return ResponsiveBuilder( + builder: (context, sizingInfo) { + bool isMobile = sizingInfo.isMobile; + bool isDesktop = + sizingInfo.deviceScreenType == DeviceScreenType.desktop; - return Container( - // color: Color(0xFFF4F4FB), - child: Form( - key: _formKey, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(28.0), - child: Center( - child: Column(children: _buildAccomadtionForm(isDesktop)), + return Container( + // color: Color(0xFFF4F4FB), + child: Form( + key: _formKey, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(28.0), + child: Center( + child: Column(children: _buildAccomadtionForm(isDesktop)), + ), ), - ) - ], + ], + ), ), ), - ), - ); - }); + ); + }, + ); } List _buildAccomadtionForm(bool isDesktop) { @@ -714,9 +735,7 @@ class _ForexScreenState extends State { return [ ...buildResponsiveRow(_buildFirstRow(isDesktop)), - SizedBox( - height: 5, - ), + SizedBox(height: 5), // Align( // alignment: Alignment.centerLeft, // child: Text( @@ -743,9 +762,7 @@ class _ForexScreenState extends State { // Divider( // thickness: 0.3, // ), - SizedBox( - height: 10, - ), + SizedBox(height: 10), ...buildResponsiveRow(_buildSecondRow(isDesktop)), ...buildResponsiveRow(_buildCardDetailsRow(isDesktop)), ...buildResponsiveRow(_buildForexCard(isDesktop)), @@ -769,8 +786,9 @@ class _ForexScreenState extends State { initialDate = DateTime.parse(flightFirstTripDateNotifier.value!); // textControllers["_forexStartDate"]?.text = // DateFormat('yyyy-MM-dd').format(initialDate); - textControllers["_forexStartDate"]?.text = - DateFormat('dd-MM-yyyy').format(initialDate); + textControllers["_forexStartDate"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(initialDate); } catch (e) { initialDate = today; } @@ -804,8 +822,9 @@ class _ForexScreenState extends State { if (pickedDate != null && pickedDate != _selectedCheckOutDate) { setState(() { _selectedCheckOutDate = pickedDate; - textControllers["_forexStartDate"]?.text = - DateFormat('dd-MM-yyyy').format(pickedDate); + textControllers["_forexStartDate"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); }); } } @@ -854,8 +873,9 @@ class _ForexScreenState extends State { if (pickedDate != null && pickedDate != _selectedEndDate) { setState(() { _selectedEndDate = pickedDate; - textControllers["_forexEndDate"]?.text = - DateFormat('dd-MM-yyyy').format(pickedDate); + textControllers["_forexEndDate"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); // textControllers["_forexEndDate"]?.text = // DateFormat('dd-MM-yyyy').format(initialDate); }); @@ -869,9 +889,10 @@ class _ForexScreenState extends State { Text( "Start Date", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldForexWrapper( @@ -888,10 +909,12 @@ class _ForexScreenState extends State { await _selectCheckOutDate(context); if (textControllers["_forexEndDate"]!.text.isNotEmpty) { - DateTime? startDate = - _parseDate(textControllers["_forexStartDate"]!.text); - DateTime? endDate = - _parseDate(textControllers["_forexEndDate"]!.text); + DateTime? startDate = _parseDate( + textControllers["_forexStartDate"]!.text, + ); + DateTime? endDate = _parseDate( + textControllers["_forexEndDate"]!.text, + ); if (startDate != null && endDate != null && @@ -914,13 +937,18 @@ class _ForexScreenState extends State { style: const TextStyle(fontSize: 12), decoration: InputDecoration( labelText: "Select Date", - labelStyle: - const TextStyle(fontSize: 12, color: Colors.grey), + labelStyle: const TextStyle( + fontSize: 12, + color: Colors.grey, + ), floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, contentPadding: const EdgeInsets.symmetric(vertical: 16), - suffixIcon: const Icon(Icons.calendar_today, - size: 16, color: Colors.grey), + suffixIcon: const Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), ), ), ), @@ -936,21 +964,17 @@ class _ForexScreenState extends State { ], ], ), - if (isDesktop) - Spacer() - else - SizedBox( - height: 8, - ), + if (isDesktop) Spacer() else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "End Date", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldForexWrapper( @@ -964,10 +988,12 @@ class _ForexScreenState extends State { await _selectForexEndDate(context); if (textControllers["_forexEndDate"]!.text.isNotEmpty) { - DateTime? startDate = - _parseDate(textControllers["_forexStartDate"]!.text); - DateTime? endDate = - _parseDate(textControllers["_forexEndDate"]!.text); + DateTime? startDate = _parseDate( + textControllers["_forexStartDate"]!.text, + ); + DateTime? endDate = _parseDate( + textControllers["_forexEndDate"]!.text, + ); if (startDate != null && endDate != null && @@ -995,8 +1021,11 @@ class _ForexScreenState extends State { floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 16), - suffixIcon: Icon(Icons.calendar_today, - size: 16, color: Colors.grey), + suffixIcon: Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), ), ), ), @@ -1013,21 +1042,17 @@ class _ForexScreenState extends State { ], ], ), - if (isDesktop) - Spacer() - else - SizedBox( - height: 8, - ), + if (isDesktop) Spacer() else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Duration", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldForexWrapper( @@ -1043,9 +1068,10 @@ class _ForexScreenState extends State { // selectedDuration?.isNotEmpty == true ? selectedDuration! : "Duration", selectedDuration ?? "Duration", style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), // decoration: const InputDecoration( // labelText: "To", // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), @@ -1071,7 +1097,7 @@ class _ForexScreenState extends State { // Map country codes to country names countryMap = { for (var item in countryList) - item['country_code'] as String: item['country_name'] as String + item['country_code'] as String: item['country_name'] as String, }; // Extract only country codes for processing @@ -1099,9 +1125,10 @@ class _ForexScreenState extends State { Text( "Country", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldForexWrapper( @@ -1124,25 +1151,25 @@ class _ForexScreenState extends State { dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( - horizontal: 1, + contentPadding: EdgeInsets.symmetric(horizontal: 1), + ), + ), + dropdownBuilder: + (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select Country", + style: TextStyle(fontSize: 12), + ), ), - ), - ), - dropdownBuilder: (context, selectedItem) => Align( - // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select Country", - style: TextStyle(fontSize: 12), - ), - ), onChanged: (String? newValue) { setState(() { // Find the country_code based on selected country_name - selectedCountry = countryMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; + selectedCountry = + countryMap.entries + .firstWhere((entry) => entry.value == newValue) + .key; _onCountryChanged(selectedCountry); }); }, @@ -1164,22 +1191,19 @@ class _ForexScreenState extends State { // height: 8, // ), if (isDesktop) - SizedBox( - width: MediaQuery.of(context).size.width * 0.048, - ) + SizedBox(width: MediaQuery.of(context).size.width * 0.048) else - SizedBox( - height: 8, - ), + SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( "Currency *", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldForexWrapper( @@ -1200,9 +1224,10 @@ class _ForexScreenState extends State { selectedCurrency ?? "Currency", // selectedCurrency?.isNotEmpty == true ? selectedCurrency! : "Currency", style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), ), ), @@ -1211,21 +1236,17 @@ class _ForexScreenState extends State { ], ), // if (isDesktop)SizedBox(width: 8,) else SizedBox(height: 8,), - if (isDesktop) - Spacer() - else - SizedBox( - height: 8, - ), + if (isDesktop) Spacer() else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Perdiem Amount", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldForexWrapper( @@ -1241,9 +1262,10 @@ class _ForexScreenState extends State { selectedPerdiemAmount ?? "Amount", // selectedPerdiemAmount?.isNotEmpty == true ? selectedPerdiemAmount! : "Amount", style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), // decoration: const InputDecoration( // labelText: "To", // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), @@ -1277,9 +1299,10 @@ class _ForexScreenState extends State { Text( "Transport", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w500, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), Container( @@ -1298,8 +1321,9 @@ class _ForexScreenState extends State { }, keyboardType: TextInputType.numberWithOptions(decimal: true), inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp( - r'^\d*\.?\d*$')), // Allow only positive numbers with optional decimal + FilteringTextInputFormatter.allow( + RegExp(r'^\d*\.?\d*$'), + ), // Allow only positive numbers with optional decimal ], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( @@ -1310,7 +1334,7 @@ class _ForexScreenState extends State { contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), - ) + ), // CustomTextFieldItnerarySubWrapper( // width: isDesktop ? MediaQuery.of(context).size.width * 0.07 : null, // isFocused: focusStates["_transport"] ?? false, @@ -1339,23 +1363,17 @@ class _ForexScreenState extends State { // ), ], ), - if (isDesktop) - SizedBox( - width: 10, - ) - else - SizedBox( - height: 8, - ), + if (isDesktop) SizedBox(width: 10) else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Accomodation", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w500, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), Container( @@ -1374,8 +1392,9 @@ class _ForexScreenState extends State { }, keyboardType: TextInputType.numberWithOptions(decimal: true), inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp( - r'^\d*\.?\d*$')), // Allow only positive numbers with optional decimal + FilteringTextInputFormatter.allow( + RegExp(r'^\d*\.?\d*$'), + ), // Allow only positive numbers with optional decimal ], style: const TextStyle(fontSize: 12), decoration: const InputDecoration( @@ -1386,7 +1405,7 @@ class _ForexScreenState extends State { contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), - ) + ), // CustomTextFieldItnerarySubWrapper( // width: isDesktop ? MediaQuery.of(context).size.width * 0.07 : null, // isFocused: focusStates["_accomodation"] ?? false, @@ -1415,54 +1434,49 @@ class _ForexScreenState extends State { // ), ], ), - if (isDesktop) - SizedBox( - width: 10, - ) - else - SizedBox( - height: 8, - ), + if (isDesktop) SizedBox(width: 10) else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Telephone", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w500, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), Container( - color: Colors.yellow.shade50, - padding: const EdgeInsets.only(left: 10), - width: - isDesktop ? MediaQuery.of(context).size.width * 0.06 : null, - height: 30, - child: TextField( - focusNode: focusNodes["_telephone"], - controller: textControllers["_telephone"], - onChanged: (value) { - setState(() { - userEdited = true; - }); - _onFieldChangedForOthers(); - }, - keyboardType: TextInputType.numberWithOptions(decimal: true), - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp( - r'^\d*\.?\d*$')), // Allow only positive numbers with optional decimal - ], - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "0", - labelStyle: TextStyle(fontSize: 12, color: Colors.black), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), - )) + color: Colors.yellow.shade50, + padding: const EdgeInsets.only(left: 10), + width: isDesktop ? MediaQuery.of(context).size.width * 0.06 : null, + height: 30, + child: TextField( + focusNode: focusNodes["_telephone"], + controller: textControllers["_telephone"], + onChanged: (value) { + setState(() { + userEdited = true; + }); + _onFieldChangedForOthers(); + }, + keyboardType: TextInputType.numberWithOptions(decimal: true), + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'^\d*\.?\d*$'), + ), // Allow only positive numbers with optional decimal + ], + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "0", + labelStyle: TextStyle(fontSize: 12, color: Colors.black), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + ), + ), + ), // CustomTextFieldItnerarySubWrapper( // width: isDesktop ? MediaQuery.of(context).size.width * 0.07 : null, // isFocused: focusStates["_telephone"] ?? false, @@ -1491,23 +1505,17 @@ class _ForexScreenState extends State { // ), ], ), - if (isDesktop) - SizedBox( - width: 40, - ) - else - SizedBox( - height: 8, - ), + if (isDesktop) SizedBox(width: 40) else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Other Expenses", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldForexWrapper( @@ -1523,9 +1531,10 @@ class _ForexScreenState extends State { // focusNode: _toFocusNode, // controller: _toController, style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), // decoration: const InputDecoration( // labelText: "To", // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), @@ -1545,19 +1554,24 @@ class _ForexScreenState extends State { List _buildCardDetailsRow(bool isDesktop) { List purposeList = widget.apiData?['flight_class'] ?? []; - List> dropdownItems = purposeList - .map((item) => DropdownMenuItem( - value: item['dropdown_value'], - child: Text(item['dropdown_value']), - )) - .toList(); + List> dropdownItems = + purposeList + .map( + (item) => DropdownMenuItem( + value: item['dropdown_value'], + child: Text(item['dropdown_value']), + ), + ) + .toList(); if (dropdownItems.isEmpty) { dropdownItems.add( DropdownMenuItem( value: null, - child: Text("No options available", - style: TextStyle(color: Colors.grey)), + child: Text( + "No options available", + style: TextStyle(color: Colors.grey), + ), ), ); } @@ -1572,9 +1586,10 @@ class _ForexScreenState extends State { Text( "Cash*", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldForexWrapper( @@ -1590,7 +1605,8 @@ class _ForexScreenState extends State { onChanged: (value) { // errorMessages["deposit_on_cash"] = ""; _validateCashAmount( - value); // Call validation when text changes + value, + ); // Call validation when text changes }, decoration: const InputDecoration( labelText: "Cash", @@ -1613,12 +1629,7 @@ class _ForexScreenState extends State { ], ), - if (isDesktop) - Spacer() - else - SizedBox( - height: 8, - ), + if (isDesktop) Spacer() else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -1626,9 +1637,10 @@ class _ForexScreenState extends State { Text( "Card*", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldForexWrapper( @@ -1643,7 +1655,8 @@ class _ForexScreenState extends State { keyboardType: TextInputType.number, onChanged: (value) { _validateCardAmount( - value); // Call validation when text changes + value, + ); // Call validation when text changes }, decoration: const InputDecoration( labelText: "Card", @@ -1665,12 +1678,7 @@ class _ForexScreenState extends State { ], ), - if (isDesktop) - Spacer() - else - SizedBox( - height: 8, - ), + if (isDesktop) Spacer() else SizedBox(height: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -1678,9 +1686,10 @@ class _ForexScreenState extends State { Text( "Total Amount", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldForexWrapper( @@ -1696,9 +1705,10 @@ class _ForexScreenState extends State { selectedQuotedAmount ?? "0", // selectedPerdiemAmount?.isNotEmpty == true ? selectedPerdiemAmount! : "Amount", style: const TextStyle( - fontSize: 13, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 13, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), ), ), @@ -1824,9 +1834,10 @@ class _ForexScreenState extends State { Text( "Comments", style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), SizedBox(height: 5), CustomTextFieldWrapper( @@ -1853,9 +1864,7 @@ class _ForexScreenState extends State { ], ), if (isDesktop) Spacer(), - SizedBox( - height: 5, - ), + SizedBox(height: 5), // Actions row remains a Row Column( children: [ @@ -1872,96 +1881,94 @@ class _ForexScreenState extends State { return [ !isChecked ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Card Number", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Card Number", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), ), - SizedBox(height: 5), - CustomTextFieldForexWrapper( - isFocused: focusStates["_cardNumber"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 35, - child: TextField( - enabled: !isChecked, - focusNode: focusNodes["_cardNumber"], - controller: textControllers["_cardNumber"], - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Card Number", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), + ), + SizedBox(height: 5), + CustomTextFieldForexWrapper( + isFocused: focusStates["_cardNumber"] ?? false, + isDesktop: isDesktop, + child: SizedBox( + height: 35, + child: TextField( + enabled: !isChecked, + focusNode: focusNodes["_cardNumber"], + controller: textControllers["_cardNumber"], + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Card Number", + labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), ), - if (errorMessages["card_number"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - "Required", - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], + ), + if (errorMessages["card_number"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + "Required", + style: TextStyle(color: Colors.red, fontSize: 12), + ), ], - ) + ], + ) : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Delivery Location", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Delivery Location", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: focusStates["_deliveryLocation"] ?? - false, // Dropdown doesn't use focus - isDesktop: isDesktop, - width: isDesktop - ? MediaQuery.of(context).size.width * 0.45 - : null, - child: SizedBox( - height: 35, - child: TextField( - focusNode: focusNodes["_deliveryLocation"], - controller: textControllers["_deliveryLocation"], - style: TextStyle(fontSize: 12), - decoration: InputDecoration( - labelText: "Location", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: + focusStates["_deliveryLocation"] ?? + false, // Dropdown doesn't use focus + isDesktop: isDesktop, + width: + isDesktop ? MediaQuery.of(context).size.width * 0.45 : null, + child: SizedBox( + height: 35, + child: TextField( + focusNode: focusNodes["_deliveryLocation"], + controller: textControllers["_deliveryLocation"], + style: TextStyle(fontSize: 12), + decoration: InputDecoration( + labelText: "Location", + labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), ), - if (errorMessages["delivery_location"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - "Required", - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], + ), + if (errorMessages["delivery_location"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + "Required", + style: TextStyle(color: Colors.red, fontSize: 12), + ), ], - ), + ], + ), if (isDesktop) - SizedBox( - width: MediaQuery.of(context).size.width * 0.04, - ) + SizedBox(width: MediaQuery.of(context).size.width * 0.04) else - SizedBox( - height: 8, - ), + SizedBox(height: 8), Column( children: [ Row( @@ -1995,9 +2002,10 @@ class _ForexScreenState extends State { Text( "Check If You Don't Have a Forex Account", style: GoogleFonts.poppins( - fontSize: 10, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74)), + fontSize: 10, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), ), ], ), @@ -2015,9 +2023,7 @@ class _ForexScreenState extends State { }, style: ElevatedButton.styleFrom( backgroundColor: Colors.grey[400], // Light grey color - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), child: Text( @@ -2026,7 +2032,6 @@ class _ForexScreenState extends State { ), ), SizedBox(width: 10), // Space between buttons - // Save Changes Button ElevatedButton( onPressed: () { @@ -2034,9 +2039,7 @@ class _ForexScreenState extends State { }, style: ElevatedButton.styleFrom( backgroundColor: Color(0xFF114D8B), // Primary color for save - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), child: Text( diff --git a/lib/Screens/myTemplates/dialog_placeholders.dart b/lib/Screens/myTemplates/dialog_placeholders.dart index f9500f8..428c983 100644 --- a/lib/Screens/myTemplates/dialog_placeholders.dart +++ b/lib/Screens/myTemplates/dialog_placeholders.dart @@ -42,7 +42,7 @@ class _PlaceholdersModalState extends State { content: Container( width: isDesktop - ? MediaQuery.of(context).size.width * 0.3 + ? MediaQuery.of(context).size.width * 0.4 : double.maxFinite, // Set max height so ListView knows constraints height: 300, diff --git a/lib/Screens/myTemplates/template.dart b/lib/Screens/myTemplates/template.dart index a896883..6a34d81 100644 --- a/lib/Screens/myTemplates/template.dart +++ b/lib/Screens/myTemplates/template.dart @@ -642,7 +642,7 @@ class TemplateState extends State