ts-tat/lib/Screens/plans/dynamic_itinerary_stepper.dart
2025-04-02 15:47:15 +05:30

559 lines
19 KiB
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:responsive_builder/responsive_builder.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 Map<String, dynamic>? apiData;
final List<dynamic>? apiCountryData;
final String? loginUser;
final Function(String, List<Map<String, dynamic>>) onItineraryUpdate; // Updated Signature
final Map<String,dynamic> selectedPlanData;
final bool isViewMode ;
const DynamicItinerary({super.key, required this.apiData, required this.onItineraryUpdate,
required this.apiCountryData, required this.loginUser,required this.selectedPlanData, required this.isViewMode});
@override
_DynamicItineraryState createState() => _DynamicItineraryState();
}
class _DynamicItineraryState extends State<DynamicItinerary> {
String selectedOption = "";
String selectedListOption = "";
bool isSelected = false;
Map<String, dynamic>? selectedItem;
int? selectedIndex;
// List<Map<String, dynamic>> miscellaneousList = [];
Map<String, List<Map<String, dynamic>>> itineraryData = {
"Train": [],
"Bus": [],
"Taxi": [],
"Miscellaneous": [],
"Flight": [],
"Accomodation": [],
"Insurance": [],
"Visa": [],
"Forex": [],
};
// Store form values for each tab
final Map<String, Map<String, String>> formData = {
"Flight": {}, // Stores data for the Flight tab
"Train": {}, // Stores data for the Train tab
"Taxi": {}, // Stores data for the Car tab
"Bus": {}, // Stores data for the Bus tab
"Insurance": {}, // Stores data for the Bus tab
"Accomodation": {},// Stores data for the Accomodation tab
"Miscellaneous": {},
"Forex": {},
"Visa": {},
};
@override
void initState() {
super.initState();
handleSelectedPlan();
}
void 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) {
return true; // At least one list has data
}
}
return false; // No itinerary data available
}
void handleClose(bool value) {
setState(() {
selectedOption = "";
isSelected = value;
selectedIndex = null;
selectedItem = null;
});
}
void handleEdit(bool value,selectedItem, title) {
setState(() {
selectedOption = title;
isSelected = value;
this.selectedItem = selectedItem;
});
print(selectedItem);
}
Widget build(BuildContext context) {
Widget selectedWidget;
Widget selectedListWidget;
// void updateFormData(String tab, String key, String value) {
// setState(() {
// formData[tab]![key] = value; // Update the stored data
// });
// }
void updateFormData(String tab, String key, String value) {
setState(() {
if (!formData.containsKey(tab)) {
formData[tab] = {}; // Initialize if null
}
formData[tab]![key] = value; // Update the stored data
});
}
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
}
// 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( trainList : itineraryData["Train"]!,
onOpen: handleEdit,
onDeleteTrain: (data)=> handleItinerarydelete("Train", data),
);
break;
case "Taxi":
selectedListWidget = TaxiListWidget( taxiList : itineraryData["Taxi"]! ,
onOpen: handleEdit,
onDeleteTaxi: (data)=> handleItinerarydelete("Taxi", data),);
break;
case "Bus":
selectedListWidget = BusListWidget(busList : itineraryData["Bus"]!,
onOpen: handleEdit,
onDeleteBus: (data) => handleItinerarydelete("Bus", data),);
break;
case "Insurance":
selectedListWidget = InsuranceListWidget(insuranceList : itineraryData["Insurance"]!,
onOpen: handleEdit, apiData: widget.apiData,
onDeleteInsurance:(data) => handleItinerarydelete("Insurance", data),);
break;
case "Visa":
selectedListWidget = VisaListWidget(visaList : itineraryData["Visa"]!,
apiData: widget.apiData, apiCountryData : widget.apiCountryData,
onOpen: handleEdit,
onDeleteMiscellaneous: (data) => handleItinerarydelete("Visa", data),);
break;
case "Forex":
selectedListWidget = ForexListWidget(forexList: itineraryData["Forex"]!,
apiCountryData : widget.apiCountryData,
onOpen: handleEdit,
onDeleteForex: (data) => handleItinerarydelete("Forex", data),);
break;
case "Accomodation":
selectedListWidget = AccomodationListWidget(accommodationList: itineraryData["Accomodation"]!,
onOpen: handleEdit,
onDeleteAccommodation:(data) => handleItinerarydelete("Accomodation", data));
break;
case "Miscellaneous":
selectedListWidget = MiscellaneousListWidget(miscellaneousList: itineraryData["Miscellaneous"]!,
onOpen: handleEdit,apiData: widget.apiData,
onDeleteMiscellaneous: (data) => handleItinerarydelete("Miscellaneous", data),
);
break;
case "Flight":
default:
selectedListWidget = FlightListWidget(flightList : itineraryData["Flight"]!,
onOpen: handleEdit,
onDeleteFlight: (data) => handleItinerarydelete("Flight", data)
);
break;
}
switch (selectedOption) {
case "Train":
selectedWidget = TrainScreen(onClose: handleClose, apiData: widget.apiData, loginUser : widget.loginUser,
onSavetrain :(data) => handleItineraryUpdate("Train", data),
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);
break;
case "Visa":
selectedWidget = VisaScreen(onClose: handleClose,apiData: widget.apiData, apiCountryData : widget.apiCountryData, loginUser : widget.loginUser,
onSaveVisa: (data) => handleItineraryUpdate("Visa", data),
selectedItem: selectedItem,);
break;
case "Miscellaneous":
selectedWidget = MiscellaneousScreen(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,
onSaveAccomadation: (data)=>handleItineraryUpdate("Accomodation", data),
selectedItem: selectedItem, );
break;
case "Forex":
selectedWidget = ForexScreen( onClose: handleClose,apiData: widget.apiData, loginUser : widget.loginUser,
apiCountryData : widget.apiCountryData,
onSaveForex: (data)=>handleItineraryUpdate("Forex", data),
selectedItem: selectedItem);
break;
case "Flight":
default:
selectedWidget = FlightScreen(onClose: handleClose,loginUser : widget.loginUser,
onSaveFlight: (data)=>handleItineraryUpdate("Flight", data), apiData: widget.apiData,
selectedItem: selectedItem
);
break;
}
return ResponsiveBuilder(builder: (context, sizingInfo) {
bool isMobile = sizingInfo.isMobile;
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
return Column(
// mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Itinerary",
style: TextStyle(
fontSize: 18,
),),
],
),
SizedBox(height: 8),
Container(
decoration: BoxDecoration(
border: Border.all(color: Color(0xFFF4F4FB)),
borderRadius: BorderRadius.circular(1),
color: Color(0xFFF4F4FB),
),
padding: EdgeInsets.all(5),
child: isMobile ?
Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: _buildOptions(),
),
),
)
: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// mainAxisSize: MainAxisSize.min,
children: _buildOptions(),
),
),
Column(
// mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox(height: 2),
isSelected ? selectedWidget : selectedListWidget,
// TrainScreen()
],
),
],
);
});
}
List<Widget> _buildOptions() {
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),
];
}
// List<Widget> _buildOptions() {
// return [
// _buildOption("Flight", itineraryData["Flight"]?.isNotEmpty ?? false),
// _buildOption("Flight"),
// SizedBox(width: 20),
// _buildOption("Taxi"),
// SizedBox(width: 20),
// _buildOption("Train"),
// SizedBox(width: 20),
// _buildOption("Bus"),
// SizedBox(width: 20),
// _buildOption("Accomodation"),
// SizedBox(width: 20),
// _buildOption("Forex"),
// SizedBox(width: 20),
// _buildOption("Insurance"),
// SizedBox(width: 20),
// _buildOption("Visa"),
// SizedBox(width: 20),
// _buildOption("Miscellaneous"),
// ];
// }
Widget _buildOption(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,
),
),
]
),
);
}
}