Exceptional Classes
This commit is contained in:
parent
e33af3cd8a
commit
53fd28d65d
@ -817,7 +817,7 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
|||||||
Navigator.pop(
|
Navigator.pop(
|
||||||
context,
|
context,
|
||||||
); // Close popup manually
|
); // Close popup manually
|
||||||
ApiService.viewPlan(
|
ApiService.viewPlanTravelAgent(
|
||||||
context,
|
context,
|
||||||
plan.planId,
|
plan.planId,
|
||||||
isViewMode:
|
isViewMode:
|
||||||
|
|||||||
@ -1,16 +1,20 @@
|
|||||||
|
import 'package:dropdown_search/dropdown_search.dart';
|
||||||
import 'package:flutter/material.dart';
|
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';
|
||||||
import 'package:responsive_builder/responsive_builder.dart';
|
import 'package:responsive_builder/responsive_builder.dart';
|
||||||
|
|
||||||
import '../../services/apiService.dart';
|
import '../../services/apiService.dart';
|
||||||
|
import '../../widgets/custom_confirmation_dialog.dart';
|
||||||
import '../../widgets/custom_text_field.dart';
|
import '../../widgets/custom_text_field.dart';
|
||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
|
|
||||||
class AccomodationScreen extends StatefulWidget {
|
class AccomodationScreen extends StatefulWidget {
|
||||||
final List<Map<String, dynamic>> flightData;
|
final List<Map<String, dynamic>> flightData;
|
||||||
final Function(bool) onClose; // Callback function
|
final Map<String, dynamic>? apiDataForClass;
|
||||||
|
final Function(String, bool) onClose; // Callback function
|
||||||
final Function(Map<String, dynamic>) onSaveAccomadation;
|
final Function(Map<String, dynamic>) onSaveAccomadation;
|
||||||
|
final void Function(bool)? onExceptionalClass;
|
||||||
final Map<String, dynamic>? selectedItem;
|
final Map<String, dynamic>? selectedItem;
|
||||||
final String? loginUser;
|
final String? loginUser;
|
||||||
final String? tripType;
|
final String? tripType;
|
||||||
@ -22,6 +26,8 @@ class AccomodationScreen extends StatefulWidget {
|
|||||||
required this.loginUser,
|
required this.loginUser,
|
||||||
required this.flightData,
|
required this.flightData,
|
||||||
this.tripType,
|
this.tripType,
|
||||||
|
this.apiDataForClass,
|
||||||
|
this.onExceptionalClass,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -34,6 +40,10 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
// late Map<String, String> countryMap;
|
// late Map<String, String> countryMap;
|
||||||
Map<String, String> countryMap = {};
|
Map<String, String> countryMap = {};
|
||||||
|
|
||||||
|
String? selectedClass;
|
||||||
|
String? exceptionalClass = "0";
|
||||||
|
bool hasExceptionalClass = false;
|
||||||
|
|
||||||
late ValueNotifier<String?> flightFirstTripDateNotifier;
|
late ValueNotifier<String?> flightFirstTripDateNotifier;
|
||||||
late ValueNotifier<String?> flightLastTripDateNotifier;
|
late ValueNotifier<String?> flightLastTripDateNotifier;
|
||||||
late ValueNotifier<String?> flightFirstToDestinationNotifier;
|
late ValueNotifier<String?> flightFirstToDestinationNotifier;
|
||||||
@ -42,6 +52,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
|
|
||||||
final FocusNode _destinationFocusNode = FocusNode();
|
final FocusNode _destinationFocusNode = FocusNode();
|
||||||
final FocusNode _hotelNameFocusNode = FocusNode();
|
final FocusNode _hotelNameFocusNode = FocusNode();
|
||||||
|
final FocusNode _CategoryFocusNode = FocusNode();
|
||||||
final FocusNode _checkInFocusNode = FocusNode();
|
final FocusNode _checkInFocusNode = FocusNode();
|
||||||
final FocusNode _checkInTimeFocusNode = FocusNode();
|
final FocusNode _checkInTimeFocusNode = FocusNode();
|
||||||
final FocusNode _checkOutFocusNode = FocusNode();
|
final FocusNode _checkOutFocusNode = FocusNode();
|
||||||
@ -58,6 +69,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
|
|
||||||
bool _destinationFocused = false;
|
bool _destinationFocused = false;
|
||||||
bool _isHotelNameFocused = false;
|
bool _isHotelNameFocused = false;
|
||||||
|
bool _CategoryFocused = false;
|
||||||
bool _checkInFocus = false;
|
bool _checkInFocus = false;
|
||||||
bool _checkInTimeFocus = false;
|
bool _checkInTimeFocus = false;
|
||||||
bool _checkOutFocus = false;
|
bool _checkOutFocus = false;
|
||||||
@ -78,11 +90,13 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
Map<String, dynamic> data = {
|
Map<String, dynamic> data = {
|
||||||
"destination_city": _destinationController.text,
|
"destination_city": _destinationController.text,
|
||||||
"hotel_name": _hotelNameController.text,
|
"hotel_name": _hotelNameController.text,
|
||||||
|
"class": selectedClass,
|
||||||
"checkin_date": _checkInController.text,
|
"checkin_date": _checkInController.text,
|
||||||
"checkin_time": _checkInTimeController.text,
|
"checkin_time": _checkInTimeController.text,
|
||||||
"checkout_date": _checkOutController.text,
|
"checkout_date": _checkOutController.text,
|
||||||
"checkout_time": _checkOutTimeController.text,
|
"checkout_time": _checkOutTimeController.text,
|
||||||
"comments": _commentsController.text,
|
"comments": _commentsController.text,
|
||||||
|
"is_this_exceptional": exceptionalClass,
|
||||||
"created_by": widget.loginUser,
|
"created_by": widget.loginUser,
|
||||||
"updated_by": widget.loginUser,
|
"updated_by": widget.loginUser,
|
||||||
};
|
};
|
||||||
@ -191,6 +205,16 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
_checkOutTimeController.text = '12:00'; // 12 PM
|
_checkOutTimeController.text = '12:00'; // 12 PM
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (widget.selectedItem != null &&
|
||||||
|
widget.selectedItem!["is_this_exceptional"] != null) {
|
||||||
|
exceptionalClass = widget.selectedItem!["is_this_exceptional"].toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the selected value if available
|
||||||
|
if (widget.selectedItem != null && widget.selectedItem!["class"] != null) {
|
||||||
|
selectedClass = widget.selectedItem!["class"].toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -365,9 +389,13 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
return; // Stop execution if validation fails
|
return; // Stop execution if validation fails
|
||||||
} else {
|
} else {
|
||||||
widget.onSaveAccomadation(accomadationData);
|
widget.onSaveAccomadation(accomadationData);
|
||||||
|
|
||||||
|
// if (hasExceptionalClass) {
|
||||||
|
// widget.onExceptionalClass?.call(true); // or false
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
widget.onClose(false); // Close screen after saving
|
widget.onClose("Accomodation", false); // Close screen after saving
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -421,6 +449,34 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildFirstRow(isDesktop) {
|
List<Widget> _buildFirstRow(isDesktop) {
|
||||||
|
List<dynamic> purposeList = widget.apiDataForClass?['hotel_class'] ?? [];
|
||||||
|
|
||||||
|
List<DropdownMenuItem<String>> dropdownItems =
|
||||||
|
purposeList
|
||||||
|
.map(
|
||||||
|
(item) => DropdownMenuItem<String>(
|
||||||
|
value: item['dropdown_key'],
|
||||||
|
child: Text(item['dropdown_value']),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (dropdownItems.isEmpty) {
|
||||||
|
dropdownItems.add(
|
||||||
|
DropdownMenuItem<String>(
|
||||||
|
value: null,
|
||||||
|
child: Text(
|
||||||
|
"No options available",
|
||||||
|
style: TextStyle(color: Colors.grey),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default selected value
|
||||||
|
// selectedClass ??=
|
||||||
|
// dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
// Column(
|
// Column(
|
||||||
// children: [
|
// children: [
|
||||||
@ -493,13 +549,13 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _isHotelNameFocused,
|
isFocused: _isHotelNameFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width:
|
// width:
|
||||||
isDesktop
|
// isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
// ? MediaQuery.of(context).size.width * 0.34
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
// : MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
@ -525,6 +581,147 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Category *",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Color(0xFF575A74),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
CustomTextFieldItnerarySubWrapper(
|
||||||
|
// isFocused: focusStates["_class${index}Focused"] ?? false,
|
||||||
|
isFocused: false,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
|
isDesktop: isDesktop,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 40,
|
||||||
|
width: double.infinity,
|
||||||
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
|
key:
|
||||||
|
selectedClass == null
|
||||||
|
? UniqueKey()
|
||||||
|
: ValueKey(selectedClass),
|
||||||
|
|
||||||
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
|
// selectedItem: purposeList.firstWhere(
|
||||||
|
// (item) => item['dropdown_key'] == selectedClass,
|
||||||
|
// orElse: () => {},
|
||||||
|
// ),
|
||||||
|
selectedItem:
|
||||||
|
selectedClass != null
|
||||||
|
? purposeList.firstWhere(
|
||||||
|
(item) => item['dropdown_key'] == selectedClass,
|
||||||
|
orElse: () => {},
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
|
||||||
|
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||||
|
popupProps: PopupProps.menu(
|
||||||
|
showSearchBox: false,
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
|
itemBuilder: (context, item, isSelected) {
|
||||||
|
print("categotey - $item ");
|
||||||
|
final bool isNotAllowed = item['is_allowed'] == 'No';
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 5,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item['dropdown_value'] ?? '',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: isNotAllowed ? Colors.redAccent : Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||||
|
dropdownSearchDecoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownBuilder: (context, selectedItem) {
|
||||||
|
if (selectedItem == null || selectedItem.isEmpty) {
|
||||||
|
return Text(
|
||||||
|
"Select ",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
color: Colors.grey,
|
||||||
|
fontSize: 13,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Text(
|
||||||
|
selectedItem['dropdown_value'] ?? '',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
// color: Colors.red,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onChanged:
|
||||||
|
purposeList.isNotEmpty
|
||||||
|
? (Map<String, dynamic>? newValue) async {
|
||||||
|
if (newValue != null &&
|
||||||
|
newValue['is_allowed'] == 'No') {
|
||||||
|
final confirm = await showNotAllowedDialog(
|
||||||
|
context,
|
||||||
|
message:
|
||||||
|
"You are not entitled for this service. If you wish to continue with this service, you may require another approval.",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (confirm) {
|
||||||
|
setState(() {
|
||||||
|
exceptionalClass = "1";
|
||||||
|
selectedClass = newValue['dropdown_key'];
|
||||||
|
});
|
||||||
|
print("Selected Purpose: ${selectedClass}");
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
exceptionalClass = "0";
|
||||||
|
selectedClass =
|
||||||
|
null; // ❌ Clear selection if user cancels
|
||||||
|
});
|
||||||
|
print(
|
||||||
|
"selectedItem resolved to: ${selectedClass}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else if (newValue != null &&
|
||||||
|
newValue['is_allowed'] == 'yes') {
|
||||||
|
setState(() {
|
||||||
|
exceptionalClass = "0";
|
||||||
|
selectedClass = newValue?['dropdown_key'];
|
||||||
|
print("Selected Purpose: ${selectedClass}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (errorMessages["class"] != null) ...[
|
||||||
|
SizedBox(height: 5), // Space before error message
|
||||||
|
Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
// if (isDesktop) Spacer() else SizedBox(height: 8),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1025,7 +1222,8 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
widget.onClose(false); // Close the dialog or screen
|
widget.onClose("Accomodation", false);
|
||||||
|
// widget.onClose(false); // Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import '../../widgets/custom_text_itnerary_sub.dart';
|
|||||||
|
|
||||||
class BusScreen extends StatefulWidget {
|
class BusScreen extends StatefulWidget {
|
||||||
final Map<String, dynamic>? apiData;
|
final Map<String, dynamic>? apiData;
|
||||||
final Function(bool) onClose;
|
final Function(String, bool) onClose;
|
||||||
final Function(Map<String, dynamic>) onSaveBus;
|
final Function(Map<String, dynamic>) onSaveBus;
|
||||||
final Map<String, dynamic>? selectedItem;
|
final Map<String, dynamic>? selectedItem;
|
||||||
final String? loginUser;
|
final String? loginUser;
|
||||||
@ -190,8 +190,8 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
} else {
|
} else {
|
||||||
widget.onSaveBus(busData);
|
widget.onSaveBus(busData);
|
||||||
}
|
}
|
||||||
|
widget.onClose("Bus", false);
|
||||||
widget.onClose(false); // Close screen after saving
|
// widget.onClose(false); // Close screen after saving
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -678,7 +678,8 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
widget.onClose(false); // Close the dialog or screen
|
widget.onClose("Bus", false);
|
||||||
|
// widget.onClose(false); // Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import 'package:intl/intl.dart';
|
|||||||
import 'package:responsive_builder/responsive_builder.dart';
|
import 'package:responsive_builder/responsive_builder.dart';
|
||||||
|
|
||||||
import '../../utils/auth_utils.dart';
|
import '../../utils/auth_utils.dart';
|
||||||
|
import '../../widgets/custom_confirmation_dialog.dart';
|
||||||
import '../../widgets/custom_radio_button.dart';
|
import '../../widgets/custom_radio_button.dart';
|
||||||
import '../../widgets/custom_text_field.dart';
|
import '../../widgets/custom_text_field.dart';
|
||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
@ -17,7 +18,7 @@ class FlightScreen extends StatefulWidget {
|
|||||||
final Map<String, dynamic>? apiData;
|
final Map<String, dynamic>? apiData;
|
||||||
final Map<String, dynamic>? apiDataForClass;
|
final Map<String, dynamic>? apiDataForClass;
|
||||||
final String? loginUser;
|
final String? loginUser;
|
||||||
final Function(bool) onClose;
|
final Function(String, bool) onClose;
|
||||||
final Function(Map<String, dynamic>) onSaveFlight;
|
final Function(Map<String, dynamic>) onSaveFlight;
|
||||||
final Map<String, dynamic>? selectedItem;
|
final Map<String, dynamic>? selectedItem;
|
||||||
final ValueNotifier<String?> tripTypeNotifier;
|
final ValueNotifier<String?> tripTypeNotifier;
|
||||||
@ -60,6 +61,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
|
|
||||||
String? selectedTripType;
|
String? selectedTripType;
|
||||||
Map<int, String?> selectedClasses = {}; // Store class selection for each trip
|
Map<int, String?> selectedClasses = {}; // Store class selection for each trip
|
||||||
|
Map<int, String?> exceptionalClass =
|
||||||
|
{}; // Store class selection for each trip
|
||||||
Map<int, String?> selectedFrom = {}; // Store class selection for each trip
|
Map<int, String?> selectedFrom = {}; // Store class selection for each trip
|
||||||
Map<int, String?> selectedTo = {}; // Store class selection for each trip
|
Map<int, String?> selectedTo = {}; // Store class selection for each trip
|
||||||
String? selectedvisa_available;
|
String? selectedvisa_available;
|
||||||
@ -409,6 +412,7 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
for (int i = 1; i <= rowCount; i++) {
|
for (int i = 1; i <= rowCount; i++) {
|
||||||
final trip = {
|
final trip = {
|
||||||
"class": selectedClasses[i],
|
"class": selectedClasses[i],
|
||||||
|
"is_this_exceptional": exceptionalClass[i],
|
||||||
// "from_place": countryMap[selectedFrom[i]],
|
// "from_place": countryMap[selectedFrom[i]],
|
||||||
"from_place": selectedFrom[i],
|
"from_place": selectedFrom[i],
|
||||||
"to_place": selectedTo[i],
|
"to_place": selectedTo[i],
|
||||||
@ -505,6 +509,7 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
int index = i + 1; // Use 1-based indexing to match the form
|
int index = i + 1; // Use 1-based indexing to match the form
|
||||||
|
|
||||||
selectedClasses[index] = trip["class"].toString();
|
selectedClasses[index] = trip["class"].toString();
|
||||||
|
exceptionalClass[index] = trip["is_this_exceptional"].toString();
|
||||||
selectedFrom[index] = trip["from_place"].toString();
|
selectedFrom[index] = trip["from_place"].toString();
|
||||||
selectedTo[index] = trip["to_place"].toString();
|
selectedTo[index] = trip["to_place"].toString();
|
||||||
// textControllers["_from${index}Controller"] =
|
// textControllers["_from${index}Controller"] =
|
||||||
@ -545,7 +550,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
widget.onSaveFlight(flightsData); // Send object to parent
|
widget.onSaveFlight(flightsData); // Send object to parent
|
||||||
widget.onClose(false);
|
// widget.onClose(false);
|
||||||
|
widget.onClose("Flight", false);
|
||||||
|
|
||||||
print("FlightData - $flightsData");
|
print("FlightData - $flightsData");
|
||||||
}
|
}
|
||||||
@ -789,6 +795,16 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
|
|
||||||
selectedClasses = updatedClasses; // Update the map
|
selectedClasses = updatedClasses; // Update the map
|
||||||
|
|
||||||
|
Map<int, String?> updatedExptionalClasses = {};
|
||||||
|
newIndex = 1;
|
||||||
|
|
||||||
|
for (int i = 1; i <= exceptionalClass.length; i++) {
|
||||||
|
if (i == index) continue; // Skip the one being deleted
|
||||||
|
updatedExptionalClasses[newIndex] = exceptionalClass[i];
|
||||||
|
newIndex++;
|
||||||
|
}
|
||||||
|
exceptionalClass = updatedExptionalClasses;
|
||||||
|
|
||||||
// Shift the selectedFrom map BEFORE removing the index
|
// Shift the selectedFrom map BEFORE removing the index
|
||||||
Map<int, String?> updatedFrom = {};
|
Map<int, String?> updatedFrom = {};
|
||||||
newIndex = 1;
|
newIndex = 1;
|
||||||
@ -1320,8 +1336,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default selected value
|
// Default selected value
|
||||||
selectedClasses[index] ??=
|
// selectedClasses[index] ??=
|
||||||
dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
// dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||||
// -------------------------------------------------
|
// -------------------------------------------------
|
||||||
|
|
||||||
DateTime? _selectedCheckOutDate;
|
DateTime? _selectedCheckOutDate;
|
||||||
@ -2046,16 +2062,30 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
},
|
},
|
||||||
child: DropdownSearch<Map<String, dynamic>>(
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
items: purposeList.cast<Map<String, dynamic>>(),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
selectedItem: purposeList.firstWhere(
|
key:
|
||||||
(item) => item['dropdown_key'] == selectedClasses[index],
|
selectedClasses[index] == null
|
||||||
orElse: () => {},
|
? UniqueKey()
|
||||||
),
|
: ValueKey(selectedClasses[index]),
|
||||||
|
// selectedItem: purposeList.firstWhere(
|
||||||
|
// (item) => item['dropdown_key'] == selectedClasses[index],
|
||||||
|
// orElse: () => {},
|
||||||
|
// ),
|
||||||
|
selectedItem:
|
||||||
|
selectedClasses[index] != null
|
||||||
|
? purposeList.firstWhere(
|
||||||
|
(item) =>
|
||||||
|
item['dropdown_key'] ==
|
||||||
|
selectedClasses[index],
|
||||||
|
orElse: () => {},
|
||||||
|
)
|
||||||
|
: null,
|
||||||
itemAsString: (item) => item['dropdown_value'] ?? '',
|
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
showSearchBox: false,
|
showSearchBox: false,
|
||||||
fit: FlexFit.loose,
|
fit: FlexFit.loose,
|
||||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
itemBuilder: (context, item, isSelected) {
|
itemBuilder: (context, item, isSelected) {
|
||||||
|
final bool isNotAllowed = item['is_allowed'] == 'No';
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
@ -2065,7 +2095,10 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
item['dropdown_value'] ?? '',
|
item['dropdown_value'] ?? '',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Colors.black,
|
color:
|
||||||
|
isNotAllowed
|
||||||
|
? Colors.redAccent
|
||||||
|
: Colors.black,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -2124,14 +2157,67 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
},
|
},
|
||||||
onChanged:
|
onChanged:
|
||||||
purposeList.isNotEmpty
|
purposeList.isNotEmpty
|
||||||
? (Map<String, dynamic>? newValue) {
|
? (Map<String, dynamic>? newValue) async {
|
||||||
setState(() {
|
// if (newValue != null &&
|
||||||
selectedClasses[index] =
|
// newValue['is_allowed'] == 'No') {
|
||||||
newValue?['dropdown_key'];
|
// print('not allowed');
|
||||||
print(
|
//
|
||||||
"Selected Class: ${selectedClasses[index]}",
|
// exceptionalClass[index] = "1";
|
||||||
|
// } else if (newValue != null &&
|
||||||
|
// newValue['is_allowed'] == 'yes') {
|
||||||
|
// print('not allowed');
|
||||||
|
//
|
||||||
|
// exceptionalClass[index] = "0";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// setState(() {
|
||||||
|
// selectedClasses[index] =
|
||||||
|
// newValue?['dropdown_key'];
|
||||||
|
// print(
|
||||||
|
// "Selected Class: ${selectedClasses[index]}",
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
|
||||||
|
if (newValue != null &&
|
||||||
|
newValue['is_allowed'] == 'No') {
|
||||||
|
final confirm = await showNotAllowedDialog(
|
||||||
|
context,
|
||||||
|
message:
|
||||||
|
"You are not entitled for this service. If you wish to continue with this service, you may require another approval.",
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
if (confirm) {
|
||||||
|
setState(() {
|
||||||
|
exceptionalClass[index] = "1";
|
||||||
|
selectedClasses[index] =
|
||||||
|
newValue['dropdown_key'];
|
||||||
|
});
|
||||||
|
print(
|
||||||
|
"Selected Purpose: ${selectedClasses[index]}",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
exceptionalClass[index] = "0";
|
||||||
|
selectedClasses[index] =
|
||||||
|
null; // ❌ Clear selection if user cancels
|
||||||
|
});
|
||||||
|
print(
|
||||||
|
"selectedItem resolved to: ${selectedClasses[index]}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else if (newValue != null &&
|
||||||
|
newValue['is_allowed'] == 'yes') {
|
||||||
|
setState(() {
|
||||||
|
exceptionalClass[index] = "0";
|
||||||
|
selectedClasses[index] =
|
||||||
|
newValue?['dropdown_key'];
|
||||||
|
print(
|
||||||
|
"Selected Purpose: ${selectedClasses[index]}",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
@ -2690,7 +2776,8 @@ class FlightScreenState extends State<FlightScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
widget.onClose(false); // Close the dialog or screen
|
widget.onClose("Flight", false);
|
||||||
|
// widget.onClose(false); // Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import 'package:http/http.dart' as http;
|
|||||||
class ForexScreen extends StatefulWidget {
|
class ForexScreen extends StatefulWidget {
|
||||||
final List<Map<String, dynamic>> flightData;
|
final List<Map<String, dynamic>> flightData;
|
||||||
final Map<String, dynamic>? apiData;
|
final Map<String, dynamic>? apiData;
|
||||||
final Function(bool) onClose;
|
final Function(String, bool) onClose;
|
||||||
final Map<String, dynamic>? selectedItem;
|
final Map<String, dynamic>? selectedItem;
|
||||||
final List<dynamic>? apiCountryData;
|
final List<dynamic>? apiCountryData;
|
||||||
final Function(Map<String, dynamic>) onSaveForex;
|
final Function(Map<String, dynamic>) onSaveForex;
|
||||||
@ -366,8 +366,8 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
} else {
|
} else {
|
||||||
widget.onSaveForex(forexData); // Send object to parent
|
widget.onSaveForex(forexData); // Send object to parent
|
||||||
}
|
}
|
||||||
|
widget.onClose("Forex", false);
|
||||||
widget.onClose(false); // Close screen after saving
|
// widget.onClose(false); // Close screen after saving
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime? _parseDate(String date) {
|
DateTime? _parseDate(String date) {
|
||||||
@ -2294,7 +2294,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
widget.onClose(false); // Close the dialog or screen
|
widget.onClose("Forex", false); // Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import '../../widgets/custom_text_itnerary_sub.dart';
|
|||||||
class InsuranceScreen extends StatefulWidget {
|
class InsuranceScreen extends StatefulWidget {
|
||||||
final List<Map<String, dynamic>> flightData;
|
final List<Map<String, dynamic>> flightData;
|
||||||
final Map<String, dynamic>? apiData;
|
final Map<String, dynamic>? apiData;
|
||||||
final Function(bool) onClose;
|
final Function(String, bool) onClose;
|
||||||
final Function(Map<String, dynamic>) onSaveInsurance;
|
final Function(Map<String, dynamic>) onSaveInsurance;
|
||||||
final Map<String, dynamic>? selectedItem;
|
final Map<String, dynamic>? selectedItem;
|
||||||
final String? loginUser;
|
final String? loginUser;
|
||||||
@ -290,8 +290,8 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
} else {
|
} else {
|
||||||
widget.onSaveInsurance(InsuranceData);
|
widget.onSaveInsurance(InsuranceData);
|
||||||
}
|
}
|
||||||
|
widget.onClose("Insurance", false);
|
||||||
widget.onClose(false); // Close screen after saving
|
// widget.onClose(false); // Close screen after saving
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime? _parseDate(String date) {
|
DateTime? _parseDate(String date) {
|
||||||
@ -1371,7 +1371,7 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
widget.onClose(false); // Close the dialog or screen
|
widget.onClose("Insurance", false); // Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
|
|||||||
@ -9,7 +9,8 @@ import '../../widgets/custom_text_itnerary_sub.dart';
|
|||||||
|
|
||||||
class MiscellaneousScreen extends StatefulWidget {
|
class MiscellaneousScreen extends StatefulWidget {
|
||||||
final Map<String, dynamic>? apiData;
|
final Map<String, dynamic>? apiData;
|
||||||
final Function(bool) onClose;
|
final Function(String, bool) onClose;
|
||||||
|
|
||||||
final Function(Map<String, dynamic>) onSaveMiscellaneous;
|
final Function(Map<String, dynamic>) onSaveMiscellaneous;
|
||||||
final Map<String, dynamic>? selectedItem;
|
final Map<String, dynamic>? selectedItem;
|
||||||
final int? selectedIndex;
|
final int? selectedIndex;
|
||||||
@ -137,7 +138,8 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
widget.onSaveMiscellaneous(miscellaneousData); // Send object to parent
|
widget.onSaveMiscellaneous(miscellaneousData); // Send object to parent
|
||||||
}
|
}
|
||||||
|
|
||||||
widget.onClose(false); // Close screen after saving
|
widget.onClose("Miscellaneous", false); // Close screen after saving
|
||||||
|
// widget.onClose(false); // Close screen after saving
|
||||||
// Clear only if this is a new entry
|
// Clear only if this is a new entry
|
||||||
// if (widget.selectedItem == null) {
|
// if (widget.selectedItem == null) {
|
||||||
// _commentsController.clear();
|
// _commentsController.clear();
|
||||||
@ -281,9 +283,10 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _isHotelNameFocused,
|
isFocused: _isHotelNameFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width:
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
isDesktop
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
@ -291,7 +294,7 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
// focusNode: _taxiReqFocusNode,
|
// focusNode: _taxiReqFocusNode,
|
||||||
items: purposeList.cast<Map<String, dynamic>>(),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
selectedItem: purposeList.firstWhere(
|
selectedItem: purposeList.firstWhere(
|
||||||
(item) => item['dropdown_key'] == selectedSpecialType,
|
(item) => item['dropdown_key'] == selectedSpecialType,
|
||||||
orElse: () => {},
|
orElse: () => {},
|
||||||
),
|
),
|
||||||
itemAsString: (item) => item['dropdown_value'] ?? '',
|
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||||
@ -328,31 +331,23 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
if (selectedItem == null || selectedItem.isEmpty) {
|
if (selectedItem == null || selectedItem.isEmpty) {
|
||||||
return Text(
|
return Text(
|
||||||
"Select ",
|
"Select ",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(color: Colors.grey, fontSize: 13),
|
||||||
color: Colors.grey,
|
|
||||||
fontSize: 13,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return Text(
|
return Text(
|
||||||
selectedItem['dropdown_value'] ?? '',
|
selectedItem['dropdown_value'] ?? '',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
fontSize: 12,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onChanged:
|
onChanged:
|
||||||
purposeList.isNotEmpty
|
purposeList.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedSpecialType = newValue as String?;
|
selectedSpecialType = newValue as String?;
|
||||||
});
|
});
|
||||||
print(
|
print("Updating form data: -> ${newValue ?? ""}");
|
||||||
"Updating form data: -> ${newValue ?? ""}",
|
}
|
||||||
);
|
: null,
|
||||||
}
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -421,7 +416,8 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_commentsController.clear();
|
_commentsController.clear();
|
||||||
widget.onClose(false); // Close the dialog or screen
|
widget.onClose("Miscellaneous", false);
|
||||||
|
// widget.onClose(false); // Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import '../../widgets/custom_text_itnerary_sub.dart';
|
|||||||
|
|
||||||
class TaxiScreen extends StatefulWidget {
|
class TaxiScreen extends StatefulWidget {
|
||||||
final Map<String, dynamic>? apiData;
|
final Map<String, dynamic>? apiData;
|
||||||
final Function(bool) onClose;
|
final Function(String, bool) onClose;
|
||||||
final Function(Map<String, dynamic>) onSavetaxi;
|
final Function(Map<String, dynamic>) onSavetaxi;
|
||||||
final Map<String, dynamic>? selectedItem;
|
final Map<String, dynamic>? selectedItem;
|
||||||
final String? loginUser;
|
final String? loginUser;
|
||||||
@ -199,8 +199,8 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
} else {
|
} else {
|
||||||
widget.onSavetaxi(taxiData);
|
widget.onSavetaxi(taxiData);
|
||||||
}
|
}
|
||||||
|
widget.onClose("Taxi", false);
|
||||||
widget.onClose(false); // Close screen after saving
|
// widget.onClose(false); // Close screen after saving
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -404,7 +404,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
// focusNode: _taxiReqFocusNode,
|
// focusNode: _taxiReqFocusNode,
|
||||||
items: purposeList.cast<Map<String, dynamic>>(),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
selectedItem: purposeList.firstWhere(
|
selectedItem: purposeList.firstWhere(
|
||||||
(item) => item['dropdown_key'] == selectedCarType,
|
(item) => item['dropdown_key'] == selectedCarType,
|
||||||
orElse: () => {},
|
orElse: () => {},
|
||||||
),
|
),
|
||||||
itemAsString: (item) => item['dropdown_value'] ?? '',
|
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||||
@ -456,16 +456,14 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
onChanged:
|
onChanged:
|
||||||
purposeList.isNotEmpty
|
purposeList.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedCarType = newValue as String?;
|
selectedCarType = newValue as String?;
|
||||||
});
|
});
|
||||||
print(
|
print("Updating form data: -> ${newValue ?? ""}");
|
||||||
"Updating form data: -> ${newValue ?? ""}",
|
}
|
||||||
);
|
: null,
|
||||||
}
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -544,9 +542,9 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
isFocused: _taxiReqFocused,
|
isFocused: _taxiReqFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width:
|
width:
|
||||||
isDesktop
|
isDesktop
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
@ -554,7 +552,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
// focusNode: _taxiReqFocusNode,
|
// focusNode: _taxiReqFocusNode,
|
||||||
items: purposeList.cast<Map<String, dynamic>>(),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
selectedItem: purposeList.firstWhere(
|
selectedItem: purposeList.firstWhere(
|
||||||
(item) => item['dropdown_key'] == selectedReqTaxi,
|
(item) => item['dropdown_key'] == selectedReqTaxi,
|
||||||
orElse: () => {},
|
orElse: () => {},
|
||||||
),
|
),
|
||||||
itemAsString: (item) => item['dropdown_value'] ?? '',
|
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||||
@ -591,31 +589,23 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
if (selectedItem == null || selectedItem.isEmpty) {
|
if (selectedItem == null || selectedItem.isEmpty) {
|
||||||
return Text(
|
return Text(
|
||||||
"Select ",
|
"Select ",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(color: Colors.grey, fontSize: 13),
|
||||||
color: Colors.grey,
|
|
||||||
fontSize: 13,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return Text(
|
return Text(
|
||||||
selectedItem['dropdown_value'] ?? '',
|
selectedItem['dropdown_value'] ?? '',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||||
fontSize: 12,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onChanged:
|
onChanged:
|
||||||
purposeList.isNotEmpty
|
purposeList.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedReqTaxi = newValue as String?;
|
selectedReqTaxi = newValue as String?;
|
||||||
});
|
});
|
||||||
print(
|
print("Updating form data: -> ${newValue ?? ""}");
|
||||||
"Updating form data: -> ${newValue ?? ""}",
|
}
|
||||||
);
|
: null,
|
||||||
}
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -974,7 +964,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
widget.onClose(false); // Close the dialog or screen
|
widget.onClose("Taxi", false); // Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import 'package:intl/intl.dart';
|
|||||||
import 'package:responsive_builder/responsive_builder.dart';
|
import 'package:responsive_builder/responsive_builder.dart';
|
||||||
|
|
||||||
import '../../services/apiService.dart';
|
import '../../services/apiService.dart';
|
||||||
|
import '../../widgets/custom_confirmation_dialog.dart';
|
||||||
import '../../widgets/custom_text_field.dart';
|
import '../../widgets/custom_text_field.dart';
|
||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
|
|
||||||
@ -12,7 +13,7 @@ class TrainScreen extends StatefulWidget {
|
|||||||
final Map<String, dynamic>? apiData;
|
final Map<String, dynamic>? apiData;
|
||||||
final Map<String, dynamic>? apiDataForClass;
|
final Map<String, dynamic>? apiDataForClass;
|
||||||
final Function(Map<String, dynamic>) onSavetrain;
|
final Function(Map<String, dynamic>) onSavetrain;
|
||||||
final Function(bool) onClose;
|
final Function(String, bool) onClose;
|
||||||
final Map<String, dynamic>? selectedItem;
|
final Map<String, dynamic>? selectedItem;
|
||||||
final String? loginUser;
|
final String? loginUser;
|
||||||
final String? tripType;
|
final String? tripType;
|
||||||
@ -67,6 +68,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
bool _commentsFocus = false;
|
bool _commentsFocus = false;
|
||||||
|
|
||||||
String? selectedClass;
|
String? selectedClass;
|
||||||
|
String? exceptionalClass = "0";
|
||||||
String? selectedFrom;
|
String? selectedFrom;
|
||||||
String? selectedTo;
|
String? selectedTo;
|
||||||
|
|
||||||
@ -80,6 +82,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
// "from_station": _fromController.text,
|
// "from_station": _fromController.text,
|
||||||
"to_station": selectedTo,
|
"to_station": selectedTo,
|
||||||
// "to_station": _toController.text,
|
// "to_station": _toController.text,
|
||||||
|
"is_this_exceptional": exceptionalClass,
|
||||||
"date": _dateController.text,
|
"date": _dateController.text,
|
||||||
"time": _timeController.text,
|
"time": _timeController.text,
|
||||||
"comments": _trainCommentsController.text,
|
"comments": _trainCommentsController.text,
|
||||||
@ -151,6 +154,11 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
_dateController = initController("date");
|
_dateController = initController("date");
|
||||||
_timeController = initController("time");
|
_timeController = initController("time");
|
||||||
|
|
||||||
|
if (widget.selectedItem != null &&
|
||||||
|
widget.selectedItem!["is_this_exceptional"] != null) {
|
||||||
|
exceptionalClass = widget.selectedItem!["is_this_exceptional"].toString();
|
||||||
|
}
|
||||||
|
|
||||||
// Set the selected value if available
|
// Set the selected value if available
|
||||||
if (widget.selectedItem != null && widget.selectedItem!["class"] != null) {
|
if (widget.selectedItem != null && widget.selectedItem!["class"] != null) {
|
||||||
selectedClass = widget.selectedItem!["class"].toString();
|
selectedClass = widget.selectedItem!["class"].toString();
|
||||||
@ -288,8 +296,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
} else {
|
} else {
|
||||||
widget.onSavetrain(trainData);
|
widget.onSavetrain(trainData);
|
||||||
}
|
}
|
||||||
|
widget.onClose("Train", false);
|
||||||
widget.onClose(false); // Close screen after saving
|
// widget.onClose(false); // Close screen after saving
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -576,8 +584,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default selected value
|
// Default selected value
|
||||||
selectedClass ??=
|
// selectedClass ??=
|
||||||
dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
// dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
Column(
|
Column(
|
||||||
@ -631,17 +639,30 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: DropdownSearch<Map<String, dynamic>>(
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
|
key:
|
||||||
|
selectedClass == null
|
||||||
|
? UniqueKey()
|
||||||
|
: ValueKey(selectedClass),
|
||||||
items: purposeList.cast<Map<String, dynamic>>(),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
selectedItem: purposeList.firstWhere(
|
|
||||||
(item) => item['dropdown_key'] == selectedClass,
|
// selectedItem: purposeList.firstWhere(
|
||||||
orElse: () => {},
|
// (item) => item['dropdown_key'] == selectedClass,
|
||||||
),
|
// orElse: () => {},
|
||||||
|
// ),
|
||||||
|
selectedItem:
|
||||||
|
selectedClass != null
|
||||||
|
? purposeList.firstWhere(
|
||||||
|
(item) => item['dropdown_key'] == selectedClass,
|
||||||
|
orElse: () => {},
|
||||||
|
)
|
||||||
|
: null,
|
||||||
itemAsString: (item) => item['dropdown_value'] ?? '',
|
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
showSearchBox: false,
|
showSearchBox: false,
|
||||||
fit: FlexFit.loose,
|
fit: FlexFit.loose,
|
||||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
itemBuilder: (context, item, isSelected) {
|
itemBuilder: (context, item, isSelected) {
|
||||||
|
final bool isNotAllowed = item['is_allowed'] == 'No';
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
@ -651,7 +672,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
item['dropdown_value'] ?? '',
|
item['dropdown_value'] ?? '',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Colors.black,
|
color: isNotAllowed ? Colors.redAccent : Colors.black,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -660,7 +681,10 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 10,vertical: 10,),
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder: (context, selectedItem) {
|
dropdownBuilder: (context, selectedItem) {
|
||||||
@ -682,14 +706,59 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
onChanged:
|
onChanged:
|
||||||
purposeList.isNotEmpty
|
purposeList.isNotEmpty
|
||||||
? (Map<String, dynamic>? newValue) {
|
? (Map<String, dynamic>? newValue) async {
|
||||||
setState(() {
|
if (newValue != null &&
|
||||||
selectedClass= newValue?['dropdown_key'];
|
newValue['is_allowed'] == 'No') {
|
||||||
print("Selected Purpose: ${selectedClass}");
|
final confirm = await showNotAllowedDialog(
|
||||||
});
|
context,
|
||||||
}
|
message:
|
||||||
: null,
|
"You are not entitled for this service. If you wish to continue with this service, you may require another approval.",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (confirm) {
|
||||||
|
setState(() {
|
||||||
|
exceptionalClass = "1";
|
||||||
|
selectedClass = newValue['dropdown_key'];
|
||||||
|
});
|
||||||
|
print("Selected Purpose: ${selectedClass}");
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
exceptionalClass = "0";
|
||||||
|
selectedClass =
|
||||||
|
null; // ❌ Clear selection if user cancels
|
||||||
|
});
|
||||||
|
print(
|
||||||
|
"selectedItem resolved to: ${selectedClass}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else if (newValue != null &&
|
||||||
|
newValue['is_allowed'] == 'yes') {
|
||||||
|
setState(() {
|
||||||
|
exceptionalClass = "0";
|
||||||
|
selectedClass = newValue?['dropdown_key'];
|
||||||
|
print("Selected Purpose: ${selectedClass}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (newValue != null &&
|
||||||
|
// newValue['is_allowed'] == 'No') {
|
||||||
|
// print('not allowed');
|
||||||
|
//
|
||||||
|
// setState(() {
|
||||||
|
// exceptionalClass = "1";
|
||||||
|
// // hasExceptionalClass = true;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
selectedClass = newValue?['dropdown_key'];
|
||||||
|
print("Selected Purpose: ${selectedClass}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -817,16 +886,16 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
itemBuilder:
|
itemBuilder:
|
||||||
(context, item, isSelected) => Container(
|
(context, item, isSelected) => Container(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
vertical: 6,
|
vertical: 6,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
item,
|
item,
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search ...",
|
hintText: "Search ...",
|
||||||
@ -843,22 +912,20 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
(context, selectedItem) => Align(
|
(context, selectedItem) => Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select ",
|
selectedItem ?? "Select ",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
onChanged: (String? newValue) {
|
onChanged: (String? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedFrom =
|
selectedFrom =
|
||||||
countryMap.entries
|
countryMap.entries
|
||||||
.firstWhere(
|
.firstWhere((entry) => entry.value == newValue)
|
||||||
(entry) => entry.value == newValue,
|
|
||||||
)
|
|
||||||
.key;
|
.key;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -952,16 +1019,16 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
itemBuilder:
|
itemBuilder:
|
||||||
(context, item, isSelected) => Container(
|
(context, item, isSelected) => Container(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
vertical: 6,
|
vertical: 6,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
item,
|
item,
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search ...",
|
hintText: "Search ...",
|
||||||
@ -978,22 +1045,20 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
(context, selectedItem) => Align(
|
(context, selectedItem) => Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select ",
|
selectedItem ?? "Select ",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
onChanged: (String? newValue) {
|
onChanged: (String? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedTo =
|
selectedTo =
|
||||||
countryMap.entries
|
countryMap.entries
|
||||||
.firstWhere(
|
.firstWhere((entry) => entry.value == newValue)
|
||||||
(entry) => entry.value == newValue,
|
|
||||||
)
|
|
||||||
.key;
|
.key;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -1174,7 +1239,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
widget.onClose(false);
|
// widget.onClose(false);
|
||||||
|
widget.onClose("Train", false);
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class VisaScreen extends StatefulWidget {
|
|||||||
final Map<String, dynamic>? apiData;
|
final Map<String, dynamic>? apiData;
|
||||||
final List<dynamic>? apiCountryData;
|
final List<dynamic>? apiCountryData;
|
||||||
|
|
||||||
final Function(bool) onClose;
|
final Function(String, bool) onClose;
|
||||||
final Function(Map<String, dynamic>) onSaveVisa;
|
final Function(Map<String, dynamic>) onSaveVisa;
|
||||||
final Map<String, dynamic>? selectedItem;
|
final Map<String, dynamic>? selectedItem;
|
||||||
final String? loginUser;
|
final String? loginUser;
|
||||||
@ -259,8 +259,8 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
} else {
|
} else {
|
||||||
widget.onSaveVisa(visaData);
|
widget.onSaveVisa(visaData);
|
||||||
}
|
}
|
||||||
|
widget.onClose("Visa", false);
|
||||||
widget.onClose(false); // Close screen after saving
|
// widget.onClose(false); // Close screen after saving
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -513,9 +513,10 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _isHotelNameFocused,
|
isFocused: _isHotelNameFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
width: isDesktop
|
width:
|
||||||
? MediaQuery.of(context).size.width * 0.34
|
isDesktop
|
||||||
: MediaQuery.of(context).size.width * 0.66,
|
? MediaQuery.of(context).size.width * 0.34
|
||||||
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: DropdownSearch<String>(
|
child: DropdownSearch<String>(
|
||||||
@ -527,16 +528,16 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||||
itemBuilder:
|
itemBuilder:
|
||||||
(context, item, isSelected) => Container(
|
(context, item, isSelected) => Container(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
vertical: 6,
|
vertical: 6,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
item,
|
item,
|
||||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search ...",
|
hintText: "Search ...",
|
||||||
@ -553,18 +554,21 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
),
|
),
|
||||||
dropdownBuilder:
|
dropdownBuilder:
|
||||||
(context, selectedItem) => Align(
|
(context, selectedItem) => Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
selectedItem ?? "Select ",
|
selectedItem ?? "Select ",
|
||||||
style: GoogleFonts.poppins(fontSize: 12,color: Colors.black,),
|
style: GoogleFonts.poppins(
|
||||||
),
|
fontSize: 12,
|
||||||
),
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
onChanged: (String? newValue) {
|
onChanged: (String? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedCountry =
|
selectedCountry =
|
||||||
countryMap.entries.firstWhere(
|
countryMap.entries
|
||||||
(entry) => entry.value == newValue,
|
.firstWhere((entry) => entry.value == newValue)
|
||||||
).key;
|
.key;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -635,7 +639,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
child: DropdownSearch<Map<String, dynamic>>(
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
items: purposeList.cast<Map<String, dynamic>>(),
|
items: purposeList.cast<Map<String, dynamic>>(),
|
||||||
selectedItem: purposeList.firstWhere(
|
selectedItem: purposeList.firstWhere(
|
||||||
(item) => item['dropdown_key'] == selectedPurpose,
|
(item) => item['dropdown_key'] == selectedPurpose,
|
||||||
orElse: () => {},
|
orElse: () => {},
|
||||||
),
|
),
|
||||||
itemAsString: (item) => item['dropdown_value'] ?? '',
|
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||||
@ -662,7 +666,10 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||||
dropdownSearchDecoration: InputDecoration(
|
dropdownSearchDecoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 10,vertical: 10,),
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dropdownBuilder: (context, selectedItem) {
|
dropdownBuilder: (context, selectedItem) {
|
||||||
@ -692,14 +699,14 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
// EdgeInsets.symmetric(horizontal: 10), // Proper padding
|
// EdgeInsets.symmetric(horizontal: 10), // Proper padding
|
||||||
// ),
|
// ),
|
||||||
onChanged:
|
onChanged:
|
||||||
purposeList.isNotEmpty
|
purposeList.isNotEmpty
|
||||||
? (Map<String, dynamic>? newValue) {
|
? (Map<String, dynamic>? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedPurpose= newValue?['dropdown_key'];
|
selectedPurpose = newValue?['dropdown_key'];
|
||||||
print("Selected Purpose: ${selectedPurpose}");
|
print("Selected Purpose: ${selectedPurpose}");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -826,7 +833,8 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
widget.onClose(false); // Close the dialog or screen
|
widget.onClose("Visa", false);
|
||||||
|
// widget.onClose(false); // Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
|
|||||||
@ -133,7 +133,8 @@ class _FlightListWidgetState extends State<FlightListWidget> {
|
|||||||
widget.isViewMode
|
widget.isViewMode
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
checkClass();
|
widget.onAddNew("Flight", true);
|
||||||
|
// checkClass();
|
||||||
print("New data");
|
print("New data");
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
|
|||||||
@ -298,6 +298,8 @@ class _CreatePlansState extends State<CreatePlan> {
|
|||||||
context.go('/listPlan');
|
context.go('/listPlan');
|
||||||
} else if (currentUri == "/approver/plans") {
|
} else if (currentUri == "/approver/plans") {
|
||||||
context.go('/approvallist');
|
context.go('/approvallist');
|
||||||
|
} else if (currentUri == "/travelagent/trips") {
|
||||||
|
context.go('/listTravelAgentPlan');
|
||||||
} else {
|
} else {
|
||||||
isApprover ? context.go('/approvallist') : context.go('/listPlan');
|
isApprover ? context.go('/approvallist') : context.go('/listPlan');
|
||||||
}
|
}
|
||||||
@ -381,6 +383,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
|
|
||||||
final TextEditingController _tripTitleController = TextEditingController();
|
final TextEditingController _tripTitleController = TextEditingController();
|
||||||
final TextEditingController _descriptionController = TextEditingController();
|
final TextEditingController _descriptionController = TextEditingController();
|
||||||
|
final TextEditingController _excepntldescriptionController =
|
||||||
|
TextEditingController();
|
||||||
final TextEditingController _remarksController = TextEditingController();
|
final TextEditingController _remarksController = TextEditingController();
|
||||||
|
|
||||||
// final FocusNode _tripTitleFocusNode = FocusNode();
|
// final FocusNode _tripTitleFocusNode = FocusNode();
|
||||||
@ -416,6 +420,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
bool showDomestic = false;
|
bool showDomestic = false;
|
||||||
bool showInternational = false;
|
bool showInternational = false;
|
||||||
bool hasAction = true;
|
bool hasAction = true;
|
||||||
|
bool hasExceptionalClass = false;
|
||||||
|
|
||||||
late Map<String, String> costCenterMap;
|
late Map<String, String> costCenterMap;
|
||||||
List<String> costCenterIds = [];
|
List<String> costCenterIds = [];
|
||||||
@ -445,10 +450,10 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
List<Map<String, dynamic>> insuranceList = [];
|
List<Map<String, dynamic>> insuranceList = [];
|
||||||
List<Map<String, dynamic>> accommodationList = [];
|
List<Map<String, dynamic>> accommodationList = [];
|
||||||
List<Map<String, dynamic>> trainList = [];
|
List<Map<String, dynamic>> trainList = [];
|
||||||
|
List<Map<String, dynamic>> flightList = [];
|
||||||
List<Map<String, dynamic>> busList = [];
|
List<Map<String, dynamic>> busList = [];
|
||||||
List<Map<String, dynamic>> taxiList = [];
|
List<Map<String, dynamic>> taxiList = [];
|
||||||
List<Map<String, dynamic>> forexList = [];
|
List<Map<String, dynamic>> forexList = [];
|
||||||
List<Map<String, dynamic>> flightList = [];
|
|
||||||
|
|
||||||
List<Map<String, dynamic>> planStatusList = [];
|
List<Map<String, dynamic>> planStatusList = [];
|
||||||
|
|
||||||
@ -471,6 +476,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
"is_billable": _selectedIsBillable,
|
"is_billable": _selectedIsBillable,
|
||||||
"purpose_of_travel": selectedPurpose,
|
"purpose_of_travel": selectedPurpose,
|
||||||
"description": _descriptionController.text,
|
"description": _descriptionController.text,
|
||||||
|
"exceptional_plan_reason": _excepntldescriptionController.text,
|
||||||
"functional_department": selectedFuncDept,
|
"functional_department": selectedFuncDept,
|
||||||
"so_number": "12345",
|
"so_number": "12345",
|
||||||
"created_by": selfId,
|
"created_by": selfId,
|
||||||
@ -495,6 +501,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
"is_billable",
|
"is_billable",
|
||||||
"purpose_of_travel",
|
"purpose_of_travel",
|
||||||
"description",
|
"description",
|
||||||
|
"excepntldescription",
|
||||||
"functional_department",
|
"functional_department",
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -535,6 +542,13 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
print("Updated $type List: $newList");
|
print("Updated $type List: $newList");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleExcentionalClass(bool val) {
|
||||||
|
print("handleExcentionalClass - $val");
|
||||||
|
setState(() {
|
||||||
|
hasExceptionalClass = val;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -652,6 +666,13 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
_descriptionController.text =
|
_descriptionController.text =
|
||||||
widget.selectedPlanData['description'] ?? '';
|
widget.selectedPlanData['description'] ?? '';
|
||||||
|
|
||||||
|
_excepntldescriptionController.text =
|
||||||
|
widget.selectedPlanData['exceptional_plan_reason'] ?? '';
|
||||||
|
|
||||||
|
if (_excepntldescriptionController.text != "") {
|
||||||
|
hasExceptionalClass = true;
|
||||||
|
}
|
||||||
|
|
||||||
_selectedTripType = widget.selectedPlanData['trip_type'];
|
_selectedTripType = widget.selectedPlanData['trip_type'];
|
||||||
flightTripTypeNotifier.value = widget.selectedPlanData['trip_type'];
|
flightTripTypeNotifier.value = widget.selectedPlanData['trip_type'];
|
||||||
_selectedIsBillable =
|
_selectedIsBillable =
|
||||||
@ -1136,6 +1157,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
"cost_center_id": selectedCostCenterId,
|
"cost_center_id": selectedCostCenterId,
|
||||||
"functional_department": selectedFuncDept,
|
"functional_department": selectedFuncDept,
|
||||||
"purpose_of_travel": selectedPurpose,
|
"purpose_of_travel": selectedPurpose,
|
||||||
|
if (hasExceptionalClass)
|
||||||
|
"exceptional_plan_reason": _excepntldescriptionController.text,
|
||||||
};
|
};
|
||||||
print("validateForm.....3");
|
print("validateForm.....3");
|
||||||
for (var entry in requiredFields.entries) {
|
for (var entry in requiredFields.entries) {
|
||||||
@ -1268,8 +1291,55 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> checkExceptionalClass() async {
|
||||||
|
// pretend we fetch something
|
||||||
|
await Future.delayed(Duration(seconds: 1)); // Example async operation
|
||||||
|
|
||||||
|
int exceptionalCount = 0;
|
||||||
|
|
||||||
|
bool hasExceptional(List<Map<String, dynamic>> list) {
|
||||||
|
return list.any(
|
||||||
|
(item) =>
|
||||||
|
item['is_this_exceptional']?.toString() == '1' &&
|
||||||
|
item['is_active']?.toString() == '1',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasExceptionalInFlights(List<Map<String, dynamic>> flights) {
|
||||||
|
for (var flight in flights) {
|
||||||
|
if (flight['is_active']?.toString() == '1') {
|
||||||
|
final trips = flight['trips'];
|
||||||
|
if (trips is List) {
|
||||||
|
final exceptionalTrip = trips.any(
|
||||||
|
(trip) => trip['is_this_exceptional']?.toString() == '1',
|
||||||
|
);
|
||||||
|
if (exceptionalTrip) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasExceptionalInFlights(flightList)) exceptionalCount++;
|
||||||
|
if (hasExceptional(trainList)) exceptionalCount++;
|
||||||
|
if (hasExceptional(accommodationList)) exceptionalCount++;
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
hasExceptionalClass = exceptionalCount >= 1;
|
||||||
|
if (!hasExceptionalClass) {
|
||||||
|
_excepntldescriptionController.text = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
print("hasExceptionalClass: $hasExceptionalClass");
|
||||||
|
}
|
||||||
|
|
||||||
void handleSubmit() {
|
void handleSubmit() {
|
||||||
setState(() async {
|
setState(() async {
|
||||||
|
await checkExceptionalClass();
|
||||||
|
|
||||||
|
print("Handle Submit....after check");
|
||||||
|
|
||||||
print("Hansle Submit....11");
|
print("Hansle Submit....11");
|
||||||
if (validateForm() && temporaryMessage == null) {
|
if (validateForm() && temporaryMessage == null) {
|
||||||
print("Hansle Submit....11222");
|
print("Hansle Submit....11222");
|
||||||
@ -1690,17 +1760,18 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
? Row(
|
? Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
// _buildNonDescriptionColumn(),
|
//
|
||||||
// SizedBox(width: 25),
|
|
||||||
_buildDescriptionColumn(isDesktop),
|
_buildDescriptionColumn(isDesktop),
|
||||||
|
SizedBox(width: 25),
|
||||||
|
if (hasExceptionalClass) _buildNonDescriptionColumn(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: Column(
|
: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
// _buildNonDescriptionColumn(),
|
|
||||||
// SizedBox(height: 15),
|
|
||||||
_buildDescriptionColumn(isDesktop),
|
_buildDescriptionColumn(isDesktop),
|
||||||
|
SizedBox(height: 15),
|
||||||
|
_buildNonDescriptionColumn(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -1743,6 +1814,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
apiDataForClass: apiDataForClass,
|
apiDataForClass: apiDataForClass,
|
||||||
apiCountryData: apiCountryData,
|
apiCountryData: apiCountryData,
|
||||||
onItineraryUpdate: handleItineraryUpdate,
|
onItineraryUpdate: handleItineraryUpdate,
|
||||||
|
onExeptionalClass: handleExcentionalClass,
|
||||||
loginUser: selfId,
|
loginUser: selfId,
|
||||||
selectedPlanData: planData,
|
selectedPlanData: planData,
|
||||||
isViewMode: widget.isViewMode,
|
isViewMode: widget.isViewMode,
|
||||||
@ -3248,7 +3320,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Trip Name", // Your label
|
"Reason For Exceptional Class *", // Your label
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@ -3256,32 +3328,54 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
|
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: false,
|
isFocused: focusStates["excepntldescriptionFocused"] ?? false,
|
||||||
// isFocused: _isTripTitleFocused,
|
// isFocused: _isdescriptionFocused,
|
||||||
|
width:
|
||||||
|
widget.isDesktop
|
||||||
|
? MediaQuery.of(context).size.width * 0.42
|
||||||
|
: null,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 35,
|
height: 55,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
// focusNode: _tripTitleFocusNode,
|
focusNode: focusNodes["excepntldescriptionFocusNode"],
|
||||||
controller: _tripTitleController,
|
controller: _excepntldescriptionController,
|
||||||
|
maxLines: 2,
|
||||||
|
keyboardType: TextInputType.multiline,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
enabled: !widget.isViewMode,
|
enabled: !widget.isViewMode,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: "Trip Name",
|
labelText: "Exceptional Description",
|
||||||
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
labelStyle: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
// labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: EdgeInsets.symmetric(vertical: 1),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
if (validationErrors["exceptional_plan_reason"] != null)
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 4),
|
||||||
|
child: Text(
|
||||||
|
validationErrors["exceptional_plan_reason"]!,
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.red,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 8),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,8 @@ class DynamicItinerary extends StatefulWidget {
|
|||||||
final String? loginUser;
|
final String? loginUser;
|
||||||
final Function(String, List<Map<String, dynamic>>)
|
final Function(String, List<Map<String, dynamic>>)
|
||||||
onItineraryUpdate; // Updated Signature
|
onItineraryUpdate; // Updated Signature
|
||||||
|
|
||||||
|
final void Function(bool)? onExeptionalClass;
|
||||||
final Map<String, dynamic> selectedPlanData;
|
final Map<String, dynamic> selectedPlanData;
|
||||||
final bool isViewMode;
|
final bool isViewMode;
|
||||||
final GlobalKey<FlightScreenState> flightScreenKey;
|
final GlobalKey<FlightScreenState> flightScreenKey;
|
||||||
@ -48,6 +50,7 @@ class DynamicItinerary extends StatefulWidget {
|
|||||||
required this.selectedPlanData,
|
required this.selectedPlanData,
|
||||||
required this.isViewMode,
|
required this.isViewMode,
|
||||||
required this.hasAction,
|
required this.hasAction,
|
||||||
|
this.onExeptionalClass,
|
||||||
this.tripType,
|
this.tripType,
|
||||||
this.apiDataForClass,
|
this.apiDataForClass,
|
||||||
required this.tripTypeNotifier,
|
required this.tripTypeNotifier,
|
||||||
@ -64,6 +67,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
String? _tripType;
|
String? _tripType;
|
||||||
String selectedOption = "";
|
String selectedOption = "";
|
||||||
String selectedListOption = "";
|
String selectedListOption = "";
|
||||||
|
String selectedActiveTab = "";
|
||||||
|
|
||||||
bool isSelected = false;
|
bool isSelected = false;
|
||||||
Map<String, dynamic>? selectedItem;
|
Map<String, dynamic>? selectedItem;
|
||||||
@ -400,7 +404,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
return false; // No itinerary data available
|
return false; // No itinerary data available
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleClose(bool value) {
|
void handleMClose(bool value) {
|
||||||
|
print("handleClos- $isSelected");
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedOption = "";
|
selectedOption = "";
|
||||||
isSelected = value;
|
isSelected = value;
|
||||||
@ -409,6 +414,17 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleClose(name, bool value) {
|
||||||
|
print("handleMClos- $name, $isSelected");
|
||||||
|
setState(() {
|
||||||
|
selectedListOption = name;
|
||||||
|
selectedOption = "";
|
||||||
|
isSelected = value;
|
||||||
|
selectedIndex = null;
|
||||||
|
selectedItem = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void handleEdit(bool value, selectedItem, title) {
|
void handleEdit(bool value, selectedItem, title) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedOption = title;
|
selectedOption = title;
|
||||||
@ -420,6 +436,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void handlecreateNewPlan(name, bool value) {
|
void handlecreateNewPlan(name, bool value) {
|
||||||
|
print("handlecreateNewPlan- $name , $value");
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedOption = name;
|
selectedOption = name;
|
||||||
isSelected = value;
|
isSelected = value;
|
||||||
@ -710,6 +727,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
break;
|
break;
|
||||||
case "Miscellaneous":
|
case "Miscellaneous":
|
||||||
selectedWidget = MiscellaneousScreen(
|
selectedWidget = MiscellaneousScreen(
|
||||||
|
// onClose: handleClose,
|
||||||
onClose: handleClose,
|
onClose: handleClose,
|
||||||
apiData: widget.apiData,
|
apiData: widget.apiData,
|
||||||
loginUser: widget.loginUser,
|
loginUser: widget.loginUser,
|
||||||
@ -723,10 +741,12 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
selectedWidget = AccomodationScreen(
|
selectedWidget = AccomodationScreen(
|
||||||
onClose: handleClose,
|
onClose: handleClose,
|
||||||
loginUser: widget.loginUser,
|
loginUser: widget.loginUser,
|
||||||
|
apiDataForClass: widget.apiDataForClass,
|
||||||
onSaveAccomadation:
|
onSaveAccomadation:
|
||||||
(data) => handleItineraryUpdate("Accomodation", data),
|
(data) => handleItineraryUpdate("Accomodation", data),
|
||||||
selectedItem: selectedItem,
|
selectedItem: selectedItem,
|
||||||
flightData: itineraryData["Flight"]!,
|
flightData: itineraryData["Flight"]!,
|
||||||
|
onExceptionalClass: widget.onExeptionalClass,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Forex":
|
case "Forex":
|
||||||
@ -747,6 +767,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
tripTypeNotifier: widget.tripTypeNotifier,
|
tripTypeNotifier: widget.tripTypeNotifier,
|
||||||
hasAction: widget.hasAction,
|
hasAction: widget.hasAction,
|
||||||
tripType: widget.tripType,
|
tripType: widget.tripType,
|
||||||
|
// onClose: handleMClose,
|
||||||
onClose: handleClose,
|
onClose: handleClose,
|
||||||
loginUser: widget.loginUser,
|
loginUser: widget.loginUser,
|
||||||
onSaveFlight: (data) => handleItineraryUpdate("Flight", data),
|
onSaveFlight: (data) => handleItineraryUpdate("Flight", data),
|
||||||
@ -758,71 +779,6 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return ResponsiveBuilder(builder: (context, sizingInfo) {
|
|
||||||
// bool isMobile = sizingInfo.isMobile;
|
|
||||||
// bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
|
|
||||||
//
|
|
||||||
// return Column(
|
|
||||||
// // mainAxisSize: MainAxisSize.min,
|
|
||||||
// children: [
|
|
||||||
// Transform.translate(
|
|
||||||
// offset: Offset(0, 20),
|
|
||||||
// child: Container(
|
|
||||||
// decoration: BoxDecoration(
|
|
||||||
// border: Border(
|
|
||||||
// bottom: BorderSide(color: Color(0xFFF4F4FB), width: 2)),
|
|
||||||
// borderRadius: BorderRadius.circular(1),
|
|
||||||
// color: Color(0xFFF4F4FB),
|
|
||||||
// ),
|
|
||||||
// margin: EdgeInsets.symmetric(
|
|
||||||
// horizontal: MediaQuery.of(context).size.width *
|
|
||||||
// 0.05, // 30% of screen width as horizontal padding
|
|
||||||
// vertical: MediaQuery.of(context).size.height *
|
|
||||||
// 0, // 5% of screen height as vertical padding
|
|
||||||
// ),
|
|
||||||
// child: isMobile
|
|
||||||
// ? Expanded(
|
|
||||||
// child: SingleChildScrollView(
|
|
||||||
// scrollDirection: Axis.horizontal,
|
|
||||||
// child: Row(
|
|
||||||
// children: _buildOptions(),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// )
|
|
||||||
// : Row(
|
|
||||||
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
||||||
// // mainAxisSize: MainAxisSize.min,
|
|
||||||
// children: _buildOptions(),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Container(
|
|
||||||
// decoration: BoxDecoration(
|
|
||||||
// // border:
|
|
||||||
// // Border(bottom: BorderSide(color: Colors.black, width: 2)),
|
|
||||||
//
|
|
||||||
// border: Border.all(color: Colors.green, width: 1.5),
|
|
||||||
// borderRadius: BorderRadius.circular(1),
|
|
||||||
// color: Colors.yellowAccent.shade100,
|
|
||||||
// ),
|
|
||||||
// margin: EdgeInsets.only(top: 0),
|
|
||||||
// child: Column(
|
|
||||||
// // mainAxisSize: MainAxisSize.min,
|
|
||||||
// crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
// children: [
|
|
||||||
// SizedBox(height: 2),
|
|
||||||
// isSelected ? selectedWidget : selectedListWidget,
|
|
||||||
// // TrainScreen()
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
//
|
|
||||||
// ],
|
|
||||||
// );
|
|
||||||
// });
|
|
||||||
|
|
||||||
return ResponsiveBuilder(
|
return ResponsiveBuilder(
|
||||||
builder: (context, sizingInfo) {
|
builder: (context, sizingInfo) {
|
||||||
bool isMobile = sizingInfo.isMobile;
|
bool isMobile = sizingInfo.isMobile;
|
||||||
@ -964,19 +920,69 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool checkClass() {
|
||||||
|
if (widget.hasAction) {
|
||||||
|
if (widget.tripType?.isNotEmpty == true) {
|
||||||
|
print("Teppp - ${widget.tripType}");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('Select Trip Type'),
|
||||||
|
content: const Text(
|
||||||
|
'Please select a trip type before selecting services.',
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("Teppp No - ${widget.tripType}");
|
||||||
|
return true; // still allow it when `hasAction` is false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildOption(Map<String, dynamic> service, bool hasData) {
|
Widget _buildOption(Map<String, dynamic> service, bool hasData) {
|
||||||
String name = service['name'];
|
String name = service['name'];
|
||||||
String iconUrl = service['icon']; // Can be empty string
|
String iconUrl = service['icon']; // Can be empty string
|
||||||
IconData fallbackIcon = _getLocalIconForService(name);
|
IconData fallbackIcon = _getLocalIconForService(name);
|
||||||
|
|
||||||
bool isOptionSelected = selectedListOption == name;
|
// bool isOptionSelected = selectedListOption == name;
|
||||||
|
bool isOptionSelected = selectedActiveTab == name;
|
||||||
|
// bool isOptionSelected =
|
||||||
|
// hasData ? selectedListOption == name : selectedOption == name;
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
if (checkClass()) {
|
||||||
selectedListOption = name;
|
setState(() {
|
||||||
isSelected = false;
|
if (hasData) {
|
||||||
});
|
selectedListOption = name;
|
||||||
|
selectedActiveTab = name;
|
||||||
|
isSelected = false;
|
||||||
|
} else {
|
||||||
|
selectedOption = name;
|
||||||
|
selectedActiveTab = name;
|
||||||
|
isSelected = true;
|
||||||
|
selectedItem = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// setState(() {
|
||||||
|
// selectedListOption = name;
|
||||||
|
// isSelected = false;
|
||||||
|
// // selectedOption = name;
|
||||||
|
// // isSelected = true;
|
||||||
|
// });
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
//api url
|
//api url
|
||||||
// const String apiUrl = 'http://apitest.tripapprovaltool.com/tstat_be';
|
const String apiUrl = 'http://apitest.tripapprovaltool.com/tstat_be';
|
||||||
const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be';
|
// const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be';
|
||||||
|
|||||||
@ -680,11 +680,7 @@ final List<Map<String, dynamic>> menuItems = [
|
|||||||
// 'label': 'Template List'
|
// 'label': 'Template List'
|
||||||
// },
|
// },
|
||||||
// {'value': '/template', 'icon': Icons.ac_unit_sharp, 'label': 'Template'},
|
// {'value': '/template', 'icon': Icons.ac_unit_sharp, 'label': 'Template'},
|
||||||
{
|
{'value': '/report', 'icon': Icons.auto_graph, 'label': 'Reports'},
|
||||||
'value': '/report',
|
|
||||||
'icon': Icons.auto_graph,
|
|
||||||
'label': 'Reports',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
'value': '/CreateUserDetails',
|
'value': '/CreateUserDetails',
|
||||||
'icon': Icons.account_circle,
|
'icon': Icons.account_circle,
|
||||||
|
|||||||
@ -81,6 +81,10 @@ final GoRouter router = GoRouter(
|
|||||||
path: '/approver/plans',
|
path: '/approver/plans',
|
||||||
builder: (context, state) => CreatePlan(),
|
builder: (context, state) => CreatePlan(),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: '/travelagent/trips',
|
||||||
|
builder: (context, state) => CreatePlan(),
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/listUser',
|
path: '/listUser',
|
||||||
builder: (context, state) => UserListScreen(),
|
builder: (context, state) => UserListScreen(),
|
||||||
|
|||||||
@ -643,6 +643,25 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<void> viewPlanTravelAgent(
|
||||||
|
BuildContext context,
|
||||||
|
String planId, {
|
||||||
|
bool isViewMode = false,
|
||||||
|
bool isMyTrips = false,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
Map<String, dynamic> planData = await getViewPlanEdit(planId);
|
||||||
|
print("ViewAAA - $planData");
|
||||||
|
|
||||||
|
context.go(
|
||||||
|
'/travelagent/trips',
|
||||||
|
extra: {'planData': planData, 'isViewMode': isViewMode},
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
print("Error fetching plan: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> fetchUserApprovalList() async {
|
Future<Map<String, dynamic>> fetchUserApprovalList() async {
|
||||||
String? orgId = await getOrgId();
|
String? orgId = await getOrgId();
|
||||||
String? userId = await getUserId();
|
String? userId = await getUserId();
|
||||||
@ -899,8 +918,8 @@ class ApiService {
|
|||||||
|
|
||||||
// download the Template for bulk upload the user
|
// download the Template for bulk upload the user
|
||||||
Future<void> getDownloadUserTemplateForUpload() async {
|
Future<void> getDownloadUserTemplateForUpload() async {
|
||||||
|
final String apiUrldata =
|
||||||
final String apiUrldata = '$apiUrl/api/user/userUploadTemplate'; // download the Template for bulk upload user => api
|
'$apiUrl/api/user/userUploadTemplate'; // download the Template for bulk upload user => api
|
||||||
|
|
||||||
// final String apiUrldata = '$apiUrl/auth/googlelogin';
|
// final String apiUrldata = '$apiUrl/auth/googlelogin';
|
||||||
|
|
||||||
@ -930,9 +949,9 @@ class ApiService {
|
|||||||
|
|
||||||
// Create a link element to trigger the download
|
// Create a link element to trigger the download
|
||||||
final anchor =
|
final anchor =
|
||||||
html.AnchorElement(href: url)
|
html.AnchorElement(href: url)
|
||||||
..setAttribute('download', 'user_file.xlsx')
|
..setAttribute('download', 'user_file.xlsx')
|
||||||
..click();
|
..click();
|
||||||
|
|
||||||
// Revoke the download URL to free up resources
|
// Revoke the download URL to free up resources
|
||||||
html.Url.revokeObjectUrl(url);
|
html.Url.revokeObjectUrl(url);
|
||||||
@ -962,7 +981,6 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------User Management-----------------------------------
|
//---------------------------------------User Management-----------------------------------
|
||||||
|
|
||||||
Future<Map<String, dynamic>> getSingleUser(int userId) async {
|
Future<Map<String, dynamic>> getSingleUser(int userId) async {
|
||||||
@ -1511,7 +1529,7 @@ class ApiService {
|
|||||||
|
|
||||||
// ----------------------- User Management - CheckDuplicate end here ----------------------------------
|
// ----------------------- User Management - CheckDuplicate end here ----------------------------------
|
||||||
// ----------------------- Report -------------------------
|
// ----------------------- Report -------------------------
|
||||||
Future<Map<String, dynamic>> CallReports(String apiRoute,String body) async {
|
Future<Map<String, dynamic>> CallReports(String apiRoute, String body) async {
|
||||||
String apiUrldata = '$apiUrl/api/$apiRoute';
|
String apiUrldata = '$apiUrl/api/$apiRoute';
|
||||||
final token = await getToken();
|
final token = await getToken();
|
||||||
|
|
||||||
@ -1521,8 +1539,11 @@ class ApiService {
|
|||||||
|
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
Uri.parse(apiUrldata),
|
Uri.parse(apiUrldata),
|
||||||
headers: {'Authorization': 'Bearer $token','Content-Type': 'application/json'},
|
headers: {
|
||||||
body: body
|
'Authorization': 'Bearer $token',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: body,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
@ -1539,14 +1560,20 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> reportExcelDownload(String apiRoute,String body,String name) async {
|
Future<void> reportExcelDownload(
|
||||||
|
String apiRoute,
|
||||||
|
String body,
|
||||||
|
String name,
|
||||||
|
) async {
|
||||||
final String apiUrldata = '$apiUrl/api/$apiRoute';
|
final String apiUrldata = '$apiUrl/api/$apiRoute';
|
||||||
|
|
||||||
// Sanitize name for filename (optional)
|
// Sanitize name for filename (optional)
|
||||||
final safeName = name.replaceAll(RegExp(r'[^\w\s-]'), ''); // remove any special chars if needed
|
final safeName = name.replaceAll(
|
||||||
|
RegExp(r'[^\w\s-]'),
|
||||||
|
'',
|
||||||
|
); // remove any special chars if needed
|
||||||
final excelName = '$safeName.xlsx';
|
final excelName = '$safeName.xlsx';
|
||||||
|
|
||||||
|
|
||||||
final token = await getToken();
|
final token = await getToken();
|
||||||
|
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
@ -1554,9 +1581,12 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
Uri.parse(apiUrldata),
|
Uri.parse(apiUrldata),
|
||||||
headers: {'Authorization': 'Bearer $token','Content-Type': 'application/json'},
|
headers: {
|
||||||
body: body
|
'Authorization': 'Bearer $token',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: body,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
@ -1571,9 +1601,9 @@ class ApiService {
|
|||||||
|
|
||||||
// Create a link element to trigger the download
|
// Create a link element to trigger the download
|
||||||
final anchor =
|
final anchor =
|
||||||
html.AnchorElement(href: url)
|
html.AnchorElement(href: url)
|
||||||
..setAttribute('download', excelName)
|
..setAttribute('download', excelName)
|
||||||
..click();
|
..click();
|
||||||
|
|
||||||
// Revoke the download URL to free up resources
|
// Revoke the download URL to free up resources
|
||||||
html.Url.revokeObjectUrl(url);
|
html.Url.revokeObjectUrl(url);
|
||||||
@ -1587,5 +1617,6 @@ class ApiService {
|
|||||||
throw Exception('Failed to Download');
|
throw Exception('Failed to Download');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----------------------- Report -------------------------
|
|
||||||
|
// ----------------------- Report -------------------------
|
||||||
}
|
}
|
||||||
|
|||||||
30
lib/widgets/custom_confirmation_dialog.dart
Normal file
30
lib/widgets/custom_confirmation_dialog.dart
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
Future<bool> showNotAllowedDialog(
|
||||||
|
BuildContext context, {
|
||||||
|
String? message,
|
||||||
|
}) async {
|
||||||
|
return await showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false, // Force user to choose
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('Notice'),
|
||||||
|
content: Text(
|
||||||
|
message ?? 'This class is not allowed. Do you want to continue?',
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(false), // Cancel
|
||||||
|
child: const Text('Cancel'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(true), // OK
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
) ??
|
||||||
|
false; // Default to false if dialog is dismissed
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user