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

This commit is contained in:
venba-Inspriron-3558 2025-08-04 18:11:44 +05:30
commit 2dee35c37c
32 changed files with 11526 additions and 9797 deletions

View File

@ -505,7 +505,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
margin: isDesktop ? EdgeInsets.all(10.0) : null, margin: isDesktop ? EdgeInsets.all(10.0) : null,
padding: padding:
isDesktop isDesktop
? const EdgeInsets.only(top: 15, bottom: 15, left: 20, right: 20) ? const EdgeInsets.only(top: 5, bottom: 5, left: 20, right: 20)
: EdgeInsets.all(3.0), : EdgeInsets.all(3.0),
height: height:
isDesktop isDesktop
@ -526,7 +526,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
// color: Colors.amber, // color: Colors.amber,
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.all(1.0), padding: const EdgeInsets.only(top: 15, bottom: 15, left: 5, right: 5),
child: Container( child: Container(
// padding: const EdgeInsets.all(10.0), // padding: const EdgeInsets.all(10.0),
color: isDesktop ? Colors.white : Color(0xFFFCFCFC), color: isDesktop ? Colors.white : Color(0xFFFCFCFC),
@ -540,7 +540,12 @@ class _ListAllPlansState extends State<ListAllPlans> {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Padding(
padding:
isDesktop
? const EdgeInsets.all(0)
: const EdgeInsets.only(left: 14.0),
child: Row(
children: [ children: [
Text( Text(
'All Trips', 'All Trips',
@ -558,6 +563,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
), ),
], ],
), ),
),
SizedBox(width: 1), SizedBox(width: 1),
Spacer(), Spacer(),
@ -802,8 +808,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
child: child: ConstrainedBox(
ConstrainedBox(
constraints: BoxConstraints(minWidth: minWidth), constraints: BoxConstraints(minWidth: minWidth),
child: DataTable( child: DataTable(
dividerThickness: 0.5, dividerThickness: 0.5,
@ -835,7 +840,9 @@ class _ListAllPlansState extends State<ListAllPlans> {
), ),
), ),
DataColumn( DataColumn(
label: Text( label: Expanded(
flex: 1,
child: Text(
'Trip Name', 'Trip Name',
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 13, fontSize: 13,
@ -843,6 +850,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
), ),
), ),
), ),
),
DataColumn( DataColumn(
label: Text( label: Text(
@ -905,6 +913,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
paginatedPlans.asMap().entries.map((entry) { paginatedPlans.asMap().entries.map((entry) {
int index = entry.key; int index = entry.key;
var plan = entry.value; var plan = entry.value;
print("fordIf - ${plan.forexId}");
return DataRow( return DataRow(
cells: [ cells: [
DataCell( DataCell(
@ -927,14 +936,19 @@ class _ListAllPlansState extends State<ListAllPlans> {
), ),
), ),
DataCell( DataCell(
Text( SizedBox(
width: 130,
child: Text(
plan.tripTitle, plan.tripTitle,
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
fontFamily: "Inter", fontFamily: "Inter",
), ),
softWrap: true, softWrap: true,
overflow: TextOverflow.ellipsis, maxLines: 2,
// overflow: TextOverflow.ellipsis,
),
), ),
), ),
DataCell( DataCell(
@ -979,7 +993,8 @@ class _ListAllPlansState extends State<ListAllPlans> {
), ),
DataCell( DataCell(
GestureDetector( GestureDetector(
onTap: () => _showDetails(plan.planId), onTap:
() => _showDetails(plan.planId),
child: Container( child: Container(
width: width:
double double
@ -990,9 +1005,8 @@ class _ListAllPlansState extends State<ListAllPlans> {
color: getStatusColor( color: getStatusColor(
plan.statusValue, plan.statusValue,
), ),
borderRadius: BorderRadius.circular( borderRadius:
10, BorderRadius.circular(10),
),
), ),
child: Text( child: Text(
plan.statusValue, plan.statusValue,
@ -1032,7 +1046,8 @@ class _ListAllPlansState extends State<ListAllPlans> {
), ),
child: Row( child: Row(
mainAxisSize: mainAxisSize:
MainAxisSize.min, MainAxisSize
.min,
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment MainAxisAlignment
.center, .center,
@ -1103,9 +1118,10 @@ class _ListAllPlansState extends State<ListAllPlans> {
), ),
IconButton( IconButton(
icon: Icon( icon: Icon(
Icons.download, Icons
.download,
color: Color( color: Color(
0xFF114D8B, 0xFF475569,
), ),
size: 18, size: 18,
), ),
@ -1121,6 +1137,33 @@ class _ListAllPlansState extends State<ListAllPlans> {
); );
}, },
), ),
if (plan.statusValue ==
"Approved" &&
plan.forexId !=
null &&
plan.forexId !=
'')
IconButton(
icon: Icon(
Icons
.monetization_on_outlined,
color: Color(
0xFF475569,
),
size: 18,
),
tooltip:
'Download Forex PDF',
onPressed: () {
Navigator.pop(
context,
);
apiService
.getForexPdfDownload(
plan.forexId,
);
},
),
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons.comment, Icons.comment,
@ -1141,8 +1184,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
) => CommentModalList( ) => CommentModalList(
// planId: plan.planId, // planId: plan.planId,
planId: planId:
plan.planId plan.planId.toString(),
.toString(),
layoutColorForUser: layoutColorForUser:
layoutColor!, layoutColor!,
role: role:
@ -1165,7 +1207,8 @@ class _ListAllPlansState extends State<ListAllPlans> {
}).toList(), }).toList(),
), ),
), ),
)); ),
);
}, },
); );
@ -1369,7 +1412,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
Icons Icons
.download, .download,
color: Color( color: Color(
0xFF114D8B, 0xFF475569,
), ),
size: 18, size: 18,
), ),
@ -1385,6 +1428,35 @@ class _ListAllPlansState extends State<ListAllPlans> {
); );
}, },
), ),
if (plan.statusValue ==
"Approved" &&
plan.forexId !=
null &&
plan.forexId !=
'')
IconButton(
icon: Icon(
Icons
.monetization_on_outlined,
color: Color(
0xFF475569,
),
size: 18,
),
tooltip:
'Download Forex PDF',
onPressed: () {
Navigator.pop(
context,
);
apiService
.getForexPdfDownload(
plan.forexId,
);
},
),
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons Icons
@ -1433,7 +1505,8 @@ class _ListAllPlansState extends State<ListAllPlans> {
CrossAxisAlignment.end, CrossAxisAlignment.end,
children: [ children: [
Flexible( child:Column( Flexible(
child: Column(
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.start, CrossAxisAlignment.start,
children: [ children: [
@ -1469,7 +1542,8 @@ class _ListAllPlansState extends State<ListAllPlans> {
), ),
), ),
], ],
),), ),
),
Column( Column(
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.end, MainAxisAlignment.end,

View File

@ -373,7 +373,15 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
// color: Colors.amber, // color: Colors.amber,
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.all(1.0), padding:
isDesktop
? const EdgeInsets.only(
top: 15,
bottom: 15,
left: 20,
right: 20,
)
: const EdgeInsets.only(top: 15, bottom: 15, left: 5, right: 5),
child: Container( child: Container(
// padding: const EdgeInsets.all(10.0), // padding: const EdgeInsets.all(10.0),
color: isDesktop ? Colors.white : Color(0xFFFCFCFC), color: isDesktop ? Colors.white : Color(0xFFFCFCFC),
@ -387,7 +395,12 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Padding(
padding:
isDesktop
? const EdgeInsets.all(0)
: const EdgeInsets.only(left: 14.0),
child: Row(
children: [ children: [
Text( Text(
'Trips', 'Trips',
@ -404,6 +417,7 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
), ),
], ],
), ),
),
Spacer(), Spacer(),
if (isDesktop) if (isDesktop)
@ -447,7 +461,7 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
), ),
// SizedBox(width: 16), // SizedBox(width: 16),
Spacer(), // Spacer(),
// ElevatedButton( // ElevatedButton(
// style: ElevatedButton.styleFrom( // style: ElevatedButton.styleFrom(
// foregroundColor: Colors.white, // foregroundColor: Colors.white,
@ -473,6 +487,7 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
if (!isDesktop) const SizedBox(height: 10), if (!isDesktop) const SizedBox(height: 10),
if (!isDesktop) if (!isDesktop)
Row( Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Container( Container(
width: MediaQuery.of(context).size.width * 0.85, width: MediaQuery.of(context).size.width * 0.85,
@ -694,14 +709,18 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
), ),
DataCell( DataCell(
Text( SizedBox(
width: 130,
child: Text(
plan.tripTitle, plan.tripTitle,
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
fontFamily: "Inter", fontFamily: "Inter",
), ),
softWrap: true, softWrap: true,
overflow: TextOverflow.ellipsis, maxLines: 2,
// overflow: TextOverflow.ellipsis,
),
), ),
), ),
@ -870,6 +889,34 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
); );
}, },
), ),
if (plan.statusValue ==
"Approved" &&
plan.forexId !=
null &&
plan.forexId !=
'')
IconButton(
icon: Icon(
Icons
.monetization_on_outlined,
color: Color(
0xFF475569,
),
size: 18,
),
tooltip:
'Download Forex PDF',
onPressed: () {
Navigator.pop(
context,
);
apiService
.getForexPdfDownload(
plan.forexId,
);
},
),
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons.comment, Icons.comment,
@ -1003,6 +1050,7 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
PlanPopupMenu( PlanPopupMenu(
plan: plan, plan: plan,
deletePlan: deletePlan, deletePlan: deletePlan,
apiService: apiService, apiService: apiService,
layoutColor: layoutColor, layoutColor: layoutColor,
), ),

View File

