Plan Creation
This commit is contained in:
parent
7b1e7cf624
commit
a82f4a271c
@ -21,6 +21,35 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
final TextEditingController _passwordController = TextEditingController();
|
final TextEditingController _passwordController = TextEditingController();
|
||||||
bool _obscureText = true;
|
bool _obscureText = true;
|
||||||
|
|
||||||
|
Future<void> storeUserDetails(String token) async{
|
||||||
|
try{
|
||||||
|
final parts = token.split('.');
|
||||||
|
if (parts.length != 3) throw Exception('Invalid token format');
|
||||||
|
|
||||||
|
final payload = json.decode(
|
||||||
|
utf8.decode(base64Url.decode(base64Url.normalize(parts[1])))
|
||||||
|
);
|
||||||
|
|
||||||
|
final userData = payload['data'];
|
||||||
|
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.setString('auth_token', token);
|
||||||
|
await prefs.setString('user_data', jsonEncode(userData)); // Store full user data
|
||||||
|
|
||||||
|
if(userData != null){
|
||||||
|
final pref = await SharedPreferences.getInstance();
|
||||||
|
await pref.setString('auth_token', token);
|
||||||
|
await pref.setString('user_data', jsonEncode(userData));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(e){
|
||||||
|
print('Error decoding token: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void _login(BuildContext context) async {
|
void _login(BuildContext context) async {
|
||||||
if (_formKey.currentState!.validate()) {
|
if (_formKey.currentState!.validate()) {
|
||||||
const String url = '$apiUrl/auth/login';
|
const String url = '$apiUrl/auth/login';
|
||||||
@ -40,12 +69,10 @@ class _LoginWidgetState extends State<LoginWidget> {
|
|||||||
print("data- $data");
|
print("data- $data");
|
||||||
|
|
||||||
final token = data['token']; // Assuming the token is in response
|
final token = data['token']; // Assuming the token is in response
|
||||||
final userId = data['user_id'].toString();
|
// final userId = data['user_id'].toString();
|
||||||
|
|
||||||
|
await storeUserDetails(token);
|
||||||
|
|
||||||
// Save token to SharedPreferences
|
|
||||||
final prefs = await SharedPreferences.getInstance();
|
|
||||||
await prefs.setString('auth_token', token);
|
|
||||||
await prefs.setString('userId', userId);
|
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(content: Text("Login Successful")),
|
const SnackBar(content: Text("Login Successful")),
|
||||||
|
|||||||
@ -6,14 +6,15 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||||||
|
|
||||||
|
|
||||||
import '../../config/apiUrl.dart';
|
import '../../config/apiUrl.dart';
|
||||||
|
import '../../data/models/Searchtraveller.dart';
|
||||||
import '../../data/models/searchUser.dart';
|
import '../../data/models/searchUser.dart';
|
||||||
import '../../widgets/custom_text_traveller.dart';
|
import '../../widgets/custom_text_traveller.dart';
|
||||||
|
|
||||||
class UserSelectionDialog extends StatefulWidget{
|
class UserSelectionDialog extends StatefulWidget{
|
||||||
final String title;
|
final String title;
|
||||||
final void Function(String) onSubmit;
|
final void Function(String,String, bool) onSubmit;
|
||||||
|
|
||||||
UserSelectionDialog({Key? key, required this.title, required this.onSubmit}) : super(key: key);
|
UserSelectionDialog({Key? key, required this.title, required this.onSubmit,}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_UserSelectionDialogState createState() => _UserSelectionDialogState();
|
_UserSelectionDialogState createState() => _UserSelectionDialogState();
|
||||||
@ -25,7 +26,13 @@ class _UserSelectionDialogState extends State<UserSelectionDialog>{
|
|||||||
// List<String> _filteredUsers = [];
|
// List<String> _filteredUsers = [];
|
||||||
// List<String> _users = [];
|
// List<String> _users = [];
|
||||||
List<SearchUser> _users = [];
|
List<SearchUser> _users = [];
|
||||||
|
List<SearchTraveler> _traveller = [];
|
||||||
List<SearchUser> _filteredUsers = [];
|
List<SearchUser> _filteredUsers = [];
|
||||||
|
List<Map<String, dynamic>> _filteredList = [];
|
||||||
|
List<SearchTraveler> _filteredTraveller = [];
|
||||||
|
String userIdSelected = " ";
|
||||||
|
bool isTraveller = false;
|
||||||
|
|
||||||
bool _showTravellerForm = false;
|
bool _showTravellerForm = false;
|
||||||
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
@ -93,7 +100,7 @@ class _UserSelectionDialogState extends State<UserSelectionDialog>{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _filterUsers(String query) {
|
void _filterUsers1(String query) {
|
||||||
print("Filtering users...");
|
print("Filtering users...");
|
||||||
setState(() {
|
setState(() {
|
||||||
if (query.isEmpty) {
|
if (query.isEmpty) {
|
||||||
@ -104,7 +111,6 @@ class _UserSelectionDialogState extends State<UserSelectionDialog>{
|
|||||||
"${user.firstName} ${user.lastName}".toLowerCase(),
|
"${user.firstName} ${user.lastName}".toLowerCase(),
|
||||||
user.email.toLowerCase() ?? "",
|
user.email.toLowerCase() ?? "",
|
||||||
user.userId.toLowerCase() ?? "",
|
user.userId.toLowerCase() ?? "",
|
||||||
user.travellerId ?? "",
|
|
||||||
user.mobileNo ?? "",
|
user.mobileNo ?? "",
|
||||||
user.alternateMobileNo ?? ""
|
user.alternateMobileNo ?? ""
|
||||||
];
|
];
|
||||||
@ -121,12 +127,136 @@ class _UserSelectionDialogState extends State<UserSelectionDialog>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _filterUsers(String query) {
|
||||||
|
print("Filtering _filterUsersTravellers...");
|
||||||
|
setState(() {
|
||||||
|
_filteredList.clear(); // Reset the list before filtering
|
||||||
|
|
||||||
|
if (query.isEmpty) {
|
||||||
|
_filteredList = [
|
||||||
|
..._users.map((user) => {"type": "user", "data": user}),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
_filteredList = [
|
||||||
|
..._users.where((user) {
|
||||||
|
List<String> searchFields = [
|
||||||
|
"${user.firstName} ${user.lastName}".toLowerCase(),
|
||||||
|
user.email.toLowerCase() ?? "",
|
||||||
|
user.userId.toLowerCase() ?? "",
|
||||||
|
user.mobileNo ?? "",
|
||||||
|
user.alternateMobileNo ?? ""
|
||||||
|
];
|
||||||
|
return searchFields.any((field) => field.contains(query.toLowerCase()));
|
||||||
|
}).map((user) => {"type": "user", "data": user}),
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
print("Filtered List:");
|
||||||
|
for (var item in _filteredList) {
|
||||||
|
var user = item["data"];
|
||||||
|
print("${item["type"].toUpperCase()} - ${user.firstName} ${user.lastName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _filterUsersTravellers(String query) {
|
||||||
|
print("Filtering _filterUsersTravellers...");
|
||||||
|
setState(() {
|
||||||
|
_filteredList.clear(); // Reset the list before filtering
|
||||||
|
|
||||||
|
if (query.isEmpty) {
|
||||||
|
_filteredList = [
|
||||||
|
..._users.map((user) => {"type": "user", "data": user}),
|
||||||
|
..._traveller.map((traveller) => {"type": "traveller", "data": traveller}),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
_filteredList = [
|
||||||
|
..._users.where((user) {
|
||||||
|
List<String> searchFields = [
|
||||||
|
"${user.firstName} ${user.lastName}".toLowerCase(),
|
||||||
|
user.email.toLowerCase() ?? "",
|
||||||
|
user.userId.toLowerCase() ?? "",
|
||||||
|
user.mobileNo ?? "",
|
||||||
|
user.alternateMobileNo ?? ""
|
||||||
|
];
|
||||||
|
return searchFields.any((field) => field.contains(query.toLowerCase()));
|
||||||
|
}).map((user) => {"type": "user", "data": user}),
|
||||||
|
|
||||||
|
..._traveller.where((traveller) {
|
||||||
|
List<String> searchFields = [
|
||||||
|
"${traveller.firstName} ${traveller.lastName}".toLowerCase(),
|
||||||
|
traveller.email.toLowerCase() ?? "",
|
||||||
|
traveller.travellerId.toLowerCase() ?? "",
|
||||||
|
traveller.mobileNo ?? "",
|
||||||
|
];
|
||||||
|
return searchFields.any((field) => field.contains(query.toLowerCase()));
|
||||||
|
}).map((traveller) => {"type": "traveller", "data": traveller}),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
print("Filtered List:");
|
||||||
|
for (var item in _filteredList) {
|
||||||
|
var user = item["data"];
|
||||||
|
print("${item["type"].toUpperCase()} - ${user.firstName} ${user.lastName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Future<void> fetchTraveller() async {
|
||||||
|
final String apiUrldata = '$apiUrl/api/travellers';
|
||||||
|
|
||||||
|
try {
|
||||||
|
final token = await getToken();
|
||||||
|
if (token == null) {
|
||||||
|
throw Exception('Token not found. Please log in.');
|
||||||
|
}
|
||||||
|
|
||||||
|
final response = await http.get(
|
||||||
|
Uri.parse(apiUrldata),
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer $token',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final Map<String,dynamic> responseBody = json.decode(response.body);
|
||||||
|
|
||||||
|
|
||||||
|
print("API Response: $responseBody"); // Debugging
|
||||||
|
|
||||||
|
if (responseBody.containsKey('data') && responseBody['data'] is List) {
|
||||||
|
List<dynamic> travellerList = responseBody['data'];
|
||||||
|
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_traveller = travellerList.map((user) => SearchTraveler.fromJson(user)).toList();
|
||||||
|
_filteredTraveller = List.from(_traveller);
|
||||||
|
});
|
||||||
|
|
||||||
|
print("Users fetched: ${_users.length}");
|
||||||
|
for (var travvelr in _traveller) {
|
||||||
|
print("${travvelr.firstName} ${travvelr.lastName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw Exception("Unexpected response format: Expected a List but got ${responseBody.runtimeType}");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw Exception('Failed to load users. Status Code: ${response.statusCode}');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print("Error fetching traveller: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
fetchUsers();
|
fetchUsers();
|
||||||
|
fetchTraveller();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -150,7 +280,9 @@ class _UserSelectionDialogState extends State<UserSelectionDialog>{
|
|||||||
setState(() {
|
setState(() {
|
||||||
_showTravellerForm = false;
|
_showTravellerForm = false;
|
||||||
});
|
});
|
||||||
|
widget.title == "Others"? _filterUsersTravellers(query):
|
||||||
_filterUsers(query);
|
_filterUsers(query);
|
||||||
|
|
||||||
},
|
},
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Search for a user",
|
hintText: "Search for a user",
|
||||||
@ -189,7 +321,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog>{
|
|||||||
_searchController.text.isNotEmpty
|
_searchController.text.isNotEmpty
|
||||||
? SizedBox(
|
? SizedBox(
|
||||||
height: 300, // Limit height to avoid overflow
|
height: 300, // Limit height to avoid overflow
|
||||||
child: _filteredUsers.isEmpty
|
// child: _filteredUsers.isEmpty
|
||||||
|
child: _filteredList.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"No users found",
|
"No users found",
|
||||||
@ -197,18 +330,27 @@ class _UserSelectionDialogState extends State<UserSelectionDialog>{
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
itemCount: _filteredUsers.length,
|
// itemCount: _filteredUsers.length,
|
||||||
|
itemCount: _filteredList.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final user = _filteredUsers[index];
|
// final user = _filteredUsers[index];
|
||||||
|
|
||||||
|
final item = _filteredList[index];
|
||||||
|
final user = item["data"]; // Extract user object
|
||||||
|
final userType = item["type"]; // "user" or "traveller"
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text("${user.firstName ?? "Unknown"} ${user.lastName ?? ""}"),
|
title: Text("${user.firstName ?? "Unknown"} ${user.lastName ?? ""}"),
|
||||||
subtitle: Text("ID: ${user.userId}"),
|
subtitle: Text("ID: ${userType == "user" ? user.userId : user.travellerId}"),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
String selectedUser = "${user.firstName ?? "Unknown"} ${user.lastName ?? ""}";
|
String selectedUser = "${user.firstName ?? "Unknown"} ${user.lastName ?? ""}";
|
||||||
setState(() {
|
setState(() {
|
||||||
_searchController.text = selectedUser;
|
_searchController.text = selectedUser;
|
||||||
|
userIdSelected = userType == "user" ? user.userId : user.travellerId;
|
||||||
|
isTraveller = userType == "traveller";
|
||||||
});
|
});
|
||||||
print("Selected: $selectedUser, ID: ${user.userId}");
|
print("Selected: $selectedUser, ID: ${userType == "user" ? user.userId : user.travellerId},"
|
||||||
|
" isTraveller: $userIdSelected");
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -224,6 +366,9 @@ class _UserSelectionDialogState extends State<UserSelectionDialog>{
|
|||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: TravelerForm(
|
child: TravelerForm(
|
||||||
formKey: _formKey,
|
formKey: _formKey,
|
||||||
|
onSubmit: (String fullName, String travellerId, bool isTraveller) {
|
||||||
|
widget.onSubmit(fullName, travellerId,isTraveller); // Pass the data up
|
||||||
|
},
|
||||||
firstNameController: TextEditingController(),
|
firstNameController: TextEditingController(),
|
||||||
lastNameController: TextEditingController(),
|
lastNameController: TextEditingController(),
|
||||||
emailController: TextEditingController(),
|
emailController: TextEditingController(),
|
||||||
@ -261,7 +406,8 @@ class _UserSelectionDialogState extends State<UserSelectionDialog>{
|
|||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
widget.onSubmit(_searchController.text);
|
print("Submitting: ${_searchController.text}, ID: $userIdSelected");
|
||||||
|
widget.onSubmit(_searchController.text,userIdSelected,isTraveller);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
child: Text("Submit"),
|
child: Text("Submit"),
|
||||||
@ -282,6 +428,7 @@ class TravelerForm extends StatefulWidget {
|
|||||||
final TextEditingController emailController;
|
final TextEditingController emailController;
|
||||||
final TextEditingController mobileController;
|
final TextEditingController mobileController;
|
||||||
final GlobalKey<FormState> formKey;
|
final GlobalKey<FormState> formKey;
|
||||||
|
final void Function(String, String, bool) onSubmit;
|
||||||
|
|
||||||
TravelerForm({
|
TravelerForm({
|
||||||
required this.formKey,
|
required this.formKey,
|
||||||
@ -289,6 +436,7 @@ class TravelerForm extends StatefulWidget {
|
|||||||
required this.lastNameController,
|
required this.lastNameController,
|
||||||
required this.emailController,
|
required this.emailController,
|
||||||
required this.mobileController,
|
required this.mobileController,
|
||||||
|
required this.onSubmit
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -371,8 +519,26 @@ class _TravelerFormState extends State<TravelerForm> {
|
|||||||
|
|
||||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||||
|
|
||||||
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||||
|
final Map<String, dynamic> responseData = jsonDecode(response.body); // Parse response
|
||||||
|
if (responseData["success"] == true && responseData.containsKey("data")) {
|
||||||
|
final travellerData = responseData["data"];
|
||||||
|
|
||||||
|
String travellerId = travellerData["traveller_id"];
|
||||||
|
String firstName = travellerData["first_name"];
|
||||||
|
String lastName = travellerData["last_name"];
|
||||||
|
|
||||||
|
print("Traveller Added: ID: $travellerId, Name: $firstName $lastName");
|
||||||
|
|
||||||
|
// Pass data to callback
|
||||||
|
widget.onSubmit("$firstName $lastName", travellerId, true);
|
||||||
|
|
||||||
|
|
||||||
|
// Close the dialog
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Navigator.pop(context);
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(
|
content: Text(
|
||||||
|
|||||||
@ -6,12 +6,13 @@ import '../../widgets/custom_text_field.dart';
|
|||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
|
|
||||||
class AccomodationScreen extends StatefulWidget {
|
class AccomodationScreen extends StatefulWidget {
|
||||||
final Map<String, String> formData;
|
|
||||||
final Function(String tab, String key, String value) updateFormData;
|
|
||||||
final Function(bool) onClose; // Callback function
|
|
||||||
|
|
||||||
AccomodationScreen({required this.formData, required this.updateFormData,
|
final Function(bool) onClose; // Callback function
|
||||||
required this.onClose,});
|
final Function(Map<String,dynamic>) onSaveAccomadation;
|
||||||
|
final Map<String, dynamic>? selectedItem;
|
||||||
|
|
||||||
|
AccomodationScreen({
|
||||||
|
required this.onClose, required this.onSaveAccomadation, required this.selectedItem});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_AccomodationScreenState createState() => _AccomodationScreenState();
|
_AccomodationScreenState createState() => _AccomodationScreenState();
|
||||||
@ -28,7 +29,6 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
final FocusNode _checkOutTimeFocusNode = FocusNode();
|
final FocusNode _checkOutTimeFocusNode = FocusNode();
|
||||||
final FocusNode _commentsFocusNode = FocusNode();
|
final FocusNode _commentsFocusNode = FocusNode();
|
||||||
|
|
||||||
late Map<String, TextEditingController> _controllers;
|
|
||||||
|
|
||||||
late TextEditingController _destinationController = TextEditingController();
|
late TextEditingController _destinationController = TextEditingController();
|
||||||
late TextEditingController _hotelNameController = TextEditingController();
|
late TextEditingController _hotelNameController = TextEditingController();
|
||||||
@ -46,105 +46,65 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
bool _checkOutTimeFocus = false;
|
bool _checkOutTimeFocus = false;
|
||||||
bool _commentsFocus = false;
|
bool _commentsFocus = false;
|
||||||
|
|
||||||
|
void _addFocusListener(FocusNode node, Function(bool) onFocusChange) {
|
||||||
|
node.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
onFocusChange(node.hasFocus);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Map<String, dynamic> get accomadationData {
|
||||||
|
|
||||||
|
Map<String,dynamic> data ={
|
||||||
|
"destination_city": _destinationController.text,
|
||||||
|
"hotel_name": _hotelNameController.text,
|
||||||
|
"checkin_date": _checkInController.text ,
|
||||||
|
"checkin_time": _checkInTimeController.text,
|
||||||
|
"checkout_date": _checkOutController.text,
|
||||||
|
"checkout_time": _checkOutTimeController.text,
|
||||||
|
"comments": _commentsController.text,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (widget.selectedItem != null) {
|
||||||
|
if (widget.selectedItem?["indx"] != null && widget.selectedItem?["indx"] != 0) {
|
||||||
|
data["indx"] = widget.selectedItem!["indx"];
|
||||||
|
} else if (widget.selectedItem?["accomodation_id"] != null && widget.selectedItem?["accomodation_id"] != 0) {
|
||||||
|
data["accomodation_id"] = widget.selectedItem!["accomodation_id"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextEditingController initController(String key) {
|
||||||
|
return TextEditingController(text: widget.selectedItem?[key] ?? "");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_destinationFocusNode.addListener(() {
|
_addFocusListener(_destinationFocusNode, (focus) => _destinationFocused = focus);
|
||||||
setState(() {
|
_addFocusListener(_hotelNameFocusNode, (focus) => _isHotelNameFocused = focus);
|
||||||
_destinationFocused = _destinationFocusNode.hasFocus;
|
_addFocusListener(_checkInFocusNode, (focus) => _checkInFocus = focus);
|
||||||
});
|
_addFocusListener(_checkInTimeFocusNode, (focus) => _checkInTimeFocus = focus);
|
||||||
|
_addFocusListener(_checkOutFocusNode, (focus) => _checkOutFocus = focus);
|
||||||
_hotelNameFocusNode.addListener(() {
|
_addFocusListener(_checkOutTimeFocusNode, (focus) => _checkOutTimeFocus = focus);
|
||||||
setState(() {
|
_addFocusListener(_commentsFocusNode, (focus) => _commentsFocus = focus);
|
||||||
_isHotelNameFocused = _hotelNameFocusNode.hasFocus;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
_checkInFocusNode.addListener(() {
|
|
||||||
setState(() {
|
|
||||||
_checkInFocus = _checkInFocusNode.hasFocus;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
_checkInTimeFocusNode.addListener(() {
|
|
||||||
setState(() {
|
|
||||||
_checkInTimeFocus = _checkInTimeFocusNode.hasFocus;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
_checkOutFocusNode.addListener(() {
|
|
||||||
setState(() {
|
|
||||||
_checkInFocus = _checkInFocusNode.hasFocus;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
_checkOutTimeFocusNode.addListener(() {
|
|
||||||
setState(() {
|
|
||||||
_checkInTimeFocus = _checkOutTimeFocusNode.hasFocus;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
_commentsFocusNode.addListener(() {
|
|
||||||
setState(() {
|
|
||||||
_commentsFocus = _commentsFocusNode.hasFocus;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
List<String> fields = [
|
|
||||||
"_destination",
|
|
||||||
"_hotelName",
|
|
||||||
"_Check_In",
|
|
||||||
"_Check_In_Time",
|
|
||||||
"_Check_Out",
|
|
||||||
"_Check_Out_Time",
|
|
||||||
"_comments"
|
|
||||||
];
|
|
||||||
|
|
||||||
|
_destinationController = initController("destination_city");
|
||||||
|
_hotelNameController = initController("hotel_name");
|
||||||
|
_checkInController = initController("checkin_date");
|
||||||
|
_checkInTimeController = initController("checkin_time");
|
||||||
|
_checkOutController = initController("checkout_date");
|
||||||
|
_checkOutTimeController = initController("checkout_time");
|
||||||
|
_commentsController = initController("comments");
|
||||||
|
|
||||||
_destinationController =
|
|
||||||
TextEditingController(text: widget.formData["destination"] ?? "");
|
|
||||||
_hotelNameController =
|
|
||||||
TextEditingController(text: widget.formData["_hotelName"] ?? "");
|
|
||||||
_checkInController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_In"] ?? "");
|
|
||||||
_checkInTimeController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_In_Time"] ?? "");
|
|
||||||
_checkOutController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_Out"] ?? "");
|
|
||||||
_checkOutTimeController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_Out_Time"] ?? "");
|
|
||||||
_commentsController =
|
|
||||||
TextEditingController(text: widget.formData["_comments"] ?? "");
|
|
||||||
|
|
||||||
// Save data when user types
|
|
||||||
_destinationController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Accommodation", "destination", _destinationController.text);
|
|
||||||
}); // Save data when user types
|
|
||||||
_hotelNameController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Accommodation", "_hotelName", _hotelNameController.text);
|
|
||||||
});
|
|
||||||
_checkInController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Accommodation", "_Check_In", _checkInController.text);
|
|
||||||
});
|
|
||||||
_checkInTimeController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Accommodation", "_Check_In_Time", _checkInTimeController.text);
|
|
||||||
});
|
|
||||||
_checkOutController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Accommodation", "_Check_Out", _checkOutController.text);
|
|
||||||
});
|
|
||||||
_checkOutTimeController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Accommodation", "_Check_Out_Time", _checkOutTimeController.text);
|
|
||||||
});
|
|
||||||
_commentsController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Accommodation", "_comments", _commentsController.text);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -160,6 +120,19 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleSave(){
|
||||||
|
|
||||||
|
print( "Handle Save accomadtion $accomadationData");
|
||||||
|
widget.onSaveAccomadation(accomadationData); // Send object to parent
|
||||||
|
widget.onClose(false);// Close screen after saving
|
||||||
|
// Clear only if this is a new entry
|
||||||
|
// if (widget.selectedItem == null) {
|
||||||
|
// _commentsController.clear();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
||||||
@ -642,7 +615,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop(); // Close the dialog or screen
|
widget.onClose(false); // Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
@ -661,7 +634,7 @@ class _AccomodationScreenState extends State<AccomodationScreen> {
|
|||||||
// Save Changes Button
|
// Save Changes Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// TODO: Implement save logic
|
handleSave();
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.blue, // Primary color for save
|
backgroundColor: Colors.blue, // Primary color for save
|
||||||
|
|||||||
@ -6,13 +6,14 @@ import '../../widgets/custom_text_field.dart';
|
|||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
|
|
||||||
class BusScreen extends StatefulWidget {
|
class BusScreen extends StatefulWidget {
|
||||||
final Map<String, String> formData;
|
|
||||||
final Map<String, dynamic>? apiData;
|
|
||||||
final Function(String tab, String key, String value) updateFormData;
|
|
||||||
final Function(bool) onClose;
|
|
||||||
|
|
||||||
BusScreen({required this.formData, required this.updateFormData,
|
final Map<String, dynamic>? apiData;
|
||||||
required this.onClose, this.apiData});
|
final Function(bool) onClose;
|
||||||
|
final Function(Map<String, dynamic>)onSaveBus;
|
||||||
|
final Map<String, dynamic>? selectedItem;
|
||||||
|
|
||||||
|
BusScreen({
|
||||||
|
required this.onClose, this.apiData, required this.onSaveBus, required this.selectedItem});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_BusScreenState createState() => _BusScreenState();
|
_BusScreenState createState() => _BusScreenState();
|
||||||
@ -39,7 +40,7 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
late TextEditingController _toController = TextEditingController();
|
late TextEditingController _toController = TextEditingController();
|
||||||
late TextEditingController _dateController = TextEditingController();
|
late TextEditingController _dateController = TextEditingController();
|
||||||
late TextEditingController _timeController = TextEditingController();
|
late TextEditingController _timeController = TextEditingController();
|
||||||
late TextEditingController _commentsController = TextEditingController();
|
late TextEditingController _buscommentsController = TextEditingController();
|
||||||
|
|
||||||
bool _tripTypeFocused = false;
|
bool _tripTypeFocused = false;
|
||||||
bool _isHotelNameFocused = false;
|
bool _isHotelNameFocused = false;
|
||||||
@ -49,6 +50,33 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
bool _timeFocus = false;
|
bool _timeFocus = false;
|
||||||
bool _commentsFocus = false;
|
bool _commentsFocus = false;
|
||||||
|
|
||||||
|
|
||||||
|
Map<String, dynamic> get busData{
|
||||||
|
Map<String,dynamic> data = {
|
||||||
|
"from": _fromController.text,
|
||||||
|
"to": _toController.text,
|
||||||
|
"date": _dateController.text,
|
||||||
|
"time": _timeController.text,
|
||||||
|
"comments": _buscommentsController.text,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (widget.selectedItem != null) {
|
||||||
|
if (widget.selectedItem?["indx"] != null && widget.selectedItem?["indx"] != 0) {
|
||||||
|
data["indx"] = widget.selectedItem!["indx"];
|
||||||
|
} else if (widget.selectedItem?["bus_id"] != null && widget.selectedItem?["bus_id"] != 0) {
|
||||||
|
data["bus_id"] = widget.selectedItem!["bus_id"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextEditingController initController(String key) {
|
||||||
|
return TextEditingController(text: widget.selectedItem?[key] ?? "");
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -57,6 +85,7 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_tripTypeFocused = _tripTypeFocusNode.hasFocus;
|
_tripTypeFocused = _tripTypeFocusNode.hasFocus;
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
_hotelNameFocusNode.addListener(() {
|
_hotelNameFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -91,54 +120,15 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
_commentsFocus = _commentsFocusNode.hasFocus;
|
_commentsFocus = _commentsFocusNode.hasFocus;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_tripTypeController =
|
_buscommentsController = initController("comments");
|
||||||
TextEditingController(text: widget.formData["tripType"] ?? "");
|
_fromController = initController("from");
|
||||||
_hotelNameController =
|
_toController = initController("to");
|
||||||
TextEditingController(text: widget.formData["_hotelName"] ?? "");
|
_dateController = initController("date");
|
||||||
_fromController =
|
_timeController = initController("time");
|
||||||
TextEditingController(text: widget.formData["_from"] ?? "");
|
|
||||||
_toController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_In_Time"] ?? "");
|
|
||||||
_dateController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_Out"] ?? "");
|
|
||||||
_timeController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_Out_Time"] ?? "");
|
|
||||||
_commentsController =
|
|
||||||
TextEditingController(text: widget.formData["_comments"] ?? "");
|
|
||||||
|
|
||||||
// Save data when user types
|
|
||||||
_tripTypeController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Bus", "_tripType", _tripTypeController.text);
|
|
||||||
}); // Save data when user types
|
|
||||||
_hotelNameController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Bus", "_hotelName", _hotelNameController.text);
|
|
||||||
});
|
|
||||||
_fromController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Bus", "_from", _fromController.text);
|
|
||||||
});
|
|
||||||
_toController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Bus", "_Check_In_Time", _toController.text);
|
|
||||||
});
|
|
||||||
_dateController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Bus", "_Check_Out", _dateController.text);
|
|
||||||
});
|
|
||||||
_timeController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Bus", "_Check_Out_Time", _timeController.text);
|
|
||||||
});
|
|
||||||
_commentsController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Bus", "_comments", _commentsController.text);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -150,12 +140,23 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
_toController.dispose();
|
_toController.dispose();
|
||||||
_dateController.dispose();
|
_dateController.dispose();
|
||||||
_timeController.dispose();
|
_timeController.dispose();
|
||||||
_commentsController.dispose();
|
_buscommentsController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void handleSave(){
|
||||||
|
|
||||||
|
print( "Handle Save miscellaneousData $busData");
|
||||||
|
widget.onSaveBus(busData); // Send object to parent
|
||||||
|
widget.onClose(false);// Close screen after saving
|
||||||
|
// Clear only if this is a new entry
|
||||||
|
// if (widget.selectedItem == null) {
|
||||||
|
// _commentsController.clear();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
||||||
@ -277,7 +278,7 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
.map((item)=>DropdownMenuItem<String>(
|
||||||
value: item['dropdown_value'],
|
value: item['dropdown_key'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
)).toList();
|
)).toList();
|
||||||
|
|
||||||
@ -318,7 +319,6 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
print("Updating form data: Flight -> trip_type -> ${newValue ?? ""}");
|
print("Updating form data: Flight -> trip_type -> ${newValue ?? ""}");
|
||||||
|
|
||||||
|
|
||||||
widget.updateFormData("Flight", "trip_type", newValue ?? "");
|
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
|
|
||||||
@ -654,7 +654,7 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
: MediaQuery.of(context).size.width * 0.66,
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _commentsFocusNode,
|
focusNode: _commentsFocusNode,
|
||||||
controller: _commentsController,
|
controller: _buscommentsController,
|
||||||
maxLines: 6,
|
maxLines: 6,
|
||||||
keyboardType: TextInputType.multiline,
|
keyboardType: TextInputType.multiline,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
@ -677,7 +677,7 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop(); // Close the dialog or screen
|
widget.onClose(false);// Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
@ -696,7 +696,7 @@ class _BusScreenState extends State<BusScreen> {
|
|||||||
// Save Changes Button
|
// Save Changes Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// TODO: Implement save logic
|
handleSave();
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.blue, // Primary color for save
|
backgroundColor: Colors.blue, // Primary color for save
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -6,13 +6,15 @@ import '../../widgets/custom_text_field.dart';
|
|||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
|
|
||||||
class InsuranceScreen extends StatefulWidget {
|
class InsuranceScreen extends StatefulWidget {
|
||||||
final Map<String, String> formData;
|
|
||||||
final Map<String, dynamic>? apiData;
|
|
||||||
final Function(String tab, String key, String value) updateFormData;
|
|
||||||
final Function(bool) onClose;
|
|
||||||
|
|
||||||
InsuranceScreen({required this.formData, required this.updateFormData,
|
final Map<String, dynamic>? apiData;
|
||||||
required this.onClose, required this.apiData});
|
final Function(bool) onClose;
|
||||||
|
final Function(Map<String, dynamic>) onSaveInsurance;
|
||||||
|
final Map<String,dynamic>? selectedItem;
|
||||||
|
|
||||||
|
|
||||||
|
InsuranceScreen({
|
||||||
|
required this.onClose, required this.apiData, required this.onSaveInsurance, required this.selectedItem});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_InsuranceScreenState createState() => _InsuranceScreenState();
|
_InsuranceScreenState createState() => _InsuranceScreenState();
|
||||||
@ -26,17 +28,14 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
final FocusNode _tripTypeFocusNode = FocusNode();
|
final FocusNode _tripTypeFocusNode = FocusNode();
|
||||||
final FocusNode _hotelNameFocusNode = FocusNode();
|
final FocusNode _hotelNameFocusNode = FocusNode();
|
||||||
final FocusNode _fromFocusNode = FocusNode();
|
final FocusNode _fromFocusNode = FocusNode();
|
||||||
final FocusNode _toFocusNode = FocusNode();
|
|
||||||
final FocusNode _dateFocusNode = FocusNode();
|
final FocusNode _dateFocusNode = FocusNode();
|
||||||
final FocusNode _timeFocusNode = FocusNode();
|
|
||||||
final FocusNode _commentsFocusNode = FocusNode();
|
final FocusNode _commentsFocusNode = FocusNode();
|
||||||
|
|
||||||
late Map<String, TextEditingController> _controllers;
|
|
||||||
|
|
||||||
late TextEditingController _tripTypeController = TextEditingController();
|
late TextEditingController _tripTypeController = TextEditingController();
|
||||||
late TextEditingController _startdateController = TextEditingController();
|
late TextEditingController _startdateController = TextEditingController();
|
||||||
late TextEditingController _endDateController = TextEditingController();
|
late TextEditingController _endDateController = TextEditingController();
|
||||||
late TextEditingController _commentsController = TextEditingController();
|
late TextEditingController _insuranceCommentsController = TextEditingController();
|
||||||
|
|
||||||
bool _isHotelNameFocused = false;
|
bool _isHotelNameFocused = false;
|
||||||
bool _dateFocus = false;
|
bool _dateFocus = false;
|
||||||
@ -44,62 +43,53 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
|
|
||||||
|
|
||||||
String? selectedTripType;
|
String? selectedTripType;
|
||||||
|
String? selectedInsuranceType;
|
||||||
|
|
||||||
|
Map<String, dynamic> get InsuranceData{
|
||||||
|
Map<String, dynamic> data = {
|
||||||
|
|
||||||
|
"type_of_insurance": selectedInsuranceType,
|
||||||
|
"start_date": _startdateController.text,
|
||||||
|
"end_date": _endDateController.text,
|
||||||
|
"comments": _insuranceCommentsController.text,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (widget.selectedItem != null) {
|
||||||
|
if (widget.selectedItem?["indx"] != null && widget.selectedItem?["indx"] != 0) {
|
||||||
|
data["indx"] = widget.selectedItem!["indx"];
|
||||||
|
} else if (widget.selectedItem?["insurance_id"] != null && widget.selectedItem?["insurance_id"] != 0) {
|
||||||
|
data["insurance_id"] = widget.selectedItem!["insurance_id"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
// _tripTypeFocusNode.addListener(() {
|
|
||||||
// setState(() {
|
|
||||||
// _tripTypeFocused = _tripTypeFocusNode.hasFocus;
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
_hotelNameFocusNode.addListener(() {
|
_hotelNameFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {_isHotelNameFocused = _hotelNameFocusNode.hasFocus;});});
|
||||||
_isHotelNameFocused = _hotelNameFocusNode.hasFocus;
|
_dateFocusNode.addListener(() {
|
||||||
});
|
setState(() {_dateFocus = _fromFocusNode.hasFocus;});});
|
||||||
});
|
|
||||||
|
|
||||||
_dateFocusNode.addListener(() {
|
|
||||||
setState(() {
|
|
||||||
_dateFocus = _fromFocusNode.hasFocus;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
_commentsFocusNode.addListener(() {
|
_commentsFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {_commentsFocus = _commentsFocusNode.hasFocus;});});
|
||||||
_commentsFocus = _commentsFocusNode.hasFocus;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
_insuranceCommentsController =
|
||||||
|
TextEditingController(text: widget.selectedItem?["comments"] ?? "");
|
||||||
_tripTypeController =
|
|
||||||
TextEditingController(text: widget.formData["tripType"] ?? "");
|
|
||||||
_startdateController =
|
_startdateController =
|
||||||
TextEditingController(text: widget.formData["_Check_Out"] ?? "");
|
TextEditingController(text: widget.selectedItem?["start_date"] ?? "");
|
||||||
_commentsController =
|
_endDateController =
|
||||||
TextEditingController(text: widget.formData["_comments"] ?? "");
|
TextEditingController(text: widget.selectedItem?['end_date'] ?? "");
|
||||||
|
|
||||||
// Save data when user types
|
// Set the selected value if available
|
||||||
_tripTypeController.addListener(() {
|
if (widget.selectedItem != null && widget.selectedItem!["type_of_insurance"] != null) {
|
||||||
widget.updateFormData(
|
selectedInsuranceType = widget.selectedItem!["type_of_insurance"].toString();
|
||||||
"Insurance", "_tripType", _tripTypeController.text);
|
}
|
||||||
}); // Save data when user types
|
|
||||||
|
|
||||||
_startdateController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Insurance", "_Check_Out", _startdateController.text);
|
|
||||||
});
|
|
||||||
|
|
||||||
_commentsController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Insurance", "_comments", _commentsController.text);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -111,12 +101,25 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void handleSave(){
|
||||||
|
|
||||||
|
print( "Handle Save InsuranceData $InsuranceData");
|
||||||
|
widget.onSaveInsurance(InsuranceData); // Send object to parent
|
||||||
|
widget.onClose(false);// Close screen after saving
|
||||||
|
// // Clear only if this is a new entry
|
||||||
|
// if (widget.selectedItem == null) {
|
||||||
|
// _commentsController.clear();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_tripTypeFocusNode.dispose();
|
_tripTypeFocusNode.dispose();
|
||||||
_tripTypeController.dispose();
|
_tripTypeController.dispose();
|
||||||
_startdateController.dispose();
|
_startdateController.dispose();
|
||||||
_commentsController.dispose();
|
_insuranceCommentsController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +247,7 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
.map((item)=>DropdownMenuItem<String>(
|
||||||
value: item['dropdown_value'],
|
value: item['dropdown_key'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
)).toList();
|
)).toList();
|
||||||
|
|
||||||
@ -258,7 +261,7 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default selected value
|
// Default selected value
|
||||||
String? selectedPurpose = dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
selectedInsuranceType ??= dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||||
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -270,7 +273,7 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
|
|
||||||
child: DropdownButtonFormField<String>(
|
child: DropdownButtonFormField<String>(
|
||||||
focusNode: _tripTypeFocusNode, // Assign the correct focus node
|
focusNode: _tripTypeFocusNode, // Assign the correct focus node
|
||||||
value: selectedPurpose,
|
value: selectedInsuranceType,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
@ -280,10 +283,10 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
onChanged: purposeList.isNotEmpty
|
onChanged: purposeList.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedPurpose = newValue;
|
selectedInsuranceType = newValue;
|
||||||
});
|
});
|
||||||
|
|
||||||
print(selectedPurpose);
|
print(selectedInsuranceType);
|
||||||
|
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
@ -298,85 +301,6 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<Widget> _builClassType(bool isDesktop){
|
|
||||||
|
|
||||||
List<dynamic> purposeList = widget.apiData?['flight_class'] ?? [];
|
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
|
||||||
value: item['dropdown_value'],
|
|
||||||
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
|
|
||||||
String? selectedPurpose = dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
|
||||||
|
|
||||||
return [
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Class *",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Color(0xFF575A74)),
|
|
||||||
),
|
|
||||||
SizedBox(height: 5),
|
|
||||||
CustomTextFieldWrapper(
|
|
||||||
isFocused: _isHotelNameFocused,
|
|
||||||
isDesktop: isDesktop,
|
|
||||||
child: SizedBox(
|
|
||||||
height: 40,
|
|
||||||
|
|
||||||
child: DropdownButtonFormField<String>(
|
|
||||||
focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
|
||||||
// controller: _hotelNameController,
|
|
||||||
value: selectedPurpose,
|
|
||||||
style: TextStyle(fontSize: 12),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: InputBorder.none,
|
|
||||||
contentPadding: EdgeInsets.symmetric(
|
|
||||||
horizontal: 10), // Proper padding
|
|
||||||
),
|
|
||||||
onChanged: purposeList.isNotEmpty
|
|
||||||
? (newValue) {
|
|
||||||
setState(() {
|
|
||||||
selectedPurpose = newValue;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
items: dropdownItems,
|
|
||||||
),
|
|
||||||
|
|
||||||
// child: TextField(
|
|
||||||
// focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
|
||||||
// controller: _hotelNameController,
|
|
||||||
// style: TextStyle(fontSize: 12),
|
|
||||||
// decoration: InputDecoration(
|
|
||||||
// labelText: "Select Class",
|
|
||||||
// labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
|
||||||
// floatingLabelBehavior: FloatingLabelBehavior.never,
|
|
||||||
// border: InputBorder.none,
|
|
||||||
// contentPadding: EdgeInsets.symmetric(vertical: 16),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
List<Widget> _buildSecondRow(bool isDesktop) {
|
List<Widget> _buildSecondRow(bool isDesktop) {
|
||||||
|
|
||||||
@ -554,7 +478,7 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
: MediaQuery.of(context).size.width * 0.66,
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _commentsFocusNode,
|
focusNode: _commentsFocusNode,
|
||||||
controller: _commentsController,
|
controller: _insuranceCommentsController,
|
||||||
maxLines: 6,
|
maxLines: 6,
|
||||||
keyboardType: TextInputType.multiline,
|
keyboardType: TextInputType.multiline,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
@ -577,7 +501,7 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop(); // Close the dialog or screen
|
widget.onClose(false); // Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
@ -596,7 +520,7 @@ class _InsuranceScreenState extends State<InsuranceScreen> {
|
|||||||
// Save Changes Button
|
// Save Changes Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// TODO: Implement save logic
|
handleSave();
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.blue, // Primary color for save
|
backgroundColor: Colors.blue, // Primary color for save
|
||||||
|
|||||||
@ -6,13 +6,16 @@ import '../../widgets/custom_text_field.dart';
|
|||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
|
|
||||||
class MiscellaneousScreen extends StatefulWidget {
|
class MiscellaneousScreen extends StatefulWidget {
|
||||||
final Map<String, String> formData;
|
|
||||||
final Map<String, dynamic>? apiData;
|
|
||||||
final Function(String tab, String key, String value) updateFormData;
|
|
||||||
final Function(bool) onClose;
|
|
||||||
|
|
||||||
MiscellaneousScreen({required this.formData, required this.updateFormData,
|
final Map<String, dynamic>? apiData;
|
||||||
required this.onClose, required this.apiData});
|
final Function(bool) onClose;
|
||||||
|
final Function(Map<String, dynamic>) onSaveMiscellaneous;
|
||||||
|
final Map<String, dynamic>? selectedItem;
|
||||||
|
final int? selectedIndex;
|
||||||
|
|
||||||
|
MiscellaneousScreen({
|
||||||
|
required this.onClose, required this.apiData, required this.onSaveMiscellaneous,
|
||||||
|
this.selectedItem, this.selectedIndex,});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MiscellaneousScreenState createState() => _MiscellaneousScreenState();
|
_MiscellaneousScreenState createState() => _MiscellaneousScreenState();
|
||||||
@ -25,36 +28,46 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
|
|
||||||
final FocusNode _tripTypeFocusNode = FocusNode();
|
final FocusNode _tripTypeFocusNode = FocusNode();
|
||||||
final FocusNode _hotelNameFocusNode = FocusNode();
|
final FocusNode _hotelNameFocusNode = FocusNode();
|
||||||
final FocusNode _fromFocusNode = FocusNode();
|
|
||||||
final FocusNode _toFocusNode = FocusNode();
|
|
||||||
final FocusNode _dateFocusNode = FocusNode();
|
|
||||||
final FocusNode _timeFocusNode = FocusNode();
|
|
||||||
final FocusNode _commentsFocusNode = FocusNode();
|
final FocusNode _commentsFocusNode = FocusNode();
|
||||||
|
|
||||||
late Map<String, TextEditingController> _controllers;
|
late Map<String, TextEditingController> _controllers;
|
||||||
|
|
||||||
late TextEditingController _tripTypeController = TextEditingController();
|
late TextEditingController _tripTypeController = TextEditingController();
|
||||||
late TextEditingController _startdateController = TextEditingController();
|
|
||||||
late TextEditingController _endDateController = TextEditingController();
|
|
||||||
late TextEditingController _commentsController = TextEditingController();
|
late TextEditingController _commentsController = TextEditingController();
|
||||||
|
|
||||||
bool _isHotelNameFocused = false;
|
bool _isHotelNameFocused = false;
|
||||||
bool _dateFocus = false;
|
|
||||||
bool _commentsFocus = false;
|
bool _commentsFocus = false;
|
||||||
|
|
||||||
|
|
||||||
String? selectedTripType;
|
String? selectedSpecialType;
|
||||||
|
|
||||||
|
Map<String, dynamic> get miscellaneousData {
|
||||||
|
Map<String, dynamic> data = {
|
||||||
|
"special_request": selectedSpecialType,
|
||||||
|
"comments": _commentsController.text,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (widget.selectedItem != null) {
|
||||||
|
if (widget.selectedItem?["indx"] != null && widget.selectedItem?["indx"] != 0) {
|
||||||
|
data["indx"] = widget.selectedItem!["indx"];
|
||||||
|
} else if (widget.selectedItem?["miscellaneous_id"] != null && widget.selectedItem?["miscellaneous_id"] != 0) {
|
||||||
|
data["miscellaneous_id"] = widget.selectedItem!["miscellaneous_id"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
if (widget.selectedItem == null) {
|
||||||
// _tripTypeFocusNode.addListener(() {
|
_commentsController.clear();
|
||||||
// setState(() {
|
}
|
||||||
// _tripTypeFocused = _tripTypeFocusNode.hasFocus;
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
_hotelNameFocusNode.addListener(() {
|
_hotelNameFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -62,13 +75,6 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
_dateFocusNode.addListener(() {
|
|
||||||
setState(() {
|
|
||||||
_dateFocus = _fromFocusNode.hasFocus;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
_commentsFocusNode.addListener(() {
|
_commentsFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_commentsFocus = _commentsFocusNode.hasFocus;
|
_commentsFocus = _commentsFocusNode.hasFocus;
|
||||||
@ -77,50 +83,37 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_tripTypeController =
|
|
||||||
TextEditingController(text: widget.formData["tripType"] ?? "");
|
|
||||||
_startdateController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_Out"] ?? "");
|
|
||||||
_commentsController =
|
_commentsController =
|
||||||
TextEditingController(text: widget.formData["_comments"] ?? "");
|
TextEditingController(text: widget.selectedItem?["comments"] ?? "");
|
||||||
|
|
||||||
// Save data when user types
|
// Set the selected value if available
|
||||||
_tripTypeController.addListener(() {
|
if (widget.selectedItem != null && widget.selectedItem!["special_request"] != null) {
|
||||||
widget.updateFormData(
|
selectedSpecialType = widget.selectedItem!["special_request"].toString();
|
||||||
"Miscellaneous", "_tripType", _tripTypeController.text);
|
}
|
||||||
}); // Save data when user types
|
|
||||||
|
|
||||||
_startdateController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Miscellaneous", "_Check_Out", _startdateController.text);
|
|
||||||
});
|
|
||||||
|
|
||||||
_commentsController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Miscellaneous", "_comments", _commentsController.text);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
|
||||||
node.addListener(() {
|
|
||||||
setState(() {
|
|
||||||
updateState(node.hasFocus);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_tripTypeFocusNode.dispose();
|
_tripTypeFocusNode.dispose();
|
||||||
_tripTypeController.dispose();
|
_tripTypeController.dispose();
|
||||||
_startdateController.dispose();
|
|
||||||
_commentsController.dispose();
|
_commentsController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleSave(){
|
||||||
|
|
||||||
|
print( "Handle Save miscellaneousData $miscellaneousData");
|
||||||
|
widget.onSaveMiscellaneous(miscellaneousData); // Send object to parent
|
||||||
|
widget.onClose(false);// Close screen after saving
|
||||||
|
// Clear only if this is a new entry
|
||||||
|
if (widget.selectedItem == null) {
|
||||||
|
_commentsController.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -140,6 +133,7 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
_commentsController.clear();
|
||||||
widget.onClose(false);
|
widget.onClose(false);
|
||||||
},
|
},
|
||||||
child: Icon(
|
child: Icon(
|
||||||
@ -177,18 +171,11 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<List<Widget>> rowBuilders = [
|
|
||||||
// _builClassType(isDesktop),
|
|
||||||
_buildSecondRow(isDesktop)
|
|
||||||
];
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
||||||
...buildResponsiveRow(_buildFirstRow(isDesktop)),
|
...buildResponsiveRow(_buildFirstRow(isDesktop)),
|
||||||
|
|
||||||
// // Iterate over rowBuilders and wrap each in a responsive container
|
|
||||||
// ...rowBuilders.expand((row) => buildResponsiveRow(row)),
|
|
||||||
|
|
||||||
...buildResponsiveRow(_buildThirdRow(isDesktop)),
|
...buildResponsiveRow(_buildThirdRow(isDesktop)),
|
||||||
|
|
||||||
// Actions row remains a Row
|
// Actions row remains a Row
|
||||||
@ -244,7 +231,7 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
.map((item)=>DropdownMenuItem<String>(
|
||||||
value: item['dropdown_value'],
|
value: item['dropdown_key'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
)).toList();
|
)).toList();
|
||||||
|
|
||||||
@ -258,7 +245,7 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default selected value
|
// Default selected value
|
||||||
String? selectedSpecialType = dropdownItems.isNotEmpty ? dropdownItems.first.value : "No options";
|
selectedSpecialType ??= dropdownItems.isNotEmpty ? dropdownItems.first.value : "No options";
|
||||||
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -287,7 +274,6 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
|
|
||||||
items: dropdownItems,
|
items: dropdownItems,
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -298,240 +284,6 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<Widget> _builClassType(bool isDesktop){
|
|
||||||
|
|
||||||
List<dynamic> purposeList = widget.apiData?['flight_class'] ?? [];
|
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
|
||||||
value: item['dropdown_value'],
|
|
||||||
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
|
|
||||||
String? selectedSpecialType = dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
|
||||||
|
|
||||||
return [
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Class *",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Color(0xFF575A74)),
|
|
||||||
),
|
|
||||||
SizedBox(height: 5),
|
|
||||||
CustomTextFieldWrapper(
|
|
||||||
isFocused: _isHotelNameFocused,
|
|
||||||
isDesktop: isDesktop,
|
|
||||||
child: SizedBox(
|
|
||||||
height: 40,
|
|
||||||
|
|
||||||
child: DropdownButtonFormField<String>(
|
|
||||||
focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
|
||||||
// controller: _hotelNameController,
|
|
||||||
value: selectedSpecialType,
|
|
||||||
style: TextStyle(fontSize: 12),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: InputBorder.none,
|
|
||||||
contentPadding: EdgeInsets.symmetric(
|
|
||||||
horizontal: 10), // Proper padding
|
|
||||||
),
|
|
||||||
onChanged: purposeList.isNotEmpty
|
|
||||||
? (newValue) {
|
|
||||||
setState(() {
|
|
||||||
selectedSpecialType = newValue;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
items: dropdownItems,
|
|
||||||
),
|
|
||||||
|
|
||||||
// child: TextField(
|
|
||||||
// focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
|
||||||
// controller: _hotelNameController,
|
|
||||||
// style: TextStyle(fontSize: 12),
|
|
||||||
// decoration: InputDecoration(
|
|
||||||
// labelText: "Select Class",
|
|
||||||
// labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
|
||||||
// floatingLabelBehavior: FloatingLabelBehavior.never,
|
|
||||||
// border: InputBorder.none,
|
|
||||||
// contentPadding: EdgeInsets.symmetric(vertical: 16),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
List<Widget> _buildSecondRow(bool isDesktop) {
|
|
||||||
|
|
||||||
|
|
||||||
DateTime? _selectedCheckOutDate;
|
|
||||||
TimeOfDay? _selectedCheckOutTime;
|
|
||||||
|
|
||||||
Future<void> _selectCheckOutDate(BuildContext context) async {
|
|
||||||
DateTime now = DateTime.now();
|
|
||||||
DateTime today = DateTime(now.year, now.month, now.day);
|
|
||||||
|
|
||||||
DateTime? pickedDate = await showDatePicker(
|
|
||||||
context: context,
|
|
||||||
|
|
||||||
|
|
||||||
initialDate: _selectedCheckOutDate != null && _selectedCheckOutDate!.isAfter(today)
|
|
||||||
? _selectedCheckOutDate!
|
|
||||||
: today,
|
|
||||||
firstDate: today,
|
|
||||||
lastDate: DateTime(2100),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
|
||||||
setState(() {
|
|
||||||
_selectedCheckOutDate = pickedDate;
|
|
||||||
_startdateController.text = DateFormat('yyyy-MM-dd').format(pickedDate);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Future<void> _selectEndCheckOutDate(BuildContext context) async {
|
|
||||||
DateTime now = DateTime.now();
|
|
||||||
DateTime today = DateTime(now.year, now.month, now.day);
|
|
||||||
|
|
||||||
DateTime? pickedDate = await showDatePicker(
|
|
||||||
context: context,
|
|
||||||
|
|
||||||
|
|
||||||
initialDate: _selectedCheckOutDate != null && _selectedCheckOutDate!.isAfter(today)
|
|
||||||
? _selectedCheckOutDate!
|
|
||||||
: today,
|
|
||||||
firstDate: today,
|
|
||||||
lastDate: DateTime(2100),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
|
|
||||||
setState(() {
|
|
||||||
_selectedCheckOutDate = pickedDate;
|
|
||||||
_endDateController.text = DateFormat('yyyy-MM-dd').format(pickedDate);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Start Date",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Color(0xFF575A74)),
|
|
||||||
),
|
|
||||||
SizedBox(height: 5),
|
|
||||||
CustomTextFieldWrapper(
|
|
||||||
isFocused: _dateFocus,
|
|
||||||
isDesktop: isDesktop,
|
|
||||||
child: SizedBox(
|
|
||||||
height: 40,
|
|
||||||
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: () => _selectCheckOutDate(context),
|
|
||||||
child: AbsorbPointer(
|
|
||||||
child: TextField(
|
|
||||||
focusNode: _dateFocusNode,
|
|
||||||
controller: _startdateController,
|
|
||||||
style: const TextStyle(fontSize: 12),
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: "Select Date",
|
|
||||||
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
|
||||||
border: InputBorder.none,
|
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
|
||||||
suffixIcon: Icon(Icons.calendar_today,
|
|
||||||
size: 16, color: Colors.grey),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (isDesktop)
|
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"End Date",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Color(0xFF575A74)),
|
|
||||||
),
|
|
||||||
SizedBox(height: 5),
|
|
||||||
CustomTextFieldWrapper(
|
|
||||||
isFocused: _dateFocus,
|
|
||||||
isDesktop: isDesktop,
|
|
||||||
child: SizedBox(
|
|
||||||
height: 40,
|
|
||||||
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: () => _selectEndCheckOutDate(context),
|
|
||||||
child: AbsorbPointer(
|
|
||||||
child: TextField(
|
|
||||||
focusNode: _dateFocusNode,
|
|
||||||
controller: _endDateController,
|
|
||||||
style: const TextStyle(fontSize: 12),
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: "Select Date",
|
|
||||||
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
|
||||||
border: InputBorder.none,
|
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
|
||||||
suffixIcon: Icon(Icons.calendar_today,
|
|
||||||
size: 16, color: Colors.grey),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (isDesktop)
|
|
||||||
Spacer()
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Widget> _buildThirdRow(bool isDesktop) {
|
List<Widget> _buildThirdRow(bool isDesktop) {
|
||||||
return [
|
return [
|
||||||
@ -577,7 +329,9 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop(); // Close the dialog or screen
|
|
||||||
|
_commentsController.clear();
|
||||||
|
widget.onClose(false);// Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
@ -596,7 +350,7 @@ class _MiscellaneousScreenState extends State<MiscellaneousScreen> {
|
|||||||
// Save Changes Button
|
// Save Changes Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// TODO: Implement save logic
|
handleSave();
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.blue, // Primary color for save
|
backgroundColor: Colors.blue, // Primary color for save
|
||||||
|
|||||||
@ -6,13 +6,13 @@ import '../../widgets/custom_text_field.dart';
|
|||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
|
|
||||||
class TaxiScreen extends StatefulWidget {
|
class TaxiScreen extends StatefulWidget {
|
||||||
final Map<String, String> formData;
|
|
||||||
final Map<String, dynamic>? apiData;
|
final Map<String, dynamic>? apiData;
|
||||||
final Function(String tab, String key, String value) updateFormData;
|
|
||||||
final Function(bool) onClose;
|
final Function(bool) onClose;
|
||||||
|
final Function(Map<String,dynamic>) onSavetaxi;
|
||||||
|
final Map<String,dynamic>? selectedItem;
|
||||||
|
|
||||||
TaxiScreen({required this.formData, required this.updateFormData,
|
TaxiScreen({
|
||||||
required this.onClose, this.apiData});
|
required this.onClose, this.apiData, required this.onSavetaxi, required this.selectedItem});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_TaxiScreenState createState() => _TaxiScreenState();
|
_TaxiScreenState createState() => _TaxiScreenState();
|
||||||
@ -23,86 +23,101 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
|
|
||||||
Map<String, String?> selectedValues = {};
|
Map<String, String?> selectedValues = {};
|
||||||
|
|
||||||
final FocusNode _tripTypeFocusNode = FocusNode();
|
final FocusNode _destinationFocusNode = FocusNode();
|
||||||
final FocusNode _hotelNameFocusNode = FocusNode();
|
final FocusNode _locationFocusNode = FocusNode();
|
||||||
final FocusNode _fromFocusNode = FocusNode();
|
final FocusNode _taxiReqFocusNode = FocusNode();
|
||||||
final FocusNode _toFocusNode = FocusNode();
|
final FocusNode _toFocusNode = FocusNode();
|
||||||
final FocusNode _dateFocusNode = FocusNode();
|
final FocusNode _dateFocusNode = FocusNode();
|
||||||
final FocusNode _timeFocusNode = FocusNode();
|
final FocusNode _timeFocusNode = FocusNode();
|
||||||
|
final FocusNode _numPassengerFocusNode = FocusNode();
|
||||||
final FocusNode _commentsFocusNode = FocusNode();
|
final FocusNode _commentsFocusNode = FocusNode();
|
||||||
|
|
||||||
late Map<String, TextEditingController> _controllers;
|
late TextEditingController _destinationController = TextEditingController();
|
||||||
|
late TextEditingController _locationController = TextEditingController();
|
||||||
late TextEditingController _tripTypeController = TextEditingController();
|
|
||||||
late TextEditingController _hotelNameController = TextEditingController();
|
|
||||||
late TextEditingController _fromController = TextEditingController();
|
|
||||||
late TextEditingController _toController = TextEditingController();
|
|
||||||
late TextEditingController _dateController = TextEditingController();
|
late TextEditingController _dateController = TextEditingController();
|
||||||
late TextEditingController _timeController = TextEditingController();
|
late TextEditingController _timeController = TextEditingController();
|
||||||
late TextEditingController _commentsController = TextEditingController();
|
late TextEditingController _numPassengerController = TextEditingController();
|
||||||
|
late TextEditingController _taxiCommentsController = TextEditingController();
|
||||||
|
|
||||||
bool _tripTypeFocused = false;
|
bool _destinationFocus = false;
|
||||||
bool _isHotelNameFocused = false;
|
bool _locationFocus = false;
|
||||||
bool _fromFocus = false;
|
|
||||||
bool _toFocus = false;
|
bool _toFocus = false;
|
||||||
bool _dateFocus = false;
|
bool _dateFocus = false;
|
||||||
|
bool _taxiReqFocused = false;
|
||||||
|
bool _numPassengerFocus = false;
|
||||||
bool _timeFocus = false;
|
bool _timeFocus = false;
|
||||||
bool _commentsFocus = false;
|
bool _commentsFocus = false;
|
||||||
|
|
||||||
|
String? selectedReqTaxi;
|
||||||
|
String? selectedCarType;
|
||||||
|
|
||||||
|
|
||||||
|
Map<String , dynamic> get taxiData {
|
||||||
|
Map<String, dynamic> data ={
|
||||||
|
|
||||||
|
|
||||||
|
"destination_city": _destinationController.text,
|
||||||
|
"date": _dateController.text,
|
||||||
|
"time": _timeController.text,
|
||||||
|
"location_of_pickup": _locationController.text,
|
||||||
|
"car_required_for": selectedReqTaxi,
|
||||||
|
"no_of_passengers": _numPassengerController.text,
|
||||||
|
"car_type": selectedCarType,
|
||||||
|
"comments": _taxiCommentsController.text,
|
||||||
|
// "updated_on": ,
|
||||||
|
// "updated_by": ,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
if (widget.selectedItem != null) {
|
||||||
|
if (widget.selectedItem?["indx"] != null && widget.selectedItem?["indx"] != 0) {
|
||||||
|
data["indx"] = widget.selectedItem!["indx"];
|
||||||
|
} else if (widget.selectedItem?["taxi_id"] != null && widget.selectedItem?["taxi_id"] != 0) {
|
||||||
|
data["taxi_id"] = widget.selectedItem!["taxi_id"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextEditingController initController(String key) {
|
||||||
|
return TextEditingController(text: widget.selectedItem?[key] ?? "");
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
|
||||||
_addFocusListener(_tripTypeFocusNode, (focus) => _tripTypeFocused = focus);
|
_addFocusListener(_destinationFocusNode, (focus) => _destinationFocus = focus);
|
||||||
_addFocusListener(_hotelNameFocusNode, (focus) => _isHotelNameFocused = focus);
|
_addFocusListener(_locationFocusNode, (focus) => _locationFocus = focus);
|
||||||
_addFocusListener(_fromFocusNode, (focus) => _fromFocus = focus);
|
|
||||||
_addFocusListener(_toFocusNode, (focus) => _toFocus = focus);
|
|
||||||
_addFocusListener(_dateFocusNode, (focus) => _dateFocus = focus);
|
_addFocusListener(_dateFocusNode, (focus) => _dateFocus = focus);
|
||||||
_addFocusListener(_timeFocusNode, (focus) => _timeFocus = focus);
|
_addFocusListener(_timeFocusNode, (focus) => _timeFocus = focus);
|
||||||
|
_addFocusListener(_taxiReqFocusNode, (focus) => _taxiReqFocused = focus);
|
||||||
|
_addFocusListener(_numPassengerFocusNode, (focus) => _numPassengerFocus = focus);
|
||||||
_addFocusListener(_commentsFocusNode, (focus) => _commentsFocus = focus);
|
_addFocusListener(_commentsFocusNode, (focus) => _commentsFocus = focus);
|
||||||
|
|
||||||
// _commentsFocusNode.addListener(() {
|
|
||||||
// setState(() {
|
|
||||||
// _commentsFocus = _commentsFocusNode.hasFocus;
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
|
||||||
|
_destinationController = initController("destination_city");
|
||||||
|
_dateController = initController("date");
|
||||||
|
_timeController = initController("time");
|
||||||
|
_locationController = initController("location_of_pickup");
|
||||||
|
_numPassengerController = initController("no_of_passengers");
|
||||||
|
_taxiCommentsController = initController("comments");
|
||||||
|
|
||||||
_tripTypeController =
|
|
||||||
TextEditingController(text: widget.formData["tripType"] ?? "");
|
|
||||||
_hotelNameController =
|
|
||||||
TextEditingController(text: widget.formData["_hotelName"] ?? "");
|
|
||||||
_fromController =
|
|
||||||
TextEditingController(text: widget.formData["_from"] ?? "");
|
|
||||||
_toController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_In_Time"] ?? "");
|
|
||||||
_dateController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_Out"] ?? "");
|
|
||||||
_timeController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_Out_Time"] ?? "");
|
|
||||||
_commentsController =
|
|
||||||
TextEditingController(text: widget.formData["_comments"] ?? "");
|
|
||||||
|
|
||||||
// Save data when user types
|
// Set the selected value if available
|
||||||
List<TextEditingController> controllers = [
|
if (widget.selectedItem != null && widget.selectedItem!["car_required_for"] != null) {
|
||||||
_tripTypeController, _hotelNameController, _fromController, _toController, _dateController,
|
selectedReqTaxi = widget.selectedItem!["car_required_for"].toString();
|
||||||
_timeController, _commentsController
|
|
||||||
];
|
|
||||||
|
|
||||||
List<String> keys = [
|
|
||||||
"_tripType", "_hotelName", "_from", "_Check_In_Time", "_Check_Out",
|
|
||||||
"_Check_Out_Time", "_comments"
|
|
||||||
];
|
|
||||||
|
|
||||||
for (int i = 0; i < controllers.length; i++) {
|
|
||||||
controllers[i].addListener(() {
|
|
||||||
widget.updateFormData("Flight", keys[i], controllers[i].text);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the selected value if available
|
||||||
|
if (widget.selectedItem != null && widget.selectedItem!["car_type"] != null) {
|
||||||
|
selectedCarType = widget.selectedItem!["car_type"].toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
@ -113,21 +128,33 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_tripTypeFocusNode.dispose();
|
_destinationFocusNode.dispose();
|
||||||
_tripTypeController.dispose();
|
_locationFocusNode.dispose();
|
||||||
_hotelNameController.dispose();
|
_destinationController.dispose();
|
||||||
_fromController.dispose();
|
|
||||||
_toController.dispose();
|
|
||||||
_dateController.dispose();
|
_dateController.dispose();
|
||||||
_timeController.dispose();
|
_timeController.dispose();
|
||||||
_commentsController.dispose();
|
_taxiCommentsController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void handleSave(){
|
||||||
|
|
||||||
|
print( "Handle Save taxiData $taxiData");
|
||||||
|
widget.onSavetaxi(taxiData); // Send object to parent
|
||||||
|
widget.onClose(false);// Close screen after saving
|
||||||
|
// Clear only if this is a new entry
|
||||||
|
// if (widget.selectedItem == null) {
|
||||||
|
// _commentsController.clear();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
||||||
@ -213,7 +240,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
.map((item)=>DropdownMenuItem<String>(
|
||||||
value: item['dropdown_value'],
|
value: item['dropdown_key'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
)).toList();
|
)).toList();
|
||||||
|
|
||||||
@ -227,7 +254,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default selected value
|
// Default selected value
|
||||||
String? selectedPurpose = dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
selectedCarType ??= dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||||
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -271,16 +298,16 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _fromFocus,
|
isFocused: _numPassengerFocus,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _fromFocusNode,
|
focusNode: _numPassengerFocusNode,
|
||||||
controller: _fromController,
|
controller: _numPassengerController,
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Destination",
|
labelText: "Number of Passenger",
|
||||||
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
@ -316,8 +343,8 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
|
|
||||||
child: DropdownButtonFormField<String>(
|
child: DropdownButtonFormField<String>(
|
||||||
focusNode: _tripTypeFocusNode, // Assign the correct focus node
|
focusNode: _toFocusNode, // Assign the correct focus node
|
||||||
value: selectedPurpose,
|
value: selectedCarType,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
@ -327,12 +354,10 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
onChanged: purposeList.isNotEmpty
|
onChanged: purposeList.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedPurpose = newValue;
|
selectedCarType = newValue;
|
||||||
});
|
});
|
||||||
print("Updating form data: Flight -> trip_type -> ${newValue ?? ""}");
|
print("Updating form data: Flight -> trip_type -> ${newValue ?? ""}");
|
||||||
|
|
||||||
|
|
||||||
widget.updateFormData("Flight", "trip_type", newValue ?? "");
|
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
|
|
||||||
@ -360,7 +385,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
.map((item)=>DropdownMenuItem<String>(
|
||||||
value: item['dropdown_value'],
|
value: item['dropdown_key'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
)).toList();
|
)).toList();
|
||||||
|
|
||||||
@ -374,19 +399,19 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default selected value
|
// Default selected value
|
||||||
String? selectedPurpose = dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
selectedReqTaxi ??= dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||||
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: _isHotelNameFocused,
|
isFocused: _taxiReqFocused,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
|
||||||
child: DropdownButtonFormField<String>(
|
child: DropdownButtonFormField<String>(
|
||||||
focusNode: _tripTypeFocusNode, // Assign the correct focus node
|
focusNode: _taxiReqFocusNode, // Assign the correct focus node
|
||||||
value: selectedPurpose,
|
value: selectedReqTaxi,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
@ -396,12 +421,9 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
onChanged: purposeList.isNotEmpty
|
onChanged: purposeList.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedPurpose = newValue;
|
selectedReqTaxi = newValue;
|
||||||
});
|
});
|
||||||
print("Updating form data: Flight -> trip_type -> ${newValue ?? ""}");
|
print("Updating form data: Flight -> trip_type -> ${newValue ?? ""}");
|
||||||
|
|
||||||
|
|
||||||
widget.updateFormData("Flight", "trip_type", newValue ?? "");
|
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
|
|
||||||
@ -415,86 +437,6 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<Widget> _builClassType(bool isDesktop){
|
|
||||||
|
|
||||||
List<dynamic> purposeList = widget.apiData?['flight_class'] ?? [];
|
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
|
||||||
value: item['dropdown_value'],
|
|
||||||
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
|
|
||||||
String? selectedPurpose = dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
|
||||||
|
|
||||||
return [
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Class *",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Color(0xFF575A74)),
|
|
||||||
),
|
|
||||||
SizedBox(height: 5),
|
|
||||||
CustomTextFieldWrapper(
|
|
||||||
isFocused: _isHotelNameFocused,
|
|
||||||
isDesktop: isDesktop,
|
|
||||||
child: SizedBox(
|
|
||||||
height: 40,
|
|
||||||
|
|
||||||
child: DropdownButtonFormField<String>(
|
|
||||||
focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
|
||||||
// controller: _hotelNameController,
|
|
||||||
value: selectedPurpose,
|
|
||||||
style: TextStyle(fontSize: 12),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: InputBorder.none,
|
|
||||||
contentPadding: EdgeInsets.symmetric(
|
|
||||||
horizontal: 10), // Proper padding
|
|
||||||
),
|
|
||||||
onChanged: purposeList.isNotEmpty
|
|
||||||
? (newValue) {
|
|
||||||
setState(() {
|
|
||||||
selectedPurpose = newValue;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
items: dropdownItems,
|
|
||||||
),
|
|
||||||
|
|
||||||
// child: TextField(
|
|
||||||
// focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
|
||||||
// controller: _hotelNameController,
|
|
||||||
// style: TextStyle(fontSize: 12),
|
|
||||||
// decoration: InputDecoration(
|
|
||||||
// labelText: "Select Class",
|
|
||||||
// labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
|
||||||
// floatingLabelBehavior: FloatingLabelBehavior.never,
|
|
||||||
// border: InputBorder.none,
|
|
||||||
// contentPadding: EdgeInsets.symmetric(vertical: 16),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
List<Widget> _buildSecondRow(bool isDesktop) {
|
List<Widget> _buildSecondRow(bool isDesktop) {
|
||||||
|
|
||||||
|
|
||||||
@ -558,13 +500,13 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _fromFocus,
|
isFocused: _destinationFocus,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _fromFocusNode,
|
focusNode: _destinationFocusNode,
|
||||||
controller: _fromController,
|
controller: _destinationController,
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Destination",
|
labelText: "Destination",
|
||||||
@ -597,14 +539,14 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldItnerarySubWrapper(
|
CustomTextFieldItnerarySubWrapper(
|
||||||
isFocused: _toFocus,
|
isFocused: _locationFocus,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _toFocusNode,
|
focusNode: _locationFocusNode,
|
||||||
controller: _toController,
|
controller: _locationController,
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "Location of Pickup",
|
labelText: "Location of Pickup",
|
||||||
@ -711,8 +653,6 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -737,7 +677,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
: MediaQuery.of(context).size.width * 0.66,
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _commentsFocusNode,
|
focusNode: _commentsFocusNode,
|
||||||
controller: _commentsController,
|
controller: _taxiCommentsController,
|
||||||
maxLines: 6,
|
maxLines: 6,
|
||||||
keyboardType: TextInputType.multiline,
|
keyboardType: TextInputType.multiline,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
@ -760,7 +700,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop(); // Close the dialog or screen
|
widget.onClose(false);// Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
@ -779,7 +719,7 @@ class _TaxiScreenState extends State<TaxiScreen> {
|
|||||||
// Save Changes Button
|
// Save Changes Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// TODO: Implement save logic
|
handleSave();
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.blue, // Primary color for save
|
backgroundColor: Colors.blue, // Primary color for save
|
||||||
|
|||||||
@ -6,19 +6,20 @@ import '../../widgets/custom_text_field.dart';
|
|||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
|
|
||||||
class TrainScreen extends StatefulWidget {
|
class TrainScreen extends StatefulWidget {
|
||||||
final Map<String, String> formData;
|
|
||||||
final Map<String, dynamic>? apiData;
|
|
||||||
final Function(String tab, String key, String value) updateFormData;
|
|
||||||
final Function(bool) onClose;
|
|
||||||
|
|
||||||
TrainScreen({required this.formData, required this.updateFormData,
|
final Map<String, dynamic>? apiData;
|
||||||
required this.onClose, this.apiData});
|
final Function(Map<String, dynamic>)onSavetrain;
|
||||||
|
final Function(bool) onClose;
|
||||||
|
final Map<String, dynamic>? selectedItem;
|
||||||
|
|
||||||
|
TrainScreen({
|
||||||
|
required this.onClose, this.apiData, required this.onSavetrain, required this.selectedItem});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_BusScreenState createState() => _BusScreenState();
|
_TrainScreenState createState() => _TrainScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BusScreenState extends State<TrainScreen> {
|
class _TrainScreenState extends State<TrainScreen> {
|
||||||
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
Map<String, String?> selectedValues = {};
|
Map<String, String?> selectedValues = {};
|
||||||
@ -31,7 +32,6 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
final FocusNode _timeFocusNode = FocusNode();
|
final FocusNode _timeFocusNode = FocusNode();
|
||||||
final FocusNode _commentsFocusNode = FocusNode();
|
final FocusNode _commentsFocusNode = FocusNode();
|
||||||
|
|
||||||
late Map<String, TextEditingController> _controllers;
|
|
||||||
|
|
||||||
late TextEditingController _trainNoController = TextEditingController();
|
late TextEditingController _trainNoController = TextEditingController();
|
||||||
late TextEditingController _hotelNameController = TextEditingController();
|
late TextEditingController _hotelNameController = TextEditingController();
|
||||||
@ -39,7 +39,7 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
late TextEditingController _toController = TextEditingController();
|
late TextEditingController _toController = TextEditingController();
|
||||||
late TextEditingController _dateController = TextEditingController();
|
late TextEditingController _dateController = TextEditingController();
|
||||||
late TextEditingController _timeController = TextEditingController();
|
late TextEditingController _timeController = TextEditingController();
|
||||||
late TextEditingController _commentsController = TextEditingController();
|
late TextEditingController _trainCommentsController = TextEditingController();
|
||||||
|
|
||||||
bool _trainNoFocused = false;
|
bool _trainNoFocused = false;
|
||||||
bool _isHotelNameFocused = false;
|
bool _isHotelNameFocused = false;
|
||||||
@ -49,11 +49,43 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
bool _timeFocus = false;
|
bool _timeFocus = false;
|
||||||
bool _commentsFocus = false;
|
bool _commentsFocus = false;
|
||||||
|
|
||||||
|
String? selectedClass;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Map<String , dynamic> get trainData {
|
||||||
|
Map<String, dynamic> data ={
|
||||||
|
|
||||||
|
"train_no": _trainNoController.text,
|
||||||
|
"class": selectedClass,
|
||||||
|
"from": _fromController.text,
|
||||||
|
"to": _toController.text,
|
||||||
|
"date": _dateController.text,
|
||||||
|
"time": _timeController.text,
|
||||||
|
"comments": _trainCommentsController.text,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (widget.selectedItem != null) {
|
||||||
|
if (widget.selectedItem?["indx"] != null && widget.selectedItem?["indx"] != 0) {
|
||||||
|
data["indx"] = widget.selectedItem!["indx"];
|
||||||
|
} else if (widget.selectedItem?["train_id"] != null && widget.selectedItem?["train_id"] != 0) {
|
||||||
|
data["train_id"] = widget.selectedItem!["train_id"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextEditingController initController(String key) {
|
||||||
|
return TextEditingController(text: widget.selectedItem?[key] ?? "");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
_trainNoFocusNode.addListener(() {
|
_trainNoFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_trainNoFocused = _trainNoFocusNode.hasFocus;
|
_trainNoFocused = _trainNoFocusNode.hasFocus;
|
||||||
});
|
});
|
||||||
@ -68,7 +100,6 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
_fromFocus = _fromFocusNode.hasFocus;
|
_fromFocus = _fromFocusNode.hasFocus;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
_toFocusNode.addListener(() {
|
_toFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_toFocus = _toFocusNode.hasFocus;
|
_toFocus = _toFocusNode.hasFocus;
|
||||||
@ -79,13 +110,11 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
_dateFocus = _fromFocusNode.hasFocus;
|
_dateFocus = _fromFocusNode.hasFocus;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
_timeFocusNode.addListener(() {
|
_timeFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_timeFocus = _timeFocusNode.hasFocus;
|
_timeFocus = _timeFocusNode.hasFocus;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
_commentsFocusNode.addListener(() {
|
_commentsFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_commentsFocus = _commentsFocusNode.hasFocus;
|
_commentsFocus = _commentsFocusNode.hasFocus;
|
||||||
@ -93,53 +122,20 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
_trainCommentsController = initController("comments");
|
||||||
|
_trainNoController = initController("train_no");
|
||||||
|
_fromController = initController("from");
|
||||||
|
_toController = initController("to");
|
||||||
|
_dateController = initController("date");
|
||||||
|
_timeController = initController("time");
|
||||||
|
|
||||||
_trainNoController =
|
// Set the selected value if available
|
||||||
TextEditingController(text: widget.formData["trainNo"] ?? "");
|
if (widget.selectedItem != null && widget.selectedItem!["class"] != null) {
|
||||||
_hotelNameController =
|
selectedClass = widget.selectedItem!["class"].toString();
|
||||||
TextEditingController(text: widget.formData["_hotelName"] ?? "");
|
}
|
||||||
_fromController =
|
|
||||||
TextEditingController(text: widget.formData["_from"] ?? "");
|
|
||||||
_toController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_In_Time"] ?? "");
|
|
||||||
_dateController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_Out"] ?? "");
|
|
||||||
_timeController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_Out_Time"] ?? "");
|
|
||||||
_commentsController =
|
|
||||||
TextEditingController(text: widget.formData["_comments"] ?? "");
|
|
||||||
|
|
||||||
// Save data when user types
|
|
||||||
_trainNoController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Train", "_trainNo", _trainNoController.text);
|
|
||||||
}); // Save data when user types
|
|
||||||
_hotelNameController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Train", "_hotelName", _hotelNameController.text);
|
|
||||||
});
|
|
||||||
_fromController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Train", "_from", _fromController.text);
|
|
||||||
});
|
|
||||||
_toController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Train", "_Check_In_Time", _toController.text);
|
|
||||||
});
|
|
||||||
_dateController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Train", "_Check_Out", _dateController.text);
|
|
||||||
});
|
|
||||||
_timeController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Train", "_Check_Out_Time", _timeController.text);
|
|
||||||
});
|
|
||||||
_commentsController.addListener(() {
|
|
||||||
widget.updateFormData(
|
|
||||||
"Train", "_comments", _commentsController.text);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_trainNoFocusNode.dispose();
|
_trainNoFocusNode.dispose();
|
||||||
@ -149,11 +145,22 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
_toController.dispose();
|
_toController.dispose();
|
||||||
_dateController.dispose();
|
_dateController.dispose();
|
||||||
_timeController.dispose();
|
_timeController.dispose();
|
||||||
_commentsController.dispose();
|
_trainCommentsController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleSave(){
|
||||||
|
|
||||||
|
print( "Handle Save trainData $trainData");
|
||||||
|
widget.onSavetrain(trainData); // Send object to parent
|
||||||
|
widget.onClose(false);// Close screen after saving
|
||||||
|
// Clear only if this is a new entry
|
||||||
|
// if (widget.selectedItem == null) {
|
||||||
|
// _commentsController.clear();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -312,29 +319,6 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// child: DropdownButtonFormField<String>(
|
|
||||||
// focusNode: _trainNoFocusNode, // Assign the correct focus node
|
|
||||||
// value: selectedPurpose,
|
|
||||||
// style: TextStyle(fontSize: 12),
|
|
||||||
// decoration: InputDecoration(
|
|
||||||
// border: InputBorder.none,
|
|
||||||
// contentPadding: EdgeInsets.symmetric(
|
|
||||||
// horizontal: 10), // Proper padding
|
|
||||||
// ),
|
|
||||||
// onChanged: purposeList.isNotEmpty
|
|
||||||
// ? (newValue) {
|
|
||||||
// setState(() {
|
|
||||||
// selectedPurpose = newValue;
|
|
||||||
// });
|
|
||||||
// print("Updating form data: Flight -> trip_type -> ${newValue ?? ""}");
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// widget.updateFormData("Flight", "trip_type", newValue ?? "");
|
|
||||||
// }
|
|
||||||
// : null,
|
|
||||||
//
|
|
||||||
// items: dropdownItems,
|
|
||||||
// ),
|
|
||||||
|
|
||||||
|
|
||||||
),
|
),
|
||||||
@ -349,7 +333,7 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
.map((item)=>DropdownMenuItem<String>(
|
||||||
value: item['dropdown_value'],
|
value: item['dropdown_key'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
)).toList();
|
)).toList();
|
||||||
|
|
||||||
@ -363,7 +347,7 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default selected value
|
// Default selected value
|
||||||
String? selectedPurpose = dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
selectedClass ??= dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
Column(
|
Column(
|
||||||
@ -386,7 +370,7 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
child: DropdownButtonFormField<String>(
|
child: DropdownButtonFormField<String>(
|
||||||
focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
||||||
// controller: _hotelNameController,
|
// controller: _hotelNameController,
|
||||||
value: selectedPurpose,
|
value: selectedClass,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
@ -396,25 +380,14 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
onChanged: purposeList.isNotEmpty
|
onChanged: purposeList.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedPurpose = newValue;
|
selectedClass = newValue;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
items: dropdownItems,
|
items: dropdownItems,
|
||||||
),
|
),
|
||||||
|
|
||||||
// child: TextField(
|
|
||||||
// focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
|
||||||
// controller: _hotelNameController,
|
|
||||||
// style: TextStyle(fontSize: 12),
|
|
||||||
// decoration: InputDecoration(
|
|
||||||
// labelText: "Select Class",
|
|
||||||
// labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
|
||||||
// floatingLabelBehavior: FloatingLabelBehavior.never,
|
|
||||||
// border: InputBorder.none,
|
|
||||||
// contentPadding: EdgeInsets.symmetric(vertical: 16),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -665,12 +638,12 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
: MediaQuery.of(context).size.width * 0.66,
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _commentsFocusNode,
|
focusNode: _commentsFocusNode,
|
||||||
controller: _commentsController,
|
controller: _trainCommentsController,
|
||||||
maxLines: 6,
|
maxLines: 6,
|
||||||
keyboardType: TextInputType.multiline,
|
keyboardType: TextInputType.multiline,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: "Description",
|
labelText: "Comments",
|
||||||
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
@ -688,7 +661,7 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop(); // Close the dialog or screen
|
widget.onClose(false);
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
@ -707,7 +680,7 @@ class _BusScreenState extends State<TrainScreen> {
|
|||||||
// Save Changes Button
|
// Save Changes Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// TODO: Implement save logic
|
handleSave();
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.blue, // Primary color for save
|
backgroundColor: Colors.blue, // Primary color for save
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:dropdown_search/dropdown_search.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:responsive_builder/responsive_builder.dart';
|
import 'package:responsive_builder/responsive_builder.dart';
|
||||||
@ -6,13 +7,17 @@ import '../../widgets/custom_text_field.dart';
|
|||||||
import '../../widgets/custom_text_itnerary_sub.dart';
|
import '../../widgets/custom_text_itnerary_sub.dart';
|
||||||
|
|
||||||
class VisaScreen extends StatefulWidget {
|
class VisaScreen extends StatefulWidget {
|
||||||
final Map<String, String> formData;
|
|
||||||
final Map<String, dynamic>? apiData;
|
|
||||||
final Function(String tab, String key, String value) updateFormData;
|
|
||||||
final Function(bool) onClose;
|
|
||||||
|
|
||||||
VisaScreen({required this.formData, required this.updateFormData,
|
final Map<String, dynamic>? apiData;
|
||||||
required this.onClose, this.apiData});
|
final List<dynamic>? apiCountryData;
|
||||||
|
|
||||||
|
|
||||||
|
final Function(bool) onClose;
|
||||||
|
final Function(Map<String,dynamic>) onSaveVisa;
|
||||||
|
final Map<String, dynamic>? selectedItem;
|
||||||
|
|
||||||
|
VisaScreen({
|
||||||
|
required this.onClose,required this.onSaveVisa, this.apiData, required this.selectedItem, required this.apiCountryData});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_VisaScreenState createState() => _VisaScreenState();
|
_VisaScreenState createState() => _VisaScreenState();
|
||||||
@ -23,15 +28,13 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
|
|
||||||
Map<String, String?> selectedValues = {};
|
Map<String, String?> selectedValues = {};
|
||||||
|
|
||||||
|
List<dynamic> countryList = [];
|
||||||
|
|
||||||
final FocusNode _tripTypeFocusNode = FocusNode();
|
final FocusNode _tripTypeFocusNode = FocusNode();
|
||||||
final FocusNode _hotelNameFocusNode = FocusNode();
|
final FocusNode _hotelNameFocusNode = FocusNode();
|
||||||
final FocusNode _fromFocusNode = FocusNode();
|
|
||||||
final FocusNode _toFocusNode = FocusNode();
|
|
||||||
final FocusNode _dateFocusNode = FocusNode();
|
final FocusNode _dateFocusNode = FocusNode();
|
||||||
final FocusNode _timeFocusNode = FocusNode();
|
|
||||||
final FocusNode _commentsFocusNode = FocusNode();
|
final FocusNode _commentsFocusNode = FocusNode();
|
||||||
|
|
||||||
late Map<String, TextEditingController> _controllers;
|
|
||||||
|
|
||||||
late TextEditingController _tripTypeController = TextEditingController();
|
late TextEditingController _tripTypeController = TextEditingController();
|
||||||
late TextEditingController _hotelNameController = TextEditingController();
|
late TextEditingController _hotelNameController = TextEditingController();
|
||||||
@ -39,72 +42,65 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
late TextEditingController _toController = TextEditingController();
|
late TextEditingController _toController = TextEditingController();
|
||||||
late TextEditingController _dateController = TextEditingController();
|
late TextEditingController _dateController = TextEditingController();
|
||||||
late TextEditingController _timeController = TextEditingController();
|
late TextEditingController _timeController = TextEditingController();
|
||||||
late TextEditingController _commentsController = TextEditingController();
|
late TextEditingController _visaCommentsController = TextEditingController();
|
||||||
|
|
||||||
bool _tripTypeFocused = false;
|
bool _tripTypeFocused = false;
|
||||||
bool _isHotelNameFocused = false;
|
bool _isHotelNameFocused = false;
|
||||||
bool _fromFocus = false;
|
|
||||||
bool _toFocus = false;
|
|
||||||
bool _dateFocus = false;
|
bool _dateFocus = false;
|
||||||
bool _timeFocus = false;
|
|
||||||
bool _commentsFocus = false;
|
bool _commentsFocus = false;
|
||||||
|
|
||||||
|
String? selectedPurpose;
|
||||||
|
String? selectedCountry;
|
||||||
|
|
||||||
|
Map<String, dynamic> get visaData{
|
||||||
|
Map<String, dynamic> data ={
|
||||||
|
"type_of_visa" :selectedPurpose,
|
||||||
|
"country": selectedCountry,
|
||||||
|
// "country_code": selectedCountry,
|
||||||
|
"start_date": _dateController.text,
|
||||||
|
"comments":_visaCommentsController.text
|
||||||
|
};
|
||||||
|
|
||||||
|
if (widget.selectedItem != null) {
|
||||||
|
if (widget.selectedItem?["indx"] != null && widget.selectedItem?["indx"] != 0) {
|
||||||
|
data["indx"] = widget.selectedItem!["indx"];
|
||||||
|
} else if (widget.selectedItem?["visa_id"] != null && widget.selectedItem?["visa_id"] != 0) {
|
||||||
|
data["visa_id"] = widget.selectedItem!["visa_id"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
|
||||||
_addFocusListener(_tripTypeFocusNode, (focus) => _tripTypeFocused = focus);
|
_addFocusListener(_tripTypeFocusNode, (focus) => _tripTypeFocused = focus);
|
||||||
_addFocusListener(_hotelNameFocusNode, (focus) => _isHotelNameFocused = focus);
|
_addFocusListener(_hotelNameFocusNode, (focus) => _isHotelNameFocused = focus);
|
||||||
_addFocusListener(_fromFocusNode, (focus) => _fromFocus = focus);
|
|
||||||
_addFocusListener(_toFocusNode, (focus) => _toFocus = focus);
|
|
||||||
_addFocusListener(_dateFocusNode, (focus) => _dateFocus = focus);
|
_addFocusListener(_dateFocusNode, (focus) => _dateFocus = focus);
|
||||||
_addFocusListener(_timeFocusNode, (focus) => _timeFocus = focus);
|
|
||||||
_addFocusListener(_commentsFocusNode, (focus) => _commentsFocus = focus);
|
_addFocusListener(_commentsFocusNode, (focus) => _commentsFocus = focus);
|
||||||
|
|
||||||
// _commentsFocusNode.addListener(() {
|
_visaCommentsController =
|
||||||
// setState(() {
|
TextEditingController(text: widget.selectedItem?["comments"] ?? "");
|
||||||
// _commentsFocus = _commentsFocusNode.hasFocus;
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_tripTypeController =
|
|
||||||
TextEditingController(text: widget.formData["tripType"] ?? "");
|
|
||||||
_hotelNameController =
|
|
||||||
TextEditingController(text: widget.formData["_hotelName"] ?? "");
|
|
||||||
_fromController =
|
|
||||||
TextEditingController(text: widget.formData["_from"] ?? "");
|
|
||||||
_toController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_In_Time"] ?? "");
|
|
||||||
_dateController =
|
_dateController =
|
||||||
TextEditingController(text: widget.formData["_Check_Out"] ?? "");
|
TextEditingController(text: widget.selectedItem?["start_date"] ?? "");
|
||||||
_timeController =
|
|
||||||
TextEditingController(text: widget.formData["_Check_Out_Time"] ?? "");
|
|
||||||
_commentsController =
|
|
||||||
TextEditingController(text: widget.formData["_comments"] ?? "");
|
|
||||||
|
|
||||||
// Save data when user types
|
// Set the selected value if available
|
||||||
List<TextEditingController> controllers = [
|
if (widget.selectedItem != null && widget.selectedItem!["type_of_visa"] != null) {
|
||||||
_tripTypeController, _hotelNameController, _fromController, _toController, _dateController,
|
selectedPurpose = widget.selectedItem!["type_of_visa"].toString();
|
||||||
_timeController, _commentsController
|
}
|
||||||
];
|
if (widget.selectedItem != null && widget.selectedItem!["selectedCountry"] != null) {
|
||||||
|
selectedPurpose = widget.selectedItem!["selectedCountry"].toString();
|
||||||
List<String> keys = [
|
|
||||||
"_tripType", "_hotelName", "_from", "_Check_In_Time", "_Check_Out",
|
|
||||||
"_Check_Out_Time", "_comments"
|
|
||||||
];
|
|
||||||
|
|
||||||
for (int i = 0; i < controllers.length; i++) {
|
|
||||||
controllers[i].addListener(() {
|
|
||||||
widget.updateFormData("Flight", keys[i], controllers[i].text);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||||
node.addListener(() {
|
node.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -122,11 +118,23 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
_toController.dispose();
|
_toController.dispose();
|
||||||
_dateController.dispose();
|
_dateController.dispose();
|
||||||
_timeController.dispose();
|
_timeController.dispose();
|
||||||
_commentsController.dispose();
|
_visaCommentsController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleSave(){
|
||||||
|
|
||||||
|
print( "Handle Save miscellaneousData $visaData");
|
||||||
|
widget.onSaveVisa(visaData); // Send object to parent
|
||||||
|
widget.onClose(false);// Close screen after saving
|
||||||
|
// // Clear only if this is a new entry
|
||||||
|
// if (widget.selectedItem == null) {
|
||||||
|
// _visaCommentsController.clear();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -184,7 +192,6 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<List<Widget>> rowBuilders = [
|
List<List<Widget>> rowBuilders = [
|
||||||
// _builClassType(isDesktop),
|
|
||||||
_buildSecondRow(isDesktop)
|
_buildSecondRow(isDesktop)
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -249,7 +256,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
.map((item)=>DropdownMenuItem<String>(
|
||||||
value: item['dropdown_value'],
|
value: item['dropdown_key'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
)).toList();
|
)).toList();
|
||||||
|
|
||||||
@ -263,7 +270,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default selected value
|
// Default selected value
|
||||||
String? selectedPurpose = dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
selectedPurpose ??= dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||||
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -290,7 +297,6 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
print("Updating form data: Flight -> trip_type -> ${newValue ?? ""}");
|
print("Updating form data: Flight -> trip_type -> ${newValue ?? ""}");
|
||||||
|
|
||||||
|
|
||||||
widget.updateFormData("Flight", "trip_type", newValue ?? "");
|
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
|
|
||||||
@ -304,110 +310,51 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<Widget> _builClassType(bool isDesktop){
|
|
||||||
|
|
||||||
List<dynamic> purposeList = widget.apiData?['flight_class'] ?? [];
|
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
|
||||||
value: item['dropdown_value'],
|
|
||||||
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
|
|
||||||
String? selectedPurpose = dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
|
||||||
|
|
||||||
return [
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Country",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Color(0xFF575A74)),
|
|
||||||
),
|
|
||||||
SizedBox(height: 5),
|
|
||||||
CustomTextFieldWrapper(
|
|
||||||
isFocused: _isHotelNameFocused,
|
|
||||||
isDesktop: isDesktop,
|
|
||||||
child: SizedBox(
|
|
||||||
height: 40,
|
|
||||||
|
|
||||||
child: DropdownButtonFormField<String>(
|
|
||||||
focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
|
||||||
// controller: _hotelNameController,
|
|
||||||
value: selectedPurpose,
|
|
||||||
style: TextStyle(fontSize: 12),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: InputBorder.none,
|
|
||||||
contentPadding: EdgeInsets.symmetric(
|
|
||||||
horizontal: 10), // Proper padding
|
|
||||||
),
|
|
||||||
onChanged: purposeList.isNotEmpty
|
|
||||||
? (newValue) {
|
|
||||||
setState(() {
|
|
||||||
selectedPurpose = newValue;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
items: dropdownItems,
|
|
||||||
),
|
|
||||||
|
|
||||||
// child: TextField(
|
|
||||||
// focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
|
||||||
// controller: _hotelNameController,
|
|
||||||
// style: TextStyle(fontSize: 12),
|
|
||||||
// decoration: InputDecoration(
|
|
||||||
// labelText: "Select Class",
|
|
||||||
// labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
|
||||||
// floatingLabelBehavior: FloatingLabelBehavior.never,
|
|
||||||
// border: InputBorder.none,
|
|
||||||
// contentPadding: EdgeInsets.symmetric(vertical: 16),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
List<Widget> _buildSecondRow(bool isDesktop) {
|
List<Widget> _buildSecondRow(bool isDesktop) {
|
||||||
|
|
||||||
List<dynamic> purposeList = widget.apiData?['flight_class'] ?? [];
|
// List<dynamic> countryList = widget.apiCountryData ?? [];
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
//
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
// List<DropdownMenuItem<String>> dropdownItems = countryList
|
||||||
value: item['dropdown_value'],
|
// .map((item)=>DropdownMenuItem<String>(
|
||||||
child: Text(item['dropdown_value']),
|
// value: item['country_code'], // Use 'country_code' from API response
|
||||||
)).toList();
|
// child: Text(item['country_name']),
|
||||||
|
// )).toList();
|
||||||
|
//
|
||||||
|
// if (dropdownItems.isEmpty) {
|
||||||
|
// dropdownItems.add(
|
||||||
|
// DropdownMenuItem<String>(
|
||||||
|
// value: null,
|
||||||
|
// child: Text("No options available", style: TextStyle(color: Colors.grey)),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Default selected value
|
||||||
|
// selectedCountry ??= dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||||
|
// List<String> countryNames = countryList.map((item) => item['country_name'] as String).toList();
|
||||||
|
//
|
||||||
|
|
||||||
if (dropdownItems.isEmpty) {
|
late Map<String, String> countryMap; // Mapping country_code -> country_name
|
||||||
dropdownItems.add(
|
late List<String> countryCodes; // List of country codes
|
||||||
DropdownMenuItem<String>(
|
|
||||||
value: null,
|
|
||||||
child: Text("No options available", style: TextStyle(color: Colors.grey)),
|
countryList = widget.apiCountryData ?? [];
|
||||||
),
|
|
||||||
);
|
// Map country codes to country names
|
||||||
|
countryMap = {
|
||||||
|
for (var item in countryList) item['country_code'] as String: item['country_name'] as String
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extract only country codes for processing
|
||||||
|
countryCodes = countryMap.keys.toList();
|
||||||
|
|
||||||
|
// Set default selected value
|
||||||
|
if (selectedCountry == null && countryCodes.isNotEmpty) {
|
||||||
|
selectedCountry = countryCodes.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default selected value
|
|
||||||
String? selectedPurpose = dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ____________
|
// ____________
|
||||||
DateTime? _selectedCheckOutDate;
|
DateTime? _selectedCheckOutDate;
|
||||||
TimeOfDay? _selectedCheckOutTime;
|
TimeOfDay? _selectedCheckOutTime;
|
||||||
@ -454,41 +401,71 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
child: DropdownSearch<String>(
|
||||||
child: DropdownButtonFormField<String>(
|
selectedItem: countryMap[selectedCountry],
|
||||||
focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
popupProps: PopupProps.menu(
|
||||||
// controller: _hotelNameController,
|
showSearchBox: true, // Enables search functionality
|
||||||
value: selectedPurpose,
|
searchFieldProps: TextFieldProps(
|
||||||
style: TextStyle(fontSize: 12),
|
decoration: InputDecoration(
|
||||||
decoration: InputDecoration(
|
hintText: "Search Country...",
|
||||||
border: InputBorder.none,
|
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
contentPadding: EdgeInsets.symmetric(
|
),
|
||||||
horizontal: 10), // Proper padding
|
),
|
||||||
),
|
),
|
||||||
onChanged: purposeList.isNotEmpty
|
items: countryMap.values.toList(),
|
||||||
? (newValue) {
|
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||||
|
dropdownSearchDecoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 1,),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownBuilder: (context, selectedItem) => Align( // Center-align selected item
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
selectedItem ?? "Select Country",
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onChanged: (String? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedPurpose = newValue;
|
// Find the country_code based on selected country_name
|
||||||
|
selectedCountry = countryMap.entries
|
||||||
|
.firstWhere((entry) => entry.value == newValue)
|
||||||
|
.key;
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
: null,
|
|
||||||
items: dropdownItems,
|
|
||||||
),
|
),
|
||||||
|
|
||||||
// child: TextField(
|
|
||||||
// focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
|
||||||
// controller: _hotelNameController,
|
|
||||||
// style: TextStyle(fontSize: 12),
|
|
||||||
// decoration: InputDecoration(
|
|
||||||
// labelText: "Select Class",
|
|
||||||
// labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
|
||||||
// floatingLabelBehavior: FloatingLabelBehavior.never,
|
|
||||||
// border: InputBorder.none,
|
|
||||||
// contentPadding: EdgeInsets.symmetric(vertical: 16),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// CustomTextFieldWrapper(
|
||||||
|
// isFocused: _isHotelNameFocused,
|
||||||
|
// isDesktop: isDesktop,
|
||||||
|
// child: SizedBox(
|
||||||
|
// height: 40,
|
||||||
|
//
|
||||||
|
// child: DropdownButtonFormField<String>(
|
||||||
|
// focusNode: _hotelNameFocusNode, // Assign the correct focus node
|
||||||
|
// // controller: _hotelNameController,
|
||||||
|
// value: selectedCountry,
|
||||||
|
// style: TextStyle(fontSize: 12),
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// border: InputBorder.none,
|
||||||
|
// contentPadding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: 10), // Proper padding
|
||||||
|
// ),
|
||||||
|
// onChanged: countryList.isNotEmpty
|
||||||
|
// ? (newValue) {
|
||||||
|
// setState(() {
|
||||||
|
// selectedCountry = newValue;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// : null,
|
||||||
|
// items: dropdownItems,
|
||||||
|
// ),
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -502,7 +479,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Date",
|
"Start Date",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@ -566,7 +543,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
: MediaQuery.of(context).size.width * 0.66,
|
: MediaQuery.of(context).size.width * 0.66,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _commentsFocusNode,
|
focusNode: _commentsFocusNode,
|
||||||
controller: _commentsController,
|
controller: _visaCommentsController,
|
||||||
maxLines: 6,
|
maxLines: 6,
|
||||||
keyboardType: TextInputType.multiline,
|
keyboardType: TextInputType.multiline,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
@ -589,7 +566,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
// Close Button
|
// Close Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop(); // Close the dialog or screen
|
widget.onClose(false); // Close the dialog or screen
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[400], // Light grey color
|
backgroundColor: Colors.grey[400], // Light grey color
|
||||||
@ -608,7 +585,7 @@ class _VisaScreenState extends State<VisaScreen> {
|
|||||||
// Save Changes Button
|
// Save Changes Button
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// TODO: Implement save logic
|
handleSave();
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.blue, // Primary color for save
|
backgroundColor: Colors.blue, // Primary color for save
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class AccomodationListWidget extends StatelessWidget {
|
class AccomodationListWidget extends StatelessWidget {
|
||||||
const AccomodationListWidget({super.key});
|
|
||||||
|
final List<Map<String,dynamic>> accommodationList;
|
||||||
|
final Function(bool, Map<String, dynamic>, String) onOpen;
|
||||||
|
final Function(Map<String, dynamic>) onDeleteAccommodation;
|
||||||
|
|
||||||
|
const AccomodationListWidget({super.key, required this.accommodationList, required this.onOpen, required this.onDeleteAccommodation});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -26,10 +31,11 @@ class AccomodationListWidget extends StatelessWidget {
|
|||||||
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
||||||
),
|
),
|
||||||
columns: const [
|
columns: const [
|
||||||
DataColumn(label: Text('Trip Type')),
|
DataColumn(label: Text('#')),
|
||||||
DataColumn(label: Text('Class')),
|
DataColumn(label: Text('Destination City')),
|
||||||
DataColumn(label: Text('From')),
|
DataColumn(label: Text('Hotel Name')),
|
||||||
DataColumn(label: Text('To')),
|
DataColumn(label: Text('CheckIn Date')),
|
||||||
|
DataColumn(label: Text('CheckOut Date')),
|
||||||
DataColumn(label: Text('Actions')),
|
DataColumn(label: Text('Actions')),
|
||||||
],
|
],
|
||||||
rows: _buildDataRows(),
|
rows: _buildDataRows(),
|
||||||
@ -42,17 +48,19 @@ class AccomodationListWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<DataRow> _buildDataRows() {
|
List<DataRow> _buildDataRows() {
|
||||||
List<Map<String, String>> data = [
|
|
||||||
{"tripType": "One-Way", "class": "Economy", "from": "NYC", "to": "LA"},
|
|
||||||
{"tripType": "Round-Trip", "class": "Business", "from": "SF", "to": "Seattle"},
|
|
||||||
];
|
|
||||||
|
|
||||||
return data.map((bus) {
|
|
||||||
|
return accommodationList.asMap() .entries.map((entry) {
|
||||||
|
|
||||||
|
final Map<String, dynamic> item = entry.value;
|
||||||
|
|
||||||
return DataRow(cells: [
|
return DataRow(cells: [
|
||||||
DataCell(Text(bus["tripType"]!)),
|
|
||||||
DataCell(Text(bus["class"]!)),
|
DataCell(Text(item["indx"]?.toString() ?? "N/A")), // Index column
|
||||||
DataCell(Text(bus["from"]!)),
|
DataCell(Text(item["destination_city"]!)),
|
||||||
DataCell(Text(bus["to"]!)),
|
DataCell(Text(item["hotel_name"]!)),
|
||||||
|
DataCell(Text(item["checkin_date"]!)),
|
||||||
|
DataCell(Text(item["checkout_date"]!)),
|
||||||
DataCell(Row(
|
DataCell(Row(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
@ -64,13 +72,13 @@ class AccomodationListWidget extends StatelessWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.edit, color: Colors.green),
|
icon: Icon(Icons.edit, color: Colors.green),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Edit action
|
onOpen(true, item, "Accommodation");
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.delete, color: Colors.red),
|
icon: Icon(Icons.delete, color: Colors.red),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Delete action
|
onDeleteAccommodation(item);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -8,61 +8,12 @@ import '../../config/apiUrl.dart';
|
|||||||
import '../../data/models/plan.dart';
|
import '../../data/models/plan.dart';
|
||||||
|
|
||||||
|
|
||||||
class BusListWidget extends StatefulWidget{
|
class BusListWidget extends StatelessWidget{
|
||||||
const BusListWidget({super.key});
|
final List<Map<String, dynamic>> busList;
|
||||||
|
final Function(bool, Map<String, dynamic>, String) onOpen;
|
||||||
|
final Function(Map<String,dynamic>) onDeleteBus;
|
||||||
|
const BusListWidget({super.key, required this.busList, required this.onOpen, required this.onDeleteBus});
|
||||||
|
|
||||||
@override
|
|
||||||
_BusListWidgetState createState() => _BusListWidgetState();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BusListWidgetState extends State<BusListWidget> {
|
|
||||||
// const BusListWidget({super.key});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
late Future<List<Plan>> futurePlans;
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState(){
|
|
||||||
super.initState();
|
|
||||||
futurePlans = fetchPlans();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String?> getToken() async {
|
|
||||||
final prefs = await SharedPreferences.getInstance();
|
|
||||||
return prefs.getString('auth_token');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Fetch API Data
|
|
||||||
Future<List<Plan>> fetchPlans() async {
|
|
||||||
final String apiUrldata = '$apiUrl/api/plans';
|
|
||||||
|
|
||||||
final token = await getToken();
|
|
||||||
|
|
||||||
if (token == null) {
|
|
||||||
throw Exception('Token not found. Please log in.');
|
|
||||||
}
|
|
||||||
|
|
||||||
final response = await http.get(
|
|
||||||
Uri.parse(apiUrldata),
|
|
||||||
headers: {
|
|
||||||
'Authorization': 'Bearer $token', // Add token here
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
|
||||||
final data = json.decode(response.body);
|
|
||||||
List<dynamic> plansJson = data['data'];
|
|
||||||
return plansJson.map((json) => Plan.fromJson(json)).toList();
|
|
||||||
} else {
|
|
||||||
throw Exception('Failed to load plans');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -91,10 +42,12 @@ Future<List<Plan>> fetchPlans() async {
|
|||||||
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
||||||
),
|
),
|
||||||
columns: const [
|
columns: const [
|
||||||
DataColumn(label: Text('Trip Type')),
|
|
||||||
DataColumn(label: Text('Class')),
|
DataColumn(label: Text('#')),
|
||||||
DataColumn(label: Text('From')),
|
DataColumn(label: Text('From')),
|
||||||
DataColumn(label: Text('To')),
|
DataColumn(label: Text('To')),
|
||||||
|
DataColumn(label: Text('Date')),
|
||||||
|
DataColumn(label: Text('Time')),
|
||||||
|
|
||||||
DataColumn(label: Text('Actions')),
|
DataColumn(label: Text('Actions')),
|
||||||
],
|
],
|
||||||
@ -113,17 +66,18 @@ Future<List<Plan>> fetchPlans() async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<DataRow> _buildDataRows() {
|
List<DataRow> _buildDataRows() {
|
||||||
List<Map<String, String>> data = [
|
|
||||||
{"tripType": "One-Way", "class": "Economy", "from": "NYC", "to": "LA"},
|
|
||||||
{"tripType": "Round-Trip", "class": "Business", "from": "SF", "to": "Seattle"},
|
|
||||||
];
|
|
||||||
|
|
||||||
return data.map((bus) {
|
|
||||||
|
return busList.asMap().entries.map((entry) {
|
||||||
|
|
||||||
|
final Map<String, dynamic> item = entry.value;
|
||||||
|
|
||||||
return DataRow(cells: [
|
return DataRow(cells: [
|
||||||
DataCell(Text(bus["tripType"]!)),
|
DataCell(Text(item["indx"]?.toString() ?? "N/A")), // Index column
|
||||||
DataCell(Text(bus["class"]!)),
|
DataCell(Text(item["from"]!)),
|
||||||
DataCell(Text(bus["from"]!)),
|
DataCell(Text(item["to"]!)),
|
||||||
DataCell(Text(bus["to"]!)),
|
DataCell(Text(item["date"]!)),
|
||||||
|
DataCell(Text(item["time"]!)),
|
||||||
DataCell(Row(
|
DataCell(Row(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
@ -135,13 +89,13 @@ Future<List<Plan>> fetchPlans() async {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.edit, color: Colors.green),
|
icon: Icon(Icons.edit, color: Colors.green),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Edit action
|
onOpen(true, item, "Bus");
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.delete, color: Colors.red),
|
icon: Icon(Icons.delete, color: Colors.red),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Delete action
|
onDeleteBus(item);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,67 +1,14 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:responsive_builder/responsive_builder.dart';
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
|
|
||||||
import '../../config/apiUrl.dart';
|
|
||||||
import '../../data/models/plan.dart';
|
|
||||||
|
|
||||||
|
|
||||||
class ForexListWidget extends StatefulWidget{
|
class ForexListWidget extends StatelessWidget{
|
||||||
const ForexListWidget({super.key});
|
final List<Map<String,dynamic>> forexList;
|
||||||
|
final Function(bool, Map<String,dynamic>, String)onOpen;
|
||||||
|
final Function(Map<String,dynamic>) onDeleteForex;
|
||||||
|
|
||||||
@override
|
const ForexListWidget({super.key, required this.forexList, required this.onOpen, required this.onDeleteForex});
|
||||||
_ForexListWidgetState createState() => _ForexListWidgetState();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ForexListWidgetState extends State<ForexListWidget> {
|
|
||||||
// const BusListWidget({super.key});
|
|
||||||
|
|
||||||
|
|
||||||
late Future<List<Plan>> futurePlans;
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState(){
|
|
||||||
super.initState();
|
|
||||||
futurePlans = fetchPlans();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String?> getToken() async {
|
|
||||||
final prefs = await SharedPreferences.getInstance();
|
|
||||||
return prefs.getString('auth_token');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Fetch API Data
|
|
||||||
Future<List<Plan>> fetchPlans() async {
|
|
||||||
final String apiUrldata = '$apiUrl/api/plans';
|
|
||||||
|
|
||||||
final token = await getToken();
|
|
||||||
|
|
||||||
if (token == null) {
|
|
||||||
throw Exception('Token not found. Please log in.');
|
|
||||||
}
|
|
||||||
|
|
||||||
final response = await http.get(
|
|
||||||
Uri.parse(apiUrldata),
|
|
||||||
headers: {
|
|
||||||
'Authorization': 'Bearer $token', // Add token here
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
|
||||||
final data = json.decode(response.body);
|
|
||||||
List<dynamic> plansJson = data['data'];
|
|
||||||
return plansJson.map((json) => Plan.fromJson(json)).toList();
|
|
||||||
} else {
|
|
||||||
throw Exception('Failed to load plans');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -90,11 +37,11 @@ class _ForexListWidgetState extends State<ForexListWidget> {
|
|||||||
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
||||||
),
|
),
|
||||||
columns: const [
|
columns: const [
|
||||||
DataColumn(label: Text('Trip Type')),
|
DataColumn(label: Text('#')),
|
||||||
DataColumn(label: Text('Class')),
|
DataColumn(label: Text('Forex Start Date')),
|
||||||
DataColumn(label: Text('From')),
|
DataColumn(label: Text('Forex End Date')),
|
||||||
DataColumn(label: Text('To')),
|
DataColumn(label: Text('Country')),
|
||||||
|
DataColumn(label: Text('Perdiem Amount')),
|
||||||
DataColumn(label: Text('Actions')),
|
DataColumn(label: Text('Actions')),
|
||||||
],
|
],
|
||||||
rows: _buildDataRows(),
|
rows: _buildDataRows(),
|
||||||
@ -112,17 +59,18 @@ class _ForexListWidgetState extends State<ForexListWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<DataRow> _buildDataRows() {
|
List<DataRow> _buildDataRows() {
|
||||||
List<Map<String, String>> data = [
|
|
||||||
{"tripType": "One-Way", "class": "Economy", "from": "NYC", "to": "LA"},
|
|
||||||
{"tripType": "Round-Trip", "class": "Business", "from": "SF", "to": "Seattle"},
|
|
||||||
];
|
|
||||||
|
|
||||||
return data.map((bus) {
|
|
||||||
|
return forexList.asMap().entries.map((entry) {
|
||||||
|
|
||||||
|
Map<String,dynamic> item = entry.value;
|
||||||
|
|
||||||
return DataRow(cells: [
|
return DataRow(cells: [
|
||||||
DataCell(Text(bus["tripType"]!)),
|
DataCell(Text(item["indx"]?.toString() ?? "N/A")), // Index column
|
||||||
DataCell(Text(bus["class"]!)),
|
DataCell(Text(item["start_date"] ?? "N/A")),
|
||||||
DataCell(Text(bus["from"]!)),
|
DataCell(Text(item["end_date"] ?? "N/A")),
|
||||||
DataCell(Text(bus["to"]!)),
|
DataCell(Text(item["country_code"] ?? "N/A")),
|
||||||
|
DataCell(Text(item["perdiem_amount"] ?? "N/A")),
|
||||||
DataCell(Row(
|
DataCell(Row(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
@ -134,13 +82,13 @@ class _ForexListWidgetState extends State<ForexListWidget> {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.edit, color: Colors.green),
|
icon: Icon(Icons.edit, color: Colors.green),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Edit action
|
onOpen(true, item, "Forex");
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.delete, color: Colors.red),
|
icon: Icon(Icons.delete, color: Colors.red),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Delete action
|
onDeleteForex(item);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
|
import 'dart:js_interop';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class InsuranceListWidget extends StatelessWidget {
|
class InsuranceListWidget extends StatelessWidget {
|
||||||
const InsuranceListWidget({super.key});
|
final List<Map<String,dynamic>> insuranceList;
|
||||||
|
final Function(bool, Map<String,dynamic>, String)onOpen;
|
||||||
|
final Function(Map<String,dynamic>)onDeleteInsurance;
|
||||||
|
const InsuranceListWidget({super.key, required this.insuranceList, required this.onOpen,required this.onDeleteInsurance});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -27,10 +32,10 @@ class InsuranceListWidget extends StatelessWidget {
|
|||||||
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
||||||
),
|
),
|
||||||
columns: const [
|
columns: const [
|
||||||
DataColumn(label: Text('Trip Type')),
|
DataColumn(label: Text('#')),
|
||||||
DataColumn(label: Text('Class')),
|
DataColumn(label: Text('Insurance Type')),
|
||||||
DataColumn(label: Text('From')),
|
DataColumn(label: Text('Start Date')),
|
||||||
DataColumn(label: Text('To')),
|
DataColumn(label: Text('End Date')),
|
||||||
DataColumn(label: Text('Actions')),
|
DataColumn(label: Text('Actions')),
|
||||||
],
|
],
|
||||||
rows: _buildDataRows(),
|
rows: _buildDataRows(),
|
||||||
@ -45,17 +50,16 @@ class InsuranceListWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<DataRow> _buildDataRows() {
|
List<DataRow> _buildDataRows() {
|
||||||
List<Map<String, String>> data = [
|
|
||||||
{"tripType": "One-Way", "class": "Economy", "from": "NYC", "to": "LA"},
|
|
||||||
{"tripType": "Round-Trip", "class": "Business", "from": "SF", "to": "Seattle"},
|
|
||||||
];
|
|
||||||
|
|
||||||
return data.map((bus) {
|
|
||||||
|
return insuranceList.asMap().entries.map((entry) {
|
||||||
|
|
||||||
|
Map<String,dynamic> item = entry.value;
|
||||||
return DataRow(cells: [
|
return DataRow(cells: [
|
||||||
DataCell(Text(bus["tripType"]!)),
|
DataCell(Text(item["indx"]?.toString() ?? "N/A")), // Index column
|
||||||
DataCell(Text(bus["class"]!)),
|
DataCell(Text(item["type_of_insurance"]!)),
|
||||||
DataCell(Text(bus["from"]!)),
|
DataCell(Text(item["start_date"]!)),
|
||||||
DataCell(Text(bus["to"]!)),
|
DataCell(Text(item["end_date"]!)),
|
||||||
DataCell(Row(
|
DataCell(Row(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
@ -67,13 +71,13 @@ class InsuranceListWidget extends StatelessWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.edit, color: Colors.green),
|
icon: Icon(Icons.edit, color: Colors.green),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Edit action
|
onOpen(true, item, "Insurance");
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.delete, color: Colors.red),
|
icon: Icon(Icons.delete, color: Colors.red),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Delete action
|
onDeleteInsurance(item);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,7 +1,13 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class MiscellaneousListWidget extends StatelessWidget {
|
class MiscellaneousListWidget extends StatelessWidget {
|
||||||
const MiscellaneousListWidget({super.key});
|
|
||||||
|
final List<Map<String,dynamic>> miscellaneousList;
|
||||||
|
final Function(bool, Map<String, dynamic>, String) onOpen;
|
||||||
|
final Function(Map<String, dynamic>) onDeleteMiscellaneous;
|
||||||
|
|
||||||
|
const MiscellaneousListWidget({super.key, required this.miscellaneousList, required this.onOpen,
|
||||||
|
required this.onDeleteMiscellaneous});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -27,10 +33,10 @@ class MiscellaneousListWidget extends StatelessWidget {
|
|||||||
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
||||||
),
|
),
|
||||||
columns: const [
|
columns: const [
|
||||||
DataColumn(label: Text('Trip Type')),
|
DataColumn(label: Text('#')),
|
||||||
DataColumn(label: Text('Class')),
|
DataColumn(label: Text('Special Request')),
|
||||||
DataColumn(label: Text('From')),
|
DataColumn(label: Text('Comments')),
|
||||||
DataColumn(label: Text('To')),
|
DataColumn(label: Text('Created On')),
|
||||||
DataColumn(label: Text('Actions')),
|
DataColumn(label: Text('Actions')),
|
||||||
],
|
],
|
||||||
rows: _buildDataRows(),
|
rows: _buildDataRows(),
|
||||||
@ -45,17 +51,17 @@ class MiscellaneousListWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<DataRow> _buildDataRows() {
|
List<DataRow> _buildDataRows() {
|
||||||
List<Map<String, String>> data = [
|
print("miscellaneousList - $miscellaneousList");
|
||||||
{"tripType": "One-Way", "class": "Economy", "from": "NYC", "to": "LA"},
|
|
||||||
{"tripType": "Round-Trip", "class": "Business", "from": "SF", "to": "Seattle"},
|
|
||||||
];
|
|
||||||
|
|
||||||
return data.map((bus) {
|
return miscellaneousList.asMap().entries.map( (entry) {
|
||||||
|
int index = entry.key + 1; // To start index from 1
|
||||||
|
Map<String, dynamic> item = entry.value;
|
||||||
|
print(item);
|
||||||
return DataRow(cells: [
|
return DataRow(cells: [
|
||||||
DataCell(Text(bus["tripType"]!)),
|
DataCell(Text(item["indx"]?.toString() ?? "N/A")), // Index column
|
||||||
DataCell(Text(bus["class"]!)),
|
DataCell(Text(item["special_request"] ?? "N/A")),
|
||||||
DataCell(Text(bus["from"]!)),
|
DataCell(Text(item["comments"] ?? "N/A")),
|
||||||
DataCell(Text(bus["to"]!)),
|
DataCell(Text(item["created_on"] ?? "N/A")),
|
||||||
DataCell(Row(
|
DataCell(Row(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
@ -67,12 +73,14 @@ class MiscellaneousListWidget extends StatelessWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.edit, color: Colors.green),
|
icon: Icon(Icons.edit, color: Colors.green),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
onOpen(true, item, "Miscellaneous");
|
||||||
// Edit action
|
// Edit action
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.delete, color: Colors.red),
|
icon: Icon(Icons.delete, color: Colors.red),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
onDeleteMiscellaneous(item);
|
||||||
// Delete action
|
// Delete action
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class TaxiListWidget extends StatelessWidget {
|
class TaxiListWidget extends StatelessWidget {
|
||||||
const TaxiListWidget({super.key});
|
final List<Map<String,dynamic>> taxiList;
|
||||||
|
final Function(bool, Map<String,dynamic>, String) onOpen;
|
||||||
|
final Function(Map<String,dynamic>) onDeleteTaxi;
|
||||||
|
|
||||||
|
const TaxiListWidget({super.key, required this.taxiList, required this.onOpen, required this.onDeleteTaxi});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -26,10 +30,11 @@ class TaxiListWidget extends StatelessWidget {
|
|||||||
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
||||||
),
|
),
|
||||||
columns: const [
|
columns: const [
|
||||||
DataColumn(label: Text('Trip Type')),
|
DataColumn(label: Text('#')),
|
||||||
DataColumn(label: Text('Class')),
|
DataColumn(label: Text('Destination')),
|
||||||
DataColumn(label: Text('From')),
|
DataColumn(label: Text('Location Of Pickup')),
|
||||||
DataColumn(label: Text('To')),
|
DataColumn(label: Text('Date')),
|
||||||
|
DataColumn(label: Text('Taxi Required For')),
|
||||||
DataColumn(label: Text('Actions')),
|
DataColumn(label: Text('Actions')),
|
||||||
],
|
],
|
||||||
rows: _buildDataRows(),
|
rows: _buildDataRows(),
|
||||||
@ -43,17 +48,18 @@ class TaxiListWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<DataRow> _buildDataRows() {
|
List<DataRow> _buildDataRows() {
|
||||||
List<Map<String, String>> data = [
|
|
||||||
{"tripType": "One-Way", "class": "Economy", "from": "NYC", "to": "LA"},
|
|
||||||
{"tripType": "Round-Trip", "class": "Business", "from": "SF", "to": "Seattle"},
|
|
||||||
];
|
|
||||||
|
|
||||||
return data.map((bus) {
|
|
||||||
|
return taxiList.asMap().entries.map((entry) {
|
||||||
|
|
||||||
|
final Map<String, dynamic> item = entry.value;
|
||||||
|
|
||||||
return DataRow(cells: [
|
return DataRow(cells: [
|
||||||
DataCell(Text(bus["tripType"]!)),
|
DataCell(Text(item["indx"]?.toString() ?? "N/A")), // Index column
|
||||||
DataCell(Text(bus["class"]!)),
|
DataCell(Text(item["destination_city"]!)),
|
||||||
DataCell(Text(bus["from"]!)),
|
DataCell(Text(item["location_of_pickup"]!)),
|
||||||
DataCell(Text(bus["to"]!)),
|
DataCell(Text(item["date"]!)),
|
||||||
|
DataCell(Text(item["car_required_for"]!)),
|
||||||
DataCell(Row(
|
DataCell(Row(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
@ -65,13 +71,13 @@ class TaxiListWidget extends StatelessWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.edit, color: Colors.green),
|
icon: Icon(Icons.edit, color: Colors.green),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Edit action
|
onOpen(true, item, "Taxi");
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.delete, color: Colors.red),
|
icon: Icon(Icons.delete, color: Colors.red),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Delete action
|
onDeleteTaxi(item);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class TrainListWidget extends StatelessWidget {
|
class TrainListWidget extends StatelessWidget {
|
||||||
const TrainListWidget({super.key});
|
final List<Map<String,dynamic>> trainList;
|
||||||
|
final Function(bool, Map<String,dynamic>, String) onOpen;
|
||||||
|
final Function(Map<String,dynamic>) onDeleteTrain;
|
||||||
|
const TrainListWidget({super.key, required this.trainList, required this.onOpen, required this.onDeleteTrain});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -27,7 +30,8 @@ class TrainListWidget extends StatelessWidget {
|
|||||||
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
||||||
),
|
),
|
||||||
columns: const [
|
columns: const [
|
||||||
DataColumn(label: Text('Trip Type')),
|
DataColumn(label: Text('#')),
|
||||||
|
DataColumn(label: Text('Train Number')),
|
||||||
DataColumn(label: Text('Class')),
|
DataColumn(label: Text('Class')),
|
||||||
DataColumn(label: Text('From')),
|
DataColumn(label: Text('From')),
|
||||||
DataColumn(label: Text('To')),
|
DataColumn(label: Text('To')),
|
||||||
@ -45,17 +49,17 @@ class TrainListWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<DataRow> _buildDataRows() {
|
List<DataRow> _buildDataRows() {
|
||||||
List<Map<String, String>> data = [
|
|
||||||
{"tripType": "One-Way", "class": "Economy", "from": "NYC", "to": "LA"},
|
|
||||||
{"tripType": "Round-Trip", "class": "Business", "from": "SF", "to": "Seattle"},
|
|
||||||
];
|
|
||||||
|
|
||||||
return data.map((bus) {
|
|
||||||
|
return trainList.asMap().entries.map((entry) {
|
||||||
|
final Map<String,dynamic> item = entry.value;
|
||||||
|
|
||||||
return DataRow(cells: [
|
return DataRow(cells: [
|
||||||
DataCell(Text(bus["tripType"]!)),
|
DataCell(Text(item["indx"]?.toString() ?? "N/A")),
|
||||||
DataCell(Text(bus["class"]!)),
|
DataCell(Text(item["train_no"]!)),
|
||||||
DataCell(Text(bus["from"]!)),
|
DataCell(Text(item["class"]!)),
|
||||||
DataCell(Text(bus["to"]!)),
|
DataCell(Text(item["from"]!)),
|
||||||
|
DataCell(Text(item["to"]!)),
|
||||||
DataCell(Row(
|
DataCell(Row(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
@ -67,13 +71,13 @@ class TrainListWidget extends StatelessWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.edit, color: Colors.green),
|
icon: Icon(Icons.edit, color: Colors.green),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Edit action
|
onOpen(true, item, "Train");
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.delete, color: Colors.red),
|
icon: Icon(Icons.delete, color: Colors.red),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Delete action
|
onDeleteTrain(item);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class VisaListWidget extends StatelessWidget {
|
class VisaListWidget extends StatelessWidget {
|
||||||
const VisaListWidget({super.key});
|
final List<Map<String, dynamic>> visaList;
|
||||||
|
final Function(bool, Map<String, dynamic>, String) onOpen;
|
||||||
|
final Function(Map<String, dynamic>) onDeleteMiscellaneous;
|
||||||
|
|
||||||
|
const VisaListWidget({super.key, required this.visaList, required this.onOpen,required this.onDeleteMiscellaneous});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -27,10 +31,10 @@ class VisaListWidget extends StatelessWidget {
|
|||||||
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines
|
||||||
),
|
),
|
||||||
columns: const [
|
columns: const [
|
||||||
DataColumn(label: Text('Trip Type')),
|
DataColumn(label: Text('#')),
|
||||||
DataColumn(label: Text('Class')),
|
DataColumn(label: Text('Type of Visa')),
|
||||||
DataColumn(label: Text('From')),
|
DataColumn(label: Text('Country')),
|
||||||
DataColumn(label: Text('To')),
|
DataColumn(label: Text('Start Date')),
|
||||||
DataColumn(label: Text('Actions')),
|
DataColumn(label: Text('Actions')),
|
||||||
],
|
],
|
||||||
rows: _buildDataRows(),
|
rows: _buildDataRows(),
|
||||||
@ -45,17 +49,17 @@ class VisaListWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<DataRow> _buildDataRows() {
|
List<DataRow> _buildDataRows() {
|
||||||
List<Map<String, String>> data = [
|
|
||||||
{"tripType": "One-Way", "class": "Economy", "from": "NYC", "to": "LA"},
|
|
||||||
{"tripType": "Round-Trip", "class": "Business", "from": "SF", "to": "Seattle"},
|
|
||||||
];
|
|
||||||
|
|
||||||
return data.map((bus) {
|
return visaList.asMap().entries.map((entry){
|
||||||
|
|
||||||
|
int index = entry.key + 1; // To start index from 1
|
||||||
|
Map<String, dynamic> item = entry.value;
|
||||||
|
print(item);
|
||||||
return DataRow(cells: [
|
return DataRow(cells: [
|
||||||
DataCell(Text(bus["tripType"]!)),
|
DataCell(Text(item["indx"]?.toString() ?? "N/A")),
|
||||||
DataCell(Text(bus["class"]!)),
|
DataCell(Text(item["type_of_visa"]!)),
|
||||||
DataCell(Text(bus["from"]!)),
|
DataCell(Text(item["country"]!)),
|
||||||
DataCell(Text(bus["to"]!)),
|
DataCell(Text(item["start_date"]!)),
|
||||||
DataCell(Row(
|
DataCell(Row(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
@ -67,13 +71,13 @@ class VisaListWidget extends StatelessWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.edit, color: Colors.green),
|
icon: Icon(Icons.edit, color: Colors.green),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Edit action
|
onOpen(true, item, "Visa");
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.delete, color: Colors.red),
|
icon: Icon(Icons.delete, color: Colors.red),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Delete action
|
onDeleteMiscellaneous(item);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import '../../config/apiUrl.dart';
|
|||||||
import '../../data/models/plan.dart';
|
import '../../data/models/plan.dart';
|
||||||
import '../../routes/custom_appBar.dart';
|
import '../../routes/custom_appBar.dart';
|
||||||
import '../../routes/custom_drawer.dart';
|
import '../../routes/custom_drawer.dart';
|
||||||
|
import '../../widgets/custom_radio_button.dart';
|
||||||
import '../../widgets/custom_text_field.dart';
|
import '../../widgets/custom_text_field.dart';
|
||||||
import '../dialog/user_selection_dialog.dart';
|
import '../dialog/user_selection_dialog.dart';
|
||||||
|
|
||||||
@ -90,36 +91,190 @@ class CreateNewPlan extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _CreateNewPlansState extends State<CreateNewPlan> {
|
class _CreateNewPlansState extends State<CreateNewPlan> {
|
||||||
final FocusNode _textFieldFocusNode = FocusNode(); // Declare FocusNode
|
|
||||||
bool _isTextFieldFocused = false;
|
final TextEditingController _tripTitleController = TextEditingController();
|
||||||
|
final TextEditingController _descriptionController = TextEditingController();
|
||||||
|
|
||||||
|
final FocusNode _tripTitleFocusNode = FocusNode();
|
||||||
|
final FocusNode _descriptionFocusNode = FocusNode(); // Declare FocusNode
|
||||||
|
|
||||||
|
bool _isTripTitleFocused = false;
|
||||||
|
bool _isdescriptionFocused = false;
|
||||||
late String _selectedOption = "Option 1";
|
late String _selectedOption = "Option 1";
|
||||||
late String? _selectedIsBillable = "Billable";
|
// late String? _selectedIsBillable = "Billable";
|
||||||
Map<String, dynamic>? storedData;
|
|
||||||
|
|
||||||
|
String? userDetails;
|
||||||
|
String? userName;
|
||||||
|
String? selfId;
|
||||||
|
String? otherUserName;
|
||||||
|
String? selectedplanUserId;
|
||||||
|
bool? selectedIstravelUser;
|
||||||
|
|
||||||
Map<String, dynamic>? apiData; // Store API response here
|
Map<String, dynamic>? apiData; // Store API response here
|
||||||
|
List<dynamic>? apiCountryData;
|
||||||
|
List<dynamic>? apiCostData; // Store API response here
|
||||||
bool isLoading = true; // Track loading state
|
bool isLoading = true; // Track loading state
|
||||||
|
|
||||||
|
String? planUsrId;
|
||||||
|
String? planTravlrId;
|
||||||
|
String? _selectedTripType;
|
||||||
|
String? selectedCostCenterId;
|
||||||
|
String? _selectedIsBillable ;
|
||||||
|
String? selectedFuncDept;
|
||||||
|
String? selectedPurpose;
|
||||||
|
|
||||||
|
Map<String, String?> validationErrors = {};
|
||||||
|
List<Map<String, dynamic>> miscellaneousList = [];
|
||||||
|
// List<Map<String, dynamic>> miscellaneousList = [{"special_request": 1, "comments": "posta", "indx": 1}];
|
||||||
|
List<Map<String, dynamic>> trainList = [];
|
||||||
|
List<Map<String, dynamic>> busList = [];
|
||||||
|
List<Map<String, dynamic>> taxiList = [];
|
||||||
|
|
||||||
|
//Getter Method
|
||||||
|
Map<String, dynamic> get planData => {
|
||||||
|
"user_id": planUsrId,
|
||||||
|
"traveller_id": planTravlrId,
|
||||||
|
"trip_title": _tripTitleController.text,
|
||||||
|
"trip_type": _selectedTripType,
|
||||||
|
"cost_center_id": selectedCostCenterId,
|
||||||
|
"is_billable": _selectedIsBillable,
|
||||||
|
"purpose_of_travel": selectedPurpose,
|
||||||
|
"description": _descriptionController.text,
|
||||||
|
"functional_department": selectedFuncDept,
|
||||||
|
"so_number": "12345",
|
||||||
|
"status": "0",
|
||||||
|
// "created_on": "2025-02-10 14:38:21",
|
||||||
|
"created_by": selfId,
|
||||||
|
// "updated_on": null,
|
||||||
|
"updated_by": null,
|
||||||
|
"is_active": "1",
|
||||||
|
"flight":[],
|
||||||
|
"accommodation": [],
|
||||||
|
"bus": [],
|
||||||
|
"insurance": [],
|
||||||
|
"miscellaneous": miscellaneousList,
|
||||||
|
"taxi": [],
|
||||||
|
"train": [],
|
||||||
|
"visa": [],
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Function to update miscellaneous list
|
||||||
|
void updateMiscellaneousData(List<Map<String, dynamic>> newMiscellaneousList) {
|
||||||
|
setState(() {
|
||||||
|
miscellaneousList = newMiscellaneousList; // Update miscellaneous data
|
||||||
|
});
|
||||||
|
print("Updated Miscellaneous Data in CreateNewPlan: $miscellaneousList");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleItineraryUpdate(String type, List<Map<String, dynamic>> newList) {
|
||||||
|
setState(() {
|
||||||
|
switch (type) {
|
||||||
|
case "Miscellaneous":
|
||||||
|
miscellaneousList = newList;
|
||||||
|
break;
|
||||||
|
case "Train":
|
||||||
|
trainList = newList;
|
||||||
|
break;
|
||||||
|
case "Bus":
|
||||||
|
busList = newList;
|
||||||
|
break;
|
||||||
|
case "Taxi":
|
||||||
|
taxiList = newList;
|
||||||
|
break;
|
||||||
|
case "Forex":
|
||||||
|
taxiList = newList;
|
||||||
|
break;
|
||||||
|
case "Accommodation":
|
||||||
|
taxiList = newList;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
print("Unknown itinerary type: $type");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
print("Updated $type List: $newList");
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState(){
|
||||||
super.initState();
|
super.initState();
|
||||||
fetchPlans();
|
fetchUserDetails();
|
||||||
|
|
||||||
_textFieldFocusNode.addListener(() {
|
fetchPlans();
|
||||||
|
fetchCostCenter();
|
||||||
|
fetchCountryList();
|
||||||
|
|
||||||
|
// _tripTitleController.addListener(() {
|
||||||
|
// print("Current Value: ${_tripTitleController.text}");
|
||||||
|
// });
|
||||||
|
|
||||||
|
_tripTitleFocusNode.addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isTextFieldFocused = _textFieldFocusNode.hasFocus;
|
_isTripTitleFocused = _tripTitleFocusNode.hasFocus;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_descriptionFocusNode.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
_isdescriptionFocused = _descriptionFocusNode.hasFocus;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_textFieldFocusNode.dispose();
|
_tripTitleFocusNode.dispose();
|
||||||
|
_descriptionFocusNode.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void getSelectedPlanFor(){
|
||||||
|
if (!mounted) return;
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
if(selectedplanUserId != null){
|
||||||
|
|
||||||
|
if(selectedIstravelUser!){
|
||||||
|
planUsrId = "";
|
||||||
|
planTravlrId = selectedplanUserId;
|
||||||
|
}else {
|
||||||
|
planUsrId = selectedplanUserId;
|
||||||
|
planTravlrId = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
planUsrId = selfId;
|
||||||
|
planTravlrId = "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
print("USER ID - $planUsrId , TRAVELLER ID - $planTravlrId");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void fetchUserDetails() async {
|
||||||
|
final details = await getUserDetails();
|
||||||
|
|
||||||
|
print("details- $details");
|
||||||
|
|
||||||
|
|
||||||
|
if (details != null) {
|
||||||
|
setState(() {
|
||||||
|
userDetails = details.toString(); // Store the full Map
|
||||||
|
userName = details['name']; // Extract the name
|
||||||
|
selfId = details['user_id'];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
print("userDetails - $selfId");
|
||||||
|
getSelectedPlanFor();
|
||||||
|
}
|
||||||
|
|
||||||
Future<String?> getToken() async {
|
Future<String?> getToken() async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
@ -132,7 +287,20 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
return prefs.getString('userId');
|
return prefs.getString('userId');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future <Map<String,String>?> getUserDetails() async{
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
final userData = prefs.getString('user_data');
|
||||||
|
|
||||||
|
if(userData!= null){
|
||||||
|
final decodedData = jsonDecode(userData);
|
||||||
|
|
||||||
|
return {
|
||||||
|
'user_id': decodedData['user_id'].toString(),
|
||||||
|
'name': "${decodedData['first_name']} ${decodedData['last_name']}",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> fetchPlans() async {
|
Future<void> fetchPlans() async {
|
||||||
@ -167,7 +335,7 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
|
|
||||||
Map<String, dynamic> plansJson = data['data']; // 'data' is a Map, not a List
|
Map<String, dynamic> plansJson = data['data']; // 'data' is a Map, not a List
|
||||||
setState(() {
|
setState(() {
|
||||||
apiData = data['data']; // Store API response in state
|
apiData = plansJson; // Store API response in state
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -180,22 +348,176 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> fetchCostCenter() async {
|
||||||
|
final String apiUrldata = '$apiUrl/api/getCostCenterMaster';
|
||||||
|
|
||||||
|
final token = await getToken();
|
||||||
|
|
||||||
Future<void> getStoredData() async {
|
// final userId = await getUserId();
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
||||||
String? jsonString = prefs.getString('api_response');
|
|
||||||
|
|
||||||
if (jsonString != null) {
|
// print("SUSRTRT- $userId");
|
||||||
storedData = json.decode(jsonString);
|
//
|
||||||
print('Stored Data: $storedData');
|
if (token == null) {
|
||||||
} else {
|
throw Exception('Token not found. Please log in.');
|
||||||
storedData = null;
|
}
|
||||||
|
|
||||||
|
final response = await http.get(
|
||||||
|
Uri.parse(apiUrldata),
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer $token',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
try {
|
||||||
|
final data = json.decode(response.body);
|
||||||
|
print(data);
|
||||||
|
|
||||||
|
if (!data.containsKey('data') || data['data'] is!List) {
|
||||||
|
throw Exception("Invalid response format: 'data' field is missing or not a List");
|
||||||
|
}
|
||||||
|
|
||||||
|
List <dynamic> plansJson = data['data']; // 'data' is a Map, not a List
|
||||||
|
setState(() {
|
||||||
|
apiCostData = plansJson; // Store API response in state
|
||||||
|
if(apiCostData!.isNotEmpty){
|
||||||
|
selectedCostCenterId =apiCostData?.first['department_id'];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
print('plansJSON');
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
throw Exception('Error parsing response: $e');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw Exception('Failed to load plans');
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Future<void> fetchCountryList() async {
|
||||||
|
final String apiUrldata = '$apiUrl/api/getcountryMaster';
|
||||||
|
|
||||||
|
final token = await getToken();
|
||||||
|
|
||||||
|
// final userId = await getUserId();
|
||||||
|
|
||||||
|
// print("SUSRTRT- $userId");
|
||||||
|
//
|
||||||
|
if (token == null) {
|
||||||
|
throw Exception('Token not found. Please log in.');
|
||||||
|
}
|
||||||
|
|
||||||
|
final response = await http.get(
|
||||||
|
Uri.parse(apiUrldata),
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer $token',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
try {
|
||||||
|
final data = json.decode(response.body);
|
||||||
|
print("Country - $data");
|
||||||
|
|
||||||
|
if (!data.containsKey('data') || data['data'] is!List) {
|
||||||
|
throw Exception("Invalid response format: 'data' field is missing or not a List");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
List <dynamic> plansJson = data['data']; // 'data' is a Map, not a List
|
||||||
|
|
||||||
|
if (data['data'] is List) {
|
||||||
|
List<dynamic> plansJson = data['data'];
|
||||||
|
print("plansJson.length - ${plansJson.length}");
|
||||||
|
} else {
|
||||||
|
print("The 'data' key does not contain a list.");
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
apiCountryData = plansJson; // Store API response in state
|
||||||
|
|
||||||
|
});
|
||||||
|
print('plansJSONContry - $plansJson');
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
throw Exception('Error parsing response: $e');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw Exception('Failed to load plans');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle Submit
|
||||||
|
|
||||||
|
bool validateForm(){
|
||||||
|
validationErrors.clear(); // Clear previous errors
|
||||||
|
|
||||||
|
// Ensure either "user_id" or "traveller_id" is provided
|
||||||
|
if ((planUsrId == null || planUsrId!.isEmpty) && (planTravlrId == null || planTravlrId!.isEmpty)) {
|
||||||
|
validationErrors["user_id"] = "Either User ID or Traveller ID is required";
|
||||||
|
validationErrors["traveller_id"] = "Either User ID or Traveller ID is required";
|
||||||
|
}
|
||||||
|
|
||||||
|
final requiredFields = {
|
||||||
|
"trip_type": _selectedTripType,
|
||||||
|
"cost_center_id": selectedCostCenterId,
|
||||||
|
"functional_department": selectedFuncDept,
|
||||||
|
"purpose_of_travel": selectedPurpose,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var entry in requiredFields.entries) {
|
||||||
|
if (entry.value == null || entry.value!.isEmpty) {
|
||||||
|
validationErrors[entry.key] = "${entry.key.replaceAll('_', ' ').toUpperCase()} is required";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return validationErrors.isEmpty; // Returns true if no errors
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleSubmit() {
|
||||||
|
setState(() {
|
||||||
|
if(validateForm()){
|
||||||
|
print("Form submitted successfully: $planData");
|
||||||
|
postPlanData(planData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> postPlanData(Map<String, dynamic> planData) async {
|
||||||
|
final String apiUrldata = '$apiUrl/api/plans/createOrEditPlan';
|
||||||
|
final token = await getToken(); // Fetch token
|
||||||
|
|
||||||
|
if (token == null) {
|
||||||
|
throw Exception('Token not found. Please log in.');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await http.post(
|
||||||
|
Uri.parse(apiUrldata),
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer $token',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: jsonEncode(planData), // Convert map to JSON
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
print("Plan submitted successfully!");
|
||||||
|
print("Response: ${response.body}");
|
||||||
|
} else {
|
||||||
|
print("Failed to submit plan. Status: ${response.statusCode}");
|
||||||
|
print("Error: ${response.body}");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print(" Error submitting plan: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
return ResponsiveBuilder(builder: (context, sizingInfo) {
|
||||||
bool isMobile = sizingInfo.isMobile;
|
bool isMobile = sizingInfo.isMobile;
|
||||||
@ -210,14 +532,36 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
// Text(
|
||||||
"Plan This Trip For", // Your label
|
// "Plan This Trip For : ${userName} ", // Your label
|
||||||
style: TextStyle(
|
// style: TextStyle(
|
||||||
|
// fontSize: 12,
|
||||||
|
// fontWeight: FontWeight.w600,
|
||||||
|
// color: Color(0xFF575A74)),
|
||||||
|
// ),
|
||||||
|
|
||||||
|
Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
text: "Plan This Trip For: ", // Static text
|
||||||
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74), // Default color
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: otherUserName ?? userName ?? " ", // Dynamic username
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Colors.blueAccent, // Change this to any color
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
|
||||||
|
SizedBox(height: 7),
|
||||||
isMobile
|
isMobile
|
||||||
? SingleChildScrollView(
|
? SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
@ -254,12 +598,13 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: _isTextFieldFocused,
|
isFocused: _isTripTitleFocused,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _textFieldFocusNode,
|
focusNode: _tripTitleFocusNode,
|
||||||
|
controller: _tripTitleController,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: "Trip Title",
|
labelText: "Trip Title",
|
||||||
@ -285,7 +630,7 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Trip Type", // Your label
|
"Trip Type *", // Your label
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@ -302,6 +647,14 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
: Row(
|
: Row(
|
||||||
children: _buildTripType(isMobile),
|
children: _buildTripType(isMobile),
|
||||||
),
|
),
|
||||||
|
if (validationErrors["trip_type"] != null)
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 4),
|
||||||
|
child: Text(
|
||||||
|
validationErrors["trip_type"]!,
|
||||||
|
style: TextStyle(color: Colors.red, fontSize: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -336,6 +689,8 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
_buildNonDescriptionColumn(),
|
_buildNonDescriptionColumn(),
|
||||||
SizedBox(height: 15),
|
SizedBox(height: 15),
|
||||||
_buildDescriptionColumn(isDesktop),
|
_buildDescriptionColumn(isDesktop),
|
||||||
|
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -349,10 +704,19 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
|
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: DynamicItinerary(apiData: apiData)), // Wrap with Expanded if needed
|
Expanded(child: DynamicItinerary(apiData: apiData, apiCountryData: apiCountryData,
|
||||||
|
onItineraryUpdate: handleItineraryUpdate,
|
||||||
|
)), // Wrap with Expanded if needed
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
SizedBox(height: 15),
|
||||||
|
isDesktop
|
||||||
|
? Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: _buildSubmit(isDesktop),)
|
||||||
|
:Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: _buildSubmit(isDesktop),)
|
||||||
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -362,6 +726,9 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
|
|
||||||
/// Extracted helper function
|
/// Extracted helper function
|
||||||
List<Widget> _buildCostIsBillable() {
|
List<Widget> _buildCostIsBillable() {
|
||||||
|
|
||||||
|
List<dynamic> purposeList = apiData?['plan_is_billable'] ?? [];
|
||||||
|
|
||||||
return [
|
return [
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -380,72 +747,114 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 45, // Set appropriate height
|
height: 45, // Set appropriate height
|
||||||
child: DropdownButtonFormField<String>(
|
child: DropdownButtonFormField<String>(
|
||||||
value: "Option 1",
|
value: selectedCostCenterId,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding:
|
contentPadding:
|
||||||
EdgeInsets.symmetric(horizontal: 10), // Proper padding
|
EdgeInsets.symmetric(horizontal: 10), // Proper padding
|
||||||
),
|
),
|
||||||
onChanged: (newValue) {},
|
onChanged: (newValue) {
|
||||||
items: [
|
setState(() {
|
||||||
DropdownMenuItem(value: "Option 1", child: Text("Option 1")),
|
selectedCostCenterId = newValue;
|
||||||
DropdownMenuItem(value: "Option 2", child: Text("Option 2")),
|
});
|
||||||
],
|
},
|
||||||
|
items:apiCostData?.map<DropdownMenuItem<String>>((item){
|
||||||
|
return DropdownMenuItem(
|
||||||
|
value: item['department_id'], // ID as value
|
||||||
|
child: Text(item['name'] ?? "Unknown"),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(width: 25),
|
|
||||||
|
SizedBox(width: 25,height: 5,),
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Is Billable ", // Your label
|
"Is Billable ", // Your label
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF575A74)),
|
color: Color(0xFF575A74)),
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: purposeList.map<Widget>((item) {
|
||||||
Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Radio<String>(
|
Radio<String>(
|
||||||
value: "Billable",
|
value: item['dropdown_key'], // Use dropdown_value as value
|
||||||
groupValue: _selectedIsBillable,
|
groupValue: _selectedIsBillable,
|
||||||
activeColor: Colors.blueAccent,
|
activeColor: Colors.blueAccent,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedIsBillable = value;
|
_selectedIsBillable = value;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Text("Billable"),
|
Text(item['dropdown_value'] ?? ''), // Display dropdown_value
|
||||||
],
|
SizedBox(width: 20), // Spacing
|
||||||
),
|
],
|
||||||
SizedBox(width: 20), // Spacing
|
);
|
||||||
Row(
|
}).toList(),
|
||||||
children: [
|
),
|
||||||
Radio<String>(
|
|
||||||
value: "Non Billable",
|
])
|
||||||
groupValue: _selectedIsBillable,
|
// Column(
|
||||||
activeColor: Colors.blueAccent,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
onChanged: (value) {
|
// children: [
|
||||||
setState(() {
|
// Text(
|
||||||
_selectedIsBillable = value;
|
// "Is Billable ", // Your label
|
||||||
});
|
// style: TextStyle(
|
||||||
},
|
// fontSize: 12,
|
||||||
),
|
// fontWeight: FontWeight.w600,
|
||||||
Text("Non Billable"),
|
// color: Color(0xFF575A74)),
|
||||||
],
|
// ),
|
||||||
),
|
// SizedBox(height: 5),
|
||||||
],
|
// Row(
|
||||||
),
|
// children: [
|
||||||
],
|
// Row(
|
||||||
)
|
// children: [
|
||||||
|
// Radio<String>(
|
||||||
|
// value: "Billable",
|
||||||
|
// groupValue: _selectedIsBillable,
|
||||||
|
// activeColor: Colors.blueAccent,
|
||||||
|
// onChanged: (value) {
|
||||||
|
// setState(() {
|
||||||
|
// _selectedIsBillable = value;
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// Text("Billable"),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// SizedBox(width: 20), // Spacing
|
||||||
|
// Row(
|
||||||
|
// children: [
|
||||||
|
// Radio<String>(
|
||||||
|
// value: "Non Billable",
|
||||||
|
// groupValue: _selectedIsBillable,
|
||||||
|
// activeColor: Colors.blueAccent,
|
||||||
|
// onChanged: (value) {
|
||||||
|
// setState(() {
|
||||||
|
// _selectedIsBillable = value;
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// Text("Non Billable"),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// )
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,11 +899,12 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
|
|
||||||
List<Widget> _buildTripType(bool isMobile) {
|
List<Widget> _buildTripType(bool isMobile) {
|
||||||
return [
|
return [
|
||||||
|
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
color: Color(0xFFF4F4FB),
|
color: Color(0xFFF4F4FB),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
||||||
width: 120,
|
width: 120,
|
||||||
isFocused: _selectedOption == "Option 1",
|
isFocused: _selectedTripType == "1",
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 35,
|
height: 35,
|
||||||
@ -506,11 +916,11 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
dense: true,
|
dense: true,
|
||||||
title: Text("Domestic"),
|
title: Text("Domestic"),
|
||||||
value: "Option 1",
|
value: "1",
|
||||||
groupValue: _selectedOption,
|
groupValue: _selectedTripType,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedOption = value!;
|
_selectedTripType = value!;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -522,22 +932,24 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
color: Color(0xFFF4F4FB),
|
color: Color(0xFFF4F4FB),
|
||||||
width: 150,
|
width: 150,
|
||||||
padding: EdgeInsets.symmetric(horizontal: 5, vertical: 2),
|
padding: EdgeInsets.symmetric(horizontal: 5, vertical: 2),
|
||||||
isFocused: _selectedOption == "Option 2",
|
isFocused: _selectedTripType == "2",
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: RadioListTile<String>(
|
child: RadioListTile<String>(
|
||||||
activeColor: Colors.blueAccent,
|
activeColor: Colors.blueAccent,
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
dense: true,
|
dense: true,
|
||||||
title: Text("International"),
|
title: Text("International"),
|
||||||
value: "Option 2",
|
value: "2",
|
||||||
groupValue: _selectedOption,
|
groupValue: _selectedTripType,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedOption = value!;
|
_selectedTripType = value!;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,11 +958,11 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
|
|
||||||
// 'plan_purpose_of_travel' Starts ------------------------------------------------------
|
// 'plan_purpose_of_travel' Starts ------------------------------------------------------
|
||||||
|
|
||||||
List<dynamic> purposeList = apiData?['plan_purpose_of_travel'] ?? [];
|
List<dynamic> purposeList = apiData?['plan_purpose_of_travel'] ?? [];
|
||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
List<DropdownMenuItem<String>> dropdownItems = purposeList
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
.map((item)=>DropdownMenuItem<String>(
|
||||||
value: item['dropdown_value'],
|
value: item['dropdown_key'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
)).toList();
|
)).toList();
|
||||||
|
|
||||||
@ -564,7 +976,7 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default selected value
|
// Default selected value
|
||||||
String? selectedPurpose = dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
selectedPurpose ??= dropdownItems.isNotEmpty ? dropdownItems.first.value : null;
|
||||||
|
|
||||||
// 'plan_functional_department' Starts ---------------------------------------------
|
// 'plan_functional_department' Starts ---------------------------------------------
|
||||||
|
|
||||||
@ -572,7 +984,7 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
|
|
||||||
List<DropdownMenuItem<String>> dropdownFuncDeptItems = funcDeptList
|
List<DropdownMenuItem<String>> dropdownFuncDeptItems = funcDeptList
|
||||||
.map((item)=>DropdownMenuItem<String>(
|
.map((item)=>DropdownMenuItem<String>(
|
||||||
value: item['dropdown_value'],
|
value: item['dropdown_key'],
|
||||||
child: Text(item['dropdown_value']),
|
child: Text(item['dropdown_value']),
|
||||||
)).toList();
|
)).toList();
|
||||||
|
|
||||||
@ -586,7 +998,7 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default selected value
|
// Default selected value
|
||||||
String? selectedFuncDept = dropdownFuncDeptItems.isNotEmpty ? dropdownFuncDeptItems.first.value : null;
|
selectedFuncDept ??= dropdownFuncDeptItems.isNotEmpty ? dropdownFuncDeptItems.first.value : null;
|
||||||
// 'plan_functional_department' End
|
// 'plan_functional_department' End
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
@ -661,7 +1073,7 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: 10), // Proper padding
|
horizontal: 10), // Proper padding
|
||||||
),
|
),
|
||||||
onChanged: purposeList.isNotEmpty
|
onChanged: funcDeptList.isNotEmpty
|
||||||
? (newValue) {
|
? (newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedFuncDept = newValue;
|
selectedFuncDept = newValue;
|
||||||
@ -701,12 +1113,13 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
CustomTextFieldWrapper(
|
CustomTextFieldWrapper(
|
||||||
isFocused: false, // Dropdown doesn't use focus
|
isFocused: _isdescriptionFocused,
|
||||||
width: isDesktop? MediaQuery.of(context).size.width * 0.5 :
|
width: isDesktop? MediaQuery.of(context).size.width * 0.5 :
|
||||||
MediaQuery.of(context).size.width * 0.85 ,
|
MediaQuery.of(context).size.width * 0.85 ,
|
||||||
isDesktop: widget.isDesktop,
|
isDesktop: widget.isDesktop,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: _textFieldFocusNode,
|
focusNode: _descriptionFocusNode,
|
||||||
|
controller: _descriptionController,
|
||||||
maxLines: 6,
|
maxLines: 6,
|
||||||
keyboardType: TextInputType.multiline,
|
keyboardType: TextInputType.multiline,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
@ -727,6 +1140,19 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Widget> _buildSubmit(isDesktop){
|
||||||
|
return[
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: (){},
|
||||||
|
child: Text("Cancel")),
|
||||||
|
SizedBox(width: 20,),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: (){
|
||||||
|
handleSubmit();
|
||||||
|
},
|
||||||
|
child: Text("Submit"))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
void _showInputDialog(String title){
|
void _showInputDialog(String title){
|
||||||
showDialog(
|
showDialog(
|
||||||
@ -734,8 +1160,14 @@ class _CreateNewPlansState extends State<CreateNewPlan> {
|
|||||||
builder: (BuildContext context){
|
builder: (BuildContext context){
|
||||||
return UserSelectionDialog(
|
return UserSelectionDialog(
|
||||||
title:title,
|
title:title,
|
||||||
onSubmit: (input){
|
onSubmit: (input,userId,isTraveller){
|
||||||
print("USer entered : $input");
|
setState(() {
|
||||||
|
otherUserName = input;
|
||||||
|
selectedplanUserId = userId;
|
||||||
|
selectedIstravelUser = isTraveller;
|
||||||
|
});
|
||||||
|
print("USer entered : $otherUserName $userId $isTraveller");
|
||||||
|
getSelectedPlanFor();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,10 @@ import '../itnerary_list/visa_list.dart';
|
|||||||
|
|
||||||
class DynamicItinerary extends StatefulWidget {
|
class DynamicItinerary extends StatefulWidget {
|
||||||
final Map<String, dynamic>? apiData;
|
final Map<String, dynamic>? apiData;
|
||||||
const DynamicItinerary({super.key, required this.apiData});
|
final List<dynamic>? apiCountryData;
|
||||||
|
final Function(String, List<Map<String, dynamic>>) onItineraryUpdate; // Updated Signature
|
||||||
|
const DynamicItinerary({super.key, required this.apiData, required this.onItineraryUpdate, required this.apiCountryData});
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_DynamicItineraryState createState() => _DynamicItineraryState();
|
_DynamicItineraryState createState() => _DynamicItineraryState();
|
||||||
@ -35,6 +38,112 @@ class _DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
String selectedListOption = "";
|
String selectedListOption = "";
|
||||||
|
|
||||||
bool isSelected = false;
|
bool isSelected = false;
|
||||||
|
Map<String, dynamic>? selectedItem;
|
||||||
|
int? selectedIndex;
|
||||||
|
|
||||||
|
// List<Map<String, dynamic>> miscellaneousList = [];
|
||||||
|
|
||||||
|
Map<String, List<Map<String, dynamic>>> itineraryData = {
|
||||||
|
"Train": [{
|
||||||
|
"train_id": "2",
|
||||||
|
"plan_id": "2",
|
||||||
|
"class": "1",
|
||||||
|
"train_no": "OJH65JHB87",
|
||||||
|
"from": "Madurai",
|
||||||
|
"to": "Chennai",
|
||||||
|
"date": "2025-02-02",
|
||||||
|
"comments": "1 st class AC",
|
||||||
|
"created_on": "2025-02-10 14:38:21",
|
||||||
|
"created_by": null,
|
||||||
|
"updated_on": null,
|
||||||
|
"updated_by": null,
|
||||||
|
"is_active": "1"
|
||||||
|
}],
|
||||||
|
"Bus": [{
|
||||||
|
"bus_id": "2",
|
||||||
|
"plan_id": "2",
|
||||||
|
"from": "Chennai - OMR",
|
||||||
|
"to": "Chennai - ECR",
|
||||||
|
"date": "2025-02-15",
|
||||||
|
"time": "12:00:00",
|
||||||
|
"comments": "i need ac bus",
|
||||||
|
"created_on": "2025-02-10 14:38:21",
|
||||||
|
"created_by": null,
|
||||||
|
"updated_on": null,
|
||||||
|
"updated_by": null,
|
||||||
|
"is_active": "1"
|
||||||
|
}],
|
||||||
|
"Taxi": [{
|
||||||
|
"taxi_id": "2",
|
||||||
|
"plan_id": "2",
|
||||||
|
"destination_city": "Madurai",
|
||||||
|
"date": "2025-02-15",
|
||||||
|
"time": "12:00:00",
|
||||||
|
"location_of_pickup": "chennai - ECR",
|
||||||
|
"car_required_for": "1",
|
||||||
|
"no_of_passengers": "2",
|
||||||
|
"car_type": "1",
|
||||||
|
"comments": "Come Sharply",
|
||||||
|
"created_by": "f",
|
||||||
|
"updated_by": "g",
|
||||||
|
"is_active": "1"
|
||||||
|
}],
|
||||||
|
"Miscellaneous": [{
|
||||||
|
"miscellaneous_id": "2",
|
||||||
|
"plan_id": "2",
|
||||||
|
"special_request": "2",
|
||||||
|
"comments": "Please arrange one guide for me ",
|
||||||
|
"created_by": null,
|
||||||
|
"updated_by": null,
|
||||||
|
"is_active": "1"
|
||||||
|
}],
|
||||||
|
"Flight": [],
|
||||||
|
"Accommodation": [{
|
||||||
|
"accomodation_id": "2",
|
||||||
|
"plan_id": "2",
|
||||||
|
"destination_city": "chennai",
|
||||||
|
"hotel_name": "The park",
|
||||||
|
"checkin_date": "2025-02-14",
|
||||||
|
"checkin_time": "03:00:00",
|
||||||
|
"checkout_date": "2025-02-15",
|
||||||
|
"checkout_time": "03:00:00",
|
||||||
|
"comments": "A/c is must",
|
||||||
|
"created_on": "2025-02-10 14:38:21",
|
||||||
|
"created_by": null,
|
||||||
|
"updated_on": null,
|
||||||
|
"updated_by": null,
|
||||||
|
"is_active": "0"
|
||||||
|
}],
|
||||||
|
"Insurance": [{
|
||||||
|
"insurance_id": "2",
|
||||||
|
"plan_id": "2",
|
||||||
|
"start_date": "2025-02-01",
|
||||||
|
"end_date": "2025-02-28",
|
||||||
|
"type_of_insurance": "1",
|
||||||
|
"comments": "Temp insurance",
|
||||||
|
"created_on": "2025-02-10 14:38:21",
|
||||||
|
"created_by": null,
|
||||||
|
"updated_on": null,
|
||||||
|
"updated_by": null,
|
||||||
|
"is_active": "1"
|
||||||
|
}],
|
||||||
|
"Visa": [{
|
||||||
|
"visa_id": "2",
|
||||||
|
"plan_id": "2",
|
||||||
|
"country": "2",
|
||||||
|
// "country_code": "2",
|
||||||
|
"type_of_visa": "2",
|
||||||
|
"start_date": "2025-02-01",
|
||||||
|
"comments": "visa registered",
|
||||||
|
"created_on": "2025-02-10 14:38:21",
|
||||||
|
"created_by": null,
|
||||||
|
"updated_on": null,
|
||||||
|
"updated_by": null,
|
||||||
|
"is_active": "1"
|
||||||
|
}],
|
||||||
|
"Forex": [],
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Store form values for each tab
|
// Store form values for each tab
|
||||||
final Map<String, Map<String, String>> formData = {
|
final Map<String, Map<String, String>> formData = {
|
||||||
@ -51,8 +160,24 @@ class _DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
|
|
||||||
void handleClose(bool value) {
|
void handleClose(bool value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
selectedOption = "";
|
||||||
isSelected = value;
|
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 build(BuildContext context) {
|
||||||
@ -77,30 +202,156 @@ class _DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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");
|
||||||
|
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");
|
||||||
|
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
|
||||||
|
itemList.add(newData);
|
||||||
|
|
||||||
|
print(" Updated $type List: ${itineraryData[type]}");
|
||||||
|
});
|
||||||
|
|
||||||
|
widget.onItineraryUpdate(type, itineraryData[type]!); // Notify parent
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleItinerarydelete(String type, Map<String, dynamic> data){
|
||||||
|
setState(() {
|
||||||
|
if(!itineraryData.containsKey(type)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<String, dynamic>> itemList = itineraryData[type]!;
|
||||||
|
// 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["id"]?.toString() == existingId.toString());
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
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) {
|
switch (selectedListOption) {
|
||||||
case "Train":
|
case "Train":
|
||||||
selectedListWidget = TrainListWidget();
|
selectedListWidget = TrainListWidget( trainList : itineraryData["Train"]!,
|
||||||
|
onOpen: handleEdit,
|
||||||
|
onDeleteTrain: (data)=> handleItinerarydelete("Train", data),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "Taxi":
|
case "Taxi":
|
||||||
selectedListWidget = TaxiListWidget();
|
selectedListWidget = TaxiListWidget( taxiList : itineraryData["Taxi"]! ,
|
||||||
|
onOpen: handleEdit,
|
||||||
|
onDeleteTaxi: (data)=> handleItinerarydelete("Taxi", data),);
|
||||||
break;
|
break;
|
||||||
case "Bus":
|
case "Bus":
|
||||||
selectedListWidget = BusListWidget();
|
selectedListWidget = BusListWidget(busList : itineraryData["Bus"]!,
|
||||||
|
onOpen: handleEdit,
|
||||||
|
onDeleteBus: (data) => handleItinerarydelete("Bus", data),);
|
||||||
break;
|
break;
|
||||||
case "Insurance":
|
case "Insurance":
|
||||||
selectedListWidget = InsuranceListWidget();
|
selectedListWidget = InsuranceListWidget(insuranceList : itineraryData["Insurance"]!,
|
||||||
|
onOpen: handleEdit,
|
||||||
|
onDeleteInsurance:(data) => handleItinerarydelete("Insurance", data),);
|
||||||
break;
|
break;
|
||||||
case "Visa":
|
case "Visa":
|
||||||
selectedListWidget = VisaListWidget();
|
selectedListWidget = VisaListWidget(visaList : itineraryData["Visa"]!,
|
||||||
|
onOpen: handleEdit,
|
||||||
|
onDeleteMiscellaneous: (data) => handleItinerarydelete("Visa", data),);
|
||||||
break;
|
break;
|
||||||
case "Forex":
|
case "Forex":
|
||||||
selectedListWidget = ForexListWidget();
|
selectedListWidget = ForexListWidget(forexList: itineraryData["Forex"]!,
|
||||||
|
onOpen: handleEdit,
|
||||||
|
onDeleteForex: (data) => handleItinerarydelete("Forex", data),);
|
||||||
break;
|
break;
|
||||||
case "Accommodation":
|
case "Accommodation":
|
||||||
selectedListWidget = AccomodationListWidget();
|
selectedListWidget = AccomodationListWidget(accommodationList: itineraryData["Accommodation"]!,
|
||||||
|
onOpen: handleEdit,
|
||||||
|
onDeleteAccommodation:(data) => handleItinerarydelete("Accommodation", data));
|
||||||
break;
|
break;
|
||||||
case "Miscellaneous":
|
case "Miscellaneous":
|
||||||
selectedListWidget = MiscellaneousListWidget();
|
selectedListWidget = MiscellaneousListWidget(miscellaneousList: itineraryData["Miscellaneous"]!,
|
||||||
|
onOpen: handleEdit,
|
||||||
|
onDeleteMiscellaneous: (data) => handleItinerarydelete("Miscellaneous", data),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "Flight":
|
case "Flight":
|
||||||
default:
|
default:
|
||||||
@ -110,29 +361,46 @@ class _DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
|
|
||||||
switch (selectedOption) {
|
switch (selectedOption) {
|
||||||
case "Train":
|
case "Train":
|
||||||
selectedWidget = TrainScreen(onClose: handleClose,formData: formData["Train"]!, updateFormData: updateFormData, apiData: widget.apiData,);
|
selectedWidget = TrainScreen(onClose: handleClose, apiData: widget.apiData,
|
||||||
// selectedWidget = TrainScreen(formData: formData["Train"]!);
|
onSavetrain :(data) => handleItineraryUpdate("Train", data),
|
||||||
|
selectedItem: selectedItem);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "Taxi":
|
case "Taxi":
|
||||||
selectedWidget = TaxiScreen(onClose: handleClose, formData: formData["Taxi"]!, updateFormData: updateFormData, apiData: widget.apiData,);
|
selectedWidget = TaxiScreen(onClose: handleClose,apiData: widget.apiData,
|
||||||
|
onSavetaxi: (data)=> handleItineraryUpdate("Taxi", data),
|
||||||
|
selectedItem: selectedItem);
|
||||||
break;
|
break;
|
||||||
case "Bus":
|
case "Bus":
|
||||||
selectedWidget = BusScreen(onClose: handleClose, formData: formData["Bus"]!, updateFormData: updateFormData, apiData: widget.apiData,);
|
selectedWidget = BusScreen(onClose: handleClose, apiData: widget.apiData,
|
||||||
|
onSaveBus: (data)=> handleItineraryUpdate("Bus", data),
|
||||||
|
selectedItem: selectedItem);
|
||||||
break;
|
break;
|
||||||
case "Insurance":
|
case "Insurance":
|
||||||
selectedWidget = InsuranceScreen(onClose: handleClose, formData: formData["Insurance"]!, updateFormData: updateFormData, apiData: widget.apiData,);
|
selectedWidget = InsuranceScreen(onClose: handleClose, apiData: widget.apiData,
|
||||||
|
onSaveInsurance:(data) => handleItineraryUpdate("Insurance", data),
|
||||||
|
selectedItem: selectedItem);
|
||||||
break;
|
break;
|
||||||
case "Visa":
|
|
||||||
selectedWidget = VisaScreen(onClose: handleClose, formData: formData["Insurance"]!, updateFormData: updateFormData, apiData: widget.apiData,);
|
case "Visa":
|
||||||
break;
|
selectedWidget = VisaScreen(onClose: handleClose,apiData: widget.apiData, apiCountryData : widget.apiCountryData,
|
||||||
|
onSaveVisa: (data) => handleItineraryUpdate("Visa", data),
|
||||||
|
selectedItem: selectedItem,);
|
||||||
|
break;
|
||||||
case "Miscellaneous":
|
case "Miscellaneous":
|
||||||
selectedWidget =MiscellaneousScreen(formData: formData["Miscellaneous"]!, updateFormData: updateFormData, onClose: handleClose, apiData: widget.apiData);
|
selectedWidget = MiscellaneousScreen(onClose: handleClose, apiData: widget.apiData,
|
||||||
break;
|
onSaveMiscellaneous: (data) => handleItineraryUpdate("Miscellaneous", data),
|
||||||
|
selectedItem: selectedItem, selectedIndex: selectedIndex, );
|
||||||
|
break;
|
||||||
case "Accommodation":
|
case "Accommodation":
|
||||||
selectedWidget = AccomodationScreen( onClose: handleClose,formData: formData["Accommodation"]!, updateFormData: updateFormData);
|
selectedWidget = AccomodationScreen( onClose: handleClose,
|
||||||
|
onSaveAccomadation: (data)=>handleItineraryUpdate("Accommodation", data),
|
||||||
|
selectedItem: selectedItem, );
|
||||||
break;
|
break;
|
||||||
case "Forex":
|
case "Forex":
|
||||||
selectedWidget = ForexScreen( onClose: handleClose,formData: formData["Forex"]!, updateFormData: updateFormData, apiData: widget.apiData);
|
selectedWidget = ForexScreen( onClose: handleClose,apiData: widget.apiData, apiCountryData : widget.apiCountryData,
|
||||||
|
onSaveForex: (data)=>handleItineraryUpdate("Forex", data),
|
||||||
|
selectedItem: selectedItem);
|
||||||
break;
|
break;
|
||||||
case "Flight":
|
case "Flight":
|
||||||
default:
|
default:
|
||||||
@ -194,7 +462,6 @@ class _DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
);
|
);
|
||||||
@ -248,6 +515,7 @@ class _DynamicItineraryState extends State<DynamicItinerary> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
selectedOption = title;
|
selectedOption = title;
|
||||||
isSelected = true;
|
isSelected = true;
|
||||||
|
selectedItem = null;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Icon(
|
child: Icon(
|
||||||
|
|||||||
@ -138,74 +138,78 @@ class _ListPlansState extends State<ListPlans>{
|
|||||||
builder: (context, sizingInfo) {
|
builder: (context, sizingInfo) {
|
||||||
bool isTabletOrDesktop = sizingInfo.isTablet || sizingInfo.isDesktop;
|
bool isTabletOrDesktop = sizingInfo.isTablet || sizingInfo.isDesktop;
|
||||||
|
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.vertical,
|
||||||
// scrollDirection: isTabletOrDesktop ? Axis.vertical : Axis.horizontal,
|
child: SingleChildScrollView(
|
||||||
child: SizedBox(
|
scrollDirection: Axis.horizontal,
|
||||||
// constraints: isTabletOrDesktop
|
// scrollDirection: isTabletOrDesktop ? Axis.vertical : Axis.horizontal,
|
||||||
// ? const BoxConstraints(maxWidth: double.infinity)
|
child: SizedBox(
|
||||||
// : BoxConstraints.tightFor(width: 600),
|
// constraints: isTabletOrDesktop
|
||||||
width: MediaQuery.of(context).size.width ,
|
// ? const BoxConstraints(maxWidth: double.infinity)
|
||||||
child: DataTable(
|
// : BoxConstraints.tightFor(width: 600),
|
||||||
// columnSpacing: 50.0,
|
width: MediaQuery.of(context).size.width ,
|
||||||
dividerThickness: 0.5, // Reduce the thickness of row dividers
|
child: DataTable(
|
||||||
border: TableBorder(
|
// columnSpacing: 50.0,
|
||||||
horizontalInside: BorderSide(width: 0.5, color: Colors.grey.shade200), // Reduce horizontal line thickness
|
dividerThickness: 0.5, // Reduce the thickness of row dividers
|
||||||
),
|
border: TableBorder(
|
||||||
columns: const [
|
horizontalInside: BorderSide(width: 0.5, color: Colors.grey.shade200), // Reduce horizontal line thickness
|
||||||
DataColumn(label: Text('Plan ID', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
),
|
||||||
DataColumn(label: Text('Trip Title', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
columns: const [
|
||||||
DataColumn(label: Text('Trip Type', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
DataColumn(label: Text('Plan ID', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
||||||
DataColumn(label: Text('Cost Center', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
DataColumn(label: Text('Trip Title', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
||||||
// DataColumn(label: Text('Functional Department', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
DataColumn(label: Text('Trip Type', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
||||||
// DataColumn(label: Text('Purpose Of Travel', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
DataColumn(label: Text('Cost Center', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
||||||
// DataColumn(label: Text('Description', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
// DataColumn(label: Text('Functional Department', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
||||||
//
|
// DataColumn(label: Text('Purpose Of Travel', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
||||||
DataColumn(label: Text('Is Billable', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
// DataColumn(label: Text('Description', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
||||||
DataColumn(label: Text('Status', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
|
||||||
DataColumn(label: Text('Actions', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
|
||||||
],
|
|
||||||
rows: plans.map((plan) {
|
|
||||||
return DataRow(cells: [
|
|
||||||
DataCell(Text(plan.planId)),
|
|
||||||
// DataCell(Text(plan.tripTitle)),
|
|
||||||
DataCell(Row(
|
|
||||||
children: [
|
|
||||||
Flexible(
|
|
||||||
child: Text(
|
|
||||||
plan.tripTitle,
|
|
||||||
softWrap: true,
|
|
||||||
overflow: TextOverflow.ellipsis, // Adds "..." if text is too long
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
|
|
||||||
|
|
||||||
DataCell(Text(plan.tripType)),
|
|
||||||
DataCell(Text(plan.costCenter)),
|
|
||||||
// DataCell(Text(plan.functionalDepartment)),
|
|
||||||
// DataCell(Text(plan.purposeOfTravel)),
|
|
||||||
// DataCell(Text(plan.description)),
|
|
||||||
//
|
//
|
||||||
DataCell(Text(plan.isBillable)),
|
DataColumn(label: Text('Is Billable', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
||||||
DataCell(Text(plan.status)),
|
DataColumn(label: Text('Status', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
||||||
DataCell(
|
DataColumn(label: Text('Actions', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
|
||||||
TextButton(
|
],
|
||||||
onPressed: () {
|
rows: plans.map((plan) {
|
||||||
print("View button clicked for ${plan.tripTitle}");
|
return DataRow(cells: [
|
||||||
},
|
DataCell(Text(plan.planId)),
|
||||||
child: const Text('View',
|
// DataCell(Text(plan.tripTitle)),
|
||||||
style: TextStyle(color: Colors.blueAccent)),
|
DataCell(Row(
|
||||||
),
|
children: [
|
||||||
),
|
Flexible(
|
||||||
]);
|
child: Text(
|
||||||
}).toList(),
|
plan.tripTitle,
|
||||||
),
|
softWrap: true,
|
||||||
),
|
overflow: TextOverflow.ellipsis, // Adds "..." if text is too long
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
|
||||||
);
|
|
||||||
},
|
DataCell(Text(plan.tripType)),
|
||||||
|
DataCell(Text(plan.costCenter)),
|
||||||
|
// DataCell(Text(plan.functionalDepartment)),
|
||||||
|
// DataCell(Text(plan.purposeOfTravel)),
|
||||||
|
// DataCell(Text(plan.description)),
|
||||||
|
//
|
||||||
|
DataCell(Text(plan.isBillable)),
|
||||||
|
DataCell(Text(plan.status)),
|
||||||
|
DataCell(
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
print("View button clicked for ${plan.tripTitle}");
|
||||||
|
},
|
||||||
|
child: const Text('View',
|
||||||
|
style: TextStyle(color: Colors.blueAccent)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
31
lib/data/models/Searchtraveller.dart
Normal file
31
lib/data/models/Searchtraveller.dart
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
class SearchTraveler {
|
||||||
|
final String travellerId;
|
||||||
|
final String firstName;
|
||||||
|
final String lastName;
|
||||||
|
final String email;
|
||||||
|
final String mobileNo;
|
||||||
|
|
||||||
|
|
||||||
|
SearchTraveler({
|
||||||
|
required this.travellerId,
|
||||||
|
required this.firstName,
|
||||||
|
required this.lastName,
|
||||||
|
required this.email,
|
||||||
|
required this.mobileNo,
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
factory SearchTraveler.fromJson(Map<String, dynamic> json){
|
||||||
|
return SearchTraveler(
|
||||||
|
|
||||||
|
travellerId: json['traveller_id'].toString(),
|
||||||
|
firstName: json['first_name'].toString()?? '',
|
||||||
|
lastName: json['last_name'].toString()?? '',
|
||||||
|
email: json['email'].toString()?? '',
|
||||||
|
mobileNo: json['mobile_no'].toString()?? '',
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
class SearchUser{
|
class SearchUser{
|
||||||
final String userId;
|
final String userId;
|
||||||
final String travellerId;
|
|
||||||
final String firstName;
|
final String firstName;
|
||||||
final String lastName;
|
final String lastName;
|
||||||
final String email;
|
final String email;
|
||||||
@ -9,7 +8,6 @@ class SearchUser{
|
|||||||
|
|
||||||
SearchUser({
|
SearchUser({
|
||||||
required this.userId,
|
required this.userId,
|
||||||
required this.travellerId,
|
|
||||||
required this.firstName,
|
required this.firstName,
|
||||||
required this.lastName,
|
required this.lastName,
|
||||||
required this.email,
|
required this.email,
|
||||||
@ -21,7 +19,6 @@ class SearchUser{
|
|||||||
factory SearchUser.fromJson(Map<String, dynamic> json){
|
factory SearchUser.fromJson(Map<String, dynamic> json){
|
||||||
return SearchUser(
|
return SearchUser(
|
||||||
userId: json['user_id'].toString(),
|
userId: json['user_id'].toString(),
|
||||||
travellerId: json['traveller_id'].toString(),
|
|
||||||
firstName: json['first_name'].toString()?? '',
|
firstName: json['first_name'].toString()?? '',
|
||||||
lastName: json['last_name'].toString()?? '',
|
lastName: json['last_name'].toString()?? '',
|
||||||
email: json['email'].toString()?? '',
|
email: json['email'].toString()?? '',
|
||||||
|
|||||||
58
lib/widgets/custom_text_forex.dart
Normal file
58
lib/widgets/custom_text_forex.dart
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class CustomTextFieldForexWrapper extends StatefulWidget {
|
||||||
|
final Widget child;
|
||||||
|
final bool isFocused;
|
||||||
|
final bool isDesktop;
|
||||||
|
final double? width;
|
||||||
|
final Color? color;
|
||||||
|
final VoidCallback? onFocusChange; // Callback for focus handling
|
||||||
|
final EdgeInsetsGeometry padding;
|
||||||
|
|
||||||
|
const CustomTextFieldForexWrapper({
|
||||||
|
super.key,
|
||||||
|
required this.child,
|
||||||
|
required this.isFocused,
|
||||||
|
required this.isDesktop,
|
||||||
|
this.width,
|
||||||
|
this.color = Colors.white,
|
||||||
|
this.onFocusChange,
|
||||||
|
this.padding = const EdgeInsets.symmetric(horizontal: 12),
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_CustomTextFieldForexWrapperState createState() => _CustomTextFieldForexWrapperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CustomTextFieldForexWrapperState extends State<CustomTextFieldForexWrapper> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
width: widget.width ?? // Use custom width if provided, else default
|
||||||
|
(widget.isDesktop
|
||||||
|
? MediaQuery.of(context).size.width * 0.25
|
||||||
|
: MediaQuery.of(context).size.width * 0.8),
|
||||||
|
padding: widget.padding,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: widget.color,
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
border: Border.all(
|
||||||
|
color: widget.isFocused ? Color(0xFF78B4FC) : Color(0xFFD6D5E6),
|
||||||
|
width: widget.isFocused ? 2.0 : 0.5,
|
||||||
|
),
|
||||||
|
boxShadow: widget.isFocused
|
||||||
|
? [
|
||||||
|
BoxShadow(
|
||||||
|
color: Color.fromRGBO(120, 180, 252, 0.3),
|
||||||
|
blurRadius: 10,
|
||||||
|
spreadRadius: 2,
|
||||||
|
offset: Offset(0, 4),
|
||||||
|
|
||||||
|
),
|
||||||
|
]
|
||||||
|
: [],
|
||||||
|
),
|
||||||
|
child: widget.child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -65,6 +65,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.8"
|
version: "1.0.8"
|
||||||
|
dropdown_search:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: dropdown_search
|
||||||
|
sha256: "55106e8290acaa97ed15bea1fdad82c3cf0c248dd410e651f5a8ac6870f783ab"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.6"
|
||||||
easy_stepper:
|
easy_stepper:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
@ -40,6 +40,7 @@ dependencies:
|
|||||||
shared_preferences: ^2.5.2
|
shared_preferences: ^2.5.2
|
||||||
easy_stepper: ^0.8.5+1
|
easy_stepper: ^0.8.5+1
|
||||||
intl: ^0.20.2
|
intl: ^0.20.2
|
||||||
|
dropdown_search: ^5.0.6
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user