UI_TRIPTYPE_SERVICE_HANDLING

This commit is contained in:
venbaittech 2025-07-31 18:15:37 +05:30
parent 8d6b62f0fa
commit a32fb0d0c3
10 changed files with 2309 additions and 1914 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),
@ -802,8 +802,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 +834,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 +844,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
), ),
), ),
), ),
),
DataColumn( DataColumn(
label: Text( label: Text(
@ -905,6 +907,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 +930,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 +987,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 +999,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 +1040,8 @@ class _ListAllPlansState extends State<ListAllPlans> {
), ),
child: Row( child: Row(
mainAxisSize: mainAxisSize:
MainAxisSize.min, MainAxisSize
.min,
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment MainAxisAlignment
.center, .center,
@ -1103,9 +1112,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 +1131,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
.getPdfDownload(
plan.forexId,
);
},
),
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons.comment, Icons.comment,
@ -1141,8 +1178,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 +1201,8 @@ class _ListAllPlansState extends State<ListAllPlans> {
}).toList(), }).toList(),
), ),
), ),
)); ),
);
}, },
); );
@ -1369,7 +1406,7 @@ class _ListAllPlansState extends State<ListAllPlans> {
Icons Icons
.download, .download,
color: Color( color: Color(
0xFF114D8B, 0xFF475569,
), ),
size: 18, size: 18,
), ),
@ -1385,6 +1422,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
.getPdfDownload(
plan.forexId,
);
},
),
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons Icons
@ -1433,7 +1499,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 +1536,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),
@ -473,6 +481,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 +703,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 +883,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
.getPdfDownload(
plan.forexId,
);
},
),
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons.comment, Icons.comment,
@ -1003,6 +1044,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
@ -818,14 +818,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 +935,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 +1044,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 +1175,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 +1185,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 +1226,8 @@ class _ApprovalListState extends State<ApprovalList> {
), ),
child: Row( child: Row(
mainAxisSize: mainAxisSize:
MainAxisSize.min, MainAxisSize
.min,
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment MainAxisAlignment
.center, .center,
@ -1311,9 +1315,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 +1334,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
.getPdfDownload(
plan.forexId,
);
},
),
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons.comment, Icons.comment,
@ -1349,8 +1382,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 +1453,9 @@ class _ApprovalListState extends State<ApprovalList> {
); );
}).toList(), }).toList(),
), ),
))); ),
),
);
}, },
); );
@ -1469,7 +1503,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 +1587,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 +1615,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 +1627,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 +1643,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
.getPdfDownload(
plan.forexId,
);
},
),
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons Icons
@ -1633,15 +1683,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 +1718,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 +1740,8 @@ class _ApprovalListState extends State<ApprovalList> {
), ),
), ),
], ],
),), ),
),
Column( Column(
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.end, MainAxisAlignment.end,

View File

@ -254,8 +254,8 @@ 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,
), ),
), ),

View File

@ -448,8 +448,9 @@ class CreateNewPlansState extends State<CreateNewPlan> {
String? selectedPurpose; String? selectedPurpose;
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 = [];
@ -1316,6 +1317,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 +1901,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,
), ),
@ -1948,10 +2000,45 @@ class CreateNewPlansState extends State<CreateNewPlan> {
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;
},
popupProps: PopupProps.menu( popupProps: PopupProps.menu(
showSearchBox: false, // Optionally enable search showSearchBox: false, // Optionally enable search
fit: FlexFit.loose, fit: FlexFit.loose,
@ -2046,6 +2133,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 =
@ -2059,6 +2156,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
fetchTrainFlightClass( fetchTrainFlightClass(
int.parse(_selectedTripType!), int.parse(_selectedTripType!),
); );
dynamicItineraryKey.currentState dynamicItineraryKey.currentState
?.updateSelectedServices(); ?.updateSelectedServices();
}); });

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");

View File

@ -78,7 +78,7 @@ class _ListPlansState extends State<ListPlans> {
print("msUser - $msUser"); print("msUser - $msUser");
html.window.history.pushState(null, '', html.window.location.href); html.window.history.pushState(null, '', html.window.location.href);
if(!msUser){ if (!msUser) {
_popStateListener = html.window.onPopState.listen((event) { _popStateListener = html.window.onPopState.listen((event) {
if (!_dialogShown && mounted) { if (!_dialogShown && mounted) {
_showBackConfirmationDialog(); _showBackConfirmationDialog();
@ -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
@ -839,6 +842,7 @@ 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,
@ -964,7 +968,7 @@ class _ListPlansState extends State<ListPlans> {
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
child:ConstrainedBox( child: ConstrainedBox(
constraints: BoxConstraints(minWidth: minWidth), constraints: BoxConstraints(minWidth: minWidth),
child: DataTable( child: DataTable(
dividerThickness: 0.5, dividerThickness: 0.5,
@ -986,7 +990,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 +1000,7 @@ class _ListPlansState extends State<ListPlans> {
), ),
), ),
), ),
),
DataColumn( DataColumn(
label: Text( label: Text(
'Emp Code', 'Emp Code',
@ -1064,14 +1071,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 +1127,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 +1149,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 +1198,8 @@ class _ListPlansState extends State<ListPlans> {
), ),
child: Row( child: Row(
mainAxisSize: mainAxisSize:
MainAxisSize.min, MainAxisSize
.min,
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment MainAxisAlignment
.center, .center,
@ -1212,7 +1224,8 @@ class _ListPlansState extends State<ListPlans> {
plan.planId, plan.planId,
isViewMode: isViewMode:
true, true,
isMyTrips: true, isMyTrips:
true,
); );
}, },
), ),
@ -1261,9 +1274,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 +1293,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
.getPdfDownload(
plan.forexId,
);
},
),
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons.comment, Icons.comment,
@ -1299,8 +1341,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 +1411,9 @@ class _ListPlansState extends State<ListPlans> {
); );
}).toList(), }).toList(),
), ),
))); ),
),
);
}, },
); );
@ -1419,7 +1462,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 +1538,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 +1565,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 +1581,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
.getPdfDownload(
plan.forexId,
);
}, },
), ),
IconButton( IconButton(
@ -1563,11 +1651,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 +1685,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 +1705,8 @@ class _ListPlansState extends State<ListPlans> {
), ),
), ),
], ],
),), ),
),
Column( Column(
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.end, MainAxisAlignment.end,

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");
@ -76,7 +76,7 @@ class _MyAppState extends State<MyApp> {
}); });
html.window.console.log("Auth code detected: $authCode"); html.window.console.log("Auth code detected: $authCode");
}else { } else {
html.window.console.log("No auth code found or wrong path."); html.window.console.log("No auth code found or wrong path.");
} }
} }
@ -110,13 +110,15 @@ 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');
print("MS orgdata - $orgDataString"); print("MS orgdata - $orgDataString");
if (orgDataString != null && userData != null){ if (orgDataString != null && userData != null) {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: "You're in!", msg: "You're in!",
toastLength: Toast.LENGTH_SHORT, toastLength: Toast.LENGTH_SHORT,
@ -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

@ -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) {
@ -55,8 +57,9 @@ 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,