UI_TRIPTYPE_SERVICE_HANDLING
This commit is contained in:
parent
8d6b62f0fa
commit
a32fb0d0c3
File diff suppressed because it is too large
Load Diff
@ -373,7 +373,15 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
||||
// color: Colors.amber,
|
||||
),
|
||||
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(
|
||||
// padding: const EdgeInsets.all(10.0),
|
||||
color: isDesktop ? Colors.white : Color(0xFFFCFCFC),
|
||||
@ -473,6 +481,7 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
||||
if (!isDesktop) const SizedBox(height: 10),
|
||||
if (!isDesktop)
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width * 0.85,
|
||||
@ -694,14 +703,18 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
||||
),
|
||||
|
||||
DataCell(
|
||||
Text(
|
||||
plan.tripTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontFamily: "Inter",
|
||||
SizedBox(
|
||||
width: 130,
|
||||
child: Text(
|
||||
plan.tripTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontFamily: "Inter",
|
||||
),
|
||||
softWrap: true,
|
||||
maxLines: 2,
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
softWrap: true,
|
||||
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(
|
||||
icon: const Icon(
|
||||
Icons.comment,
|
||||
@ -1003,6 +1044,7 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
||||
PlanPopupMenu(
|
||||
plan: plan,
|
||||
deletePlan: deletePlan,
|
||||
|
||||
apiService: apiService,
|
||||
layoutColor: layoutColor,
|
||||
),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -254,8 +254,8 @@ class _FlightListWidgetState extends State<FlightListWidget> {
|
||||
"No Data Found",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
|
||||
@ -448,8 +448,9 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
String? selectedPurpose;
|
||||
|
||||
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 = [];
|
||||
List<Map<String, dynamic>> visaList = [];
|
||||
List<Map<String, dynamic>> insuranceList = [];
|
||||
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 {
|
||||
// pretend we fetch something
|
||||
await Future.delayed(Duration(seconds: 1)); // Example async operation
|
||||
@ -1850,6 +1901,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
onItineraryUpdate: handleItineraryUpdate,
|
||||
onExeptionalClass: handleExcentionalClass,
|
||||
loginUser: selfId,
|
||||
|
||||
selectedPlanData: planData,
|
||||
isViewMode: widget.isViewMode,
|
||||
),
|
||||
@ -1948,10 +2000,45 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
print("TRIP CLICKESS1");
|
||||
// Request focus when user taps
|
||||
focusNodes["trip_typeFocusNode"]?.requestFocus();
|
||||
print("TRIP CLICKESS15");
|
||||
},
|
||||
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(
|
||||
showSearchBox: false, // Optionally enable search
|
||||
fit: FlexFit.loose,
|
||||
@ -2046,6 +2133,16 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
widget.isViewMode
|
||||
? null
|
||||
: (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) {
|
||||
setState(() {
|
||||
_selectedTripType =
|
||||
@ -2059,6 +2156,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
fetchTrainFlightClass(
|
||||
int.parse(_selectedTripType!),
|
||||
);
|
||||
|
||||
dynamicItineraryKey.currentState
|
||||
?.updateSelectedServices();
|
||||
});
|
||||
|
||||
@ -104,6 +104,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
print("DynamicItinerary");
|
||||
super.initState();
|
||||
handleSelectedPlan();
|
||||
updateSelectedServices();
|
||||
@ -128,7 +129,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
||||
// selectedIndex = null;
|
||||
// selectedItem = null;
|
||||
// });
|
||||
|
||||
print("updateTripType - $_tripType");
|
||||
updateTripType(widget.tripType);
|
||||
}
|
||||
}
|
||||
@ -187,6 +188,9 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
||||
_tripType = newTripType;
|
||||
});
|
||||
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 {
|
||||
// await loadAllServices();
|
||||
// await loadOrgSelectedAlServices();
|
||||
@ -389,6 +400,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
||||
}
|
||||
|
||||
void handleSelectedPlan() {
|
||||
print("handleSelectedPlan");
|
||||
// Check if selectedPlanData has itinerary data
|
||||
if (hasAnyItineraryData()) {
|
||||
print("selectedPlanData HAS DATA");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
61
lib/app.dart
61
lib/app.dart
@ -2,7 +2,7 @@ import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
// import 'package:flutter/rendering.dart';
|
||||
import 'dart:html' as html;
|
||||
import 'package:frontend/config/apiUrl.dart'; // 1 newly added
|
||||
import 'package:frontend/services/apiService.dart';
|
||||
@ -34,8 +34,8 @@ class _MyAppState extends State<MyApp> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
SemanticsBinding.instance
|
||||
.ensureSemantics(); // Safe here -only for testing uncomment, Otherwise Email Template wont allow to type
|
||||
// SemanticsBinding.instance
|
||||
// .ensureSemantics(); // Safe here -only for testing uncomment, Otherwise Email Template wont allow to type
|
||||
if (kIsWeb) {
|
||||
final uri = Uri.parse(html.window.location.href);
|
||||
print("URI - $uri");
|
||||
@ -76,7 +76,7 @@ class _MyAppState extends State<MyApp> {
|
||||
});
|
||||
|
||||
html.window.console.log("Auth code detected: $authCode");
|
||||
}else {
|
||||
} else {
|
||||
html.window.console.log("No auth code found or wrong path.");
|
||||
}
|
||||
}
|
||||
@ -110,32 +110,34 @@ class _MyAppState extends State<MyApp> {
|
||||
setState(() {
|
||||
_isloading = false;
|
||||
});
|
||||
if(_isloading){ const CircularProgressIndicator(); }
|
||||
if (_isloading) {
|
||||
const CircularProgressIndicator();
|
||||
}
|
||||
final userData = prefs.getString('user_data');
|
||||
print("MS Userdata - $userData");
|
||||
final orgDataString = prefs.getString('org_data');
|
||||
print("MS orgdata - $orgDataString");
|
||||
|
||||
if (orgDataString != null && userData != null){
|
||||
Fluttertoast.showToast(
|
||||
msg: "You're in!",
|
||||
toastLength: Toast.LENGTH_SHORT,
|
||||
gravity: ToastGravity.CENTER,
|
||||
backgroundColor: Colors.green,
|
||||
textColor: Colors.white,
|
||||
fontSize: 16,
|
||||
webBgColor: "linear-gradient(to right, #28a745, #28a745)",
|
||||
);
|
||||
if (orgDataString != null && userData != null) {
|
||||
Fluttertoast.showToast(
|
||||
msg: "You're in!",
|
||||
toastLength: Toast.LENGTH_SHORT,
|
||||
gravity: ToastGravity.CENTER,
|
||||
backgroundColor: Colors.green,
|
||||
textColor: Colors.white,
|
||||
fontSize: 16,
|
||||
webBgColor: "linear-gradient(to right, #28a745, #28a745)",
|
||||
);
|
||||
|
||||
print("Microsoft User Logged In Refer the Role - $userRole");
|
||||
// Navigate based on role
|
||||
if (userRole == "Travel Agent") {
|
||||
router.go('/listTravelAgentPlan');
|
||||
} else if (userRole == "Org Admin" || userRole == "Travel Admin") {
|
||||
router.go('/StatusDashboard');
|
||||
} else {
|
||||
router.go('/listPlan');
|
||||
}
|
||||
print("Microsoft User Logged In Refer the Role - $userRole");
|
||||
// Navigate based on role
|
||||
if (userRole == "Travel Agent") {
|
||||
router.go('/listTravelAgentPlan');
|
||||
} else if (userRole == "Org Admin" || userRole == "Travel Admin") {
|
||||
router.go('/StatusDashboard');
|
||||
} else {
|
||||
router.go('/listPlan');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw Exception('Token missing in response.');
|
||||
@ -172,7 +174,10 @@ class _MyAppState extends State<MyApp> {
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
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) {
|
||||
final pref = await SharedPreferences.getInstance();
|
||||
@ -188,7 +193,6 @@ class _MyAppState extends State<MyApp> {
|
||||
print("MicroSoft Started");
|
||||
await apiService.getOrganizationData();
|
||||
print("MicroSoft end");
|
||||
|
||||
} catch (e) {
|
||||
print('Error decoding token MS: $e');
|
||||
router.go('/');
|
||||
@ -197,12 +201,9 @@ class _MyAppState extends State<MyApp> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
if (_isAuthRedirect) {
|
||||
return const MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
home: Scaffold(body: Center(child: CircularProgressIndicator())),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@ class Plan {
|
||||
final String createdOn;
|
||||
final String? approverId;
|
||||
final String? delegaterId;
|
||||
final String? forexId;
|
||||
|
||||
Plan({
|
||||
required this.planId,
|
||||
@ -41,6 +42,7 @@ class Plan {
|
||||
required this.createdOn,
|
||||
this.approverId,
|
||||
this.delegaterId,
|
||||
this.forexId,
|
||||
});
|
||||
|
||||
factory Plan.fromJson(Map<String, dynamic> json) {
|
||||
@ -55,8 +57,9 @@ class Plan {
|
||||
? ''
|
||||
: json['approver_status']?.toString() ?? "",
|
||||
status: json['status'] == "0" ? "Inactive" : "Active",
|
||||
costCenter: json['cost_center_value']?.toString() ?? "" ,
|
||||
functionalDepartment: json['functional_department_value']?.toString() ?? "",
|
||||
costCenter: json['cost_center_value']?.toString() ?? "",
|
||||
functionalDepartment:
|
||||
json['functional_department_value']?.toString() ?? "",
|
||||
purposeOfTravel: json['purpose_of_travel_value']?.toString() ?? "",
|
||||
soNumber: json['so_number']?.toString() ?? "",
|
||||
description: json['description']?.toString() ?? "",
|
||||
@ -73,9 +76,15 @@ class Plan {
|
||||
statusValue: json["status_value"]?.toString() ?? "",
|
||||
createdOn: json["created_on"]?.toString() ?? "",
|
||||
approverId:
|
||||
json["approver_id"] == null ? '' : json['approver_id']?.toString() ?? "",
|
||||
json["approver_id"] == null
|
||||
? ''
|
||||
: json['approver_id']?.toString() ?? "",
|
||||
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() ?? "",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ class PlanPopupMenu extends StatelessWidget {
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.download,
|
||||
color: Color(0xFF114D8B),
|
||||
color: Color(0xFF475569),
|
||||
size: 18,
|
||||
),
|
||||
onPressed: () {
|
||||
@ -79,6 +79,22 @@ class PlanPopupMenu extends StatelessWidget {
|
||||
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(
|
||||
icon: const Icon(
|
||||
Icons.comment,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user