@ -722,7 +722,7 @@ class _ApprovalListState extends State<ApprovalList> {
padding: padding:
isDesktop isDesktop
? const EdgeInsets.only(top: 15, bottom: 15, left: 20, right: 20) ? const EdgeInsets.only(top: 15, bottom: 15, left: 20, right: 20)
: EdgeInsets.all(3.0), : const EdgeInsets.only(top: 15, bottom: 15, left: 5, right: 5),
height: height:
isDesktop isDesktop
? MediaQuery.of(context).size.height * 0.98 ? MediaQuery.of(context).size.height * 0.98
@ -755,7 +755,12 @@ class _ApprovalListState extends State<ApprovalList> {
// ), // ),
Row( Row(
children: [ children: [
Row( Padding(
padding:
isDesktop
? const EdgeInsets.all(0)
: const EdgeInsets.only(left: 14.0),
child: Row(
children: [ children: [
Text( Text(
'My Approvals', 'My Approvals',
@ -772,6 +777,7 @@ class _ApprovalListState extends State<ApprovalList> {
), ),
], ],
), ),
),
if (isDesktop) if (isDesktop)
SizedBox(width: MediaQuery.of(context).size.width * 0.23), SizedBox(width: MediaQuery.of(context).size.width * 0.23),
@ -818,14 +824,14 @@ class _ApprovalListState extends State<ApprovalList> {
], ],
), ),
if (!isDesktop) SizedBox(height: 5), if (!isDesktop) SizedBox(height: 10),
isDesktop isDesktop
? SizedBox.shrink() ? SizedBox.shrink()
: Row( : Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Container( Container(
width: MediaQuery.of(context).size.width * 0.82, width: MediaQuery.of(context).size.width * 0.85,
height: 35, height: 35,
child: TextField( child: TextField(
controller: searchController, controller: searchController,
@ -935,8 +941,7 @@ class _ApprovalListState extends State<ApprovalList> {
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
child: child: ConstrainedBox(
ConstrainedBox(
constraints: BoxConstraints(minWidth: minWidth), constraints: BoxConstraints(minWidth: minWidth),
child: DataTable( child: DataTable(
dividerThickness: 0.5, dividerThickness: 0.5,
@ -1045,14 +1050,18 @@ class _ApprovalListState extends State<ApprovalList> {
), ),
DataCell( DataCell(
Text( SizedBox(
width: 130,
child: Text(
plan.tripTitle, plan.tripTitle,
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
fontFamily: "Inter", fontFamily: "Inter",
), ),
softWrap: true, softWrap: true,
overflow: TextOverflow.ellipsis, maxLines: 2,
// overflow: TextOverflow.ellipsis,
),
), ),
), ),
DataCell( DataCell(
@ -1172,7 +1181,8 @@ class _ApprovalListState extends State<ApprovalList> {
// ), // ),
DataCell( DataCell(
GestureDetector( GestureDetector(
onTap: () => _showDetails(plan.planId), onTap:
() => _showDetails(plan.planId),
child: Container( child: Container(
width: double.infinity, width: double.infinity,
height: 25, height: 25,
@ -1181,9 +1191,8 @@ class _ApprovalListState extends State<ApprovalList> {
color: getStatusColor( color: getStatusColor(
plan.statusValue, plan.statusValue,
), ),
borderRadius: BorderRadius.circular( borderRadius:
8, BorderRadius.circular(8),
),
), ),
child: Text( child: Text(
plan.statusValue, plan.statusValue,
@ -1223,7 +1232,8 @@ class _ApprovalListState extends State<ApprovalList> {
), ),
child: Row( child: Row(
mainAxisSize: mainAxisSize:
MainAxisSize.min, MainAxisSize
.min,
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment MainAxisAlignment
.center, .center,
@ -1311,9 +1321,10 @@ class _ApprovalListState extends State<ApprovalList> {
), ),
IconButton( IconButton(
icon: Icon( icon: Icon(
Icons.download, Icons
.download,
color: Color( color: Color(
0xFF114D8B, 0xFF475569,
), ),
size: 18, size: 18,
), ),
@ -1329,6 +1340,34 @@ class _ApprovalListState extends State<ApprovalList> {
); );
}, },
), ),
if (plan.statusValue ==
"Approved" &&
plan.forexId !=
null &&
plan.forexId !=
'')
IconButton(
icon: Icon(
Icons
.monetization_on_outlined,
color: Color(
0xFF475569,
),
size: 18,
),
tooltip:
'Download Forex PDF',
onPressed: () {
Navigator.pop(
context,
);
apiService
.getForexPdfDownload(
plan.forexId,
);
},
),
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons.comment, Icons.comment,
@ -1349,8 +1388,7 @@ class _ApprovalListState extends State<ApprovalList> {
) => CommentModalList( ) => CommentModalList(
// planId: plan.planId, // planId: plan.planId,
planId: planId:
plan.planId plan.planId.toString(),
.toString(),
layoutColorForUser: layoutColorForUser:
layoutColor!, layoutColor!,
role: role:
@ -1421,7 +1459,9 @@ class _ApprovalListState extends State<ApprovalList> {
); );
}).toList(), }).toList(),
), ),
))); ),
),
);
}, },
); );
@ -1469,7 +1509,11 @@ class _ApprovalListState extends State<ApprovalList> {
? 'assets/images/IconsImg/Domestic_new.png' ? 'assets/images/IconsImg/Domestic_new.png'
: 'assets/images/IconsImg/International_new.png', : 'assets/images/IconsImg/International_new.png',
// width: 65, // width: 65,
height: plan.tripType == 'Domestic' ? 28 : 30, height:
plan.tripType ==
'Domestic'
? 28
: 30,
), ),
], ],
), ),
@ -1549,8 +1593,10 @@ class _ApprovalListState extends State<ApprovalList> {
plan.planId, plan.planId,
plan.approverId, plan.approverId,
plan.delegaterId, plan.delegaterId,
isViewMode:true, isViewMode:
isApprover:true, true,
isApprover:
true,
); );
}, },
), ),
@ -1575,8 +1621,10 @@ class _ApprovalListState extends State<ApprovalList> {
plan.planId, plan.planId,
plan.approverId, plan.approverId,
plan.delegaterId, plan.delegaterId,
isViewMode: true, isViewMode:
isApprover: true, true,
isApprover:
true,
); );
}, },
), ),
@ -1585,26 +1633,7 @@ class _ApprovalListState extends State<ApprovalList> {
Icons Icons
.download, .download,
color: Color( color: Color(
0xFF114D8B, 0xFF475569,
),
size: 18,
),
tooltip:
'Download The PDF',
onPressed: () {
Navigator.pop(context);
apiService
.getPdfDownload(
plan.planId,
);
},
),
IconButton(
icon: Icon(
Icons
.download,
color: Color(
0xFF114D8B,
), ),
size: 18, size: 18,
), ),
@ -1620,6 +1649,33 @@ class _ApprovalListState extends State<ApprovalList> {
); );
}, },
), ),
if (plan.statusValue ==
"Approved" &&
plan.forexId !=
null &&
plan.forexId !=
'')
IconButton(
icon: Icon(
Icons
.monetization_on_outlined,
color: Color(
0xFF475569,
),
size: 18,
),
tooltip:
'Download Forex PDF',
onPressed: () {
Navigator.pop(
context,
);
apiService
.getForexPdfDownload(
plan.forexId,
);
},
),
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons Icons
@ -1633,15 +1689,15 @@ class _ApprovalListState extends State<ApprovalList> {
'Trip Comments', 'Trip Comments',
onPressed: () { onPressed: () {
showDialog( showDialog(
context: context, context:
context,
builder: builder:
( (
context, context,
) => CommentModalList( ) => CommentModalList(
// planId: plan.planId, // planId: plan.planId,
planId: planId:
plan.planId plan.planId.toString(),
.toString(),
layoutColorForUser: layoutColorForUser:
layoutColor!, layoutColor!,
role: role:
@ -1668,7 +1724,8 @@ class _ApprovalListState extends State<ApprovalList> {
CrossAxisAlignment.end, CrossAxisAlignment.end,
children: [ children: [
Flexible( child:Column( Flexible(
child: Column(
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.start, CrossAxisAlignment.start,
children: [ children: [
@ -1689,7 +1746,8 @@ class _ApprovalListState extends State<ApprovalList> {
), ),
), ),
], ],
),), ),
),
Column( Column(
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.end, MainAxisAlignment.end,

View File

@ -52,7 +52,7 @@ class StatusDashboardState extends State<StatusDashboard> {
"Partially Approved", "Partially Approved",
"Approved", "Approved",
"Rejected", "Rejected",
"Cancelled" "Cancelled",
]; ];
// Extract counts for "Both" section // Extract counts for "Both" section
@ -151,7 +151,6 @@ class StatusDashboardState extends State<StatusDashboard> {
}); });
setState(() { setState(() {
isLoading = true; isLoading = true;
}); });
// If token exists, load the dashboard data // If token exists, load the dashboard data
loadDashboardData(); loadDashboardData();
@ -320,25 +319,27 @@ class StatusDashboardState extends State<StatusDashboard> {
setState(() { setState(() {
// currentData = selectedView == "Today" ? todayBasedCount : weekBasedCount; // currentData = selectedView == "Today" ? todayBasedCount : weekBasedCount;
typeData = selectedView == "Today" typeData =
? typeBasedTodayCount selectedView == "Today" ? typeBasedTodayCount : typeBasedWeeklyCount;
: typeBasedWeeklyCount ; statusData =
statusData = selectedView == "Today" selectedView == "Today"
? statusBasedTodayCount ? statusBasedTodayCount
: statusBasedWeeklyCount; : statusBasedWeeklyCount;
flightData = selectedView == "Today" flightData =
selectedView == "Today"
? getStatusValues(todayBasedCount['flight'] ?? {}) ? getStatusValues(todayBasedCount['flight'] ?? {})
: getStatusValues(weekBasedCount['flight'] ?? {}); : getStatusValues(weekBasedCount['flight'] ?? {});
accommodationData = selectedView == "Today" accommodationData =
selectedView == "Today"
? getStatusValues(todayBasedCount['acomodation'] ?? {}) ? getStatusValues(todayBasedCount['acomodation'] ?? {})
: getStatusValues(weekBasedCount['acomodation'] ?? {}); : getStatusValues(weekBasedCount['acomodation'] ?? {});
forexData = selectedView == "Today" forexData =
selectedView == "Today"
? getStatusValues(todayBasedCount['forex'] ?? {}) ? getStatusValues(todayBasedCount['forex'] ?? {})
: getStatusValues(weekBasedCount['forex'] ?? {}); : getStatusValues(weekBasedCount['forex'] ?? {});
}); });
print("statusBasedCount - => $statusBasedCount"); print("statusBasedCount - => $statusBasedCount");
print("Current Data - => $currentData"); print("Current Data - => $currentData");
// 👇 Local function to create the card widget // 👇 Local function to create the card widget
@ -403,6 +404,7 @@ class StatusDashboardState extends State<StatusDashboard> {
print("dashboard .."); print("dashboard ..");
} }
} }
String capitalize(String s) => s[0].toUpperCase() + s.substring(1); String capitalize(String s) => s[0].toUpperCase() + s.substring(1);
Widget toggleChip(String label) { Widget toggleChip(String label) {
@ -478,10 +480,10 @@ class StatusDashboardState extends State<StatusDashboard> {
child: Text( child: Text(
label, label,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 10, fontSize: 12,
color: color, color: color,
// color: const Color(0xFFEAF3FB), // color: const Color(0xFFEAF3FB),
fontWeight: FontWeight.w700, fontWeight: FontWeight.w500,
), ),
), ),
), ),
@ -542,7 +544,8 @@ class StatusDashboardState extends State<StatusDashboard> {
color: const Color(0xFFEAF3FB), color: const Color(0xFFEAF3FB),
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: isDesktop child:
isDesktop
? Column( ? Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
@ -594,9 +597,12 @@ class StatusDashboardState extends State<StatusDashboard> {
); );
} }
Widget buildCategoryCard(
Widget buildCategoryCard(String title, IconData icon, List<String> statusLabels,List<int> values) { String title,
IconData icon,
List<String> statusLabels,
List<int> values,
) {
final statusIcons = [ final statusIcons = [
Icons.calendar_today, Icons.calendar_today,
Icons.assignment, Icons.assignment,
@ -650,17 +656,16 @@ class StatusDashboardState extends State<StatusDashboard> {
color: Color(0xFF004A8E), color: Color(0xFF004A8E),
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
child: Icon( child: Icon(icon, color: Colors.white, size: 20),
icon,
color: Colors.white,
size: 20,
),
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Text(title, style: GoogleFonts.poppins( Text(
title,
style: GoogleFonts.poppins(
color: Colors.black87, color: Colors.black87,
fontWeight: FontWeight.bold fontWeight: FontWeight.bold,
),), ),
),
], ],
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
@ -678,7 +683,9 @@ class StatusDashboardState extends State<StatusDashboard> {
height: 28, height: 28,
decoration: BoxDecoration( decoration: BoxDecoration(
color: statusColors[index], // background color color: statusColors[index], // background color
borderRadius: BorderRadius.circular(4), // square with slight rounding borderRadius: BorderRadius.circular(
4,
), // square with slight rounding
), ),
alignment: Alignment.center, alignment: Alignment.center,
child: Icon( child: Icon(
@ -688,16 +695,20 @@ class StatusDashboardState extends State<StatusDashboard> {
), ),
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
Text(statusLabels[index], style: GoogleFonts.poppins( Text(
color: Colors.black87, statusLabels[index],
),), style: GoogleFonts.poppins(color: Colors.black87),
),
], ],
), ),
Text(values[index].toString(), style: GoogleFonts.poppins( Text(
values[index].toString(),
style: GoogleFonts.poppins(
fontSize: 10, fontSize: 10,
color: Colors.black87, color: Colors.black87,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
),), ),
),
], ],
), ),
); );
@ -802,35 +813,41 @@ class StatusDashboardState extends State<StatusDashboard> {
appBar: CustomAppBar(isDesktop: isDesktop), appBar: CustomAppBar(isDesktop: isDesktop),
drawer: CustomDrawer(isDesktop: false), drawer: CustomDrawer(isDesktop: false),
body: Padding( body: Padding(
padding: isDesktop padding:
isDesktop
? const EdgeInsets.symmetric(vertical: 5) ? const EdgeInsets.symmetric(vertical: 5)
: EdgeInsets.zero, : EdgeInsets.zero,
child: Center( child: Center(
child: ConstrainedBox( child: ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(maxWidth: 1200),
maxWidth: 1200,
),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0), // Scroll content padding padding: const EdgeInsets.symmetric(
horizontal: 15.0,
), // Scroll content padding
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
isLoading ? Center(child: CircularProgressIndicator()) : isLoading
LayoutBuilder( ? Center(child: CircularProgressIndicator())
: LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment:
CrossAxisAlignment.start,
children: [ children: [
const SizedBox(height: 10),
// First Row: Toggle Buttons Row // First Row: Toggle Buttons Row
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment:
MainAxisAlignment.end,
children: [ children: [
Container( Container(
height: 36, height: 36,
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFEAEAEA), color: const Color(0xFFEAEAEA),
borderRadius: BorderRadius.circular(20), borderRadius:
BorderRadius.circular(20),
), ),
child: Row( child: Row(
children: [ children: [
@ -846,15 +863,20 @@ class StatusDashboardState extends State<StatusDashboard> {
// Second Row: Domestic & International and Status // Second Row: Domestic & International and Status
isDesktop isDesktop
? Row( ? Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment:
mainAxisAlignment: MainAxisAlignment.spaceBetween, CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [ children: [
Expanded( Expanded(
flex: 2, flex: 2,
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(12), borderRadius:
BorderRadius.circular(
12,
),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.blueGrey, color: Colors.blueGrey,
@ -863,7 +885,9 @@ class StatusDashboardState extends State<StatusDashboard> {
), ),
], ],
), ),
padding: const EdgeInsets.all(15), padding: const EdgeInsets.all(
15,
),
child: Row( child: Row(
children: [ children: [
...typeData.map((item) { ...typeData.map((item) {
@ -871,14 +895,28 @@ class StatusDashboardState extends State<StatusDashboard> {
child: Column( child: Column(
children: [ children: [
buildTopCard( buildTopCard(
color: item['value'] == "Domestic" color:
? Color(0xFF0DB04B) item['value'] ==
: Color(0xFF004A8E), "Domestic"
label: item['value'], ? Color(
count: item['count'], 0xFF0DB04B,
bgColor: item['value'] == "Domestic" )
? const Color(0xFFD6FBE4) : Color(
: const Color(0xFFD9E8FF), 0xFF004A8E,
),
label:
item['value'],
count:
item['count'],
bgColor:
item['value'] ==
"Domestic"
? const Color(
0xFFD6FBE4,
)
: const Color(
0xFFD9E8FF,
),
), ),
], ],
), ),
@ -894,7 +932,10 @@ class StatusDashboardState extends State<StatusDashboard> {
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(12), borderRadius:
BorderRadius.circular(
12,
),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.blueGrey, color: Colors.blueGrey,
@ -903,23 +944,46 @@ class StatusDashboardState extends State<StatusDashboard> {
), ),
], ],
), ),
padding: const EdgeInsets.all(15), padding: const EdgeInsets.all(
15,
),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment:
CrossAxisAlignment
.start,
children: [ children: [
Text( Text(
"Status", "Status",
style: GoogleFonts.poppins( style:
GoogleFonts.poppins(
fontSize: 19, fontSize: 19,
color: Colors.black87, color:
fontWeight: FontWeight.bold, Colors
.black87,
fontWeight:
FontWeight
.bold,
), ),
), ),
const SizedBox(height: 10), const SizedBox(
height: 10,
),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment:
MainAxisAlignment
.spaceAround,
children: [ children: [
...statusData.map((item) => statusCard(item['value'], item['count'], isDesktop)).toList(), ...statusData
.map(
(
item,
) => statusCard(
item['value'],
item['count'],
isDesktop,
),
)
.toList(),
], ],
), ),
], ],
@ -929,12 +993,14 @@ class StatusDashboardState extends State<StatusDashboard> {
], ],
) )
: Column( : Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment:
CrossAxisAlignment.start,
children: [ children: [
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(12), borderRadius:
BorderRadius.circular(12),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.blueGrey, color: Colors.blueGrey,
@ -943,7 +1009,9 @@ class StatusDashboardState extends State<StatusDashboard> {
), ),
], ],
), ),
padding: const EdgeInsets.all(15), padding: const EdgeInsets.all(
15,
),
child: Row( child: Row(
children: [ children: [
...typeData.map((item) { ...typeData.map((item) {
@ -951,14 +1019,28 @@ class StatusDashboardState extends State<StatusDashboard> {
child: Column( child: Column(
children: [ children: [
buildTopCard( buildTopCard(
color: item['value'] == "Domestic" color:
? const Color(0xFF0DB04B) item['value'] ==
: const Color(0xFF004A8E), "Domestic"
label: item['value'], ? const Color(
count: item['count'], 0xFF0DB04B,
bgColor: item['value'] == "Domestic" )
? const Color(0xFFD6FBE4) : const Color(
: const Color(0xFFD9E8FF), 0xFF004A8E,
),
label:
item['value'],
count:
item['count'],
bgColor:
item['value'] ==
"Domestic"
? const Color(
0xFFD6FBE4,
)
: const Color(
0xFFD9E8FF,
),
), ),
], ],
), ),
@ -971,7 +1053,8 @@ class StatusDashboardState extends State<StatusDashboard> {
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(12), borderRadius:
BorderRadius.circular(12),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.blueGrey, color: Colors.blueGrey,
@ -980,16 +1063,22 @@ class StatusDashboardState extends State<StatusDashboard> {
), ),
], ],
), ),
padding: const EdgeInsets.all(15), padding: const EdgeInsets.all(
15,
),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment:
CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"Status", "Status",
style: GoogleFonts.poppins( style:
GoogleFonts.poppins(
fontSize: 19, fontSize: 19,
color: Colors.black87, color:
fontWeight: FontWeight.bold, Colors.black87,
fontWeight:
FontWeight.bold,
), ),
), ),
const SizedBox(height: 23), const SizedBox(height: 23),
@ -997,7 +1086,17 @@ class StatusDashboardState extends State<StatusDashboard> {
spacing: 10, spacing: 10,
runSpacing: 10, runSpacing: 10,
children: [ children: [
...statusData.map((item) => statusCard(item['value'], item['count'], isDesktop)).toList(), ...statusData
.map(
(
item,
) => statusCard(
item['value'],
item['count'],
isDesktop,
),
)
.toList(),
], ],
), ),
], ],
@ -1011,33 +1110,77 @@ class StatusDashboardState extends State<StatusDashboard> {
// Third Row: Flight, Accommodation, Forex // Third Row: Flight, Accommodation, Forex
isDesktop isDesktop
? Row( ? Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment:
CrossAxisAlignment.start,
children: [ children: [
Expanded(child: buildCategoryCard("Flight", Icons.flight, statusLabels, flightData)), Expanded(
child: buildCategoryCard(
"Flight",
Icons.flight,
statusLabels,
flightData,
),
),
const SizedBox(width: 10), const SizedBox(width: 10),
Expanded(child: buildCategoryCard("Accomodation", Icons.hotel_outlined, statusLabels, accommodationData)), Expanded(
child: buildCategoryCard(
"Accomodation",
Icons.hotel_outlined,
statusLabels,
accommodationData,
),
),
const SizedBox(width: 10), const SizedBox(width: 10),
Expanded(child: buildCategoryCard("Forex", Icons.attach_money, statusLabels, forexData)), Expanded(
child: buildCategoryCard(
"Forex",
Icons.attach_money,
statusLabels,
forexData,
),
),
], ],
) )
: Column( : Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment:
CrossAxisAlignment.start,
children: [ children: [
Row( Row(
children: [ children: [
Expanded(child: buildCategoryCard("Flight", Icons.flight, statusLabels, flightData)), Expanded(
child: buildCategoryCard(
"Flight",
Icons.flight,
statusLabels,
flightData,
),
),
], ],
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
Row( Row(
children: [ children: [
Expanded(child: buildCategoryCard("Accomodation", Icons.hotel_outlined, statusLabels, accommodationData)), Expanded(
child: buildCategoryCard(
"Accomodation",
Icons.hotel_outlined,
statusLabels,
accommodationData,
),
),
], ],
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
Row( Row(
children: [ children: [
Expanded(child: buildCategoryCard("Forex", Icons.attach_money, statusLabels, forexData)), Expanded(
child: buildCategoryCard(
"Forex",
Icons.attach_money,
statusLabels,
forexData,
),
),
], ],
), ),
const SizedBox(height: 20), const SizedBox(height: 20),

File diff suppressed because it is too large Load Diff

View File

@ -1530,7 +1530,8 @@ class _ForexScreenState extends State<ForexScreen> {
else else
SizedBox(height: 8), SizedBox(height: 8),
Column( Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment:
isDesktop ? CrossAxisAlignment.center : CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"Currency *", "Currency *",
@ -1552,19 +1553,24 @@ class _ForexScreenState extends State<ForexScreen> {
height: 40, height: 40,
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Center( child:
child: Text( isDesktop
// "cur", ? Center(child: currencyText())
// "${selectedCurrency}", : Container(child: currencyText()),
selectedCurrency ?? "Currency", // child: Center
// selectedCurrency?.isNotEmpty == true ? selectedCurrency! : "Currency", // (
style: const TextStyle( // child: Text(
fontSize: 12, // // "cur",
fontWeight: FontWeight.w600, // // "${selectedCurrency}",
color: Color(0xFF575A74), // selectedCurrency ?? "Currency",
), // // selectedCurrency?.isNotEmpty == true ? selectedCurrency! : "Currency",
), // style: const TextStyle(
), // fontSize: 12,
// fontWeight: FontWeight.w600,
// color: Color(0xFF575A74),
// ),
// ),
// ),
), ),
), ),
), ),
@ -1632,6 +1638,14 @@ class _ForexScreenState extends State<ForexScreen> {
]; ];
} }
Widget currencyText() => Text(
selectedCurrency ?? "Currency",
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
);
List<Widget> _buildSecondRow(bool isDesktop) { List<Widget> _buildSecondRow(bool isDesktop) {
return [ return [
if (isDesktop) Spacer(), if (isDesktop) Spacer(),
@ -2344,7 +2358,8 @@ class _ForexScreenState extends State<ForexScreen> {
children: [ children: [
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: isDesktop ? MainAxisAlignment.center : MainAxisAlignment.start, mainAxisAlignment:
isDesktop ? MainAxisAlignment.center : MainAxisAlignment.start,
children: [ children: [
Container( Container(
alignment: Alignment.bottomLeft, alignment: Alignment.bottomLeft,

View File

@ -2,11 +2,12 @@ import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
class AccomodationListWidget extends StatelessWidget { import '../../utils/auth_utils.dart';
class AccomodationListWidget extends StatefulWidget {
final List<Map<String, dynamic>> accommodationList; final List<Map<String, dynamic>> accommodationList;
final Function(bool, Map<String, dynamic>, String) onOpen; final Function(bool, Map<String, dynamic>, String) onOpen;
final Function(Map<String, dynamic>) onDeleteAccommodation; final Function(Map<String, dynamic>) onDeleteAccommodation;
final Function(String, bool) onAddNew; final Function(String, bool) onAddNew;
final bool isViewMode; final bool isViewMode;
@ -19,12 +20,57 @@ class AccomodationListWidget extends StatelessWidget {
required this.isViewMode, required this.isViewMode,
}); });
@override
State<AccomodationListWidget> createState() => _AccomodationListWidgetState();
}
class _AccomodationListWidgetState extends State<AccomodationListWidget> {
Color? layoutColor;
Color? secondColor;
Color? thridColor;
@override
void initState() {
super.initState();
loadInitialData();
}
void loadInitialData() async {
String? layoutString = await getLayoutColor();
String? secondString = await getSecondaryColor();
String? thridString = await getTernaryColor();
// String? bodyStringColor = await getBodyColor();
setState(() {
layoutColor =
layoutString != null
? Color(int.parse(layoutString))
: Colors.redAccent;
secondColor =
layoutString != null
? Color(int.parse(secondString!))
: Colors.orange;
thridColor =
layoutString != null
? Color(int.parse(thridString!))
: Colors.orangeAccent;
// bodyColor =
// bodyStringColor != null
// ? Color(int.parse(bodyStringColor))
// : Colors.white;
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isDesktop = MediaQuery.of(context).size.width > 1024; final isDesktop = MediaQuery.of(context).size.width > 1024;
return Padding( return Padding(
padding: const EdgeInsets.all(16.0), padding:
isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0),
child: Container( child: Container(
margin: const EdgeInsets.only(top: 16.0), margin: const EdgeInsets.only(top: 16.0),
child: Column( child: Column(
@ -34,7 +80,7 @@ class AccomodationListWidget extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
if ((!isDesktop) && accommodationList.isNotEmpty) if ((!isDesktop) && widget.accommodationList.isNotEmpty)
Text( Text(
" ", " ",
style: const TextStyle( style: const TextStyle(
@ -44,16 +90,18 @@ class AccomodationListWidget extends StatelessWidget {
), ),
MouseRegion( MouseRegion(
cursor: isViewMode cursor:
widget.isViewMode
? SystemMouseCursors.forbidden ? SystemMouseCursors.forbidden
: SystemMouseCursors.click, : SystemMouseCursors.click,
child: GestureDetector( child: GestureDetector(
onTap: isViewMode onTap:
widget.isViewMode
? null ? null
: () { : () {
print("New data"); print("New data");
onAddNew("Accomodation", true); widget.onAddNew("Accomodation", true);
}, },
child: Row( child: Row(
mainAxisSize: mainAxisSize:
@ -68,7 +116,7 @@ class AccomodationListWidget extends StatelessWidget {
Icons.add_circle_sharp, Icons.add_circle_sharp,
size: 30, size: 30,
color: Color(0xFF114D8B), color: Color(0xFF114D8B),
) ),
// Container( // Container(
// decoration: BoxDecoration( // decoration: BoxDecoration(
// shape: BoxShape.circle, // shape: BoxShape.circle,
@ -147,9 +195,9 @@ class AccomodationListWidget extends StatelessWidget {
], ],
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
// Scroll behavior based on device
_buildData(context, isDesktop) // Scroll behavior based on device
_buildData(context, isDesktop),
], ],
), ),
), ),
@ -158,7 +206,9 @@ class AccomodationListWidget extends StatelessWidget {
Widget _buildData(BuildContext context, bool isDesktop) { Widget _buildData(BuildContext context, bool isDesktop) {
List<Map<String, dynamic>> filteredList = List<Map<String, dynamic>> filteredList =
accommodationList.where((item) => item["is_active"] == "1").toList(); widget.accommodationList
.where((item) => item["is_active"] == "1")
.toList();
print("filteredList- $filteredList"); print("filteredList- $filteredList");
// String formatDate(String dateString) { // String formatDate(String dateString) {
@ -191,8 +241,11 @@ class AccomodationListWidget extends StatelessWidget {
if (hour == 24 && minute == 0) { if (hour == 24 && minute == 0) {
// 24:00 is treated as 00:00 on the next day // 24:00 is treated as 00:00 on the next day
dateTime = DateTime(now.year, now.month, now.day) dateTime = DateTime(
.add(const Duration(days: 1)); now.year,
now.month,
now.day,
).add(const Duration(days: 1));
} else { } else {
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
throw FormatException("Invalid hour or minute"); throw FormatException("Invalid hour or minute");
@ -235,14 +288,18 @@ class AccomodationListWidget extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
// color: Colors.orange.shade50, // color: Colors.orange.shade50,
color: Colors.white, color: isDesktop ? Colors.white : thridColor,
boxShadow: [ // color: Colors.white,
boxShadow:
isDesktop
? [
BoxShadow( BoxShadow(
color: Colors.black12, color: Colors.black12,
blurRadius: 3, blurRadius: 3,
offset: Offset(0, 1), offset: Offset(0, 1),
), ),
], ]
: [],
border: Border( border: Border(
top: BorderSide( top: BorderSide(
color: Colors.white70, // Change color to match your theme color: Colors.white70, // Change color to match your theme
@ -251,36 +308,38 @@ class AccomodationListWidget extends StatelessWidget {
), ),
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(12), padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, // mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Text( Text(
item["hotel_name"]!, item["hotel_name"]!,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w800, fontWeight:
color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74),) isDesktop ? FontWeight.w800 : FontWeight.w600,
color: !isDesktop ? Colors.black : Color(0xFF575A74),
),
), ),
Spacer(), Spacer(),
GestureDetector( GestureDetector(
onTap: () => onOpen(true, item, "Accomodation"), onTap: () => widget.onOpen(true, item, "Accomodation"),
child: Tooltip( child: Tooltip(
message: 'Edit Accomodation Details', message: 'Edit Accomodation Details',
child: Image.asset( child: Image.asset(
'assets/images/IconsImg/edit.png', 'assets/images/IconsImg/edit.png',
width: 20, width: 20,
height: 15, height: 15,
color: Color(0xFF114D8B), color: isDesktop ? Color(0xFF114D8B) : Colors.black87,
), ),
), ),
), ),
SizedBox(width: 10), SizedBox(width: 10),
GestureDetector( GestureDetector(
onTap: () => onDeleteAccommodation(item), onTap: () => widget.onDeleteAccommodation(item),
child: Tooltip( child: Tooltip(
message: 'Delete Accommodation Details', message: 'Delete Accommodation Details',
child: Image.asset( child: Image.asset(
@ -293,9 +352,7 @@ class AccomodationListWidget extends StatelessWidget {
), ),
], ],
), ),
Divider( // Divider(color: Colors.blueGrey.shade50),
color: Colors.blueGrey.shade50,
),
SizedBox(height: 4), SizedBox(height: 4),
isDesktop isDesktop
? Row( ? Row(
@ -304,37 +361,34 @@ class AccomodationListWidget extends StatelessWidget {
flex: 2, flex: 2,
child: Text( child: Text(
" DestinationCity", " DestinationCity",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Check (in) ", " Check (in) ",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Check (out) ", " Check (out) ",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Comments", " Comments",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
], ],
) )
: SizedBox.shrink(), : SizedBox.shrink(),
SizedBox(height: 8),
isDesktop isDesktop
? Row( ? Row(
children: [ children: [
@ -374,87 +428,97 @@ class AccomodationListWidget extends StatelessWidget {
Expanded( Expanded(
flex: 2, flex: 2,
child: _buildComments( child: _buildComments(
"Comments:", item["comments"] ?? "N/A"), "Comments:",
item["comments"] ?? "N/A",
),
), ),
], ],
) )
: Column( : Container(
color: Colors.white,
padding: EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Wrap( _buildRow(
spacing: 20, // horizontal space between items "Destination City",
runSpacing: 10, // vertical space between rows item["destination_city"],
children: [ ),
_buildInfoColumn("City", item["destination_city"]), SizedBox(height: 5),
_buildInfoColumn("Check (In)", "${formatDate(item["checkin_date"]!)} ${formatTime(item["checkin_time"]!)}"), _buildRow(
_buildInfoColumn("Check (Out)", "${formatDate(item["checkout_date"]!)} ${formatTime(item["checkout_time"]!)}"), "Check (in)",
// City - long name handled with flexible space "${formatDate(item["checkin_date"]!)} ${formatTime(item["checkin_time"]!)}",
// Expanded( ),
// flex: 3, SizedBox(height: 5),
// child: _buildInfoColumn("City", item["destination_city"]), _buildRow(
// ), "Check (out)",
"${formatDate(item["checkout_date"]!)} ${formatTime(item["checkout_time"]!)}",
// SizedBox(width: 8), ),
SizedBox(height: 5),
// Check In and Check Out stacked right side _buildRow("Comments:", item["comments"] ?? "N/A"),
// Expanded(
// flex: 4,
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// _buildInfoColumn(
// "Check In",
// "${formatDate(item["checkin_date"]!)} ${formatTime(item["checkin_time"]!)}",
// ),
// SizedBox(height: 6),
// _buildInfoColumn(
// "Check Out",
// "${formatDate(item["checkout_date"]!)} ${formatTime(item["checkout_time"]!)}",
// ),
// ],
// ),
// ),
], ],
), ),
const SizedBox(height: 10),
const Text(
"Comment",
style: TextStyle(fontWeight: FontWeight.w500),
), ),
const SizedBox(height: 5),
if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty)
Container(
width: double.infinity,
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
border: Border.all(color: Color(0xFF7098DD), width: 1),
borderRadius: BorderRadius.circular(6),
),
child: Text(
item["comments"],
style: const TextStyle(fontSize: 12),
),
)
else
const Text( "N/A", style: TextStyle(fontSize: 12), ),
],
)
// Column( // Column(
// crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
// children: [ // children: [
// _buildRow("City:", item["destination_city"]), // Wrap(
// SizedBox(width: 10), // spacing: 20, // horizontal space between items
// SizedBox(width: 10), // runSpacing: 10, // vertical space between rows
// _buildDateTimeRow( // children: [
// "Check-in:", // _buildInfoColumn("City", item["destination_city"]),
// formatDate(item["checkin_date"]!), // _buildInfoColumn("Check (In)", "${formatDate(item["checkin_date"]!)} ${formatTime(item["checkin_time"]!)}"),
// item["checkin_time"]!, // _buildInfoColumn("Check (Out)", "${formatDate(item["checkout_date"]!)} ${formatTime(item["checkout_time"]!)}"),
// // City - long name handled with flexible space
// // Expanded(
// // flex: 3,
// // child: _buildInfoColumn("City", item["destination_city"]),
// // ),
//
// // SizedBox(width: 8),
//
// // Check In and Check Out stacked right side
// // Expanded(
// // flex: 4,
// // child: Column(
// // crossAxisAlignment: CrossAxisAlignment.end,
// // children: [
// // _buildInfoColumn(
// // "Check In",
// // "${formatDate(item["checkin_date"]!)} ${formatTime(item["checkin_time"]!)}",
// // ),
// // SizedBox(height: 6),
// // _buildInfoColumn(
// // "Check Out",
// // "${formatDate(item["checkout_date"]!)} ${formatTime(item["checkout_time"]!)}",
// // ),
// // ],
// // ),
// // ),
// ],
// ), // ),
// SizedBox(width: 10), // const SizedBox(height: 10),
// _buildRow( // const Text(
// "Date(out):", formatDate(item["checkout_date"]!)), // "Comment",
// SizedBox(width: 10), // style: TextStyle(fontWeight: FontWeight.w500),
// _buildRow("Comments:", item["comments"] ?? "N/A"), // ),
// const SizedBox(height: 5),
// if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty)
// Container(
// width: double.infinity,
// padding: const EdgeInsets.all(8),
// decoration: BoxDecoration(
// border: Border.all(color: Color(0xFF7098DD), width: 1),
// borderRadius: BorderRadius.circular(6),
// ),
// child: Text(
// item["comments"],
// style: const TextStyle(fontSize: 12),
// ),
// )
// else
// const Text( "N/A", style: TextStyle(fontSize: 12), ),
// ], // ],
// ) // )
], ],
@ -485,23 +549,27 @@ class AccomodationListWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
child: exceedsLimit child:
exceedsLimit
? Tooltip( ? Tooltip(
message: wrapText(value, 50), message: wrapText(value, 50),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey.shade200, // Black background color: Colors.grey.shade200, // Black background
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
), ),
textStyle: textStyle: TextStyle(
TextStyle(color: Colors.black), // Tooltip text color color: Colors.black,
), // Tooltip text color
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
preferBelow: false, preferBelow: false,
child: Text(value.substring(0, limit) + "...", child: Text(
value.substring(0, limit) + "...",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
overflow: TextOverflow.ellipsis), overflow: TextOverflow.ellipsis,
),
) )
: Text( : Text(
value, value,
@ -531,87 +599,90 @@ class AccomodationListWidget extends StatelessWidget {
SizedBox(height: 4), SizedBox(height: 4),
Text( Text(
value, value,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
fontSize: 12,
color: Colors.black87,
),
), ),
], ],
); );
} }
// Widget _buildRow(String title, String value) { Widget _buildRow(String title, String value) {
// // Define character limits based on title // Define character limits based on title
// Map<String, int> limits = { Map<String, int> limits = {
// // "Special Request:": 30, // "Special Request:": 30,
// "Comments:": 10, "Comments:": 10,
// // Add more keys and limits if needed // Add more keys and limits if needed
// }; };
//
// int limit = limits[title] ?? 50; // Default limit if title not found
// bool exceedsLimit = value.length > limit;
//
// String wrapText(String text, int maxLineLength) {
// final pattern = RegExp('.{1,$maxLineLength}(\\s+|\$)');
// return pattern.allMatches(text).map((m) => m.group(0)!).join('\n');
// }
//
// return Row(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// title,
// style: GoogleFonts.poppins(
// fontSize: 12,
// ),
// ),
// SizedBox(width: 8),
// Expanded(
// child: exceedsLimit
// ? Tooltip(
// message: wrapText(value, 50),
// decoration: BoxDecoration(
// color: Colors.grey.shade200, // Black background
// borderRadius: BorderRadius.circular(6),
// ),
// textStyle:
// TextStyle(color: Colors.black), // Tooltip text color
// padding: EdgeInsets.all(8),
// preferBelow: false,
// child: Text(value.substring(0, limit) + "...",
// style: TextStyle(fontSize: 12),
// overflow: TextOverflow.ellipsis),
// )
// : Text(
// value,
// style: TextStyle(fontSize: 12),
// ),
// ),
// ],
// );
// }
// Widget _buildDateTimeRow(String title, String date, String time) { int limit = limits[title] ?? 50; // Default limit if title not found
// return Row( bool exceedsLimit = value.length > limit;
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [ String wrapText(String text, int maxLineLength) {
// Text( final pattern = RegExp('.{1,$maxLineLength}(\\s+|\$)');
// title, return pattern.allMatches(text).map((m) => m.group(0)!).join('\n');
// style: GoogleFonts.poppins( }
// fontSize: 12,
// fontWeight: FontWeight.w600, return Row(
// ), crossAxisAlignment: CrossAxisAlignment.start,
// ),
// SizedBox(width: 8), children: [
// Expanded( SizedBox(
// child: Text( // color: Colors.yellowAccent.shade100,
// "$date, $time", width: 100,
// style: GoogleFonts.poppins( child: Text(
// fontSize: 12, title,
// ), style: GoogleFonts.poppins(
// ), fontSize: 12,
// ), fontWeight: FontWeight.w600,
// ], ),
// ); ),
// } ),
SizedBox(width: 5),
// Expanded(child: Text(value, style: TextStyle(fontSize: 12))),
Expanded(
child:
exceedsLimit
? Tooltip(
message: wrapText(value, 50),
decoration: BoxDecoration(
color: Colors.grey.shade200, // Black background
borderRadius: BorderRadius.circular(6),
),
textStyle: TextStyle(
color: Colors.black,
), // Tooltip text color
padding: EdgeInsets.all(8),
preferBelow: false,
child: Text(
value.substring(0, limit) + "...",
style: TextStyle(fontSize: 12),
overflow: TextOverflow.ellipsis,
),
)
: Text(value, style: TextStyle(fontSize: 12)),
),
],
);
}
Widget _buildDateTimeRow(String title, String date, String time) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 100,
child: Text(
title,
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
),
),
),
SizedBox(width: 5),
Expanded(
child: Text("$date, $time", style: GoogleFonts.poppins(fontSize: 12)),
),
],
);
}
} }

View File

@ -8,8 +8,9 @@ import 'package:shared_preferences/shared_preferences.dart';
import '../../config/apiUrl.dart'; import '../../config/apiUrl.dart';
import '../../data/models/plan.dart'; import '../../data/models/plan.dart';
import '../../utils/auth_utils.dart';
class BusListWidget extends StatelessWidget { class BusListWidget extends StatefulWidget {
final List<Map<String, dynamic>> busList; final List<Map<String, dynamic>> busList;
final Function(bool, Map<String, dynamic>, String) onOpen; final Function(bool, Map<String, dynamic>, String) onOpen;
final Function(Map<String, dynamic>) onDeleteBus; final Function(Map<String, dynamic>) onDeleteBus;
@ -17,20 +18,66 @@ class BusListWidget extends StatelessWidget {
final Function(String, bool) onAddNew; final Function(String, bool) onAddNew;
final bool isViewMode; final bool isViewMode;
const BusListWidget( const BusListWidget({
{super.key, super.key,
required this.busList, required this.busList,
required this.onOpen, required this.onOpen,
required this.onDeleteBus, required this.onDeleteBus,
required this.onAddNew, required this.onAddNew,
required this.isViewMode}); required this.isViewMode,
});
@override
State<BusListWidget> createState() => _BusListWidgetState();
}
class _BusListWidgetState extends State<BusListWidget> {
Color? layoutColor;
Color? secondColor;
Color? thridColor;
@override
void initState() {
super.initState();
loadInitialData();
}
void loadInitialData() async {
String? layoutString = await getLayoutColor();
String? secondString = await getSecondaryColor();
String? thridString = await getTernaryColor();
// String? bodyStringColor = await getBodyColor();
setState(() {
layoutColor =
layoutString != null
? Color(int.parse(layoutString))
: Colors.redAccent;
secondColor =
layoutString != null
? Color(int.parse(secondString!))
: Colors.orange;
thridColor =
layoutString != null
? Color(int.parse(thridString!))
: Colors.orangeAccent;
// bodyColor =
// bodyStringColor != null
// ? Color(int.parse(bodyStringColor))
// : Colors.white;
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isDesktop = MediaQuery.of(context).size.width > 1024; final isDesktop = MediaQuery.of(context).size.width > 1024;
return Padding( return Padding(
padding: const EdgeInsets.all(16.0), padding:
isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0),
child: Container( child: Container(
margin: const EdgeInsets.only(top: 16.0), margin: const EdgeInsets.only(top: 16.0),
child: Column( child: Column(
@ -40,7 +87,7 @@ class BusListWidget extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
if ((!isDesktop) && busList.isNotEmpty) if ((!isDesktop) && widget.busList.isNotEmpty)
Text( Text(
" ", " ",
style: const TextStyle( style: const TextStyle(
@ -50,15 +97,17 @@ class BusListWidget extends StatelessWidget {
), ),
MouseRegion( MouseRegion(
cursor: isViewMode cursor:
widget.isViewMode
? SystemMouseCursors.forbidden ? SystemMouseCursors.forbidden
: SystemMouseCursors.click, : SystemMouseCursors.click,
child: GestureDetector( child: GestureDetector(
onTap: isViewMode onTap:
widget.isViewMode
? null ? null
: () { : () {
print("New data"); print("New data");
onAddNew("Bus", true); widget.onAddNew("Bus", true);
}, },
child: Row( child: Row(
mainAxisSize: mainAxisSize:
@ -73,7 +122,7 @@ class BusListWidget extends StatelessWidget {
Icons.add_circle_sharp, Icons.add_circle_sharp,
size: 30, size: 30,
color: Color(0xFF114D8B), color: Color(0xFF114D8B),
) ),
// Container( // Container(
// decoration: BoxDecoration( // decoration: BoxDecoration(
// shape: BoxShape.circle, // shape: BoxShape.circle,
@ -130,9 +179,9 @@ class BusListWidget extends StatelessWidget {
], ],
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
// Scroll behavior based on device
_buildData(context, isDesktop) // Scroll behavior based on device
_buildData(context, isDesktop),
], ],
), ),
), ),
@ -141,7 +190,7 @@ class BusListWidget extends StatelessWidget {
Widget _buildData(BuildContext context, bool isDesktop) { Widget _buildData(BuildContext context, bool isDesktop) {
List<Map<String, dynamic>> filteredList = List<Map<String, dynamic>> filteredList =
busList.where((item) => item["is_active"] == "1").toList(); widget.busList.where((item) => item["is_active"] == "1").toList();
print("filteredList- $filteredList"); print("filteredList- $filteredList");
// String formatDate(String dateString) { // String formatDate(String dateString) {
@ -191,8 +240,11 @@ class BusListWidget extends StatelessWidget {
if (hour == 24 && minute == 0) { if (hour == 24 && minute == 0) {
// 24:00 is treated as 00:00 on the next day // 24:00 is treated as 00:00 on the next day
dateTime = DateTime(now.year, now.month, now.day) dateTime = DateTime(
.add(const Duration(days: 1)); now.year,
now.month,
now.day,
).add(const Duration(days: 1));
} else { } else {
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
throw FormatException("Invalid hour or minute"); throw FormatException("Invalid hour or minute");
@ -218,14 +270,17 @@ class BusListWidget extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
// color: Colors.orange.shade50, // color: Colors.orange.shade50,
color: Colors.white, color: isDesktop ? Colors.white : thridColor,
boxShadow: [ boxShadow:
isDesktop
? [
BoxShadow( BoxShadow(
color: Colors.black12, color: Colors.black12,
blurRadius: 3, blurRadius: 3,
offset: Offset(0, 1), offset: Offset(0, 1),
), ),
], ]
: [],
border: Border( border: Border(
top: BorderSide( top: BorderSide(
color: Colors.white70, // Change color to match your theme color: Colors.white70, // Change color to match your theme
@ -234,7 +289,7 @@ class BusListWidget extends StatelessWidget {
), ),
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(12), padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -246,25 +301,27 @@ class BusListWidget extends StatelessWidget {
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
color:
!isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74),
), ),
), ),
Spacer(), Spacer(),
GestureDetector( GestureDetector(
onTap: () => onOpen(true, item, "Bus"), onTap: () => widget.onOpen(true, item, "Bus"),
child: Tooltip( child: Tooltip(
message: 'Delete Edit Details', message: 'Edit Bus Details',
child: Image.asset( child: Image.asset(
'assets/images/IconsImg/edit.png', 'assets/images/IconsImg/edit.png',
width: 20, width: 20,
height: 15, height: 15,
// color: Color(0xFF114D8B), // color: Color(0xFF114D8B),
color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) color: !isDesktop ? Colors.black : Color(0xFF575A74),
), ),
), ),
), ),
SizedBox(width: 10), SizedBox(width: 10),
GestureDetector( GestureDetector(
onTap: () => onDeleteBus(item), onTap: () => widget.onDeleteBus(item),
child: Tooltip( child: Tooltip(
message: 'Delete Bus Details', message: 'Delete Bus Details',
child: Image.asset( child: Image.asset(
@ -277,9 +334,7 @@ class BusListWidget extends StatelessWidget {
), ),
], ],
), ),
Divider( // Divider(color: Colors.blueGrey.shade50),
color: Colors.blueGrey.shade50,
),
SizedBox(height: 4), SizedBox(height: 4),
isDesktop isDesktop
? Row( ? Row(
@ -288,30 +343,27 @@ class BusListWidget extends StatelessWidget {
flex: 3, flex: 3,
child: Text( child: Text(
"Planned Trips", "Planned Trips",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 3, flex: 3,
child: Text( child: Text(
" Date", " Date",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 3, flex: 3,
child: Text( child: Text(
" Comments", " Comments",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
], ],
) )
: SizedBox.shrink(), : SizedBox.shrink(),
SizedBox(height: 4), SizedBox(height: 8),
isDesktop isDesktop
? Row( ? Row(
children: [ children: [
@ -340,74 +392,91 @@ class BusListWidget extends StatelessWidget {
Expanded( Expanded(
flex: 3, flex: 3,
child: _buildComments( child: _buildComments(
"Comments:", item["comments"] ?? "N/A"), "Comments:",
item["comments"] ?? "N/A",
),
), ),
], ],
) )
: : Container(
Column( color: Colors.white,
padding: const EdgeInsets.all(4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Top Row (Country, Currency, Total) _buildRow(
Wrap( "PlannedTrips",
spacing: 20, // horizontal space between items '${item["from"]!} - ${item["to"]!}',
runSpacing: 10, // vertical space between rows
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_infoBlock("From", item["from"] ?? "N/A"),
_infoBlock("To", item["to"]! ?? "N/A"),
_infoBlock("Date",
(item["date"] != null && item["time"] != null)
? "${formatDate(item["date"]!)} ${formatTime(item["time"]!)}"
: "N/A",
), ),
SizedBox(height: 5),
// _buildRow("To", item["to"]!),
// SizedBox(width: 10),
_buildDateTimeRow(
"Date",
formatDate(item["date"]!),
formatTime(item["time"]!),
),
SizedBox(height: 5),
_buildRow("Comments", item["comments"] ?? "N/A"),
], ],
), ),
const SizedBox(height: 16), ),
// Comment label
Text(
"Comment",
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty)
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
border: Border.all(color: const Color(0xFF7098DD), width: 1),
borderRadius: BorderRadius.circular(6),
),
child: Text(
item["comments"] ?? "N/A",
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
),
)
else
const Text( "N/A", style: TextStyle(fontSize: 12), ),
],
),
// Column( // Column(
// crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
// children: [ // children: [
// _buildRow("From:", item["from"]), // // Top Row (Country, Currency, Total)
// SizedBox(width: 10), // Wrap(
// _buildRow("To:", item["to"]!), // spacing: 20, // horizontal space between items
// SizedBox(width: 10), // runSpacing: 10, // vertical space between rows
// _buildDateTimeRow( // // Row(
// "Date:", // // mainAxisAlignment: MainAxisAlignment.spaceBetween,
// formatDate(item["date"]!), // children: [
// formatTime(item["time"]!), // _infoBlock("From", item["from"] ?? "N/A"),
// _infoBlock("To", item["to"]! ?? "N/A"),
// _infoBlock(
// "Date",
// (item["date"] != null && item["time"] != null)
// ? "${formatDate(item["date"]!)} ${formatTime(item["time"]!)}"
// : "N/A",
// ), // ),
// _buildRow("Comments:", item["comments"] ?? "N/A"),
// ], // ],
// ),
// const SizedBox(height: 16),
//
// // Comment label
// Text(
// "Comment",
// style: GoogleFonts.poppins(
// fontSize: 14,
// fontWeight: FontWeight.w600,
// ),
// ),
// const SizedBox(height: 8),
// if (item["comments"] != null &&
// item["comments"].toString().trim().isNotEmpty)
// Container(
// width: double.infinity,
// padding: const EdgeInsets.all(12),
// decoration: BoxDecoration(
// border: Border.all(
// color: const Color(0xFF7098DD),
// width: 1,
// ),
// borderRadius: BorderRadius.circular(6),
// ),
// child: Text(
// item["comments"] ?? "N/A",
// style: GoogleFonts.poppins(
// fontSize: 12,
// color: Colors.black87,
// ),
// ),
// ) // )
// else
// const Text("N/A", style: TextStyle(fontSize: 12)),
// ],
// ),
], ],
), ),
), ),
@ -434,16 +503,14 @@ class BusListWidget extends StatelessWidget {
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
value, value,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
fontSize: 12,
color: Colors.black87,
),
), ),
], ],
), ),
), ),
); );
} }
Widget _buildComments(String title, String value) { Widget _buildComments(String title, String value) {
// Define character limits based on title // Define character limits based on title
Map<String, int> limits = { Map<String, int> limits = {
@ -464,23 +531,27 @@ class BusListWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
child: exceedsLimit child:
exceedsLimit
? Tooltip( ? Tooltip(
message: wrapText(value, 50), message: wrapText(value, 50),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey.shade200, // Black background color: Colors.grey.shade200, // Black background
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
), ),
textStyle: textStyle: TextStyle(
TextStyle(color: Colors.black), // Tooltip text color color: Colors.black,
), // Tooltip text color
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
preferBelow: false, preferBelow: false,
child: Text(value.substring(0, limit) + "...", child: Text(
value.substring(0, limit) + "...",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
overflow: TextOverflow.ellipsis), overflow: TextOverflow.ellipsis,
),
) )
: Text( : Text(
value, value,
@ -513,36 +584,38 @@ class BusListWidget extends StatelessWidget {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( SizedBox(
width: 100,
child: Text(
title, title,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
),
SizedBox(width: 8), SizedBox(width: 8),
Expanded( Expanded(
child: exceedsLimit child:
exceedsLimit
? Tooltip( ? Tooltip(
message: wrapText(value, 50), message: wrapText(value, 50),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey.shade200, // Black background color: Colors.grey.shade200, // Black background
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
), ),
textStyle: textStyle: TextStyle(
TextStyle(color: Colors.black), // Tooltip text color color: Colors.black,
), // Tooltip text color
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
preferBelow: false, preferBelow: false,
child: Text(value.substring(0, limit) + "...", child: Text(
value.substring(0, limit) + "...",
style: TextStyle(fontSize: 12), style: TextStyle(fontSize: 12),
overflow: TextOverflow.ellipsis), overflow: TextOverflow.ellipsis,
),
) )
: Text( : Text(value, style: GoogleFonts.poppins(fontSize: 12)),
value,
style: GoogleFonts.poppins(
fontSize: 12,
),
),
), ),
], ],
); );
@ -552,21 +625,19 @@ class BusListWidget extends StatelessWidget {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( SizedBox(
width: 100,
child: Text(
title, title,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
),
SizedBox(width: 8), SizedBox(width: 8),
Expanded( Expanded(
child: Text( child: Text("$date, $time", style: GoogleFonts.poppins(fontSize: 12)),
"$date, $time",
style: GoogleFonts.poppins(
fontSize: 12,
),
),
), ),
], ],
); );

View File

@ -3,6 +3,7 @@ import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import '../../services/apiService.dart'; import '../../services/apiService.dart';
import '../../utils/auth_utils.dart';
class FlightListWidget extends StatefulWidget { class FlightListWidget extends StatefulWidget {
final bool hasAction; final bool hasAction;
@ -32,6 +33,9 @@ class FlightListWidget extends StatefulWidget {
class _FlightListWidgetState extends State<FlightListWidget> { class _FlightListWidgetState extends State<FlightListWidget> {
ApiService apiService = ApiService(); ApiService apiService = ApiService();
Color? layoutColor;
Color? secondColor;
Color? thridColor;
// late Map<String, String> countryMap; // late Map<String, String> countryMap;
Map<String, String> countryMap = {}; Map<String, String> countryMap = {};
@ -40,6 +44,36 @@ class _FlightListWidgetState extends State<FlightListWidget> {
void initState() { void initState() {
super.initState(); super.initState();
loadCountryList(); // Call your method here loadCountryList(); // Call your method here
loadInitialData();
}
void loadInitialData() async {
String? layoutString = await getLayoutColor();
String? secondString = await getSecondaryColor();
String? thridString = await getTernaryColor();
// String? bodyStringColor = await getBodyColor();
setState(() {
layoutColor =
layoutString != null
? Color(int.parse(layoutString))
: Colors.redAccent;
secondColor =
layoutString != null
? Color(int.parse(secondString!))
: Colors.orange;
thridColor =
layoutString != null
? Color(int.parse(thridString!))
: Colors.orangeAccent;
// bodyColor =
// bodyStringColor != null
// ? Color(int.parse(bodyStringColor))
// : Colors.white;
});
} }
Future<void> loadCountryList() async { Future<void> loadCountryList() async {
@ -169,7 +203,8 @@ class _FlightListWidgetState extends State<FlightListWidget> {
// ); // );
return Padding( return Padding(
padding: const EdgeInsets.all(16.0), padding:
isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0),
child: Container( child: Container(
margin: const EdgeInsets.only(top: 16.0), margin: const EdgeInsets.only(top: 16.0),
child: Column( child: Column(
@ -192,11 +227,13 @@ class _FlightListWidgetState extends State<FlightListWidget> {
// Right side: either "Add" icon or nothing // Right side: either "Add" icon or nothing
if (widget.flightList.isNotEmpty) if (widget.flightList.isNotEmpty)
MouseRegion( MouseRegion(
cursor: widget.isViewMode cursor:
widget.isViewMode
? SystemMouseCursors.forbidden ? SystemMouseCursors.forbidden
: SystemMouseCursors.click, : SystemMouseCursors.click,
child: GestureDetector( child: GestureDetector(
onTap: widget.isViewMode onTap:
widget.isViewMode
? null ? null
: () { : () {
widget.onAddNew("Flight", true); widget.onAddNew("Flight", true);
@ -217,14 +254,13 @@ class _FlightListWidgetState extends State<FlightListWidget> {
"No Data Found", "No Data Found",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 20, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.w500,
color: Colors.grey, color: Colors.grey,
), ),
), ),
), ),
) ),
], ],
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
@ -235,7 +271,6 @@ class _FlightListWidgetState extends State<FlightListWidget> {
), ),
), ),
); );
} }
Widget _buildData(BuildContext context, bool isDesktop) { Widget _buildData(BuildContext context, bool isDesktop) {
@ -347,10 +382,13 @@ class _FlightListWidgetState extends State<FlightListWidget> {
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 6), margin: EdgeInsets.symmetric(horizontal: 8, vertical: 6),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
// color: isDesktop ? Colors.white : Color(0xFFFFF0F5),
color: isDesktop ? Colors.white : thridColor,
// color: Colors.orange.shade50, // color: Colors.orange.shade50,
color: Colors.white, // color: Colors.white,
boxShadow:
boxShadow: [ isDesktop
? [
BoxShadow( BoxShadow(
color: Colors.black12, color: Colors.black12,
blurRadius: 2, blurRadius: 2,
@ -362,7 +400,8 @@ class _FlightListWidgetState extends State<FlightListWidget> {
blurRadius: 0.5, blurRadius: 0.5,
offset: Offset(0, -1), // up offset: Offset(0, -1), // up
), ),
], ]
: [],
border: Border( border: Border(
top: BorderSide( top: BorderSide(
color: Colors.white70, // Change color to match your theme color: Colors.white70, // Change color to match your theme
@ -371,18 +410,23 @@ class _FlightListWidgetState extends State<FlightListWidget> {
), ),
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(12), padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(5),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Padding(
padding: const EdgeInsets.symmetric(horizontal: 2),
child: Row(
children: [ children: [
Text( Text(
tripTypeName ?? "N/A", tripTypeName ?? "N/A",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w800, fontWeight:
color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74), isDesktop ? FontWeight.w800 : FontWeight.w600,
color: !isDesktop ? Colors.black : Color(0xFF575A74),
// Color(0xFF114D8B)
), ),
), ),
Spacer(), Spacer(),
@ -394,7 +438,8 @@ class _FlightListWidgetState extends State<FlightListWidget> {
'assets/images/IconsImg/edit.png', 'assets/images/IconsImg/edit.png',
width: 20, width: 20,
height: 15, height: 15,
color: Color(0xFF114D8B), color:
isDesktop ? Color(0xFF114D8B) : Colors.black87,
), ),
), ),
), ),
@ -413,7 +458,8 @@ class _FlightListWidgetState extends State<FlightListWidget> {
), ),
], ],
), ),
Divider(color: Colors.blueGrey.shade50), ),
// Divider(color: Colors.blueGrey.shade50),
SizedBox(height: 4), SizedBox(height: 4),
if (isDesktop) if (isDesktop)
Row( Row(
@ -600,7 +646,6 @@ class _FlightListWidgetState extends State<FlightListWidget> {
item["trips"] != null && item["trips"] != null &&
item["trips"].isNotEmpty) item["trips"].isNotEmpty)
...item["trips"].map<Widget>((trip) { ...item["trips"].map<Widget>((trip) {
String fromPlaceCountry = String fromPlaceCountry =
countryMap[trip["from_place"]?.toString()] ?? countryMap[trip["from_place"]?.toString()] ??
"Unknown Country"; "Unknown Country";
@ -631,41 +676,44 @@ class _FlightListWidgetState extends State<FlightListWidget> {
final tocity = tocityMatch?.group(1) ?? ''; final tocity = tocityMatch?.group(1) ?? '';
final tocode = tocityMatch?.group(2) ?? ''; final tocode = tocityMatch?.group(2) ?? '';
// return Padding( return Padding(
// padding: const EdgeInsets.symmetric(vertical: 6.0), padding: const EdgeInsets.symmetric(vertical: 6.0),
// child: Container( child: Container(
// decoration: BoxDecoration( decoration: BoxDecoration(
// border: Border.all(color: Colors.grey.shade300), border: Border.all(color: Colors.grey.shade300),
// borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
// color: Colors.grey.shade50, color: Colors.grey.shade50,
// ), ),
// padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
// child: Column( child: Column(
// crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
// children: [ children: [
// _buildKeyValueRow( _buildKeyValueRow(
// "Class", "Class",
// getRequestForClass(trip["class"].toString()) ?? getRequestForClass(trip["class"].toString()) ??
// "N/A", "N/A",
// ), ),
// _buildKeyValueRow( _buildKeyValueRow(
// "Sector", "From",
// "$fromcity ($fromcode), $fromairport$tocity ($tocode), $toairport", "$fromcity ($fromcode), $fromairport ",
// ), ),
// _buildKeyValueRow(
// _buildKeyValueRow( "To",
// "Date", "$tocity ($tocode), $toairport",
// formatDate(trip["date"] ?? ""), ),
// ),
// _buildKeyValueRow(
// "Time",
// formatTime(trip["time"] ?? ""),
// ),
// ],
// ),
// ),
// );
_buildKeyValueRow(
"Date",
formatDate(trip["date"] ?? ""),
),
_buildKeyValueRow(
"Time",
formatTime(trip["time"] ?? ""),
),
],
),
),
);
// return Padding( // return Padding(
// padding: const EdgeInsets.symmetric(vertical: 6.0), // padding: const EdgeInsets.symmetric(vertical: 6.0),
@ -701,9 +749,13 @@ class _FlightListWidgetState extends State<FlightListWidget> {
// ), // ),
// ), // ),
// const Padding( // const Padding(
// padding: EdgeInsets.symmetric(horizontal: 6), // padding: EdgeInsets.symmetric(
// horizontal: 6,
// ),
// child: Image( // child: Image(
// image: AssetImage('assets/images/IconsImg/Frame.png'), // image: AssetImage(
// 'assets/images/IconsImg/Frame.png',
// ),
// width: 18, // width: 18,
// height: 18, // height: 18,
// ), // ),
@ -738,68 +790,67 @@ class _FlightListWidgetState extends State<FlightListWidget> {
// ), // ),
// ); // );
return Padding( // return Padding(
padding: const EdgeInsets.symmetric(vertical: 6.0), // padding: const EdgeInsets.symmetric(vertical: 6.0),
child: Container( // child: Container(
child: Column( // child: Column(
crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
children: [ // children: [
Wrap( // Wrap(
crossAxisAlignment: WrapCrossAlignment.center, // crossAxisAlignment: WrapCrossAlignment.center,
spacing: 4, // spacing: 4,
runSpacing: 4, // runSpacing: 4,
children: [ // children: [
Text( // Text(
'${getRequestForClass(trip["class"].toString()) ?? "N/A"} (', // '${getRequestForClass(trip["class"].toString()) ?? "N/A"} (',
style: const TextStyle( // style: const TextStyle(
fontWeight: FontWeight.bold, // fontWeight: FontWeight.bold,
fontSize: 14, // fontSize: 14,
color: Colors.black87, // color: Colors.black87,
), // ),
), // ),
Text( // Text(
fromcode, // fromcode,
style: const TextStyle( // style: const TextStyle(
fontWeight: FontWeight.bold, // fontWeight: FontWeight.bold,
fontSize: 14, // fontSize: 14,
color: Colors.black87, // color: Colors.black87,
), // ),
), // ),
const Padding( // const Padding(
padding: EdgeInsets.symmetric(horizontal: 4), // padding: EdgeInsets.symmetric(horizontal: 4),
child: Image( // child: Image(
image: AssetImage('assets/images/IconsImg/Frame.png'), // image: AssetImage('assets/images/IconsImg/Frame.png'),
width: 18, // width: 18,
height: 18, // height: 18,
), // ),
), // ),
Text( // Text(
'$tocode)', // '$tocode)',
style: const TextStyle( // style: const TextStyle(
fontWeight: FontWeight.bold, // fontWeight: FontWeight.bold,
fontSize: 14, // fontSize: 14,
color: Colors.black87, // color: Colors.black87,
), // ),
), // ),
], // ],
), // ),
const SizedBox(height: 6), // const SizedBox(height: 6),
Align( // Align(
alignment: Alignment.centerRight, // alignment: Alignment.centerRight,
child: Text( // child: Text(
'${formatDate(trip["date"] ?? "")} ${formatTime(trip["time"] ?? "")}', // '${formatDate(trip["date"] ?? "")} ${formatTime(trip["time"] ?? "")}',
textAlign: TextAlign.right, // textAlign: TextAlign.right,
style: const TextStyle( // style: const TextStyle(
fontSize: 13, // fontSize: 13,
color: Colors.black87, // color: Colors.black87,
), // ),
), // ),
), // ),
], // ],
), // ),
), // ),
); // );
}).toList(), }).toList(),
], ],
), ),
@ -816,12 +867,12 @@ class _FlightListWidgetState extends State<FlightListWidget> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SizedBox( SizedBox(
width: 80, // adjust width as needed width: 70, // adjust width as needed
child: Text( child: Text(
"$key:", "$key",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w600,
), ),
), ),
), ),

View File

@ -5,8 +5,9 @@ import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import '../../services/apiService.dart'; import '../../services/apiService.dart';
import '../../utils/auth_utils.dart';
class ForexListWidget extends StatelessWidget { class ForexListWidget extends StatefulWidget {
final List<Map<String, dynamic>> forexList; final List<Map<String, dynamic>> forexList;
final Function(bool, Map<String, dynamic>, String) onOpen; final Function(bool, Map<String, dynamic>, String) onOpen;
final Function(Map<String, dynamic>) onDeleteForex; final Function(Map<String, dynamic>) onDeleteForex;
@ -16,15 +17,60 @@ class ForexListWidget extends StatelessWidget {
final Function(String, bool) onAddNew; final Function(String, bool) onAddNew;
final bool isViewMode; final bool isViewMode;
const ForexListWidget( const ForexListWidget({
{super.key, super.key,
required this.forexList, required this.forexList,
required this.onOpen, required this.onOpen,
required this.onDeleteForex, required this.onDeleteForex,
required this.apiCountryData, required this.apiCountryData,
required this.onAddNew, required this.onAddNew,
required this.apiData, required this.apiData,
required this.isViewMode}); required this.isViewMode,
});
@override
State<ForexListWidget> createState() => _ForexListWidgetState();
}
class _ForexListWidgetState extends State<ForexListWidget> {
Color? layoutColor;
Color? secondColor;
Color? thridColor;
@override
void initState() {
super.initState();
loadInitialData();
}
void loadInitialData() async {
String? layoutString = await getLayoutColor();
String? secondString = await getSecondaryColor();
String? thridString = await getTernaryColor();
// String? bodyStringColor = await getBodyColor();
setState(() {
layoutColor =
layoutString != null
? Color(int.parse(layoutString))
: Colors.redAccent;
secondColor =
layoutString != null
? Color(int.parse(secondString!))
: Colors.orange;
thridColor =
layoutString != null
? Color(int.parse(thridString!))
: Colors.orangeAccent;
// bodyColor =
// bodyStringColor != null
// ? Color(int.parse(bodyStringColor))
// : Colors.white;
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -32,7 +78,8 @@ class ForexListWidget extends StatelessWidget {
final ApiService apiService = ApiService(); final ApiService apiService = ApiService();
return Padding( return Padding(
padding: const EdgeInsets.all(16.0), padding:
isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0),
child: Container( child: Container(
margin: const EdgeInsets.only(top: 16.0), margin: const EdgeInsets.only(top: 16.0),
child: Column( child: Column(
@ -134,27 +181,24 @@ class ForexListWidget extends StatelessWidget {
// // ), // // ),
// ], // ],
// ), // ),
const SizedBox(height: 16), SizedBox(height: isDesktop ? 16 : 4),
// Scroll behavior based on device
_buildData(context, isDesktop) // Scroll behavior based on device
_buildData(context, isDesktop),
], ],
), ),
), ),
); );
} }
Widget _buildData( Widget _buildData(BuildContext context, bool isDesktop) {
BuildContext context,
bool isDesktop,
) {
final ApiService apiService = ApiService(); final ApiService apiService = ApiService();
List<Map<String, dynamic>> filteredList = List<Map<String, dynamic>> filteredList =
forexList.where((item) => item["is_active"] == "1").toList(); widget.forexList.where((item) => item["is_active"] == "1").toList();
print("filteredList- $filteredList"); print("filteredList- $filteredList");
List<dynamic> visatypeList = apiData?['visa_type_of_visa'] ?? []; List<dynamic> visatypeList = widget.apiData?['visa_type_of_visa'] ?? [];
List<dynamic> countryList = apiCountryData ?? []; List<dynamic> countryList = widget.apiCountryData ?? [];
String getRequestForVisa(String? specialRequestKey) { String getRequestForVisa(String? specialRequestKey) {
if (specialRequestKey == null) return "N/A"; if (specialRequestKey == null) return "N/A";
@ -209,8 +253,11 @@ class ForexListWidget extends StatelessWidget {
if (hour == 24 && minute == 0) { if (hour == 24 && minute == 0) {
// 24:00 is treated as 00:00 on the next day // 24:00 is treated as 00:00 on the next day
dateTime = DateTime(now.year, now.month, now.day) dateTime = DateTime(
.add(const Duration(days: 1)); now.year,
now.month,
now.day,
).add(const Duration(days: 1));
} else { } else {
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
throw FormatException("Invalid hour or minute"); throw FormatException("Invalid hour or minute");
@ -231,27 +278,34 @@ class ForexListWidget extends StatelessWidget {
itemBuilder: (context, index) { itemBuilder: (context, index) {
final item = filteredList[index]; final item = filteredList[index];
final double transport = double.tryParse(item["transport"] ?? "0") ?? 0; final double transport = double.tryParse(item["transport"] ?? "0") ?? 0;
final double accommodation = double.tryParse(item["accommodation"] ?? "0") ?? 0; final double accommodation =
double.tryParse(item["accommodation"] ?? "0") ?? 0;
final double telephone = double.tryParse(item["telephone"] ?? "0") ?? 0; final double telephone = double.tryParse(item["telephone"] ?? "0") ?? 0;
final double perdiemAmount = double.tryParse(item["perdiem_amount"] ?? "0") ?? 0; final double perdiemAmount =
double.tryParse(item["perdiem_amount"] ?? "0") ?? 0;
final double calculatedValue = transport + accommodation + telephone; final double calculatedValue = transport + accommodation + telephone;
final String calculatedOtherExpenses = calculatedValue.toStringAsFixed(0); final String calculatedOtherExpenses = calculatedValue.toStringAsFixed(
0,
);
final double finalTotal = calculatedValue + perdiemAmount; final double finalTotal = calculatedValue + perdiemAmount;
return Container( return Container(
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 6), margin: EdgeInsets.symmetric(horizontal: 8, vertical: 6),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
// color: Colors.orange.shade50, // color: Colors.orange.shade50,
color: Colors.white, // color: Colors.white,
boxShadow: [ color: isDesktop ? Colors.white : thridColor,
boxShadow:
isDesktop
? [
BoxShadow( BoxShadow(
color: Colors.black12, color: Colors.black12,
blurRadius: 3, blurRadius: 3,
offset: Offset(0, 1), offset: Offset(0, 1),
), ),
], ]
: [],
border: Border( border: Border(
top: BorderSide( top: BorderSide(
color: Colors.white70, // Change color to match your theme color: Colors.white70, // Change color to match your theme
@ -260,23 +314,28 @@ class ForexListWidget extends StatelessWidget {
), ),
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(12), padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, // mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Text( Expanded(
flex: 1,
child: Text(
getRequestForCountry(item["country_code"]!.toString()), getRequestForCountry(item["country_code"]!.toString()),
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 14,
fontWeight: FontWeight.w700, fontWeight:
isDesktop ? FontWeight.w800 : FontWeight.w600,
color: !isDesktop ? Colors.black : Color(0xFF575A74),
),
), ),
), ),
Spacer(), Spacer(),
GestureDetector( GestureDetector(
onTap: () => onOpen(true, item, "Forex"), onTap: () => widget.onOpen(true, item, "Forex"),
child: Tooltip( child: Tooltip(
message: 'Edit Forex Details', message: 'Edit Forex Details',
child: Image.asset( child: Image.asset(
@ -284,27 +343,30 @@ class ForexListWidget extends StatelessWidget {
width: 20, width: 20,
height: 15, height: 15,
// color: Color(0xFF114D8B), // color: Color(0xFF114D8B),
color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) color: !isDesktop ? Colors.black : Color(0xFF575A74),
),
),
),
SizedBox(width: 10),
GestureDetector(
onTap: () => widget.onDeleteForex(item),
child: Tooltip(
message: 'Delete Forex Details',
child: Image.asset(
'assets/images/IconsImg/delete.png',
width: 20,
height: 15,
color: Colors.red,
), ),
), ),
), ),
// SizedBox(width: 10),
// GestureDetector(
// onTap: () => onDeleteForex(item),
// child: Tooltip(
// message: 'Delete Forex Details',
// child: Image.asset(
// 'assets/images/IconsImg/delete.png',
// width: 20,
// height: 15,
// color: Colors.red,
// ),
// ),
// ),
item['forex_id'] != null item['forex_id'] != null
? IconButton( ? IconButton(
icon: Icon(Icons.download, icon: Icon(
color: Color(0xFF114D8B), size: 18), Icons.download,
color: Color(0xFF114D8B),
size: 18,
),
onPressed: () { onPressed: () {
print("PDF- ${item['forex_id']}"); print("PDF- ${item['forex_id']}");
final forexIdString = item['forex_id']; final forexIdString = item['forex_id'];
@ -320,10 +382,8 @@ class ForexListWidget extends StatelessWidget {
: SizedBox.shrink(), // or Container() : SizedBox.shrink(), // or Container()
], ],
), ),
Divider( // Divider(color: Colors.blueGrey.shade50),
color: Colors.blueGrey.shade50, // SizedBox(height: 4),
),
SizedBox(height: 4),
isDesktop isDesktop
? Row( ? Row(
children: [ children: [
@ -331,26 +391,23 @@ class ForexListWidget extends StatelessWidget {
flex: 2, flex: 2,
child: Text( child: Text(
"Currency", "Currency",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Duration", " Duration",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Time Period ", " Time Period ",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
// Expanded( // Expanded(
// flex: 2, // flex: 2,
// child: Text( // child: Text(
@ -362,53 +419,48 @@ class ForexListWidget extends StatelessWidget {
flex: 2, flex: 2,
child: Text( child: Text(
" Perdiem ", " Perdiem ",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Others ", " Others ",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Total ", " Total ",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Cash ", " Cash ",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Card ", " Card ",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Comments", " Comments",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
], ],
) )
: SizedBox.shrink(), : SizedBox.shrink(),
SizedBox(height: 8),
isDesktop isDesktop
? Row( ? Row(
children: [ children: [
@ -503,85 +555,113 @@ class ForexListWidget extends StatelessWidget {
Expanded( Expanded(
flex: 2, flex: 2,
child: _buildComments( child: _buildComments(
"Comments:", item["comments"] ?? "N/A"), "Comments:",
item["comments"] ?? "N/A",
),
), ),
], ],
): Column( )
: Container(
color: Colors.white,
padding: const EdgeInsets.all(4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Top Row (Country, Currency, Total) _buildRow("Currency", item["currency"]),
Wrap( SizedBox(height: 2),
spacing: 20, // horizontal space between items _buildRow("Duration", item["duration"]),
runSpacing: 10, // vertical space between rows SizedBox(height: 2),
// Row( _buildRow(
// mainAxisAlignment: MainAxisAlignment.spaceBetween, "Time Period",
children: [ "${formatDate(item["start_date"]!)} - ${formatDate(item["end_date"]!)}",
_infoBlock("Country code", item["country_code"] ?? "N/A"), // "${item["start_date"]!} - ${item["end_date"]!}",
_infoBlock("Currency", item["currency"] ?? "N/A"), ),
_infoBlock("Total Amount", item["total_amount"]?.toString() ?? "0"), SizedBox(height: 2),
_buildRow("Perdiem", "$perdiemAmount"),
SizedBox(height: 2),
_buildRow("Others", "$calculatedOtherExpenses"),
SizedBox(height: 2),
_buildRow("Total", "$finalTotal"),
SizedBox(height: 2),
_buildRow("Cash", item["deposit_on_cash"]!),
SizedBox(height: 2),
_buildRow("Card", item["deposit_on_card"]!),
SizedBox(height: 2),
_buildRow("Comments", item["comments"] ?? "N/A"),
], ],
), ),
const SizedBox(height: 12),
// Second Row (Start Date, End Date, Duration)
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_infoBlock("Start Date", item["start_date"] ?? "N/A"),
_infoBlock("End Date", item["end_date"] ?? "N/A"),
_infoBlock("Duration", item["duration"]?.toString() ?? "N/A"),
],
), ),
const SizedBox(height: 16), // child: Column(
// Comment label
Text(
"Comment",
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty)
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
border: Border.all(color: const Color(0xFF7098DD), width: 1),
borderRadius: BorderRadius.circular(6),
),
child: Text(
item["comments"] ?? "N/A",
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
),
)
else
const Text( "N/A", style: TextStyle(fontSize: 12), ),
],
),
// old code
// : Column(
// crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
// children: [ // children: [
// _buildRow( // // Top Row (Country, Currency, Total)
// "Currency:", // Wrap(
// item["currency"], // spacing: 20, // horizontal space between items
// runSpacing: 10, // vertical space between rows
// // Row(
// // mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// _infoBlock(
// "Country code",
// item["country_code"] ?? "N/A",
// ), // ),
// // SizedBox(height: 6), // _infoBlock("Currency", item["currency"] ?? "N/A"),
// _buildRow( // _infoBlock(
// "Duration:", // "Total Amount",
// item["duration"], // item["total_amount"]?.toString() ?? "0",
// ), // ),
// // SizedBox(height: 6), // ],
// _buildRow("StartDate:", item["start_date"]!), // ),
// _buildRow("EndDate:", item["end_date"]!), // const SizedBox(height: 12),
// _buildRow("Perdiem:", "$perdiemAmount",), //
// _buildRow("Others:", "$calculatedOtherExpenses"), // // Second Row (Start Date, End Date, Duration)
// _buildRow("Total:", "$finalTotal"), // Row(
// _buildRow("Cash:", item["deposit_on_cash"]!), // mainAxisAlignment: MainAxisAlignment.spaceBetween,
// _buildRow("Card:", item["deposit_on_card"]!), // children: [
// _buildRow("Comments:", item["comments"] ?? "N/A"), // _infoBlock(
// "Start Date",
// item["start_date"] ?? "N/A",
// ),
// _infoBlock("End Date", item["end_date"] ?? "N/A"),
// _infoBlock(
// "Duration",
// item["duration"]?.toString() ?? "N/A",
// ),
// ],
// ),
// const SizedBox(height: 16),
//
// // Comment label
// Text(
// "Comment",
// style: GoogleFonts.poppins(
// fontSize: 14,
// fontWeight: FontWeight.w600,
// ),
// ),
// const SizedBox(height: 8),
// if (item["comments"] != null &&
// item["comments"].toString().trim().isNotEmpty)
// Container(
// width: double.infinity,
// padding: const EdgeInsets.all(12),
// decoration: BoxDecoration(
// border: Border.all(
// color: const Color(0xFF7098DD),
// width: 1,
// ),
// borderRadius: BorderRadius.circular(6),
// ),
// child: Text(
// item["comments"] ?? "N/A",
// style: GoogleFonts.poppins(
// fontSize: 12,
// color: Colors.black87,
// ),
// ),
// )
// else
// const Text("N/A", style: TextStyle(fontSize: 12)),
// ], // ],
// ), // ),
], ],
@ -612,23 +692,27 @@ class ForexListWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
child: exceedsLimit child:
exceedsLimit
? Tooltip( ? Tooltip(
message: wrapText(value, 50), message: wrapText(value, 50),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey.shade200, // Black background color: Colors.grey.shade200, // Black background
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
), ),
textStyle: textStyle: TextStyle(
TextStyle(color: Colors.black), // Tooltip text color color: Colors.black,
), // Tooltip text color
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
preferBelow: false, preferBelow: false,
child: Text(value.substring(0, limit) + "...", child: Text(
value.substring(0, limit) + "...",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
overflow: TextOverflow.ellipsis), overflow: TextOverflow.ellipsis,
),
) )
: Text( : Text(
value, value,
@ -660,10 +744,7 @@ class ForexListWidget extends StatelessWidget {
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
value, value,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
fontSize: 12,
color: Colors.black87,
),
), ),
], ],
), ),
@ -671,60 +752,59 @@ class ForexListWidget extends StatelessWidget {
); );
} }
// Widget _buildRow(String title, String value) { Widget _buildRow(String title, String value) {
// // Define character limits based on title // Define character limits based on title
// Map<String, int> limits = { Map<String, int> limits = {
// // "Special Request:": 30, // "Special Request:": 30,
// "Comments:": 10, "Comments:": 10,
// // Add more keys and limits if needed // Add more keys and limits if needed
// }; };
//
// int limit = limits[title] ?? 50; // Default limit if title not found
// bool exceedsLimit = value.length > limit;
//
// String wrapText(String text, int maxLineLength) {
// final pattern = RegExp('.{1,$maxLineLength}(\\s+|\$)');
// return pattern.allMatches(text).map((m) => m.group(0)!).join('\n');
// }
//
// return Row(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// title,
// style: GoogleFonts.poppins(
// fontSize: 12,
// fontWeight: FontWeight.w600,
// ),
// ),
// SizedBox(width: 8),
// Expanded(
// child: exceedsLimit
// ? Tooltip(
// message: wrapText(value, 50),
// decoration: BoxDecoration(
// color: Colors.grey.shade200, // Black background
// borderRadius: BorderRadius.circular(6),
// ),
// textStyle:
// TextStyle(color: Colors.black), // Tooltip text color
// padding: EdgeInsets.all(8),
// preferBelow: false,
// child: Text(value.substring(0, limit) + "...",
// style: GoogleFonts.poppins(
// fontSize: 12,
// ),
// overflow: TextOverflow.ellipsis),
// )
// : Text(
// value,
// style: GoogleFonts.poppins(
// fontSize: 12,
// ),
// ),
// ),
// ],
// );
// }
int limit = limits[title] ?? 50; // Default limit if title not found
bool exceedsLimit = value.length > limit;
String wrapText(String text, int maxLineLength) {
final pattern = RegExp('.{1,$maxLineLength}(\\s+|\$)');
return pattern.allMatches(text).map((m) => m.group(0)!).join('\n');
}
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 100,
child: Text(
title,
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
),
),
),
SizedBox(width: 8),
Expanded(
child:
exceedsLimit
? Tooltip(
message: wrapText(value, 50),
decoration: BoxDecoration(
color: Colors.grey.shade200, // Black background
borderRadius: BorderRadius.circular(6),
),
textStyle: TextStyle(
color: Colors.black,
), // Tooltip text color
padding: EdgeInsets.all(8),
preferBelow: false,
child: Text(
value.substring(0, limit) + "...",
style: GoogleFonts.poppins(fontSize: 12),
overflow: TextOverflow.ellipsis,
),
)
: Text(value, style: GoogleFonts.poppins(fontSize: 12)),
),
],
);
}
} }

View File

@ -4,7 +4,9 @@ import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
class InsuranceListWidget extends StatelessWidget { import '../../utils/auth_utils.dart';
class InsuranceListWidget extends StatefulWidget {
final List<Map<String, dynamic>> insuranceList; final List<Map<String, dynamic>> insuranceList;
final Function(bool, Map<String, dynamic>, String) onOpen; final Function(bool, Map<String, dynamic>, String) onOpen;
final Function(Map<String, dynamic>) onDeleteInsurance; final Function(Map<String, dynamic>) onDeleteInsurance;
@ -13,21 +15,67 @@ class InsuranceListWidget extends StatelessWidget {
final Function(String, bool) onAddNew; final Function(String, bool) onAddNew;
final bool isViewMode; final bool isViewMode;
const InsuranceListWidget( const InsuranceListWidget({
{super.key, super.key,
required this.insuranceList, required this.insuranceList,
required this.onOpen, required this.onOpen,
required this.apiData, required this.apiData,
required this.onDeleteInsurance, required this.onDeleteInsurance,
required this.onAddNew, required this.onAddNew,
required this.isViewMode}); required this.isViewMode,
});
@override
State<InsuranceListWidget> createState() => _InsuranceListWidgetState();
}
class _InsuranceListWidgetState extends State<InsuranceListWidget> {
Color? layoutColor;
Color? secondColor;
Color? thridColor;
@override
void initState() {
super.initState();
loadInitialData();
}
void loadInitialData() async {
String? layoutString = await getLayoutColor();
String? secondString = await getSecondaryColor();
String? thridString = await getTernaryColor();
// String? bodyStringColor = await getBodyColor();
setState(() {
layoutColor =
layoutString != null
? Color(int.parse(layoutString))
: Colors.redAccent;
secondColor =
layoutString != null
? Color(int.parse(secondString!))
: Colors.orange;
thridColor =
layoutString != null
? Color(int.parse(thridString!))
: Colors.orangeAccent;
// bodyColor =
// bodyStringColor != null
// ? Color(int.parse(bodyStringColor))
// : Colors.white;
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isDesktop = MediaQuery.of(context).size.width > 1024; final isDesktop = MediaQuery.of(context).size.width > 1024;
return Padding( return Padding(
padding: const EdgeInsets.all(16.0), padding:
isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0),
child: Container( child: Container(
margin: const EdgeInsets.only(top: 16.0), margin: const EdgeInsets.only(top: 16.0),
child: Column( child: Column(
@ -107,10 +155,10 @@ class InsuranceListWidget extends StatelessWidget {
// ), // ),
// ], // ],
// ), // ),
const SizedBox(height: 16), // const SizedBox(height: 16),
// Scroll behavior based on device
_buildData(context, isDesktop) // Scroll behavior based on device
_buildData(context, isDesktop),
], ],
), ),
), ),
@ -119,11 +167,11 @@ class InsuranceListWidget extends StatelessWidget {
Widget _buildData(BuildContext context, bool isDesktop) { Widget _buildData(BuildContext context, bool isDesktop) {
List<Map<String, dynamic>> filteredList = List<Map<String, dynamic>> filteredList =
insuranceList.where((item) => item["is_active"] == "1").toList(); widget.insuranceList.where((item) => item["is_active"] == "1").toList();
print("filteredList- $filteredList"); print("filteredList- $filteredList");
List<dynamic> insurancetypeList = List<dynamic> insurancetypeList =
apiData?['insurance_type_of_insurance'] ?? []; widget.apiData?['insurance_type_of_insurance'] ?? [];
String getRequestForInsuranceType(String? specialRequestKey) { String getRequestForInsuranceType(String? specialRequestKey) {
if (specialRequestKey == null) return "N/A"; if (specialRequestKey == null) return "N/A";
@ -146,7 +194,7 @@ class InsuranceListWidget extends StatelessWidget {
String getRequestValue(String? specialRequestKey) { String getRequestValue(String? specialRequestKey) {
if (specialRequestKey == null) return "N/A"; if (specialRequestKey == null) return "N/A";
return (apiData?['miscellaneous_special_request'] ?? []) return (widget.apiData?['miscellaneous_special_request'] ?? [])
.firstWhere( .firstWhere(
(element) => (element) =>
element["dropdown_key"].toString() == specialRequestKey, element["dropdown_key"].toString() == specialRequestKey,
@ -177,14 +225,18 @@ class InsuranceListWidget extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
// color: Colors.orange.shade50, // color: Colors.orange.shade50,
color: Colors.white, // color: Colors.white,
boxShadow: [ color: isDesktop ? Colors.white : thridColor,
boxShadow:
isDesktop
? [
BoxShadow( BoxShadow(
color: Colors.black12, color: Colors.black12,
blurRadius: 3, blurRadius: 3,
offset: Offset(0, 1), offset: Offset(0, 1),
), ),
], ]
: [],
border: Border( border: Border(
top: BorderSide( top: BorderSide(
color: Colors.white70, // Change color to match your theme color: Colors.white70, // Change color to match your theme
@ -193,54 +245,58 @@ class InsuranceListWidget extends StatelessWidget {
), ),
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(12), padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Text( Expanded(
getRequestForInsuranceType(item["type_of_insurance"]!.toString()), flex: 1,
child: Text(
getRequestForInsuranceType(
item["type_of_insurance"]!.toString(),
),
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w800, fontWeight:
color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) isDesktop ? FontWeight.w800 : FontWeight.w600,
color: !isDesktop ? Colors.black : Color(0xFF575A74),
),
), ),
), ),
Spacer(), Spacer(),
GestureDetector( GestureDetector(
onTap: () => onOpen(true, item, "Insurance"), onTap: () => widget.onOpen(true, item, "Insurance"),
child: Tooltip( child: Tooltip(
message: 'Edit Insurance Details', message: 'Edit Insurance Details',
child: Image.asset( child: Image.asset(
'assets/images/IconsImg/edit.png', 'assets/images/IconsImg/edit.png',
width: 20, width: 20,
height: 15, height: 15,
color: Color(0xFF114D8B), color: isDesktop ? Color(0xFF114D8B) : Colors.black,
),
),
),
SizedBox(width: 10),
GestureDetector(
onTap: () => widget.onDeleteInsurance(item),
child: Tooltip(
message: 'Delete Insurance Details',
child: Image.asset(
'assets/images/IconsImg/delete.png',
width: 20,
height: 15,
color: Colors.red,
), ),
), ),
), ),
// SizedBox(width: 10),
// GestureDetector(
// onTap: () => onDeleteInsurance(item),
// child: Tooltip(
// message: 'Delete Insurance Details',
// child: Image.asset(
// 'assets/images/IconsImg/delete.png',
// width: 20,
// height: 15,
// color: Colors.red,
// ),
// ),
// ),
], ],
), ),
SizedBox(height: 4), SizedBox(height: 4),
Divider( // Divider(color: Colors.blueGrey.shade50),
color: Colors.blueGrey.shade50, // SizedBox(height: 4),
),
SizedBox(height: 4),
isDesktop isDesktop
? Row( ? Row(
children: [ children: [
@ -248,29 +304,27 @@ class InsuranceListWidget extends StatelessWidget {
flex: 2, flex: 2,
child: Text( child: Text(
" InsuranceType", " InsuranceType",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Time Period ", " Time Period ",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Comments", " Comments",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
], ],
) )
: SizedBox.shrink(), : SizedBox.shrink(),
SizedBox(height: 8),
isDesktop isDesktop
? Row( ? Row(
children: [ children: [
@ -278,7 +332,8 @@ class InsuranceListWidget extends StatelessWidget {
flex: 2, flex: 2,
child: Text( child: Text(
getRequestForInsuranceType( getRequestForInsuranceType(
item["type_of_insurance"]!.toString()), item["type_of_insurance"]!.toString(),
),
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -300,67 +355,95 @@ class InsuranceListWidget extends StatelessWidget {
Expanded( Expanded(
flex: 2, flex: 2,
child: _buildComments( child: _buildComments(
"Comments:", item["comments"] ?? "N/A"), "Comments:",
),
],
)
:
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Top Row (Country, Currency, Total)
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
Wrap(
spacing: 20, // horizontal space between items
runSpacing: 10, // vertical space between rows
children: [
_infoBlock("Insurance Type", getRequestForInsuranceType(item["type_of_insurance"]!.toString()) ?? "N/A"),
_infoBlock("Start Date", formatDate(item["start_date"]!) ?? "N/A"),
_infoBlock("End Date", formatDate(item["end_date"]) ?? "N/A"),
],
),
const SizedBox(height: 16),
// Comment label
Text(
"Comment",
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty)
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
border: Border.all(color: const Color(0xFF7098DD), width: 1),
borderRadius: BorderRadius.circular(6),
),
child: Text(
item["comments"] ?? "N/A", item["comments"] ?? "N/A",
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
), ),
),
],
) )
else : Container(
const Text( "N/A", style: TextStyle(fontSize: 12), ), color: Colors.white,
padding: const EdgeInsets.all(4.0),
child: Column(
children: [
_buildRow(
"InsuranceType",
getRequestForInsuranceType(
item["type_of_insurance"]!.toString(),
),
),
SizedBox(width: 10),
_buildRow(
"TimePeriod",
'${formatDate(item["start_date"]!)} - ${formatDate(item["end_date"])} ',
),
SizedBox(width: 10),
_buildRow("Comments", item["comments"] ?? "N/A"),
], ],
), ),
),
// Column( // Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [ // children: [
// _buildRow( // // Top Row (Country, Currency, Total)
// "InsuranceType:", // // Row(
// // mainAxisAlignment: MainAxisAlignment.spaceBetween,
// Wrap(
// spacing: 20, // horizontal space between items
// runSpacing: 10, // vertical space between rows
// children: [
// _infoBlock(
// "Insurance Type",
// getRequestForInsuranceType( // getRequestForInsuranceType(
// item["type_of_insurance"]!.toString())), // item["type_of_insurance"]!.toString(),
// SizedBox(width: 10), // ) ??
// _buildRow( // "N/A",
// "StartDate:", formatDate(item["start_date"]!)), // ),
// SizedBox(width: 10), // _infoBlock(
// _buildRow("EndDate:", formatDate(item["end_date"])), // "Start Date",
// SizedBox(width: 10), // formatDate(item["start_date"]!) ?? "N/A",
// _buildRow("Comments:", item["comments"] ?? "N/A"), // ),
// _infoBlock(
// "End Date",
// formatDate(item["end_date"]) ?? "N/A",
// ),
// ],
// ),
// const SizedBox(height: 16),
//
// // Comment label
// Text(
// "Comment",
// style: GoogleFonts.poppins(
// fontSize: 14,
// fontWeight: FontWeight.w600,
// ),
// ),
// const SizedBox(height: 8),
// if (item["comments"] != null &&
// item["comments"].toString().trim().isNotEmpty)
// Container(
// width: double.infinity,
// padding: const EdgeInsets.all(12),
// decoration: BoxDecoration(
// border: Border.all(
// color: const Color(0xFF7098DD),
// width: 1,
// ),
// borderRadius: BorderRadius.circular(6),
// ),
// child: Text(
// item["comments"] ?? "N/A",
// style: GoogleFonts.poppins(
// fontSize: 12,
// color: Colors.black87,
// ),
// ),
// )
// else
// const Text("N/A", style: TextStyle(fontSize: 12)),
// ], // ],
// ), // ),
], ],
@ -391,23 +474,27 @@ class InsuranceListWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
child: exceedsLimit child:
exceedsLimit
? Tooltip( ? Tooltip(
message: wrapText(value, 50), message: wrapText(value, 50),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey.shade200, // Black background color: Colors.grey.shade200, // Black background
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
), ),
textStyle: textStyle: TextStyle(
TextStyle(color: Colors.black), // Tooltip text color color: Colors.black,
), // Tooltip text color
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
preferBelow: false, preferBelow: false,
child: Text(value.substring(0, limit) + "...", child: Text(
value.substring(0, limit) + "...",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
overflow: TextOverflow.ellipsis), overflow: TextOverflow.ellipsis,
),
) )
: Text( : Text(
value, value,
@ -439,16 +526,14 @@ class InsuranceListWidget extends StatelessWidget {
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
value, value,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
fontSize: 12,
color: Colors.black87,
),
), ),
], ],
), ),
), ),
); );
} }
Widget _buildRow(String title, String value) { Widget _buildRow(String title, String value) {
// Define character limits based on title // Define character limits based on title
Map<String, int> limits = { Map<String, int> limits = {
@ -468,16 +553,20 @@ class InsuranceListWidget extends StatelessWidget {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( SizedBox(
width: 100,
child: Text(
title, title,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
),
SizedBox(width: 8), SizedBox(width: 8),
Expanded( Expanded(
child: exceedsLimit child:
exceedsLimit
? Tooltip( ? Tooltip(
message: wrapText(value, 50), message: wrapText(value, 50),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -485,23 +574,18 @@ class InsuranceListWidget extends StatelessWidget {
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
), ),
textStyle: TextStyle( textStyle: TextStyle(
color: Colors.black, fontSize: 12), // Tooltip text color color: Colors.black,
fontSize: 12,
), // Tooltip text color
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
preferBelow: false, preferBelow: false,
child: Text( child: Text(
value.substring(0, limit) + "...", value.substring(0, limit) + "...",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 12),
fontSize: 12,
),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
) )
: Text( : Text(value, style: GoogleFonts.poppins(fontSize: 12)),
value,
style: GoogleFonts.poppins(
fontSize: 12,
),
),
), ),
], ],
); );
@ -509,11 +593,11 @@ class InsuranceListWidget extends StatelessWidget {
List<DataRow> _buildDataRows() { List<DataRow> _buildDataRows() {
List<Map<String, dynamic>> filteredList = List<Map<String, dynamic>> filteredList =
insuranceList.where((item) => item["is_active"] == "1").toList(); widget.insuranceList.where((item) => item["is_active"] == "1").toList();
print("filteredList- $filteredList"); print("filteredList- $filteredList");
List<dynamic> insurancetypeList = List<dynamic> insurancetypeList =
apiData?['insurance_type_of_insurance'] ?? []; widget.apiData?['insurance_type_of_insurance'] ?? [];
String getRequestForInsuranceType(String? specialRequestKey) { String getRequestForInsuranceType(String? specialRequestKey) {
if (specialRequestKey == null) return "N/A"; if (specialRequestKey == null) return "N/A";
@ -529,17 +613,22 @@ class InsuranceListWidget extends StatelessWidget {
return filteredList.asMap().entries.map((entry) { return filteredList.asMap().entries.map((entry) {
Map<String, dynamic> item = entry.value; Map<String, dynamic> item = entry.value;
return DataRow(cells: [ return DataRow(
cells: [
// DataCell(Text(item["indx"]?.toString() ?? "N/A")), // Index column // DataCell(Text(item["indx"]?.toString() ?? "N/A")), // Index column
// DataCell(Text(item["type_of_insurance"]!)), // DataCell(Text(item["type_of_insurance"]!)),
DataCell(Text( DataCell(
getRequestForInsuranceType(item["type_of_insurance"]!.toString()))), Text(
getRequestForInsuranceType(item["type_of_insurance"]!.toString()),
),
),
DataCell(Text(item["start_date"]!)), DataCell(Text(item["start_date"]!)),
DataCell(Text(item["end_date"]!)), DataCell(Text(item["end_date"]!)),
DataCell(Row( DataCell(
Row(
children: [ children: [
GestureDetector( GestureDetector(
onTap: () => onOpen(true, item, "Insurance"), onTap: () => widget.onOpen(true, item, "Insurance"),
child: Tooltip( child: Tooltip(
message: 'Edit Insurance Details', message: 'Edit Insurance Details',
child: Image.asset( child: Image.asset(
@ -551,7 +640,7 @@ class InsuranceListWidget extends StatelessWidget {
), ),
SizedBox(width: 10), SizedBox(width: 10),
GestureDetector( GestureDetector(
onTap: () => onDeleteInsurance(item), onTap: () => widget.onDeleteInsurance(item),
child: Tooltip( child: Tooltip(
message: 'Delete Insurance Details', message: 'Delete Insurance Details',
child: Image.asset( child: Image.asset(
@ -562,14 +651,17 @@ class InsuranceListWidget extends StatelessWidget {
), ),
), ),
IconButton( IconButton(
icon: Icon(Icons.keyboard_arrow_down_outlined, icon: Icon(
size: 28, color: Color(0xFF475569)), Icons.keyboard_arrow_down_outlined,
size: 28,
color: Color(0xFF475569),
),
onPressed: () { onPressed: () {
// Expand logic // Expand logic
}, },
), ),
], ],
) ),
// Row( // Row(
// children: [ // children: [
@ -593,9 +685,9 @@ class InsuranceListWidget extends StatelessWidget {
// ), // ),
// ], // ],
// ) // )
), ),
]); ],
);
}).toList(); }).toList();
} }
} }

View File

@ -1,7 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
class MiscellaneousListWidget extends StatelessWidget { import '../../utils/auth_utils.dart';
class MiscellaneousListWidget extends StatefulWidget {
final List<Map<String, dynamic>> miscellaneousList; final List<Map<String, dynamic>> miscellaneousList;
final Function(bool, Map<String, dynamic>, String) onOpen; final Function(bool, Map<String, dynamic>, String) onOpen;
final Function(Map<String, dynamic>) onDeleteMiscellaneous; final Function(Map<String, dynamic>) onDeleteMiscellaneous;
@ -19,12 +21,58 @@ class MiscellaneousListWidget extends StatelessWidget {
required this.isViewMode, required this.isViewMode,
}); });
@override
State<MiscellaneousListWidget> createState() =>
_MiscellaneousListWidgetState();
}
class _MiscellaneousListWidgetState extends State<MiscellaneousListWidget> {
Color? layoutColor;
Color? secondColor;
Color? thridColor;
@override
void initState() {
super.initState();
loadInitialData();
}
void loadInitialData() async {
String? layoutString = await getLayoutColor();
String? secondString = await getSecondaryColor();
String? thridString = await getTernaryColor();
// String? bodyStringColor = await getBodyColor();
setState(() {
layoutColor =
layoutString != null
? Color(int.parse(layoutString))
: Colors.redAccent;
secondColor =
layoutString != null
? Color(int.parse(secondString!))
: Colors.orange;
thridColor =
layoutString != null
? Color(int.parse(thridString!))
: Colors.orangeAccent;
// bodyColor =
// bodyStringColor != null
// ? Color(int.parse(bodyStringColor))
// : Colors.white;
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isDesktop = MediaQuery.of(context).size.width > 1024; final isDesktop = MediaQuery.of(context).size.width > 1024;
return Padding( return Padding(
padding: const EdgeInsets.all(16.0), padding:
isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0),
child: Container( child: Container(
margin: const EdgeInsets.only(top: 16.0), margin: const EdgeInsets.only(top: 16.0),
child: Column( child: Column(
@ -34,7 +82,7 @@ class MiscellaneousListWidget extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
if ((!isDesktop) && miscellaneousList.isNotEmpty) if ((!isDesktop) && widget.miscellaneousList.isNotEmpty)
Text( Text(
" ", " ",
style: const TextStyle( style: const TextStyle(
@ -44,16 +92,16 @@ class MiscellaneousListWidget extends StatelessWidget {
), ),
MouseRegion( MouseRegion(
cursor: cursor:
isViewMode widget.isViewMode
? SystemMouseCursors.forbidden ? SystemMouseCursors.forbidden
: SystemMouseCursors.click, : SystemMouseCursors.click,
child: GestureDetector( child: GestureDetector(
onTap: onTap:
isViewMode widget.isViewMode
? null ? null
: () { : () {
print("New data"); print("New data");
onAddNew("Miscellaneous", true); widget.onAddNew("Miscellaneous", true);
}, },
child: Row( child: Row(
mainAxisSize: mainAxisSize:
@ -133,7 +181,9 @@ class MiscellaneousListWidget extends StatelessWidget {
Widget _buildData(BuildContext context, bool isDesktop) { Widget _buildData(BuildContext context, bool isDesktop) {
List<Map<String, dynamic>> filteredList = List<Map<String, dynamic>> filteredList =
miscellaneousList.where((item) => item["is_active"] == "1").toList(); widget.miscellaneousList
.where((item) => item["is_active"] == "1")
.toList();
return ListView.builder( return ListView.builder(
shrinkWrap: true, shrinkWrap: true,
@ -144,7 +194,7 @@ class MiscellaneousListWidget extends StatelessWidget {
String getRequestValue(String? specialRequestKey) { String getRequestValue(String? specialRequestKey) {
if (specialRequestKey == null) return "N/A"; if (specialRequestKey == null) return "N/A";
return (apiData?['miscellaneous_special_request'] ?? []) return (widget.apiData?['miscellaneous_special_request'] ?? [])
.firstWhere( .firstWhere(
(element) => (element) =>
element["dropdown_key"].toString() == specialRequestKey, element["dropdown_key"].toString() == specialRequestKey,
@ -158,14 +208,17 @@ class MiscellaneousListWidget extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
// color: Colors.yellow.shade50, // color: Colors.yellow.shade50,
color: Colors.white, color: isDesktop ? Colors.white : thridColor,
boxShadow: [ boxShadow:
isDesktop
? [
BoxShadow( BoxShadow(
color: Colors.black12, color: Colors.black12,
blurRadius: 3, blurRadius: 3,
offset: Offset(0, 1), offset: Offset(0, 1),
), ),
], ]
: [],
border: Border( border: Border(
top: BorderSide( top: BorderSide(
color: Colors.white70, // Change color to match your theme color: Colors.white70, // Change color to match your theme
@ -174,7 +227,7 @@ class MiscellaneousListWidget extends StatelessWidget {
), ),
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(12), padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -185,26 +238,28 @@ class MiscellaneousListWidget extends StatelessWidget {
getRequestValue(item["special_request"]?.toString()), getRequestValue(item["special_request"]?.toString()),
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w800, fontWeight:
isDesktop ? FontWeight.w800 : FontWeight.w600,
color: !isDesktop ? Colors.black : Color(0xFF575A74),
), ),
), ),
Spacer(), Spacer(),
GestureDetector( GestureDetector(
onTap: () => onOpen(true, item, "Miscellaneous"), onTap: () => widget.onOpen(true, item, "Miscellaneous"),
child: Tooltip( child: Tooltip(
message: 'Edit Miscellaneous Details', message: 'Edit Miscellaneous Details',
child: Image.asset( child: Image.asset(
'assets/images/IconsImg/edit.png', 'assets/images/IconsImg/edit.png',
width: 20, width: 20,
height: 15, height: 15,
color: Color(0xFF114D8B), color: isDesktop ? Color(0xFF114D8B) : Colors.black,
), ),
), ),
), ),
SizedBox(width: 10), SizedBox(width: 10),
GestureDetector( GestureDetector(
// onTap: () => onOpen(true, item, "Miscellaneous"), // onTap: () => onOpen(true, item, "Miscellaneous"),
onTap: () => onDeleteMiscellaneous(item), onTap: () => widget.onDeleteMiscellaneous(item),
child: Tooltip( child: Tooltip(
message: 'Delete Miscellaneous Details', message: 'Delete Miscellaneous Details',
child: Image.asset( child: Image.asset(
@ -217,7 +272,7 @@ class MiscellaneousListWidget extends StatelessWidget {
), ),
], ],
), ),
Divider(color: Colors.blueGrey.shade50), // Divider(color: Colors.blueGrey.shade50),
SizedBox(height: 4), SizedBox(height: 4),
isDesktop isDesktop
? Row( ? Row(
@ -238,74 +293,49 @@ class MiscellaneousListWidget extends StatelessWidget {
), ),
], ],
) )
// : SizedBox.shrink(), : SizedBox.shrink(),
// isDesktop SizedBox(height: 8),
// ? Row( isDesktop
// children: [ ? Row(
// Expanded(
// flex: 2,
// child: Text(
// getRequestValue(
// item["special_request"]?.toString(),
// ),
// style: GoogleFonts.poppins(
// fontSize: 12,
// fontWeight: FontWeight.w600,
// ),
// ),
// ),
// Expanded(
// flex: 3,
// child: Text(
// item["comments"],
// style: GoogleFonts.poppins(
// fontSize: 12,
// fontWeight: FontWeight.w600,
// ),
// ),
// ),
// ],
// )
:
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Comment label Expanded(
Text( flex: 2,
"Comment", child: Text(
getRequestValue(
item["special_request"]?.toString(),
),
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 14, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
const SizedBox(height: 8),
if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty)
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
border: Border.all(color: const Color(0xFF7098DD), width: 1),
borderRadius: BorderRadius.circular(6),
), ),
Expanded(
flex: 3,
child: Text( child: Text(
item["comments"] ?? "N/A", item["comments"],
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87), style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
),
),
), ),
)
else
const Text( "N/A", style: TextStyle(fontSize: 12), ),
], ],
), )
// Column( : Container(
// children: [ color: Colors.white,
padding: const EdgeInsets.all(4.0),
child: Column(
children: [
// _buildRow( // _buildRow(
// "Special Request:", // "Special Request",
// getRequestValue(item["special_request"]?.toString()), // getRequestValue(item["special_request"]?.toString()),
// ), // ),
// SizedBox(width: 10), SizedBox(width: 10),
// _buildRow("Comments:", item["comments"] ?? "N/A"), _buildRow("Comments", item["comments"] ?? "N/A"),
// ], ],
// ), ),
),
], ],
), ),
), ),
@ -387,9 +417,15 @@ class MiscellaneousListWidget extends StatelessWidget {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( SizedBox(
width: 100,
child: Text(
title, title,
style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600), style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
),
),
), ),
SizedBox(width: 8), SizedBox(width: 8),
Expanded( Expanded(

View File

@ -2,7 +2,9 @@ import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
class TaxiListWidget extends StatelessWidget { import '../../utils/auth_utils.dart';
class TaxiListWidget extends StatefulWidget {
final List<Map<String, dynamic>> taxiList; final List<Map<String, dynamic>> taxiList;
final Function(bool, Map<String, dynamic>, String) onOpen; final Function(bool, Map<String, dynamic>, String) onOpen;
final Function(Map<String, dynamic>) onDeleteTaxi; final Function(Map<String, dynamic>) onDeleteTaxi;
@ -21,12 +23,57 @@ class TaxiListWidget extends StatelessWidget {
required this.isViewMode, required this.isViewMode,
}); });
@override
State<TaxiListWidget> createState() => _TaxiListWidgetState();
}
class _TaxiListWidgetState extends State<TaxiListWidget> {
Color? layoutColor;
Color? secondColor;
Color? thridColor;
@override
void initState() {
super.initState();
loadInitialData();
}
void loadInitialData() async {
String? layoutString = await getLayoutColor();
String? secondString = await getSecondaryColor();
String? thridString = await getTernaryColor();
// String? bodyStringColor = await getBodyColor();
setState(() {
layoutColor =
layoutString != null
? Color(int.parse(layoutString))
: Colors.redAccent;
secondColor =
layoutString != null
? Color(int.parse(secondString!))
: Colors.orange;
thridColor =
layoutString != null
? Color(int.parse(thridString!))
: Colors.orangeAccent;
// bodyColor =
// bodyStringColor != null
// ? Color(int.parse(bodyStringColor))
// : Colors.white;
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isDesktop = MediaQuery.of(context).size.width > 1024; final isDesktop = MediaQuery.of(context).size.width > 1024;
return Padding( return Padding(
padding: const EdgeInsets.all(16.0), padding:
isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0),
child: Container( child: Container(
margin: const EdgeInsets.only(top: 16.0), margin: const EdgeInsets.only(top: 16.0),
child: Column( child: Column(
@ -36,7 +83,7 @@ class TaxiListWidget extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
if ((!isDesktop) && taxiList.isNotEmpty) if ((!isDesktop) && widget.taxiList.isNotEmpty)
Text( Text(
" ", " ",
style: const TextStyle( style: const TextStyle(
@ -46,17 +93,17 @@ class TaxiListWidget extends StatelessWidget {
), ),
MouseRegion( MouseRegion(
cursor: cursor:
isViewMode widget.isViewMode
? SystemMouseCursors.forbidden ? SystemMouseCursors.forbidden
: SystemMouseCursors.click, : SystemMouseCursors.click,
child: GestureDetector( child: GestureDetector(
onTap: onTap:
isViewMode widget.isViewMode
? null ? null
: () { : () {
print("New data"); print("New data");
onAddNew("Taxi", true); widget.onAddNew("Taxi", true);
}, },
child: Row( child: Row(
mainAxisSize: mainAxisSize:
@ -121,11 +168,12 @@ class TaxiListWidget extends StatelessWidget {
Widget _buildData(BuildContext context, bool isDesktop) { Widget _buildData(BuildContext context, bool isDesktop) {
List<Map<String, dynamic>> filteredList = List<Map<String, dynamic>> filteredList =
taxiList.where((item) => item["is_active"] == "1").toList(); widget.taxiList.where((item) => item["is_active"] == "1").toList();
print("filteredList- $filteredList"); print("filteredList- $filteredList");
List<dynamic> taxiClassList = apiData?['taxt_car_type'] ?? []; List<dynamic> taxiClassList = widget.apiData?['taxt_car_type'] ?? [];
List<dynamic> taxirequiredFor = apiData?['taxi_car_required_for'] ?? []; List<dynamic> taxirequiredFor =
widget.apiData?['taxi_car_required_for'] ?? [];
String getRequestForTaxiClass(String? specialRequestKey) { String getRequestForTaxiClass(String? specialRequestKey) {
if (specialRequestKey == null) return "N/A"; if (specialRequestKey == null) return "N/A";
@ -228,14 +276,17 @@ class TaxiListWidget extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
// color: Colors.orange.shade50, // color: Colors.orange.shade50,
color: Colors.white, color: isDesktop ? Colors.white : thridColor,
boxShadow: [ boxShadow:
isDesktop
? [
BoxShadow( BoxShadow(
color: Colors.black12, color: Colors.black12,
blurRadius: 3, blurRadius: 3,
offset: Offset(0, 1), offset: Offset(0, 1),
), ),
], ]
: [],
border: Border( border: Border(
top: BorderSide( top: BorderSide(
color: Colors.white70, // Change color to match your theme color: Colors.white70, // Change color to match your theme
@ -244,37 +295,41 @@ class TaxiListWidget extends StatelessWidget {
), ),
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(12), padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Text( Expanded(
flex: 1,
child: Text(
"${getRequestForTaxiClass(item["car_type"]!.toString())} For ${item["no_of_passengers"]!} Passenger", "${getRequestForTaxiClass(item["car_type"]!.toString())} For ${item["no_of_passengers"]!} Passenger",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w800, fontWeight:
color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) isDesktop ? FontWeight.w800 : FontWeight.w600,
color: !isDesktop ? Colors.black : Color(0xFF575A74),
),
), ),
), ),
Spacer(), Spacer(),
GestureDetector( GestureDetector(
onTap: () => onOpen(true, item, "Taxi"), onTap: () => widget.onOpen(true, item, "Taxi"),
child: Tooltip( child: Tooltip(
message: 'Edit Taxi Details', message: 'Edit Taxi Details',
child: Image.asset( child: Image.asset(
'assets/images/IconsImg/edit.png', 'assets/images/IconsImg/edit.png',
width: 20, width: 20,
height: 15, height: 15,
color: Color(0xFF114D8B), color: isDesktop ? Color(0xFF114D8B) : Colors.black,
), ),
), ),
), ),
SizedBox(width: 10), SizedBox(width: 10),
GestureDetector( GestureDetector(
onTap: () => onDeleteTaxi(item), onTap: () => widget.onDeleteTaxi(item),
child: Tooltip( child: Tooltip(
message: 'Delete Taxi Details', message: 'Delete Taxi Details',
child: Image.asset( child: Image.asset(
@ -287,7 +342,7 @@ class TaxiListWidget extends StatelessWidget {
), ),
], ],
), ),
Divider(color: Colors.blueGrey.shade50), // Divider(color: Colors.blueGrey.shade50),
SizedBox(height: 4), SizedBox(height: 4),
isDesktop isDesktop
? Row( ? Row(
@ -323,7 +378,8 @@ class TaxiListWidget extends StatelessWidget {
], ],
) )
: SizedBox.shrink(), : SizedBox.shrink(),
SizedBox(height: 4), SizedBox(height: 8),
isDesktop isDesktop
? Row( ? Row(
children: [ children: [
@ -369,72 +425,75 @@ class TaxiListWidget extends StatelessWidget {
), ),
], ],
) )
: : Container(
Column( color: Colors.white,
padding: const EdgeInsets.all(4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// First row: City & Location _buildRow("City", item["destination_city"]),
Row( SizedBox(width: 10),
mainAxisAlignment: MainAxisAlignment.spaceBetween, _buildRow("Location", item["location_of_pickup"]!),
children: [ SizedBox(width: 10),
_infoColumn("City", item["destination_city"] ?? "N/A"), _buildDateTimeRow(
_infoColumn("Location", item["location_of_pickup"] ?? "N/A",alignEnd: true), "Date",
formatDate(item["date"]!),
formatTime(item["time"]!),
),
_buildRow("Comments", item["comments"] ?? "N/A"),
], ],
), ),
const SizedBox(height: 16),
// Second row: Date & Time
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_infoColumn("Date", "${formatDate(item["date"]!)}" ?? "N/A"),
_infoColumn("Time", "${formatTime(item["time"]!)}" ?? "N/A",alignEnd: true),
],
),
const SizedBox(height: 16),
// Comment label
Text(
"Comment",
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
// Comment box
if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty)
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
border: Border.all(color: const Color(0xFF7098DD), width: 1),
borderRadius: BorderRadius.circular(6),
),
child: Text(
item["comments"] ?? "N/A",
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
),
)else const Text( "N/A", style: TextStyle(fontSize: 12), ),
] )
// Column( // Column(
// crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
// children: [ // children: [
// _buildRow("City:", item["destination_city"]), // // First row: City & Location
// SizedBox(width: 10), // Row(
// _buildRow("Pickup:", item["location_of_pickup"]!), // mainAxisAlignment: MainAxisAlignment.spaceBetween,
// SizedBox(width: 10), // children: [
// _buildDateTimeRow( // _infoColumn("City", item["destination_city"] ?? "N/A"),
// "Date:", // _infoColumn("Location", item["location_of_pickup"] ?? "N/A",alignEnd: true),
// formatDate(item["date"]!),
// formatTime(item["time"]!),
// ),
// _buildRow("TaxiFor:", item["car_required_for"]!),
// _buildRow("Comments:", item["comments"] ?? "N/A"),
// ], // ],
// ), // ),
// const SizedBox(height: 16),
//
// // Second row: Date & Time
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// _infoColumn("Date", "${formatDate(item["date"]!)}" ?? "N/A"),
// _infoColumn("Time", "${formatTime(item["time"]!)}" ?? "N/A",alignEnd: true),
// ],
// ),
// const SizedBox(height: 16),
//
// // Comment label
// Text(
// "Comment",
// style: GoogleFonts.poppins(
// fontSize: 14,
// fontWeight: FontWeight.w600,
// ),
// ),
// const SizedBox(height: 8),
//
// // Comment box
// if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty)
// Container(
// width: double.infinity,
// padding: const EdgeInsets.all(12),
// decoration: BoxDecoration(
// border: Border.all(color: const Color(0xFF7098DD), width: 1),
// borderRadius: BorderRadius.circular(6),
// ),
// child: Text(
// item["comments"] ?? "N/A",
// style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
// ),
// )else const Text( "N/A", style: TextStyle(fontSize: 12), ),
//
// ] ),
),
], ],
), ),
), ),
@ -516,10 +575,13 @@ class TaxiListWidget extends StatelessWidget {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( SizedBox(
width: 100,
child: Text(
title, title,
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 12), style: TextStyle(fontWeight: FontWeight.w600, fontSize: 12),
), ),
),
SizedBox(width: 8), SizedBox(width: 8),
Expanded( Expanded(
child: child:
@ -551,9 +613,15 @@ class TaxiListWidget extends StatelessWidget {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( SizedBox(
width: 100,
child: Text(
title, title,
style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600), style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
),
),
), ),
SizedBox(width: 8), SizedBox(width: 8),
Expanded( Expanded(
@ -562,6 +630,7 @@ class TaxiListWidget extends StatelessWidget {
], ],
); );
} }
Widget _infoColumn(String label, String value, {bool alignEnd = false}) { Widget _infoColumn(String label, String value, {bool alignEnd = false}) {
return Column( return Column(
// crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
@ -579,13 +648,9 @@ class TaxiListWidget extends StatelessWidget {
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
value, value,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
fontSize: 12,
color: Colors.black87,
),
), ),
], ],
); );
} }
} }

View File

@ -3,6 +3,7 @@ import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import '../../services/apiService.dart'; import '../../services/apiService.dart';
import '../../utils/auth_utils.dart';
class TrainListWidget extends StatefulWidget { class TrainListWidget extends StatefulWidget {
final bool hasAction; final bool hasAction;
@ -36,12 +37,46 @@ class _TrainListWidgetState extends State<TrainListWidget> {
// late Map<String, String> countryMap; // late Map<String, String> countryMap;
Map<String, String> countryMap = {}; Map<String, String> countryMap = {};
Color? layoutColor;
Color? secondColor;
Color? thridColor;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
loadInitialData();
loadCountryList(); // Call your method here loadCountryList(); // Call your method here
} }
void loadInitialData() async {
String? layoutString = await getLayoutColor();
String? secondString = await getSecondaryColor();
String? thridString = await getTernaryColor();
// String? bodyStringColor = await getBodyColor();
setState(() {
layoutColor =
layoutString != null
? Color(int.parse(layoutString))
: Colors.redAccent;
secondColor =
layoutString != null
? Color(int.parse(secondString!))
: Colors.orange;
thridColor =
layoutString != null
? Color(int.parse(thridString!))
: Colors.orangeAccent;
// bodyColor =
// bodyStringColor != null
// ? Color(int.parse(bodyStringColor))
// : Colors.white;
});
}
void checkClass() { void checkClass() {
if (widget.hasAction) { if (widget.hasAction) {
if (widget.tripType?.isNotEmpty == true) { if (widget.tripType?.isNotEmpty == true) {
@ -99,7 +134,8 @@ class _TrainListWidgetState extends State<TrainListWidget> {
final isDesktop = MediaQuery.of(context).size.width > 1024; final isDesktop = MediaQuery.of(context).size.width > 1024;
return Padding( return Padding(
padding: const EdgeInsets.all(16.0), padding:
isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0),
child: Container( child: Container(
margin: const EdgeInsets.only(top: 16.0), margin: const EdgeInsets.only(top: 16.0),
child: Column( child: Column(
@ -315,14 +351,17 @@ class _TrainListWidgetState extends State<TrainListWidget> {
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
// color: Colors.orange.shade50, // color: Colors.orange.shade50,
color: Colors.white, color: isDesktop ? Colors.white : thridColor,
boxShadow: [ boxShadow:
isDesktop
? [
BoxShadow( BoxShadow(
color: Colors.black12, color: Colors.black12,
blurRadius: 3, blurRadius: 3,
offset: Offset(0, 1), offset: Offset(0, 1),
), ),
], ]
: [],
border: Border( border: Border(
top: BorderSide( top: BorderSide(
color: Colors.white70, // Change color to match your theme color: Colors.white70, // Change color to match your theme
@ -331,7 +370,7 @@ class _TrainListWidgetState extends State<TrainListWidget> {
), ),
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(12), padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -343,7 +382,8 @@ class _TrainListWidgetState extends State<TrainListWidget> {
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) color:
!isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74),
), ),
), ),
Spacer(), Spacer(),
@ -355,7 +395,7 @@ class _TrainListWidgetState extends State<TrainListWidget> {
'assets/images/IconsImg/edit.png', 'assets/images/IconsImg/edit.png',
width: 20, width: 20,
height: 15, height: 15,
color: Color(0xFF114D8B), color: isDesktop ? Color(0xFF114D8B) : Colors.black,
), ),
), ),
), ),
@ -374,7 +414,7 @@ class _TrainListWidgetState extends State<TrainListWidget> {
), ),
], ],
), ),
Divider(color: Colors.blueGrey.shade50), // Divider(color: Colors.blueGrey.shade50),
SizedBox(height: 4), SizedBox(height: 4),
isDesktop isDesktop
? Row( ? Row(
@ -410,7 +450,7 @@ class _TrainListWidgetState extends State<TrainListWidget> {
], ],
) )
: SizedBox.shrink(), : SizedBox.shrink(),
SizedBox(height: 4), SizedBox(height: 8),
isDesktop isDesktop
? Row( ? Row(
children: [ children: [
@ -539,72 +579,102 @@ class _TrainListWidgetState extends State<TrainListWidget> {
), ),
], ],
) )
: : Container(
Column( color: Colors.white,
padding: const EdgeInsets.all(4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// First row: City & Location _buildRow(
Row( "Class",
mainAxisAlignment: MainAxisAlignment.spaceBetween, getRequestForTrainClass(item["class"]!.toString()),
children: [ ),
_infoColumn("Class", getRequestForTrainClass(item["class"]!.toString()) ?? "N/A"), _buildRow("From", item["from_station"]!),
_infoColumn("From", item["from_station"]! ?? "N/A"), _buildRow("To", item["to_station"]!),
_infoColumn("To", item["to_station"]! ?? "N/A",alignEnd: true), _buildDateTimeRow(
"Date",
formatDate(item["date"]!),
formatTime(item["time"]!),
),
_buildRow("Comments", item["comments"] ?? "N/A"),
], ],
), ),
const SizedBox(height: 16), ),
// Second row: Date & Time
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_infoColumn("Date", "${formatDate(item["date"]!)}" ?? "N/A"),
_infoColumn("Time", "${formatTime(item["time"]!)}" ?? "N/A",alignEnd: true),
],
),
const SizedBox(height: 16),
// Comment label
Text(
"Comment",
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
// Comment box
if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty)
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
border: Border.all(color: const Color(0xFF7098DD), width: 1),
borderRadius: BorderRadius.circular(6),
),
child: Text(
item["comments"] ?? "N/A",
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
),
)else const Text( "N/A", style: TextStyle(fontSize: 12), ),
] )
// Column( // Column(
// crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
// children: [ // children: [
// _buildRow( // // First row: City & Location
// "Class:", // Row(
// getRequestForTrainClass(item["class"]!.toString()), // mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// _infoColumn(
// "Class",
// getRequestForTrainClass(
// item["class"]!.toString(),
// ) ??
// "N/A",
// ), // ),
// _buildRow("From:", item["from_station"]!), // _infoColumn("From", item["from_station"]! ?? "N/A"),
// _buildRow("To:", item["to_station"]!), // _infoColumn(
// _buildDateTimeRow( // "To",
// "Date:", // item["to_station"]! ?? "N/A",
// formatDate(item["date"]!), // alignEnd: true,
// formatTime(item["time"]!),
// ), // ),
// _buildRow("Comments:", item["comments"] ?? "N/A"), // ],
// ),
// const SizedBox(height: 16),
//
// // Second row: Date & Time
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// _infoColumn(
// "Date",
// "${formatDate(item["date"]!)}" ?? "N/A",
// ),
// _infoColumn(
// "Time",
// "${formatTime(item["time"]!)}" ?? "N/A",
// alignEnd: true,
// ),
// ],
// ),
// const SizedBox(height: 16),
//
// // Comment label
// Text(
// "Comment",
// style: GoogleFonts.poppins(
// fontSize: 14,
// fontWeight: FontWeight.w600,
// ),
// ),
// const SizedBox(height: 8),
//
// // Comment box
// if (item["comments"] != null &&
// item["comments"].toString().trim().isNotEmpty)
// Container(
// width: double.infinity,
// padding: const EdgeInsets.all(12),
// decoration: BoxDecoration(
// border: Border.all(
// color: const Color(0xFF7098DD),
// width: 1,
// ),
// borderRadius: BorderRadius.circular(6),
// ),
// child: Text(
// item["comments"] ?? "N/A",
// style: GoogleFonts.poppins(
// fontSize: 12,
// color: Colors.black87,
// ),
// ),
// )
// else
// const Text("N/A", style: TextStyle(fontSize: 12)),
// ], // ],
// ), // ),
], ],
@ -690,9 +760,15 @@ class _TrainListWidgetState extends State<TrainListWidget> {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( SizedBox(
width: 100,
child: Text(
title, title,
style: GoogleFonts.poppins(fontSize: 12, fontWeight: FontWeight.w600), style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
),
),
), ),
SizedBox(width: 8), SizedBox(width: 8),
Expanded( Expanded(
@ -738,22 +814,23 @@ class _TrainListWidgetState extends State<TrainListWidget> {
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
value, value,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
fontSize: 12,
color: Colors.black87,
),
), ),
], ],
); );
} }
Widget _buildDateTimeRow(String title, String date, String time) { Widget _buildDateTimeRow(String title, String date, String time) {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( SizedBox(
width: 100,
child: Text(
title, title,
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 12), style: TextStyle(fontWeight: FontWeight.w600, fontSize: 12),
), ),
),
SizedBox(width: 8), SizedBox(width: 8),
Expanded(child: Text("$date, $time", style: TextStyle(fontSize: 12))), Expanded(child: Text("$date, $time", style: TextStyle(fontSize: 12))),
], ],

View File

@ -2,7 +2,9 @@ import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
class VisaListWidget extends StatelessWidget { import '../../utils/auth_utils.dart';
class VisaListWidget extends StatefulWidget {
final List<Map<String, dynamic>> visaList; final List<Map<String, dynamic>> visaList;
final Function(bool, Map<String, dynamic>, String) onOpen; final Function(bool, Map<String, dynamic>, String) onOpen;
final Function(Map<String, dynamic>) onDeleteMiscellaneous; final Function(Map<String, dynamic>) onDeleteMiscellaneous;
@ -12,91 +14,138 @@ class VisaListWidget extends StatelessWidget {
final Function(String, bool) onAddNew; final Function(String, bool) onAddNew;
final bool isViewMode; final bool isViewMode;
const VisaListWidget( const VisaListWidget({
{super.key, super.key,
required this.visaList, required this.visaList,
required this.onOpen, required this.onOpen,
required this.onDeleteMiscellaneous, required this.onDeleteMiscellaneous,
required this.apiData, required this.apiData,
required this.apiCountryData, required this.apiCountryData,
required this.onAddNew, required this.onAddNew,
required this.isViewMode}); required this.isViewMode,
});
State<VisaListWidget> createState() => _VisaListWidgetState();
}
class _VisaListWidgetState extends State<VisaListWidget> {
Color? layoutColor;
Color? secondColor;
Color? thridColor;
@override
void initState() {
super.initState();
loadInitialData();
}
void loadInitialData() async {
String? layoutString = await getLayoutColor();
String? secondString = await getSecondaryColor();
String? thridString = await getTernaryColor();
// String? bodyStringColor = await getBodyColor();
setState(() {
layoutColor =
layoutString != null
? Color(int.parse(layoutString))
: Colors.redAccent;
secondColor =
layoutString != null
? Color(int.parse(secondString!))
: Colors.orange;
thridColor =
layoutString != null
? Color(int.parse(thridString!))
: Colors.orangeAccent;
// bodyColor =
// bodyStringColor != null
// ? Color(int.parse(bodyStringColor))
// : Colors.white;
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isDesktop = MediaQuery.of(context).size.width > 1024; final isDesktop = MediaQuery.of(context).size.width > 1024;
return Padding( return Padding(
padding: const EdgeInsets.all(16.0), padding:
isDesktop ? const EdgeInsets.all(16.0) : const EdgeInsets.all(5.0),
child: Container( child: Container(
margin: const EdgeInsets.only(top: 16.0), margin: const EdgeInsets.only(top: 16.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
// Header with title and button // Header with title and button
Row( // Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ // children: [
if ((!isDesktop) && visaList.isNotEmpty) // if ((!isDesktop) && widget.visaList.isNotEmpty)
Text(
" ",
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
MouseRegion(
cursor: isViewMode
? SystemMouseCursors.forbidden
: SystemMouseCursors.click,
child: GestureDetector(
onTap: isViewMode
? null
: () {
print("New data");
onAddNew("Visa", true);
},
child: Row(
mainAxisSize:
MainAxisSize.min, // Ensures content fits nicely
children: [
// Text( // Text(
// "Add New", // " ",
// style: TextStyle(fontSize: 13), // style: const TextStyle(
// fontSize: 18,
// fontWeight: FontWeight.bold,
// ), // ),
// SizedBox(width: 8), // spacing between icon and text // ),
// Icon( // MouseRegion(
// Icons.add_circle_sharp, // cursor:
// size: 30, // widget.isViewMode
// color: Color(0xFF114D8B), // ? SystemMouseCursors.forbidden
// ) // : SystemMouseCursors.click,
], //
), // child: GestureDetector(
), // onTap:
// onPressed: isViewMode // widget.isViewMode
// ? null // ? null
// : () { // : () {
// print("New data"); // print("New data");
// // widget.onAddNew("Visa", true);
// }, // },
// child: Row( // child: Row(
// mainAxisSize: MainAxisSize.min, // mainAxisSize:
// MainAxisSize.min, // Ensures content fits nicely
// children: [ // children: [
// Icon( // // Text(
// Icons.add_circle_sharp, // // "Add New",
// size: 30, // // style: TextStyle(fontSize: 13),
// color: Color(0xFF114D8B), // // ),
// ) // // SizedBox(width: 8), // spacing between icon and text
// // Icon(
// // Icons.add_circle_sharp,
// // size: 30,
// // color: Color(0xFF114D8B),
// // )
// ], // ],
// ), // ),
), // ),
], // // onPressed: isViewMode
), // // ? null
const SizedBox(height: 16), // // : () {
// Scroll behavior based on device // // print("New data");
// //
// // },
// // child: Row(
// // mainAxisSize: MainAxisSize.min,
// // children: [
// // Icon(
// // Icons.add_circle_sharp,
// // size: 30,
// // color: Color(0xFF114D8B),
// // )
// // ],
// // ),
// ),
// ],
// ),
// const SizedBox(height: 16),
_buildData(context, isDesktop) // Scroll behavior based on device
_buildData(context, isDesktop),
], ],
), ),
), ),
@ -191,11 +240,11 @@ class VisaListWidget extends StatelessWidget {
Widget _buildData(BuildContext context, bool isDesktop) { Widget _buildData(BuildContext context, bool isDesktop) {
List<Map<String, dynamic>> filteredList = List<Map<String, dynamic>> filteredList =
visaList.where((item) => item["is_active"] == "1").toList(); widget.visaList.where((item) => item["is_active"] == "1").toList();
print("filteredList- $filteredList"); print("filteredList- $filteredList");
List<dynamic> visatypeList = apiData?['visa_type_of_visa'] ?? []; List<dynamic> visatypeList = widget.apiData?['visa_type_of_visa'] ?? [];
List<dynamic> countryList = apiCountryData ?? []; List<dynamic> countryList = widget.apiCountryData ?? [];
String getRequestForVisa(String? specialRequestKey) { String getRequestForVisa(String? specialRequestKey) {
if (specialRequestKey == null) return "N/A"; if (specialRequestKey == null) return "N/A";
@ -249,8 +298,11 @@ class VisaListWidget extends StatelessWidget {
if (hour == 24 && minute == 0) { if (hour == 24 && minute == 0) {
// 24:00 is treated as 00:00 on the next day // 24:00 is treated as 00:00 on the next day
dateTime = DateTime(now.year, now.month, now.day) dateTime = DateTime(
.add(const Duration(days: 1)); now.year,
now.month,
now.day,
).add(const Duration(days: 1));
} else { } else {
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
throw FormatException("Invalid hour or minute"); throw FormatException("Invalid hour or minute");
@ -276,14 +328,17 @@ class VisaListWidget extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
// color: Colors.orange.shade50, // color: Colors.orange.shade50,
color: Colors.white, color: isDesktop ? Colors.white : thridColor,
boxShadow: [ boxShadow:
isDesktop
? [
BoxShadow( BoxShadow(
color: Colors.black12, color: Colors.black12,
blurRadius: 3, blurRadius: 3,
offset: Offset(0, 1), offset: Offset(0, 1),
), ),
], ]
: [],
border: Border( border: Border(
top: BorderSide( top: BorderSide(
color: Colors.white70, // Change color to match your theme color: Colors.white70, // Change color to match your theme
@ -292,7 +347,7 @@ class VisaListWidget extends StatelessWidget {
), ),
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(12), padding: isDesktop ? EdgeInsets.all(12) : EdgeInsets.all(8),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -303,26 +358,27 @@ class VisaListWidget extends StatelessWidget {
getRequestForVisa(item["type_of_visa"]!.toString()), getRequestForVisa(item["type_of_visa"]!.toString()),
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w800, fontWeight:
color: !isDesktop ? Color(0xFF114D8B) : Color(0xFF575A74) isDesktop ? FontWeight.w800 : FontWeight.w600,
color: !isDesktop ? Colors.black : Color(0xFF575A74),
), ),
), ),
Spacer(), Spacer(),
GestureDetector( GestureDetector(
onTap: () => onOpen(true, item, "Visa"), onTap: () => widget.onOpen(true, item, "Visa"),
child: Tooltip( child: Tooltip(
message: 'Edit Visa Details', message: 'Edit Visa Details',
child: Image.asset( child: Image.asset(
'assets/images/IconsImg/edit.png', 'assets/images/IconsImg/edit.png',
width: 20, width: 20,
height: 15, height: 15,
color: Color(0xFF114D8B), color: isDesktop ? Color(0xFF114D8B) : Colors.black,
), ),
), ),
), ),
SizedBox(width: 10), SizedBox(width: 10),
GestureDetector( GestureDetector(
onTap: () => onDeleteMiscellaneous(item), onTap: () => widget.onDeleteMiscellaneous(item),
child: Tooltip( child: Tooltip(
message: 'Delete Visa Details', message: 'Delete Visa Details',
child: Image.asset( child: Image.asset(
@ -335,9 +391,7 @@ class VisaListWidget extends StatelessWidget {
), ),
], ],
), ),
Divider( // Divider(color: Colors.blueGrey.shade50),
color: Colors.blueGrey.shade50,
),
SizedBox(height: 4), SizedBox(height: 4),
isDesktop isDesktop
? Row( ? Row(
@ -346,37 +400,34 @@ class VisaListWidget extends StatelessWidget {
flex: 2, flex: 2,
child: Text( child: Text(
" Country", " Country",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Visa Type", " Visa Type",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Date", " Date",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
" Comments", " Comments",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 11),
fontSize: 11, ),
), ),
)),
], ],
) )
: SizedBox.shrink(), : SizedBox.shrink(),
SizedBox(height: 8),
isDesktop isDesktop
? Row( ? Row(
children: [ children: [
@ -384,7 +435,8 @@ class VisaListWidget extends StatelessWidget {
flex: 2, flex: 2,
child: Text( child: Text(
getRequestForCountry( getRequestForCountry(
item["country_code"]!.toString()), item["country_code"]!.toString(),
),
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -395,8 +447,7 @@ class VisaListWidget extends StatelessWidget {
Expanded( Expanded(
flex: 2, flex: 2,
child: Text( child: Text(
getRequestForVisa( getRequestForVisa(item["type_of_visa"]!.toString()),
item["type_of_visa"]!.toString()),
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -418,70 +469,100 @@ class VisaListWidget extends StatelessWidget {
Expanded( Expanded(
flex: 2, flex: 2,
child: _buildComments( child: _buildComments(
"Comments:", item["comments"] ?? "N/A"), "Comments:",
item["comments"] ?? "N/A",
),
), ),
], ],
) )
: : Container(
Column( color: Colors.white,
padding: const EdgeInsets.all(4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Top Row (Country, Currency, Total) _buildRow(
// Row( "VisaType",
// mainAxisAlignment: MainAxisAlignment.spaceBetween, getRequestForVisa(item["type_of_visa"]!.toString()),
Wrap( ),
spacing: 20, // horizontal space between items SizedBox(height: 6),
runSpacing: 10, // vertical space between rows _buildRow(
children: [ "Country",
_infoBlock("Visa Type", getRequestForCountry(item["country_code"]!.toString()) ?? "N/A"), getRequestForCountry(
_infoBlock("Country", getRequestForCountry(item["country_code"]!.toString()) ?? "N/A"), item["country_code"]!.toString(),
_infoBlock("Start Date", formatDate(item["start_date"]!) ?? "N/A"), ),
),
SizedBox(height: 6),
_buildRow("StartDate", item["start_date"]!),
SizedBox(height: 6),
_buildRow("Comments", item["comments"] ?? "N/A"),
], ],
), ),
const SizedBox(height: 16), ),
// Comment label
Text(
"Comment",
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
if (item["comments"] != null && item["comments"].toString().trim().isNotEmpty)
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
border: Border.all(color: const Color(0xFF7098DD), width: 1),
borderRadius: BorderRadius.circular(6),
),
child: Text(
item["comments"] ?? "N/A",
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
),
)
else
const Text( "N/A", style: TextStyle(fontSize: 12), ),
],
),
// Column( // Column(
// crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
// children: [ // children: [
// _buildRow( // // Top Row (Country, Currency, Total)
// "VisaType:", // // Row(
// getRequestForVisa( // // mainAxisAlignment: MainAxisAlignment.spaceBetween,
// item["type_of_visa"]!.toString())), // Wrap(
// SizedBox(height: 6), // spacing: 20, // horizontal space between items
// _buildRow( // runSpacing: 10, // vertical space between rows
// "Country:", // children: [
// _infoBlock(
// "Visa Type",
// getRequestForCountry( // getRequestForCountry(
// item["country_code"]!.toString())), // item["country_code"]!.toString(),
// SizedBox(height: 6), // ) ??
// _buildRow("StartDate:", item["start_date"]!), // "N/A",
// SizedBox(height: 6), // ),
// _buildRow("Comments:", item["comments"] ?? "N/A"), // _infoBlock(
// "Country",
// getRequestForCountry(
// item["country_code"]!.toString(),
// ) ??
// "N/A",
// ),
// _infoBlock(
// "Start Date",
// formatDate(item["start_date"]!) ?? "N/A",
// ),
// ],
// ),
// const SizedBox(height: 16),
//
// // Comment label
// Text(
// "Comment",
// style: GoogleFonts.poppins(
// fontSize: 14,
// fontWeight: FontWeight.w600,
// ),
// ),
// const SizedBox(height: 8),
// if (item["comments"] != null &&
// item["comments"].toString().trim().isNotEmpty)
// Container(
// width: double.infinity,
// padding: const EdgeInsets.all(12),
// decoration: BoxDecoration(
// border: Border.all(
// color: const Color(0xFF7098DD),
// width: 1,
// ),
// borderRadius: BorderRadius.circular(6),
// ),
// child: Text(
// item["comments"] ?? "N/A",
// style: GoogleFonts.poppins(
// fontSize: 12,
// color: Colors.black87,
// ),
// ),
// )
// else
// const Text("N/A", style: TextStyle(fontSize: 12)),
// ], // ],
// ), // ),
], ],
@ -512,30 +593,36 @@ class VisaListWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
child: exceedsLimit child:
exceedsLimit
? Tooltip( ? Tooltip(
message: wrapText(value, 50), message: wrapText(value, 50),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey.shade200, // Black background color: Colors.grey.shade200, // Black background
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
), ),
textStyle: textStyle: TextStyle(
TextStyle(color: Colors.black), // Tooltip text color color: Colors.black,
), // Tooltip text color
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
preferBelow: false, preferBelow: false,
child: Text(value.substring(0, limit) + "...", child: Text(
value.substring(0, limit) + "...",
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontFamily: "Archivo"), fontFamily: "Archivo",
overflow: TextOverflow.ellipsis), ),
overflow: TextOverflow.ellipsis,
),
) )
: Text( : Text(
value, value,
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontFamily: "Archivo"), fontFamily: "Archivo",
),
), ),
), ),
], ],
@ -560,16 +647,14 @@ class VisaListWidget extends StatelessWidget {
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
value, value,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(fontSize: 12, color: Colors.black87),
fontSize: 12,
color: Colors.black87,
),
), ),
], ],
), ),
), ),
); );
} }
Widget _buildRow(String title, String value) { Widget _buildRow(String title, String value) {
// Define character limits based on title // Define character limits based on title
Map<String, int> limits = { Map<String, int> limits = {
@ -589,34 +674,38 @@ class VisaListWidget extends StatelessWidget {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( SizedBox(
width: 100,
child: Text(
title, title,
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
),
SizedBox(width: 8), SizedBox(width: 8),
Expanded( Expanded(
child: exceedsLimit child:
exceedsLimit
? Tooltip( ? Tooltip(
message: wrapText(value, 50), message: wrapText(value, 50),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey.shade200, // Black background color: Colors.grey.shade200, // Black background
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
), ),
textStyle: textStyle: TextStyle(
TextStyle(color: Colors.black), // Tooltip text color color: Colors.black,
), // Tooltip text color
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
preferBelow: false, preferBelow: false,
child: Text(value.substring(0, limit) + "...", child: Text(
style: TextStyle(fontSize: 12), value.substring(0, limit) + "...",
overflow: TextOverflow.ellipsis),
)
: Text(
value,
style: TextStyle(fontSize: 12), style: TextStyle(fontSize: 12),
overflow: TextOverflow.ellipsis,
), ),
)
: Text(value, style: TextStyle(fontSize: 12)),
), ),
], ],
); );

View File

@ -578,8 +578,6 @@ class TemplateForexState extends State<TemplateForex> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Row( Row(
children: [ children: [
Container( Container(
@ -591,11 +589,9 @@ class TemplateForexState extends State<TemplateForex> {
tooltip: 'Go To Organization Settings', tooltip: 'Go To Organization Settings',
onTap: (context) { onTap: (context) {
context.go("/OrganizationSettings"); context.go("/OrganizationSettings");
} },
),
BreadcrumbItem(
title: 'Forex',
), ),
BreadcrumbItem(title: 'Forex'),
], ],
), ),
), ),
@ -788,7 +784,7 @@ class TemplateForexState extends State<TemplateForex> {
), ),
Container( Container(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
height: MediaQuery.of(context).size.height * 0.5, height: MediaQuery.of(context).size.height * 0.45,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
border: Border.all(color: Color(0xFFD6D5E6), width: 0.5), border: Border.all(color: Color(0xFFD6D5E6), width: 0.5),
@ -862,7 +858,8 @@ class TemplateForexState extends State<TemplateForex> {
SizedBox(width: 10), SizedBox(width: 10),
SizedBox( SizedBox(
child: ElevatedButton( child: ElevatedButton(
onPressed: isDisable onPressed:
isDisable
? null ? null
: () async { : () async {
setState(() { setState(() {

View File

@ -1131,7 +1131,7 @@ class _OrgSetUpState extends State<OrgSetUp> {
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
), ),
onPressed: () { onPressed: () {
context.go('/listPlan'); context.go('/OrganizationSettings');
}, },
child: Text("Cancel", style: GoogleFonts.poppins(fontSize: 12)), child: Text("Cancel", style: GoogleFonts.poppins(fontSize: 12)),
), ),

View File

@ -58,6 +58,21 @@ class _ColorThemePickerWidgetState extends State<ColorThemePickerWidget> {
]; ];
final List<Color> layoutTertiaryColors = [ final List<Color> layoutTertiaryColors = [
Color(0xFFE5EFFF), // Very Light Blue
Color(0xFFE6FDFF), // Very Light Teal
Color(0xFFE8FDEF), // Mint Green
Color(0xFFFFE7E6), // Light Coral/Red
Color(0xFFFDE9E7), // Peach
Color(0xFFFFF5E5), // Lightest Orange
Color(0xFFECEEF8), // Very Light Rose
Color(0xFFE5FFFC), // Pastel Pink
Color(0xFFFEE6F3), // Light Lavender
Color(0xFFF9EBF3), // Soft Purple Grey
Color(0xFFF8EAFA), // Near-white Neutral
Color(0xFFF4EDF7), // Near-white Neutral
];
final List<Color> layoutTertiaryColors1 = [
Color(0xFFE3F2FD), // Very Light Blue Color(0xFFE3F2FD), // Very Light Blue
Color(0xFFE0F7FA), // Very Light Teal Color(0xFFE0F7FA), // Very Light Teal
Color(0xFFC8E6C9), // Mint Green Color(0xFFC8E6C9), // Mint Green
@ -67,7 +82,7 @@ class _ColorThemePickerWidgetState extends State<ColorThemePickerWidget> {
Color(0xFFFFEBEE), // Very Light Rose Color(0xFFFFEBEE), // Very Light Rose
Color(0xFFFCE4EC), // Pastel Pink Color(0xFFFCE4EC), // Pastel Pink
Color(0xFFF3E5F5), // Light Lavender Color(0xFFF3E5F5), // Light Lavender
Color(0xFFEDE7F6), // Soft Purple Grey Color(0xFFF9EBF3), // Soft Purple Grey
Color(0xFFF8F9FA), // Near-white Neutral Color(0xFFF8F9FA), // Near-white Neutral
]; ];

View File

@ -446,10 +446,12 @@ class CreateNewPlansState extends State<CreateNewPlan> {
String? _selectedIsBillable; String? _selectedIsBillable;
String? selectedFuncDept; String? selectedFuncDept;
String? selectedPurpose; String? selectedPurpose;
bool hasUpdateVal = false;
Map<String, String?> validationErrors = {}; Map<String, String?> validationErrors = {};
List<Map<String, dynamic>> miscellaneousList = [];
// List<Map<String, dynamic>> miscellaneousList = [{"special_request": 1, "comments": "posta", "indx": 1}]; // List<Map<String, dynamic>> miscellaneousList = [{"special_request": 1, "comments": "posta", "indx": 1}];
List<Map<String, dynamic>> miscellaneousList = [];
List<Map<String, dynamic>> visaList = []; List<Map<String, dynamic>> visaList = [];
List<Map<String, dynamic>> insuranceList = []; List<Map<String, dynamic>> insuranceList = [];
List<Map<String, dynamic>> accommodationList = []; List<Map<String, dynamic>> accommodationList = [];
@ -562,6 +564,10 @@ class CreateNewPlansState extends State<CreateNewPlan> {
loadInitialData(); loadInitialData();
}); });
// if (widget.selectedPlanData != null) {
// hasUpdateVal = true;
// }
if (widget.approverStatus == "Approval pending") { if (widget.approverStatus == "Approval pending") {
print("Status approver - Approval Pending"); print("Status approver - Approval Pending");
} }
@ -656,6 +662,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
planTravlrId = travellerId; planTravlrId = travellerId;
_selectedOption = "Option 3"; _selectedOption = "Option 3";
otherUserName = travellerName; otherUserName = travellerName;
hasUpdateVal = true;
} else if (userId.isNotEmpty && userId != "0") { } else if (userId.isNotEmpty && userId != "0") {
print("TestplanUsrId : $userId"); print("TestplanUsrId : $userId");
print("TestplanUsrIdSelf : $selfId"); print("TestplanUsrIdSelf : $selfId");
@ -663,6 +671,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
print("TestplanUsrId2 : $planUsrId"); print("TestplanUsrId2 : $planUsrId");
_selectedOption = (selfId != userId) ? "Option 2" : "Option 1"; _selectedOption = (selfId != userId) ? "Option 2" : "Option 1";
otherUserName = userName; otherUserName = userName;
hasUpdateVal = true;
} }
}); });
} }
@ -1316,6 +1325,56 @@ class CreateNewPlansState extends State<CreateNewPlan> {
} }
} }
Future<bool> serviceHasData() async {
return miscellaneousList.isNotEmpty ||
visaList.isNotEmpty ||
insuranceList.isNotEmpty ||
accommodationList.isNotEmpty ||
trainList.isNotEmpty ||
flightList.isNotEmpty ||
busList.isNotEmpty ||
taxiList.isNotEmpty ||
forexList.isNotEmpty;
}
void clearAllServiceLists() async {
setState(() {
miscellaneousList = [];
visaList = [];
insuranceList = [];
accommodationList = [];
trainList = [];
flightList = [];
busList = [];
taxiList = [];
forexList = [];
planData['miscellaneous'] = [];
planData['visa'] = [];
planData['insurance'] = [];
planData['accommodation'] = [];
planData['train'] = [];
planData['flight'] = [];
planData['bus'] = [];
planData['taxi'] = [];
planData['forex'] = [];
});
// Debugging output
print("After clearing:");
print("After clearing: $planData");
print("miscellaneousList: ${miscellaneousList.length}");
print("visaList: ${visaList.length}");
print("insuranceList: ${insuranceList.length}");
print("accommodationList: ${accommodationList.length}");
print("trainList: ${trainList.length}");
print("flightList: ${flightList.length}");
print("busList: ${busList.length}");
print("taxiList: ${taxiList.length}");
print("forexList: ${forexList.length}");
}
Future<void> checkExceptionalClass() async { Future<void> checkExceptionalClass() async {
// pretend we fetch something // pretend we fetch something
await Future.delayed(Duration(seconds: 1)); // Example async operation await Future.delayed(Duration(seconds: 1)); // Example async operation
@ -1850,6 +1909,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
onItineraryUpdate: handleItineraryUpdate, onItineraryUpdate: handleItineraryUpdate,
onExeptionalClass: handleExcentionalClass, onExeptionalClass: handleExcentionalClass,
loginUser: selfId, loginUser: selfId,
selectedPlanData: planData, selectedPlanData: planData,
isViewMode: widget.isViewMode, isViewMode: widget.isViewMode,
), ),
@ -1945,12 +2005,49 @@ class CreateNewPlansState extends State<CreateNewPlan> {
focusStates["trip_typeFocused"] = hasFocus; focusStates["trip_typeFocused"] = hasFocus;
}); });
}, },
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
print("TRIP CLICKESS1");
// Request focus when user taps // Request focus when user taps
focusNodes["trip_typeFocusNode"]?.requestFocus(); focusNodes["trip_typeFocusNode"]?.requestFocus();
print("TRIP CLICKESS15");
}, },
child: DropdownSearch<Map<String, dynamic>>( child: DropdownSearch<Map<String, dynamic>>(
onBeforePopupOpening: (selectedItem) async {
bool hasData = await serviceHasData();
if (hasData) {
bool? shouldProceed = await showDialog<bool>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
"Changing trip type will remove added services",
),
content: Text("Do you wish to proceed?"),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(false); // Cancel
},
child: Text("Cancel"),
),
TextButton(
onPressed: () {
Navigator.of(context).pop(true); // Continue
},
child: Text("Continue"),
),
],
);
},
);
return shouldProceed ?? false;
}
return true;
},
enabled: !hasUpdateVal,
popupProps: PopupProps.menu( popupProps: PopupProps.menu(
showSearchBox: false, // Optionally enable search showSearchBox: false, // Optionally enable search
fit: FlexFit.loose, fit: FlexFit.loose,
@ -2045,6 +2142,16 @@ class CreateNewPlansState extends State<CreateNewPlan> {
widget.isViewMode widget.isViewMode
? null ? null
: (Map<String, dynamic>? newItem) { : (Map<String, dynamic>? newItem) {
final newTripType =
newItem?['dropdown_key'].toString();
print("newTripType - $newTripType");
print("_selectedTripType- $_selectedTripType");
if (newTripType != _selectedTripType) {
print("Type changed");
clearAllServiceLists();
dynamicItineraryKey.currentState
?.clearAllServiceLists();
}
if (newItem != null) { if (newItem != null) {
setState(() { setState(() {
_selectedTripType = _selectedTripType =
@ -2058,6 +2165,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
fetchTrainFlightClass( fetchTrainFlightClass(
int.parse(_selectedTripType!), int.parse(_selectedTripType!),
); );
dynamicItineraryKey.currentState dynamicItineraryKey.currentState
?.updateSelectedServices(); ?.updateSelectedServices();
}); });
@ -3073,6 +3181,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
{"title": "Others (Non Employee)", "value": "Option 3"}, {"title": "Others (Non Employee)", "value": "Option 3"},
]; ];
print("isViewModeYY: ${widget.isViewMode}, hasUpdateVal: $hasUpdateVal");
return [ return [
CustomTextFieldWrapper( CustomTextFieldWrapper(
// isFocused: focusStates["trip_plannedFocused"] ?? false, // isFocused: focusStates["trip_plannedFocused"] ?? false,
@ -3099,12 +3208,14 @@ class CreateNewPlansState extends State<CreateNewPlan> {
// Request focus when user taps // Request focus when user taps
focusNodes["trip_plannedFocusNode"]?.requestFocus(); focusNodes["trip_plannedFocusNode"]?.requestFocus();
}, },
child: DropdownSearch<String>( child: DropdownSearch<String>(
selectedItem: selectedItem:
options.firstWhere( options.firstWhere(
(opt) => opt['value'] == _selectedOption, (opt) => opt['value'] == _selectedOption,
)['title'], )['title'],
enabled: !widget.isViewMode, enabled: !hasUpdateVal,
// enabled: || !hasUpdateVal,
items: options.map((opt) => opt['title']!).toList(), items: options.map((opt) => opt['title']!).toList(),
popupProps: PopupProps.menu( popupProps: PopupProps.menu(
showSearchBox: false, showSearchBox: false,

View File

@ -104,6 +104,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
@override @override
void initState() { void initState() {
print("DynamicItinerary");
super.initState(); super.initState();
handleSelectedPlan(); handleSelectedPlan();
updateSelectedServices(); updateSelectedServices();
@ -128,7 +129,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
// selectedIndex = null; // selectedIndex = null;
// selectedItem = null; // selectedItem = null;
// }); // });
print("updateTripType - $_tripType");
updateTripType(widget.tripType); updateTripType(widget.tripType);
} }
} }
@ -187,6 +188,9 @@ class DynamicItineraryState extends State<DynamicItinerary> {
_tripType = newTripType; _tripType = newTripType;
}); });
updateSelectedServices(); // Refresh services based on new tripType updateSelectedServices(); // Refresh services based on new tripType
print("updateTripType2 - $newTripType");
handleSelectedPlan();
} }
} }
@ -268,6 +272,13 @@ class DynamicItineraryState extends State<DynamicItinerary> {
} }
} }
void clearAllServiceLists() async {
print("clearAllServiceLists");
setState(() {
itineraryData.updateAll((key, value) => []);
});
}
// Future<void> updateSelectedServices() async { // Future<void> updateSelectedServices() async {
// await loadAllServices(); // await loadAllServices();
// await loadOrgSelectedAlServices(); // await loadOrgSelectedAlServices();
@ -389,6 +400,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
} }
void handleSelectedPlan() { void handleSelectedPlan() {
print("handleSelectedPlan");
// Check if selectedPlanData has itinerary data // Check if selectedPlanData has itinerary data
if (hasAnyItineraryData()) { if (hasAnyItineraryData()) {
print("selectedPlanData HAS DATA"); print("selectedPlanData HAS DATA");
@ -856,7 +868,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
margin: EdgeInsets.only( margin: EdgeInsets.only(
top: 40, top: 40,
), // Push it down to make room for the tab bar ), // Push it down to make room for the tab bar
padding: EdgeInsets.all(12), padding: EdgeInsets.only(top: 12, bottom: 12, left: 3, right: 3),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, // Card background color: Colors.white, // Card background
// color: Colors.yellow.shade50, // Card background // color: Colors.yellow.shade50, // Card background

View File

@ -645,7 +645,10 @@ class _ListPlansState extends State<ListPlans> {
return Container( return Container(
margin: isDesktop ? EdgeInsets.all(10.0) : null, margin: isDesktop ? EdgeInsets.all(10.0) : null,
padding: const EdgeInsets.only(top: 15, bottom: 15, left: 20, right: 20), padding:
isDesktop
? const EdgeInsets.only(top: 15, bottom: 15, left: 20, right: 20)
: const EdgeInsets.only(top: 15, bottom: 15, left: 5, right: 5),
height: height:
isDesktop isDesktop
? MediaQuery.of(context).size.height * 0.98 ? MediaQuery.of(context).size.height * 0.98
@ -676,7 +679,12 @@ class _ListPlansState extends State<ListPlans> {
// thickness: 0.2, // how "thick" the line is // thickness: 0.2, // how "thick" the line is
// color: Colors.grey, // optional // color: Colors.grey, // optional
// ), // ),
Row( Padding(
padding:
isDesktop
? const EdgeInsets.all(8.0)
: const EdgeInsets.symmetric(horizontal: 14.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Row(
@ -836,9 +844,11 @@ class _ListPlansState extends State<ListPlans> {
), ),
], ],
), ),
),
if (!isDesktop) const SizedBox(height: 10), if (!isDesktop) const SizedBox(height: 10),
if (!isDesktop) if (!isDesktop)
Row( Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Container( Container(
width: MediaQuery.of(context).size.width * 0.85, width: MediaQuery.of(context).size.width * 0.85,
@ -986,7 +996,9 @@ class _ListPlansState extends State<ListPlans> {
), ),
), ),
DataColumn( DataColumn(
label: Text( label: Expanded(
flex: 1,
child: Text(
'Trip Name', 'Trip Name',
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 13, fontSize: 13,
@ -994,6 +1006,7 @@ class _ListPlansState extends State<ListPlans> {
), ),
), ),
), ),
),
DataColumn( DataColumn(
label: Text( label: Text(
'Emp Code', 'Emp Code',
@ -1064,14 +1077,18 @@ class _ListPlansState extends State<ListPlans> {
), ),
DataCell( DataCell(
Text( SizedBox(
width: 130,
child: Text(
plan.tripTitle, plan.tripTitle,
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
fontFamily: "Inter", fontFamily: "Inter",
), ),
softWrap: true, softWrap: true,
overflow: TextOverflow.ellipsis, maxLines: 2,
// overflow: TextOverflow.ellipsis,
),
), ),
), ),
@ -1116,7 +1133,8 @@ class _ListPlansState extends State<ListPlans> {
), ),
DataCell( DataCell(
GestureDetector( GestureDetector(
onTap: () => _showDetails(plan.planId), onTap:
() => _showDetails(plan.planId),
child: Container( child: Container(
width: width:
double double
@ -1137,9 +1155,8 @@ class _ListPlansState extends State<ListPlans> {
// : plan.statusValue == "Rejected" // : plan.statusValue == "Rejected"
// ? Colors.red.shade100 // ? Colors.red.shade100
// : Colors.grey.shade100, // : Colors.grey.shade100,
borderRadius: BorderRadius.circular( borderRadius:
10, BorderRadius.circular(10),
),
), ),
child: Text( child: Text(
plan.statusValue, plan.statusValue,
@ -1187,7 +1204,8 @@ class _ListPlansState extends State<ListPlans> {
), ),
child: Row( child: Row(
mainAxisSize: mainAxisSize:
MainAxisSize.min, MainAxisSize
.min,
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment MainAxisAlignment
.center, .center,
@ -1212,7 +1230,8 @@ class _ListPlansState extends State<ListPlans> {
plan.planId, plan.planId,
isViewMode: isViewMode:
true, true,
isMyTrips: true, isMyTrips:
true,
); );
}, },
), ),
@ -1261,9 +1280,10 @@ class _ListPlansState extends State<ListPlans> {
), ),
IconButton( IconButton(
icon: Icon( icon: Icon(
Icons.download, Icons
.download,
color: Color( color: Color(
0xFF114D8B, 0xFF475569,
), ),
size: 18, size: 18,
), ),
@ -1279,6 +1299,34 @@ class _ListPlansState extends State<ListPlans> {
); );
}, },
), ),
if (plan.statusValue ==
"Approved" &&
plan.forexId !=
null &&
plan.forexId !=
'')
IconButton(
icon: Icon(
Icons
.monetization_on_outlined,
color: Color(
0xFF475569,
),
size: 18,
),
tooltip:
'Download Forex PDF',
onPressed: () {
Navigator.pop(
context,
);
apiService
.getForexPdfDownload(
plan.forexId,
);
},
),
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons.comment, Icons.comment,
@ -1299,8 +1347,7 @@ class _ListPlansState extends State<ListPlans> {
) => CommentModalList( ) => CommentModalList(
// planId: plan.planId, // planId: plan.planId,
planId: planId:
plan.planId plan.planId.toString(),
.toString(),
layoutColorForUser: layoutColorForUser:
layoutColor!, layoutColor!,
role: role:
@ -1370,7 +1417,9 @@ class _ListPlansState extends State<ListPlans> {
); );
}).toList(), }).toList(),
), ),
))); ),
),
);
}, },
); );
@ -1419,7 +1468,10 @@ class _ListPlansState extends State<ListPlans> {
: 'assets/images/IconsImg/International_new.png', : 'assets/images/IconsImg/International_new.png',
// width: 65, // width: 65,
height: height:
plan.tripType == 'Domestic' ? 28 : 30, plan.tripType ==
'Domestic'
? 28
: 30,
), ),
], ],
), ),
@ -1492,8 +1544,10 @@ class _ListPlansState extends State<ListPlans> {
ApiService.viewPlan( ApiService.viewPlan(
context, context,
plan.planId, plan.planId,
isViewMode:true, isViewMode:
isMyTrips: true, true,
isMyTrips:
true,
); );
}, },
), ),
@ -1517,8 +1571,10 @@ class _ListPlansState extends State<ListPlans> {
ApiService.viewPlan( ApiService.viewPlan(
context, context,
plan.planId, plan.planId,
isViewMode:false, isViewMode:
isMyTrips: true, false,
isMyTrips:
true,
); );
}, },
), ),
@ -1531,23 +1587,61 @@ class _ListPlansState extends State<ListPlans> {
tooltip: tooltip:
'Cancellation The Trip Details', 'Cancellation The Trip Details',
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(
deletePlan(plan.planId);}, context,
);
deletePlan(
plan.planId,
);
},
), ),
IconButton( IconButton(
icon: Icon( icon: Icon(
Icons Icons
.download, .download,
color: Color( color: Color(
0xFF114D8B, 0xFF475569,
), ),
size: 18, size: 18,
), ),
tooltip: tooltip:
'Download The PDF', 'Download The PDF',
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(
apiService.getPdfDownload(plan.planId,); context,
);
apiService
.getPdfDownload(
plan.planId,
);
},
),
if (plan.statusValue ==
"Approved" &&
plan.forexId !=
null &&
plan.forexId !=
'')
IconButton(
icon: Icon(
Icons
.monetization_on_outlined,
color: Color(
0xFF475569,
),
size: 18,
),
tooltip:
'Download Forex PDF',
onPressed: () {
Navigator.pop(
context,
);
apiService
.getForexPdfDownload(
plan.forexId,
);
}, },
), ),
IconButton( IconButton(
@ -1563,11 +1657,18 @@ class _ListPlansState extends State<ListPlans> {
'Trip Comments', 'Trip Comments',
onPressed: () { onPressed: () {
showDialog( showDialog(
context:context, context:
builder:(context) => CommentModalList( context,
planId:plan.planId.toString(), builder:
layoutColorForUser:layoutColor!, (
role: "User", context,
) => CommentModalList(
planId:
plan.planId.toString(),
layoutColorForUser:
layoutColor!,
role:
"User",
), ),
); );
}, },
@ -1590,7 +1691,8 @@ class _ListPlansState extends State<ListPlans> {
CrossAxisAlignment.end, CrossAxisAlignment.end,
children: [ children: [
Flexible( child:Column( Flexible(
child: Column(
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.start, CrossAxisAlignment.start,
children: [ children: [
@ -1609,7 +1711,8 @@ class _ListPlansState extends State<ListPlans> {
), ),
), ),
], ],
),), ),
),
Column( Column(
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.end, MainAxisAlignment.end,

View File

@ -103,7 +103,6 @@ class _PolicyState extends State<Policy> {
}); });
}).toList(); }).toList();
Map<String, dynamic> data = { Map<String, dynamic> data = {
"name": _policyController.text, "name": _policyController.text,
"domestic": SelectedDomestic, "domestic": SelectedDomestic,
@ -155,6 +154,7 @@ class _PolicyState extends State<Policy> {
// } // }
// }); // });
} }
void _addFocusListener(FocusNode node, Function(bool) updateState) { void _addFocusListener(FocusNode node, Function(bool) updateState) {
node.addListener(() { node.addListener(() {
setState(() { setState(() {
@ -162,6 +162,7 @@ class _PolicyState extends State<Policy> {
}); });
}); });
} }
void _checkAuthAndLoadData() async { void _checkAuthAndLoadData() async {
final String? token = await getToken(); // Your async function to get token final String? token = await getToken(); // Your async function to get token
@ -181,9 +182,6 @@ class _PolicyState extends State<Policy> {
loadInitialData(); loadInitialData();
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (widget.policy != null) { if (widget.policy != null) {
final details = List<Map<String, dynamic>>.from( final details = List<Map<String, dynamic>>.from(
@ -193,7 +191,6 @@ class _PolicyState extends State<Policy> {
} }
}); });
// if (widget.policy != null) { // if (widget.policy != null) {
// print("185"); // print("185");
// final details = List<Map<String, dynamic>>.from( // final details = List<Map<String, dynamic>>.from(
@ -313,30 +310,29 @@ class _PolicyState extends State<Policy> {
}); });
print("298 ServicesChoosed ${ServicesChoosed}"); print("298 ServicesChoosed ${ServicesChoosed}");
if (ServicesChoosed!.isNotEmpty) { if (ServicesChoosed!.isNotEmpty) {
print("Filtered Selected Services ChooesedIpfa1: $ServicesChoosed"); print("Filtered Selected Services ChooesedIpfa1: $ServicesChoosed");
ServicesChoosed!.sort( ServicesChoosed!.sort(
(a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0), (a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0),
); );
String firstServiceName = ServicesChoosed?.first['name']; String firstServiceName = ServicesChoosed?.first['name'];
String firstServiceId = ServicesChoosed?.first['service_id']; String firstServiceId = ServicesChoosed?.first['service_id'];
print("✅ 306 First service name selected for filter: $firstServiceName - $firstServiceId"); print(
"✅ 306 First service name selected for filter: $firstServiceName - $firstServiceId",
);
selectedService = firstServiceName; selectedService = firstServiceName;
if (selectedServiceDBValue.value == "0") { if (selectedServiceDBValue.value == "0") {
setState(() { setState(() {
selectedServiceDBValue.value = firstServiceId.toString(); selectedServiceDBValue.value = firstServiceId.toString();
}); });
} }
List<int> serviceDBvalue = ServicesChoosed! List<int> serviceDBvalue =
ServicesChoosed!
.map((item) => int.parse(item['service_id'].toString())) .map((item) => int.parse(item['service_id'].toString()))
.toList(); .toList();
serviceDBValueList = serviceDBvalue; serviceDBValueList = serviceDBvalue;
} }
print(widget.policy); print(widget.policy);
// updateData(); // updateData();
@ -357,14 +353,10 @@ class _PolicyState extends State<Policy> {
}); });
print("✅ Loaded services from policy (decoded): $services"); print("✅ Loaded services from policy (decoded): $services");
} }
print("Filtered Selected Services Added to Policy: $ServicesChoosed"); print("Filtered Selected Services Added to Policy: $ServicesChoosed");
} else {
}
else {
final filtered = final filtered =
selectedAllServices! selectedAllServices!
.where( .where(
@ -404,7 +396,9 @@ class _PolicyState extends State<Policy> {
); );
String firstServiceName = ServicesChoosed?.first['name']; String firstServiceName = ServicesChoosed?.first['name'];
String firstServiceId = ServicesChoosed?.first['service_id']; String firstServiceId = ServicesChoosed?.first['service_id'];
print("✅ 363 First service name selected for filter: $firstServiceName - $firstServiceId"); print(
"✅ 363 First service name selected for filter: $firstServiceName - $firstServiceId",
);
selectedService = firstServiceName; selectedService = firstServiceName;
if (selectedServiceDBValue.value == "0") { if (selectedServiceDBValue.value == "0") {
setState(() { setState(() {
@ -412,12 +406,11 @@ class _PolicyState extends State<Policy> {
}); });
} }
List<int> serviceDBvalue = ServicesChoosed! List<int> serviceDBvalue =
ServicesChoosed!
.map((item) => int.parse(item['service_id'].toString())) .map((item) => int.parse(item['service_id'].toString()))
.toList(); .toList();
serviceDBValueList = serviceDBvalue; serviceDBValueList = serviceDBvalue;
} }
} }
} }
@ -525,7 +518,6 @@ class _PolicyState extends State<Policy> {
}); });
} }
bool isValidData(Map<String, dynamic> data) { bool isValidData(Map<String, dynamic> data) {
errorMessages.clear(); // Reset previous errors errorMessages.clear(); // Reset previous errors
@ -859,7 +851,7 @@ class _PolicyState extends State<Policy> {
isDesktop isDesktop
? Container( ? Container(
// color: Colors.yellow.shade50, // color: Colors.yellow.shade50,
height: MediaQuery.of(context).size.height * 0.54, height: MediaQuery.of(context).size.height * 0.56,
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
child: Row( child: Row(
@ -1215,11 +1207,11 @@ class _PolicyState extends State<Policy> {
// List<int> serviceDBvalue = // List<int> serviceDBvalue =
// ServicesChoosed!.map((service) => int.parse(service['service_id'].toString())).toList(); // ServicesChoosed!.map((service) => int.parse(service['service_id'].toString())).toList();
List<int> serviceDBvalue = ServicesChoosed! List<int> serviceDBvalue =
ServicesChoosed!
.map((item) => int.parse(item['service_id'].toString())) .map((item) => int.parse(item['service_id'].toString()))
.toList(); .toList();
print("1093"); print("1093");
print(services); print(services);
print(serviceDBvalue); print(serviceDBvalue);
@ -1253,7 +1245,9 @@ class _PolicyState extends State<Policy> {
// max((MediaQuery.of(context).size.height * 0.09), 10) // max((MediaQuery.of(context).size.height * 0.09), 10)
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
print("1201 Selected Services - $service - Tab Index - $index Service Id- $serviceId"); print(
"1201 Selected Services - $service - Tab Index - $index Service Id- $serviceId",
);
setState(() { setState(() {
selectedServiceIndex.value = index.toString(); selectedServiceIndex.value = index.toString();
selectedServiceDBValue.value = serviceId.toString(); selectedServiceDBValue.value = serviceId.toString();
@ -1263,13 +1257,13 @@ class _PolicyState extends State<Policy> {
" selectedServiceIndex.value - ${selectedServiceIndex.value}", " selectedServiceIndex.value - ${selectedServiceIndex.value}",
); );
// policyCriteriaKey.currentState?.fieldForPolicy(); // policyCriteriaKey.currentState?.fieldForPolicy();
// policyCriteriaKey.currentState // policyCriteriaKey.currentState
// ?.addOrUpdatePolicy(selectedServiceIndex.value); // ?.addOrUpdatePolicy(selectedServiceIndex.value);
print("policyselectedService - $selectedService"); print("policyselectedService - $selectedService");
if (selectedService == "Flight" || if (selectedService == "Flight" ||
selectedService == "Train" || selectedService == "Accomodation") { selectedService == "Train" ||
selectedService == "Accomodation") {
showClass = true; showClass = true;
showCost = false; showCost = false;
// int serviceCode = selectedService == "Flight" ? 1 : 2; // int serviceCode = selectedService == "Flight" ? 1 : 2;
@ -1460,7 +1454,8 @@ class _PolicyState extends State<Policy> {
// color: Colors.brown.shade100, // color: Colors.brown.shade100,
// child: Text("data"), // child: Text("data"),
// color: Colors.white60, // color: Colors.white60,
child: (selectedService != null && selectedServiceDBValue.value != "0") child:
(selectedService != null && selectedServiceDBValue.value != "0")
? PolicyCriteria( ? PolicyCriteria(
key: policyCriteriaKey, key: policyCriteriaKey,
isDesktop: isDesktop, isDesktop: isDesktop,
@ -1469,7 +1464,8 @@ class _PolicyState extends State<Policy> {
selectedTabNotifier: selectedServiceIndex, selectedTabNotifier: selectedServiceIndex,
selectedIdNotifier: selectedServiceDBValue, selectedIdNotifier: selectedServiceDBValue,
selectedService: selectedService!, selectedService: selectedService!,
serviceDBValueList: serviceDBValueList, // 👈 Pass the array here serviceDBValueList:
serviceDBValueList, // 👈 Pass the array here
userId: userId, userId: userId,
onPolicyDataChanged: (List<Map<String, dynamic>>? policyData) { onPolicyDataChanged: (List<Map<String, dynamic>>? policyData) {
print("🟢 policyData received from child: $policyData"); print("🟢 policyData received from child: $policyData");
@ -1481,7 +1477,8 @@ class _PolicyState extends State<Policy> {
}); });
}); });
}, },
) : const Center(child: CircularProgressIndicator()), )
: const Center(child: CircularProgressIndicator()),
); );
} }

View File

@ -103,7 +103,6 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
fetchTrainFlightClass(); fetchTrainFlightClass();
@ -216,7 +215,6 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
// To set the data (update) // To set the data (update)
void loadPolicyDetails(List<Map<String, dynamic>> details) { void loadPolicyDetails(List<Map<String, dynamic>> details) {
print("loadPolicyDetails"); print("loadPolicyDetails");
for (var item in details) { for (var item in details) {
final serviceId = item['service_id'].toString(); final serviceId = item['service_id'].toString();
@ -339,12 +337,14 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
[a1, a2, a3].where((a) => a != null).length > 0 && [a1, a2, a3].where((a) => a != null).length > 0 &&
[a1, a2, a3].where((a) => a == null).length > 0; [a1, a2, a3].where((a) => a == null).length > 0;
bool allExceptionalActionsNull = ae1 == null && ae2 == null && ae3 == null && ae4 == null; bool allExceptionalActionsNull =
ae1 == null && ae2 == null && ae3 == null && ae4 == null;
bool someExceptionalActionsMissing = bool someExceptionalActionsMissing =
[ae1, ae2, ae3, ae4].where((a) => a != null).length > 0 && [ae1, ae2, ae3, ae4].where((a) => a != null).length > 0 &&
[ae1, ae2, ae3, ae4].where((a) => a == null).length > 0; [ae1, ae2, ae3, ae4].where((a) => a == null).length > 0;
bool allAmendActionsNull = aa1 == null && aa2 == null && aa3 == null && aa4 == null; bool allAmendActionsNull =
aa1 == null && aa2 == null && aa3 == null && aa4 == null;
bool someAmendActionsMissing = bool someAmendActionsMissing =
[aa1, aa2, aa3, aa4].where((a) => a != null).length > 0 && [aa1, aa2, aa3, aa4].where((a) => a != null).length > 0 &&
[aa1, aa2, aa3, aa4].where((a) => a == null).length > 0; [aa1, aa2, aa3, aa4].where((a) => a == null).length > 0;
@ -477,7 +477,6 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
void fieldForPolicy() { void fieldForPolicy() {
print("fieldForPolicy - ${widget.selectedTabNotifier.value}"); print("fieldForPolicy - ${widget.selectedTabNotifier.value}");
// Save current input to policyData before switching // Save current input to policyData before switching
if (ServiceId != null) { if (ServiceId != null) {
print("Calling addOrUpdatePolicy"); print("Calling addOrUpdatePolicy");
@ -495,11 +494,12 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
print(" db - ${widget.serviceDBValueList.length}"); print(" db - ${widget.serviceDBValueList.length}");
print(" db list - ${widget.serviceDBValueList}"); print(" db list - ${widget.serviceDBValueList}");
if (tabIndex != null && tabIndex >= 0 && tabIndex <= widget.serviceDBValueList.length) { if (tabIndex != null &&
tabIndex >= 0 &&
tabIndex <= widget.serviceDBValueList.length) {
ServiceId = widget.serviceDBValueList[tabIndex - 1].toString(); ServiceId = widget.serviceDBValueList[tabIndex - 1].toString();
print('✅ 484 Selected ServiceId: $ServiceId'); print('✅ 484 Selected ServiceId: $ServiceId');
} } else {
else {
print('❌ Invalid tab index or out of range'); print('❌ Invalid tab index or out of range');
} }
print("502 ServiceId $ServiceId"); print("502 ServiceId $ServiceId");
@ -836,35 +836,67 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"SelectedParallelProcess - $SelectedParallelProcess", "SelectedParallelProcess - $SelectedParallelProcess",
); );
}, },
child: Container( child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Circle icon
Container(
height: 25, height: 25,
width: 25, width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
(SelectedParallelProcess[ServiceId] ==
"1")
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon( child: Icon(
Icons.check_circle, Icons.circle,
size: 20, size: 15,
color: color:
(SelectedParallelProcess[ServiceId] == (SelectedParallelProcess[ServiceId] ==
"1") "1")
? Colors.green ? Colors.green
: Colors.grey, : Colors.grey,
// color: Colors.grey,
), ),
), ),
Icon(
Icons.arrow_downward,
size: 16,
color:
(SelectedParallelProcess[ServiceId] ==
"1")
? Colors.green
: Colors.grey,
),
// Bottom line
],
),
// child: Container(
// height: 25,
// width: 25,
// // decoration: BoxDecoration(
// // shape: BoxShape.circle,
// // border: Border.all(
// // color:
// // (SelectedParallelProcess[ServiceId] ==
// // "1")
// // ? Colors.green
// // : Colors.grey,
// // width: 2,
// // ),
// // ),
// child: Icon(
// Icons.circle,
// size: 20,
// color:
// (SelectedParallelProcess[ServiceId] ==
// "1")
// ? Colors.green
// : Colors.grey,
// // color: Colors.grey,
// ),
// ),
), ),
], ],
), ),
), ),
Container( Container(
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
child: Row( child: Row(
@ -981,25 +1013,16 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"SelectedParallelProcess - $SelectedParallelProcess", "SelectedParallelProcess - $SelectedParallelProcess",
); );
}, },
child: Container( child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Circle icon
Container(
height: 25, height: 25,
width: 25, width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelProcess[ServiceId] ==
"1") ||
(SelectedParallelProcess[ServiceId] ==
"2"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon( child: Icon(
Icons.check_circle, Icons.circle,
size: 20, size: 15,
color: color:
((SelectedParallelProcess[ServiceId] == ((SelectedParallelProcess[ServiceId] ==
"1") || "1") ||
@ -1007,9 +1030,53 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"2")) "2"))
? Colors.green ? Colors.green
: Colors.grey, : Colors.grey,
// color: Colors.grey,
), ),
), ),
Icon(
Icons.arrow_downward_sharp,
size: 16,
color:
((SelectedParallelProcess[ServiceId] ==
"1") ||
(SelectedParallelProcess[ServiceId] ==
"2"))
? Colors.green
: Colors.grey,
),
// Bottom line
],
),
// child: Container(
// height: 25,
// width: 25,
// // decoration: BoxDecoration(
// // shape: BoxShape.circle,
// // border: Border.all(
// // color:
// // ((SelectedParallelProcess[ServiceId] ==
// // "1") ||
// // (SelectedParallelProcess[ServiceId] ==
// // "2"))
// // ? Colors.green
// // : Colors.grey,
// // width: 2,
// // ),
// // ),
// child: Icon(
// Icons.circle,
// size: 20,
// color:
// ((SelectedParallelProcess[ServiceId] ==
// "1") ||
// (SelectedParallelProcess[ServiceId] ==
// "2"))
// ? Colors.green
// : Colors.grey,
// // color: Colors.grey,
// ),
// ),
), ),
], ],
), ),
@ -1127,27 +1194,17 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"SelectedParallelProcess - $SelectedParallelProcess[ServiceId]", "SelectedParallelProcess - $SelectedParallelProcess[ServiceId]",
); );
}, },
child: Container( child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Top lin
// Circle icon
Container(
height: 25, height: 25,
width: 25, width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelProcess[ServiceId] ==
"1") ||
(SelectedParallelProcess[ServiceId] ==
"2") ||
(SelectedParallelProcess[ServiceId] ==
"3"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon( child: Icon(
Icons.check_circle, Icons.circle,
size: 20, size: 15,
color: color:
((SelectedParallelProcess[ServiceId] == ((SelectedParallelProcess[ServiceId] ==
"1") || "1") ||
@ -1157,9 +1214,43 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"3")) "3"))
? Colors.green ? Colors.green
: Colors.grey, : Colors.grey,
// color: Colors.grey,
), ),
), ),
],
),
// child: Container(
// height: 25,
// width: 25,
// // decoration: BoxDecoration(
// // shape: BoxShape.circle,
// // border: Border.all(
// // color:
// // ((SelectedParallelProcess[ServiceId] ==
// // "1") ||
// // (SelectedParallelProcess[ServiceId] ==
// // "2") ||
// // (SelectedParallelProcess[ServiceId] ==
// // "3"))
// // ? Colors.green
// // : Colors.grey,
// // width: 2,
// // ),
// // ),
// child: Icon(
// Icons.circle,
// size: 20,
// color:
// ((SelectedParallelProcess[ServiceId] ==
// "1") ||
// (SelectedParallelProcess[ServiceId] ==
// "2") ||
// (SelectedParallelProcess[ServiceId] ==
// "3"))
// ? Colors.green
// : Colors.grey,
// // color: Colors.grey,
// ),
// ),
), ),
], ],
), ),
@ -1268,7 +1359,10 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
children: [ children: [
Container( Container(
// padding: const EdgeInsets.all(10), // padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), padding: const EdgeInsets.symmetric(
horizontal: 4.0,
vertical: 4.0,
),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
@ -1383,38 +1477,71 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess", "SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess",
); );
}, },
child: Container( child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Circle icon
Container(
height: 25, height: 25,
width: 25, width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
(SelectedParallelExceptionalProcess[ServiceId] ==
"1")
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon( child: Icon(
Icons.check_circle, Icons.circle,
size: 20, size: 15,
color: color:
(SelectedParallelExceptionalProcess[ServiceId] == (SelectedParallelExceptionalProcess[ServiceId] ==
"1") "1")
? Colors.green ? Colors.green
: Colors.grey, : Colors.grey,
// color: Colors.grey,
), ),
), ),
Icon(
Icons.arrow_downward_sharp,
size: 16,
color:
(SelectedParallelExceptionalProcess[ServiceId] ==
"1")
? Colors.green
: Colors.grey,
),
// Bottom line
],
),
// child: Container(
// height: 25,
// width: 25,
// // decoration: BoxDecoration(
// // shape: BoxShape.circle,
// // border: Border.all(
// // color:
// // (SelectedParallelExceptionalProcess[ServiceId] ==
// // "1")
// // ? Colors.green
// // : Colors.grey,
// // width: 2,
// // ),
// // ),
// child: Icon(
// Icons.circle,
// size: 20,
// color:
// (SelectedParallelExceptionalProcess[ServiceId] ==
// "1")
// ? Colors.green
// : Colors.grey,
// // color: Colors.grey,
// ),
// ),
), ),
], ],
), ),
), ),
Container( Container(
// padding: const EdgeInsets.all(10), // padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), padding: const EdgeInsets.symmetric(
horizontal: 4.0,
vertical: 4.0,
),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
@ -1529,25 +1656,16 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess", "SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess",
); );
}, },
child: Container( child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Circle icon
Container(
height: 25, height: 25,
width: 25, width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelExceptionalProcess[ServiceId] ==
"1") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"2"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon( child: Icon(
Icons.check_circle, Icons.circle,
size: 20, size: 15,
color: color:
((SelectedParallelExceptionalProcess[ServiceId] == ((SelectedParallelExceptionalProcess[ServiceId] ==
"1") || "1") ||
@ -1555,16 +1673,62 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"2")) "2"))
? Colors.green ? Colors.green
: Colors.grey, : Colors.grey,
// color: Colors.grey,
), ),
), ),
Icon(
Icons.arrow_downward_sharp,
size: 16,
color:
((SelectedParallelExceptionalProcess[ServiceId] ==
"1") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"2"))
? Colors.green
: Colors.grey,
),
// Bottom line
],
),
// child: Container(
// height: 25,
// width: 25,
// // decoration: BoxDecoration(
// // shape: BoxShape.circle,
// // border: Border.all(
// // color:
// // ((SelectedParallelExceptionalProcess[ServiceId] ==
// // "1") ||
// // (SelectedParallelExceptionalProcess[ServiceId] ==
// // "2"))
// // ? Colors.green
// // : Colors.grey,
// // width: 2,
// // ),
// // ),
// child: Icon(
// Icons.circle,
// size: 20,
// color:
// ((SelectedParallelExceptionalProcess[ServiceId] ==
// "1") ||
// (SelectedParallelExceptionalProcess[ServiceId] ==
// "2"))
// ? Colors.green
// : Colors.grey,
// // color: Colors.grey,
// ),
// ),
), ),
], ],
), ),
), ),
Container( Container(
// padding: const EdgeInsets.all(10), // padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), padding: const EdgeInsets.symmetric(
horizontal: 4.0,
vertical: 4.0,
),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
@ -1676,27 +1840,16 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess[ServiceId]", "SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess[ServiceId]",
); );
}, },
child: Container( child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Circle icon
Container(
height: 25, height: 25,
width: 25, width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelExceptionalProcess[ServiceId] ==
"1") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"2") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"3"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon( child: Icon(
Icons.check_circle, Icons.circle,
size: 20, size: 15,
color: color:
((SelectedParallelExceptionalProcess[ServiceId] == ((SelectedParallelExceptionalProcess[ServiceId] ==
"1") || "1") ||
@ -1706,16 +1859,68 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"3")) "3"))
? Colors.green ? Colors.green
: Colors.grey, : Colors.grey,
// color: Colors.grey,
), ),
), ),
Icon(
Icons.arrow_downward_sharp,
size: 16,
color:
((SelectedParallelExceptionalProcess[ServiceId] ==
"1") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"2") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"3"))
? Colors.green
: Colors.grey,
),
// Bottom line
],
),
// child: Container(
// height: 25,
// width: 25,
// // decoration: BoxDecoration(
// // shape: BoxShape.circle,
// // border: Border.all(
// // color:
// // ((SelectedParallelExceptionalProcess[ServiceId] ==
// // "1") ||
// // (SelectedParallelExceptionalProcess[ServiceId] ==
// // "2") ||
// // (SelectedParallelExceptionalProcess[ServiceId] ==
// // "3"))
// // ? Colors.green
// // : Colors.grey,
// // width: 2,
// // ),
// // ),
// child: Icon(
// Icons.circle,
// size: 20,
// color:
// ((SelectedParallelExceptionalProcess[ServiceId] ==
// "1") ||
// (SelectedParallelExceptionalProcess[ServiceId] ==
// "2") ||
// (SelectedParallelExceptionalProcess[ServiceId] ==
// "3"))
// ? Colors.green
// : Colors.grey,
// // color: Colors.grey,
// ),
// ),
), ),
], ],
), ),
), ),
Container( Container(
// padding: const EdgeInsets.all(10), // padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), padding: const EdgeInsets.symmetric(
horizontal: 4.0,
vertical: 4.0,
),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
@ -1830,26 +2035,27 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
child: Container( child: Container(
height: 25, height: 25,
width: 25, width: 25,
decoration: BoxDecoration( // decoration: BoxDecoration(
shape: BoxShape.circle, // shape: BoxShape.circle,
border: Border.all( // border: Border.all(
color: // color:
((SelectedParallelExceptionalProcess[ServiceId] == // ((SelectedParallelExceptionalProcess[ServiceId] ==
"1") || // "1") ||
(SelectedParallelExceptionalProcess[ServiceId] == // (SelectedParallelExceptionalProcess[ServiceId] ==
"2") || // "2") ||
(SelectedParallelExceptionalProcess[ServiceId] == // (SelectedParallelExceptionalProcess[ServiceId] ==
"3") || // "3") ||
(SelectedParallelExceptionalProcess[ServiceId] == // (SelectedParallelExceptionalProcess[ServiceId] ==
"4")) // "4"))
? Colors.green // ? Colors.green
: Colors.grey, // : Colors.grey,
width: 2, // width: 2,
), // ),
), // ),
child: Icon( child: Icon(
Icons.check_circle, Icons.circle,
size: 20, size: 15,
color: color:
((SelectedParallelExceptionalProcess[ServiceId] == ((SelectedParallelExceptionalProcess[ServiceId] ==
"1") || "1") ||
@ -1960,7 +2166,10 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
children: [ children: [
Container( Container(
// padding: const EdgeInsets.all(10), // padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), padding: const EdgeInsets.symmetric(
horizontal: 4.0,
vertical: 4.0,
),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
@ -2075,38 +2284,71 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"SelectedParallelAmendProcess - $SelectedParallelAmendProcess", "SelectedParallelAmendProcess - $SelectedParallelAmendProcess",
); );
}, },
child: Container( child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Circle icon
Container(
height: 25, height: 25,
width: 25, width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
(SelectedParallelAmendProcess[ServiceId] ==
"1")
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon( child: Icon(
Icons.check_circle, Icons.circle,
size: 20, size: 15,
color: color:
(SelectedParallelAmendProcess[ServiceId] == (SelectedParallelAmendProcess[ServiceId] ==
"1") "1")
? Colors.green ? Colors.green
: Colors.grey, : Colors.grey,
// color: Colors.grey,
), ),
), ),
Icon(
Icons.arrow_downward_sharp,
size: 16,
color:
(SelectedParallelAmendProcess[ServiceId] ==
"1")
? Colors.green
: Colors.grey,
),
// Bottom line
],
),
// child: Container(
// height: 25,
// width: 25,
// // decoration: BoxDecoration(
// // shape: BoxShape.circle,
// // border: Border.all(
// // color:
// // (SelectedParallelAmendProcess[ServiceId] ==
// // "1")
// // ? Colors.green
// // : Colors.grey,
// // width: 2,
// // ),
// // ),
// child: Icon(
// Icons.circle,
// size: 20,
// color:
// (SelectedParallelAmendProcess[ServiceId] ==
// "1")
// ? Colors.green
// : Colors.grey,
// // color: Colors.grey,
// ),
// ),
), ),
], ],
), ),
), ),
Container( Container(
// padding: const EdgeInsets.all(10), // padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), padding: const EdgeInsets.symmetric(
horizontal: 4.0,
vertical: 4.0,
),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
@ -2221,25 +2463,16 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"SelectedParallelAmendProcess - $SelectedParallelAmendProcess", "SelectedParallelAmendProcess - $SelectedParallelAmendProcess",
); );
}, },
child: Container( child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Circle icon
Container(
height: 25, height: 25,
width: 25, width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelAmendProcess[ServiceId] ==
"1") ||
(SelectedParallelAmendProcess[ServiceId] ==
"2"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon( child: Icon(
Icons.check_circle, Icons.circle,
size: 20, size: 15,
color: color:
((SelectedParallelAmendProcess[ServiceId] == ((SelectedParallelAmendProcess[ServiceId] ==
"1") || "1") ||
@ -2247,16 +2480,63 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"2")) "2"))
? Colors.green ? Colors.green
: Colors.grey, : Colors.grey,
// color: Colors.grey,
), ),
), ),
Icon(
Icons.arrow_downward_sharp,
size: 16,
color:
((SelectedParallelAmendProcess[ServiceId] ==
"1") ||
(SelectedParallelAmendProcess[ServiceId] ==
"2"))
? Colors.green
: Colors.grey,
),
// Bottom line
],
),
// child: Container(
// height: 25,
// width: 25,
// // decoration: BoxDecoration(
// // shape: BoxShape.circle,
// // border: Border.all(
// // color:
// // ((SelectedParallelAmendProcess[ServiceId] ==
// // "1") ||
// // (SelectedParallelAmendProcess[ServiceId] ==
// // "2"))
// // ? Colors.green
// // : Colors.grey,
// // width: 2,
// // ),
// // ),
// child: Icon(
// Icons.circle,
// size: 20,
// color:
// ((SelectedParallelAmendProcess[ServiceId] ==
// "1") ||
// (SelectedParallelAmendProcess[ServiceId] ==
// "2"))
// ? Colors.green
// : Colors.grey,
// // color: Colors.grey,
// ),
// ),
), ),
], ],
), ),
), ),
Container( Container(
// padding: const EdgeInsets.all(10), // padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), padding: const EdgeInsets.symmetric(
horizontal: 4.0,
vertical: 4.0,
),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
@ -2368,27 +2648,16 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"SelectedParallelAmendProcess - $SelectedParallelAmendProcess[ServiceId]", "SelectedParallelAmendProcess - $SelectedParallelAmendProcess[ServiceId]",
); );
}, },
child: Container( child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Circle icon
Container(
height: 25, height: 25,
width: 25, width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelAmendProcess[ServiceId] ==
"1") ||
(SelectedParallelAmendProcess[ServiceId] ==
"2") ||
(SelectedParallelAmendProcess[ServiceId] ==
"3"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon( child: Icon(
Icons.check_circle, Icons.circle,
size: 20, size: 15,
color: color:
((SelectedParallelAmendProcess[ServiceId] == ((SelectedParallelAmendProcess[ServiceId] ==
"1") || "1") ||
@ -2398,16 +2667,68 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"3")) "3"))
? Colors.green ? Colors.green
: Colors.grey, : Colors.grey,
// color: Colors.grey,
), ),
), ),
Icon(
Icons.arrow_downward_sharp,
size: 16,
color:
((SelectedParallelAmendProcess[ServiceId] ==
"1") ||
(SelectedParallelAmendProcess[ServiceId] ==
"2") ||
(SelectedParallelAmendProcess[ServiceId] ==
"3"))
? Colors.green
: Colors.grey,
),
// Bottom line
],
),
// child: Container(
// height: 25,
// width: 25,
// // decoration: BoxDecoration(
// // shape: BoxShape.circle,
// // border: Border.all(
// // color:
// // ((SelectedParallelAmendProcess[ServiceId] ==
// // "1") ||
// // (SelectedParallelAmendProcess[ServiceId] ==
// // "2") ||
// // (SelectedParallelAmendProcess[ServiceId] ==
// // "3"))
// // ? Colors.green
// // : Colors.grey,
// // width: 2,
// // ),
// // ),
// child: Icon(
// Icons.circle,
// size: 20,
// color:
// ((SelectedParallelAmendProcess[ServiceId] ==
// "1") ||
// (SelectedParallelAmendProcess[ServiceId] ==
// "2") ||
// (SelectedParallelAmendProcess[ServiceId] ==
// "3"))
// ? Colors.green
// : Colors.grey,
// // color: Colors.grey,
// ),
// ),
), ),
], ],
), ),
), ),
Container( Container(
// padding: const EdgeInsets.all(10), // padding: const EdgeInsets.all(10),
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0), padding: const EdgeInsets.symmetric(
horizontal: 4.0,
vertical: 4.0,
),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
@ -2522,26 +2843,26 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
child: Container( child: Container(
height: 25, height: 25,
width: 25, width: 25,
decoration: BoxDecoration( // decoration: BoxDecoration(
shape: BoxShape.circle, // shape: BoxShape.circle,
border: Border.all( // border: Border.all(
color: // color:
((SelectedParallelAmendProcess[ServiceId] == // ((SelectedParallelAmendProcess[ServiceId] ==
"1") || // "1") ||
(SelectedParallelAmendProcess[ServiceId] == // (SelectedParallelAmendProcess[ServiceId] ==
"2") || // "2") ||
(SelectedParallelAmendProcess[ServiceId] == // (SelectedParallelAmendProcess[ServiceId] ==
"3") || // "3") ||
(SelectedParallelAmendProcess[ServiceId] == // (SelectedParallelAmendProcess[ServiceId] ==
"4")) // "4"))
? Colors.green // ? Colors.green
: Colors.grey, // : Colors.grey,
width: 2, // width: 2,
), // ),
), // ),
child: Icon( child: Icon(
Icons.check_circle, Icons.circle,
size: 20, size: 15,
color: color:
((SelectedParallelAmendProcess[ServiceId] == ((SelectedParallelAmendProcess[ServiceId] ==
"1") || "1") ||
@ -2633,7 +2954,6 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
) )
.toList(); .toList();
if (dropdownItems.isEmpty) { if (dropdownItems.isEmpty) {
dropdownItems.add( dropdownItems.add(
DropdownMenuItem<String>( DropdownMenuItem<String>(

View File

@ -18,10 +18,10 @@ import '../../../services/apiService.dart';
import '../../../utils/pagination.dart'; import '../../../utils/pagination.dart';
import '../../../widgets/custom_breadcrumb_navigation.dart'; import '../../../widgets/custom_breadcrumb_navigation.dart';
import '../../../widgets/popup_travelAgentList_action.dart'; import '../../../widgets/popup_travelAgentList_action.dart';
/// import '../../../widgets/custom_popup.dart'; /// import '../../../widgets/custom_popup.dart';
/// import '../../../../widgets/popup_TravelAgentList_action.dart'; /// import '../../../../widgets/popup_TravelAgentList_action.dart';
class TravelAgentListScreen extends StatefulWidget { class TravelAgentListScreen extends StatefulWidget {
@override @override
_TravelAgentListScreenState createState() => _TravelAgentListScreenState(); _TravelAgentListScreenState createState() => _TravelAgentListScreenState();
@ -144,7 +144,8 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
Future<List<dynamic>> fetchUsers() async { Future<List<dynamic>> fetchUsers() async {
// return []; // return [];
orgId = await getOrgId(); orgId = await getOrgId();
final String apiUrlData = '$apiUrl/api/agentList?org_id=$orgId&for=table_view'; final String apiUrlData =
'$apiUrl/api/agentList?org_id=$orgId&for=table_view';
final String? token = await getToken(); final String? token = await getToken();
print("Fetch Users"); print("Fetch Users");
@ -463,11 +464,9 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
tooltip: 'Go To Organization Settings', tooltip: 'Go To Organization Settings',
onTap: (context) { onTap: (context) {
context.go("/OrganizationSettings"); context.go("/OrganizationSettings");
} },
),
BreadcrumbItem(
title: 'Travel Agent',
), ),
BreadcrumbItem(title: 'Travel Agent'),
], ],
), ),
), ),
@ -848,7 +847,8 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
children: [ children: [
GestureDetector( GestureDetector(
child: Tooltip( child: Tooltip(
message: 'Edit Travel Agent Details', message:
'Edit Travel Agent Details',
child: Image.asset( child: Image.asset(
'assets/images/IconsImg/edit.png', 'assets/images/IconsImg/edit.png',
width: 20, width: 20,
@ -858,12 +858,18 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
onTap: () async { onTap: () async {
// Navigator.pop(context); // Close the menu // Navigator.pop(context); // Close the menu
// final userId = user['user_id']; // final userId = user['user_id'];
final userId = int.parse(user['user_id'].toString()); final userId = int.parse(
final usersData = await apiService.getSingleUser(userId); user['user_id'].toString(),
context.go("/CreateTravelAgent", extra: { );
final usersData = await apiService
.getSingleUser(userId);
context.go(
"/CreateTravelAgent",
extra: {
"selectedUser": usersData, "selectedUser": usersData,
"isViewMode": false, "isViewMode": false,
}); },
);
}, },
), ),
], ],
@ -911,14 +917,14 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
), ),
), ),
Row( Row(
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.start, MainAxisAlignment.start,
children: [ children: [
GestureDetector( GestureDetector(
child: Tooltip( child: Tooltip(
message: 'Edit Travel Agent Details', message:
'Edit Travel Agent Details',
child: Image.asset( child: Image.asset(
'assets/images/IconsImg/edit.png', 'assets/images/IconsImg/edit.png',
width: 20, width: 20,
@ -926,14 +932,30 @@ class _TravelAgentListScreenState extends State<TravelAgentListScreen> {
), ),
), ),
onTap: () async { onTap: () async {
Navigator.pop(context); // Close the menu // Navigator.pop(context); // Close the menu
final userId = int.parse(user['user_id'].toString()); // final userId = user['user_id'];
final usersData = await apiService.getSingleUser(userId); final userId = int.parse(
context.go("/CreateTravelAgent", extra: { user['user_id'].toString(),
);
final usersData = await apiService
.getSingleUser(userId);
context.go(
"/CreateTravelAgent",
extra: {
"selectedUser": usersData, "selectedUser": usersData,
"isViewMode": false, "isViewMode": false,
});
}, },
);
},
// onTap: () async {
// Navigator.pop(context); // Close the menu
// final userId = int.parse(user['user_id'].toString());
// final usersData = await apiService.getSingleUser(userId);
// context.go("/CreateTravelAgent", extra: {
// "selectedUser": usersData,
// "isViewMode": false,
// });
// },
), ),
], ],
), ),

View File

@ -806,7 +806,10 @@ class PersonalDetailsState extends State<PersonalDetails> {
CustomTextFieldUserWrapper( CustomTextFieldUserWrapper(
isFocused: focusStates["FnameFocused"] ?? false, isFocused: focusStates["FnameFocused"] ?? false,
isDesktop: widget.isDesktop, isDesktop: widget.isDesktop,
width: MediaQuery.of(context).size.width * 0.12, width:
widget.isDesktop
? MediaQuery.of(context).size.width * 0.12
: null,
child: SizedBox( child: SizedBox(
height: 40, height: 40,
child: TextField( child: TextField(
@ -858,7 +861,10 @@ class PersonalDetailsState extends State<PersonalDetails> {
CustomTextFieldUserWrapper( CustomTextFieldUserWrapper(
isFocused: focusStates["LnameFocused"] ?? false, isFocused: focusStates["LnameFocused"] ?? false,
isDesktop: widget.isDesktop, isDesktop: widget.isDesktop,
width: MediaQuery.of(context).size.width * 0.12, width:
widget.isDesktop
? MediaQuery.of(context).size.width * 0.12
: null,
child: SizedBox( child: SizedBox(
height: 40, height: 40,
child: TextField( child: TextField(
@ -1210,7 +1216,10 @@ class PersonalDetailsState extends State<PersonalDetails> {
CustomTextFieldUserWrapper( CustomTextFieldUserWrapper(
isFocused: focusStates["mobileNumberFocused"] ?? false, isFocused: focusStates["mobileNumberFocused"] ?? false,
isDesktop: widget.isDesktop, isDesktop: widget.isDesktop,
width: MediaQuery.of(context).size.width * 0.12, width:
widget.isDesktop
? MediaQuery.of(context).size.width * 0.12
: null,
child: SizedBox( child: SizedBox(
height: 40, height: 40,
child: TextField( child: TextField(
@ -1274,7 +1283,10 @@ class PersonalDetailsState extends State<PersonalDetails> {
// isFocused: false, // isFocused: false,
isFocused: focusStates["alternateMobileFocused"] ?? false, isFocused: focusStates["alternateMobileFocused"] ?? false,
isDesktop: widget.isDesktop, isDesktop: widget.isDesktop,
width: MediaQuery.of(context).size.width * 0.12, width:
widget.isDesktop
? MediaQuery.of(context).size.width * 0.12
: null,
child: SizedBox( child: SizedBox(
height: 40, height: 40,
child: TextField( child: TextField(
@ -1387,7 +1399,9 @@ class PersonalDetailsState extends State<PersonalDetails> {
// ), // ),
(context, item, isSelected) { (context, item, isSelected) {
print("contryItem - $item"); print("contryItem - $item");
final match = RegExp(r'^(.*)\s\((.*)\)$').firstMatch(item); final match = RegExp(
r'^(.*)\s\((.*)\)$',
).firstMatch(item);
final countryName = match?.group(1) ?? ''; final countryName = match?.group(1) ?? '';
final countryCode = match?.group(2) ?? ''; final countryCode = match?.group(2) ?? '';
return Padding( return Padding(
@ -1397,7 +1411,10 @@ class PersonalDetailsState extends State<PersonalDetails> {
), ),
child: Padding( child: Padding(
// padding: const EdgeInsets.all(3.0), // padding: const EdgeInsets.all(3.0),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 3), padding: EdgeInsets.symmetric(
horizontal: 2,
vertical: 3,
),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@ -1454,9 +1471,14 @@ class PersonalDetailsState extends State<PersonalDetails> {
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color : (layoutColor ?? Colors.grey), width: 1), color: (layoutColor ?? Colors.grey),
width: 1,
),
),
contentPadding: EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
), ),
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0,),
// contentPadding: EdgeInsets.symmetric(horizontal: 1), // contentPadding: EdgeInsets.symmetric(horizontal: 1),
), ),
), ),
@ -1496,7 +1518,9 @@ class PersonalDetailsState extends State<PersonalDetails> {
final countryCode = final countryCode =
countryMap.entries countryMap.entries
.firstWhere((entry) => entry.value == newValue) .firstWhere(
(entry) => entry.value == newValue,
)
.key; .key;
setState(() { setState(() {
@ -1507,7 +1531,9 @@ class PersonalDetailsState extends State<PersonalDetails> {
countryCode, countryCode,
); // send code not name ); // send code not name
}, },
),),), ),
),
),
), ),
), ),
], ],

View File

@ -181,7 +181,8 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
"first_approver": selectedFirstApprover, "first_approver": selectedFirstApprover,
"second_approver": selectedSecondApprover, "second_approver": selectedSecondApprover,
"third_approver": selectedThirdApprover, "third_approver": selectedThirdApprover,
"exceptional_approver": selectedExceptionalApprover, "fourth_approver": selectedExceptionalApprover,
// "exceptional_approver": selectedExceptionalApprover,
"delegated_to_user_id": selectedSubstituteApprover, "delegated_to_user_id": selectedSubstituteApprover,
// "passport_number": controllers["passportNumber"]?.text, // "passport_number": controllers["passportNumber"]?.text,
// "place_of_issue": controllers["placeOfIssue"]?.text, // "place_of_issue": controllers["placeOfIssue"]?.text,
@ -300,9 +301,14 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
apiselectedUser?["third_approver"]?.toString() ?? ""; apiselectedUser?["third_approver"]?.toString() ?? "";
} }
if (apiselectedUser?["exceptional_approver"] != null) { // if (apiselectedUser?["exceptional_approver"] != null) {
// selectedExceptionalApprover =
// apiselectedUser?["exceptional_approver"]?.toString() ?? "";
// }
if (apiselectedUser?["fourth_approver"] != null) {
selectedExceptionalApprover = selectedExceptionalApprover =
apiselectedUser?["exceptional_approver"]?.toString() ?? ""; apiselectedUser?["fourth_approver"]?.toString() ?? "";
} }
if (apiselectedUser?["delegated_to_user_id"] != null) { if (apiselectedUser?["delegated_to_user_id"] != null) {
@ -1329,9 +1335,11 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
print("📨 Response: ${response.body}"); print("📨 Response: ${response.body}");
if(roleId == "4"){ context.go('/listPlan'); } if (roleId == "4") {
else{ context.go('/listUser'); } context.go('/listPlan');
} else {
context.go('/listUser');
}
} else { } else {
print("❌ Submission failed. Status: ${response.statusCode}"); print("❌ Submission failed. Status: ${response.statusCode}");
print("📨 Body: ${response.body}"); print("📨 Body: ${response.body}");

View File

@ -191,18 +191,34 @@ class OfficeDetailsState extends State<OfficeDetails> {
fetchUsers(); fetchUsers();
fetchFindGroup(); fetchFindGroup();
_addFocusListener(
_addFocusListener(_employeeCodeFocusNode, (focus) => _employeeCodeFocus = focus); _employeeCodeFocusNode,
_addFocusListener(_departmentFocusNode, (focus) => _departmentFocus = focus); (focus) => _employeeCodeFocus = focus,
);
_addFocusListener(
_departmentFocusNode,
(focus) => _departmentFocus = focus,
);
_addFocusListener(_groupFocusNode, (focus) => _groupFocus = focus); _addFocusListener(_groupFocusNode, (focus) => _groupFocus = focus);
_addFocusListener(_firstApprovalFocusNode, (focus) => _firstApprovalFocus = focus); _addFocusListener(
_addFocusListener(_secondApprovalFocusNode, (focus) => _secondApprovalFocus = focus); _firstApprovalFocusNode,
_addFocusListener(_thirdApprovalFocusNode, (focus) => _thirdApprovalFocus = focus); (focus) => _firstApprovalFocus = focus,
_addFocusListener(_exceptionalApprovalFocusNode, (focus) => _exceptionalApprovalFocus = focus); );
_addFocusListener(
_secondApprovalFocusNode,
(focus) => _secondApprovalFocus = focus,
);
_addFocusListener(
_thirdApprovalFocusNode,
(focus) => _thirdApprovalFocus = focus,
);
_addFocusListener(
_exceptionalApprovalFocusNode,
(focus) => _exceptionalApprovalFocus = focus,
);
_addFocusListener(_delegateFocusNode, (focus) => _delegateFocus = focus); _addFocusListener(_delegateFocusNode, (focus) => _delegateFocus = focus);
_addFocusListener(_startDateFocusNode, (focus) => _startDateFocus = focus); _addFocusListener(_startDateFocusNode, (focus) => _startDateFocus = focus);
_addFocusListener(_endDateFocusNode, (focus) => _endDateFocus = focus); _addFocusListener(_endDateFocusNode, (focus) => _endDateFocus = focus);
} }
void _addFocusListener(FocusNode node, Function(bool) updateState) { void _addFocusListener(FocusNode node, Function(bool) updateState) {
@ -372,6 +388,8 @@ class OfficeDetailsState extends State<OfficeDetails> {
), ),
), ),
), ),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -399,6 +417,7 @@ class OfficeDetailsState extends State<OfficeDetails> {
_buildFourthRow(widget.isDesktop), _buildFourthRow(widget.isDesktop),
], ],
), ),
),
); );
} }
@ -465,10 +484,7 @@ class OfficeDetailsState extends State<OfficeDetails> {
widget.isDesktop widget.isDesktop
? Row( ? Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [buildExceptionApprover(isDesktop), Spacer()],
buildExceptionApprover(isDesktop),
Spacer(),
],
) )
: Column( : Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -703,27 +719,28 @@ class OfficeDetailsState extends State<OfficeDetails> {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(_departmentFocus) (_departmentFocus) ? (layoutColor) : Colors.white,
? (layoutColor)
: Colors.white,
width: 0.5, width: 0.5,
), ),
), ),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(_departmentFocus) (_departmentFocus) ? (layoutColor) : Colors.white,
? (layoutColor)
: Colors.white,
width: 0.5, width: 0.5,
// const Color(0xFFD6D5E6), // const Color(0xFFD6D5E6),
), ),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color : (layoutColor ?? Colors.grey), width: 0.5), color: (layoutColor ?? Colors.grey),
width: 0.5,
),
),
contentPadding: EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
), ),
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
// contentPadding: EdgeInsets.symmetric(horizontal: 1), // contentPadding: EdgeInsets.symmetric(horizontal: 1),
), ),
), ),
@ -746,7 +763,9 @@ class OfficeDetailsState extends State<OfficeDetails> {
final departmentId = final departmentId =
departmentMap.entries departmentMap.entries
.firstWhere((entry) => entry.value == newValue) .firstWhere(
(entry) => entry.value == newValue,
)
.key; .key;
setState(() { setState(() {
@ -757,7 +776,9 @@ class OfficeDetailsState extends State<OfficeDetails> {
departmentId, departmentId,
); // Send department_id ); // Send department_id
}, },
),),), ),
),
),
), ),
), ),
], ],
@ -914,9 +935,14 @@ class OfficeDetailsState extends State<OfficeDetails> {
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color : (layoutColor ?? Colors.grey), width: 0.5), color: (layoutColor ?? Colors.grey),
width: 0.5,
),
),
contentPadding: EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
), ),
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
), ),
), ),
dropdownBuilder: dropdownBuilder:
@ -934,7 +960,9 @@ class OfficeDetailsState extends State<OfficeDetails> {
final levelId = final levelId =
groupMap.entries groupMap.entries
.firstWhere((entry) => entry.value == newValue) .firstWhere(
(entry) => entry.value == newValue,
)
.key; .key;
setState(() { setState(() {
@ -946,7 +974,8 @@ class OfficeDetailsState extends State<OfficeDetails> {
); // pass the ID not the name ); // pass the ID not the name
}, },
), ),
),), ),
),
), ),
), ),
], ],
@ -1003,16 +1032,20 @@ class OfficeDetailsState extends State<OfficeDetails> {
), ),
) )
: DropdownSearch<String>( : DropdownSearch<String>(
selectedItem: userMap[selectedFirstApprover], selectedItem:
userMap[selectedFirstApprover],
enabled: !widget.isViewMode, enabled: !widget.isViewMode,
popupProps: PopupProps.menu( popupProps: PopupProps.menu(
showSearchBox: true, showSearchBox: true,
fit: FlexFit.loose, // Allows flexible height fit:
FlexFit
.loose, // Allows flexible height
menuProps: const MenuProps( menuProps: const MenuProps(
backgroundColor: Colors.white, backgroundColor: Colors.white,
), ),
itemBuilder: itemBuilder:
(context, item, isSelected) => Container( (context, item, isSelected) =>
Container(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 10, horizontal: 10,
vertical: 6, vertical: 6,
@ -1024,7 +1057,9 @@ class OfficeDetailsState extends State<OfficeDetails> {
), ),
), ),
), ),
constraints: BoxConstraints(maxHeight: 250), constraints: BoxConstraints(
maxHeight: 250,
),
searchFieldProps: TextFieldProps( searchFieldProps: TextFieldProps(
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search User...", hintText: "Search User...",
@ -1038,14 +1073,19 @@ class OfficeDetailsState extends State<OfficeDetails> {
apiUserData!.map((user) { apiUserData!.map((user) {
return "${user['first_name']} ${user['last_name']}"; return "${user['first_name']} ${user['last_name']}";
}).toList(), }).toList(),
dropdownDecoratorProps: DropDownDecoratorProps( dropdownDecoratorProps:
dropdownSearchDecoration: InputDecoration( DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius:
BorderRadius.circular(8),
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(_firstApprovalFocus ?? false) (_firstApprovalFocus ??
? (layoutColor ?? Colors.white) false)
? (layoutColor ??
Colors.white)
: Colors.white, : Colors.white,
width: 0.5, width: 0.5,
), ),
@ -1053,18 +1093,29 @@ class OfficeDetailsState extends State<OfficeDetails> {
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(_firstApprovalFocus ?? false) (_firstApprovalFocus ??
? (layoutColor ?? Colors.white) false)
? (layoutColor ??
Colors.white)
: Colors.white, : Colors.white,
width: 0.5, width: 0.5,
// const Color(0xFFD6D5E6), // const Color(0xFFD6D5E6),
), ),
), ),
focusedBorder: OutlineInputBorder( focusedBorder:
OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color : (layoutColor ?? Colors.grey), width: 0.5), color:
(layoutColor ??
Colors.grey),
width: 0.5,
),
),
contentPadding:
EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
), ),
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
), ),
), ),
dropdownBuilder: dropdownBuilder:
@ -1098,7 +1149,8 @@ class OfficeDetailsState extends State<OfficeDetails> {
final approverId = final approverId =
userMap.entries userMap.entries
.firstWhere( .firstWhere(
(entry) => entry.value == newValue, (entry) =>
entry.value == newValue,
) )
.key; .key;
@ -1111,7 +1163,8 @@ class OfficeDetailsState extends State<OfficeDetails> {
); // not newValue, but approverId ); // not newValue, but approverId
}, },
), ),
),), ),
),
), ),
), ),
], ],
@ -1175,16 +1228,20 @@ class OfficeDetailsState extends State<OfficeDetails> {
), ),
) )
: DropdownSearch<String>( : DropdownSearch<String>(
selectedItem: userMap[selectedSecondApprover], selectedItem:
userMap[selectedSecondApprover],
enabled: !widget.isViewMode, enabled: !widget.isViewMode,
popupProps: PopupProps.menu( popupProps: PopupProps.menu(
showSearchBox: true, showSearchBox: true,
fit: FlexFit.loose, // Allows flexible height fit:
FlexFit
.loose, // Allows flexible height
menuProps: const MenuProps( menuProps: const MenuProps(
backgroundColor: Colors.white, backgroundColor: Colors.white,
), ),
itemBuilder: itemBuilder:
(context, item, isSelected) => Container( (context, item, isSelected) =>
Container(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 10, horizontal: 10,
vertical: 6, vertical: 6,
@ -1196,7 +1253,9 @@ class OfficeDetailsState extends State<OfficeDetails> {
), ),
), ),
), ),
constraints: BoxConstraints(maxHeight: 250), constraints: BoxConstraints(
maxHeight: 250,
),
searchFieldProps: TextFieldProps( searchFieldProps: TextFieldProps(
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search User...", hintText: "Search User...",
@ -1210,14 +1269,19 @@ class OfficeDetailsState extends State<OfficeDetails> {
apiUserData!.map((user) { apiUserData!.map((user) {
return "${user['first_name']} ${user['last_name']}"; return "${user['first_name']} ${user['last_name']}";
}).toList(), }).toList(),
dropdownDecoratorProps: DropDownDecoratorProps( dropdownDecoratorProps:
dropdownSearchDecoration: InputDecoration( DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius:
BorderRadius.circular(8),
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(_secondApprovalFocus ?? false) (_secondApprovalFocus ??
? (layoutColor ?? Colors.white) false)
? (layoutColor ??
Colors.white)
: Colors.white, : Colors.white,
width: 0.5, width: 0.5,
), ),
@ -1225,18 +1289,29 @@ class OfficeDetailsState extends State<OfficeDetails> {
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(_secondApprovalFocus ?? false) (_secondApprovalFocus ??
? (layoutColor ?? Colors.white) false)
? (layoutColor ??
Colors.white)
: Colors.white, : Colors.white,
width: 0.5, width: 0.5,
// const Color(0xFFD6D5E6), // const Color(0xFFD6D5E6),
), ),
), ),
focusedBorder: OutlineInputBorder( focusedBorder:
OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color : (layoutColor ?? Colors.grey), width: 0.5), color:
(layoutColor ??
Colors.grey),
width: 0.5,
),
),
contentPadding:
EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
), ),
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
), ),
), ),
dropdownBuilder: dropdownBuilder:
@ -1257,7 +1332,8 @@ class OfficeDetailsState extends State<OfficeDetails> {
final approverId = final approverId =
userMap.entries userMap.entries
.firstWhere( .firstWhere(
(entry) => entry.value == newValue, (entry) =>
entry.value == newValue,
) )
.key; .key;
@ -1282,7 +1358,8 @@ class OfficeDetailsState extends State<OfficeDetails> {
// }); // });
// }, // },
), ),
),), ),
),
), ),
), ),
], ],
@ -1346,16 +1423,20 @@ class OfficeDetailsState extends State<OfficeDetails> {
), ),
) )
: DropdownSearch<String>( : DropdownSearch<String>(
selectedItem: userMap[selectedThirdApprover], selectedItem:
userMap[selectedThirdApprover],
enabled: !widget.isViewMode, enabled: !widget.isViewMode,
popupProps: PopupProps.menu( popupProps: PopupProps.menu(
showSearchBox: true, showSearchBox: true,
fit: FlexFit.loose, // Allows flexible height fit:
FlexFit
.loose, // Allows flexible height
menuProps: const MenuProps( menuProps: const MenuProps(
backgroundColor: Colors.white, backgroundColor: Colors.white,
), ),
itemBuilder: itemBuilder:
(context, item, isSelected) => Container( (context, item, isSelected) =>
Container(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 10, horizontal: 10,
vertical: 6, vertical: 6,
@ -1367,7 +1448,9 @@ class OfficeDetailsState extends State<OfficeDetails> {
), ),
), ),
), ),
constraints: BoxConstraints(maxHeight: 250), constraints: BoxConstraints(
maxHeight: 250,
),
searchFieldProps: TextFieldProps( searchFieldProps: TextFieldProps(
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search User...", hintText: "Search User...",
@ -1381,14 +1464,19 @@ class OfficeDetailsState extends State<OfficeDetails> {
apiUserData!.map((user) { apiUserData!.map((user) {
return "${user['first_name']} ${user['last_name']}"; return "${user['first_name']} ${user['last_name']}";
}).toList(), }).toList(),
dropdownDecoratorProps: DropDownDecoratorProps( dropdownDecoratorProps:
dropdownSearchDecoration: InputDecoration( DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius:
BorderRadius.circular(8),
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(_thirdApprovalFocus ?? false) (_thirdApprovalFocus ??
? (layoutColor ?? Colors.white) false)
? (layoutColor ??
Colors.white)
: Colors.white, : Colors.white,
width: 0.5, width: 0.5,
), ),
@ -1396,18 +1484,29 @@ class OfficeDetailsState extends State<OfficeDetails> {
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(_thirdApprovalFocus ?? false) (_thirdApprovalFocus ??
? (layoutColor ?? Colors.white) false)
? (layoutColor ??
Colors.white)
: Colors.white, : Colors.white,
width: 0.5, width: 0.5,
// const Color(0xFFD6D5E6), // const Color(0xFFD6D5E6),
), ),
), ),
focusedBorder: OutlineInputBorder( focusedBorder:
OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color : (layoutColor ?? Colors.grey), width: 0.5), color:
(layoutColor ??
Colors.grey),
width: 0.5,
),
),
contentPadding:
EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
), ),
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
), ),
), ),
dropdownBuilder: dropdownBuilder:
@ -1427,7 +1526,8 @@ class OfficeDetailsState extends State<OfficeDetails> {
final approverId = final approverId =
userMap.entries userMap.entries
.firstWhere( .firstWhere(
(entry) => entry.value == newValue, (entry) =>
entry.value == newValue,
) )
.key; .key;
@ -1452,7 +1552,8 @@ class OfficeDetailsState extends State<OfficeDetails> {
// }); // });
// }, // },
), ),
),), ),
),
), ),
), ),
], ],
@ -1480,7 +1581,7 @@ class OfficeDetailsState extends State<OfficeDetails> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"Exceptional Approver", "Fourth Approver",
style: GoogleFonts.poppins( style: GoogleFonts.poppins(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -1516,16 +1617,20 @@ class OfficeDetailsState extends State<OfficeDetails> {
), ),
) )
: DropdownSearch<String>( : DropdownSearch<String>(
selectedItem: userMap[selectedExceptionalApprover], selectedItem:
userMap[selectedExceptionalApprover],
enabled: !widget.isViewMode, enabled: !widget.isViewMode,
popupProps: PopupProps.menu( popupProps: PopupProps.menu(
showSearchBox: true, showSearchBox: true,
fit: FlexFit.loose, // Allows flexible height fit:
FlexFit
.loose, // Allows flexible height
menuProps: const MenuProps( menuProps: const MenuProps(
backgroundColor: Colors.white, backgroundColor: Colors.white,
), ),
itemBuilder: itemBuilder:
(context, item, isSelected) => Container( (context, item, isSelected) =>
Container(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 10, horizontal: 10,
vertical: 6, vertical: 6,
@ -1537,7 +1642,9 @@ class OfficeDetailsState extends State<OfficeDetails> {
), ),
), ),
), ),
constraints: BoxConstraints(maxHeight: 250), constraints: BoxConstraints(
maxHeight: 250,
),
searchFieldProps: TextFieldProps( searchFieldProps: TextFieldProps(
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search User...", hintText: "Search User...",
@ -1554,11 +1661,15 @@ class OfficeDetailsState extends State<OfficeDetails> {
dropdownDecoratorProps: DropDownDecoratorProps( dropdownDecoratorProps: DropDownDecoratorProps(
dropdownSearchDecoration: InputDecoration( dropdownSearchDecoration: InputDecoration(
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(
8,
),
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(_exceptionalApprovalFocus ?? false) (_exceptionalApprovalFocus ??
? (layoutColor ?? Colors.white) false)
? (layoutColor ??
Colors.white)
: Colors.white, : Colors.white,
width: 0.5, width: 0.5,
), ),
@ -1566,8 +1677,10 @@ class OfficeDetailsState extends State<OfficeDetails> {
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(_exceptionalApprovalFocus ?? false) (_exceptionalApprovalFocus ??
? (layoutColor ?? Colors.white) false)
? (layoutColor ??
Colors.white)
: Colors.white, : Colors.white,
width: 0.5, width: 0.5,
// const Color(0xFFD6D5E6), // const Color(0xFFD6D5E6),
@ -1575,9 +1688,15 @@ class OfficeDetailsState extends State<OfficeDetails> {
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color : (layoutColor ?? Colors.white), width: 0.5), color:
(layoutColor ?? Colors.white),
width: 0.5,
),
),
contentPadding: EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
), ),
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
), ),
), ),
dropdownBuilder: dropdownBuilder:
@ -1598,12 +1717,14 @@ class OfficeDetailsState extends State<OfficeDetails> {
final approverId = final approverId =
userMap.entries userMap.entries
.firstWhere( .firstWhere(
(entry) => entry.value == newValue, (entry) =>
entry.value == newValue,
) )
.key; .key;
setState(() { setState(() {
selectedExceptionalApprover = approverId; selectedExceptionalApprover =
approverId;
}); });
widget.onExceptionalApproverChanged?.call( widget.onExceptionalApproverChanged?.call(
@ -1611,7 +1732,8 @@ class OfficeDetailsState extends State<OfficeDetails> {
); // not newValue, but approverId ); // not newValue, but approverId
}, },
), ),
),), ),
),
), ),
), ),
], ],
@ -1625,7 +1747,6 @@ class OfficeDetailsState extends State<OfficeDetails> {
); );
} }
Widget buildApproverSubstitute1(bool isDesktop) { Widget buildApproverSubstitute1(bool isDesktop) {
return Container( return Container(
color: Colors.white, color: Colors.white,
@ -1683,12 +1804,15 @@ class OfficeDetailsState extends State<OfficeDetails> {
enabled: !widget.isViewMode, enabled: !widget.isViewMode,
popupProps: PopupProps.menu( popupProps: PopupProps.menu(
showSearchBox: true, showSearchBox: true,
fit: FlexFit.loose, // Allows flexible height fit:
FlexFit
.loose, // Allows flexible height
menuProps: const MenuProps( menuProps: const MenuProps(
backgroundColor: Colors.white, backgroundColor: Colors.white,
), ),
itemBuilder: itemBuilder:
(context, item, isSelected) => Container( (context, item, isSelected) =>
Container(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 10, horizontal: 10,
vertical: 6, vertical: 6,
@ -1700,7 +1824,9 @@ class OfficeDetailsState extends State<OfficeDetails> {
), ),
), ),
), ),
constraints: BoxConstraints(maxHeight: 133), constraints: BoxConstraints(
maxHeight: 133,
),
searchFieldProps: TextFieldProps( searchFieldProps: TextFieldProps(
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search User...", hintText: "Search User...",
@ -1714,14 +1840,19 @@ class OfficeDetailsState extends State<OfficeDetails> {
apiUserData!.map((user) { apiUserData!.map((user) {
return "${user['first_name']} ${user['last_name']}"; return "${user['first_name']} ${user['last_name']}";
}).toList(), }).toList(),
dropdownDecoratorProps: DropDownDecoratorProps( dropdownDecoratorProps:
dropdownSearchDecoration: InputDecoration( DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius:
BorderRadius.circular(8),
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(_delegateFocus ?? false) (_delegateFocus ??
? (layoutColor ?? Colors.white) false)
? (layoutColor ??
Colors.white)
: Colors.white, : Colors.white,
width: 0.5, width: 0.5,
), ),
@ -1729,18 +1860,29 @@ class OfficeDetailsState extends State<OfficeDetails> {
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: color:
(_delegateFocus ?? false) (_delegateFocus ??
? (layoutColor ?? Colors.white) false)
? (layoutColor ??
Colors.white)
: Colors.white, : Colors.white,
width: 0.5, width: 0.5,
// const Color(0xFFD6D5E6), // const Color(0xFFD6D5E6),
), ),
), ),
focusedBorder: OutlineInputBorder( focusedBorder:
OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color : (layoutColor ?? Colors.grey), width: 0.5), color:
(layoutColor ??
Colors.grey),
width: 0.5,
),
),
contentPadding:
EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
), ),
contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
), ),
), ),
dropdownBuilder: dropdownBuilder:
@ -1774,7 +1916,8 @@ class OfficeDetailsState extends State<OfficeDetails> {
final approverId = final approverId =
userMap.entries userMap.entries
.firstWhere( .firstWhere(
(entry) => entry.value == newValue, (entry) =>
entry.value == newValue,
) )
.key; .key;
@ -1787,7 +1930,8 @@ class OfficeDetailsState extends State<OfficeDetails> {
); // not newValue, but approverId ); // not newValue, but approverId
}, },
), ),
),), ),
),
), ),
), ),
], ],
@ -1892,7 +2036,10 @@ class OfficeDetailsState extends State<OfficeDetails> {
child: TextField( child: TextField(
controller: widget.controllers["delegationStartDate"], controller: widget.controllers["delegationStartDate"],
readOnly: true, readOnly: true,
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), style: GoogleFonts.poppins(
fontSize: 12,
color: Colors.black,
),
decoration: InputDecoration( decoration: InputDecoration(
labelText: "Select Date", labelText: "Select Date",
labelStyle: GoogleFonts.poppins( labelStyle: GoogleFonts.poppins(
@ -2049,7 +2196,10 @@ class OfficeDetailsState extends State<OfficeDetails> {
child: TextField( child: TextField(
controller: widget.controllers["delegationEndDate"], controller: widget.controllers["delegationEndDate"],
readOnly: true, readOnly: true,
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black), style: GoogleFonts.poppins(
fontSize: 12,
color: Colors.black,
),
decoration: InputDecoration( decoration: InputDecoration(
labelText: "Select Date", labelText: "Select Date",
labelStyle: GoogleFonts.poppins( labelStyle: GoogleFonts.poppins(

View File

@ -225,18 +225,27 @@ class _UserListScreenState extends State<UserListScreen> {
print("handDel - $userId"); print("handDel - $userId");
} }
void _showConfirmationDialog(String subtitle, List<String> successList, List<Map<String, String>> failedList) { void _showConfirmationDialog(
String subtitle,
List<String> successList,
List<Map<String, String>> failedList,
) {
_dialogShown = true; _dialogShown = true;
showDialog( showDialog(
context: context, context: context,
builder: (context) => AlertDialog( builder:
(context) => AlertDialog(
// title: Text("User Details"), // title: Text("User Details"),
title: Text("Upload Status - $subtitle", style: GoogleFonts.poppins( title: Text(
"Upload Status - $subtitle",
style: GoogleFonts.poppins(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.black, color: Colors.black,
), overflow: TextOverflow.ellipsis), ),
overflow: TextOverflow.ellipsis,
),
content: SingleChildScrollView( content: SingleChildScrollView(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -244,11 +253,14 @@ class _UserListScreenState extends State<UserListScreen> {
// Text(subtitle, style: TextStyle(fontWeight: FontWeight.bold)), // Text(subtitle, style: TextStyle(fontWeight: FontWeight.bold)),
// //
// SizedBox(height: 12), // SizedBox(height: 12),
Text("Success Report :", style: GoogleFonts.poppins( Text(
"Success Report :",
style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: Colors.black, color: Colors.black,
)), ),
),
// if (successList.isNotEmpty) // if (successList.isNotEmpty)
// ...successList.asMap().entries.map((entry) => Text("${entry.key + 1}) ${entry.value} created.")) // ...successList.asMap().entries.map((entry) => Text("${entry.key + 1}) ${entry.value} created."))
if (successList.isNotEmpty) if (successList.isNotEmpty)
@ -279,11 +291,17 @@ class _UserListScreenState extends State<UserListScreen> {
color: Colors.black, color: Colors.black,
), ),
), ),
) ),
], ],
rows: successList.asMap().entries.map((entry) { rows:
successList.asMap().entries.map((entry) {
final newIndex = entry.key + 1; final newIndex = entry.key + 1;
final data = entry.value?.toString().trim().isNotEmpty == true final data =
entry.value
?.toString()
.trim()
.isNotEmpty ==
true
? entry.value.toString() ? entry.value.toString()
: '-'; : '-';
@ -321,90 +339,141 @@ class _UserListScreenState extends State<UserListScreen> {
), ),
) )
else else
Text("-- no data. --",style: GoogleFonts.poppins( Text(
"-- no data. --",
style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w200, fontWeight: FontWeight.w200,
color: Colors.black, color: Colors.black,
)), ),
),
SizedBox(height: 12), SizedBox(height: 12),
// Text("Failed Report :", style: TextStyle(fontWeight: FontWeight.bold)), // Text("Failed Report :", style: TextStyle(fontWeight: FontWeight.bold)),
Text("Failed Report :", style: GoogleFonts.poppins( Text(
"Failed Report :",
style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: Colors.black, color: Colors.black,
)), ),
),
// if (failedList.isNotEmpty) // if (failedList.isNotEmpty)
// ...failedList.asMap().entries.map((entry) { // ...failedList.asMap().entries.map((entry) {
// final data = entry.value["data"] ?? "-"; // final data = entry.value["data"] ?? "-";
// final reason = entry.value["reason"] ?? "Unknown error"; // final reason = entry.value["reason"] ?? "Unknown error";
// return Text("${entry.key + 1}) $data - unable to create due to \"$reason\"."); // return Text("${entry.key + 1}) $data - unable to create due to \"$reason\".");
// }) // })
if (failedList.isNotEmpty) if (failedList.isNotEmpty)
SizedBox( SizedBox(
height: 250, // Vertical scroll height height: 250, // Vertical scroll height
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.horizontal, // Enable horizontal scrolling scrollDirection:
Axis.horizontal, // Enable horizontal scrolling
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.vertical, // Enable vertical scrolling scrollDirection:
Axis.vertical, // Enable vertical scrolling
child: DataTable( child: DataTable(
columns: [ columns: [
DataColumn(label: Text('S.No', style: GoogleFonts.poppins( DataColumn(
label: Text(
'S.No',
style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.black, color: Colors.black,
))), ),
DataColumn(label: Text('Data', style: GoogleFonts.poppins( ),
),
DataColumn(
label: Text(
'Data',
style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.black, color: Colors.black,
))), ),
DataColumn(label: Text('Reason', style: GoogleFonts.poppins( ),
),
DataColumn(
label: Text(
'Reason',
style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.black, color: Colors.black,
))), ),
),
),
], ],
rows: failedList.asMap().entries.map((entry) { rows:
failedList.asMap().entries.map((entry) {
final index = entry.key + 1; final index = entry.key + 1;
final rawData = entry.value['data']; final rawData = entry.value['data'];
final data = (rawData == null || rawData.toString().trim().isEmpty) ? '-' : rawData.toString(); final data =
final reason = entry.value['reason'] ?? 'Unknown error'; (rawData == null ||
rawData.toString().trim().isEmpty)
? '-'
: rawData.toString();
final reason =
entry.value['reason'] ?? 'Unknown error';
return DataRow(cells: [ return DataRow(
DataCell(Text('$index',style: GoogleFonts.poppins( cells: [
DataCell(
Text(
'$index',
style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: Colors.black, color: Colors.black,
))), ),
DataCell(SizedBox( ),
),
DataCell(
SizedBox(
width: 180, width: 180,
child: Text(data, style: GoogleFonts.poppins( child: Text(
data,
style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: Colors.black, color: Colors.black,
), overflow: TextOverflow.ellipsis), ),
)), overflow: TextOverflow.ellipsis,
DataCell(SizedBox( ),
),
),
DataCell(
SizedBox(
width: 280, width: 280,
child: Text(reason, style: GoogleFonts.poppins( child: Text(
reason,
style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: Colors.black, color: Colors.black,
),overflow: TextOverflow.ellipsis), ),
)), overflow: TextOverflow.ellipsis,
]); ),
),
),
],
);
}).toList(), }).toList(),
), ),
), ),
), ),
) )
else else
Text("-- no data. --",style: GoogleFonts.poppins( Text(
"-- no data. --",
style: GoogleFonts.poppins(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w200, fontWeight: FontWeight.w200,
color: Colors.black, color: Colors.black,
)), ),
),
], ],
), ),
), ),
@ -421,12 +490,13 @@ class _UserListScreenState extends State<UserListScreen> {
); );
} }
Future<void> handleDownload() async { Future<void> handleDownload() async {
final result = await apiService.getDownloadUserTemplateForUpload(); final result = await apiService.getDownloadUserTemplateForUpload();
final String displayBackgroundColor = result['status'] ? '#28a745' : '#dc1c13'; final String displayBackgroundColor =
final Color displayColor = result['status'] ? Colors.green : Colors.redAccent; result['status'] ? '#28a745' : '#dc1c13';
final Color displayColor =
result['status'] ? Colors.green : Colors.redAccent;
final String displayMessage = result['message']; final String displayMessage = result['message'];
// final bool status = result['status'] == true; // final bool status = result['status'] == true;
@ -438,9 +508,11 @@ class _UserListScreenState extends State<UserListScreen> {
backgroundColor: displayColor, backgroundColor: displayColor,
textColor: Colors.white, textColor: Colors.white,
fontSize: 18.0, fontSize: 18.0,
webBgColor: "linear-gradient(to right, $displayBackgroundColor, $displayBackgroundColor)", webBgColor:
"linear-gradient(to right, $displayBackgroundColor, $displayBackgroundColor)",
); );
} }
Future<void> handleUpload() async { Future<void> handleUpload() async {
final Completer<void> completer = Completer<void>(); final Completer<void> completer = Completer<void>();
@ -540,9 +612,14 @@ class _UserListScreenState extends State<UserListScreen> {
final status = responseData['status'] ?? ''; final status = responseData['status'] ?? '';
final data = responseData['data'] ?? {}; final data = responseData['data'] ?? {};
final List<String> successList = List<String>.from(data['successfulUsers'] ?? []); final List<String> successList = List<String>.from(
final List<Map<String, String>> failedList = List<Map<String, String>>.from( data['successfulUsers'] ?? [],
(data['failedUsers'] ?? []).map((item) => Map<String, String>.from(item)), );
final List<Map<String, String>> failedList =
List<Map<String, String>>.from(
(data['failedUsers'] ?? []).map(
(item) => Map<String, String>.from(item),
),
); );
_showConfirmationDialog(message, successList, failedList); _showConfirmationDialog(message, successList, failedList);
@ -565,10 +642,10 @@ class _UserListScreenState extends State<UserListScreen> {
// Refresh list if needed // Refresh list if needed
refreshUserList(); refreshUserList();
} else { } else {
// For non-200 responses // For non-200 responses
final errorMsg = 'Failed to upload file: ${response.reasonPhrase}'; final errorMsg =
'Failed to upload file: ${response.reasonPhrase}';
Fluttertoast.showToast( Fluttertoast.showToast(
msg: errorMsg, msg: errorMsg,
toastLength: Toast.LENGTH_SHORT, toastLength: Toast.LENGTH_SHORT,
@ -581,7 +658,6 @@ class _UserListScreenState extends State<UserListScreen> {
); );
print(errorMsg); print(errorMsg);
} }
} }
} }
return completer.future; // Wait for upload to finish before proceeding return completer.future; // Wait for upload to finish before proceeding
@ -768,8 +844,7 @@ class _UserListScreenState extends State<UserListScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return return ResponsiveBuilder(
ResponsiveBuilder(
builder: (context, sizingInfo) { builder: (context, sizingInfo) {
bool isDesktop = bool isDesktop =
sizingInfo.deviceScreenType == DeviceScreenType.desktop; sizingInfo.deviceScreenType == DeviceScreenType.desktop;
@ -965,7 +1040,8 @@ class _UserListScreenState extends State<UserListScreen> {
// UPLOAD BUTTON // UPLOAD BUTTON
Align( Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: _isUploading child:
_isUploading
? const SizedBox( ? const SizedBox(
width: 28, width: 28,
height: 28, height: 28,
@ -1297,12 +1373,18 @@ class _UserListScreenState extends State<UserListScreen> {
onTap: () async { onTap: () async {
// Navigator.pop(context); // Close the menu // Navigator.pop(context); // Close the menu
// final userId = user['user_id']; // final userId = user['user_id'];
final userId = int.parse(user['user_id'].toString()); final userId = int.parse(
final usersData = await apiService.getSingleUser(userId); user['user_id'].toString(),
context.go("/CreateUserDetails", extra: { );
final usersData = await apiService
.getSingleUser(userId);
context.go(
"/CreateUserDetails",
extra: {
"selectedUser": usersData, "selectedUser": usersData,
"isViewMode": false, "isViewMode": false,
}); },
);
}, },
), ),
], ],
@ -1546,14 +1628,31 @@ class _UserListScreenState extends State<UserListScreen> {
), ),
), ),
onTap: () async { onTap: () async {
Navigator.pop(context); // Close the menu // Navigator.pop(context); // Close the menu
final userId = int.parse(user['user_id'].toString()); // final userId = user['user_id'];
final usersData = await apiService.getSingleUser(userId); final userId = int.parse(
context.go("/CreateUserDetails", extra: { user['user_id'].toString(),
);
final usersData = await apiService
.getSingleUser(userId);
context.go(
"/CreateUserDetails",
extra: {
"selectedUser": usersData, "selectedUser": usersData,
"isViewMode": true, "isViewMode": false,
});
}, },
);
},
// onTap: () async {
// Navigator.pop(context); // Close the menu
// final userId = int.parse(user['user_id'].toString());
// final usersData = await apiService.getSingleUser(userId);
// context.go("/CreateUserDetails", extra: {
// "selectedUser": usersData,
// "isViewMode": true,
// });
// },
), ),
], ],
), ),

