1431 lines
46 KiB
Dart
1431 lines
46 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:dotted_border/dotted_border.dart';
|
|
import 'package:easy_stepper/easy_stepper.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:frontend/Screens/itnerary_list/accomodation_list.dart';
|
|
import 'package:frontend/Screens/itnerary_list/bus_list.dart';
|
|
import 'package:frontend/Screens/itnerary_list/flight_list.dart';
|
|
import 'package:frontend/Screens/itnerary_list/taxi_list.dart';
|
|
import 'package:frontend/Screens/itnerary_list/train_list.dart';
|
|
import 'package:frontend/utils/auth_utils.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:responsive_builder/responsive_builder.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import '../../services/apiService.dart';
|
|
import '../../utils/auth_utils.dart';
|
|
import '../itnerary/accomodations.dart';
|
|
import '../itnerary/bus.dart';
|
|
import '../itnerary/flights.dart';
|
|
import '../itnerary/forex.dart';
|
|
import '../itnerary/insurance.dart';
|
|
import '../itnerary/miscellaneous.dart';
|
|
import '../itnerary/taxi.dart';
|
|
import '../itnerary/train.dart';
|
|
import '../itnerary/visa.dart';
|
|
import '../itnerary_list/forex_list.dart';
|
|
import '../itnerary_list/insurance_list.dart';
|
|
import '../itnerary_list/miscellaneous_list.dart';
|
|
import '../itnerary_list/visa_list.dart';
|
|
|
|
class DynamicItinerary extends StatefulWidget {
|
|
final bool hasAction;
|
|
final String? tripType;
|
|
final Map<String, dynamic>? apiData;
|
|
final Map<String, dynamic>? apiDataForClass;
|
|
final List<dynamic>? apiCountryData;
|
|
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;
|
|
final ValueNotifier<String?> tripTypeNotifier;
|
|
|
|
const DynamicItinerary({
|
|
super.key,
|
|
required this.apiData,
|
|
required this.onItineraryUpdate,
|
|
required this.apiCountryData,
|
|
required this.loginUser,
|
|
required this.selectedPlanData,
|
|
required this.isViewMode,
|
|
required this.hasAction,
|
|
this.onExeptionalClass,
|
|
this.tripType,
|
|
this.apiDataForClass,
|
|
required this.tripTypeNotifier,
|
|
required this.flightScreenKey,
|
|
});
|
|
|
|
@override
|
|
DynamicItineraryState createState() => DynamicItineraryState();
|
|
}
|
|
|
|
class DynamicItineraryState extends State<DynamicItinerary> {
|
|
final ApiService apiService = ApiService();
|
|
|
|
late ScrollController _scrollController;
|
|
bool _canScrollLeft = false;
|
|
bool _canScrollRight = true;
|
|
|
|
Color? layoutColor;
|
|
Color? secondColor;
|
|
Color? thridColor;
|
|
|
|
String? _tripType;
|
|
String selectedOption = "";
|
|
String selectedListOption = "";
|
|
String selectedActiveTab = "";
|
|
|
|
bool isSelected = false;
|
|
Map<String, dynamic>? selectedItem;
|
|
int? selectedIndex;
|
|
|
|
List<dynamic>? selectedAllServices;
|
|
// List<Map<String, String>> selectedOrgServiceIds = [];
|
|
List<Map<String, dynamic>> selectedOrgServiceIds = [];
|
|
List<dynamic>? ServicesChoosed;
|
|
List<String> filledItineraryKeys = [];
|
|
|
|
// List<Map<String, dynamic>> miscellaneousList = [];
|
|
|
|
Map<String, List<Map<String, dynamic>>> itineraryData = {
|
|
"Train": [],
|
|
"Bus": [],
|
|
"Taxi": [],
|
|
"Miscellaneous": [],
|
|
"Flight": [],
|
|
"Accomodation": [],
|
|
"Insurance": [],
|
|
"Visa": [],
|
|
"Forex": [],
|
|
};
|
|
|
|
@override
|
|
void initState() {
|
|
print("DynamicItinerary");
|
|
super.initState();
|
|
handleSelectedPlan();
|
|
updateSelectedServices();
|
|
_tripType = widget.tripType;
|
|
loadInitialData();
|
|
_scrollController = ScrollController();
|
|
_scrollController.addListener(_updateScrollButtonState);
|
|
// Delay check after layout is built
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
_updateScrollButtonState(); // Initial scroll check
|
|
});
|
|
}
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
super.didChangeDependencies();
|
|
|
|
if (widget.tripType != _tripType) {
|
|
// setState(() {
|
|
// selectedOption = "";
|
|
// isSelected = false;
|
|
// selectedIndex = null;
|
|
// selectedItem = null;
|
|
// });
|
|
print("updateTripType - $_tripType");
|
|
updateTripType(widget.tripType);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_scrollController.removeListener(_updateScrollButtonState);
|
|
_scrollController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
void _updateScrollButtonState() {
|
|
if (!_scrollController.hasClients) return;
|
|
|
|
final max = _scrollController.position.maxScrollExtent;
|
|
final offset = _scrollController.offset;
|
|
|
|
setState(() {
|
|
_canScrollLeft = offset > 0;
|
|
_canScrollRight = offset < max;
|
|
});
|
|
}
|
|
|
|
void loadInitialData() async {
|
|
String? layoutString = await getLayoutColor();
|
|
String? secondString = await getSecondaryColor();
|
|
String? thridString = await getTernaryColor();
|
|
|
|
// String? bodyStringColor = await getBodyColor();
|
|
|
|
setState(() {
|
|
layoutColor =
|
|
layoutString != null
|
|
? Color(int.parse(layoutString))
|
|
: Colors.redAccent;
|
|
|
|
secondColor =
|
|
layoutString != null
|
|
? Color(int.parse(secondString!))
|
|
: Colors.orange;
|
|
|
|
thridColor =
|
|
layoutString != null
|
|
? Color(int.parse(thridString!))
|
|
: Colors.orangeAccent;
|
|
// bodyColor =
|
|
// bodyStringColor != null
|
|
// ? Color(int.parse(bodyStringColor))
|
|
// : Colors.white;
|
|
});
|
|
}
|
|
|
|
void updateTripType(String? newTripType) {
|
|
if (_tripType != newTripType) {
|
|
setState(() {
|
|
_tripType = newTripType;
|
|
});
|
|
updateSelectedServices(); // Refresh services based on new tripType
|
|
|
|
print("updateTripType2 - $newTripType");
|
|
handleSelectedPlan();
|
|
}
|
|
}
|
|
|
|
Future<void> loadAllServices() async {
|
|
try {
|
|
final result = await apiService.fetchAllServices(context);
|
|
setState(() {
|
|
selectedAllServices = result;
|
|
});
|
|
print("Fetched services Order: $selectedAllServices");
|
|
} catch (e) {
|
|
print('Error fetching role list: $e');
|
|
}
|
|
}
|
|
|
|
/// Org token based services
|
|
Future<void> loadOrgSelectedAlServices() async {
|
|
print('loadOrgSelectedAlServices');
|
|
try {
|
|
final result = await apiService.fetchOrganization(context);
|
|
|
|
if (result != null && result is Map<String, dynamic>) {
|
|
final rawServices = result['services_ids'];
|
|
|
|
if (rawServices != null && rawServices is String) {
|
|
try {
|
|
List<dynamic> decoded = json.decode(rawServices);
|
|
List<Map<String, String>> formatted =
|
|
decoded
|
|
.map((e) => {"service_id": e['service_id'].toString()})
|
|
.toList();
|
|
|
|
setState(() {
|
|
selectedOrgServiceIds = formatted;
|
|
});
|
|
print("selectedOrgServiceIds: ${selectedOrgServiceIds}");
|
|
|
|
for (var service in selectedOrgServiceIds) {
|
|
print("service_id: ${service['service_id']}");
|
|
}
|
|
} catch (e) {
|
|
print("Failed to decode services_ids: $e");
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
print('Error fetching role list: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> saveSelectedOrgServices(
|
|
List<Map<String, dynamic>> services,
|
|
) async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final jsonString = jsonEncode(services);
|
|
await prefs.setString("selectedOrgServiceName", jsonString);
|
|
}
|
|
|
|
Future<void> OrgServices() async {
|
|
print('loadOrgSelectedAlServices');
|
|
try {
|
|
List<Map<String, String>> formattedName =
|
|
selectedOrgServiceIds.map((e) {
|
|
final id = e['service_id'].toString();
|
|
|
|
// find matching service from master list
|
|
final match = selectedAllServices?.firstWhere(
|
|
(service) => service['service_id'].toString() == id,
|
|
orElse: () => {},
|
|
);
|
|
|
|
return {
|
|
"service_id": id,
|
|
"name": match.isNotEmpty ? match['name'].toString() : "",
|
|
};
|
|
}).toList();
|
|
await saveSelectedOrgServices(formattedName);
|
|
print("ServiceformattedName: $formattedName");
|
|
} catch (e) {
|
|
print('Error fetching role list: $e');
|
|
}
|
|
}
|
|
|
|
List<String> getAllowedServiceNames() {
|
|
print(
|
|
"DID Updatee changee - $selectedOption $selectedListOption $isSelected $selectedItem $selectedIndex",
|
|
);
|
|
setState(() {
|
|
selectedOption = "";
|
|
selectedListOption = "";
|
|
isSelected = false;
|
|
selectedIndex = null;
|
|
selectedItem = null;
|
|
});
|
|
print(
|
|
"DID Updatee changee - $selectedOption $isSelected $selectedItem $selectedIndex",
|
|
);
|
|
|
|
if (widget.tripType == "1") {
|
|
return ["flight", "accomodation", "train", "bus", "taxi"];
|
|
} else if (widget.tripType == "2") {
|
|
return [
|
|
"flight",
|
|
"accomodation",
|
|
"forex",
|
|
"insurance",
|
|
"visa",
|
|
"miscellaneous",
|
|
"taxi",
|
|
];
|
|
} else {
|
|
// tripType is null or not 1/2, allow everything
|
|
return [];
|
|
}
|
|
}
|
|
|
|
void clearAllServiceLists() async {
|
|
print("clearAllServiceLists");
|
|
setState(() {
|
|
itineraryData.updateAll((key, value) => []);
|
|
});
|
|
}
|
|
|
|
// Future<void> updateSelectedServices() async {
|
|
// await loadAllServices();
|
|
// await loadOrgSelectedAlServices();
|
|
//
|
|
// if (hasAnyItineraryData()) {
|
|
// print("SELCTSplanChhose: ${filledItineraryKeys}");
|
|
//
|
|
// final selectedIds =
|
|
// selectedOrgServiceIds.map((e) => e['service_id']).toSet();
|
|
//
|
|
// // Filter services that match filled keys (name match) and are not already selected
|
|
// final additionalServices = selectedAllServices!.where((service) {
|
|
// final name = (service['name'] ?? "").toString().toLowerCase();
|
|
// final id = service['service_id'].toString();
|
|
// return filledItineraryKeys.contains(name) && !selectedIds.contains(id);
|
|
// }).toList();
|
|
//
|
|
// final originalFiltered = selectedAllServices!
|
|
// .where((service) =>
|
|
// selectedIds.contains(service['service_id'].toString()))
|
|
// .toList();
|
|
//
|
|
// // setState(() {
|
|
// // ServicesChoosed = [...originalFiltered, ...additionalServices];
|
|
// // });
|
|
// setState(() {
|
|
// ServicesChoosed = [...originalFiltered, ...additionalServices]
|
|
// ..sort((a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0));
|
|
// });
|
|
//
|
|
// print(
|
|
// "Services chosen based on filled keys + selected: $ServicesChoosed");
|
|
// } else {
|
|
// final selectedIds =
|
|
// selectedOrgServiceIds.map((e) => e['service_id']).toSet();
|
|
//
|
|
// final filtered = selectedAllServices!
|
|
// .where((service) =>
|
|
// selectedIds.contains(service['service_id'].toString()))
|
|
// .toList();
|
|
//
|
|
// setState(() {
|
|
// ServicesChoosed = filtered
|
|
// ..sort((a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0));
|
|
// });
|
|
//
|
|
// // setState(() {
|
|
// // ServicesChoosed = filtered;
|
|
// // });
|
|
//
|
|
// print("Filtered Selected Services Chooesed: $ServicesChoosed");
|
|
// }
|
|
// }
|
|
|
|
Future<void> updateSelectedServices() async {
|
|
await loadAllServices();
|
|
await loadOrgSelectedAlServices();
|
|
await OrgServices();
|
|
|
|
final allowedServiceNames = getAllowedServiceNames();
|
|
|
|
if (hasAnyItineraryData()) {
|
|
print("SELCTSplanChhose: $filledItineraryKeys");
|
|
|
|
final selectedIds =
|
|
selectedOrgServiceIds.map((e) => e['service_id']).toSet();
|
|
|
|
final additionalServices =
|
|
selectedAllServices!.where((service) {
|
|
final name = (service['name'] ?? "").toString().toLowerCase();
|
|
final id = service['service_id'].toString();
|
|
final isNameAllowed =
|
|
allowedServiceNames.isEmpty ||
|
|
allowedServiceNames.contains(name);
|
|
return filledItineraryKeys.contains(name) &&
|
|
!selectedIds.contains(id) &&
|
|
isNameAllowed;
|
|
}).toList();
|
|
|
|
final originalFiltered =
|
|
selectedAllServices!.where((service) {
|
|
final name = (service['name'] ?? "").toString().toLowerCase();
|
|
final id = service['service_id'].toString();
|
|
final isNameAllowed =
|
|
allowedServiceNames.isEmpty ||
|
|
allowedServiceNames.contains(name);
|
|
return selectedIds.contains(id) && isNameAllowed;
|
|
}).toList();
|
|
|
|
setState(() {
|
|
ServicesChoosed = [...originalFiltered, ...additionalServices]
|
|
..sort((a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0));
|
|
});
|
|
|
|
print(
|
|
"Services chosen based on filled keys + selected: $ServicesChoosed",
|
|
);
|
|
} else {
|
|
final selectedIds =
|
|
selectedOrgServiceIds.map((e) => e['service_id']).toSet();
|
|
|
|
final filtered =
|
|
selectedAllServices!.where((service) {
|
|
final name = (service['name'] ?? "").toString().toLowerCase();
|
|
final isNameAllowed =
|
|
allowedServiceNames.isEmpty ||
|
|
allowedServiceNames.contains(name);
|
|
return selectedIds.contains(service['service_id'].toString()) &&
|
|
isNameAllowed;
|
|
}).toList();
|
|
|
|
setState(() {
|
|
ServicesChoosed =
|
|
filtered
|
|
..sort((a, b) => (a['order'] ?? 0).compareTo(b['order'] ?? 0));
|
|
});
|
|
|
|
print("Filtered Selected Services Chosen: $ServicesChoosed");
|
|
}
|
|
}
|
|
|
|
void handleSelectedPlan() {
|
|
print("handleSelectedPlan");
|
|
// Check if selectedPlanData has itinerary data
|
|
if (hasAnyItineraryData()) {
|
|
print("selectedPlanData HAS DATA");
|
|
|
|
setState(() {
|
|
itineraryData = {
|
|
"Train": List<Map<String, dynamic>>.from(
|
|
widget.selectedPlanData['train'] ?? [],
|
|
),
|
|
"Bus": List<Map<String, dynamic>>.from(
|
|
widget.selectedPlanData['bus'] ?? [],
|
|
),
|
|
"Taxi": List<Map<String, dynamic>>.from(
|
|
widget.selectedPlanData['taxi'] ?? [],
|
|
),
|
|
"Miscellaneous": List<Map<String, dynamic>>.from(
|
|
widget.selectedPlanData['miscellaneous'] ?? [],
|
|
),
|
|
"Flight": List<Map<String, dynamic>>.from(
|
|
widget.selectedPlanData['flight'] ?? [],
|
|
),
|
|
"Accomodation": List<Map<String, dynamic>>.from(
|
|
widget.selectedPlanData['accomodation'] ?? [],
|
|
),
|
|
"Insurance": List<Map<String, dynamic>>.from(
|
|
widget.selectedPlanData['insurance'] ?? [],
|
|
),
|
|
"Visa": List<Map<String, dynamic>>.from(
|
|
widget.selectedPlanData['visa'] ?? [],
|
|
),
|
|
"Forex": List<Map<String, dynamic>>.from(
|
|
widget.selectedPlanData['forex'] ?? [],
|
|
),
|
|
};
|
|
});
|
|
} else {
|
|
print("No itinerary data available");
|
|
}
|
|
}
|
|
|
|
bool hasAnyItineraryData() {
|
|
List<String> keys = [
|
|
"train",
|
|
"bus",
|
|
"taxi",
|
|
"miscellaneous",
|
|
"flight",
|
|
"accomodation",
|
|
"insurance",
|
|
"visa",
|
|
"forex",
|
|
];
|
|
|
|
// for (String key in keys) {
|
|
// if (widget.selectedPlanData.containsKey(key) &&
|
|
// widget.selectedPlanData[key] is List &&
|
|
// (widget.selectedPlanData[key] as List).isNotEmpty) {
|
|
// print("SelectedPLANDFDDSF- ${widget.selectedPlanData}");
|
|
// return true; // At least one list has data
|
|
// }
|
|
// }
|
|
|
|
filledItineraryKeys.clear(); // Clear previous results
|
|
|
|
for (String key in keys) {
|
|
if (widget.selectedPlanData.containsKey(key) &&
|
|
widget.selectedPlanData[key] is List &&
|
|
(widget.selectedPlanData[key] as List).isNotEmpty) {
|
|
filledItineraryKeys.add(key); // Store key with data
|
|
}
|
|
}
|
|
|
|
if (filledItineraryKeys.isNotEmpty) {
|
|
print("Selected keys with data: $filledItineraryKeys");
|
|
return true;
|
|
}
|
|
|
|
return false; // No itinerary data available
|
|
}
|
|
|
|
void handleMClose(bool value) {
|
|
print("handleClos- $isSelected");
|
|
setState(() {
|
|
selectedOption = "";
|
|
isSelected = value;
|
|
selectedIndex = null;
|
|
selectedItem = null;
|
|
});
|
|
}
|
|
|
|
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;
|
|
isSelected = value;
|
|
this.selectedItem = selectedItem;
|
|
});
|
|
|
|
print(selectedItem);
|
|
}
|
|
|
|
void handlecreateNewPlan(name, bool value) {
|
|
print("handlecreateNewPlan- $name , $value");
|
|
setState(() {
|
|
selectedOption = name;
|
|
isSelected = value;
|
|
this.selectedItem = null;
|
|
});
|
|
}
|
|
|
|
Widget build(BuildContext context) {
|
|
Widget selectedWidget;
|
|
Widget selectedListWidget;
|
|
|
|
void handleItineraryUpdate(String type, Map<String, dynamic> newData) {
|
|
setState(() {
|
|
if (!itineraryData.containsKey(type)) {
|
|
itineraryData[type] = []; // Initialize if null
|
|
}
|
|
|
|
List<Map<String, dynamic>> itemList = itineraryData[type]!;
|
|
|
|
print("newData - $newData");
|
|
|
|
// int? existingId = newData["id"];
|
|
// String? existingId = newData["id"];
|
|
|
|
String? idKey = "${type.toLowerCase()}_id";
|
|
String? existingId = newData[idKey];
|
|
|
|
print("Looking for ID using key: $idKey, Found ID: $existingId");
|
|
|
|
int? existingIndex = newData["indx"];
|
|
print("existingIndex - $existingIndex, existingId - $existingId");
|
|
|
|
// CASE 2: Update using id if available
|
|
if (existingId != null && existingId != 0) {
|
|
// int itemId = itemList.indexWhere((item) => item["id"] == existingId);
|
|
int itemId = itemList.indexWhere(
|
|
(item) => item[idKey]?.toString() == existingId.toString(),
|
|
);
|
|
|
|
if (itemId != -1) {
|
|
print(" Updating existing item with id: $existingId");
|
|
newData["is_active"] = "1";
|
|
itemList[itemId] = newData;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// CASE 1: Update if indx exists in list
|
|
if (existingIndex != null && existingIndex != 0) {
|
|
int itemIndex = itemList.indexWhere(
|
|
(item) => item["indx"] == existingIndex,
|
|
);
|
|
if (itemIndex != -1) {
|
|
print("Updating existing item with indx: $existingIndex");
|
|
newData["is_active"] = "1";
|
|
itemList[itemIndex] = newData; // Update the item
|
|
return;
|
|
}
|
|
}
|
|
// CASE 3: New Entry (Assign new indx)
|
|
print(" Creating new entry");
|
|
newData["indx"] = itemList.length + 1; // Assign a new indx
|
|
newData["is_active"] = "1";
|
|
itemList.add(newData);
|
|
|
|
print(" Updated $type List: ${itineraryData[type]}");
|
|
});
|
|
print(" onItineraryUpdate - $type - ${itineraryData[type]!} ");
|
|
widget.onItineraryUpdate(type, itineraryData[type]!); // Notify parent
|
|
}
|
|
|
|
void handleItinerarydelete(String type, Map<String, dynamic> data) {
|
|
setState(() {
|
|
// if(!itineraryData.containsKey(type)){
|
|
// return;
|
|
// }
|
|
|
|
if (!itineraryData.containsKey(type)) {
|
|
itineraryData[type] = []; // Initialize if null
|
|
}
|
|
|
|
List<Map<String, dynamic>> itemList = itineraryData[type]!;
|
|
|
|
String? idKey = "${type.toLowerCase()}_id";
|
|
String? existingId = data[idKey];
|
|
// int? existingId = data["id"];
|
|
// String? existingId = data["id"];
|
|
int? existingIndex = data["indx"];
|
|
|
|
print("🗑️ Deleting item -> ID: $existingId, Index: $existingIndex");
|
|
|
|
// Delete by ID
|
|
if (existingId != null && existingId != 0) {
|
|
// itemList.removeWhere((item) => item[idKey]?.toString() == existingId.toString());
|
|
|
|
for (var item in itemList) {
|
|
if (item[idKey]?.toString() == existingId.toString()) {
|
|
item["is_active"] = 0; // Soft delete
|
|
print("Updated is_active to 0 for ID: $existingId");
|
|
}
|
|
}
|
|
itineraryData[type] = List.from(itemList);
|
|
print("Deleted by ID: $existingId");
|
|
}
|
|
//Delete by Index
|
|
else if (existingIndex != null && existingId != 0) {
|
|
itemList.removeWhere((item) => item["indx"] == existingIndex);
|
|
print("Deleted by ID: $existingIndex");
|
|
} else {
|
|
print("No Valid Deletion");
|
|
}
|
|
|
|
itineraryData[type] = List.from(itemList);
|
|
});
|
|
print(" onItineraryUpdate - $type - ${itineraryData[type]!} ");
|
|
widget.onItineraryUpdate(type, itineraryData[type]!); // Notify parent
|
|
print("ItienreayDATE - $itineraryData");
|
|
}
|
|
|
|
// void handleItineraryUpdate(String type, Map<String, dynamic> newData) {
|
|
// setState(() {
|
|
// if (!itineraryData.containsKey(type)) {
|
|
// itineraryData[type] = []; // Initialize if null
|
|
// }
|
|
//
|
|
// // Assign an index based on the current list length
|
|
// int newIndex = itineraryData[type]!.length + 1;
|
|
// newData["indx"] = newIndex; // Add an ID field
|
|
//
|
|
// itineraryData[type]!.add(newData); // Append new object
|
|
// });
|
|
//
|
|
// widget.onItineraryUpdate(type, itineraryData[type]!); // Notify parent
|
|
// print("Updated $type List: ${itineraryData[type]}");
|
|
// }
|
|
|
|
switch (selectedListOption) {
|
|
case "Train":
|
|
selectedListWidget = TrainListWidget(
|
|
hasAction: widget.hasAction,
|
|
tripType: widget.tripType,
|
|
trainList: itineraryData["Train"]!,
|
|
onOpen: handleEdit,
|
|
onAddNew: handlecreateNewPlan,
|
|
isViewMode: widget.isViewMode,
|
|
apiData: widget.apiData,
|
|
onDeleteTrain: (data) => handleItinerarydelete("Train", data),
|
|
);
|
|
break;
|
|
case "Taxi":
|
|
selectedListWidget = TaxiListWidget(
|
|
taxiList: itineraryData["Taxi"]!,
|
|
onOpen: handleEdit,
|
|
onAddNew: handlecreateNewPlan,
|
|
isViewMode: widget.isViewMode,
|
|
apiData: widget.apiData,
|
|
onDeleteTaxi: (data) => handleItinerarydelete("Taxi", data),
|
|
);
|
|
break;
|
|
case "Bus":
|
|
selectedListWidget = BusListWidget(
|
|
busList: itineraryData["Bus"]!,
|
|
onOpen: handleEdit,
|
|
onAddNew: handlecreateNewPlan,
|
|
isViewMode: widget.isViewMode,
|
|
onDeleteBus: (data) => handleItinerarydelete("Bus", data),
|
|
);
|
|
break;
|
|
case "Insurance":
|
|
selectedListWidget = InsuranceListWidget(
|
|
insuranceList: itineraryData["Insurance"]!,
|
|
onOpen: handleEdit,
|
|
onAddNew: handlecreateNewPlan,
|
|
isViewMode: widget.isViewMode,
|
|
apiData: widget.apiData,
|
|
onDeleteInsurance: (data) => handleItinerarydelete("Insurance", data),
|
|
);
|
|
break;
|
|
case "Visa":
|
|
selectedListWidget = VisaListWidget(
|
|
visaList: itineraryData["Visa"]!,
|
|
apiData: widget.apiData,
|
|
apiCountryData: widget.apiCountryData,
|
|
onOpen: handleEdit,
|
|
onAddNew: handlecreateNewPlan,
|
|
isViewMode: widget.isViewMode,
|
|
onDeleteMiscellaneous: (data) => handleItinerarydelete("Visa", data),
|
|
);
|
|
break;
|
|
case "Forex":
|
|
selectedListWidget = ForexListWidget(
|
|
forexList: itineraryData["Forex"]!,
|
|
apiCountryData: widget.apiCountryData,
|
|
onOpen: handleEdit,
|
|
onAddNew: handlecreateNewPlan,
|
|
isViewMode: widget.isViewMode,
|
|
apiData: widget.apiData,
|
|
onDeleteForex: (data) => handleItinerarydelete("Forex", data),
|
|
);
|
|
break;
|
|
case "Accomodation":
|
|
selectedListWidget = AccomodationListWidget(
|
|
accommodationList: itineraryData["Accomodation"]!,
|
|
onOpen: handleEdit,
|
|
onAddNew: handlecreateNewPlan,
|
|
isViewMode: widget.isViewMode,
|
|
onDeleteAccommodation:
|
|
(data) => handleItinerarydelete("Accomodation", data),
|
|
);
|
|
break;
|
|
case "Miscellaneous":
|
|
selectedListWidget = MiscellaneousListWidget(
|
|
miscellaneousList: itineraryData["Miscellaneous"]!,
|
|
onOpen: handleEdit,
|
|
isViewMode: widget.isViewMode,
|
|
onAddNew: handlecreateNewPlan,
|
|
apiData: widget.apiData,
|
|
onDeleteMiscellaneous:
|
|
(data) => handleItinerarydelete("Miscellaneous", data),
|
|
);
|
|
break;
|
|
case "Flight":
|
|
default:
|
|
selectedListWidget = FlightListWidget(
|
|
hasAction: widget.hasAction,
|
|
tripType: widget.tripType,
|
|
flightList: itineraryData["Flight"]!,
|
|
onOpen: handleEdit,
|
|
onAddNew: handlecreateNewPlan,
|
|
isViewMode: widget.isViewMode,
|
|
apiData: widget.apiData,
|
|
onDeleteFlight: (data) => handleItinerarydelete("Flight", data),
|
|
);
|
|
break;
|
|
}
|
|
|
|
switch (selectedOption) {
|
|
case "Train":
|
|
selectedWidget = TrainScreen(
|
|
onClose: handleClose,
|
|
apiData: widget.apiData,
|
|
apiDataForClass: widget.apiDataForClass,
|
|
loginUser: widget.loginUser,
|
|
onSavetrain: (data) => handleItineraryUpdate("Train", data),
|
|
tripType: widget.tripType,
|
|
selectedItem: selectedItem,
|
|
);
|
|
break;
|
|
case "Taxi":
|
|
selectedWidget = TaxiScreen(
|
|
onClose: handleClose,
|
|
apiData: widget.apiData,
|
|
loginUser: widget.loginUser,
|
|
onSavetaxi: (data) => handleItineraryUpdate("Taxi", data),
|
|
selectedItem: selectedItem,
|
|
);
|
|
break;
|
|
case "Bus":
|
|
selectedWidget = BusScreen(
|
|
onClose: handleClose,
|
|
apiData: widget.apiData,
|
|
loginUser: widget.loginUser,
|
|
onSaveBus: (data) => handleItineraryUpdate("Bus", data),
|
|
selectedItem: selectedItem,
|
|
);
|
|
break;
|
|
case "Insurance":
|
|
selectedWidget = InsuranceScreen(
|
|
onClose: handleClose,
|
|
apiData: widget.apiData,
|
|
loginUser: widget.loginUser,
|
|
onSaveInsurance: (data) => handleItineraryUpdate("Insurance", data),
|
|
selectedItem: selectedItem,
|
|
flightData: itineraryData["Flight"]!,
|
|
);
|
|
break;
|
|
|
|
case "Visa":
|
|
selectedWidget = VisaScreen(
|
|
onClose: handleClose,
|
|
apiData: widget.apiData,
|
|
apiCountryData: widget.apiCountryData,
|
|
loginUser: widget.loginUser,
|
|
onSaveVisa: (data) => handleItineraryUpdate("Visa", data),
|
|
selectedItem: selectedItem,
|
|
flightData: itineraryData["Flight"]!,
|
|
);
|
|
break;
|
|
case "Miscellaneous":
|
|
selectedWidget = MiscellaneousScreen(
|
|
// onClose: handleClose,
|
|
onClose: handleClose,
|
|
apiData: widget.apiData,
|
|
loginUser: widget.loginUser,
|
|
onSaveMiscellaneous:
|
|
(data) => handleItineraryUpdate("Miscellaneous", data),
|
|
selectedItem: selectedItem,
|
|
selectedIndex: selectedIndex,
|
|
);
|
|
break;
|
|
case "Accomodation":
|
|
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":
|
|
selectedWidget = ForexScreen(
|
|
onClose: handleClose,
|
|
apiData: widget.apiData,
|
|
loginUser: widget.loginUser,
|
|
apiCountryData: widget.apiCountryData,
|
|
onSaveForex: (data) => handleItineraryUpdate("Forex", data),
|
|
selectedItem: selectedItem,
|
|
flightData: itineraryData["Flight"]!,
|
|
);
|
|
break;
|
|
case "Flight":
|
|
default:
|
|
selectedWidget = FlightScreen(
|
|
key: widget.flightScreenKey,
|
|
tripTypeNotifier: widget.tripTypeNotifier,
|
|
hasAction: widget.hasAction,
|
|
tripType: widget.tripType,
|
|
// onClose: handleMClose,
|
|
onClose: handleClose,
|
|
loginUser: widget.loginUser,
|
|
onSaveFlight: (data) => handleItineraryUpdate("Flight", data),
|
|
apiData: widget.apiData,
|
|
apiDataForClass: widget.apiDataForClass,
|
|
selectedItem: selectedItem,
|
|
flightData: itineraryData["Flight"]!,
|
|
);
|
|
break;
|
|
}
|
|
|
|
return ResponsiveBuilder(
|
|
builder: (context, sizingInfo) {
|
|
bool isMobile = sizingInfo.isMobile;
|
|
|
|
return Stack(
|
|
clipBehavior: Clip.none,
|
|
children: [
|
|
// Second container (yellow box)
|
|
Container(
|
|
margin: EdgeInsets.only(
|
|
top: 40,
|
|
), // Push it down to make room for the tab bar
|
|
padding: EdgeInsets.only(top: 12, bottom: 12, left: 3, right: 3),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white, // Card background
|
|
// color: Colors.yellow.shade50, // Card background
|
|
// color: Color(0xFFF9F9F9), // Slightly lighter than white
|
|
// border: Border.all(color: Color(0xFFE6E7F5), width: 1.3),
|
|
border: Border.all(color: Color(0xFFE6E7F5), width: 1.2),
|
|
borderRadius: BorderRadius.circular(8),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
// color: Color(0x0D000000), // 5% opacity black
|
|
color: Colors.black12, // 5% opacity black
|
|
blurRadius: 5,
|
|
offset: Offset(0, 0.2),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
SizedBox(height: 2),
|
|
isSelected ? selectedWidget : selectedListWidget,
|
|
],
|
|
),
|
|
),
|
|
|
|
// First container (tab bar) — positioned above
|
|
Positioned(
|
|
top: 0,
|
|
left: MediaQuery.of(context).size.width * 0.05,
|
|
right: MediaQuery.of(context).size.width * 0.05,
|
|
child: Container(
|
|
padding: EdgeInsets.symmetric(vertical: 2, horizontal: 2),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white, // Card background
|
|
// color: thridColor, // Card background
|
|
borderRadius: BorderRadius.circular(40),
|
|
|
|
// color: Color(0xFFE6E7F5)
|
|
// border: Border.all(color: Colors.black12, width: 1.3),
|
|
border: Border.all(color: Color(0xFFE6E7F5), width: 1.2),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black12,
|
|
// color: Color(0x0D000000), // 5% opacity black
|
|
blurRadius: 10,
|
|
offset: Offset(0, 0.2),
|
|
),
|
|
],
|
|
),
|
|
child: Row(
|
|
children: [
|
|
isMobile
|
|
? IconButton(
|
|
icon: Icon(
|
|
Icons.arrow_back_ios,
|
|
color: Colors.black54,
|
|
// color: _canScrollLeft ? Colors.black : Colors.grey,
|
|
),
|
|
onPressed:
|
|
_canScrollLeft
|
|
? () {
|
|
_scrollBy(-100);
|
|
}
|
|
: null,
|
|
)
|
|
: SizedBox.shrink(),
|
|
Expanded(
|
|
child:
|
|
isMobile
|
|
? SingleChildScrollView(
|
|
controller: _scrollController,
|
|
scrollDirection: Axis.horizontal,
|
|
child: Row(children: _buildOptions()),
|
|
)
|
|
: Row(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.spaceEvenly,
|
|
children: _buildOptions(),
|
|
),
|
|
),
|
|
isMobile
|
|
? IconButton(
|
|
icon: Icon(
|
|
Icons.arrow_forward_ios,
|
|
color: Colors.black54,
|
|
// color: _canScrollRight ? Colors.black : Colors.grey,
|
|
),
|
|
onPressed:
|
|
_canScrollRight
|
|
? () {
|
|
_scrollBy(100);
|
|
}
|
|
: null,
|
|
)
|
|
: SizedBox.shrink(),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
void _scrollBy(double offset) {
|
|
if (!_scrollController.hasClients) return;
|
|
|
|
final targetOffset = (_scrollController.offset + offset).clamp(
|
|
_scrollController.position.minScrollExtent,
|
|
_scrollController.position.maxScrollExtent,
|
|
);
|
|
|
|
_scrollController.animateTo(
|
|
targetOffset,
|
|
duration: Duration(milliseconds: 300),
|
|
curve: Curves.easeInOut,
|
|
);
|
|
}
|
|
|
|
bool hasValidItineraryEntries() {
|
|
if (ServicesChoosed == null || ServicesChoosed!.isEmpty) return false;
|
|
|
|
for (var service in ServicesChoosed!) {
|
|
final serviceName = service['name'];
|
|
final entries = itineraryData[serviceName];
|
|
|
|
// Check if there is at least one active entry (is_active == 1)
|
|
final hasActive =
|
|
entries?.any((entry) => entry['is_active'] == 1) ?? false;
|
|
|
|
if (!hasActive) {
|
|
return false; // Fail fast if any one service has no active entries
|
|
}
|
|
}
|
|
|
|
return true; // All selected services have at least one active entry
|
|
}
|
|
|
|
List<Widget> _buildOptions() {
|
|
if (ServicesChoosed == null && !hasValidItineraryEntries()) return [];
|
|
|
|
if (ServicesChoosed != null &&
|
|
ServicesChoosed!.isNotEmpty &&
|
|
selectedListOption == "") {
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
setState(() {
|
|
selectedListOption = ServicesChoosed!.first['name'];
|
|
isSelected = false;
|
|
});
|
|
});
|
|
}
|
|
|
|
// if (ServicesChoosed != null &&
|
|
// ServicesChoosed!.isNotEmpty &&
|
|
// selectedListOption == "") {
|
|
// selectedListOption = ServicesChoosed!.first['name'];
|
|
// isSelected = false;
|
|
// }
|
|
|
|
return ServicesChoosed!.map((service) {
|
|
final serviceName = service['name'];
|
|
final serviceEntries = itineraryData[serviceName];
|
|
|
|
final hasActive =
|
|
serviceEntries?.any((entry) => entry['is_active'] == "1") ?? false;
|
|
|
|
print("Service1: $serviceName");
|
|
print("Entries1: $serviceEntries");
|
|
print("Has Active1: $hasActive");
|
|
|
|
return Padding(
|
|
padding: const EdgeInsets.only(right: 20.0),
|
|
child: _buildOption(
|
|
service,
|
|
hasActive,
|
|
// itineraryData[service['name']]?.isNotEmpty ?? false,
|
|
),
|
|
);
|
|
}).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 = selectedActiveTab == name;
|
|
// bool isOptionSelected =
|
|
// hasData ? selectedListOption == name : selectedOption == name;
|
|
|
|
return GestureDetector(
|
|
onTap: () {
|
|
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(
|
|
// border: Border(
|
|
// bottom: BorderSide(
|
|
// color: isOptionSelected ? Color(0xFF114D8B) : Colors.transparent,
|
|
// width: 2,
|
|
// ),
|
|
// ),
|
|
),
|
|
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 3),
|
|
child: Column(
|
|
children: [
|
|
DottedBorder(
|
|
options: RoundedRectDottedBorderOptions(
|
|
dashPattern: [1, 3],
|
|
strokeWidth: 1.5,
|
|
radius: Radius.circular(46),
|
|
color: isOptionSelected ? secondColor! : Colors.transparent,
|
|
padding: EdgeInsets.all(3.5),
|
|
),
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
color: isOptionSelected ? secondColor : Colors.white,
|
|
|
|
borderRadius: BorderRadius.circular(20.0),
|
|
),
|
|
|
|
padding: const EdgeInsets.all(3.0),
|
|
child:
|
|
iconUrl.isNotEmpty
|
|
? Image.network(
|
|
iconUrl,
|
|
width: 15,
|
|
height: 15,
|
|
errorBuilder: (context, error, stackTrace) {
|
|
return Icon(
|
|
fallbackIcon,
|
|
size: 20,
|
|
color:
|
|
isOptionSelected
|
|
? Colors.white
|
|
: Colors.black87,
|
|
// color:
|
|
// isOptionSelected
|
|
// ? Color(0xFF114D8B)
|
|
// : Color(0xFF475569),
|
|
);
|
|
},
|
|
)
|
|
: Icon(
|
|
fallbackIcon,
|
|
size: 20,
|
|
color:
|
|
isOptionSelected ? Colors.white : Colors.black87,
|
|
// color:
|
|
// isOptionSelected
|
|
// ? Color(0xFF114D8B)
|
|
// : Color(0xFF475569),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 1),
|
|
Row(
|
|
children: [
|
|
Text(
|
|
name,
|
|
|
|
// style: GoogleFonts.poppins( fontSize: 12,
|
|
// fontWeight: FontWeight.w600,
|
|
// color: Color(0xFF575A74))
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 12,
|
|
color: Colors.black,
|
|
// color:
|
|
// isOptionSelected
|
|
// ? Color(0xFF114D8B)
|
|
// : Color(0xFF475569),
|
|
// fontFamily: "Inter",
|
|
fontWeight:
|
|
isOptionSelected ? FontWeight.w700 : FontWeight.w400,
|
|
),
|
|
),
|
|
SizedBox(width: 4),
|
|
if (hasData) Icon(Icons.circle, size: 8, color: Colors.green),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Widget _buildOption1(
|
|
// Map<String, dynamic> service,
|
|
// bool hasData,
|
|
// )
|
|
// {
|
|
// String name = service['name'];
|
|
// String iconUrl = service['icon']; // Can be empty string
|
|
// // Optional: define local icon fallback if iconUrl is empty
|
|
// IconData fallbackIcon = _getLocalIconForService(name);
|
|
// // final idMap = {"service_id": service['service_id'].toString()};
|
|
// // final isSelected = selectedServiceIds.contains(idMap);
|
|
//
|
|
// String serviceId = service['service_id'].toString();
|
|
// // bool isSelected = selectedServiceIds.contains(serviceId);
|
|
// // bool isSelected =
|
|
// // selectedServiceIds.any((item) => item["service_id"] == serviceId);
|
|
//
|
|
// return GestureDetector(
|
|
// onTap: () {
|
|
// setState(() {
|
|
// selectedListOption = name;
|
|
// isSelected = false;
|
|
// });
|
|
// },
|
|
// child: Row(children: [
|
|
// iconUrl.isNotEmpty
|
|
// ? Image.network(
|
|
// iconUrl,
|
|
// width: 18,
|
|
// height: 18,
|
|
// errorBuilder: (context, error, stackTrace) {
|
|
// return Icon(
|
|
// fallbackIcon,
|
|
// size: 18,
|
|
// color: selectedListOption == name
|
|
// ? Color(0xFF114D8B)
|
|
// : Color(0xFF475569),
|
|
// );
|
|
// },
|
|
// )
|
|
// : Icon(
|
|
// fallbackIcon,
|
|
// size: 18,
|
|
// color: selectedListOption == name
|
|
// ? Color(0xFF114D8B)
|
|
// : Color(0xFF475569),
|
|
// ),
|
|
//
|
|
// SizedBox(width: 2),
|
|
// Text(
|
|
// name,
|
|
// style: TextStyle(
|
|
// fontSize: 14,
|
|
// // color: selectedListOption == title ? Colors.blueAccent : Color(0xFF575A74),
|
|
// color: selectedListOption == name
|
|
// ? Color(0xFF114D8B)
|
|
// : Color(0xFF475569),
|
|
// fontFamily: "Archivo",
|
|
// fontWeight: selectedListOption == name
|
|
// ? FontWeight.bold
|
|
// : FontWeight.w500),
|
|
// // fontWeight: selectedListOption == title ? FontWeight.bold : FontWeight.normal,)),
|
|
// ),
|
|
//
|
|
// SizedBox(width: 2),
|
|
// // if (selectedListOption == title && widget.isViewMode == false)
|
|
// if (hasData)
|
|
// Icon(Icons.circle, size: 8, color: Colors.green
|
|
// // color: Colors.grey,
|
|
// )
|
|
// // Container(
|
|
// // height: 10,
|
|
// // width: 10,
|
|
// // // decoration: BoxDecoration(
|
|
// // // shape: BoxShape.circle,
|
|
// // // border: Border.all(color: Colors.green, width: 1.5),
|
|
// // // ),
|
|
// // child:),
|
|
// ]),
|
|
// );
|
|
// }
|
|
|
|
IconData _getLocalIconForService(String name) {
|
|
switch (name.toLowerCase()) {
|
|
case 'flight':
|
|
return Icons.flight_takeoff_outlined;
|
|
case 'train':
|
|
return Icons.train_outlined;
|
|
case 'bus':
|
|
return Icons.directions_bus_rounded;
|
|
case 'taxi':
|
|
return Icons.local_taxi_outlined;
|
|
case 'accomodation':
|
|
return Icons.local_hotel_outlined;
|
|
case 'forex':
|
|
return Icons.attach_money_outlined;
|
|
case 'insurance':
|
|
return Icons.list_alt_outlined;
|
|
case 'visa':
|
|
return Icons.badge_outlined;
|
|
case 'miscellaneous':
|
|
return Icons.card_giftcard_outlined;
|
|
default:
|
|
return Icons.circle_notifications;
|
|
}
|
|
}
|
|
|
|
//
|
|
// List<Widget> _buildOptions1() {
|
|
// return [
|
|
// _buildOption("Flight", itineraryData["Flight"]?.isNotEmpty ?? false),
|
|
// SizedBox(width: 20),
|
|
// _buildOption("Taxi", itineraryData["Taxi"]?.isNotEmpty ?? false),
|
|
// SizedBox(width: 20),
|
|
// _buildOption("Train", itineraryData["Train"]?.isNotEmpty ?? false),
|
|
// SizedBox(width: 20),
|
|
// _buildOption("Bus", itineraryData["Bus"]?.isNotEmpty ?? false),
|
|
// SizedBox(width: 20),
|
|
// _buildOption(
|
|
// "Accomodation", itineraryData["Accomodation"]?.isNotEmpty ?? false),
|
|
// SizedBox(width: 20),
|
|
// _buildOption("Forex", itineraryData["Forex"]?.isNotEmpty ?? false),
|
|
// SizedBox(width: 20),
|
|
// _buildOption(
|
|
// "Insurance", itineraryData["Insurance"]?.isNotEmpty ?? false),
|
|
// SizedBox(width: 20),
|
|
// _buildOption("Visa", itineraryData["Visa"]?.isNotEmpty ?? false),
|
|
// SizedBox(width: 20),
|
|
// _buildOption(
|
|
// "Miscellaneous", itineraryData["Miscellaneous"]?.isNotEmpty ?? false),
|
|
// ];
|
|
// }
|
|
//
|
|
//
|
|
|
|
// Widget _buildOption1(String title, bool hasData) {
|
|
// return GestureDetector(
|
|
// onTap: () {
|
|
// setState(() {
|
|
// selectedListOption = title;
|
|
// isSelected = false;
|
|
// });
|
|
// },
|
|
// child: Row(children: [
|
|
// if (hasData)
|
|
// Icon(
|
|
// Icons.circle_notifications,
|
|
// color: Colors.green,
|
|
// size: 10,
|
|
// ),
|
|
// SizedBox(width: 5),
|
|
// Text(title,
|
|
// style: TextStyle(
|
|
// fontSize: 13,
|
|
// color: selectedListOption == title
|
|
// ? Colors.blueAccent
|
|
// : Color(0xFF575A74),
|
|
// fontWeight: selectedListOption == title
|
|
// ? FontWeight.bold
|
|
// : FontWeight.normal,
|
|
// )),
|
|
// SizedBox(width: 5),
|
|
// SizedBox(width: 5),
|
|
// if (selectedListOption == title && widget.isViewMode == false)
|
|
// GestureDetector(
|
|
// onTap: () {
|
|
// setState(() {
|
|
// selectedOption = title;
|
|
// isSelected = true;
|
|
// selectedItem = null;
|
|
// });
|
|
// },
|
|
// child: Icon(
|
|
// Icons.add_circle,
|
|
// color: Colors.blueAccent,
|
|
// size: 18,
|
|
// ),
|
|
// ),
|
|
// ]),
|
|
// );
|
|
// }
|
|
}
|