merged
This commit is contained in:
commit
1c77a03067
@ -36,11 +36,12 @@ class CostCenterDataState extends State<CostCenterData> {
|
||||
final ApiService apiService = ApiService();
|
||||
Map<String, dynamic>? apiData;
|
||||
|
||||
final Map<String, FocusNode> focusNodes = {
|
||||
"name": FocusNode(),
|
||||
"description": FocusNode(),
|
||||
};
|
||||
|
||||
// final Map<String, FocusNode> focusNodes = {
|
||||
// "name": FocusNode(),
|
||||
// "description": FocusNode(),
|
||||
// };
|
||||
Map<String, FocusNode> focusNodes = {};
|
||||
Map<String, bool> focusStates = {};
|
||||
final Map<String, TextEditingController> controllers = {};
|
||||
Map<String, String> errorMessages = {};
|
||||
|
||||
@ -70,6 +71,15 @@ class CostCenterDataState extends State<CostCenterData> {
|
||||
apiData = null;
|
||||
for (var field in dataHeader) {
|
||||
controllers[field] = TextEditingController();
|
||||
focusNodes["${field}FocusNode"] = FocusNode();
|
||||
focusStates["${field}Focused"] = false;
|
||||
}
|
||||
for (var key in focusNodes.keys) {
|
||||
_addFocusListener(focusNodes[key]!, (focus) {
|
||||
setState(() {
|
||||
focusStates[key.replaceFirst("FocusNode", "Focused")] = focus;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (widget.costcenterId != null) {
|
||||
@ -89,8 +99,18 @@ class CostCenterDataState extends State<CostCenterData> {
|
||||
for (var controller in controllers.values) {
|
||||
controller.dispose();
|
||||
}
|
||||
for (var node in focusNodes.values) {
|
||||
node.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||
node.addListener(() {
|
||||
setState(() {
|
||||
updateState(node.hasFocus);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void updateCostCenterDetails() {
|
||||
print("Inside Update Function - ${widget.costcenterData}");
|
||||
@ -129,10 +149,10 @@ class CostCenterDataState extends State<CostCenterData> {
|
||||
if (data[field] == null || data[field]!.trim().isEmpty) {
|
||||
errorMessages[field] = "Required";
|
||||
|
||||
if (!hasFocused) {
|
||||
focusNodes[field]?.requestFocus();
|
||||
hasFocused = true;
|
||||
}
|
||||
// if (!hasFocused) {
|
||||
// focusNodes[field]?.requestFocus();
|
||||
// hasFocused = true;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,14 +278,14 @@ class CostCenterDataState extends State<CostCenterData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isFocused: focusStates["nameFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: controllers["name"],
|
||||
focusNode: focusNodes["name"],
|
||||
focusNode: focusNodes["nameFocusNode"],
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Name",
|
||||
@ -300,14 +320,14 @@ class CostCenterDataState extends State<CostCenterData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isFocused: focusStates["descriptionFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 100,
|
||||
child: TextField(
|
||||
controller: controllers["description"],
|
||||
focusNode: focusNodes["description"],
|
||||
focusNode: focusNodes["descriptionFocusNode"],
|
||||
style: const TextStyle(fontSize: 12),
|
||||
maxLines: null,
|
||||
expands: true,
|
||||
|
||||
@ -36,26 +36,27 @@ class DepartmentDataState extends State<DepartmentData> {
|
||||
final ApiService apiService = ApiService();
|
||||
Map<String, dynamic>? apiData;
|
||||
|
||||
final Map<String, FocusNode> focusNodes = {
|
||||
"name": FocusNode(),
|
||||
"description": FocusNode(),
|
||||
};
|
||||
// final Map<String, FocusNode> focusNodes = {
|
||||
// "name": FocusNode(),
|
||||
// "description": FocusNode(),
|
||||
// };
|
||||
|
||||
final Map<String, TextEditingController> controllers = {};
|
||||
Map<String, String> errorMessages = {};
|
||||
|
||||
Map<String, FocusNode> focusNodes = {};
|
||||
Map<String, bool> focusStates = {};
|
||||
String? selectedName;
|
||||
String? selectedDescription;
|
||||
String? userId;
|
||||
int? departmentDataId;
|
||||
late String isActive = "1";
|
||||
|
||||
List<String> dataHeader = ["name", "description"];
|
||||
List<String> dataHeader = ["dropdown_value", "description"];
|
||||
|
||||
Map<String, dynamic> departmentDetails() {
|
||||
final data = {
|
||||
// "department_id": int.parse(departmentId),
|
||||
"name": controllers["name"]?.text,
|
||||
"dropdown_value": controllers["dropdown_value"]?.text,
|
||||
"description": controllers["description"]?.text,
|
||||
"created_by": userId,
|
||||
"is_active": isActive,
|
||||
@ -70,6 +71,15 @@ class DepartmentDataState extends State<DepartmentData> {
|
||||
apiData = null;
|
||||
for (var field in dataHeader) {
|
||||
controllers[field] = TextEditingController();
|
||||
focusNodes["${field}FocusNode"] = FocusNode();
|
||||
focusStates["${field}Focused"] = false;
|
||||
}
|
||||
for (var key in focusNodes.keys) {
|
||||
_addFocusListener(focusNodes[key]!, (focus) {
|
||||
setState(() {
|
||||
focusStates[key.replaceFirst("FocusNode", "Focused")] = focus;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (widget.departmentId != null) {
|
||||
@ -89,8 +99,18 @@ class DepartmentDataState extends State<DepartmentData> {
|
||||
for (var controller in controllers.values) {
|
||||
controller.dispose();
|
||||
}
|
||||
for (var node in focusNodes.values) {
|
||||
node.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||
node.addListener(() {
|
||||
setState(() {
|
||||
updateState(node.hasFocus);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void updateDepartmentDetails() {
|
||||
print("Inside Update Function - ${widget.departmentData}");
|
||||
@ -99,10 +119,10 @@ class DepartmentDataState extends State<DepartmentData> {
|
||||
|
||||
if (data == null) return;
|
||||
setState(() {
|
||||
controllers['name']?.text = data['name'] ?? '';
|
||||
controllers['description']?.text = data['description'].toString();
|
||||
controllers['dropdown_value']?.text = data['dropdown_value'] ?? '';
|
||||
// controllers['description']?.text = data['description'].toString();
|
||||
isActive = data["is_active"];
|
||||
final departmentId = int.tryParse(data['department_id'].toString());
|
||||
final departmentId = int.tryParse(data['id'].toString());
|
||||
departmentDataId = departmentId;
|
||||
});
|
||||
}
|
||||
@ -117,11 +137,11 @@ class DepartmentDataState extends State<DepartmentData> {
|
||||
errorMessages.clear();
|
||||
|
||||
final data = {
|
||||
"name": controllers["name"]?.text,
|
||||
"description": controllers["description"]?.text,
|
||||
"dropdown_value": controllers["dropdown_value"]?.text,
|
||||
// "description": controllers["description"]?.text,
|
||||
};
|
||||
|
||||
final requiredFields = ["name", "description"];
|
||||
final requiredFields = ["dropdown_value"];
|
||||
bool hasFocused = false;
|
||||
|
||||
// Check validation for each field
|
||||
@ -129,10 +149,10 @@ class DepartmentDataState extends State<DepartmentData> {
|
||||
if (data[field] == null || data[field]!.trim().isEmpty) {
|
||||
errorMessages[field] = "Required";
|
||||
|
||||
if (!hasFocused) {
|
||||
focusNodes[field]?.requestFocus();
|
||||
hasFocused = true;
|
||||
}
|
||||
// if (!hasFocused) {
|
||||
// focusNodes[field]?.requestFocus();
|
||||
// hasFocused = true;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,7 +185,7 @@ class DepartmentDataState extends State<DepartmentData> {
|
||||
if (departmentDataId != null) {
|
||||
print("for edit department id - $departmentDataId");
|
||||
apiUrldata = '$apiUrl/api/updateDepartment/$departmentDataId';
|
||||
departmentData["department_id"] = departmentDataId.toString();
|
||||
departmentData["id"] = departmentDataId.toString();
|
||||
departmentData["updated_by"] = userId;
|
||||
(departmentData.containsKey("created_by"))
|
||||
? departmentData.remove("created_by")
|
||||
@ -261,14 +281,14 @@ class DepartmentDataState extends State<DepartmentData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isFocused: focusStates["dropdown_valueFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: controllers["name"],
|
||||
focusNode: focusNodes["name"],
|
||||
controller: controllers["dropdown_value"],
|
||||
focusNode: focusNodes["dropdown_valueFocusNode"],
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Name",
|
||||
@ -280,60 +300,60 @@ class DepartmentDataState extends State<DepartmentData> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (errorMessages["name"] != null) ...[
|
||||
if (errorMessages["dropdown_value"] != null) ...[
|
||||
SizedBox(height: 5), // Space before error message
|
||||
Text(
|
||||
errorMessages["name"]!,
|
||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
SizedBox(height: 15),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Description *",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF575A74),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 100,
|
||||
child: TextField(
|
||||
controller: controllers["description"],
|
||||
focusNode: focusNodes["description"],
|
||||
style: const TextStyle(fontSize: 12),
|
||||
maxLines: null,
|
||||
expands: true,
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Description",
|
||||
labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (errorMessages["description"] != null) ...[
|
||||
SizedBox(height: 5), // Space before error message
|
||||
Text(
|
||||
errorMessages["description"]!,
|
||||
errorMessages["dropdown_value"]!,
|
||||
style: TextStyle(color: Colors.red, fontSize: 12),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
SizedBox(height: 15),
|
||||
// Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Text(
|
||||
// "Description *",
|
||||
// style: GoogleFonts.poppins(
|
||||
// fontSize: 12,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// color: Color(0xFF575A74),
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(height: 5),
|
||||
// CustomTextFieldForexWrapper(
|
||||
// isFocused: focusStates["descriptionFocused"] ?? false,
|
||||
// isDesktop: widget.isDesktop,
|
||||
// color: Colors.transparent,
|
||||
// child: SizedBox(
|
||||
// height: 100,
|
||||
// child: TextField(
|
||||
// controller: controllers["description"],
|
||||
// focusNode: focusNodes["descriptionFocusNode"],
|
||||
// style: const TextStyle(fontSize: 12),
|
||||
// maxLines: null,
|
||||
// expands: true,
|
||||
// decoration: const InputDecoration(
|
||||
// labelText: "Description",
|
||||
// labelStyle: TextStyle(fontSize: 11, color: Colors.grey),
|
||||
// floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
// border: InputBorder.none,
|
||||
// contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// if (errorMessages["description"] != null) ...[
|
||||
// SizedBox(height: 5), // Space before error message
|
||||
// Text(
|
||||
// errorMessages["description"]!,
|
||||
// style: TextStyle(color: Colors.red, fontSize: 12),
|
||||
// ),
|
||||
// ],
|
||||
// ],
|
||||
// ),
|
||||
// SizedBox(height: 15),
|
||||
if (departmentDataId != null)
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
||||
@ -180,13 +180,13 @@ class DepartmentListState extends State<DepartmentList> {
|
||||
allDepartment.where((object) {
|
||||
final isActiveStatus =
|
||||
object['is_active'] == "1" ? "active" : "inactive";
|
||||
return (object['department_id']?.toLowerCase().contains(
|
||||
return (object['id']?.toLowerCase().contains(
|
||||
lowerQuery,
|
||||
) ??
|
||||
false) ||
|
||||
(object['name']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['description']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['dropdown_value']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
// (object['description']?.toLowerCase().contains(lowerQuery) ??
|
||||
// false) ||
|
||||
(isActiveStatus.contains(lowerQuery));
|
||||
}).toList();
|
||||
currentPage = 0;
|
||||
@ -550,15 +550,15 @@ class DepartmentListState extends State<DepartmentList> {
|
||||
),
|
||||
),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text(
|
||||
'Description',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
// DataColumn(
|
||||
// label: Text(
|
||||
// 'Description',
|
||||
// style: GoogleFonts.poppins(
|
||||
// fontSize: 13,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
DataColumn(
|
||||
label: Text(
|
||||
'Status',
|
||||
@ -581,7 +581,7 @@ class DepartmentListState extends State<DepartmentList> {
|
||||
rows:
|
||||
paginatedDepartment.map((tableObject) {
|
||||
String departmentId =
|
||||
tableObject['department_id']
|
||||
tableObject['id']
|
||||
.toString(); // Get user ID
|
||||
bool isSelected =
|
||||
selectedDepartmentId == departmentId;
|
||||
@ -590,24 +590,24 @@ class DepartmentListState extends State<DepartmentList> {
|
||||
cells: [
|
||||
DataCell(
|
||||
Text(
|
||||
tableObject['name'] ?? '',
|
||||
tableObject['dropdown_value'] ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontFamily: "Inter",
|
||||
),
|
||||
),
|
||||
),
|
||||
DataCell(
|
||||
Text(
|
||||
tableObject['description'] ?? 'N/A',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontFamily: "Inter",
|
||||
),
|
||||
softWrap: true,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
// DataCell(
|
||||
// Text(
|
||||
// tableObject['description'] ?? 'N/A',
|
||||
// style: TextStyle(
|
||||
// fontSize: 13,
|
||||
// fontFamily: "Inter",
|
||||
// ),
|
||||
// softWrap: true,
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// ),
|
||||
// ),
|
||||
DataCell(
|
||||
Text(
|
||||
tableObject['is_active'] == "1"
|
||||
@ -645,7 +645,7 @@ class DepartmentListState extends State<DepartmentList> {
|
||||
// final usersData = await getUserDetails(userId);
|
||||
//
|
||||
final departmentId = int.tryParse(
|
||||
tableObject['department_id']
|
||||
tableObject['id']
|
||||
.toString(),
|
||||
);
|
||||
|
||||
@ -716,7 +716,7 @@ class DepartmentListState extends State<DepartmentList> {
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
cardObject['name'] ?? 'N/A',
|
||||
cardObject['dropdown_value'] ?? 'N/A',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 10,
|
||||
color: Colors.black87,
|
||||
@ -738,7 +738,7 @@ class DepartmentListState extends State<DepartmentList> {
|
||||
// final usersData = await getUserDetails(userId);
|
||||
//
|
||||
final departmentId = int.tryParse(
|
||||
cardObject['department_id']
|
||||
cardObject['id']
|
||||
.toString(),
|
||||
);
|
||||
|
||||
@ -852,37 +852,37 @@ class DepartmentListState extends State<DepartmentList> {
|
||||
SizedBox(height: 2),
|
||||
// Trip Id and Trip Name
|
||||
// Name
|
||||
Row(
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
cardObject['description'] ?? '',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 10,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
cardObject['description'] ?? '',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 10,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
// Row(
|
||||
// children: [
|
||||
// Column(
|
||||
// crossAxisAlignment:
|
||||
// CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Text(
|
||||
// cardObject['description'] ?? '',
|
||||
// style: GoogleFonts.poppins(
|
||||
// fontSize: 10,
|
||||
// color: Colors.black87,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// SizedBox(width: 10),
|
||||
// Column(
|
||||
// crossAxisAlignment:
|
||||
// CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Text(
|
||||
// cardObject['description'] ?? '',
|
||||
// style: GoogleFonts.poppins(
|
||||
// fontSize: 10,
|
||||
// color: Colors.black87,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// Actions
|
||||
// Actions
|
||||
],
|
||||
|
||||
@ -42,6 +42,8 @@ class HotelsDataState extends State<HotelsData> {
|
||||
Map<String, dynamic>? apiData;
|
||||
final Map<String, TextEditingController> controllers = {};
|
||||
Map<String, String> errorMessages = {};
|
||||
Map<String, FocusNode> focusNodes = {};
|
||||
Map<String, bool> focusStates = {};
|
||||
|
||||
List<dynamic> countryList = [];
|
||||
String? selectedCountry;
|
||||
@ -83,6 +85,15 @@ class HotelsDataState extends State<HotelsData> {
|
||||
apiData = null;
|
||||
for (var field in dataHeader) {
|
||||
controllers[field] = TextEditingController();
|
||||
focusNodes["${field}FocusNode"] = FocusNode();
|
||||
focusStates["${field}Focused"] = false;
|
||||
}
|
||||
for (var key in focusNodes.keys) {
|
||||
_addFocusListener(focusNodes[key]!, (focus) {
|
||||
setState(() {
|
||||
focusStates[key.replaceFirst("FocusNode", "Focused")] = focus;
|
||||
});
|
||||
});
|
||||
}
|
||||
fetchCountries();
|
||||
if (widget.hotelsId != null) {
|
||||
@ -103,8 +114,18 @@ class HotelsDataState extends State<HotelsData> {
|
||||
for (var controller in controllers.values) {
|
||||
controller.dispose();
|
||||
}
|
||||
for (var node in focusNodes.values) {
|
||||
node.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||
node.addListener(() {
|
||||
setState(() {
|
||||
updateState(node.hasFocus);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void updateHotelsDetails() {
|
||||
print("Update - ${widget.hotelsData}");
|
||||
@ -312,12 +333,14 @@ class HotelsDataState extends State<HotelsData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
// isFocused: false,
|
||||
isFocused: focusStates["hotel_nameFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
focusNode: focusNodes["hotel_nameFocusNode"],
|
||||
controller: controllers["hotel_name"],
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
@ -353,12 +376,13 @@ class HotelsDataState extends State<HotelsData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isFocused: focusStates["hotel_chainFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
focusNode: focusNodes["hotel_chainFocusNode"],
|
||||
controller: controllers["hotel_chain"],
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
@ -394,12 +418,14 @@ class HotelsDataState extends State<HotelsData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
// isFocused: false,
|
||||
isFocused: focusStates["categoryFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
focusNode: focusNodes["categoryFocusNode"],
|
||||
controller: controllers["category"],
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 ]')),
|
||||
@ -432,61 +458,102 @@ class HotelsDataState extends State<HotelsData> {
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||
isDesktop: widget.isDesktop,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: DropdownSearch<String>(
|
||||
selectedItem: countryMap[selectedCountry],
|
||||
popupProps: PopupProps.menu(
|
||||
showSearchBox: true, // Enables search functionality
|
||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||
constraints: BoxConstraints(maxHeight: 250),
|
||||
itemBuilder:
|
||||
(context, item, isSelected) => Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8.0,
|
||||
vertical: 6.0,
|
||||
width: double.infinity,
|
||||
child: Focus(
|
||||
focusNode: focusNodes["country_codeFocusNode"],
|
||||
onFocusChange: (hasFocus) {
|
||||
setState(() {
|
||||
focusStates["country_codeFocused"] = hasFocus;
|
||||
});
|
||||
},
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
// Request focus when user taps
|
||||
focusNodes["country_codeFocusNode"]?.requestFocus();
|
||||
},
|
||||
child: DropdownSearch<String>(
|
||||
selectedItem: countryMap[selectedCountry],
|
||||
popupProps: PopupProps.menu(
|
||||
showSearchBox: true, // Enables search functionality
|
||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||
constraints: BoxConstraints(maxHeight: 200),
|
||||
itemBuilder:
|
||||
(context, item, isSelected) => Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
child: Text(
|
||||
item,
|
||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||
),
|
||||
),
|
||||
searchFieldProps: TextFieldProps(
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search ...",
|
||||
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
item,
|
||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||
items: countryMap.values.toList(),
|
||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||
dropdownSearchDecoration: InputDecoration(
|
||||
// border: InputBorder.none,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color:
|
||||
(focusStates["country_codeFocused"] ?? false)
|
||||
? widget.layoutColor!
|
||||
: Colors.white,
|
||||
// width: 0.5,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color:
|
||||
(focusStates["country_codeFocused"] ?? false)
|
||||
? widget.layoutColor!
|
||||
: Colors.white,
|
||||
// : const Color(0xFFD6D5E6),
|
||||
// width: 0.5,
|
||||
// const Color(0xFFD6D5E6),
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: widget.layoutColor!, width: 1),
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 10.0,
|
||||
vertical: 8.0,),
|
||||
),
|
||||
),
|
||||
dropdownBuilder:
|
||||
(context, selectedItem) => Align(
|
||||
// Center-align selected item
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
selectedItem ?? "Select ",
|
||||
style: GoogleFonts.poppins(fontSize: 11),
|
||||
),
|
||||
),
|
||||
onChanged: (String? newValue) {
|
||||
setState(() {
|
||||
// Find the country_code based on selected country_name
|
||||
selectedCountry =
|
||||
countryMap.entries
|
||||
.firstWhere((entry) => entry.value == newValue)
|
||||
.key;
|
||||
selectedCountryName = newValue;
|
||||
});
|
||||
},
|
||||
),
|
||||
searchFieldProps: TextFieldProps(
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search ...",
|
||||
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||
),
|
||||
),
|
||||
),
|
||||
items: countryMap.values.toList(),
|
||||
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 ",
|
||||
style: GoogleFonts.poppins(fontSize: 11),
|
||||
),
|
||||
),
|
||||
onChanged: (String? newValue) {
|
||||
setState(() {
|
||||
// Find the country_code based on selected country_name
|
||||
selectedCountry =
|
||||
countryMap.entries
|
||||
.firstWhere((entry) => entry.value == newValue)
|
||||
.key;
|
||||
selectedCountryName = newValue;
|
||||
});
|
||||
},
|
||||
),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
if (errorMessages["country_code"] != null) ...[
|
||||
@ -512,12 +579,13 @@ class HotelsDataState extends State<HotelsData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isFocused: focusStates["cityFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
focusNode: focusNodes["cityFocusNode"],
|
||||
controller: controllers["city"],
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
|
||||
@ -33,6 +33,7 @@ import '../../routes/custom_appBar.dart';
|
||||
import '../../routes/custom_drawer.dart';
|
||||
import '../../services/apiService.dart';
|
||||
import '../../utils/auth_utils.dart';
|
||||
import '../../widgets/custom_breadcrumb_navigation.dart';
|
||||
import '../../widgets/custom_user_travel.dart';
|
||||
import 'dialog_placeholders.dart';
|
||||
|
||||
@ -60,6 +61,8 @@ class TemplateState extends State<Template> {
|
||||
final Map<String, TextEditingController> controllers = {};
|
||||
List<String> dataHeader = ["subject"];
|
||||
List<String> placeholders = [];
|
||||
Map<String, FocusNode> focusNodes = {};
|
||||
Map<String, bool> focusStates = {};
|
||||
|
||||
late QuillController _controller = QuillController.basic();
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
@ -103,6 +106,15 @@ class TemplateState extends State<Template> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_checkAuthAndLoadData();
|
||||
focusNodes["subjectFocusNode"] = FocusNode();
|
||||
focusStates["subjectFocused"] = false;
|
||||
for (var key in focusNodes.keys) {
|
||||
_addFocusListener(focusNodes[key]!, (focus) {
|
||||
setState(() {
|
||||
focusStates[key.replaceFirst("FocusNode", "Focused")] = focus;
|
||||
});
|
||||
});
|
||||
}
|
||||
//
|
||||
// for (var field in dataHeader) {
|
||||
// controllers[field] = TextEditingController();
|
||||
@ -144,6 +156,13 @@ class TemplateState extends State<Template> {
|
||||
// _editorFocusNode.dispose();
|
||||
// super.dispose();
|
||||
// }
|
||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||
node.addListener(() {
|
||||
setState(() {
|
||||
updateState(node.hasFocus);
|
||||
});
|
||||
});
|
||||
}
|
||||
void loadinitializeData() async {
|
||||
orgId = await getOrgId();
|
||||
userId = await getUserId();
|
||||
@ -529,15 +548,40 @@ class TemplateState extends State<Template> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
formatTemplateName(templateName),
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.black,
|
||||
),
|
||||
// Text(
|
||||
// formatTemplateName(templateName),
|
||||
// style: GoogleFonts.poppins(
|
||||
// fontSize: 18,
|
||||
// fontWeight: FontWeight.w400,
|
||||
// color: Colors.black,
|
||||
// ),
|
||||
// ),
|
||||
Row(
|
||||
children: [
|
||||
BreadcrumbNavigation(
|
||||
isDesktop: isDesktop,
|
||||
breadcrumbItems: [
|
||||
BreadcrumbItem(
|
||||
title: 'Organization Settings',
|
||||
tooltip: 'Go To Organization Settings',
|
||||
onTap: (context) {
|
||||
context.go("/OrganizationSettings");
|
||||
}
|
||||
),
|
||||
BreadcrumbItem(
|
||||
title: 'Templates',
|
||||
tooltip: 'Go To Templates',
|
||||
onTap: (context) {
|
||||
context.go("/templateList");
|
||||
}
|
||||
),
|
||||
BreadcrumbItem(
|
||||
title: formatTemplateName(templateName),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
SizedBox(height: 10),
|
||||
buildTempalteSubject(isDesktop),
|
||||
|
||||
@ -565,7 +609,8 @@ class TemplateState extends State<Template> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldUserTravellerWrapper(
|
||||
isFocused: false,
|
||||
// isFocused: false,
|
||||
isFocused: focusStates["subjectFocused"] ?? false,
|
||||
color: Colors.white,
|
||||
width: isDesktop ? MediaQuery.of(context).size.width * 0.8 : null,
|
||||
isDesktop: isDesktop,
|
||||
@ -573,6 +618,7 @@ class TemplateState extends State<Template> {
|
||||
height: 40,
|
||||
child: TextField(
|
||||
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
||||
focusNode: focusNodes["subjectNode"],
|
||||
controller: controllers["subject"],
|
||||
onChanged: (value) {
|
||||
// _clearError("local_id_num");
|
||||
|
||||
@ -14,6 +14,7 @@ import '../../routes/custom_drawer.dart';
|
||||
import '../../services/apiService.dart';
|
||||
import '../../utils/auth_utils.dart';
|
||||
import '../../utils/pagination.dart';
|
||||
import '../../widgets/custom_breadcrumb_navigation.dart';
|
||||
import '../../widgets/popup_userList_action.dart';
|
||||
|
||||
class TemplatesList extends StatefulWidget {
|
||||
@ -432,12 +433,29 @@ class TemplatesListState extends State<TemplatesList> {
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'Templates',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: isDesktop ? 16 : 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black,
|
||||
// Text(
|
||||
// 'Templates',
|
||||
// style: GoogleFonts.poppins(
|
||||
// fontSize: isDesktop ? 16 : 14,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// color: Colors.black,
|
||||
// ),
|
||||
// ),
|
||||
Container(
|
||||
child: BreadcrumbNavigation(
|
||||
isDesktop: isDesktop,
|
||||
breadcrumbItems: [
|
||||
BreadcrumbItem(
|
||||
title: 'Organization Settings',
|
||||
tooltip: 'Go To Organization Settings',
|
||||
onTap: (context) {
|
||||
context.go("/OrganizationSettings");
|
||||
}
|
||||
),
|
||||
BreadcrumbItem(
|
||||
title: 'Templates',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@ -42,6 +42,8 @@ class ForexDataState extends State<ForexData> {
|
||||
Map<String, dynamic>? apiData;
|
||||
final Map<String, TextEditingController> controllers = {};
|
||||
Map<String, String> errorMessages = {};
|
||||
Map<String, FocusNode> focusNodes = {};
|
||||
Map<String, bool> focusStates = {};
|
||||
|
||||
List<dynamic> countryList = [];
|
||||
String? selectedCountry;
|
||||
@ -89,6 +91,15 @@ class ForexDataState extends State<ForexData> {
|
||||
apiData = null;
|
||||
for (var field in dataHeader) {
|
||||
controllers[field] = TextEditingController();
|
||||
focusNodes["${field}FocusNode"] = FocusNode();
|
||||
focusStates["${field}Focused"] = false;
|
||||
}
|
||||
for (var key in focusNodes.keys) {
|
||||
_addFocusListener(focusNodes[key]!, (focus) {
|
||||
setState(() {
|
||||
focusStates[key.replaceFirst("FocusNode", "Focused")] = focus;
|
||||
});
|
||||
});
|
||||
}
|
||||
fetchCountries();
|
||||
|
||||
@ -113,8 +124,18 @@ class ForexDataState extends State<ForexData> {
|
||||
for (var controller in controllers.values) {
|
||||
controller.dispose();
|
||||
}
|
||||
for (var node in focusNodes.values) {
|
||||
node.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||
node.addListener(() {
|
||||
setState(() {
|
||||
updateState(node.hasFocus);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void updateForexDetails() {
|
||||
print("Updateeee - ${widget.forexData}");
|
||||
@ -383,62 +404,103 @@ class ForexDataState extends State<ForexData> {
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||
isDesktop: widget.isDesktop,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: DropdownSearch<String>(
|
||||
selectedItem: countryMap[selectedCountry],
|
||||
popupProps: PopupProps.menu(
|
||||
showSearchBox: true, // Enables search functionality
|
||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||
constraints: BoxConstraints(maxHeight: 250),
|
||||
itemBuilder:
|
||||
(context, item, isSelected) => Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8.0,
|
||||
vertical: 6.0,
|
||||
width: double.infinity,
|
||||
child: Focus(
|
||||
focusNode: focusNodes["country_codeFocusNode"],
|
||||
onFocusChange: (hasFocus) {
|
||||
setState(() {
|
||||
focusStates["country_codeFocused"] = hasFocus;
|
||||
});
|
||||
},
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
// Request focus when user taps
|
||||
focusNodes["country_codeFocusNode"]?.requestFocus();
|
||||
},
|
||||
child: DropdownSearch<String>(
|
||||
selectedItem: countryMap[selectedCountry],
|
||||
popupProps: PopupProps.menu(
|
||||
showSearchBox: true, // Enables search functionality
|
||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||
constraints: BoxConstraints(maxHeight: 250),
|
||||
itemBuilder:
|
||||
(context, item, isSelected) => Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
child: Text(
|
||||
item,
|
||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||
),
|
||||
),
|
||||
searchFieldProps: TextFieldProps(
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search ...",
|
||||
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
item,
|
||||
style: GoogleFonts.poppins(fontSize: 11.5),
|
||||
items: countryMap.values.toList(),
|
||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||
dropdownSearchDecoration: InputDecoration(
|
||||
// border: InputBorder.none,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color:
|
||||
(focusStates["country_codeFocused"] ?? false)
|
||||
? widget.layoutColor!
|
||||
: Colors.white,
|
||||
// width: 0.5,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color:
|
||||
(focusStates["country_codeFocused"] ?? false)
|
||||
? widget.layoutColor!
|
||||
: Colors.white,
|
||||
// : const Color(0xFFD6D5E6),
|
||||
// width: 0.5,
|
||||
// const Color(0xFFD6D5E6),
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: widget.layoutColor!, width: 1),
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 10.0,
|
||||
vertical: 8.0,),
|
||||
),
|
||||
),
|
||||
dropdownBuilder:
|
||||
(context, selectedItem) => Align(
|
||||
// Center-align selected item
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
selectedItem ?? "Select ",
|
||||
style: GoogleFonts.poppins(fontSize: 11),
|
||||
),
|
||||
),
|
||||
onChanged: (String? newValue) {
|
||||
setState(() {
|
||||
// Find the country_code based on selected country_name
|
||||
selectedCountry =
|
||||
countryMap.entries
|
||||
.firstWhere((entry) => entry.value == newValue)
|
||||
.key;
|
||||
selectedCountryName = newValue;
|
||||
setCurrencyFromSelectedCountry(selectedCountry!);
|
||||
});
|
||||
},
|
||||
),
|
||||
searchFieldProps: TextFieldProps(
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search ...",
|
||||
hintStyle: GoogleFonts.poppins(fontSize: 11),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||
),
|
||||
),
|
||||
),
|
||||
items: countryMap.values.toList(),
|
||||
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 ",
|
||||
style: GoogleFonts.poppins(fontSize: 11),
|
||||
),
|
||||
),
|
||||
onChanged: (String? newValue) {
|
||||
setState(() {
|
||||
// Find the country_code based on selected country_name
|
||||
selectedCountry =
|
||||
countryMap.entries
|
||||
.firstWhere((entry) => entry.value == newValue)
|
||||
.key;
|
||||
selectedCountryName = newValue;
|
||||
setCurrencyFromSelectedCountry(selectedCountry!);
|
||||
});
|
||||
},
|
||||
),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
if (errorMessages["country_code"] != null) ...[
|
||||
@ -464,7 +526,7 @@ class ForexDataState extends State<ForexData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isFocused: focusStates["currencyFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
|
||||
@ -474,6 +536,7 @@ class ForexDataState extends State<ForexData> {
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
focusNode: focusNodes["currencyFocusNode"],
|
||||
controller: controllers["currency"],
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 11,
|
||||
@ -518,7 +581,7 @@ class ForexDataState extends State<ForexData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isFocused: focusStates["cashFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
width:
|
||||
@ -528,6 +591,7 @@ class ForexDataState extends State<ForexData> {
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
focusNode: focusNodes["cashFocusNode"],
|
||||
controller: controllers["cash"],
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
@ -570,7 +634,7 @@ class ForexDataState extends State<ForexData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isFocused: focusStates["cardFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
width:
|
||||
@ -580,6 +644,7 @@ class ForexDataState extends State<ForexData> {
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
focusNode: focusNodes["cardFocusNode"],
|
||||
controller: controllers["card"],
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
@ -624,12 +689,13 @@ class ForexDataState extends State<ForexData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isFocused: focusStates["perdiemAmountFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
focusNode: focusNodes["perdiemAmountFocusNode"],
|
||||
controller: controllers["perdiemAmount"],
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
|
||||
@ -57,6 +57,8 @@ class _PolicyState extends State<Policy> {
|
||||
// ValueNotifier<String> selectedService = ValueNotifier("Train");
|
||||
bool isViewMode = false;
|
||||
|
||||
Map<String, FocusNode> focusNodes = {};
|
||||
Map<String, bool> focusStates = {};
|
||||
Map<String, String> errorMessages = {};
|
||||
|
||||
String? selectedPolicyId;
|
||||
@ -68,7 +70,7 @@ class _PolicyState extends State<Policy> {
|
||||
String? userId;
|
||||
|
||||
bool showClass = true;
|
||||
bool showCost = true;
|
||||
bool showCost = false; // bool showCost = true; // on 21st june
|
||||
|
||||
List<dynamic>? selectedAllServices;
|
||||
List<Map<String, String>> selectedOrgServiceIds = [];
|
||||
@ -97,6 +99,7 @@ class _PolicyState extends State<Policy> {
|
||||
});
|
||||
}).toList();
|
||||
|
||||
|
||||
Map<String, dynamic> data = {
|
||||
"name": _policyController.text,
|
||||
"domestic": SelectedDomestic,
|
||||
@ -115,6 +118,10 @@ class _PolicyState extends State<Policy> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_checkAuthAndLoadData();
|
||||
// for (var field in dataHeader) {
|
||||
// focusNodes["${field}FocusNode"] = FocusNode();
|
||||
// focusStates["${field}Focused"] = false;
|
||||
// }
|
||||
// WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
@ -1104,18 +1111,21 @@ class _PolicyState extends State<Policy> {
|
||||
// policyCriteriaKey.currentState?.fieldForPolicy();
|
||||
// policyCriteriaKey.currentState
|
||||
// ?.addOrUpdatePolicy(selectedServiceIndex.value);
|
||||
print("policyselectedService - $selectedService");
|
||||
if (selectedService == "Flight" ||
|
||||
selectedService == "Train") {
|
||||
showClass = true;
|
||||
showCost = true;
|
||||
int serviceCode = selectedService == "Flight" ? 1 : 2;
|
||||
|
||||
policyCriteriaKey.currentState
|
||||
?.fetchTrainFlightClass();
|
||||
} else if (selectedService == "Accommodation") {
|
||||
selectedService == "Train" || selectedService == "Accomodation") {
|
||||
showClass = true;
|
||||
showCost = false;
|
||||
} else {
|
||||
int serviceCode = selectedService == "Flight" ? 1 : 2;
|
||||
print("policyselectedService1 - $selectedService");
|
||||
policyCriteriaKey.currentState
|
||||
?.fetchTrainFlightClass();
|
||||
}
|
||||
// else if (selectedService == "Accommodation") {
|
||||
// showClass = true;
|
||||
// showCost = false;
|
||||
// }
|
||||
else {
|
||||
showClass = false;
|
||||
showCost = false;
|
||||
}
|
||||
@ -1330,7 +1340,7 @@ class _PolicyState extends State<Policy> {
|
||||
Text(
|
||||
"Domestic",
|
||||
style: GoogleFonts.poppins(
|
||||
color: _selectedTripType == "1" ? Colors.white : Colors.black,
|
||||
color: _selectedTripType == "1" ? Colors.black : Colors.black,
|
||||
fontWeight: _selectedTripType == "1" ? FontWeight.w600 : null,
|
||||
fontSize: 13,
|
||||
),
|
||||
@ -1356,13 +1366,13 @@ class _PolicyState extends State<Policy> {
|
||||
borderRadius: BorderRadius.circular(4), // Rounded rectangle
|
||||
border: Border.all(
|
||||
color:
|
||||
_selectedTripType == "1" ? Colors.white : Colors.black,
|
||||
_selectedTripType == "1" ? Colors.green : Colors.black,
|
||||
width: _selectedTripType == "1" ? 2 : 1,
|
||||
),
|
||||
),
|
||||
child:
|
||||
_selectedTripType == "1"
|
||||
? Icon(Icons.rectangle, size: 8, color: Colors.white)
|
||||
? Icon(Icons.rectangle, size: 8, color: Colors.green)
|
||||
: null, // Add checkmark if selected
|
||||
),
|
||||
),
|
||||
@ -1387,7 +1397,7 @@ class _PolicyState extends State<Policy> {
|
||||
"International",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 13,
|
||||
color: _selectedTripType == "2" ? Colors.white : Colors.black,
|
||||
color: _selectedTripType == "2" ? Colors.black : Colors.black,
|
||||
fontWeight: _selectedTripType == "2" ? FontWeight.w600 : null,
|
||||
),
|
||||
),
|
||||
@ -1412,13 +1422,13 @@ class _PolicyState extends State<Policy> {
|
||||
borderRadius: BorderRadius.circular(4), // Rounded rectangle
|
||||
border: Border.all(
|
||||
color:
|
||||
_selectedTripType == "2" ? Colors.white : Colors.black,
|
||||
_selectedTripType == "2" ? Colors.green : Colors.black,
|
||||
width: _selectedTripType == "2" ? 2 : 1,
|
||||
),
|
||||
),
|
||||
child:
|
||||
_selectedTripType == "2"
|
||||
? Icon(Icons.rectangle, size: 8, color: Colors.white)
|
||||
? Icon(Icons.rectangle, size: 8, color: Colors.green)
|
||||
: null, // Add checkmark if selected
|
||||
),
|
||||
),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -36,11 +36,12 @@ class TravellerDataState extends State<TravellerData> {
|
||||
final ApiService apiService = ApiService();
|
||||
Map<String, dynamic>? apiData;
|
||||
|
||||
final Map<String, FocusNode> focusNodes = {
|
||||
"name": FocusNode(),
|
||||
"description": FocusNode(),
|
||||
};
|
||||
|
||||
// final Map<String, FocusNode> focusNodes = {
|
||||
// "name": FocusNode(),
|
||||
// "description": FocusNode(),
|
||||
// };
|
||||
Map<String, FocusNode> focusNodes = {};
|
||||
Map<String, bool> focusStates = {};
|
||||
final Map<String, TextEditingController> controllers = {};
|
||||
Map<String, String> errorMessages = {};
|
||||
|
||||
@ -71,6 +72,15 @@ class TravellerDataState extends State<TravellerData> {
|
||||
apiData = null;
|
||||
for (var field in dataHeader) {
|
||||
controllers[field] = TextEditingController();
|
||||
focusNodes["${field}FocusNode"] = FocusNode();
|
||||
focusStates["${field}Focused"] = false;
|
||||
}
|
||||
for (var key in focusNodes.keys) {
|
||||
_addFocusListener(focusNodes[key]!, (focus) {
|
||||
setState(() {
|
||||
focusStates[key.replaceFirst("FocusNode", "Focused")] = focus;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (widget.travellerId != null) {
|
||||
@ -90,8 +100,18 @@ class TravellerDataState extends State<TravellerData> {
|
||||
for (var controller in controllers.values) {
|
||||
controller.dispose();
|
||||
}
|
||||
for (var node in focusNodes.values) {
|
||||
node.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||
node.addListener(() {
|
||||
setState(() {
|
||||
updateState(node.hasFocus);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void updateTravellerDetails() {
|
||||
print("Inside Update Function - ${widget.travellerData}");
|
||||
@ -134,10 +154,10 @@ class TravellerDataState extends State<TravellerData> {
|
||||
if (data[field] == null || data[field]!.trim().isEmpty) {
|
||||
errorMessages[field] = "Required";
|
||||
|
||||
if (!hasFocused) {
|
||||
focusNodes[field]?.requestFocus();
|
||||
hasFocused = true;
|
||||
}
|
||||
// if (!hasFocused) {
|
||||
// focusNodes[field]?.requestFocus();
|
||||
// hasFocused = true;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -286,14 +306,14 @@ class TravellerDataState extends State<TravellerData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isFocused: focusStates["first_nameFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: controllers["first_name"],
|
||||
focusNode: focusNodes["first_name"],
|
||||
focusNode: focusNodes["first_nameFocusNode"],
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
labelText: "First Name",
|
||||
@ -331,14 +351,14 @@ class TravellerDataState extends State<TravellerData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isFocused: focusStates["last_nameFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: controllers["last_name"],
|
||||
focusNode: focusNodes["last_name"],
|
||||
focusNode: focusNodes["last_nameFocusNode"],
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Last Name",
|
||||
@ -376,14 +396,14 @@ class TravellerDataState extends State<TravellerData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isFocused: focusStates["emailFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: controllers["email"],
|
||||
focusNode: focusNodes["email"],
|
||||
focusNode: focusNodes["emailFocusNode"],
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Email",
|
||||
@ -421,14 +441,14 @@ class TravellerDataState extends State<TravellerData> {
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
isFocused: focusStates["mobileFocused"] ?? false,
|
||||
isDesktop: widget.isDesktop,
|
||||
color: Colors.transparent,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: controllers["mobile"],
|
||||
focusNode: focusNodes["mobile"],
|
||||
focusNode: focusNodes["mobileFocusNode"],
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Mobile",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1261,7 +1261,7 @@ class TravellerDetailsState extends State<TravellerDetails> {
|
||||
}
|
||||
|
||||
Widget buildNationality() {
|
||||
List<String> nationalityOptions = ["Indian", "International"];
|
||||
List<String> nationalityOptions = ["Indian", "International","other nationality"];
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
||||
@ -27,7 +27,7 @@ class UserListScreen extends StatefulWidget {
|
||||
class _UserListScreenState extends State<UserListScreen> {
|
||||
final ApiService apiService = ApiService();
|
||||
late Future<List<dynamic>> futureUsers;
|
||||
|
||||
late bool _dialogShown = false;
|
||||
late Map<String, dynamic> userSingleData;
|
||||
List<dynamic>? apiCountryData;
|
||||
String? selectedUserId;
|
||||
@ -219,6 +219,54 @@ class _UserListScreenState extends State<UserListScreen> {
|
||||
print("handDel - $userId");
|
||||
}
|
||||
|
||||
void _showConfirmationDialog(String subtitle, List<String> successList, List<Map<String, String>> failedList) {
|
||||
_dialogShown = true;
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
// title: Text("User Details"),
|
||||
title: Text("User Details - $subtitle", style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Text(subtitle, style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
//
|
||||
// SizedBox(height: 12),
|
||||
Text("Users Created Successfully :", style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
if (successList.isNotEmpty)
|
||||
...successList.asMap().entries.map((entry) => Text("${entry.key + 1}) ${entry.value} created."))
|
||||
else
|
||||
Text("-- There is no data to create. --"),
|
||||
|
||||
SizedBox(height: 12),
|
||||
Text("Failed to Create Users :", style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
if (failedList.isNotEmpty)
|
||||
...failedList.asMap().entries.map((entry) {
|
||||
final data = entry.value["data"] ?? "-";
|
||||
final reason = entry.value["reason"] ?? "Unknown error";
|
||||
return Text("${entry.key + 1}) $data - unable to create due to \"$reason\".");
|
||||
})
|
||||
else
|
||||
Text("-- There is no failed data. --"),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
_dialogShown = false;
|
||||
},
|
||||
child: Text("Close"),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Future<void> handleUpload() async {
|
||||
final String apiUrldata = '$apiUrl/api/user/userUpload'; // api
|
||||
final String? token = await getToken(); // 2kn
|
||||
@ -303,32 +351,51 @@ class _UserListScreenState extends State<UserListScreen> {
|
||||
|
||||
// Check the status code of the response
|
||||
if (response.statusCode == 200) {
|
||||
Map<String, dynamic> data = json.decode(responseString);
|
||||
if (data['status'] == 'success') {
|
||||
print(data['message']);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(data['message']),
|
||||
backgroundColor: Colors.green.shade500,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
refreshUserList();
|
||||
} else {
|
||||
print(data['message']);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(data['message']),
|
||||
backgroundColor: Colors.redAccent,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
refreshUserList();
|
||||
}
|
||||
Map<String, dynamic> responseData = json.decode(responseString);
|
||||
|
||||
final message = responseData['message'] ?? '';
|
||||
final status = responseData['status'] ?? '';
|
||||
final data = responseData['data'] ?? {};
|
||||
|
||||
final List<String> successList = List<String>.from(data['successfulUsers'] ?? []);
|
||||
final List<Map<String, String>> failedList = List<Map<String, String>>.from(
|
||||
(data['failedUsers'] ?? []).map((item) => Map<String, String>.from(item)),
|
||||
);
|
||||
|
||||
_showConfirmationDialog(message, successList, failedList);
|
||||
|
||||
// final successfulUsers = List.from(data['successfulUsers'] ?? []);
|
||||
// final failedUsers = List.from(data['failedUsers'] ?? []);
|
||||
|
||||
// Unified SnackBar logic
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// content: Text(
|
||||
// combinedMessage,
|
||||
// style: TextStyle(color: Colors.white),
|
||||
// ),
|
||||
// backgroundColor: Colors.green,
|
||||
// behavior: SnackBarBehavior.floating,
|
||||
// // duration: Duration(seconds: 6),
|
||||
// ),
|
||||
// );
|
||||
|
||||
// Refresh list if needed
|
||||
refreshUserList();
|
||||
|
||||
} else {
|
||||
print('Something went wrong');
|
||||
print('Failed to upload file: ${response.reasonPhrase}');
|
||||
// For non-200 responses
|
||||
final errorMsg = 'Failed to upload file: ${response.reasonPhrase}';
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(errorMsg),
|
||||
backgroundColor: Colors.redAccent,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
print(errorMsg);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
//api url
|
||||
const String apiUrl = 'http://apitest.tripapprovaltool.com/tstat_be';
|
||||
// const String apiUrl = 'https://uat.tripapprovaltool.com/tstat_be';
|
||||
|
||||
@ -11,6 +11,7 @@ import 'package:frontend/Screens/plans/create_plans.dart';
|
||||
import 'package:frontend/Screens/plans/list_plans.dart';
|
||||
import 'package:frontend/Screens/policy/policy.dart';
|
||||
import 'package:frontend/Screens/policy/policy_list.dart';
|
||||
import 'package:frontend/Screens/userManagement/create_traveller_agent/createTravelAgent.dart';
|
||||
import 'package:frontend/Screens/userManagement/create_user/create_user1.dart';
|
||||
import 'package:frontend/Screens/userManagement/user_List.dart';
|
||||
import 'package:frontend/routes/organizationSetting.dart';
|
||||
@ -39,6 +40,7 @@ import '../Screens/reports/misAir.dart';
|
||||
import '../Screens/reports/misHotel.dart';
|
||||
import '../Screens/reports/misForex.dart';
|
||||
import '../Screens/reports/guestHouse.dart';
|
||||
import '../Screens/userManagement/create_traveller_agent/listTravelAgent.dart';
|
||||
|
||||
import 'mainLayout.dart';
|
||||
|
||||
@ -176,6 +178,14 @@ final GoRouter router = GoRouter(
|
||||
path: '/guestHouseReport',
|
||||
builder: (context, state) => GuestHouse(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/listTravelAgent',
|
||||
builder: (context, state) => TravelAgentListScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/CreateTravelAgent',
|
||||
builder: (context, state) => CreateTravelAgentFormDetials(),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
@ -146,6 +146,12 @@ class OrganizationSettingState extends State<OrganizationSetting> {
|
||||
'label': 'Traveller (Non Employee)',
|
||||
'description': 'Create and Edit Traveller',
|
||||
},
|
||||
{
|
||||
'value': '/listTravelAgent',
|
||||
'icon': Icons.person_pin_outlined,
|
||||
'label': 'Travel Agents',
|
||||
'description': 'Create and Edit Travel Agent',
|
||||
},
|
||||
];
|
||||
|
||||
// List<Widget> rows = [];
|
||||
|
||||
@ -643,25 +643,6 @@ class ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> viewPlanTravelAgent(
|
||||
BuildContext context,
|
||||
String planId, {
|
||||
bool isViewMode = false,
|
||||
bool isMyTrips = false,
|
||||
}) async {
|
||||
try {
|
||||
Map<String, dynamic> planData = await getViewPlanEdit(planId);
|
||||
print("ViewAAA - $planData");
|
||||
|
||||
context.go(
|
||||
'/travelagent/trips',
|
||||
extra: {'planData': planData, 'isViewMode': isViewMode},
|
||||
);
|
||||
} catch (e) {
|
||||
print("Error fetching plan: $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> fetchUserApprovalList() async {
|
||||
String? orgId = await getOrgId();
|
||||
String? userId = await getUserId();
|
||||
@ -1301,6 +1282,25 @@ class ApiService {
|
||||
false; // Default to false if dismissed
|
||||
}
|
||||
|
||||
static Future<void> viewPlanTravelAgent(
|
||||
BuildContext context,
|
||||
String planId, {
|
||||
bool isViewMode = false,
|
||||
bool isMyTrips = false,
|
||||
}) async {
|
||||
try {
|
||||
Map<String, dynamic> planData = await getViewPlanEdit(planId);
|
||||
print("ViewAAA - $planData");
|
||||
|
||||
context.go(
|
||||
'/travelagent/trips',
|
||||
extra: {'planData': planData, 'isViewMode': isViewMode},
|
||||
);
|
||||
} catch (e) {
|
||||
print("Error fetching plan: $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> getCostCenterDetailsFind(int id) async {
|
||||
final String apiUrldata = '$apiUrl/api/findCostCenter?cost_center_id=$id';
|
||||
|
||||
|
||||
@ -63,25 +63,25 @@ class _CustomTextFieldForexWrapperState
|
||||
decoration: BoxDecoration(
|
||||
// color: widget.color,
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: widget.isFocused ? layoutColor! : Color(0xFFD6D5E6),
|
||||
// color: widget.isFocused ? Color(0xFF78B4FC) : Color(0xFFD6D5E6),
|
||||
width: widget.isFocused ? 1.0 : 0.5,
|
||||
),
|
||||
boxShadow:
|
||||
widget.isFocused
|
||||
? [
|
||||
BoxShadow(
|
||||
color: Colors.white,
|
||||
// color: Color.fromRGBO(120, 180, 252, 0.3),
|
||||
// color: Color.fromRGBO(120, 180, 252, 0.3),
|
||||
blurRadius: 5,
|
||||
spreadRadius: 2,
|
||||
offset: Offset(0, 1),
|
||||
),
|
||||
]
|
||||
: [],
|
||||
// boxShadow:
|
||||
// widget.isFocused
|
||||
// ? [
|
||||
// BoxShadow(
|
||||
// color: Colors.white,
|
||||
// // color: Color.fromRGBO(120, 180, 252, 0.3),
|
||||
// // color: Color.fromRGBO(120, 180, 252, 0.3),
|
||||
// blurRadius: 5,
|
||||
// spreadRadius: 2,
|
||||
// offset: Offset(0, 1),
|
||||
// ),
|
||||
// ]
|
||||
// : [],
|
||||
),
|
||||
// decoration: BoxDecoration(
|
||||
// color: widget.color,
|
||||
|
||||
88
lib/widgets/popup_travelAgentList_action.dart
Normal file
88
lib/widgets/popup_travelAgentList_action.dart
Normal file
@ -0,0 +1,88 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../services/apiService.dart';
|
||||
import 'custom_popup.dart';
|
||||
|
||||
class UserActionsMenu extends StatelessWidget {
|
||||
final ApiService apiService = ApiService();
|
||||
final Map<String, dynamic> user;
|
||||
final Future<Map<String, dynamic>> Function(int userId) getUserDetails;
|
||||
|
||||
UserActionsMenu({
|
||||
super.key,
|
||||
required this.user,
|
||||
required this.getUserDetails,
|
||||
});
|
||||
|
||||
int getUserId(dynamic value) {
|
||||
if (value is String) return int.parse(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PopupMenuButton<int>(
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.zero,
|
||||
offset: Offset(0, 30),
|
||||
icon: Icon(
|
||||
Icons.more_vert,
|
||||
color: Color(0xFF475569),
|
||||
size: 14,
|
||||
),
|
||||
itemBuilder: (context) => [
|
||||
CustomPopupMenuEntry(
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
GestureDetector(
|
||||
child: Tooltip(
|
||||
message: 'View Details',
|
||||
child: Icon(Icons.remove_red_eye,
|
||||
color: Color(0xFF475569), size: 18)
|
||||
),
|
||||
// child: Icon(Icons.remove_red_eye,
|
||||
// color: Color(0xFF475569), size: 18,),
|
||||
onTap: () async {
|
||||
Navigator.pop(context); // Close the menu
|
||||
final userId = getUserId(user['user_id']);
|
||||
final usersData = await getUserDetails(userId);
|
||||
context.go("/CreateTravelAgent", extra: {
|
||||
"selectedUser": usersData,
|
||||
"isViewMode": true,
|
||||
});
|
||||
},
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
GestureDetector(
|
||||
child: Tooltip(
|
||||
message: 'Edit Details',
|
||||
child: Image.asset(
|
||||
'assets/images/IconsImg/edit.png',
|
||||
width: 20,
|
||||
height: 15,
|
||||
),
|
||||
),
|
||||
onTap: () async {
|
||||
Navigator.pop(context); // Close the menu
|
||||
final userId = getUserId(user['user_id']);
|
||||
final usersData = await getUserDetails(userId);
|
||||
context.go("/CreateTravelAgent", extra: {
|
||||
"selectedUser": usersData,
|
||||
"isViewMode": false,
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user