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,20 +458,34 @@ class HotelsDataState extends State<HotelsData> {
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||
isDesktop: widget.isDesktop,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
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),
|
||||
constraints: BoxConstraints(maxHeight: 200),
|
||||
itemBuilder:
|
||||
(context, item, isSelected) => Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8.0,
|
||||
vertical: 6.0,
|
||||
horizontal: 10.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
child: Text(
|
||||
item,
|
||||
@ -463,8 +503,33 @@ class HotelsDataState extends State<HotelsData> {
|
||||
items: countryMap.values.toList(),
|
||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||
dropdownSearchDecoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||
// 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:
|
||||
@ -487,6 +552,8 @@ class HotelsDataState extends State<HotelsData> {
|
||||
});
|
||||
},
|
||||
),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
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,9 +404,23 @@ class ForexDataState extends State<ForexData> {
|
||||
SizedBox(height: 5),
|
||||
CustomTextFieldForexWrapper(
|
||||
isFocused: false,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 0),
|
||||
isDesktop: widget.isDesktop,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
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(
|
||||
@ -395,8 +430,8 @@ class ForexDataState extends State<ForexData> {
|
||||
itemBuilder:
|
||||
(context, item, isSelected) => Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8.0,
|
||||
vertical: 6.0,
|
||||
horizontal: 10.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
child: Text(
|
||||
item,
|
||||
@ -414,8 +449,33 @@ class ForexDataState extends State<ForexData> {
|
||||
items: countryMap.values.toList(),
|
||||
dropdownDecoratorProps: DropDownDecoratorProps(
|
||||
dropdownSearchDecoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 1),
|
||||
// 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:
|
||||
@ -439,6 +499,8 @@ class ForexDataState extends State<ForexData> {
|
||||
});
|
||||
},
|
||||
),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
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
@ -112,9 +112,12 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
|
||||
String getTabName(int index) {
|
||||
switch (index) {
|
||||
case 0: return "domestic";
|
||||
case 1: return "international";
|
||||
default: return "domestic"; // return "Unknown";
|
||||
case 0:
|
||||
return "domestic";
|
||||
case 1:
|
||||
return "international";
|
||||
default:
|
||||
return "domestic"; // return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
@ -332,35 +335,62 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
excelName,
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
backgroundColor: Colors.green,
|
||||
content: Text(result as String),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// backgroundColor: result['status'] ? Colors.green : Colors.red,
|
||||
// content: Text(result['message']),
|
||||
// behavior: SnackBarBehavior.floating,
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
|
||||
void handleDomesticFilter(String query) {
|
||||
|
||||
final lowerQuery = query.toLowerCase();
|
||||
setState(() {
|
||||
filteredDomestic =
|
||||
domesticData.where((object) {
|
||||
return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['customer_name']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_class']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_travel_date']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
final travelDateRaw = object['flight_travel_date'];
|
||||
String formattedDate = '';
|
||||
|
||||
if (travelDateRaw != null && travelDateRaw is String) {
|
||||
try {
|
||||
final parsedDate = DateTime.parse(travelDateRaw);
|
||||
formattedDate =
|
||||
'${parsedDate.day.toString().padLeft(2, '0')}-${parsedDate.month.toString().padLeft(2, '0')}-${parsedDate.year}';
|
||||
} catch (e) {
|
||||
// fallback if date is not parsable
|
||||
formattedDate = travelDateRaw;
|
||||
}
|
||||
}
|
||||
|
||||
return (object['plan_id']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['employee_code']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['customer_name']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['so_number']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['functional_department']?.toLowerCase().contains(
|
||||
lowerQuery,
|
||||
) ??
|
||||
false) ||
|
||||
(object['flight_trip_type']?.toLowerCase().contains(
|
||||
lowerQuery,
|
||||
) ??
|
||||
false) ||
|
||||
(object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['flight_class']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(formattedDate.toLowerCase().contains(lowerQuery)) ||
|
||||
(object['sector']?.toLowerCase().contains(lowerQuery));
|
||||
}).toList();
|
||||
currentPage1 = 0;
|
||||
});
|
||||
print("handleDomesticFilter > Total entries: ${filteredDomestic?.length ?? 0}");
|
||||
print(
|
||||
"handleDomesticFilter > Total entries: ${filteredDomestic?.length ?? 0}",
|
||||
);
|
||||
}
|
||||
|
||||
void handleInternationalFilter(String query) {
|
||||
@ -368,23 +398,49 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
setState(() {
|
||||
filteredInternational =
|
||||
internationalData.where((object) {
|
||||
return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['customer_name']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_class']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_travel_date']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
final travelDateRaw = object['flight_travel_date'];
|
||||
String formattedDate = '';
|
||||
|
||||
if (travelDateRaw != null && travelDateRaw is String) {
|
||||
try {
|
||||
final parsedDate = DateTime.parse(travelDateRaw);
|
||||
formattedDate =
|
||||
'${parsedDate.day.toString().padLeft(2, '0')}-${parsedDate.month.toString().padLeft(2, '0')}-${parsedDate.year}';
|
||||
} catch (e) {
|
||||
// fallback if date is not parsable
|
||||
formattedDate = travelDateRaw;
|
||||
}
|
||||
}
|
||||
return (object['plan_id']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['employee_code']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['customer_name']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['so_number']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['functional_department']?.toLowerCase().contains(
|
||||
lowerQuery,
|
||||
) ??
|
||||
false) ||
|
||||
(object['flight_trip_type']?.toLowerCase().contains(
|
||||
lowerQuery,
|
||||
) ??
|
||||
false) ||
|
||||
(object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['flight_class']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(formattedDate.toLowerCase().contains(lowerQuery)) ||
|
||||
(object['sector']?.toLowerCase().contains(lowerQuery));
|
||||
}).toList();
|
||||
currentPage2 = 0;
|
||||
});
|
||||
print("handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}");
|
||||
print(
|
||||
"handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
// Widget build(BuildContext context) {
|
||||
// // TODO: implement build
|
||||
@ -456,7 +512,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
children: [
|
||||
buildTitle(isDesktop),
|
||||
Spacer(),
|
||||
buildExports(isDesktop)
|
||||
buildExports(isDesktop),
|
||||
],
|
||||
)
|
||||
: Column(
|
||||
@ -464,9 +520,9 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
children: [
|
||||
buildTitle(isDesktop),
|
||||
SizedBox(height: 8),
|
||||
buildExports(isDesktop)
|
||||
buildExports(isDesktop),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
|
||||
@ -523,13 +579,34 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
: domesticData.isEmpty
|
||||
? Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Text(
|
||||
"No data found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.of(context).size.height / 4,
|
||||
),
|
||||
Text(
|
||||
"No Records Found",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Please ensure the selected dates contain report data.",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -561,7 +638,9 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width * 0.2,
|
||||
width:
|
||||
MediaQuery.of(context).size.width *
|
||||
0.2,
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: searchDomesticController,
|
||||
@ -578,24 +657,32 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
size: 18,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade200,
|
||||
width: 0.5,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade300,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
style: GoogleFonts.poppins(fontSize: 12),
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
// SizedBox(width: 16),
|
||||
@ -703,8 +790,10 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
final double minWidth =
|
||||
isDesktop ? constraints.maxWidth : 1300;
|
||||
|
||||
List<Map<String, dynamic>> newDomesticData =filteredDomestic.isNotEmpty ? filteredDomestic : domesticData;
|
||||
|
||||
List<Map<String, dynamic>> newDomesticData =
|
||||
filteredDomestic.isNotEmpty
|
||||
? filteredDomestic
|
||||
: domesticData;
|
||||
|
||||
// Pagination logic
|
||||
List<Map<String, dynamic>>
|
||||
@ -714,14 +803,43 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
.take(itemsPerPage1)
|
||||
.toList();
|
||||
|
||||
return (
|
||||
(searchDomesticController.text.isNotEmpty && filteredDomestic.isEmpty)
|
||||
return ((searchDomesticController
|
||||
.text
|
||||
.isNotEmpty &&
|
||||
filteredDomestic.isEmpty)
|
||||
? Center(
|
||||
child: Text(
|
||||
"No data found",
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.of(
|
||||
context,
|
||||
).size.height /
|
||||
4,
|
||||
),
|
||||
Text(
|
||||
"No Records Found",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Please ensure the selected dates contain report data.",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -729,17 +847,21 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
scrollDirection:
|
||||
Axis.horizontal,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: minWidth,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
scrollDirection:
|
||||
Axis.vertical,
|
||||
child: DataTable(
|
||||
dividerThickness: 0.5,
|
||||
columnSpacing:
|
||||
isDesktop ? 30.0 : 24.0,
|
||||
isDesktop
|
||||
? 30.0
|
||||
: 24.0,
|
||||
border: TableBorder(
|
||||
horizontalInside:
|
||||
BorderSide(
|
||||
@ -877,8 +999,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['plan_id']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -887,8 +1008,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['employee_code']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -897,8 +1017,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['so_number']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -907,8 +1026,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['functional_department']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -917,8 +1035,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['flight_trip_type']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -927,8 +1044,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['plan_trip_type']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -937,8 +1053,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['sector']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -947,8 +1062,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['flight_class']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -957,8 +1071,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
flightTravelDate,
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -977,7 +1090,8 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
PaginationControls(
|
||||
currentPage: currentPage1,
|
||||
itemsPerPage: itemsPerPage1,
|
||||
totalItems: newDomesticData.length,
|
||||
totalItems:
|
||||
newDomesticData.length,
|
||||
activeColor: layoutColor,
|
||||
onPageChanged: (page) {
|
||||
setState(() {
|
||||
@ -1003,13 +1117,34 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
internationalData.isEmpty
|
||||
? Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Text(
|
||||
"No data found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.of(context).size.height / 4,
|
||||
),
|
||||
Text(
|
||||
"No Records Found",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Please ensure the selected dates contain report data.",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -1140,7 +1275,8 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
vertical: 8,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
/// Title on the left
|
||||
@ -1152,17 +1288,21 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.grey[700],
|
||||
),
|
||||
overflow: TextOverflow.ellipsis, // Ensures title doesn't overflow
|
||||
overflow:
|
||||
TextOverflow
|
||||
.ellipsis, // Ensures title doesn't overflow
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
SizedBox(width: 16),
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width * 0.2,
|
||||
width:
|
||||
MediaQuery.of(context).size.width *
|
||||
0.2,
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: searchInternationalController,
|
||||
controller:
|
||||
searchInternationalController,
|
||||
onChanged: handleInternationalFilter,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search ...",
|
||||
@ -1176,27 +1316,36 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
size: 18,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade200,
|
||||
width: 0.5,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade300,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
style: GoogleFonts.poppins(fontSize: 12),
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
])
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height:
|
||||
@ -1209,7 +1358,11 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
builder: (context, constraints) {
|
||||
final double minWidth =
|
||||
isDesktop ? constraints.maxWidth : 1300;
|
||||
List<Map<String, dynamic>> newInternationalData =filteredInternational.isNotEmpty ? filteredInternational : internationalData;
|
||||
List<Map<String, dynamic>>
|
||||
newInternationalData =
|
||||
filteredInternational.isNotEmpty
|
||||
? filteredInternational
|
||||
: internationalData;
|
||||
// Pagination logic
|
||||
List<Map<String, dynamic>>
|
||||
paginatedInternational =
|
||||
@ -1218,31 +1371,65 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
.take(itemsPerPage2)
|
||||
.toList();
|
||||
|
||||
return ((searchInternationalController.text.isNotEmpty && filteredInternational.isEmpty)
|
||||
return ((searchInternationalController
|
||||
.text
|
||||
.isNotEmpty &&
|
||||
filteredInternational.isEmpty)
|
||||
? Center(
|
||||
child: Text(
|
||||
"No data found",
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.of(
|
||||
context,
|
||||
).size.height /
|
||||
4,
|
||||
),
|
||||
Text(
|
||||
"No Records Found",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Please ensure the selected dates contain report data.",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
:Column(
|
||||
: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
scrollDirection:
|
||||
Axis.horizontal,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: minWidth,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
scrollDirection:
|
||||
Axis.vertical,
|
||||
child: DataTable(
|
||||
dividerThickness: 0.5,
|
||||
columnSpacing:
|
||||
isDesktop ? 30.0 : 24.0,
|
||||
isDesktop
|
||||
? 30.0
|
||||
: 24.0,
|
||||
border: TableBorder(
|
||||
horizontalInside:
|
||||
BorderSide(
|
||||
@ -1390,8 +1577,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['plan_id']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1400,8 +1586,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['employee_code']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1410,8 +1595,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['so_number']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1420,8 +1604,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['functional_department']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1430,8 +1613,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['flight_trip_type']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1440,8 +1622,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['plan_trip_type']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1450,8 +1631,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['sector']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1460,8 +1640,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['flight_class']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1470,8 +1649,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
DataCell(
|
||||
Text(
|
||||
flightTravelDate,
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1490,7 +1668,8 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
PaginationControls(
|
||||
currentPage: currentPage2,
|
||||
itemsPerPage: itemsPerPage2,
|
||||
totalItems: newInternationalData.length,
|
||||
totalItems:
|
||||
newInternationalData.length,
|
||||
activeColor: layoutColor,
|
||||
onPageChanged: (page) {
|
||||
setState(() {
|
||||
@ -1523,7 +1702,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildTitle(bool isDesktop){
|
||||
Widget buildTitle(bool isDesktop) {
|
||||
return // Left side: Breadcrumb inside a Container (optional)
|
||||
Container(
|
||||
child: BreadcrumbNavigation(
|
||||
@ -1535,17 +1714,15 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
onTap: (context) {
|
||||
// Navigator.pushNamed(context, '/report');
|
||||
context.go("/report");
|
||||
}
|
||||
),
|
||||
BreadcrumbItem(
|
||||
title: 'Guest House',
|
||||
},
|
||||
),
|
||||
BreadcrumbItem(title: 'Guest House'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildExports(bool isDesktop){
|
||||
Widget buildExports(bool isDesktop) {
|
||||
return Row(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
@ -1555,10 +1732,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 12,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
),
|
||||
onPressed: handleDownload,
|
||||
child: Row(
|
||||
@ -1571,11 +1745,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Icon(
|
||||
Icons.file_present_outlined,
|
||||
size: 15,
|
||||
color: Colors.white,
|
||||
),
|
||||
Icon(Icons.file_present_outlined, size: 15, color: Colors.white),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -1608,14 +1778,14 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
// ),
|
||||
],
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
Widget buildFromDateField(bool isDesktop) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text( "From Date *",
|
||||
Text(
|
||||
"From Date *",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
@ -1657,12 +1827,9 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
),
|
||||
floatingLabelBehavior:
|
||||
FloatingLabelBehavior.never,
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
border: InputBorder.none,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||
suffixIcon: const Icon(
|
||||
Icons.calendar_today,
|
||||
size: 16,
|
||||
@ -1689,7 +1856,8 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text( "To Date *",
|
||||
Text(
|
||||
"To Date *",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
@ -1705,13 +1873,10 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
height: 40,
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
final fromDateText =
|
||||
textControllers["from_date"]?.text;
|
||||
final fromDateText = textControllers["from_date"]?.text;
|
||||
DateTime? mintoDate;
|
||||
if (fromDateText != null && fromDateText.isNotEmpty) {
|
||||
mintoDate = DateFormat(
|
||||
'dd-MM-yyyy',
|
||||
).parse(fromDateText);
|
||||
mintoDate = DateFormat('dd-MM-yyyy').parse(fromDateText);
|
||||
}
|
||||
|
||||
final pickedDate = await showDatePicker(
|
||||
@ -1735,16 +1900,10 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Select Date",
|
||||
labelStyle: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
),
|
||||
floatingLabelBehavior:
|
||||
FloatingLabelBehavior.never,
|
||||
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||
suffixIcon: Icon(
|
||||
Icons.calendar_today,
|
||||
size: 16,
|
||||
@ -1763,8 +1922,7 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
style: const TextStyle(color: Colors.red, fontSize: 12),
|
||||
maxLines: 2, // Allow it to wrap onto two lines
|
||||
overflow:
|
||||
TextOverflow
|
||||
.ellipsis, // Add ellipsis if it still overflows
|
||||
TextOverflow.ellipsis, // Add ellipsis if it still overflows
|
||||
),
|
||||
],
|
||||
],
|
||||
@ -1772,11 +1930,8 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
}
|
||||
|
||||
Widget buildSearchButton(bool isDesktop) {
|
||||
return
|
||||
Padding(
|
||||
padding: isDesktop
|
||||
? const EdgeInsets.only(top: 22)
|
||||
: EdgeInsets.zero,
|
||||
return Padding(
|
||||
padding: isDesktop ? const EdgeInsets.only(top: 22) : EdgeInsets.zero,
|
||||
child: SizedBox(
|
||||
width: isDesktop ? null : double.infinity,
|
||||
child: ElevatedButton(
|
||||
@ -1789,23 +1944,17 @@ class _GuestHouseState extends State<GuestHouse>
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 12,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
),
|
||||
onPressed: () {
|
||||
handleSubmit();
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize:
|
||||
MainAxisSize.min, // Ensures content fits nicely
|
||||
mainAxisSize: MainAxisSize.min, // Ensures content fits nicely
|
||||
children: [
|
||||
Text(
|
||||
"Search",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: isDesktop ? 13 : 11,
|
||||
),
|
||||
style: GoogleFonts.poppins(fontSize: isDesktop ? 13 : 11),
|
||||
),
|
||||
SizedBox(width: 8), // spacing between icon and text
|
||||
Icon(Icons.search, size: 15, color: Colors.white),
|
||||
|
||||
@ -111,9 +111,12 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
|
||||
String getTabName(int index) {
|
||||
switch (index) {
|
||||
case 0: return "domestic";
|
||||
case 1: return "international";
|
||||
default: return "domestic"; // return "Unknown";
|
||||
case 0:
|
||||
return "domestic";
|
||||
case 1:
|
||||
return "international";
|
||||
default:
|
||||
return "domestic"; // return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,13 +334,13 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
excelName,
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
backgroundColor: Colors.green,
|
||||
content: Text(result as String),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// backgroundColor: result['status'] ? Colors.green : Colors.red,
|
||||
// content: Text(result['message']),
|
||||
// behavior: SnackBarBehavior.floating,
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
|
||||
void handleDomesticFilter(String query) {
|
||||
@ -345,20 +348,48 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
setState(() {
|
||||
filteredDomestic =
|
||||
domesticData.where((object) {
|
||||
return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['customer_name']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_class']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_travel_date']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
final travelDateRaw = object['flight_travel_date'];
|
||||
String formattedDate = '';
|
||||
|
||||
if (travelDateRaw != null && travelDateRaw is String) {
|
||||
try {
|
||||
final parsedDate = DateTime.parse(travelDateRaw);
|
||||
formattedDate =
|
||||
'${parsedDate.day.toString().padLeft(2, '0')}-${parsedDate.month.toString().padLeft(2, '0')}-${parsedDate.year}';
|
||||
} catch (e) {
|
||||
// fallback if date is not parsable
|
||||
formattedDate = travelDateRaw;
|
||||
}
|
||||
}
|
||||
|
||||
return (object['plan_id']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['employee_code']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['customer_name']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['so_number']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['functional_department']?.toLowerCase().contains(
|
||||
lowerQuery,
|
||||
) ??
|
||||
false) ||
|
||||
(object['flight_trip_type']?.toLowerCase().contains(
|
||||
lowerQuery,
|
||||
) ??
|
||||
false) ||
|
||||
(object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['flight_class']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(formattedDate.toLowerCase().contains(lowerQuery)) ||
|
||||
(object['sector']?.toLowerCase().contains(lowerQuery));
|
||||
}).toList();
|
||||
currentPage1 = 0;
|
||||
});
|
||||
print("handleDomesticFilter > Total entries: ${filteredDomestic?.length ?? 0}");
|
||||
print(
|
||||
"handleDomesticFilter > Total entries: ${filteredDomestic?.length ?? 0}",
|
||||
);
|
||||
}
|
||||
|
||||
void handleInternationalFilter(String query) {
|
||||
@ -366,23 +397,50 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
setState(() {
|
||||
filteredInternational =
|
||||
internationalData.where((object) {
|
||||
return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['customer_name']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_class']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_travel_date']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
final travelDateRaw = object['flight_travel_date'];
|
||||
String formattedDate = '';
|
||||
|
||||
if (travelDateRaw != null && travelDateRaw is String) {
|
||||
try {
|
||||
final parsedDate = DateTime.parse(travelDateRaw);
|
||||
formattedDate =
|
||||
'${parsedDate.day.toString().padLeft(2, '0')}-${parsedDate.month.toString().padLeft(2, '0')}-${parsedDate.year}';
|
||||
} catch (e) {
|
||||
// fallback if date is not parsable
|
||||
formattedDate = travelDateRaw;
|
||||
}
|
||||
}
|
||||
|
||||
return (object['plan_id']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['employee_code']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['customer_name']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['so_number']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['functional_department']?.toLowerCase().contains(
|
||||
lowerQuery,
|
||||
) ??
|
||||
false) ||
|
||||
(object['flight_trip_type']?.toLowerCase().contains(
|
||||
lowerQuery,
|
||||
) ??
|
||||
false) ||
|
||||
(object['plan_trip_type']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['flight_class']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(formattedDate.toLowerCase().contains(lowerQuery)) ||
|
||||
(object['sector']?.toLowerCase().contains(lowerQuery));
|
||||
}).toList();
|
||||
currentPage2 = 0;
|
||||
});
|
||||
print("handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}");
|
||||
print(
|
||||
"handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
// Widget build(BuildContext context) {
|
||||
// // TODO: implement build
|
||||
@ -454,7 +512,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
children: [
|
||||
buildTitle(isDesktop),
|
||||
Spacer(),
|
||||
buildExports(isDesktop)
|
||||
buildExports(isDesktop),
|
||||
],
|
||||
)
|
||||
: Column(
|
||||
@ -462,9 +520,9 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
children: [
|
||||
buildTitle(isDesktop),
|
||||
SizedBox(height: 8),
|
||||
buildExports(isDesktop)
|
||||
buildExports(isDesktop),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
|
||||
@ -521,13 +579,34 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
: domesticData.isEmpty
|
||||
? Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Text(
|
||||
"No data found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.of(context).size.height / 4,
|
||||
),
|
||||
Text(
|
||||
"No Records Found",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Please ensure the selected dates contain report data.",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -559,7 +638,9 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width * 0.2,
|
||||
width:
|
||||
MediaQuery.of(context).size.width *
|
||||
0.2,
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: searchDomesticController,
|
||||
@ -576,24 +657,32 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
size: 18,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade200,
|
||||
width: 0.5,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade300,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
style: GoogleFonts.poppins(fontSize: 12),
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
// SizedBox(width: 16),
|
||||
@ -701,8 +790,10 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
final double minWidth =
|
||||
isDesktop ? constraints.maxWidth : 1300;
|
||||
|
||||
List<Map<String, dynamic>> newDomesticData =filteredDomestic.isNotEmpty ? filteredDomestic : domesticData;
|
||||
|
||||
List<Map<String, dynamic>> newDomesticData =
|
||||
filteredDomestic.isNotEmpty
|
||||
? filteredDomestic
|
||||
: domesticData;
|
||||
|
||||
// Pagination logic
|
||||
List<Map<String, dynamic>>
|
||||
@ -712,14 +803,43 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
.take(itemsPerPage1)
|
||||
.toList();
|
||||
|
||||
return (
|
||||
(searchDomesticController.text.isNotEmpty && filteredDomestic.isEmpty)
|
||||
return ((searchDomesticController
|
||||
.text
|
||||
.isNotEmpty &&
|
||||
filteredDomestic.isEmpty)
|
||||
? Center(
|
||||
child: Text(
|
||||
"No data found",
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.of(
|
||||
context,
|
||||
).size.height /
|
||||
4,
|
||||
),
|
||||
Text(
|
||||
"No Records Found",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Please ensure the selected dates contain report data.",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -727,17 +847,21 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
scrollDirection:
|
||||
Axis.horizontal,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: minWidth,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
scrollDirection:
|
||||
Axis.vertical,
|
||||
child: DataTable(
|
||||
dividerThickness: 0.5,
|
||||
columnSpacing:
|
||||
isDesktop ? 30.0 : 24.0,
|
||||
isDesktop
|
||||
? 30.0
|
||||
: 24.0,
|
||||
border: TableBorder(
|
||||
horizontalInside:
|
||||
BorderSide(
|
||||
@ -875,8 +999,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['plan_id']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -885,8 +1008,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['employee_code']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -895,8 +1017,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['so_number']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -905,8 +1026,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['functional_department']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -915,8 +1035,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['flight_trip_type']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -925,8 +1044,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['plan_trip_type']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -935,8 +1053,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['sector']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -945,8 +1062,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['flight_class']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -955,8 +1071,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
TravelDate,
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -975,7 +1090,8 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
PaginationControls(
|
||||
currentPage: currentPage1,
|
||||
itemsPerPage: itemsPerPage1,
|
||||
totalItems: newDomesticData.length,
|
||||
totalItems:
|
||||
newDomesticData.length,
|
||||
activeColor: layoutColor,
|
||||
onPageChanged: (page) {
|
||||
setState(() {
|
||||
@ -1138,7 +1254,8 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
vertical: 8,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
/// Title on the left
|
||||
@ -1150,17 +1267,21 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.grey[700],
|
||||
),
|
||||
overflow: TextOverflow.ellipsis, // Ensures title doesn't overflow
|
||||
overflow:
|
||||
TextOverflow
|
||||
.ellipsis, // Ensures title doesn't overflow
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
SizedBox(width: 16),
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width * 0.2,
|
||||
width:
|
||||
MediaQuery.of(context).size.width *
|
||||
0.2,
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: searchInternationalController,
|
||||
controller:
|
||||
searchInternationalController,
|
||||
onChanged: handleInternationalFilter,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search ...",
|
||||
@ -1174,27 +1295,36 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
size: 18,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade200,
|
||||
width: 0.5,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade300,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
style: GoogleFonts.poppins(fontSize: 12),
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
])
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height:
|
||||
@ -1207,7 +1337,11 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
builder: (context, constraints) {
|
||||
final double minWidth =
|
||||
isDesktop ? constraints.maxWidth : 1300;
|
||||
List<Map<String, dynamic>> newInternationalData =filteredInternational.isNotEmpty ? filteredInternational : internationalData;
|
||||
List<Map<String, dynamic>>
|
||||
newInternationalData =
|
||||
filteredInternational.isNotEmpty
|
||||
? filteredInternational
|
||||
: internationalData;
|
||||
// Pagination logic
|
||||
List<Map<String, dynamic>>
|
||||
paginatedInternational =
|
||||
@ -1216,7 +1350,10 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
.take(itemsPerPage2)
|
||||
.toList();
|
||||
|
||||
return ((searchInternationalController.text.isNotEmpty && filteredInternational.isEmpty)
|
||||
return ((searchInternationalController
|
||||
.text
|
||||
.isNotEmpty &&
|
||||
filteredInternational.isEmpty)
|
||||
? Center(
|
||||
child: Text(
|
||||
"No data found",
|
||||
@ -1230,17 +1367,21 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
scrollDirection:
|
||||
Axis.horizontal,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: minWidth,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
scrollDirection:
|
||||
Axis.vertical,
|
||||
child: DataTable(
|
||||
dividerThickness: 0.5,
|
||||
columnSpacing:
|
||||
isDesktop ? 30.0 : 24.0,
|
||||
isDesktop
|
||||
? 30.0
|
||||
: 24.0,
|
||||
border: TableBorder(
|
||||
horizontalInside:
|
||||
BorderSide(
|
||||
@ -1378,8 +1519,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['plan_id']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1388,8 +1528,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['employee_code']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1398,8 +1537,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['so_number']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1408,8 +1546,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['functional_department']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1418,8 +1555,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['flight_trip_type']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1428,8 +1564,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['plan_trip_type']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1438,8 +1573,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['sector']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1448,8 +1582,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['flight_class']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1458,8 +1591,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
DataCell(
|
||||
Text(
|
||||
TravelDate,
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1478,7 +1610,8 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
PaginationControls(
|
||||
currentPage: currentPage2,
|
||||
itemsPerPage: itemsPerPage2,
|
||||
totalItems: internationalData.length,
|
||||
totalItems:
|
||||
internationalData.length,
|
||||
activeColor: layoutColor,
|
||||
onPageChanged: (page) {
|
||||
setState(() {
|
||||
@ -1510,7 +1643,8 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
),
|
||||
);
|
||||
}
|
||||
Widget buildTitle(bool isDesktop){
|
||||
|
||||
Widget buildTitle(bool isDesktop) {
|
||||
return // Left side: Breadcrumb inside a Container (optional)
|
||||
Container(
|
||||
child: BreadcrumbNavigation(
|
||||
@ -1522,16 +1656,15 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
onTap: (context) {
|
||||
// Navigator.pushNamed(context, '/report');
|
||||
context.go("/report");
|
||||
}
|
||||
),
|
||||
BreadcrumbItem(
|
||||
title: 'MIS Air Report ',
|
||||
},
|
||||
),
|
||||
BreadcrumbItem(title: 'MIS Air Report '),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
Widget buildExports(bool isDesktop){
|
||||
|
||||
Widget buildExports(bool isDesktop) {
|
||||
return Row(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
@ -1541,10 +1674,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 12,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
),
|
||||
onPressed: handleDownload,
|
||||
child: Row(
|
||||
@ -1557,11 +1687,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Icon(
|
||||
Icons.file_present_outlined,
|
||||
size: 15,
|
||||
color: Colors.white,
|
||||
),
|
||||
Icon(Icons.file_present_outlined, size: 15, color: Colors.white),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -1594,14 +1720,14 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
// ),
|
||||
],
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
Widget buildFromDateField(bool isDesktop) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text( "From Date *",
|
||||
Text(
|
||||
"From Date *",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
@ -1643,12 +1769,9 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
),
|
||||
floatingLabelBehavior:
|
||||
FloatingLabelBehavior.never,
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
border: InputBorder.none,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||
suffixIcon: const Icon(
|
||||
Icons.calendar_today,
|
||||
size: 16,
|
||||
@ -1675,7 +1798,8 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text( "To Date *",
|
||||
Text(
|
||||
"To Date *",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
@ -1691,13 +1815,10 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
height: 40,
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
final fromDateText =
|
||||
textControllers["from_date"]?.text;
|
||||
final fromDateText = textControllers["from_date"]?.text;
|
||||
DateTime? mintoDate;
|
||||
if (fromDateText != null && fromDateText.isNotEmpty) {
|
||||
mintoDate = DateFormat(
|
||||
'dd-MM-yyyy',
|
||||
).parse(fromDateText);
|
||||
mintoDate = DateFormat('dd-MM-yyyy').parse(fromDateText);
|
||||
}
|
||||
|
||||
final pickedDate = await showDatePicker(
|
||||
@ -1722,16 +1843,10 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Select Date",
|
||||
labelStyle: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
),
|
||||
floatingLabelBehavior:
|
||||
FloatingLabelBehavior.never,
|
||||
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||
suffixIcon: Icon(
|
||||
Icons.calendar_today,
|
||||
size: 16,
|
||||
@ -1750,8 +1865,7 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
style: const TextStyle(color: Colors.red, fontSize: 12),
|
||||
maxLines: 2, // Allow it to wrap onto two lines
|
||||
overflow:
|
||||
TextOverflow
|
||||
.ellipsis, // Add ellipsis if it still overflows
|
||||
TextOverflow.ellipsis, // Add ellipsis if it still overflows
|
||||
),
|
||||
],
|
||||
],
|
||||
@ -1759,11 +1873,8 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
}
|
||||
|
||||
Widget buildSearchButton(bool isDesktop) {
|
||||
return
|
||||
Padding(
|
||||
padding: isDesktop
|
||||
? const EdgeInsets.only(top: 22)
|
||||
: EdgeInsets.zero,
|
||||
return Padding(
|
||||
padding: isDesktop ? const EdgeInsets.only(top: 22) : EdgeInsets.zero,
|
||||
child: SizedBox(
|
||||
width: isDesktop ? null : double.infinity,
|
||||
child: ElevatedButton(
|
||||
@ -1776,23 +1887,17 @@ class _MISairState extends State<MISair> with SingleTickerProviderStateMixin {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 12,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
),
|
||||
onPressed: () {
|
||||
handleSubmit();
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize:
|
||||
MainAxisSize.min, // Ensures content fits nicely
|
||||
mainAxisSize: MainAxisSize.min, // Ensures content fits nicely
|
||||
children: [
|
||||
Text(
|
||||
"Search",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: isDesktop ? 13 : 11,
|
||||
),
|
||||
style: GoogleFonts.poppins(fontSize: isDesktop ? 13 : 11),
|
||||
),
|
||||
SizedBox(width: 8), // spacing between icon and text
|
||||
Icon(Icons.search, size: 15, color: Colors.white),
|
||||
|
||||
@ -78,7 +78,6 @@ class _MISforexState extends State<MISforex>
|
||||
focusStates["from_date"] = false;
|
||||
}
|
||||
|
||||
|
||||
// Add focus listeners
|
||||
focusNodes.forEach((key, focusNode) {
|
||||
_addFocusListener(focusNode, (focus) {
|
||||
@ -92,7 +91,6 @@ class _MISforexState extends State<MISforex>
|
||||
// fetchMISforexReport();
|
||||
}
|
||||
|
||||
|
||||
void _addFocusListener(FocusNode node, Function(bool) updateState) {
|
||||
node.addListener(() {
|
||||
setState(() {
|
||||
@ -243,9 +241,7 @@ class _MISforexState extends State<MISforex>
|
||||
setState(() {
|
||||
// domesticData = List<Map<String, dynamic>>.from(result['data']['domestic'] ?? []);
|
||||
internationalData = List<Map<String, dynamic>>.from(
|
||||
result['status'] == 'success'
|
||||
? result['data'] ?? []
|
||||
: [],
|
||||
result['status'] == 'success' ? result['data'] ?? [] : [],
|
||||
);
|
||||
|
||||
filteredInternational = internationalData;
|
||||
@ -299,13 +295,13 @@ class _MISforexState extends State<MISforex>
|
||||
excelName,
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
backgroundColor: Colors.green,
|
||||
content: Text(result as String),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// backgroundColor: result['status'] ? Colors.green : Colors.red,
|
||||
// content: Text(result['message']),
|
||||
// behavior: SnackBarBehavior.floating,
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
|
||||
void handleInternationalFilter(String query) {
|
||||
@ -313,19 +309,60 @@ class _MISforexState extends State<MISforex>
|
||||
setState(() {
|
||||
filteredInternational =
|
||||
internationalData.where((object) {
|
||||
return (object['plan_id']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['employee_code']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['passenger_name']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['so_number']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['functional_department']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['visiting_country']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['amount']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['forex_from_date']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['forex_to_date']?.toLowerCase().contains(lowerQuery));
|
||||
final fromDateRaw = object['forex_from_date'];
|
||||
String newFromDate = '';
|
||||
|
||||
if (fromDateRaw != null && fromDateRaw is String) {
|
||||
try {
|
||||
final parsedDate = DateTime.parse(fromDateRaw);
|
||||
newFromDate =
|
||||
'${parsedDate.day.toString().padLeft(2, '0')}-${parsedDate.month.toString().padLeft(2, '0')}-${parsedDate.year}';
|
||||
} catch (e) {
|
||||
// fallback if date is not parsable
|
||||
newFromDate = fromDateRaw;
|
||||
}
|
||||
}
|
||||
|
||||
final toDateRaw = object['flight_travel_date'];
|
||||
String newToDate = '';
|
||||
|
||||
if (toDateRaw != null && toDateRaw is String) {
|
||||
try {
|
||||
final parsedDate = DateTime.parse(toDateRaw);
|
||||
newToDate =
|
||||
'${parsedDate.day.toString().padLeft(2, '0')}-${parsedDate.month.toString().padLeft(2, '0')}-${parsedDate.year}';
|
||||
} catch (e) {
|
||||
// fallback if date is not parsable
|
||||
newToDate = toDateRaw;
|
||||
}
|
||||
}
|
||||
|
||||
return (object['plan_id']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['employee_code']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['passenger_name']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['so_number']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['functional_department']?.toLowerCase().contains(
|
||||
lowerQuery,
|
||||
) ??
|
||||
false) ||
|
||||
(object['visiting_country']?.toLowerCase().contains(
|
||||
lowerQuery,
|
||||
) ??
|
||||
false) ||
|
||||
(object['amount']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(newFromDate.toLowerCase().contains(lowerQuery)) ||
|
||||
(newToDate.toLowerCase().contains(lowerQuery));
|
||||
}).toList();
|
||||
currentPage = 0;
|
||||
});
|
||||
print("handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}");
|
||||
print(
|
||||
"handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}",
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -399,7 +436,7 @@ class _MISforexState extends State<MISforex>
|
||||
children: [
|
||||
buildTitle(isDesktop),
|
||||
Spacer(),
|
||||
buildExports(isDesktop)
|
||||
buildExports(isDesktop),
|
||||
],
|
||||
)
|
||||
: Column(
|
||||
@ -407,9 +444,9 @@ class _MISforexState extends State<MISforex>
|
||||
children: [
|
||||
buildTitle(isDesktop),
|
||||
SizedBox(height: 8),
|
||||
buildExports(isDesktop)
|
||||
buildExports(isDesktop),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
|
||||
@ -450,13 +487,34 @@ class _MISforexState extends State<MISforex>
|
||||
internationalData.isEmpty
|
||||
? Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Text(
|
||||
"No data found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.of(context).size.height / 4,
|
||||
),
|
||||
Text(
|
||||
"No Records Found",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Please ensure the selected dates contain report data.",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -470,7 +528,8 @@ class _MISforexState extends State<MISforex>
|
||||
vertical: 8,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
/// Title on the left
|
||||
@ -482,14 +541,16 @@ class _MISforexState extends State<MISforex>
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.grey[700],
|
||||
),
|
||||
overflow: TextOverflow.ellipsis, // Ensures title doesn't overflow
|
||||
overflow:
|
||||
TextOverflow
|
||||
.ellipsis, // Ensures title doesn't overflow
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
SizedBox(width: 16),
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width * 0.2,
|
||||
width:
|
||||
MediaQuery.of(context).size.width * 0.2,
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: searchInternationalController,
|
||||
@ -506,17 +567,23 @@ class _MISforexState extends State<MISforex>
|
||||
size: 18,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade200,
|
||||
width: 0.5,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade300,
|
||||
width: 1,
|
||||
@ -526,7 +593,8 @@ class _MISforexState extends State<MISforex>
|
||||
style: GoogleFonts.poppins(fontSize: 12),
|
||||
),
|
||||
),
|
||||
])
|
||||
],
|
||||
),
|
||||
),
|
||||
// Table container
|
||||
Container(
|
||||
@ -539,7 +607,11 @@ class _MISforexState extends State<MISforex>
|
||||
builder: (context, constraints) {
|
||||
final double minWidth =
|
||||
isDesktop ? constraints.maxWidth : 1300;
|
||||
List<Map<String, dynamic>> newInternationalData =filteredInternational.isNotEmpty ? filteredInternational : internationalData;
|
||||
List<Map<String, dynamic>>
|
||||
newInternationalData =
|
||||
filteredInternational.isNotEmpty
|
||||
? filteredInternational
|
||||
: internationalData;
|
||||
// Pagination logic
|
||||
List<Map<String, dynamic>>
|
||||
paginatedInternational =
|
||||
@ -548,17 +620,47 @@ class _MISforexState extends State<MISforex>
|
||||
.take(itemsPerPage)
|
||||
.toList();
|
||||
|
||||
return ((searchInternationalController.text.isNotEmpty && filteredInternational.isEmpty)
|
||||
return ((searchInternationalController
|
||||
.text
|
||||
.isNotEmpty &&
|
||||
filteredInternational.isEmpty)
|
||||
? Center(
|
||||
child: Text(
|
||||
"No data found",
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.of(
|
||||
context,
|
||||
).size.height /
|
||||
4,
|
||||
),
|
||||
Text(
|
||||
"No Records Found",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Please ensure the selected dates contain report data.",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
:Column(
|
||||
: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
@ -568,15 +670,20 @@ class _MISforexState extends State<MISforex>
|
||||
minWidth: minWidth,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
scrollDirection:
|
||||
Axis.vertical,
|
||||
child: DataTable(
|
||||
dividerThickness: 0.5,
|
||||
columnSpacing:
|
||||
isDesktop ? 30.0 : 24.0,
|
||||
border: TableBorder(
|
||||
horizontalInside: BorderSide(
|
||||
horizontalInside:
|
||||
BorderSide(
|
||||
width: 0.5,
|
||||
color: Colors.grey.shade200,
|
||||
color:
|
||||
Colors
|
||||
.grey
|
||||
.shade200,
|
||||
),
|
||||
),
|
||||
columns: [
|
||||
@ -587,7 +694,8 @@ class _MISforexState extends State<MISforex>
|
||||
GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
FontWeight.w600,
|
||||
FontWeight
|
||||
.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -598,7 +706,8 @@ class _MISforexState extends State<MISforex>
|
||||
GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
FontWeight.w600,
|
||||
FontWeight
|
||||
.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -609,7 +718,8 @@ class _MISforexState extends State<MISforex>
|
||||
GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
FontWeight.w600,
|
||||
FontWeight
|
||||
.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -620,7 +730,8 @@ class _MISforexState extends State<MISforex>
|
||||
GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
FontWeight.w600,
|
||||
FontWeight
|
||||
.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -631,7 +742,8 @@ class _MISforexState extends State<MISforex>
|
||||
GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
FontWeight.w600,
|
||||
FontWeight
|
||||
.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -642,7 +754,8 @@ class _MISforexState extends State<MISforex>
|
||||
GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
FontWeight.w600,
|
||||
FontWeight
|
||||
.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -653,7 +766,8 @@ class _MISforexState extends State<MISforex>
|
||||
GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
FontWeight.w600,
|
||||
FontWeight
|
||||
.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -664,7 +778,8 @@ class _MISforexState extends State<MISforex>
|
||||
GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
FontWeight.w600,
|
||||
FontWeight
|
||||
.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -675,7 +790,8 @@ class _MISforexState extends State<MISforex>
|
||||
GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
FontWeight.w600,
|
||||
FontWeight
|
||||
.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -803,7 +919,8 @@ class _MISforexState extends State<MISforex>
|
||||
PaginationControls(
|
||||
currentPage: currentPage,
|
||||
itemsPerPage: itemsPerPage,
|
||||
totalItems: newInternationalData.length,
|
||||
totalItems:
|
||||
newInternationalData.length,
|
||||
activeColor: layoutColor,
|
||||
onPageChanged: (page) {
|
||||
setState(() {
|
||||
@ -832,7 +949,8 @@ class _MISforexState extends State<MISforex>
|
||||
),
|
||||
);
|
||||
}
|
||||
Widget buildTitle(bool isDesktop){
|
||||
|
||||
Widget buildTitle(bool isDesktop) {
|
||||
return // Left side: Breadcrumb inside a Container (optional)
|
||||
Container(
|
||||
child: BreadcrumbNavigation(
|
||||
@ -844,16 +962,15 @@ class _MISforexState extends State<MISforex>
|
||||
onTap: (context) {
|
||||
// Navigator.pushNamed(context, '/report');
|
||||
context.go("/report");
|
||||
}
|
||||
),
|
||||
BreadcrumbItem(
|
||||
title: 'MIS Forex Report ',
|
||||
},
|
||||
),
|
||||
BreadcrumbItem(title: 'MIS Forex Report '),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
Widget buildExports(bool isDesktop){
|
||||
|
||||
Widget buildExports(bool isDesktop) {
|
||||
return Row(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
@ -863,10 +980,7 @@ class _MISforexState extends State<MISforex>
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 12,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
),
|
||||
onPressed: handleDownload,
|
||||
child: Row(
|
||||
@ -879,11 +993,7 @@ class _MISforexState extends State<MISforex>
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Icon(
|
||||
Icons.file_present_outlined,
|
||||
size: 15,
|
||||
color: Colors.white,
|
||||
),
|
||||
Icon(Icons.file_present_outlined, size: 15, color: Colors.white),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -916,14 +1026,14 @@ class _MISforexState extends State<MISforex>
|
||||
// ),
|
||||
],
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
Widget buildFromDateField(bool isDesktop) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text( "From Date *",
|
||||
Text(
|
||||
"From Date *",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
@ -965,12 +1075,9 @@ class _MISforexState extends State<MISforex>
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
),
|
||||
floatingLabelBehavior:
|
||||
FloatingLabelBehavior.never,
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
border: InputBorder.none,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||
suffixIcon: const Icon(
|
||||
Icons.calendar_today,
|
||||
size: 16,
|
||||
@ -997,7 +1104,8 @@ class _MISforexState extends State<MISforex>
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text( "To Date *",
|
||||
Text(
|
||||
"To Date *",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
@ -1013,13 +1121,10 @@ class _MISforexState extends State<MISforex>
|
||||
height: 40,
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
final fromDateText =
|
||||
textControllers["from_date"]?.text;
|
||||
final fromDateText = textControllers["from_date"]?.text;
|
||||
DateTime? mintoDate;
|
||||
if (fromDateText != null && fromDateText.isNotEmpty) {
|
||||
mintoDate = DateFormat(
|
||||
'dd-MM-yyyy',
|
||||
).parse(fromDateText);
|
||||
mintoDate = DateFormat('dd-MM-yyyy').parse(fromDateText);
|
||||
}
|
||||
|
||||
final pickedDate = await showDatePicker(
|
||||
@ -1044,16 +1149,10 @@ class _MISforexState extends State<MISforex>
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Select Date",
|
||||
labelStyle: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
),
|
||||
floatingLabelBehavior:
|
||||
FloatingLabelBehavior.never,
|
||||
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||
suffixIcon: Icon(
|
||||
Icons.calendar_today,
|
||||
size: 16,
|
||||
@ -1072,8 +1171,7 @@ class _MISforexState extends State<MISforex>
|
||||
style: const TextStyle(color: Colors.red, fontSize: 12),
|
||||
maxLines: 2, // Allow it to wrap onto two lines
|
||||
overflow:
|
||||
TextOverflow
|
||||
.ellipsis, // Add ellipsis if it still overflows
|
||||
TextOverflow.ellipsis, // Add ellipsis if it still overflows
|
||||
),
|
||||
],
|
||||
],
|
||||
@ -1081,11 +1179,8 @@ class _MISforexState extends State<MISforex>
|
||||
}
|
||||
|
||||
Widget buildSearchButton(bool isDesktop) {
|
||||
return
|
||||
Padding(
|
||||
padding: isDesktop
|
||||
? const EdgeInsets.only(top: 22)
|
||||
: EdgeInsets.zero,
|
||||
return Padding(
|
||||
padding: isDesktop ? const EdgeInsets.only(top: 22) : EdgeInsets.zero,
|
||||
child: SizedBox(
|
||||
width: isDesktop ? null : double.infinity,
|
||||
child: ElevatedButton(
|
||||
@ -1098,23 +1193,17 @@ class _MISforexState extends State<MISforex>
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 12,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
),
|
||||
onPressed: () {
|
||||
handleSubmit();
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize:
|
||||
MainAxisSize.min, // Ensures content fits nicely
|
||||
mainAxisSize: MainAxisSize.min, // Ensures content fits nicely
|
||||
children: [
|
||||
Text(
|
||||
"Search",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: isDesktop ? 13 : 11,
|
||||
),
|
||||
style: GoogleFonts.poppins(fontSize: isDesktop ? 13 : 11),
|
||||
),
|
||||
SizedBox(width: 8), // spacing between icon and text
|
||||
Icon(Icons.search, size: 15, color: Colors.white),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -112,9 +112,12 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
|
||||
String getTabName(int index) {
|
||||
switch (index) {
|
||||
case 0: return "domestic";
|
||||
case 1: return "international";
|
||||
default: return "domestic"; // return "Unknown";
|
||||
case 0:
|
||||
return "domestic";
|
||||
case 1:
|
||||
return "international";
|
||||
default:
|
||||
return "domestic"; // return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,13 +334,13 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
excelName,
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
backgroundColor: Colors.green,
|
||||
content: Text(result as String),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// backgroundColor: result['status'] ? Colors.green : Colors.red,
|
||||
// content: Text(result['message']),
|
||||
// behavior: SnackBarBehavior.floating,
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
|
||||
void handleDomesticFilter(String query) {
|
||||
@ -345,13 +348,17 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
setState(() {
|
||||
filteredDomestic =
|
||||
domesticData.where((object) {
|
||||
return (object['Service']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_service_count']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
return (object['Service']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['service_count']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['plan_trip_type']?.toLowerCase().contains(lowerQuery));
|
||||
}).toList();
|
||||
currentPage1 = 0;
|
||||
});
|
||||
print("handleDomesticFilter > Total entries: ${filteredDomestic?.length ?? 0}");
|
||||
print(
|
||||
"handleDomesticFilter > Total entries: ${filteredDomestic?.length ?? 0}",
|
||||
);
|
||||
}
|
||||
|
||||
void handleInternationalFilter(String query) {
|
||||
@ -359,16 +366,19 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
setState(() {
|
||||
filteredInternational =
|
||||
internationalData.where((object) {
|
||||
return (object['Service']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
(object['flight_service_count']?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||
return (object['Service']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['service_count']?.toLowerCase().contains(lowerQuery) ??
|
||||
false) ||
|
||||
(object['plan_trip_type']?.toLowerCase().contains(lowerQuery));
|
||||
}).toList();
|
||||
currentPage2 = 0;
|
||||
});
|
||||
print("handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}");
|
||||
print(
|
||||
"handleInternationalFilter > Total entries: ${filteredInternational?.length ?? 0}",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
// Widget build(BuildContext context) {
|
||||
// // TODO: implement build
|
||||
@ -429,7 +439,6 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// ------------------- First Row -------------------
|
||||
// ------------------- First Row -------------------
|
||||
Container(
|
||||
color: Colors.white,
|
||||
@ -440,7 +449,7 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
children: [
|
||||
buildTitle(isDesktop),
|
||||
Spacer(),
|
||||
buildExports(isDesktop)
|
||||
buildExports(isDesktop),
|
||||
],
|
||||
)
|
||||
: Column(
|
||||
@ -448,9 +457,9 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
children: [
|
||||
buildTitle(isDesktop),
|
||||
SizedBox(height: 8),
|
||||
buildExports(isDesktop)
|
||||
buildExports(isDesktop),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
|
||||
@ -507,13 +516,34 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
: domesticData.isEmpty
|
||||
? Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Text(
|
||||
"No data found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.of(context).size.height / 4,
|
||||
),
|
||||
Text(
|
||||
"No Records Found",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Please ensure the selected dates contain report data.",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -545,7 +575,9 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width * 0.2,
|
||||
width:
|
||||
MediaQuery.of(context).size.width *
|
||||
0.2,
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: searchDomesticController,
|
||||
@ -562,24 +594,32 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
size: 18,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade200,
|
||||
width: 0.5,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade300,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
style: GoogleFonts.poppins(fontSize: 12),
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
// SizedBox(width: 16),
|
||||
@ -687,8 +727,10 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
final double minWidth =
|
||||
isDesktop ? constraints.maxWidth : 1300;
|
||||
|
||||
List<Map<String, dynamic>> newDomesticData =filteredDomestic.isNotEmpty ? filteredDomestic : domesticData;
|
||||
|
||||
List<Map<String, dynamic>> newDomesticData =
|
||||
filteredDomestic.isNotEmpty
|
||||
? filteredDomestic
|
||||
: domesticData;
|
||||
|
||||
// Pagination logic
|
||||
List<Map<String, dynamic>>
|
||||
@ -698,14 +740,43 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
.take(itemsPerPage1)
|
||||
.toList();
|
||||
|
||||
return (
|
||||
(searchDomesticController.text.isNotEmpty && filteredDomestic.isEmpty)
|
||||
return ((searchDomesticController
|
||||
.text
|
||||
.isNotEmpty &&
|
||||
filteredDomestic.isEmpty)
|
||||
? Center(
|
||||
child: Text(
|
||||
"No data found",
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.of(
|
||||
context,
|
||||
).size.height /
|
||||
4,
|
||||
),
|
||||
Text(
|
||||
"No Records Found",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Please ensure the selected dates contain report data.",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -713,17 +784,21 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
scrollDirection:
|
||||
Axis.horizontal,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: minWidth,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
scrollDirection:
|
||||
Axis.vertical,
|
||||
child: DataTable(
|
||||
dividerThickness: 0.5,
|
||||
columnSpacing:
|
||||
isDesktop ? 30.0 : 24.0,
|
||||
isDesktop
|
||||
? 30.0
|
||||
: 24.0,
|
||||
border: TableBorder(
|
||||
horizontalInside:
|
||||
BorderSide(
|
||||
@ -781,8 +856,7 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['Service']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -790,9 +864,8 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
),
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['flight_service_count']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
'${entry['service_count']}',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -801,8 +874,7 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['plan_trip_type']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -821,7 +893,8 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
PaginationControls(
|
||||
currentPage: currentPage1,
|
||||
itemsPerPage: itemsPerPage1,
|
||||
totalItems: newDomesticData.length,
|
||||
totalItems:
|
||||
newDomesticData.length,
|
||||
activeColor: layoutColor,
|
||||
onPageChanged: (page) {
|
||||
setState(() {
|
||||
@ -847,13 +920,34 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
internationalData.isEmpty
|
||||
? Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Text(
|
||||
"No data found",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.of(context).size.height / 4,
|
||||
),
|
||||
Text(
|
||||
"No Records Found",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Please ensure the selected dates contain report data.",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -984,7 +1078,8 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
vertical: 8,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
/// Title on the left
|
||||
@ -996,17 +1091,21 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.grey[700],
|
||||
),
|
||||
overflow: TextOverflow.ellipsis, // Ensures title doesn't overflow
|
||||
overflow:
|
||||
TextOverflow
|
||||
.ellipsis, // Ensures title doesn't overflow
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
SizedBox(width: 16),
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width * 0.2,
|
||||
width:
|
||||
MediaQuery.of(context).size.width *
|
||||
0.2,
|
||||
height: 40,
|
||||
child: TextField(
|
||||
controller: searchInternationalController,
|
||||
controller:
|
||||
searchInternationalController,
|
||||
onChanged: handleInternationalFilter,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search ...",
|
||||
@ -1020,27 +1119,36 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
size: 18,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade200,
|
||||
width: 0.5,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(
|
||||
12,
|
||||
),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey.shade300,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
style: GoogleFonts.poppins(fontSize: 12),
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
])
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height:
|
||||
@ -1053,7 +1161,11 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
builder: (context, constraints) {
|
||||
final double minWidth =
|
||||
isDesktop ? constraints.maxWidth : 1300;
|
||||
List<Map<String, dynamic>> newInternationalData =filteredInternational.isNotEmpty ? filteredInternational : internationalData;
|
||||
List<Map<String, dynamic>>
|
||||
newInternationalData =
|
||||
filteredInternational.isNotEmpty
|
||||
? filteredInternational
|
||||
: internationalData;
|
||||
// Pagination logic
|
||||
List<Map<String, dynamic>>
|
||||
paginatedInternational =
|
||||
@ -1062,13 +1174,43 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
.take(itemsPerPage2)
|
||||
.toList();
|
||||
|
||||
return ((searchInternationalController.text.isNotEmpty && filteredInternational.isEmpty)
|
||||
return ((searchInternationalController
|
||||
.text
|
||||
.isNotEmpty &&
|
||||
filteredInternational.isEmpty)
|
||||
? Center(
|
||||
child: Text(
|
||||
"No data found",
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.of(
|
||||
context,
|
||||
).size.height /
|
||||
4,
|
||||
),
|
||||
Text(
|
||||
"No Records Found",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 14,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Please ensure the selected dates contain report data.",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -1076,17 +1218,21 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
scrollDirection:
|
||||
Axis.horizontal,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: minWidth,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
scrollDirection:
|
||||
Axis.vertical,
|
||||
child: DataTable(
|
||||
dividerThickness: 0.5,
|
||||
columnSpacing:
|
||||
isDesktop ? 30.0 : 24.0,
|
||||
isDesktop
|
||||
? 30.0
|
||||
: 24.0,
|
||||
border: TableBorder(
|
||||
horizontalInside:
|
||||
BorderSide(
|
||||
@ -1144,8 +1290,7 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['Service']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1153,9 +1298,8 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
),
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['flight_service_count']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
'${entry['service_count']}',
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1164,8 +1308,7 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
DataCell(
|
||||
Text(
|
||||
'${entry['plan_trip_type']}',
|
||||
style:
|
||||
GoogleFonts.poppins(
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize:
|
||||
12,
|
||||
),
|
||||
@ -1184,7 +1327,8 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
PaginationControls(
|
||||
currentPage: currentPage2,
|
||||
itemsPerPage: itemsPerPage2,
|
||||
totalItems: newInternationalData.length,
|
||||
totalItems:
|
||||
newInternationalData.length,
|
||||
activeColor: layoutColor,
|
||||
onPageChanged: (page) {
|
||||
setState(() {
|
||||
@ -1217,7 +1361,7 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildTitle(bool isDesktop){
|
||||
Widget buildTitle(bool isDesktop) {
|
||||
return // Left side: Breadcrumb inside a Container (optional)
|
||||
Container(
|
||||
child: BreadcrumbNavigation(
|
||||
@ -1229,17 +1373,15 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
onTap: (context) {
|
||||
// Navigator.pushNamed(context, '/report');
|
||||
context.go("/report");
|
||||
}
|
||||
),
|
||||
BreadcrumbItem(
|
||||
title: 'Service Analysis Report',
|
||||
},
|
||||
),
|
||||
BreadcrumbItem(title: 'Service Analysis Report'),
|
||||
],
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildExports(bool isDesktop){
|
||||
Widget buildExports(bool isDesktop) {
|
||||
return Row(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
@ -1249,10 +1391,7 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 12,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
),
|
||||
onPressed: handleDownload,
|
||||
child: Row(
|
||||
@ -1265,11 +1404,7 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Icon(
|
||||
Icons.file_present_outlined,
|
||||
size: 15,
|
||||
color: Colors.white,
|
||||
),
|
||||
Icon(Icons.file_present_outlined, size: 15, color: Colors.white),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -1302,14 +1437,14 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
// ),
|
||||
],
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
Widget buildFromDateField(bool isDesktop) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text( "From Date *",
|
||||
Text(
|
||||
"From Date *",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
@ -1350,12 +1485,9 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
),
|
||||
floatingLabelBehavior:
|
||||
FloatingLabelBehavior.never,
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
border: InputBorder.none,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||
suffixIcon: const Icon(
|
||||
Icons.calendar_today,
|
||||
size: 16,
|
||||
@ -1382,7 +1514,8 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text( "To Date *",
|
||||
Text(
|
||||
"To Date *",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
@ -1398,13 +1531,10 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
height: 40,
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
final fromDateText =
|
||||
textControllers["from_date"]?.text;
|
||||
final fromDateText = textControllers["from_date"]?.text;
|
||||
DateTime? mintoDate;
|
||||
if (fromDateText != null && fromDateText.isNotEmpty) {
|
||||
mintoDate = DateFormat(
|
||||
'dd-MM-yyyy',
|
||||
).parse(fromDateText);
|
||||
mintoDate = DateFormat('dd-MM-yyyy').parse(fromDateText);
|
||||
}
|
||||
|
||||
final pickedDate = await showDatePicker(
|
||||
@ -1429,16 +1559,10 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
style: const TextStyle(fontSize: 12),
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Select Date",
|
||||
labelStyle: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
),
|
||||
floatingLabelBehavior:
|
||||
FloatingLabelBehavior.never,
|
||||
labelStyle: TextStyle(fontSize: 12, color: Colors.grey),
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||
suffixIcon: Icon(
|
||||
Icons.calendar_today,
|
||||
size: 16,
|
||||
@ -1457,8 +1581,7 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
style: const TextStyle(color: Colors.red, fontSize: 12),
|
||||
maxLines: 2, // Allow it to wrap onto two lines
|
||||
overflow:
|
||||
TextOverflow
|
||||
.ellipsis, // Add ellipsis if it still overflows
|
||||
TextOverflow.ellipsis, // Add ellipsis if it still overflows
|
||||
),
|
||||
],
|
||||
],
|
||||
@ -1466,11 +1589,8 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
}
|
||||
|
||||
Widget buildSearchButton(bool isDesktop) {
|
||||
return
|
||||
Padding(
|
||||
padding: isDesktop
|
||||
? const EdgeInsets.only(top: 22)
|
||||
: EdgeInsets.zero,
|
||||
return Padding(
|
||||
padding: isDesktop ? const EdgeInsets.only(top: 22) : EdgeInsets.zero,
|
||||
child: SizedBox(
|
||||
width: isDesktop ? null : double.infinity,
|
||||
child: ElevatedButton(
|
||||
@ -1483,23 +1603,17 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(color: Color(0xFF114D8B), width: 2),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 12,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
),
|
||||
onPressed: () {
|
||||
handleSubmit();
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize:
|
||||
MainAxisSize.min, // Ensures content fits nicely
|
||||
mainAxisSize: MainAxisSize.min, // Ensures content fits nicely
|
||||
children: [
|
||||
Text(
|
||||
"Search",
|
||||
style: GoogleFonts.poppins(
|
||||
fontSize: isDesktop ? 13 : 11,
|
||||
),
|
||||
style: GoogleFonts.poppins(fontSize: isDesktop ? 13 : 11),
|
||||
),
|
||||
SizedBox(width: 8), // spacing between icon and text
|
||||
Icon(Icons.search, size: 15, color: Colors.white),
|
||||
@ -1509,5 +1623,4 @@ class _ServicesAnalysisState extends State<ServicesAnalysis>
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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,
|
||||
),
|
||||
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(data['message']);
|
||||
// For non-200 responses
|
||||
final errorMsg = 'Failed to upload file: ${response.reasonPhrase}';
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(data['message']),
|
||||
content: Text(errorMsg),
|
||||
backgroundColor: Colors.redAccent,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
refreshUserList();
|
||||
}
|
||||
} else {
|
||||
print('Something went wrong');
|
||||
print('Failed to upload file: ${response.reasonPhrase}');
|
||||
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