View File

@ -2,7 +2,7 @@ import 'dart:convert';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; // import 'package:flutter/rendering.dart';
import 'dart:html' as html; import 'dart:html' as html;
import 'package:frontend/config/apiUrl.dart'; // 1 newly added import 'package:frontend/config/apiUrl.dart'; // 1 newly added
import 'package:frontend/services/apiService.dart'; import 'package:frontend/services/apiService.dart';
@ -34,8 +34,8 @@ class _MyAppState extends State<MyApp> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
SemanticsBinding.instance // SemanticsBinding.instance
.ensureSemantics(); // Safe here -only for testing uncomment, Otherwise Email Template wont allow to type // .ensureSemantics(); // Safe here -only for testing uncomment, Otherwise Email Template wont allow to type
if (kIsWeb) { if (kIsWeb) {
final uri = Uri.parse(html.window.location.href); final uri = Uri.parse(html.window.location.href);
print("URI - $uri"); print("URI - $uri");
@ -110,7 +110,9 @@ class _MyAppState extends State<MyApp> {
setState(() { setState(() {
_isloading = false; _isloading = false;
}); });
if(_isloading){ const CircularProgressIndicator(); } if (_isloading) {
const CircularProgressIndicator();
}
final userData = prefs.getString('user_data'); final userData = prefs.getString('user_data');
print("MS Userdata - $userData"); print("MS Userdata - $userData");
final orgDataString = prefs.getString('org_data'); final orgDataString = prefs.getString('org_data');
@ -172,7 +174,10 @@ class _MyAppState extends State<MyApp> {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
await prefs.setString('auth_token', token); await prefs.setString('auth_token', token);
await prefs.setString('user_data', jsonEncode(userData)); // Store full user data await prefs.setString(
'user_data',
jsonEncode(userData),
); // Store full user data
if (userData != null) { if (userData != null) {
final pref = await SharedPreferences.getInstance(); final pref = await SharedPreferences.getInstance();
@ -188,7 +193,6 @@ class _MyAppState extends State<MyApp> {
print("MicroSoft Started"); print("MicroSoft Started");
await apiService.getOrganizationData(); await apiService.getOrganizationData();
print("MicroSoft end"); print("MicroSoft end");
} catch (e) { } catch (e) {
print('Error decoding token MS: $e'); print('Error decoding token MS: $e');
router.go('/'); router.go('/');
@ -197,12 +201,9 @@ class _MyAppState extends State<MyApp> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (_isAuthRedirect) { if (_isAuthRedirect) {
return const MaterialApp( return const MaterialApp(
home: Scaffold( home: Scaffold(body: Center(child: CircularProgressIndicator())),
body: Center(child: CircularProgressIndicator()),
),
); );
} }

View File

@ -14,7 +14,6 @@ const String apiUrl = 'https://apitest.tripapprovaltool.com/tstat_be';
* Check File : App.dart -> line 37 need to comment it "SemanticsBinding" **/ * Check File : App.dart -> line 37 need to comment it "SemanticsBinding" **/
// const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be'; // const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be';
/** Note : Adfactor UAT BE URL /** Note : Adfactor UAT BE URL
* incase "aujas" or "tstat" href means changed to "adfactor" * incase "aujas" or "tstat" href means changed to "adfactor"
* File : web/index.html - change below * File : web/index.html - change below

View File

@ -20,6 +20,7 @@ class Plan {
final String createdOn; final String createdOn;
final String? approverId; final String? approverId;
final String? delegaterId; final String? delegaterId;
final String? forexId;
Plan({ Plan({
required this.planId, required this.planId,
@ -41,6 +42,7 @@ class Plan {
required this.createdOn, required this.createdOn,
this.approverId, this.approverId,
this.delegaterId, this.delegaterId,
this.forexId,
}); });
factory Plan.fromJson(Map<String, dynamic> json) { factory Plan.fromJson(Map<String, dynamic> json) {
@ -56,7 +58,8 @@ class Plan {
: json['approver_status']?.toString() ?? "", : json['approver_status']?.toString() ?? "",
status: json['status'] == "0" ? "Inactive" : "Active", status: json['status'] == "0" ? "Inactive" : "Active",
costCenter: json['cost_center_value']?.toString() ?? "", costCenter: json['cost_center_value']?.toString() ?? "",
functionalDepartment: json['functional_department_value']?.toString() ?? "", functionalDepartment:
json['functional_department_value']?.toString() ?? "",
purposeOfTravel: json['purpose_of_travel_value']?.toString() ?? "", purposeOfTravel: json['purpose_of_travel_value']?.toString() ?? "",
soNumber: json['so_number']?.toString() ?? "", soNumber: json['so_number']?.toString() ?? "",
description: json['description']?.toString() ?? "", description: json['description']?.toString() ?? "",
@ -73,9 +76,15 @@ class Plan {
statusValue: json["status_value"]?.toString() ?? "", statusValue: json["status_value"]?.toString() ?? "",
createdOn: json["created_on"]?.toString() ?? "", createdOn: json["created_on"]?.toString() ?? "",
approverId: approverId:
json["approver_id"] == null ? '' : json['approver_id']?.toString() ?? "", json["approver_id"] == null
? ''
: json['approver_id']?.toString() ?? "",
delegaterId: delegaterId:
json["delegater_id"] == null ? '' : json['delegater_id']?.toString() ?? "", json["delegater_id"] == null
? ''
: json['delegater_id']?.toString() ?? "",
forexId:
json["forex_id"] == null ? '' : json['forex_id']?.toString() ?? "",
); );
} }
} }

View File

@ -71,7 +71,7 @@ class PlanPopupMenu extends StatelessWidget {
IconButton( IconButton(
icon: Icon( icon: Icon(
Icons.download, Icons.download,
color: Color(0xFF114D8B), color: Color(0xFF475569),
size: 18, size: 18,
), ),
onPressed: () { onPressed: () {
@ -79,6 +79,22 @@ class PlanPopupMenu extends StatelessWidget {
apiService.getPdfDownload(plan.planId); apiService.getPdfDownload(plan.planId);
}, },
), ),
if (plan.statusValue == "Approved" &&
plan.forexId != null &&
plan.forexId != '')
IconButton(
icon: Icon(
Icons.monetization_on_outlined,
color: Color(0xFF475569),
size: 18,
),
tooltip: 'Download Forex PDF',
onPressed: () {
Navigator.pop(context);
apiService.getPdfDownload(plan.forexId);
},
),
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons.comment, Icons.comment,