From c0218ad1c996b05d4d3ae5d7efb84481c86ea310 Mon Sep 17 00:00:00 2001 From: venba-Inspriron-3558 Date: Thu, 19 Jun 2025 17:01:32 +0530 Subject: [PATCH 1/2] report completed 4 --- lib/Screens/costCenter/costCenter_list.dart | 30 +- lib/Screens/department/department_list.dart | 30 +- lib/Screens/forex/forex_list.dart | 30 +- lib/Screens/group/groupList.dart | 31 +- lib/Screens/hotels/hotels_list.dart | 30 +- lib/Screens/myTemplates/templateForex.dart | 25 + lib/Screens/organization/orgSetup.dart | 37 +- lib/Screens/policy/policy_list.dart | 30 +- lib/Screens/reports/advancePurchase.dart | 601 ++++++++++-------- lib/Screens/reports/guestHouse.dart | 576 ++++++++++------- lib/Screens/reports/misAir.dart | 601 ++++++++++-------- lib/Screens/reports/misForex.dart | 601 ++++++++++-------- lib/Screens/reports/misHotel.dart | 582 +++++++++-------- lib/Screens/reports/reportList.dart | 25 +- lib/Screens/reports/servicesAnalysis.dart | 576 ++++++++++------- lib/Screens/traveller/travellerList.dart | 31 +- .../create_user/create_user.dart | 42 +- lib/widgets/custom_breadcrumb_navigation.dart | 162 +++++ 18 files changed, 2436 insertions(+), 1604 deletions(-) create mode 100644 lib/widgets/custom_breadcrumb_navigation.dart diff --git a/lib/Screens/costCenter/costCenter_list.dart b/lib/Screens/costCenter/costCenter_list.dart index c653e05..9ff345e 100644 --- a/lib/Screens/costCenter/costCenter_list.dart +++ b/lib/Screens/costCenter/costCenter_list.dart @@ -14,6 +14,7 @@ import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import 'costCenterDetails.dart'; class CostCenterList extends StatefulWidget { @@ -279,14 +280,31 @@ class CostCenterListState extends State { children: [ Row( children: [ - Text( - 'Cost Center Details', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Organization Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + } + ), + BreadcrumbItem( + title: 'Cost Center Details', + ), + ], ), ), + // Text( + // 'Cost Center Details', + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + // color: Colors.black, + // ), + // ), ], ), if (isDesktop) diff --git a/lib/Screens/department/department_list.dart b/lib/Screens/department/department_list.dart index 5d62bf1..28737f9 100644 --- a/lib/Screens/department/department_list.dart +++ b/lib/Screens/department/department_list.dart @@ -14,6 +14,7 @@ import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import 'departmentDetails.dart'; class DepartmentList extends StatefulWidget { @@ -278,14 +279,31 @@ class DepartmentListState extends State { children: [ Row( children: [ - Text( - 'Department Details', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Organization Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + } + ), + BreadcrumbItem( + title: 'Department Details', + ), + ], ), ), + // Text( + // 'Department Details', + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + // color: Colors.black, + // ), + // ), ], ), if (isDesktop) diff --git a/lib/Screens/forex/forex_list.dart b/lib/Screens/forex/forex_list.dart index cbaf57c..ca8c559 100644 --- a/lib/Screens/forex/forex_list.dart +++ b/lib/Screens/forex/forex_list.dart @@ -14,6 +14,7 @@ import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import '../../widgets/popup_userList_action.dart'; import 'forexDetails.dart'; @@ -448,14 +449,31 @@ class ForexDataListState extends State { children: [ Row( children: [ - Text( - 'Perdiem Amount Details', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Organization Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + } + ), + BreadcrumbItem( + title: 'Perdiem Amount Details', + ), + ], ), ), + // Text( + // 'Perdiem Amount Details', + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + // color: Colors.black, + // ), + // ), ], ), if (isDesktop) diff --git a/lib/Screens/group/groupList.dart b/lib/Screens/group/groupList.dart index 10ce46d..bc3f5b1 100644 --- a/lib/Screens/group/groupList.dart +++ b/lib/Screens/group/groupList.dart @@ -13,6 +13,7 @@ import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import 'groupDetails.dart'; class GroupList extends StatefulWidget { @@ -297,14 +298,32 @@ class _GroupListState extends State { children: [ Row( children: [ - Text( - 'Group', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Organization Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + } + ), + BreadcrumbItem( + title: 'Group ', + ), + ], ), ), + // Text( + // 'Group', + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + // color: Colors.black, + // ), + // ), + ], ), if (isDesktop) diff --git a/lib/Screens/hotels/hotels_list.dart b/lib/Screens/hotels/hotels_list.dart index 270bae5..7fd2bf1 100644 --- a/lib/Screens/hotels/hotels_list.dart +++ b/lib/Screens/hotels/hotels_list.dart @@ -14,6 +14,7 @@ import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import '../../widgets/popup_userList_action.dart'; import 'hotelsDetails.dart'; @@ -329,14 +330,31 @@ class HotelsDataListState extends State { children: [ Row( children: [ - Text( - 'Hotel Details', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Organization Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + } + ), + BreadcrumbItem( + title: 'Hotel Details', + ), + ], ), ), + // Text( + // 'Hotel Details', + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + // color: Colors.black, + // ), + // ), ], ), if (isDesktop) diff --git a/lib/Screens/myTemplates/templateForex.dart b/lib/Screens/myTemplates/templateForex.dart index 8a86eb1..a6a1ea6 100644 --- a/lib/Screens/myTemplates/templateForex.dart +++ b/lib/Screens/myTemplates/templateForex.dart @@ -39,6 +39,7 @@ import '../../routes/custom_appBar.dart'; import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import '../../widgets/custom_user_travel.dart'; import 'dialog_placeholders.dart'; @@ -535,6 +536,30 @@ class TemplateForexState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ + + + Row( + children: [ + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Organization Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + } + ), + BreadcrumbItem( + title: 'Forex', + ), + ], + ), + ), + ], + ), + SizedBox(height: 10), Text( formatTemplateName(templateName), style: GoogleFonts.poppins( diff --git a/lib/Screens/organization/orgSetup.dart b/lib/Screens/organization/orgSetup.dart index efec67c..08d046b 100644 --- a/lib/Screens/organization/orgSetup.dart +++ b/lib/Screens/organization/orgSetup.dart @@ -17,6 +17,7 @@ import '../../routes/custom_appBar.dart'; import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; class OrgSetUp extends StatefulWidget { @override @@ -574,17 +575,37 @@ class _OrgSetUpState extends State { Container( color: Colors.white, child: Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - selectedOrg != null && selectedOrg!.isNotEmpty - ? "Update Organization" - : "Create Organization", - style: GoogleFonts.poppins( - fontSize: 15, - fontWeight: FontWeight.w500, + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Organization Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + } + ), + BreadcrumbItem( + title: selectedOrg != null && selectedOrg!.isNotEmpty + ? "Update Organization" + : "Create Organization", + ), + ], ), ), + // Text( + // selectedOrg != null && selectedOrg!.isNotEmpty + // ? "Update Organization" + // : "Create Organization", + // style: GoogleFonts.poppins( + // fontSize: 15, + // fontWeight: FontWeight.w500, + // ), + // ), ], ), ), diff --git a/lib/Screens/policy/policy_list.dart b/lib/Screens/policy/policy_list.dart index 88c245d..667ba53 100644 --- a/lib/Screens/policy/policy_list.dart +++ b/lib/Screens/policy/policy_list.dart @@ -13,6 +13,7 @@ import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; class PolicyList extends StatefulWidget { @override @@ -334,14 +335,31 @@ class _PolicyListState extends State { children: [ Row( children: [ - Text( - 'Policy', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Organization Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + } + ), + BreadcrumbItem( + title: 'Policy', + ), + ], ), ), + // Text( + // 'Policy', + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + // color: Colors.black, + // ), + // ), ], ), if (isDesktop) diff --git a/lib/Screens/reports/advancePurchase.dart b/lib/Screens/reports/advancePurchase.dart index 684492d..d72a529 100644 --- a/lib/Screens/reports/advancePurchase.dart +++ b/lib/Screens/reports/advancePurchase.dart @@ -17,6 +17,7 @@ import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import '../../widgets/custom_text_field.dart'; class AdvancePurchase extends StatefulWidget { @@ -426,278 +427,55 @@ class _AdvancePurchaseState extends State crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // ------------------- First Row ------------------- - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Advance Purchase', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ), - ), - Row( + Container( + color: Colors.white, + child: + isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF114D8B), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: BorderSide(color: Color(0xFF114D8B), width: 2), - ), - padding: EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ), - ), - onPressed: handleDownload, - child: Row( - children: [ - Text( - "Excel", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - color: Colors.white, - ), - ), - SizedBox(width: 8), - Icon( - Icons.file_present_outlined, - size: 15, - color: Colors.white, - ), - ], - ), - ), - // SizedBox(width: 10), - // ElevatedButton( - // style: ElevatedButton.styleFrom( - // backgroundColor: Color(0xFF114D8B), - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(8), - // side: BorderSide(color: Color(0xFF114D8B), width: 2), - // ), - // padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - // ), - // onPressed: () { - // // Your PDF export logic here - // }, - // child: Row( - // children: [ - // Text( - // "PDF", - // style: GoogleFonts.poppins( - // fontSize: isDesktop ? 13 : 11, - // color: Colors.white, - // ), - // ), - // SizedBox(width: 8), - // Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white), - // ], - // ), - // ), + buildTitle(isDesktop), + Spacer(), + buildExports(isDesktop) ], - ), - ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildTitle(isDesktop), + SizedBox(height: 8), + buildExports(isDesktop) + ], + ) ), SizedBox(height: 5), // ------------------- Second Row ------------------- - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( "From Date *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: focusStates["from_date"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () async { - final pickedDate = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(2000), - lastDate: DateTime(2100), - ); - if (pickedDate != null) { - textControllers["from_date"]?.text = DateFormat( - 'dd-MM-yyyy', - ).format(pickedDate); - } - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["from_date"], - controller: textControllers["from_date"], - 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: const EdgeInsets.symmetric( - vertical: 16, - ), - suffixIcon: const Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), + Container( + color: Colors.white, + child: + isDesktop + ? Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildFromDateField(isDesktop), + Spacer(), + buildToDateField(isDesktop), + Spacer(), // Space after Last Name + buildSearchButton(isDesktop), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildFromDateField(isDesktop), + SizedBox(height: 8), // Vertical space + buildToDateField(isDesktop), + SizedBox(height: 8), + buildSearchButton(isDesktop), + ], ), - ), - ), - ), - ), - if (errorMessages["from_date"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["from_date"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( "To Date *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: focusStates["to_date"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () async { - final fromDateText = - textControllers["from_date"]?.text; - DateTime? mintoDate; - if (fromDateText != null && fromDateText.isNotEmpty) { - mintoDate = DateFormat( - 'dd-MM-yyyy', - ).parse(fromDateText); - } - - final pickedDate = await showDatePicker( - context: context, - initialDate: mintoDate ?? DateTime.now(), - firstDate: mintoDate ?? DateTime(2000), - lastDate: DateTime(2100), - ); - - if (pickedDate != null) { - textControllers["to_date"]?.text = DateFormat( - 'dd-MM-yyyy', - ).format(pickedDate); - } - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["to_date"], - controller: textControllers["to_date"], - readOnly: true, - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Select Date", - labelStyle: TextStyle( - fontSize: 12, - color: Colors.grey, - ), - floatingLabelBehavior: - FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( - vertical: 16, - ), - suffixIcon: Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["to_date"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["to_date"]!, - style: const TextStyle(color: Colors.red, fontSize: 12), - maxLines: 2, // Allow it to wrap onto two lines - overflow: - TextOverflow - .ellipsis, // Add ellipsis if it still overflows - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Padding( - padding: EdgeInsets.only(top: 10, left: 4), - child: SizedBox( - child: 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: EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ), - ), - onPressed: () { - handleSubmit(); - }, - child: Row( - mainAxisSize: - MainAxisSize.min, // Ensures content fits nicely - children: [ - Text( - "Search", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - ), - ), - SizedBox(width: 8), // spacing between icon and text - Icon(Icons.search, size: 15, color: Colors.white), - ], - ), - ), - ), - ), - ], - ), + ), SizedBox(height: 5), // ------------------- Third Row ------------------- @@ -1611,4 +1389,297 @@ class _AdvancePurchaseState extends State ), ); } + + Widget buildTitle(bool isDesktop){ + return // Left side: Breadcrumb inside a Container (optional) + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Report List', + tooltip: 'Go To Report List', + onTap: (context) { + // Navigator.pushNamed(context, '/report'); + context.go("/report"); + } + ), + BreadcrumbItem( + title: 'Advance Purchase', + ), + ], + ), + ); + } + + Widget buildExports(bool isDesktop){ + return Row( + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF114D8B), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(color: Color(0xFF114D8B), width: 2), + ), + padding: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: handleDownload, + child: Row( + children: [ + Text( + "Excel", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + color: Colors.white, + ), + ), + SizedBox(width: 8), + Icon( + Icons.file_present_outlined, + size: 15, + color: Colors.white, + ), + ], + ), + ), + // SizedBox(width: 10), + // ElevatedButton( + // style: ElevatedButton.styleFrom( + // backgroundColor: Color(0xFF114D8B), + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(8), + // side: BorderSide(color: Color(0xFF114D8B), width: 2), + // ), + // padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + // ), + // onPressed: () { + // // Your PDF export logic here + // }, + // child: Row( + // children: [ + // Text( + // "PDF", + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 13 : 11, + // color: Colors.white, + // ), + // ), + // SizedBox(width: 8), + // Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white), + // ], + // ), + // ), + ], + ); + + } + + Widget buildFromDateField(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( "From Date *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: focusStates["from_date"] ?? false, + // isDesktop: isDesktop ? MediaQuery.of(context).size.height * 0.51 : 200, + isDesktop: isDesktop, + width: isDesktop ? null : double.infinity, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () async { + final pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2100), + ); + if (pickedDate != null) { + textControllers["from_date"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + } + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["from_date"], + controller: textControllers["from_date"], + 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: const EdgeInsets.symmetric( + vertical: 16, + ), + suffixIcon: const Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["from_date"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["from_date"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ); + } + + Widget buildToDateField(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( "To Date *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: focusStates["to_date"] ?? false, + isDesktop: isDesktop, + width: isDesktop ? null : double.infinity, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () async { + final fromDateText = + textControllers["from_date"]?.text; + DateTime? mintoDate; + if (fromDateText != null && fromDateText.isNotEmpty) { + mintoDate = DateFormat( + 'dd-MM-yyyy', + ).parse(fromDateText); + } + + final pickedDate = await showDatePicker( + context: context, + initialDate: mintoDate ?? DateTime.now(), + firstDate: mintoDate ?? DateTime(2000), + lastDate: DateTime(2100), + ); + + if (pickedDate != null) { + textControllers["to_date"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + } + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["to_date"], + controller: textControllers["to_date"], + readOnly: true, + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Select Date", + labelStyle: TextStyle( + fontSize: 12, + color: Colors.grey, + ), + floatingLabelBehavior: + FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + vertical: 16, + ), + suffixIcon: Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["to_date"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["to_date"]!, + style: const TextStyle(color: Colors.red, fontSize: 12), + maxLines: 2, // Allow it to wrap onto two lines + overflow: + TextOverflow + .ellipsis, // Add ellipsis if it still overflows + ), + ], + ], + ); + } + + Widget buildSearchButton(bool isDesktop) { + return + Padding( + padding: isDesktop + ? const EdgeInsets.only(top: 22) + : EdgeInsets.zero, + child: SizedBox( + // width: isDesktop ? null : MediaQuery.of(context).size.width * 0.5, // don't delete + width: isDesktop ? null : double.infinity, + child: 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: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: () { + handleSubmit(); + }, + child: Row( + mainAxisSize: + MainAxisSize.min, // Ensures content fits nicely + children: [ + Text( + "Search", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + ), + ), + SizedBox(width: 8), // spacing between icon and text + Icon(Icons.search, size: 15, color: Colors.white), + ], + ), + ), + ), + ); + } } diff --git a/lib/Screens/reports/guestHouse.dart b/lib/Screens/reports/guestHouse.dart index 707d06f..5993c1a 100644 --- a/lib/Screens/reports/guestHouse.dart +++ b/lib/Screens/reports/guestHouse.dart @@ -17,6 +17,7 @@ import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import '../../widgets/custom_text_field.dart'; class GuestHouse extends StatefulWidget { @@ -445,252 +446,55 @@ class _GuestHouseState extends State crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // ------------------- First Row ------------------- - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Guest House', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ), - ), - Row( + // ------------------- First Row ------------------- + Container( + color: Colors.white, + child: + isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF114D8B), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: BorderSide(color: Color(0xFF114D8B), width: 2), - ), - padding: EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ), - ), - onPressed: handleDownload, - child: Row( - children: [ - Text( - "Excel", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - color: Colors.white, - ), - ), - SizedBox(width: 8), - Icon( - Icons.file_present_outlined, - size: 15, - color: Colors.white, - ), - ], - ), - ), + buildTitle(isDesktop), + Spacer(), + buildExports(isDesktop) ], - ), - ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildTitle(isDesktop), + SizedBox(height: 8), + buildExports(isDesktop) + ], + ) ), SizedBox(height: 5), // ------------------- Second Row ------------------- - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "From Date *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: focusStates["from_date"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () async { - final pickedDate = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(2000), - lastDate: DateTime(2100), - ); - if (pickedDate != null) { - textControllers["from_date"]?.text = DateFormat( - 'dd-MM-yyyy', - ).format(pickedDate); - } - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["from_date"], - controller: textControllers["from_date"], - 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: const EdgeInsets.symmetric( - vertical: 16, - ), - suffixIcon: const Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["from_date"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["from_date"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "To Date *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: focusStates["to_date"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () async { - final fromDateText = - textControllers["from_date"]?.text; - DateTime? mintoDate; - if (fromDateText != null && fromDateText.isNotEmpty) { - mintoDate = DateFormat( - 'dd-MM-yyyy', - ).parse(fromDateText); - } - - final pickedDate = await showDatePicker( - context: context, - initialDate: mintoDate ?? DateTime.now(), - firstDate: mintoDate ?? DateTime(2000), - lastDate: DateTime(2100), - ); - - if (pickedDate != null) { - textControllers["to_date"]?.text = DateFormat( - 'dd-MM-yyyy', - ).format(pickedDate); - } - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["to_date"], - controller: textControllers["to_date"], - readOnly: true, - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Select Date", - labelStyle: TextStyle( - fontSize: 12, - color: Colors.grey, - ), - floatingLabelBehavior: - FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( - vertical: 16, - ), - suffixIcon: Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["to_date"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["to_date"]!, - style: const TextStyle(color: Colors.red, fontSize: 12), - maxLines: 2, // Allow it to wrap onto two lines - overflow: - TextOverflow - .ellipsis, // Add ellipsis if it still overflows - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Padding( - padding: EdgeInsets.only(top: 10, left: 4), - child: SizedBox( - child: 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: EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ), - ), - onPressed: () { - handleSubmit(); - }, - child: Row( - mainAxisSize: - MainAxisSize.min, // Ensures content fits nicely - children: [ - Text( - "Search", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - ), - ), - SizedBox(width: 8), // spacing between icon and text - Icon(Icons.search, size: 15, color: Colors.white), - ], - ), - ), - ), - ), - ], + Container( + color: Colors.white, + child: + isDesktop + ? Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildFromDateField(isDesktop), + Spacer(), + buildToDateField(isDesktop), + Spacer(), // Space after Last Name + buildSearchButton(isDesktop), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildFromDateField(isDesktop), + SizedBox(height: 8), // Vertical space + buildToDateField(isDesktop), + SizedBox(height: 8), + buildSearchButton(isDesktop), + ], + ), ), SizedBox(height: 5), @@ -1718,4 +1522,296 @@ class _GuestHouseState extends State ), ); } + + Widget buildTitle(bool isDesktop){ + return // Left side: Breadcrumb inside a Container (optional) + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Report List', + tooltip: 'Go To Report List', + onTap: (context) { + // Navigator.pushNamed(context, '/report'); + context.go("/report"); + } + ), + BreadcrumbItem( + title: 'Guest House', + ), + ], + ), + ); + } + + Widget buildExports(bool isDesktop){ + return Row( + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF114D8B), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(color: Color(0xFF114D8B), width: 2), + ), + padding: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: handleDownload, + child: Row( + children: [ + Text( + "Excel", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + color: Colors.white, + ), + ), + SizedBox(width: 8), + Icon( + Icons.file_present_outlined, + size: 15, + color: Colors.white, + ), + ], + ), + ), + // SizedBox(width: 10), + // ElevatedButton( + // style: ElevatedButton.styleFrom( + // backgroundColor: Color(0xFF114D8B), + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(8), + // side: BorderSide(color: Color(0xFF114D8B), width: 2), + // ), + // padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + // ), + // onPressed: () { + // // Your PDF export logic here + // }, + // child: Row( + // children: [ + // Text( + // "PDF", + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 13 : 11, + // color: Colors.white, + // ), + // ), + // SizedBox(width: 8), + // Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white), + // ], + // ), + // ), + ], + ); + + } + + Widget buildFromDateField(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( "From Date *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: focusStates["from_date"] ?? false, + // isDesktop: isDesktop ? MediaQuery.of(context).size.height * 0.51 : 200, + isDesktop: isDesktop, + width: isDesktop ? null : double.infinity, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () async { + final pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2100), + ); + if (pickedDate != null) { + textControllers["from_date"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + } + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["from_date"], + controller: textControllers["from_date"], + 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: const EdgeInsets.symmetric( + vertical: 16, + ), + suffixIcon: const Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["from_date"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["from_date"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ); + } + + Widget buildToDateField(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( "To Date *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: focusStates["to_date"] ?? false, + isDesktop: isDesktop, + width: isDesktop ? null : double.infinity, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () async { + final fromDateText = + textControllers["from_date"]?.text; + DateTime? mintoDate; + if (fromDateText != null && fromDateText.isNotEmpty) { + mintoDate = DateFormat( + 'dd-MM-yyyy', + ).parse(fromDateText); + } + + final pickedDate = await showDatePicker( + context: context, + initialDate: mintoDate ?? DateTime.now(), + firstDate: mintoDate ?? DateTime(2000), + lastDate: DateTime(2100), + ); + + if (pickedDate != null) { + textControllers["to_date"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + } + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["to_date"], + controller: textControllers["to_date"], + readOnly: true, + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Select Date", + labelStyle: TextStyle( + fontSize: 12, + color: Colors.grey, + ), + floatingLabelBehavior: + FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + vertical: 16, + ), + suffixIcon: Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["to_date"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["to_date"]!, + style: const TextStyle(color: Colors.red, fontSize: 12), + maxLines: 2, // Allow it to wrap onto two lines + overflow: + TextOverflow + .ellipsis, // Add ellipsis if it still overflows + ), + ], + ], + ); + } + + Widget buildSearchButton(bool isDesktop) { + return + Padding( + padding: isDesktop + ? const EdgeInsets.only(top: 22) + : EdgeInsets.zero, + child: SizedBox( + width: isDesktop ? null : double.infinity, + child: 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: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: () { + handleSubmit(); + }, + child: Row( + mainAxisSize: + MainAxisSize.min, // Ensures content fits nicely + children: [ + Text( + "Search", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + ), + ), + SizedBox(width: 8), // spacing between icon and text + Icon(Icons.search, size: 15, color: Colors.white), + ], + ), + ), + ), + ); + } } diff --git a/lib/Screens/reports/misAir.dart b/lib/Screens/reports/misAir.dart index 3e723d4..c9cb274 100644 --- a/lib/Screens/reports/misAir.dart +++ b/lib/Screens/reports/misAir.dart @@ -17,6 +17,7 @@ import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import '../../widgets/custom_text_field.dart'; class MISair extends StatefulWidget { @@ -443,279 +444,55 @@ class _MISairState extends State with SingleTickerProviderStateMixin { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // ------------------- First Row ------------------- - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'MIS Air Report ', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ), - ), - Row( + // ------------------- First Row ------------------- + Container( + color: Colors.white, + child: + isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF114D8B), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: BorderSide(color: Color(0xFF114D8B), width: 2), - ), - padding: EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ), - ), - onPressed: handleDownload, - child: Row( - children: [ - Text( - "Excel", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - color: Colors.white, - ), - ), - SizedBox(width: 8), - Icon( - Icons.file_present_outlined, - size: 15, - color: Colors.white, - ), - ], - ), - ), - // SizedBox(width: 10), - // ElevatedButton( - // style: ElevatedButton.styleFrom( - // backgroundColor: Color(0xFF114D8B), - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(8), - // side: BorderSide(color: Color(0xFF114D8B), width: 2), - // ), - // padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - // ), - // onPressed: () { - // // Your PDF export logic here - // }, - // child: Row( - // children: [ - // Text( - // "PDF", - // style: GoogleFonts.poppins( - // fontSize: isDesktop ? 13 : 11, - // color: Colors.white, - // ), - // ), - // SizedBox(width: 8), - // Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white), - // ], - // ), - // ), + buildTitle(isDesktop), + Spacer(), + buildExports(isDesktop) ], - ), - ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildTitle(isDesktop), + SizedBox(height: 8), + buildExports(isDesktop) + ], + ) ), SizedBox(height: 5), // ------------------- Second Row ------------------- - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "From Date *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: focusStates["from_date"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () async { - final pickedDate = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(2000), - lastDate: DateTime(2100), - ); - if (pickedDate != null) { - textControllers["from_date"]?.text = DateFormat( - 'dd-MM-yyyy', - ).format(pickedDate); - } - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["from_date"], - controller: textControllers["from_date"], - 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: const EdgeInsets.symmetric( - vertical: 16, - ), - suffixIcon: const Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["from_date"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["from_date"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "To Date *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: focusStates["to_date"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () async { - final fromDateText = - textControllers["from_date"]?.text; - DateTime? mintoDate; - if (fromDateText != null && fromDateText.isNotEmpty) { - mintoDate = DateFormat( - 'dd-MM-yyyy', - ).parse(fromDateText); - } - - final pickedDate = await showDatePicker( - context: context, - initialDate: mintoDate ?? DateTime.now(), - firstDate: mintoDate ?? DateTime(2000), - lastDate: DateTime(2100), - ); - - if (pickedDate != null) { - textControllers["to_date"]?.text = DateFormat( - 'dd-MM-yyyy', - ).format(pickedDate); - } - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["to_date"], - controller: textControllers["to_date"], - readOnly: true, - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Select Date", - labelStyle: TextStyle( - fontSize: 12, - color: Colors.grey, - ), - floatingLabelBehavior: - FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( - vertical: 16, - ), - suffixIcon: Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["to_date"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["to_date"]!, - style: const TextStyle(color: Colors.red, fontSize: 12), - maxLines: 2, // Allow it to wrap onto two lines - overflow: - TextOverflow - .ellipsis, // Add ellipsis if it still overflows - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Padding( - padding: EdgeInsets.only(top: 10, left: 4), - child: SizedBox( - child: 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: EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ), - ), - onPressed: () { - handleSubmit(); - }, - child: Row( - mainAxisSize: - MainAxisSize.min, // Ensures content fits nicely - children: [ - Text( - "Search", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - ), - ), - SizedBox(width: 8), // spacing between icon and text - Icon(Icons.search, size: 15, color: Colors.white), - ], - ), - ), - ), - ), - ], + Container( + color: Colors.white, + child: + isDesktop + ? Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildFromDateField(isDesktop), + Spacer(), + buildToDateField(isDesktop), + Spacer(), // Space after Last Name + buildSearchButton(isDesktop), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildFromDateField(isDesktop), + SizedBox(height: 8), // Vertical space + buildToDateField(isDesktop), + SizedBox(height: 8), + buildSearchButton(isDesktop), + ], + ), ), SizedBox(height: 5), @@ -1733,4 +1510,294 @@ class _MISairState extends State with SingleTickerProviderStateMixin { ), ); } + Widget buildTitle(bool isDesktop){ + return // Left side: Breadcrumb inside a Container (optional) + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Report List', + tooltip: 'Go To Report List', + onTap: (context) { + // Navigator.pushNamed(context, '/report'); + context.go("/report"); + } + ), + BreadcrumbItem( + title: 'MIS Air Report ', + ), + ], + ), + ); + } + Widget buildExports(bool isDesktop){ + return Row( + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF114D8B), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(color: Color(0xFF114D8B), width: 2), + ), + padding: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: handleDownload, + child: Row( + children: [ + Text( + "Excel", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + color: Colors.white, + ), + ), + SizedBox(width: 8), + Icon( + Icons.file_present_outlined, + size: 15, + color: Colors.white, + ), + ], + ), + ), + // SizedBox(width: 10), + // ElevatedButton( + // style: ElevatedButton.styleFrom( + // backgroundColor: Color(0xFF114D8B), + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(8), + // side: BorderSide(color: Color(0xFF114D8B), width: 2), + // ), + // padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + // ), + // onPressed: () { + // // Your PDF export logic here + // }, + // child: Row( + // children: [ + // Text( + // "PDF", + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 13 : 11, + // color: Colors.white, + // ), + // ), + // SizedBox(width: 8), + // Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white), + // ], + // ), + // ), + ], + ); + + } + + Widget buildFromDateField(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( "From Date *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: focusStates["from_date"] ?? false, + // isDesktop: isDesktop ? MediaQuery.of(context).size.height * 0.51 : 200, + isDesktop: isDesktop, + width: isDesktop ? null : double.infinity, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () async { + final pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2100), + ); + if (pickedDate != null) { + textControllers["from_date"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + } + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["from_date"], + controller: textControllers["from_date"], + 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: const EdgeInsets.symmetric( + vertical: 16, + ), + suffixIcon: const Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["from_date"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["from_date"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ); + } + + Widget buildToDateField(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( "To Date *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: focusStates["to_date"] ?? false, + isDesktop: isDesktop, + width: isDesktop ? null : double.infinity, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () async { + final fromDateText = + textControllers["from_date"]?.text; + DateTime? mintoDate; + if (fromDateText != null && fromDateText.isNotEmpty) { + mintoDate = DateFormat( + 'dd-MM-yyyy', + ).parse(fromDateText); + } + + final pickedDate = await showDatePicker( + context: context, + initialDate: mintoDate ?? DateTime.now(), + firstDate: mintoDate ?? DateTime(2000), + lastDate: DateTime(2100), + ); + + if (pickedDate != null) { + textControllers["to_date"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + } + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["to_date"], + controller: textControllers["to_date"], + readOnly: true, + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Select Date", + labelStyle: TextStyle( + fontSize: 12, + color: Colors.grey, + ), + floatingLabelBehavior: + FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + vertical: 16, + ), + suffixIcon: Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["to_date"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["to_date"]!, + style: const TextStyle(color: Colors.red, fontSize: 12), + maxLines: 2, // Allow it to wrap onto two lines + overflow: + TextOverflow + .ellipsis, // Add ellipsis if it still overflows + ), + ], + ], + ); + } + + Widget buildSearchButton(bool isDesktop) { + return + Padding( + padding: isDesktop + ? const EdgeInsets.only(top: 22) + : EdgeInsets.zero, + child: SizedBox( + width: isDesktop ? null : double.infinity, + child: 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: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: () { + handleSubmit(); + }, + child: Row( + mainAxisSize: + MainAxisSize.min, // Ensures content fits nicely + children: [ + Text( + "Search", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + ), + ), + SizedBox(width: 8), // spacing between icon and text + Icon(Icons.search, size: 15, color: Colors.white), + ], + ), + ), + ), + ); + } } diff --git a/lib/Screens/reports/misForex.dart b/lib/Screens/reports/misForex.dart index 89990c5..9fc89b2 100644 --- a/lib/Screens/reports/misForex.dart +++ b/lib/Screens/reports/misForex.dart @@ -17,6 +17,7 @@ import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import '../../widgets/custom_text_field.dart'; class MISforex extends StatefulWidget { @@ -388,279 +389,55 @@ class _MISforexState extends State crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // ------------------- First Row ------------------- - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'MIS Forex Report', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ), - ), - Row( + // ------------------- First Row ------------------- + Container( + color: Colors.white, + child: + isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF114D8B), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: BorderSide(color: Color(0xFF114D8B), width: 2), - ), - padding: EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ), - ), - onPressed: handleDownload, - child: Row( - children: [ - Text( - "Excel", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - color: Colors.white, - ), - ), - SizedBox(width: 8), - Icon( - Icons.file_present_outlined, - size: 15, - color: Colors.white, - ), - ], - ), - ), - // SizedBox(width: 10), - // ElevatedButton( - // style: ElevatedButton.styleFrom( - // backgroundColor: Color(0xFF114D8B), - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(8), - // side: BorderSide(color: Color(0xFF114D8B), width: 2), - // ), - // padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - // ), - // onPressed: () { - // // Your PDF export logic here - // }, - // child: Row( - // children: [ - // Text( - // "PDF", - // style: GoogleFonts.poppins( - // fontSize: isDesktop ? 13 : 11, - // color: Colors.white, - // ), - // ), - // SizedBox(width: 8), - // Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white), - // ], - // ), - // ), + buildTitle(isDesktop), + Spacer(), + buildExports(isDesktop) ], - ), - ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildTitle(isDesktop), + SizedBox(height: 8), + buildExports(isDesktop) + ], + ) ), SizedBox(height: 5), // ------------------- Second Row ------------------- - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "From Date *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: focusStates["from_date"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () async { - final pickedDate = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(2000), - lastDate: DateTime(2100), - ); - if (pickedDate != null) { - textControllers["from_date"]?.text = DateFormat( - 'dd-MM-yyyy', - ).format(pickedDate); - } - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["from_date"], - controller: textControllers["from_date"], - 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: const EdgeInsets.symmetric( - vertical: 16, - ), - suffixIcon: const Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["from_date"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["from_date"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "To Date *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: focusStates["to_date"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () async { - final fromDateText = - textControllers["from_date"]?.text; - DateTime? mintoDate; - if (fromDateText != null && fromDateText.isNotEmpty) { - mintoDate = DateFormat( - 'dd-MM-yyyy', - ).parse(fromDateText); - } - - final pickedDate = await showDatePicker( - context: context, - initialDate: mintoDate ?? DateTime.now(), - firstDate: mintoDate ?? DateTime(2000), - lastDate: DateTime(2100), - ); - - if (pickedDate != null) { - textControllers["to_date"]?.text = DateFormat( - 'dd-MM-yyyy', - ).format(pickedDate); - } - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["to_date"], - controller: textControllers["to_date"], - readOnly: true, - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Select Date", - labelStyle: TextStyle( - fontSize: 12, - color: Colors.grey, - ), - floatingLabelBehavior: - FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( - vertical: 16, - ), - suffixIcon: Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["to_date"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["to_date"]!, - style: const TextStyle(color: Colors.red, fontSize: 12), - maxLines: 2, // Allow it to wrap onto two lines - overflow: - TextOverflow - .ellipsis, // Add ellipsis if it still overflows - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Padding( - padding: EdgeInsets.only(top: 10, left: 4), - child: SizedBox( - child: 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: EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ), - ), - onPressed: () { - handleSubmit(); - }, - child: Row( - mainAxisSize: - MainAxisSize.min, // Ensures content fits nicely - children: [ - Text( - "Search", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - ), - ), - SizedBox(width: 8), // spacing between icon and text - Icon(Icons.search, size: 15, color: Colors.white), - ], - ), - ), - ), - ), - ], + Container( + color: Colors.white, + child: + isDesktop + ? Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildFromDateField(isDesktop), + Spacer(), + buildToDateField(isDesktop), + Spacer(), // Space after Last Name + buildSearchButton(isDesktop), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildFromDateField(isDesktop), + SizedBox(height: 8), // Vertical space + buildToDateField(isDesktop), + SizedBox(height: 8), + buildSearchButton(isDesktop), + ], + ), ), SizedBox(height: 5), @@ -1055,4 +832,294 @@ class _MISforexState extends State ), ); } + Widget buildTitle(bool isDesktop){ + return // Left side: Breadcrumb inside a Container (optional) + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Report List', + tooltip: 'Go To Report List', + onTap: (context) { + // Navigator.pushNamed(context, '/report'); + context.go("/report"); + } + ), + BreadcrumbItem( + title: 'MIS Forex Report ', + ), + ], + ), + ); + } + Widget buildExports(bool isDesktop){ + return Row( + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF114D8B), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(color: Color(0xFF114D8B), width: 2), + ), + padding: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: handleDownload, + child: Row( + children: [ + Text( + "Excel", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + color: Colors.white, + ), + ), + SizedBox(width: 8), + Icon( + Icons.file_present_outlined, + size: 15, + color: Colors.white, + ), + ], + ), + ), + // SizedBox(width: 10), + // ElevatedButton( + // style: ElevatedButton.styleFrom( + // backgroundColor: Color(0xFF114D8B), + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(8), + // side: BorderSide(color: Color(0xFF114D8B), width: 2), + // ), + // padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + // ), + // onPressed: () { + // // Your PDF export logic here + // }, + // child: Row( + // children: [ + // Text( + // "PDF", + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 13 : 11, + // color: Colors.white, + // ), + // ), + // SizedBox(width: 8), + // Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white), + // ], + // ), + // ), + ], + ); + + } + + Widget buildFromDateField(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( "From Date *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: focusStates["from_date"] ?? false, + // isDesktop: isDesktop ? MediaQuery.of(context).size.height * 0.51 : 200, + isDesktop: isDesktop, + width: isDesktop ? null : double.infinity, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () async { + final pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2100), + ); + if (pickedDate != null) { + textControllers["from_date"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + } + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["from_date"], + controller: textControllers["from_date"], + 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: const EdgeInsets.symmetric( + vertical: 16, + ), + suffixIcon: const Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["from_date"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["from_date"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ); + } + + Widget buildToDateField(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( "To Date *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: focusStates["to_date"] ?? false, + isDesktop: isDesktop, + width: isDesktop ? null : double.infinity, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () async { + final fromDateText = + textControllers["from_date"]?.text; + DateTime? mintoDate; + if (fromDateText != null && fromDateText.isNotEmpty) { + mintoDate = DateFormat( + 'dd-MM-yyyy', + ).parse(fromDateText); + } + + final pickedDate = await showDatePicker( + context: context, + initialDate: mintoDate ?? DateTime.now(), + firstDate: mintoDate ?? DateTime(2000), + lastDate: DateTime(2100), + ); + + if (pickedDate != null) { + textControllers["to_date"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + } + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["to_date"], + controller: textControllers["to_date"], + readOnly: true, + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Select Date", + labelStyle: TextStyle( + fontSize: 12, + color: Colors.grey, + ), + floatingLabelBehavior: + FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + vertical: 16, + ), + suffixIcon: Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["to_date"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["to_date"]!, + style: const TextStyle(color: Colors.red, fontSize: 12), + maxLines: 2, // Allow it to wrap onto two lines + overflow: + TextOverflow + .ellipsis, // Add ellipsis if it still overflows + ), + ], + ], + ); + } + + Widget buildSearchButton(bool isDesktop) { + return + Padding( + padding: isDesktop + ? const EdgeInsets.only(top: 22) + : EdgeInsets.zero, + child: SizedBox( + width: isDesktop ? null : double.infinity, + child: 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: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: () { + handleSubmit(); + }, + child: Row( + mainAxisSize: + MainAxisSize.min, // Ensures content fits nicely + children: [ + Text( + "Search", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + ), + ), + SizedBox(width: 8), // spacing between icon and text + Icon(Icons.search, size: 15, color: Colors.white), + ], + ), + ), + ), + ); + } } diff --git a/lib/Screens/reports/misHotel.dart b/lib/Screens/reports/misHotel.dart index c79e60c..c11ed7f 100644 --- a/lib/Screens/reports/misHotel.dart +++ b/lib/Screens/reports/misHotel.dart @@ -17,6 +17,7 @@ import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import '../../widgets/custom_text_field.dart'; class MIShotel extends StatefulWidget { @@ -433,260 +434,55 @@ class _MIShotelState extends State crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // ------------------- First Row ------------------- - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Mis Hotel Report', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ), - ), - Row( + // ------------------- First Row ------------------- + Container( + color: Colors.white, + child: + isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF114D8B), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: BorderSide(color: Color(0xFF114D8B), width: 2), - ), - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - ), - onPressed: handleDownload, - child: Row( - children: [ - Text( - "Excel", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - color: Colors.white, - ), - ), - SizedBox(width: 8), - Icon(Icons.file_present_outlined, size: 15, color: Colors.white), - ], - ), - ), - // SizedBox(width: 10), - // ElevatedButton( - // style: ElevatedButton.styleFrom( - // backgroundColor: Color(0xFF114D8B), - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(8), - // side: BorderSide(color: Color(0xFF114D8B), width: 2), - // ), - // padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - // ), - // onPressed: () { - // // Your PDF export logic here - // }, - // child: Row( - // children: [ - // Text( - // "PDF", - // style: GoogleFonts.poppins( - // fontSize: isDesktop ? 13 : 11, - // color: Colors.white, - // ), - // ), - // SizedBox(width: 8), - // Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white), - // ], - // ), - // ), + buildTitle(isDesktop), + Spacer(), + buildExports(isDesktop) ], - ), - ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildTitle(isDesktop), + SizedBox(height: 8), + buildExports(isDesktop) + ], + ) ), SizedBox(height: 5), // ------------------- Second Row ------------------- - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "From Date *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: focusStates["from_date"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () async { - final pickedDate = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(2000), - lastDate: DateTime(2100), - ); - if (pickedDate != null) { - textControllers["from_date"]?.text = - DateFormat('dd-MM-yyyy').format(pickedDate); - } - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["from_date"], - controller: textControllers["from_date"], - 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: const EdgeInsets.symmetric(vertical: 16), - suffixIcon: const Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["from_date"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["from_date"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "To Date *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: focusStates["to_date"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () async { - final fromDateText = textControllers["from_date"]?.text; - DateTime? mintoDate; - if (fromDateText != null && fromDateText.isNotEmpty) { - mintoDate = DateFormat('dd-MM-yyyy').parse(fromDateText); - } - - final pickedDate = await showDatePicker( - context: context, - initialDate: mintoDate ?? DateTime.now(), - firstDate: mintoDate ?? DateTime(2000), - lastDate: DateTime(2100), - ); - - if (pickedDate != null) { - textControllers["to_date"]?.text = - DateFormat('dd-MM-yyyy').format(pickedDate); - } - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["to_date"], - controller: textControllers["to_date"], - readOnly: true, - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Select Date", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - suffixIcon: Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["to_date"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["to_date"]!, - style: const TextStyle(color: Colors.red, fontSize: 12), - maxLines: 2, // Allow it to wrap onto two lines - overflow: - TextOverflow.ellipsis, // Add ellipsis if it still overflows - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Padding( - padding: EdgeInsets.only(top: 10, left: 4), - child : SizedBox( - child: 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: EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ), - ), - onPressed: () {handleSubmit();}, - child: Row( - mainAxisSize: - MainAxisSize.min, // Ensures content fits nicely - children: [ - Text( - "Search", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - ), - ), - SizedBox(width: 8), // spacing between icon and text - Icon( - Icons.search, - size: 15, - color: Colors.white, - ), - ], - ), - ), - ), - ) - ], + Container( + color: Colors.white, + child: + isDesktop + ? Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildFromDateField(isDesktop), + Spacer(), + buildToDateField(isDesktop), + Spacer(), // Space after Last Name + buildSearchButton(isDesktop), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildFromDateField(isDesktop), + SizedBox(height: 8), // Vertical space + buildToDateField(isDesktop), + SizedBox(height: 8), + buildSearchButton(isDesktop), + ], + ), ), SizedBox(height: 5), @@ -1302,4 +1098,294 @@ class _MIShotelState extends State ), ); } + Widget buildTitle(bool isDesktop){ + return // Left side: Breadcrumb inside a Container (optional) + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Report List', + tooltip: 'Go To Report List', + onTap: (context) { + // Navigator.pushNamed(context, '/report'); + context.go("/report"); + } + ), + BreadcrumbItem( + title: 'MIS Hotel Report ', + ), + ], + ), + ); + } + Widget buildExports(bool isDesktop){ + return Row( + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF114D8B), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(color: Color(0xFF114D8B), width: 2), + ), + padding: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: handleDownload, + child: Row( + children: [ + Text( + "Excel", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + color: Colors.white, + ), + ), + SizedBox(width: 8), + Icon( + Icons.file_present_outlined, + size: 15, + color: Colors.white, + ), + ], + ), + ), + // SizedBox(width: 10), + // ElevatedButton( + // style: ElevatedButton.styleFrom( + // backgroundColor: Color(0xFF114D8B), + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(8), + // side: BorderSide(color: Color(0xFF114D8B), width: 2), + // ), + // padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + // ), + // onPressed: () { + // // Your PDF export logic here + // }, + // child: Row( + // children: [ + // Text( + // "PDF", + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 13 : 11, + // color: Colors.white, + // ), + // ), + // SizedBox(width: 8), + // Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white), + // ], + // ), + // ), + ], + ); + + } + + Widget buildFromDateField(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( "From Date *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: focusStates["from_date"] ?? false, + // isDesktop: isDesktop ? MediaQuery.of(context).size.height * 0.51 : 200, + isDesktop: isDesktop, + width: isDesktop ? null : double.infinity, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () async { + final pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2100), + ); + if (pickedDate != null) { + textControllers["from_date"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + } + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["from_date"], + controller: textControllers["from_date"], + 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: const EdgeInsets.symmetric( + vertical: 16, + ), + suffixIcon: const Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["from_date"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["from_date"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ); + } + + Widget buildToDateField(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( "To Date *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: focusStates["to_date"] ?? false, + isDesktop: isDesktop, + width: isDesktop ? null : double.infinity, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () async { + final fromDateText = + textControllers["from_date"]?.text; + DateTime? mintoDate; + if (fromDateText != null && fromDateText.isNotEmpty) { + mintoDate = DateFormat( + 'dd-MM-yyyy', + ).parse(fromDateText); + } + + final pickedDate = await showDatePicker( + context: context, + initialDate: mintoDate ?? DateTime.now(), + firstDate: mintoDate ?? DateTime(2000), + lastDate: DateTime(2100), + ); + + if (pickedDate != null) { + textControllers["to_date"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + } + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["to_date"], + controller: textControllers["to_date"], + readOnly: true, + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Select Date", + labelStyle: TextStyle( + fontSize: 12, + color: Colors.grey, + ), + floatingLabelBehavior: + FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + vertical: 16, + ), + suffixIcon: Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["to_date"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["to_date"]!, + style: const TextStyle(color: Colors.red, fontSize: 12), + maxLines: 2, // Allow it to wrap onto two lines + overflow: + TextOverflow + .ellipsis, // Add ellipsis if it still overflows + ), + ], + ], + ); + } + + Widget buildSearchButton(bool isDesktop) { + return + Padding( + padding: isDesktop + ? const EdgeInsets.only(top: 22) + : EdgeInsets.zero, + child: SizedBox( + width: isDesktop ? null : double.infinity, + child: 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: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: () { + handleSubmit(); + }, + child: Row( + mainAxisSize: + MainAxisSize.min, // Ensures content fits nicely + children: [ + Text( + "Search", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + ), + ), + SizedBox(width: 8), // spacing between icon and text + Icon(Icons.search, size: 15, color: Colors.white), + ], + ), + ), + ), + ); + } } \ No newline at end of file diff --git a/lib/Screens/reports/reportList.dart b/lib/Screens/reports/reportList.dart index d5c1f0b..9a5164e 100644 --- a/lib/Screens/reports/reportList.dart +++ b/lib/Screens/reports/reportList.dart @@ -139,13 +139,12 @@ class _ReportListState extends State { 'label': 'MIS Forex Report', 'description': 'View MIS Forex Report', }, - - { - 'value': '/guestHouseReport', - 'icon': Icons.home_work, - 'label': 'Guest House Report', - 'description': 'View Guest House Report', - }, + // { + // 'value': '/guestHouseReport', + // 'icon': Icons.home_work, + // 'label': 'Guest House Report', + // 'description': 'View Guest House Report', + // }, ]; return Container( @@ -178,20 +177,8 @@ class _ReportListState extends State { color: Colors.white, child: InkWell( onTap: () async { - if (item['value'] as String == - "/forexTexmplate") { - final data = - await apiService.getForexTemplate(); - print("ForexId -- $data"); - - context.go( - '/templateForex', - extra: {'templateData': data}, - ); - } else { final route = item['value'] as String; context.go(route); - } }, child: Padding( padding: EdgeInsets.all(12), diff --git a/lib/Screens/reports/servicesAnalysis.dart b/lib/Screens/reports/servicesAnalysis.dart index f55e238..6ab19b1 100644 --- a/lib/Screens/reports/servicesAnalysis.dart +++ b/lib/Screens/reports/servicesAnalysis.dart @@ -17,6 +17,7 @@ import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import '../../widgets/custom_text_field.dart'; class ServicesAnalysis extends StatefulWidget { @@ -429,252 +430,55 @@ class _ServicesAnalysisState extends State crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // ------------------- First Row ------------------- - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Service Analysis Report', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ), - ), - Row( + // ------------------- First Row ------------------- + Container( + color: Colors.white, + child: + isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF114D8B), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: BorderSide(color: Color(0xFF114D8B), width: 2), - ), - padding: EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ), - ), - onPressed: handleDownload, - child: Row( - children: [ - Text( - "Excel", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - color: Colors.white, - ), - ), - SizedBox(width: 8), - Icon( - Icons.file_present_outlined, - size: 15, - color: Colors.white, - ), - ], - ), - ), + buildTitle(isDesktop), + Spacer(), + buildExports(isDesktop) ], - ), - ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildTitle(isDesktop), + SizedBox(height: 8), + buildExports(isDesktop) + ], + ) ), SizedBox(height: 5), // ------------------- Second Row ------------------- - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "From Date *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: focusStates["from_date"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () async { - final pickedDate = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(2000), - lastDate: DateTime(2100), - ); - if (pickedDate != null) { - textControllers["from_date"]?.text = DateFormat( - 'dd-MM-yyyy', - ).format(pickedDate); - } - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["from_date"], - controller: textControllers["from_date"], - 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: const EdgeInsets.symmetric( - vertical: 16, - ), - suffixIcon: const Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["from_date"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["from_date"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "To Date *", - style: GoogleFonts.poppins( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF575A74), - ), - ), - SizedBox(height: 5), - CustomTextFieldWrapper( - isFocused: focusStates["to_date"] ?? false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: () async { - final fromDateText = - textControllers["from_date"]?.text; - DateTime? mintoDate; - if (fromDateText != null && fromDateText.isNotEmpty) { - mintoDate = DateFormat( - 'dd-MM-yyyy', - ).parse(fromDateText); - } - - final pickedDate = await showDatePicker( - context: context, - initialDate: mintoDate ?? DateTime.now(), - firstDate: mintoDate ?? DateTime(2000), - lastDate: DateTime(2100), - ); - - if (pickedDate != null) { - textControllers["to_date"]?.text = DateFormat( - 'dd-MM-yyyy', - ).format(pickedDate); - } - }, - child: AbsorbPointer( - child: TextField( - focusNode: focusNodes["to_date"], - controller: textControllers["to_date"], - readOnly: true, - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Select Date", - labelStyle: TextStyle( - fontSize: 12, - color: Colors.grey, - ), - floatingLabelBehavior: - FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( - vertical: 16, - ), - suffixIcon: Icon( - Icons.calendar_today, - size: 16, - color: Colors.grey, - ), - ), - ), - ), - ), - ), - ), - if (errorMessages["to_date"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["to_date"]!, - style: const TextStyle(color: Colors.red, fontSize: 12), - maxLines: 2, // Allow it to wrap onto two lines - overflow: - TextOverflow - .ellipsis, // Add ellipsis if it still overflows - ), - ], - ], - ), - if (isDesktop) Spacer() else SizedBox(height: 8), - Padding( - padding: EdgeInsets.only(top: 10, left: 4), - child: SizedBox( - child: 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: EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ), - ), - onPressed: () { - handleSubmit(); - }, - child: Row( - mainAxisSize: - MainAxisSize.min, // Ensures content fits nicely - children: [ - Text( - "Search", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 13 : 11, - ), - ), - SizedBox(width: 8), // spacing between icon and text - Icon(Icons.search, size: 15, color: Colors.white), - ], - ), - ), - ), - ), - ], + Container( + color: Colors.white, + child: + isDesktop + ? Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildFromDateField(isDesktop), + Spacer(), + buildToDateField(isDesktop), + Spacer(), // Space after Last Name + buildSearchButton(isDesktop), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildFromDateField(isDesktop), + SizedBox(height: 8), // Vertical space + buildToDateField(isDesktop), + SizedBox(height: 8), + buildSearchButton(isDesktop), + ], + ), ), SizedBox(height: 5), @@ -1412,4 +1216,296 @@ class _ServicesAnalysisState extends State ), ); } + + Widget buildTitle(bool isDesktop){ + return // Left side: Breadcrumb inside a Container (optional) + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Report List', + tooltip: 'Go To Report List', + onTap: (context) { + // Navigator.pushNamed(context, '/report'); + context.go("/report"); + } + ), + BreadcrumbItem( + title: 'Service Analysis Report', + ), + ], + ) + ); + } + + Widget buildExports(bool isDesktop){ + return Row( + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF114D8B), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(color: Color(0xFF114D8B), width: 2), + ), + padding: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: handleDownload, + child: Row( + children: [ + Text( + "Excel", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + color: Colors.white, + ), + ), + SizedBox(width: 8), + Icon( + Icons.file_present_outlined, + size: 15, + color: Colors.white, + ), + ], + ), + ), + // SizedBox(width: 10), + // ElevatedButton( + // style: ElevatedButton.styleFrom( + // backgroundColor: Color(0xFF114D8B), + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(8), + // side: BorderSide(color: Color(0xFF114D8B), width: 2), + // ), + // padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + // ), + // onPressed: () { + // // Your PDF export logic here + // }, + // child: Row( + // children: [ + // Text( + // "PDF", + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 13 : 11, + // color: Colors.white, + // ), + // ), + // SizedBox(width: 8), + // Icon(Icons.picture_as_pdf_outlined, size: 15, color: Colors.white), + // ], + // ), + // ), + ], + ); + + } + + Widget buildFromDateField(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( "From Date *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: focusStates["from_date"] ?? false, + isDesktop: isDesktop, + width: isDesktop ? null : double.infinity, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () async { + final pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2100), + ); + if (pickedDate != null) { + textControllers["from_date"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + } + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["from_date"], + controller: textControllers["from_date"], + 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: const EdgeInsets.symmetric( + vertical: 16, + ), + suffixIcon: const Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["from_date"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["from_date"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], + ); + } + + Widget buildToDateField(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( "To Date *", + style: GoogleFonts.poppins( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF575A74), + ), + ), + SizedBox(height: 5), + CustomTextFieldWrapper( + isFocused: focusStates["to_date"] ?? false, + isDesktop: isDesktop, + width: isDesktop ? null : double.infinity, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: () async { + final fromDateText = + textControllers["from_date"]?.text; + DateTime? mintoDate; + if (fromDateText != null && fromDateText.isNotEmpty) { + mintoDate = DateFormat( + 'dd-MM-yyyy', + ).parse(fromDateText); + } + + final pickedDate = await showDatePicker( + context: context, + initialDate: mintoDate ?? DateTime.now(), + firstDate: mintoDate ?? DateTime(2000), + lastDate: DateTime(2100), + ); + + if (pickedDate != null) { + textControllers["to_date"]?.text = DateFormat( + 'dd-MM-yyyy', + ).format(pickedDate); + } + }, + child: AbsorbPointer( + child: TextField( + focusNode: focusNodes["to_date"], + controller: textControllers["to_date"], + readOnly: true, + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Select Date", + labelStyle: TextStyle( + fontSize: 12, + color: Colors.grey, + ), + floatingLabelBehavior: + FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + vertical: 16, + ), + suffixIcon: Icon( + Icons.calendar_today, + size: 16, + color: Colors.grey, + ), + ), + ), + ), + ), + ), + ), + if (errorMessages["to_date"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["to_date"]!, + style: const TextStyle(color: Colors.red, fontSize: 12), + maxLines: 2, // Allow it to wrap onto two lines + overflow: + TextOverflow + .ellipsis, // Add ellipsis if it still overflows + ), + ], + ], + ); + } + + Widget buildSearchButton(bool isDesktop) { + return + Padding( + padding: isDesktop + ? const EdgeInsets.only(top: 22) + : EdgeInsets.zero, + child: SizedBox( + width: isDesktop ? null : double.infinity, + child: 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: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: () { + handleSubmit(); + }, + child: Row( + mainAxisSize: + MainAxisSize.min, // Ensures content fits nicely + children: [ + Text( + "Search", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + ), + ), + SizedBox(width: 8), // spacing between icon and text + Icon(Icons.search, size: 15, color: Colors.white), + ], + ), + ), + ), + ); + } + } diff --git a/lib/Screens/traveller/travellerList.dart b/lib/Screens/traveller/travellerList.dart index 911d389..8135134 100644 --- a/lib/Screens/traveller/travellerList.dart +++ b/lib/Screens/traveller/travellerList.dart @@ -14,6 +14,7 @@ import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; import '../../utils/pagination.dart'; +import '../../widgets/custom_breadcrumb_navigation.dart'; import 'travellerDetails.dart'; class TravellerList extends StatefulWidget { @@ -286,14 +287,32 @@ class TravellerListState extends State { children: [ Row( children: [ - Text( - 'Traveller Details', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, + // Left side: Breadcrumb inside a Container (optional) + Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Organization Settings', + tooltip: 'Go To Organization Settings', + onTap: (context) { + context.go("/OrganizationSettings"); + } + ), + BreadcrumbItem( + title: 'Traveller Details', + ), + ], ), ), + // Text( + // 'Traveller Details', + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + // color: Colors.black, + // ), + // ), ], ), if (isDesktop) diff --git a/lib/Screens/userManagement/create_user/create_user.dart b/lib/Screens/userManagement/create_user/create_user.dart index 6ec388b..517e8f4 100644 --- a/lib/Screens/userManagement/create_user/create_user.dart +++ b/lib/Screens/userManagement/create_user/create_user.dart @@ -26,6 +26,7 @@ import '../../../config/apiUrl.dart'; import '../../../routes/custom_appBar.dart'; import '../../../routes/custom_drawer.dart'; import '../../../services/apiService.dart'; +import '../../../widgets/custom_breadcrumb_navigation.dart'; import '../../../widgets/custom_text_field.dart'; import '../../../widgets/custom_text_forex.dart'; import '../../../widgets/custom_user_form.dart'; @@ -1349,14 +1350,39 @@ class _CreateUserFormDetialsState extends State { children: [ Row( children: [ - Text( - apiselectedUser != null ? "Profile" : "Create New User", - style: GoogleFonts.poppins( - fontSize: isDesktop ? 15 : 12, - fontWeight: FontWeight.w600, - color: Colors.black, - ), - ), + apiselectedUser != null + ? Text( "Profile", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 15 : 12, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + ) + : Container( + child: BreadcrumbNavigation( + isDesktop: isDesktop, + breadcrumbItems: [ + BreadcrumbItem( + title: 'Users', + tooltip: 'Go To Users', + onTap: (context) { + context.go("/listUser"); + } + ), + BreadcrumbItem( + title: 'Create New User', + ), + ], + ), + ), + // Text( + // apiselectedUser != null ? "Profile" : "Create New User", + // style: GoogleFonts.poppins( + // fontSize: isDesktop ? 15 : 12, + // fontWeight: FontWeight.w600, + // color: Colors.black, + // ), + // ), // if (isEditProfile) // IconButton( // icon: Icon( diff --git a/lib/widgets/custom_breadcrumb_navigation.dart b/lib/widgets/custom_breadcrumb_navigation.dart new file mode 100644 index 0000000..ac16009 --- /dev/null +++ b/lib/widgets/custom_breadcrumb_navigation.dart @@ -0,0 +1,162 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +/// Data model for a breadcrumb item. +class BreadcrumbItem { + final String title; + final void Function(BuildContext)? onTap; + final String? tooltip; + + BreadcrumbItem({ + required this.title, + this.onTap, + this.tooltip, + }); +} + +/// Breadcrumb UI widget +class BreadcrumbNavigation extends StatelessWidget { + final List breadcrumbItems; + final bool isDesktop; + + const BreadcrumbNavigation({ + super.key, + required this.breadcrumbItems, + required this.isDesktop, + }); + + @override + Widget build(BuildContext context) { + return Wrap( + crossAxisAlignment: WrapCrossAlignment.center, // Align text + arrows + children: List.generate(breadcrumbItems.length * 2 - 1, (index) { + if (index.isEven) { + final int itemIndex = index ~/ 2; + final item = breadcrumbItems[itemIndex]; + final bool isLast = itemIndex == breadcrumbItems.length - 1; + + // If last item or no tap handler, show as plain black text without tooltip/click + if (isLast || item.onTap == null) { + return Text( + item.title, + style: GoogleFonts.poppins( + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + color: Colors.black, + decoration: TextDecoration.none, + ), + ); + } else { + // If clickable, wrap with GestureDetector + Tooltip + MouseRegion + return MouseRegion( + cursor: SystemMouseCursors.click, + child: Tooltip( + message: item.tooltip ?? item.title, + child: GestureDetector( + onTap: () => item.onTap!(context), + child: Text( + item.title, + style: GoogleFonts.poppins( + // fontSize: isDesktop ? 16 : 14, + // fontWeight: FontWeight.w600, + color: Colors.black54, + decoration: TextDecoration.none, + ), + ), + ), + ), + ); + } + } else { + // Arrow between items + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 4.0), + child: Align( + alignment: Alignment.center, + child: Text( + ">", + style: TextStyle( + color: Colors.black54, + fontSize: isDesktop ? 16 : 14, + height: 1.2, + ), + ), + ), + ); + } + }), + ); + } +} + +// import 'package:flutter/material.dart'; +// import 'package:google_fonts/google_fonts.dart'; +// +// class BreadcrumbItem { +// final String title; +// final void Function(BuildContext)? onTap; +// final String? tooltip; +// +// BreadcrumbItem({ +// required this.title, +// this.onTap, +// this.tooltip, +// }); +// } +// +// class BreadcrumbNavigation extends StatelessWidget { +// final List breadcrumbItems; +// final bool isDesktop; +// +// const BreadcrumbNavigation({ +// super.key, +// required this.breadcrumbItems, +// required this.isDesktop, +// }); +// +// @override +// Widget build(BuildContext context) { +// return Wrap( +// crossAxisAlignment: WrapCrossAlignment.center, // Ensures vertical alignment +// children: List.generate(breadcrumbItems.length * 2 - 1, (index) { +// if (index.isEven) { +// final int itemIndex = index ~/ 2; +// final item = breadcrumbItems[itemIndex]; +// final bool isLast = itemIndex == breadcrumbItems.length - 1; +// +// return Tooltip( +// message: item.tooltip ?? item.title, +// child: GestureDetector( +// onTap: isLast || item.onTap == null +// ? null +// : () => item.onTap!(context), // pass context +// child: Text( item.title, +// style: GoogleFonts.poppins( +// fontSize: isDesktop ? 16 : 14, +// fontWeight: FontWeight.w600, +// color: isLast ? Colors.black : Colors.black54, +// decoration: TextDecoration.none, +// ), +// ), +// ), +// ); +// } else { +// // Arrow between items, centered vertically +// return Padding( +// padding: const EdgeInsets.symmetric(horizontal: 4.0), +// child: Align( +// alignment: Alignment.center, +// child: Text(" > ", +// style: TextStyle( +// color: Colors.black54, +// fontSize: isDesktop ? 16 : 14, +// height: 1.2, // Aligns better with text +// ), +// ), +// ), +// ); +// } +// }), +// ); +// } +// } \ No newline at end of file From 6169e8b1a2fc7f2931861288d9cbb276bfb9bdc6 Mon Sep 17 00:00:00 2001 From: venba-Inspriron-3558 Date: Thu, 19 Jun 2025 17:17:51 +0530 Subject: [PATCH 2/2] report completed 5 --- lib/Screens/reports/advancePurchase.dart | 3 +++ lib/Screens/reports/guestHouse.dart | 1 + lib/Screens/reports/misAir.dart | 2 ++ lib/Screens/reports/misForex.dart | 4 +++- lib/Screens/reports/misHotel.dart | 3 ++- lib/Screens/reports/servicesAnalysis.dart | 2 ++ 6 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/Screens/reports/advancePurchase.dart b/lib/Screens/reports/advancePurchase.dart index d72a529..4bfd681 100644 --- a/lib/Screens/reports/advancePurchase.dart +++ b/lib/Screens/reports/advancePurchase.dart @@ -1504,6 +1504,7 @@ class _AdvancePurchaseState extends State initialDate: DateTime.now(), firstDate: DateTime(2000), lastDate: DateTime(2100), + initialEntryMode: DatePickerEntryMode.calendarOnly, ); if (pickedDate != null) { textControllers["from_date"]?.text = DateFormat( @@ -1551,6 +1552,7 @@ class _AdvancePurchaseState extends State ); } + Widget buildToDateField(bool isDesktop) { return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -1583,6 +1585,7 @@ class _AdvancePurchaseState extends State final pickedDate = await showDatePicker( context: context, initialDate: mintoDate ?? DateTime.now(), + initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: mintoDate ?? DateTime(2000), lastDate: DateTime(2100), ); diff --git a/lib/Screens/reports/guestHouse.dart b/lib/Screens/reports/guestHouse.dart index 5993c1a..f13cd19 100644 --- a/lib/Screens/reports/guestHouse.dart +++ b/lib/Screens/reports/guestHouse.dart @@ -1636,6 +1636,7 @@ class _GuestHouseState extends State context: context, initialDate: DateTime.now(), firstDate: DateTime(2000), + initialEntryMode: DatePickerEntryMode.calendarOnly, lastDate: DateTime(2100), ); if (pickedDate != null) { diff --git a/lib/Screens/reports/misAir.dart b/lib/Screens/reports/misAir.dart index c9cb274..ef6c403 100644 --- a/lib/Screens/reports/misAir.dart +++ b/lib/Screens/reports/misAir.dart @@ -1621,6 +1621,7 @@ class _MISairState extends State with SingleTickerProviderStateMixin { final pickedDate = await showDatePicker( context: context, initialDate: DateTime.now(), + initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(2000), lastDate: DateTime(2100), ); @@ -1703,6 +1704,7 @@ class _MISairState extends State with SingleTickerProviderStateMixin { context: context, initialDate: mintoDate ?? DateTime.now(), firstDate: mintoDate ?? DateTime(2000), + initialEntryMode: DatePickerEntryMode.calendarOnly, lastDate: DateTime(2100), ); diff --git a/lib/Screens/reports/misForex.dart b/lib/Screens/reports/misForex.dart index 9fc89b2..09c3b83 100644 --- a/lib/Screens/reports/misForex.dart +++ b/lib/Screens/reports/misForex.dart @@ -943,6 +943,7 @@ class _MISforexState extends State final pickedDate = await showDatePicker( context: context, initialDate: DateTime.now(), + initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(2000), lastDate: DateTime(2100), ); @@ -1023,7 +1024,8 @@ class _MISforexState extends State final pickedDate = await showDatePicker( context: context, - initialDate: mintoDate ?? DateTime.now(), + initialDate: DateTime.now(), + initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: mintoDate ?? DateTime(2000), lastDate: DateTime(2100), ); diff --git a/lib/Screens/reports/misHotel.dart b/lib/Screens/reports/misHotel.dart index c11ed7f..b47891f 100644 --- a/lib/Screens/reports/misHotel.dart +++ b/lib/Screens/reports/misHotel.dart @@ -433,7 +433,6 @@ class _MIShotelState extends State child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - // ------------------- First Row ------------------- // ------------------- First Row ------------------- Container( color: Colors.white, @@ -1209,6 +1208,7 @@ class _MIShotelState extends State final pickedDate = await showDatePicker( context: context, initialDate: DateTime.now(), + initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(2000), lastDate: DateTime(2100), ); @@ -1290,6 +1290,7 @@ class _MIShotelState extends State final pickedDate = await showDatePicker( context: context, initialDate: mintoDate ?? DateTime.now(), + initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: mintoDate ?? DateTime(2000), lastDate: DateTime(2100), ); diff --git a/lib/Screens/reports/servicesAnalysis.dart b/lib/Screens/reports/servicesAnalysis.dart index 6ab19b1..057894e 100644 --- a/lib/Screens/reports/servicesAnalysis.dart +++ b/lib/Screens/reports/servicesAnalysis.dart @@ -1328,6 +1328,7 @@ class _ServicesAnalysisState extends State final pickedDate = await showDatePicker( context: context, initialDate: DateTime.now(), + initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(2000), lastDate: DateTime(2100), ); @@ -1409,6 +1410,7 @@ class _ServicesAnalysisState extends State final pickedDate = await showDatePicker( context: context, initialDate: mintoDate ?? DateTime.now(), + initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: mintoDate ?? DateTime(2000), lastDate: DateTime(2100), );