Exceptional Classes
This commit is contained in:
parent
e33af3cd8a
commit
53fd28d65d
@ -817,7 +817,7 @@ class _TravelAgentListPlansState extends State<TravelAgentListPlans> {
|
||||
Navigator.pop(
|
||||
context,
|
||||
); // Close popup manually
|
||||
ApiService.viewPlan(
|
||||
ApiService.viewPlanTravelAgent(
|
||||
context,
|
||||
plan.planId,
|
||||
isViewMode:
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
import 'package:dropdown_search/dropdown_search.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:responsive_builder/responsive_builder.dart';
|
||||
|
||||
import '../../services/apiService.dart';
|
||||
import '../../widgets/custom_confirmation_dialog.dart';
|
||||
import '../../widgets/custom_text_field.dart';
|
||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||
|
||||
class AccomodationScreen extends StatefulWidget {
|
||||
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 void Function(bool)? onExceptionalClass;
|
||||
final Map<String, dynamic>? selectedItem;
|
||||
final String? loginUser;
|
||||
final String? tripType;
|
||||
@ -22,6 +26,8 @@ class AccomodationScreen extends StatefulWidget {
|
||||
required this.loginUser,
|
||||
required this.flightData,
|
||||
this.tripType,
|
||||
this.apiDataForClass,
|
||||
this.onExceptionalClass,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -34,6 +40,10 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
||||
// late Map<String, String> countryMap;
|
||||
Map<String, String> countryMap = {};
|
||||
|
||||
String? selectedClass;
|
||||
String? exceptionalClass = "0";
|
||||
bool hasExceptionalClass = false;
|
||||
|
||||
late ValueNotifier<String?> flightFirstTripDateNotifier;
|
||||
late ValueNotifier<String?> flightLastTripDateNotifier;
|
||||
late ValueNotifier<String?> flightFirstToDestinationNotifier;
|
||||
@ -42,6 +52,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
||||
|
||||
final FocusNode _destinationFocusNode = FocusNode();
|
||||
final FocusNode _hotelNameFocusNode = FocusNode();
|
||||
final FocusNode _CategoryFocusNode = FocusNode();
|
||||
final FocusNode _checkInFocusNode = FocusNode();
|
||||
final FocusNode _checkInTimeFocusNode = FocusNode();
|
||||
final FocusNode _checkOutFocusNode = FocusNode();
|
||||
@ -58,6 +69,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
||||
|
||||
bool _destinationFocused = false;
|
||||
bool _isHotelNameFocused = false;
|
||||
bool _CategoryFocused = false;
|
||||
bool _checkInFocus = false;
|
||||
bool _checkInTimeFocus = false;
|
||||
bool _checkOutFocus = false;
|
||||
@ -78,11 +90,13 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
||||
Map<String, dynamic> data = {
|
||||
"destination_city": _destinationController.text,
|
||||
"hotel_name": _hotelNameController.text,
|
||||
"class": selectedClass,
|
||||
"checkin_date": _checkInController.text,
|
||||
"checkin_time": _checkInTimeController.text,
|
||||
"checkout_date": _checkOutController.text,
|
||||
"checkout_time": _checkOutTimeController.text,
|
||||
"comments": _commentsController.text,
|
||||
"is_this_exceptional": exceptionalClass,
|
||||
"created_by": widget.loginUser,
|
||||
"updated_by": widget.loginUser,
|
||||
};
|
||||
@ -191,6 +205,16 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
||||
_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
|
||||
@ -365,9 +389,13 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
||||
return; // Stop execution if validation fails
|
||||
} else {
|
||||
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
|
||||
@ -421,6 +449,34 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
||||
}
|
||||
|
||||
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 [
|
||||
// Column(
|
||||
// children: [
|
||||
@ -493,13 +549,13 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldWrapper(
|
||||
CustomTextFieldItnerarySubWrapper(
|
||||
isFocused: _isHotelNameFocused,
|
||||
isDesktop: isDesktop,
|
||||
width:
|
||||
isDesktop
|
||||
? MediaQuery.of(context).size.width * 0.34
|
||||
: MediaQuery.of(context).size.width * 0.66,
|
||||
// width:
|
||||
// isDesktop
|
||||
// ? MediaQuery.of(context).size.width * 0.34
|
||||
// : MediaQuery.of(context).size.width * 0.66,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
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
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
widget.onClose(false); // Close the dialog or screen
|
||||
widget.onClose("Accomodation", false);
|
||||
// widget.onClose(false); // Close the dialog or screen
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.grey[400], // Light grey color
|
||||
|
||||
@ -8,7 +8,7 @@ import '../../widgets/custom_text_itnerary_sub.dart';
|
||||
|
||||
class BusScreen extends StatefulWidget {
|
||||
final Map<String, dynamic>? apiData;
|
||||
final Function(bool) onClose;
|
||||
final Function(String, bool) onClose;
|
||||
final Function(Map<String, dynamic>) onSaveBus;
|
||||
final Map<String, dynamic>? selectedItem;
|
||||
final String? loginUser;
|
||||
@ -190,8 +190,8 @@ class _BusScreenState extends State<BusScreen> {
|
||||
} else {
|
||||
widget.onSaveBus(busData);
|
||||
}
|
||||
|
||||
widget.onClose(false); // Close screen after saving
|
||||
widget.onClose("Bus", false);
|
||||
// widget.onClose(false); // Close screen after saving
|
||||
}
|
||||
|
||||
@override
|
||||
@ -678,7 +678,8 @@ class _BusScreenState extends State<BusScreen> {
|
||||
// Close Button
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
widget.onClose(false); // Close the dialog or screen
|
||||
widget.onClose("Bus", false);
|
||||
// widget.onClose(false); // Close the dialog or screen
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.grey[400], // Light grey color
|
||||
|
||||
@ -6,6 +6,7 @@ import 'package:intl/intl.dart';
|
||||
import 'package:responsive_builder/responsive_builder.dart';
|
||||
|
||||
import '../../utils/auth_utils.dart';
|
||||
import '../../widgets/custom_confirmation_dialog.dart';
|
||||
import '../../widgets/custom_radio_button.dart';
|
||||
import '../../widgets/custom_text_field.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>? apiDataForClass;
|
||||
final String? loginUser;
|
||||
final Function(bool) onClose;
|
||||
final Function(String, bool) onClose;
|
||||
final Function(Map<String, dynamic>) onSaveFlight;
|
||||
final Map<String, dynamic>? selectedItem;
|
||||
final ValueNotifier<String?> tripTypeNotifier;
|
||||
@ -60,6 +61,8 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
|
||||
String? selectedTripType;
|
||||
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?> selectedTo = {}; // Store class selection for each trip
|
||||
String? selectedvisa_available;
|
||||
@ -409,6 +412,7 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
for (int i = 1; i <= rowCount; i++) {
|
||||
final trip = {
|
||||
"class": selectedClasses[i],
|
||||
"is_this_exceptional": exceptionalClass[i],
|
||||
// "from_place": countryMap[selectedFrom[i]],
|
||||
"from_place": selectedFrom[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
|
||||
|
||||
selectedClasses[index] = trip["class"].toString();
|
||||
exceptionalClass[index] = trip["is_this_exceptional"].toString();
|
||||
selectedFrom[index] = trip["from_place"].toString();
|
||||
selectedTo[index] = trip["to_place"].toString();
|
||||
// textControllers["_from${index}Controller"] =
|
||||
@ -545,7 +550,8 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
}
|
||||
|
||||
widget.onSaveFlight(flightsData); // Send object to parent
|
||||
widget.onClose(false);
|
||||
// widget.onClose(false);
|
||||
widget.onClose("Flight", false);
|
||||
|
||||
print("FlightData - $flightsData");
|
||||
}
|
||||
@ -789,6 +795,16 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
|
||||
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
|
||||
Map<int, String?> updatedFrom = {};
|
||||
newIndex = 1;
|
||||
@ -1320,8 +1336,8 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
}
|
||||
|
||||
// Default selected value
|
||||
selectedClasses[index] ??=
|
||||
dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||
// selectedClasses[index] ??=
|
||||
// dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||
// -------------------------------------------------
|
||||
|
||||
DateTime? _selectedCheckOutDate;
|
||||
@ -2046,16 +2062,30 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
},
|
||||
child: DropdownSearch<Map<String, dynamic>>(
|
||||
items: purposeList.cast<Map<String, dynamic>>(),
|
||||
selectedItem: purposeList.firstWhere(
|
||||
(item) => item['dropdown_key'] == selectedClasses[index],
|
||||
orElse: () => {},
|
||||
),
|
||||
key:
|
||||
selectedClasses[index] == null
|
||||
? 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'] ?? '',
|
||||
popupProps: PopupProps.menu(
|
||||
showSearchBox: false,
|
||||
fit: FlexFit.loose,
|
||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||
itemBuilder: (context, item, isSelected) {
|
||||
final bool isNotAllowed = item['is_allowed'] == 'No';
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
@ -2065,7 +2095,10 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
item['dropdown_value'] ?? '',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
color: Colors.black,
|
||||
color:
|
||||
isNotAllowed
|
||||
? Colors.redAccent
|
||||
: Colors.black,
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -2124,14 +2157,67 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
},
|
||||
onChanged:
|
||||
purposeList.isNotEmpty
|
||||
? (Map<String, dynamic>? newValue) {
|
||||
setState(() {
|
||||
selectedClasses[index] =
|
||||
newValue?['dropdown_key'];
|
||||
print(
|
||||
"Selected Class: ${selectedClasses[index]}",
|
||||
? (Map<String, dynamic>? newValue) async {
|
||||
// if (newValue != null &&
|
||||
// newValue['is_allowed'] == 'No') {
|
||||
// print('not allowed');
|
||||
//
|
||||
// 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,
|
||||
),
|
||||
@ -2690,7 +2776,8 @@ class FlightScreenState extends State<FlightScreen> {
|
||||
// Close Button
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
widget.onClose(false); // Close the dialog or screen
|
||||
widget.onClose("Flight", false);
|
||||
// widget.onClose(false); // Close the dialog or screen
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.grey[400], // Light grey color
|
||||
|
||||
@ -18,7 +18,7 @@ import 'package:http/http.dart' as http;
|
||||
class ForexScreen extends StatefulWidget {
|
||||
final List<Map<String, dynamic>> flightData;
|
||||
final Map<String, dynamic>? apiData;
|
||||
final Function(bool) onClose;
|
||||
final Function(String, bool) onClose;
|
||||
final Map<String, dynamic>? selectedItem;
|
||||
final List<dynamic>? apiCountryData;
|
||||
final Function(Map<String, dynamic>) onSaveForex;
|
||||
@ -366,8 +366,8 @@ class _ForexScreenState extends State<ForexScreen> {
|
||||
} else {
|
||||
widget.onSaveForex(forexData); // Send object to parent
|
||||
}
|
||||
|
||||
widget.onClose(false); // Close screen after saving
|
||||
widget.onClose("Forex", false);
|
||||
// widget.onClose(false); // Close screen after saving
|
||||
}
|
||||
|
||||
DateTime? _parseDate(String date) {
|
||||
@ -2294,7 +2294,7 @@ class _ForexScreenState extends State<ForexScreen> {
|
||||
// Close Button
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
widget.onClose(false); // Close the dialog or screen
|
||||
widget.onClose("Forex", false); // Close the dialog or screen
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.grey[400], // Light grey color
|
||||
|
||||
@ -11,7 +11,7 @@ import '../../widgets/custom_text_itnerary_sub.dart';
|
||||
class InsuranceScreen extends StatefulWidget {
|
||||
final List<Map<String, dynamic>> flightData;
|
||||
final Map<String, dynamic>? apiData;
|
||||
final Function(bool) onClose;
|
||||
final Function(String, bool) onClose;
|
||||
final Function(Map<String, dynamic>) onSaveInsurance;
|
||||
final Map<String, dynamic>? selectedItem;
|
||||
final String? loginUser;
|
||||
@ -290,8 +290,8 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
||||
} else {
|
||||
widget.onSaveInsurance(InsuranceData);
|
||||
}
|
||||
|
||||
widget.onClose(false); // Close screen after saving
|
||||
widget.onClose("Insurance", false);
|
||||
// widget.onClose(false); // Close screen after saving
|
||||
}
|
||||
|
||||
DateTime? _parseDate(String date) {
|
||||
@ -1371,7 +1371,7 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
||||
// Close Button
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
widget.onClose(false); // Close the dialog or screen
|
||||
widget.onClose("Insurance", false); // Close the dialog or screen
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.grey[400], // Light grey color
|
||||
|
||||
@ -9,7 +9,8 @@ import '../../widgets/custom_text_itnerary_sub.dart';
|
||||
|
||||
class MiscellaneousScreen extends StatefulWidget {
|
||||
final Map<String, dynamic>? apiData;
|
||||
final Function(bool) onClose;
|
||||
final Function(String, bool) onClose;
|
||||
|
||||
final Function(Map<String, dynamic>) onSaveMiscellaneous;
|
||||
final Map<String, dynamic>? selectedItem;
|
||||
final int? selectedIndex;
|
||||
@ -137,7 +138,8 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
||||
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
|
||||
// if (widget.selectedItem == null) {
|
||||
// _commentsController.clear();
|
||||
@ -281,9 +283,10 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
||||
CustomTextFieldItnerarySubWrapper(
|
||||
isFocused: _isHotelNameFocused,
|
||||
isDesktop: isDesktop,
|
||||
width: isDesktop
|
||||
? MediaQuery.of(context).size.width * 0.34
|
||||
: MediaQuery.of(context).size.width * 0.66,
|
||||
width:
|
||||
isDesktop
|
||||
? MediaQuery.of(context).size.width * 0.34
|
||||
: MediaQuery.of(context).size.width * 0.66,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
width: double.infinity,
|
||||
@ -291,7 +294,7 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
||||
// focusNode: _taxiReqFocusNode,
|
||||
items: purposeList.cast<Map<String, dynamic>>(),
|
||||
selectedItem: purposeList.firstWhere(
|
||||
(item) => item['dropdown_key'] == selectedSpecialType,
|
||||
(item) => item['dropdown_key'] == selectedSpecialType,
|
||||
orElse: () => {},
|
||||
),
|
||||
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||
@ -328,31 +331,23 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
||||
if (selectedItem == null || selectedItem.isEmpty) {
|
||||
return Text(
|
||||
"Select ",
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.grey,
|
||||
fontSize: 13,
|
||||
),
|
||||
style: GoogleFonts.poppins(color: Colors.grey, fontSize: 13),
|
||||
);
|
||||
}
|
||||
return Text(
|
||||
selectedItem['dropdown_value'] ?? '',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
color: Colors.black,
|
||||
),
|
||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||
);
|
||||
},
|
||||
onChanged:
|
||||
purposeList.isNotEmpty
|
||||
? (newValue) {
|
||||
setState(() {
|
||||
selectedSpecialType = newValue as String?;
|
||||
});
|
||||
print(
|
||||
"Updating form data: -> ${newValue ?? ""}",
|
||||
);
|
||||
}
|
||||
: null,
|
||||
purposeList.isNotEmpty
|
||||
? (newValue) {
|
||||
setState(() {
|
||||
selectedSpecialType = newValue as String?;
|
||||
});
|
||||
print("Updating form data: -> ${newValue ?? ""}");
|
||||
}
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -421,7 +416,8 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
_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(
|
||||
backgroundColor: Colors.grey[400], // Light grey color
|
||||
|
||||
@ -10,7 +10,7 @@ import '../../widgets/custom_text_itnerary_sub.dart';
|
||||
|
||||
class TaxiScreen extends StatefulWidget {
|
||||
final Map<String, dynamic>? apiData;
|
||||
final Function(bool) onClose;
|
||||
final Function(String, bool) onClose;
|
||||
final Function(Map<String, dynamic>) onSavetaxi;
|
||||
final Map<String, dynamic>? selectedItem;
|
||||
final String? loginUser;
|
||||
@ -199,8 +199,8 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
||||
} else {
|
||||
widget.onSavetaxi(taxiData);
|
||||
}
|
||||
|
||||
widget.onClose(false); // Close screen after saving
|
||||
widget.onClose("Taxi", false);
|
||||
// widget.onClose(false); // Close screen after saving
|
||||
}
|
||||
|
||||
@override
|
||||
@ -404,7 +404,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
||||
// focusNode: _taxiReqFocusNode,
|
||||
items: purposeList.cast<Map<String, dynamic>>(),
|
||||
selectedItem: purposeList.firstWhere(
|
||||
(item) => item['dropdown_key'] == selectedCarType,
|
||||
(item) => item['dropdown_key'] == selectedCarType,
|
||||
orElse: () => {},
|
||||
),
|
||||
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||
@ -456,16 +456,14 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
||||
);
|
||||
},
|
||||
onChanged:
|
||||
purposeList.isNotEmpty
|
||||
? (newValue) {
|
||||
setState(() {
|
||||
selectedCarType = newValue as String?;
|
||||
});
|
||||
print(
|
||||
"Updating form data: -> ${newValue ?? ""}",
|
||||
);
|
||||
}
|
||||
: null,
|
||||
purposeList.isNotEmpty
|
||||
? (newValue) {
|
||||
setState(() {
|
||||
selectedCarType = newValue as String?;
|
||||
});
|
||||
print("Updating form data: -> ${newValue ?? ""}");
|
||||
}
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -544,9 +542,9 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
||||
isFocused: _taxiReqFocused,
|
||||
isDesktop: isDesktop,
|
||||
width:
|
||||
isDesktop
|
||||
? MediaQuery.of(context).size.width * 0.34
|
||||
: MediaQuery.of(context).size.width * 0.66,
|
||||
isDesktop
|
||||
? MediaQuery.of(context).size.width * 0.34
|
||||
: MediaQuery.of(context).size.width * 0.66,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
width: double.infinity,
|
||||
@ -554,7 +552,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
||||
// focusNode: _taxiReqFocusNode,
|
||||
items: purposeList.cast<Map<String, dynamic>>(),
|
||||
selectedItem: purposeList.firstWhere(
|
||||
(item) => item['dropdown_key'] == selectedReqTaxi,
|
||||
(item) => item['dropdown_key'] == selectedReqTaxi,
|
||||
orElse: () => {},
|
||||
),
|
||||
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||
@ -591,31 +589,23 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
||||
if (selectedItem == null || selectedItem.isEmpty) {
|
||||
return Text(
|
||||
"Select ",
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.grey,
|
||||
fontSize: 13,
|
||||
),
|
||||
style: GoogleFonts.poppins(color: Colors.grey, fontSize: 13),
|
||||
);
|
||||
}
|
||||
return Text(
|
||||
selectedItem['dropdown_value'] ?? '',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
color: Colors.black,
|
||||
),
|
||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||
);
|
||||
},
|
||||
onChanged:
|
||||
purposeList.isNotEmpty
|
||||
? (newValue) {
|
||||
setState(() {
|
||||
selectedReqTaxi = newValue as String?;
|
||||
});
|
||||
print(
|
||||
"Updating form data: -> ${newValue ?? ""}",
|
||||
);
|
||||
}
|
||||
: null,
|
||||
purposeList.isNotEmpty
|
||||
? (newValue) {
|
||||
setState(() {
|
||||
selectedReqTaxi = newValue as String?;
|
||||
});
|
||||
print("Updating form data: -> ${newValue ?? ""}");
|
||||
}
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -974,7 +964,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
||||
// Close Button
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
widget.onClose(false); // Close the dialog or screen
|
||||
widget.onClose("Taxi", false); // Close the dialog or screen
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.grey[400], // Light grey color
|
||||
|
||||
@ -5,6 +5,7 @@ import 'package:intl/intl.dart';
|
||||
import 'package:responsive_builder/responsive_builder.dart';
|
||||
|
||||
import '../../services/apiService.dart';
|
||||
import '../../widgets/custom_confirmation_dialog.dart';
|
||||
import '../../widgets/custom_text_field.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>? apiDataForClass;
|
||||
final Function(Map<String, dynamic>) onSavetrain;
|
||||
final Function(bool) onClose;
|
||||
final Function(String, bool) onClose;
|
||||
final Map<String, dynamic>? selectedItem;
|
||||
final String? loginUser;
|
||||
final String? tripType;
|
||||
@ -67,6 +68,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
||||
bool _commentsFocus = false;
|
||||
|
||||
String? selectedClass;
|
||||
String? exceptionalClass = "0";
|
||||
String? selectedFrom;
|
||||
String? selectedTo;
|
||||
|
||||
@ -80,6 +82,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
||||
// "from_station": _fromController.text,
|
||||
"to_station": selectedTo,
|
||||
// "to_station": _toController.text,
|
||||
"is_this_exceptional": exceptionalClass,
|
||||
"date": _dateController.text,
|
||||
"time": _timeController.text,
|
||||
"comments": _trainCommentsController.text,
|
||||
@ -151,6 +154,11 @@ class _TrainScreenState extends State<TrainScreen> {
|
||||
_dateController = initController("date");
|
||||
_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
|
||||
if (widget.selectedItem != null && widget.selectedItem!["class"] != null) {
|
||||
selectedClass = widget.selectedItem!["class"].toString();
|
||||
@ -288,8 +296,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
||||
} else {
|
||||
widget.onSavetrain(trainData);
|
||||
}
|
||||
|
||||
widget.onClose(false); // Close screen after saving
|
||||
widget.onClose("Train", false);
|
||||
// widget.onClose(false); // Close screen after saving
|
||||
}
|
||||
|
||||
@override
|
||||
@ -576,8 +584,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
||||
}
|
||||
|
||||
// Default selected value
|
||||
selectedClass ??=
|
||||
dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||
// selectedClass ??=
|
||||
// dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||
|
||||
return [
|
||||
Column(
|
||||
@ -631,17 +639,30 @@ class _TrainScreenState extends State<TrainScreen> {
|
||||
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: 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) {
|
||||
final bool isNotAllowed = item['is_allowed'] == 'No';
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
@ -651,7 +672,7 @@ class _TrainScreenState extends State<TrainScreen> {
|
||||
item['dropdown_value'] ?? '',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
color: Colors.black,
|
||||
color: isNotAllowed ? Colors.redAccent : Colors.black,
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -660,7 +681,10 @@ class _TrainScreenState extends State<TrainScreen> {
|
||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||
dropdownSearchDecoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 10,vertical: 10,),
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 10,
|
||||
),
|
||||
),
|
||||
),
|
||||
dropdownBuilder: (context, selectedItem) {
|
||||
@ -682,14 +706,59 @@ class _TrainScreenState extends State<TrainScreen> {
|
||||
);
|
||||
},
|
||||
onChanged:
|
||||
purposeList.isNotEmpty
|
||||
? (Map<String, dynamic>? newValue) {
|
||||
setState(() {
|
||||
selectedClass= newValue?['dropdown_key'];
|
||||
print("Selected Purpose: ${selectedClass}");
|
||||
});
|
||||
}
|
||||
: null,
|
||||
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}");
|
||||
});
|
||||
}
|
||||
|
||||
// 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),
|
||||
itemBuilder:
|
||||
(context, item, isSelected) => Container(
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 6,
|
||||
),
|
||||
child: Text(
|
||||
item,
|
||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||
),
|
||||
),
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 6,
|
||||
),
|
||||
child: Text(
|
||||
item,
|
||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||
),
|
||||
),
|
||||
searchFieldProps: TextFieldProps(
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search ...",
|
||||
@ -843,22 +912,20 @@ class _TrainScreenState extends State<TrainScreen> {
|
||||
),
|
||||
dropdownBuilder:
|
||||
(context, selectedItem) => Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
selectedItem ?? "Select ",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
color: Colors.black,
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
selectedItem ?? "Select ",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
onChanged: (String? newValue) {
|
||||
setState(() {
|
||||
selectedFrom =
|
||||
countryMap.entries
|
||||
.firstWhere(
|
||||
(entry) => entry.value == newValue,
|
||||
)
|
||||
.firstWhere((entry) => entry.value == newValue)
|
||||
.key;
|
||||
});
|
||||
},
|
||||
@ -952,16 +1019,16 @@ class _TrainScreenState extends State<TrainScreen> {
|
||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||
itemBuilder:
|
||||
(context, item, isSelected) => Container(
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 6,
|
||||
),
|
||||
child: Text(
|
||||
item,
|
||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||
),
|
||||
),
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 6,
|
||||
),
|
||||
child: Text(
|
||||
item,
|
||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||
),
|
||||
),
|
||||
searchFieldProps: TextFieldProps(
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search ...",
|
||||
@ -978,22 +1045,20 @@ class _TrainScreenState extends State<TrainScreen> {
|
||||
),
|
||||
dropdownBuilder:
|
||||
(context, selectedItem) => Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
selectedItem ?? "Select ",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
color: Colors.black,
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
selectedItem ?? "Select ",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
onChanged: (String? newValue) {
|
||||
setState(() {
|
||||
selectedTo =
|
||||
countryMap.entries
|
||||
.firstWhere(
|
||||
(entry) => entry.value == newValue,
|
||||
)
|
||||
.firstWhere((entry) => entry.value == newValue)
|
||||
.key;
|
||||
});
|
||||
},
|
||||
@ -1174,7 +1239,8 @@ class _TrainScreenState extends State<TrainScreen> {
|
||||
// Close Button
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
widget.onClose(false);
|
||||
// widget.onClose(false);
|
||||
widget.onClose("Train", false);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.grey[400], // Light grey color
|
||||
|
||||
@ -13,7 +13,7 @@ class VisaScreen extends StatefulWidget {
|
||||
final Map<String, dynamic>? apiData;
|
||||
final List<dynamic>? apiCountryData;
|
||||
|
||||
final Function(bool) onClose;
|
||||
final Function(String, bool) onClose;
|
||||
final Function(Map<String, dynamic>) onSaveVisa;
|
||||
final Map<String, dynamic>? selectedItem;
|
||||
final String? loginUser;
|
||||
@ -259,8 +259,8 @@ class _VisaScreenState extends State<VisaScreen> {
|
||||
} else {
|
||||
widget.onSaveVisa(visaData);
|
||||
}
|
||||
|
||||
widget.onClose(false); // Close screen after saving
|
||||
widget.onClose("Visa", false);
|
||||
// widget.onClose(false); // Close screen after saving
|
||||
}
|
||||
|
||||
@override
|
||||
@ -513,9 +513,10 @@ class _VisaScreenState extends State<VisaScreen> {
|
||||
CustomTextFieldItnerarySubWrapper(
|
||||
isFocused: _isHotelNameFocused,
|
||||
isDesktop: isDesktop,
|
||||
width: isDesktop
|
||||
? MediaQuery.of(context).size.width * 0.34
|
||||
: MediaQuery.of(context).size.width * 0.66,
|
||||
width:
|
||||
isDesktop
|
||||
? MediaQuery.of(context).size.width * 0.34
|
||||
: MediaQuery.of(context).size.width * 0.66,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: DropdownSearch<String>(
|
||||
@ -527,16 +528,16 @@ class _VisaScreenState extends State<VisaScreen> {
|
||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||
itemBuilder:
|
||||
(context, item, isSelected) => Container(
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 6,
|
||||
),
|
||||
child: Text(
|
||||
item,
|
||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||
),
|
||||
),
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 6,
|
||||
),
|
||||
child: Text(
|
||||
item,
|
||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||
),
|
||||
),
|
||||
searchFieldProps: TextFieldProps(
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search ...",
|
||||
@ -553,18 +554,21 @@ class _VisaScreenState extends State<VisaScreen> {
|
||||
),
|
||||
dropdownBuilder:
|
||||
(context, selectedItem) => Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
selectedItem ?? "Select ",
|
||||
style: GoogleFonts.poppins(fontSize: 12,color: Colors.black,),
|
||||
),
|
||||
),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
selectedItem ?? "Select ",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
onChanged: (String? newValue) {
|
||||
setState(() {
|
||||
selectedCountry =
|
||||
countryMap.entries.firstWhere(
|
||||
(entry) => entry.value == newValue,
|
||||
).key;
|
||||
countryMap.entries
|
||||
.firstWhere((entry) => entry.value == newValue)
|
||||
.key;
|
||||
});
|
||||
},
|
||||
),
|
||||
@ -635,7 +639,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
||||
child: DropdownSearch<Map<String, dynamic>>(
|
||||
items: purposeList.cast<Map<String, dynamic>>(),
|
||||
selectedItem: purposeList.firstWhere(
|
||||
(item) => item['dropdown_key'] == selectedPurpose,
|
||||
(item) => item['dropdown_key'] == selectedPurpose,
|
||||
orElse: () => {},
|
||||
),
|
||||
itemAsString: (item) => item['dropdown_value'] ?? '',
|
||||
@ -662,7 +666,10 @@ class _VisaScreenState extends State<VisaScreen> {
|
||||
dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||
dropdownSearchDecoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 10,vertical: 10,),
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 10,
|
||||
),
|
||||
),
|
||||
),
|
||||
dropdownBuilder: (context, selectedItem) {
|
||||
@ -692,14 +699,14 @@ class _VisaScreenState extends State<VisaScreen> {
|
||||
// EdgeInsets.symmetric(horizontal: 10), // Proper padding
|
||||
// ),
|
||||
onChanged:
|
||||
purposeList.isNotEmpty
|
||||
? (Map<String, dynamic>? newValue) {
|
||||
setState(() {
|
||||
selectedPurpose= newValue?['dropdown_key'];
|
||||
print("Selected Purpose: ${selectedPurpose}");
|
||||
});
|
||||
}
|
||||
: null,
|
||||
purposeList.isNotEmpty
|
||||
? (Map<String, dynamic>? newValue) {
|
||||
setState(() {
|
||||
selectedPurpose = newValue?['dropdown_key'];
|
||||
print("Selected Purpose: ${selectedPurpose}");
|
||||
});
|
||||
}
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -826,7 +833,8 @@ class _VisaScreenState extends State<VisaScreen> {
|
||||
// Close Button
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
widget.onClose(false); // Close the dialog or screen
|
||||
widget.onClose("Visa", false);
|
||||
// widget.onClose(false); // Close the dialog or screen
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.grey[400], // Light grey color
|
||||
|
||||
@ -133,7 +133,8 @@ class _FlightListWidgetState extends State<FlightListWidget> {
|
||||
widget.isViewMode
|
||||
? null
|
||||
: () {
|
||||
checkClass();
|
||||
widget.onAddNew("Flight", true);
|
||||
// checkClass();
|
||||
print("New data");
|
||||
},
|
||||
child: Row(
|
||||
|
||||
@ -298,6 +298,8 @@ class _CreatePlansState extends State<CreatePlan> {
|
||||
context.go('/listPlan');
|
||||
} else if (currentUri == "/approver/plans") {
|
||||
context.go('/approvallist');
|
||||
} else if (currentUri == "/travelagent/trips") {
|
||||
context.go('/listTravelAgentPlan');
|
||||
} else {
|
||||
isApprover ? context.go('/approvallist') : context.go('/listPlan');
|
||||
}
|
||||
@ -381,6 +383,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
|
||||
final TextEditingController _tripTitleController = TextEditingController();
|
||||
final TextEditingController _descriptionController = TextEditingController();
|
||||
final TextEditingController _excepntldescriptionController =
|
||||
TextEditingController();
|
||||
final TextEditingController _remarksController = TextEditingController();
|
||||
|
||||
// final FocusNode _tripTitleFocusNode = FocusNode();
|
||||
@ -416,6 +420,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
bool showDomestic = false;
|
||||
bool showInternational = false;
|
||||
bool hasAction = true;
|
||||
bool hasExceptionalClass = false;
|
||||
|
||||
late Map<String, String> costCenterMap;
|
||||
List<String> costCenterIds = [];
|
||||
@ -445,10 +450,10 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
List<Map<String, dynamic>> insuranceList = [];
|
||||
List<Map<String, dynamic>> accommodationList = [];
|
||||
List<Map<String, dynamic>> trainList = [];
|
||||
List<Map<String, dynamic>> flightList = [];
|
||||
List<Map<String, dynamic>> busList = [];
|
||||
List<Map<String, dynamic>> taxiList = [];
|
||||
List<Map<String, dynamic>> forexList = [];
|
||||
List<Map<String, dynamic>> flightList = [];
|
||||
|
||||
List<Map<String, dynamic>> planStatusList = [];
|
||||
|
||||
@ -471,6 +476,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
"is_billable": _selectedIsBillable,
|
||||
"purpose_of_travel": selectedPurpose,
|
||||
"description": _descriptionController.text,
|
||||
"exceptional_plan_reason": _excepntldescriptionController.text,
|
||||
"functional_department": selectedFuncDept,
|
||||
"so_number": "12345",
|
||||
"created_by": selfId,
|
||||
@ -495,6 +501,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
"is_billable",
|
||||
"purpose_of_travel",
|
||||
"description",
|
||||
"excepntldescription",
|
||||
"functional_department",
|
||||
];
|
||||
|
||||
@ -535,6 +542,13 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
print("Updated $type List: $newList");
|
||||
}
|
||||
|
||||
void handleExcentionalClass(bool val) {
|
||||
print("handleExcentionalClass - $val");
|
||||
setState(() {
|
||||
hasExceptionalClass = val;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@ -652,6 +666,13 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
_descriptionController.text =
|
||||
widget.selectedPlanData['description'] ?? '';
|
||||
|
||||
_excepntldescriptionController.text =
|
||||
widget.selectedPlanData['exceptional_plan_reason'] ?? '';
|
||||
|
||||
if (_excepntldescriptionController.text != "") {
|
||||
hasExceptionalClass = true;
|
||||
}
|
||||
|
||||
_selectedTripType = widget.selectedPlanData['trip_type'];
|
||||
flightTripTypeNotifier.value = widget.selectedPlanData['trip_type'];
|
||||
_selectedIsBillable =
|
||||
@ -1136,6 +1157,8 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
"cost_center_id": selectedCostCenterId,
|
||||
"functional_department": selectedFuncDept,
|
||||
"purpose_of_travel": selectedPurpose,
|
||||
if (hasExceptionalClass)
|
||||
"exceptional_plan_reason": _excepntldescriptionController.text,
|
||||
};
|
||||
print("validateForm.....3");
|
||||
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() {
|
||||
setState(() async {
|
||||
await checkExceptionalClass();
|
||||
|
||||
print("Handle Submit....after check");
|
||||
|
||||
print("Hansle Submit....11");
|
||||
if (validateForm() && temporaryMessage == null) {
|
||||
print("Hansle Submit....11222");
|
||||
@ -1690,17 +1760,18 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
? Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// _buildNonDescriptionColumn(),
|
||||
// SizedBox(width: 25),
|
||||
//
|
||||
_buildDescriptionColumn(isDesktop),
|
||||
SizedBox(width: 25),
|
||||
if (hasExceptionalClass) _buildNonDescriptionColumn(),
|
||||
],
|
||||
)
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// _buildNonDescriptionColumn(),
|
||||
// SizedBox(height: 15),
|
||||
_buildDescriptionColumn(isDesktop),
|
||||
SizedBox(height: 15),
|
||||
_buildNonDescriptionColumn(),
|
||||
],
|
||||
),
|
||||
|
||||
@ -1743,6 +1814,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
apiDataForClass: apiDataForClass,
|
||||
apiCountryData: apiCountryData,
|
||||
onItineraryUpdate: handleItineraryUpdate,
|
||||
onExeptionalClass: handleExcentionalClass,
|
||||
loginUser: selfId,
|
||||
selectedPlanData: planData,
|
||||
isViewMode: widget.isViewMode,
|
||||
@ -3248,7 +3320,7 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Trip Name", // Your label
|
||||
"Reason For Exceptional Class *", // Your label
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
@ -3256,32 +3328,54 @@ class CreateNewPlansState extends State<CreateNewPlan> {
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
|
||||
CustomTextFieldWrapper(
|
||||
isFocused: false,
|
||||
// isFocused: _isTripTitleFocused,
|
||||
isFocused: focusStates["excepntldescriptionFocused"] ?? false,
|
||||
// isFocused: _isdescriptionFocused,
|
||||
width:
|
||||
widget.isDesktop
|
||||
? MediaQuery.of(context).size.width * 0.42
|
||||
: null,
|
||||
isDesktop: widget.isDesktop,
|
||||
child: SizedBox(
|
||||
height: 35,
|
||||
height: 55,
|
||||
child: TextField(
|
||||
// focusNode: _tripTitleFocusNode,
|
||||
controller: _tripTitleController,
|
||||
focusNode: focusNodes["excepntldescriptionFocusNode"],
|
||||
controller: _excepntldescriptionController,
|
||||
maxLines: 2,
|
||||
keyboardType: TextInputType.multiline,
|
||||
style: TextStyle(fontSize: 12),
|
||||
enabled: !widget.isViewMode,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Trip Name",
|
||||
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||
labelText: "Exceptional Description",
|
||||
labelStyle: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
),
|
||||
// labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
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 Function(String, List<Map<String, dynamic>>)
|
||||
onItineraryUpdate; // Updated Signature
|
||||
|
||||
final void Function(bool)? onExeptionalClass;
|
||||
final Map<String, dynamic> selectedPlanData;
|
||||
final bool isViewMode;
|
||||
final GlobalKey<FlightScreenState> flightScreenKey;
|
||||
@ -48,6 +50,7 @@ class DynamicItinerary extends StatefulWidget {
|
||||
required this.selectedPlanData,
|
||||
required this.isViewMode,
|
||||
required this.hasAction,
|
||||
this.onExeptionalClass,
|
||||
this.tripType,
|
||||
this.apiDataForClass,
|
||||
required this.tripTypeNotifier,
|
||||
@ -64,6 +67,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
||||
String? _tripType;
|
||||
String selectedOption = "";
|
||||
String selectedListOption = "";
|
||||
String selectedActiveTab = "";
|
||||
|
||||
bool isSelected = false;
|
||||
Map<String, dynamic>? selectedItem;
|
||||
@ -400,7 +404,8 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
||||
return false; // No itinerary data available
|
||||
}
|
||||
|
||||
void handleClose(bool value) {
|
||||
void handleMClose(bool value) {
|
||||
print("handleClos- $isSelected");
|
||||
setState(() {
|
||||
selectedOption = "";
|
||||
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) {
|
||||
setState(() {
|
||||
selectedOption = title;
|
||||
@ -420,6 +436,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
||||
}
|
||||
|
||||
void handlecreateNewPlan(name, bool value) {
|
||||
print("handlecreateNewPlan- $name , $value");
|
||||
setState(() {
|
||||
selectedOption = name;
|
||||
isSelected = value;
|
||||
@ -710,6 +727,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
||||
break;
|
||||
case "Miscellaneous":
|
||||
selectedWidget = MiscellaneousScreen(
|
||||
// onClose: handleClose,
|
||||
onClose: handleClose,
|
||||
apiData: widget.apiData,
|
||||
loginUser: widget.loginUser,
|
||||
@ -723,10 +741,12 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
||||
selectedWidget = AccomodationScreen(
|
||||
onClose: handleClose,
|
||||
loginUser: widget.loginUser,
|
||||
apiDataForClass: widget.apiDataForClass,
|
||||
onSaveAccomadation:
|
||||
(data) => handleItineraryUpdate("Accomodation", data),
|
||||
selectedItem: selectedItem,
|
||||
flightData: itineraryData["Flight"]!,
|
||||
onExceptionalClass: widget.onExeptionalClass,
|
||||
);
|
||||
break;
|
||||
case "Forex":
|
||||
@ -747,6 +767,7 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
||||
tripTypeNotifier: widget.tripTypeNotifier,
|
||||
hasAction: widget.hasAction,
|
||||
tripType: widget.tripType,
|
||||
// onClose: handleMClose,
|
||||
onClose: handleClose,
|
||||
loginUser: widget.loginUser,
|
||||
onSaveFlight: (data) => handleItineraryUpdate("Flight", data),
|
||||
@ -758,71 +779,6 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
||||
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(
|
||||
builder: (context, sizingInfo) {
|
||||
bool isMobile = sizingInfo.isMobile;
|
||||
@ -964,19 +920,69 @@ class DynamicItineraryState extends State<DynamicItinerary> {
|
||||
}).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) {
|
||||
String name = service['name'];
|
||||
String iconUrl = service['icon']; // Can be empty string
|
||||
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(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
selectedListOption = name;
|
||||
isSelected = false;
|
||||
});
|
||||
if (checkClass()) {
|
||||
setState(() {
|
||||
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(
|
||||
decoration: BoxDecoration(
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
//api url
|
||||
// const String apiUrl = 'http://apitest.tripapprovaltool.com/tstat_be';
|
||||
const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be';
|
||||
const String apiUrl = 'http://apitest.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'
|
||||
// },
|
||||
// {'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',
|
||||
'icon': Icons.account_circle,
|
||||
|
||||
@ -81,6 +81,10 @@ final GoRouter router = GoRouter(
|
||||
path: '/approver/plans',
|
||||
builder: (context, state) => CreatePlan(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/travelagent/trips',
|
||||
builder: (context, state) => CreatePlan(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/listUser',
|
||||
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 {
|
||||
String? orgId = await getOrgId();
|
||||
String? userId = await getUserId();
|
||||
@ -899,8 +918,8 @@ class ApiService {
|
||||
|
||||
// download the Template for bulk upload the user
|
||||
Future<void> getDownloadUserTemplateForUpload() async {
|
||||
|
||||
final String apiUrldata = '$apiUrl/api/user/userUploadTemplate'; // download the Template for bulk upload user => api
|
||||
final String apiUrldata =
|
||||
'$apiUrl/api/user/userUploadTemplate'; // download the Template for bulk upload user => api
|
||||
|
||||
// final String apiUrldata = '$apiUrl/auth/googlelogin';
|
||||
|
||||
@ -930,9 +949,9 @@ class ApiService {
|
||||
|
||||
// Create a link element to trigger the download
|
||||
final anchor =
|
||||
html.AnchorElement(href: url)
|
||||
..setAttribute('download', 'user_file.xlsx')
|
||||
..click();
|
||||
html.AnchorElement(href: url)
|
||||
..setAttribute('download', 'user_file.xlsx')
|
||||
..click();
|
||||
|
||||
// Revoke the download URL to free up resources
|
||||
html.Url.revokeObjectUrl(url);
|
||||
@ -962,7 +981,6 @@ class ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------User Management-----------------------------------
|
||||
|
||||
Future<Map<String, dynamic>> getSingleUser(int userId) async {
|
||||
@ -1511,7 +1529,7 @@ class ApiService {
|
||||
|
||||
// ----------------------- User Management - CheckDuplicate end here ----------------------------------
|
||||
// ----------------------- 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';
|
||||
final token = await getToken();
|
||||
|
||||
@ -1521,8 +1539,11 @@ class ApiService {
|
||||
|
||||
final response = await http.post(
|
||||
Uri.parse(apiUrldata),
|
||||
headers: {'Authorization': 'Bearer $token','Content-Type': 'application/json'},
|
||||
body: body
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: body,
|
||||
);
|
||||
|
||||
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';
|
||||
|
||||
// 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 token = await getToken();
|
||||
|
||||
if (token == null) {
|
||||
@ -1554,9 +1581,12 @@ class ApiService {
|
||||
}
|
||||
|
||||
final response = await http.post(
|
||||
Uri.parse(apiUrldata),
|
||||
headers: {'Authorization': 'Bearer $token','Content-Type': 'application/json'},
|
||||
body: body
|
||||
Uri.parse(apiUrldata),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: body,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
@ -1571,9 +1601,9 @@ class ApiService {
|
||||
|
||||
// Create a link element to trigger the download
|
||||
final anchor =
|
||||
html.AnchorElement(href: url)
|
||||
..setAttribute('download', excelName)
|
||||
..click();
|
||||
html.AnchorElement(href: url)
|
||||
..setAttribute('download', excelName)
|
||||
..click();
|
||||
|
||||
// Revoke the download URL to free up resources
|
||||
html.Url.revokeObjectUrl(url);
|
||||
@ -1587,5 +1617,6 @@ class ApiService {
|
||||
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