Merge branch 'main' of bitbucket.org:venbainformationtechnology/ts-tat

This commit is contained in:
venbaittech 2025-06-19 17:20:09 +05:30
commit 29eedb3162
18 changed files with 2447 additions and 1604 deletions

View File

@ -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<CostCenterList> {
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)

View File

@ -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<DepartmentList> {
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)

View File

@ -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<ForexDataList> {
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)

View File

@ -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<GroupList> {
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)

View File

@ -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<HotelsDataList> {
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)

View File

@ -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<TemplateForex> {
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(

View File

@ -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<OrgSetUp> {
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,
// ),
// ),
],
),
),

View File

@ -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<PolicyList> {
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)

View File

@ -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<AdvancePurchase>
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,300 @@ class _AdvancePurchaseState extends State<AdvancePurchase>
),
);
}
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),
initialEntryMode: DatePickerEntryMode.calendarOnly,
);
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(),
initialEntryMode: DatePickerEntryMode.calendarOnly,
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),
],
),
),
),
);
}
}

View File

@ -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<GuestHouse>
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,297 @@ class _GuestHouseState extends State<GuestHouse>
),
);
}
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),
initialEntryMode: DatePickerEntryMode.calendarOnly,
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),
],
),
),
),
);
}
}

View File

@ -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<MISair> 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,296 @@ class _MISairState extends State<MISair> 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(),
initialEntryMode: DatePickerEntryMode.calendarOnly,
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),
initialEntryMode: DatePickerEntryMode.calendarOnly,
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),
],
),
),
),
);
}
}

View File

@ -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<MISforex>
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,296 @@ class _MISforexState extends State<MISforex>
),
);
}
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(),
initialEntryMode: DatePickerEntryMode.calendarOnly,
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: DateTime.now(),
initialEntryMode: DatePickerEntryMode.calendarOnly,
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),
],
),
),
),
);
}
}

View File

@ -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,54 @@ class _MIShotelState extends State<MIShotel>
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(
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 +1097,296 @@ class _MIShotelState extends State<MIShotel>
),
);
}
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(),
initialEntryMode: DatePickerEntryMode.calendarOnly,
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(),
initialEntryMode: DatePickerEntryMode.calendarOnly,
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),
],
),
),
),
);
}
}

View File

@ -139,13 +139,12 @@ class _ReportListState extends State<ReportList> {
'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<ReportList> {
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),

View File

@ -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<ServicesAnalysis>
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,298 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
),
);
}
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(),
initialEntryMode: DatePickerEntryMode.calendarOnly,
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(),
initialEntryMode: DatePickerEntryMode.calendarOnly,
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),
],
),
),
),
);
}
}

View File

@ -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<TravellerList> {
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)

View File

@ -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<CreateUserFormDetials> {
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(

View File

@ -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<BreadcrumbItem> 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<BreadcrumbItem> 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
// ),
// ),
// ),
// );
// }
// }),
// );
// }
// }