ts-tat/lib/Screens/userManagement/create_user/office_details.dart
2025-10-27 17:35:57 +05:30

2310 lines
94 KiB
Dart

import 'dart:io' as html;
import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import '../../../services/apiService.dart';
import '../../../utils/auth_utils.dart';
import '../../../widgets/custom_user_form.dart';
class OfficeDetails extends StatefulWidget {
final Map<String, TextEditingController> controllers;
final Map<String, String> errorMessages;
final bool isDesktop;
final bool isViewMode;
final String? userIdApi;
final ValueChanged<String?>? onLevelChanged;
final ValueChanged<String?>? onDepartmentChanged;
final ValueChanged<String?>? onFirstApproverChanged;
final ValueChanged<String?>? onSecondApproverChanged;
final ValueChanged<String?>? onThirdApproverChanged;
final ValueChanged<String?>? onFirstSubsApproverChanged;
final ValueChanged<String?>? onExceptionalApproverChanged;
final String? selectedLevel;
final String? selectedDepartment;
final String? selectedFirstApprover;
final String? selectedSecondApprover;
final String? selectedThirdApprover;
final String? selectedSubstituteApprover;
final String? selectedExceptionalApprover;
const OfficeDetails({
Key? key,
this.selectedLevel,
this.selectedDepartment,
this.selectedFirstApprover,
this.selectedSecondApprover,
this.selectedThirdApprover,
required this.controllers,
required this.errorMessages,
required this.isDesktop,
required this.isViewMode,
this.onLevelChanged,
this.onDepartmentChanged,
this.onFirstApproverChanged,
this.onSecondApproverChanged,
this.onThirdApproverChanged,
this.selectedSubstituteApprover,
this.selectedExceptionalApprover,
this.onExceptionalApproverChanged,
this.onFirstSubsApproverChanged,
this.userIdApi,
}) : super(key: key);
@override
OfficeDetailsState createState() => OfficeDetailsState();
}
class OfficeDetailsState extends State<OfficeDetails> {
final ApiService apiService = ApiService();
late Map<String, String> countryMap; // Mapping country_code -> country_name
late List<String> countryCodes; // List of country codes
late List<dynamic>? apiCountryData;
bool isResetTrue = false;
late List<dynamic>? apiCostData;
late List<dynamic>? apiRoleData;
late List<dynamic>? apiUserData;
late List<dynamic>? apiAllGroups;
Map<String, dynamic>? apiselectedUser;
late List<dynamic> userList;
late List<dynamic> groupList;
late Future<List<dynamic>> futureUsers;
List<dynamic>? resolvedUserData;
// String? userIdsApi;
late List<String> userIdsApi;
late List<String> groupIdsApi;
late Map<String, String> userMap;
late Map<String, String> groupMap;
String? selectedTab;
String? selectedCountry;
String? selectedGender;
String? selectedUserType;
String? selectedRole;
String? selectedLevel;
String? selectedDepartment;
String? selectedFirstApprover;
String? selectedSecondApprover;
String? selectedThirdApprover;
String? selectedSubstituteApprover;
String? selectedExceptionalApprover;
String? selectedFileNames;
Uint8List? passportDocumentBytes;
String? passportFileUrlFromApi;
String? base64PDF;
DateTime? _selectedCheckOutDate;
DateTime? _selectedEndDate;
html.File? passportFile;
final FocusNode _employeeCodeFocusNode = FocusNode();
final FocusNode _departmentFocusNode = FocusNode();
final FocusNode _groupFocusNode = FocusNode();
final FocusNode _firstApprovalFocusNode = FocusNode();
final FocusNode _secondApprovalFocusNode = FocusNode();
final FocusNode _thirdApprovalFocusNode = FocusNode();
final FocusNode _exceptionalApprovalFocusNode = FocusNode();
final FocusNode _delegateFocusNode = FocusNode();
final FocusNode _startDateFocusNode = FocusNode();
final FocusNode _endDateFocusNode = FocusNode();
bool _employeeCodeFocus = false;
bool _departmentFocus = false;
bool _groupFocus = false;
bool _firstApprovalFocus = false;
bool _secondApprovalFocus = false;
bool _thirdApprovalFocus = false;
bool _exceptionalApprovalFocus = false;
bool _delegateFocus = false;
bool _startDateFocus = false;
bool _endDateFocus = false;
List<String> dataHeader = [
"Fname",
"Lname",
"email",
"password",
"dob",
"gender",
"mobileNumber",
"alternateMobile",
"address",
"postalCode",
"country",
"passportNumber",
"placeOfIssue",
"passportDoc",
"userType",
"roleId",
"deptId",
"levelId",
"firstApproval",
"secondApproval",
"thirdApproval",
"exceptional_approver",
"employeeCode",
"dateOfIssue",
"dateOfExpiry",
"changePassword",
];
// Color? layoutColor;
Color layoutColor = Colors.grey;
Color? bodyColor;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
loadInitialData();
_employeeCodeFocusNode.requestFocus();
});
apiCountryData = null;
apiUserData = null;
apiCostData = null;
apiRoleData = null;
apiAllGroups = null;
apiCountryData = null;
selectedLevel = widget.selectedLevel;
selectedDepartment = widget.selectedDepartment;
selectedFirstApprover = widget.selectedFirstApprover;
selectedSecondApprover = widget.selectedSecondApprover;
selectedThirdApprover = widget.selectedThirdApprover;
selectedSubstituteApprover = widget.selectedSubstituteApprover;
selectedExceptionalApprover = widget.selectedExceptionalApprover;
fetchDepartment();
fetchUsers();
fetchFindGroup();
_addFocusListener(
_employeeCodeFocusNode,
(focus) => _employeeCodeFocus = focus,
);
_addFocusListener(
_departmentFocusNode,
(focus) => _departmentFocus = focus,
);
_addFocusListener(_groupFocusNode, (focus) => _groupFocus = focus);
_addFocusListener(
_firstApprovalFocusNode,
(focus) => _firstApprovalFocus = focus,
);
_addFocusListener(
_secondApprovalFocusNode,
(focus) => _secondApprovalFocus = focus,
);
_addFocusListener(
_thirdApprovalFocusNode,
(focus) => _thirdApprovalFocus = focus,
);
_addFocusListener(
_exceptionalApprovalFocusNode,
(focus) => _exceptionalApprovalFocus = focus,
);
_addFocusListener(_delegateFocusNode, (focus) => _delegateFocus = focus);
_addFocusListener(_startDateFocusNode, (focus) => _startDateFocus = focus);
_addFocusListener(_endDateFocusNode, (focus) => _endDateFocus = focus);
}
void _addFocusListener(FocusNode node, Function(bool) updateState) {
node.addListener(() {
setState(() {
updateState(node.hasFocus);
});
});
}
void loadInitialData() async {
String? layoutString = await getLayoutColor();
String? bodyStringColor = await getBodyColor();
setState(() {
layoutColor =
layoutString != null
? Color(int.parse(layoutString))
: Colors.redAccent;
bodyColor =
bodyStringColor != null
? Color(int.parse(bodyStringColor))
: Colors.white;
});
}
Future<void> apiCheckDuplicate(
String label,
String field,
String value,
String? userId,
) async {
try {
// Basic validation: Check mobile number length
final response = await apiService.CheckDuplicate(
context,
label,
field,
value,
userId ?? "",
);
if (response.isNotEmpty) {
_clearError(field);
widget.errorMessages[field] =
response['message'] ?? "$label Already Exists";
print("Duplicate found: ${response['message']}");
return;
} else {
_clearError(field);
print("No duplicates found.");
}
} catch (e) {
print("Error in checkDuplicate: $e");
}
}
void _clearError(String field) {
setState(() {
widget.errorMessages.remove(field);
});
}
// void handleReset() {
// setState(() {
// selectedSubstituteApprover = "";
// widget.controllers["delegationEndDate"]?.text = "";
// widget.controllers["delegationStartDate"]?.text = "";
// });
// }
void handleReset() {
setState(() {
selectedSubstituteApprover = null;
widget.onFirstSubsApproverChanged?.call(null); // Notify parent if needed
// Clear date selections and fields
_selectedCheckOutDate = null;
_selectedEndDate = null;
widget.controllers["delegationStartDate"]?.text = "";
widget.controllers["delegationEndDate"]?.text = "";
// selectedSubstituteApprover = null;
// widget.onFirstSubsApproverChanged?.call(null);
// widget.controllers["delegationStartDate"]?.clear();
// widget.controllers["delegationEndDate"]?.clear();
//
// print("Start Date: ${widget.controllers["delegationStartDate"]?.text}");
// print("End Date: ${widget.controllers["delegationEndDate"]?.text}");
});
}
Future<void> fetchUsers() async {
try {
print("Test Users");
List<dynamic> users = await apiService.fetchUsers(context);
setState(() {
// apiUserData = users;
print("Total users fetched from API: ${users.length}");
// user["role_id"] != "5" - Travel Agent
apiUserData = users.where((user) => user["role_id"] != "5").toList();
print("Total users fetched from API1: ${apiUserData?.length}");
print("APIUSerDATa - $apiUserData");
userList = apiUserData ?? [];
userMap = {
for (var user in userList)
user['user_id'].toString():
"${user['first_name']} ${user['last_name']}",
};
userIdsApi = userMap.keys.toList();
});
} catch (e) {
print('Error fetching country list: $e');
}
}
Future<void> fetchDepartment() async {
try {
print("Test department");
List<dynamic> department = await apiService.fetchDepartmentCostCenter(
context,
);
setState(() {
apiCostData = department;
});
print("Test department Completeed- $apiCostData");
} catch (e) {
print('Error fetching department list: $e');
}
}
Future<void> fetchFindGroup() async {
try {
print("Test Groups");
final result = await apiService.fetchAllGroup(context);
setState(() {
apiAllGroups = result;
groupList = apiAllGroups ?? [];
// groupMap = {
// for (var group in groupList)
// group['group_id'].toString(): "${group['name']}"
// };
groupMap = {
for (var group in groupList)
group['group_id'].toString(): group['name'].toString().trim(),
};
userIdsApi = groupMap.keys.toList();
});
print("Fetched Groupss: $apiAllGroups");
} catch (e) {
print('Error fetching role list: $e');
}
}
@override
Widget build(BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height * 0.8,
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: Colors.blueGrey.shade300, // Set your desired color
width: 0.09, // Set border thickness
),
),
),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 20),
_buildFirstRow(widget.isDesktop),
if (widget.isDesktop) SizedBox(height: 10),
_buildSecondRow(widget.isDesktop),
if (widget.isDesktop) SizedBox(height: 10),
_buildThirdRow(widget.isDesktop),
if (widget.isDesktop) SizedBox(height: 10),
Divider(thickness: 0.2, color: Colors.blueGrey.shade100),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Delegation",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w500,
),
),
],
),
SizedBox(height: 15),
_buildFourthRow(widget.isDesktop),
],
),
),
);
}
Widget _buildFirstRow(bool isDesktop) {
return Container(
color: Colors.white,
child:
widget.isDesktop
? Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildEmpCodeField(),
Spacer(),
buildDepartmentField(),
Spacer(), // Space after Last Name
buildGroupField(),
],
)
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildEmpCodeField(),
SizedBox(height: 8), // Vertical space
buildDepartmentField(),
SizedBox(height: 8),
buildGroupField(),
],
),
);
}
Widget _buildSecondRow(bool isDesktop) {
return Container(
color: Colors.white,
child:
widget.isDesktop
? Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildApprover1(isDesktop),
Spacer(),
buildApprover2(isDesktop),
Spacer(), // Space after Last Name
buildApprover3(isDesktop),
],
)
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildApprover1(isDesktop),
SizedBox(height: 8), // Vertical space
buildApprover2(isDesktop),
SizedBox(height: 8),
buildApprover3(isDesktop),
],
),
);
}
Widget _buildThirdRow(bool isDesktop) {
return Container(
color: Colors.white,
child:
widget.isDesktop
? Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [buildExceptionApprover(isDesktop), Spacer()],
)
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildExceptionApprover(isDesktop),
SizedBox(height: 8), // Vertical space
],
),
);
}
Widget _buildFourthRow(bool isDesktop) {
return Container(
color: Colors.white,
child:
widget.isDesktop
? Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildApproverSubstitute1(isDesktop),
Spacer(),
buildDelegationStartDateField(isDesktop),
Spacer(), // Space after Last Name
buildDelegationEndDateField(isDesktop),
SizedBox(width: 16),
buildReset(isDesktop),
],
)
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildApproverSubstitute1(isDesktop),
SizedBox(height: 8), // Vertical space
buildDelegationStartDateField(isDesktop),
SizedBox(height: 8),
buildDelegationEndDateField(isDesktop),
buildReset(isDesktop),
],
),
);
}
Widget buildEmpCodeField() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Employee Code *",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
SizedBox(height: 5),
CustomTextFieldUserWrapper(
isFocused: _employeeCodeFocus,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 40,
child: TextField(
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')),
],
focusNode: _employeeCodeFocusNode,
controller: widget.controllers["employeeCode"],
enabled: !widget.isViewMode,
onChanged: (value) {
_clearError("employee_code");
final updaterUserId = widget.userIdApi ?? "";
apiCheckDuplicate(
"Employee Code",
"employee_code",
value,
updaterUserId,
);
},
decoration: InputDecoration(
labelText: "Employee Code",
labelStyle: GoogleFonts.poppins(
fontSize: 12,
color: Colors.grey,
),
floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16),
),
),
),
),
if (widget.errorMessages["employee_code"] != null) ...[
SizedBox(height: 5), // Space before error message
Text(
widget.errorMessages["employee_code"]!,
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
),
],
],
);
}
// Widget buildDepartmentFieldOld() {
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// "Department",
// style: GoogleFonts.poppins(
// fontSize: 12,
// fontWeight: FontWeight.w600,
// color: Color(0xFF575A74),
// ),
// ),
// SizedBox(height: 5),
// CustomTextFieldUserWrapper(
// isFocused: false, // Dropdown doesn't use focus
// isDesktop: widget.isDesktop,
// child: SizedBox(
// height: 45, // Set appropriate height
// child: DropdownButtonFormField<String>(
// value: selectedDepartment,
// // value: widget.isViewMode ? null : selectedDepartment,
// style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
// decoration: InputDecoration(
// border: InputBorder.none,
// contentPadding: EdgeInsets.symmetric(
// horizontal: 10,
// ), // Proper padding
// ),
// onChanged:
// widget.isViewMode
// ? null
// : (newValue) {
// setState(() {
// selectedDepartment = newValue;
// });
// widget.onDepartmentChanged?.call(newValue);
// },
//
// items:
// apiCostData?.map<DropdownMenuItem<String>>((item) {
// return DropdownMenuItem(
//
// value: item['department_id'], // ID as value
// child: Text(item['name'] ?? "Unknown"),
// );
// }).toList(),
// hint: Text("Select"),
// disabledHint: Text(
// selectedDepartment ?? "Select Department",
// style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
// ),
// ),
// ),
// ),
// ],
// );
// }
Widget buildDepartmentField() {
// Map department_id to department_name
Map<String, String> departmentMap = {
for (var item in apiCostData ?? [])
if (item['dropdown_key'] != null &&
item['dropdown_value'] != null &&
int.tryParse(item['dropdown_key'].toString()) != 5)
item['dropdown_key'].toString(): item['dropdown_value'].toString(),
// item['department_id'] as String: item['name'] as String,
};
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Department",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
SizedBox(height: 5),
CustomTextFieldUserWrapper(
isFocused: _departmentFocus,
padding: const EdgeInsets.symmetric(horizontal: 0),
isDesktop: widget.isDesktop,
child: SizedBox(
height: 40,
width: double.infinity,
child: Focus(
focusNode: _departmentFocusNode,
onFocusChange: (hasFocus) {
setState(() {
_departmentFocus = hasFocus;
});
},
child: GestureDetector(
onTap: () {
// Request focus when user taps
_departmentFocusNode?.requestFocus();
},
child: DropdownSearch<String>(
selectedItem: departmentMap[selectedDepartment],
enabled: !widget.isViewMode,
popupProps: PopupProps.menu(
showSearchBox: true,
fit: FlexFit.loose,
menuProps: const MenuProps(backgroundColor: Colors.white),
itemBuilder:
(context, item, isSelected) => Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 6,
),
child: Text(
item,
style: GoogleFonts.poppins(fontSize: 11.5),
),
),
constraints: BoxConstraints(maxHeight: 200),
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
hintText: "Search Department...",
contentPadding: EdgeInsets.symmetric(horizontal: 10),
),
),
),
items: departmentMap.values.toList(),
dropdownDecoratorProps: DropDownDecoratorProps(
dropdownSearchDecoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(
color:
(_departmentFocus) ? (layoutColor) : Colors.white,
width: 0.5,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color:
(_departmentFocus) ? (layoutColor) : Colors.white,
width: 0.5,
// const Color(0xFFD6D5E6),
),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: (layoutColor ?? Colors.grey),
width: 0.5,
),
),
contentPadding: EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
),
// contentPadding: EdgeInsets.symmetric(horizontal: 1),
),
),
dropdownBuilder:
(context, selectedItem) => Align(
alignment: Alignment.centerLeft,
child: Text(
selectedItem ?? "Select Department",
style: GoogleFonts.poppins(
fontSize: 12,
color: Colors.black,
),
),
),
onChanged:
widget.isViewMode
? null
: (String? newValue) {
if (newValue == null) return;
final departmentId =
departmentMap.entries
.firstWhere(
(entry) => entry.value == newValue,
)
.key;
setState(() {
selectedDepartment = departmentId;
});
widget.onDepartmentChanged?.call(
departmentId,
); // Send department_id
},
),
),
),
),
),
],
);
}
Widget buildGroupField() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Group",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
SizedBox(height: 5),
// CustomTextFieldUserWrapper(
// isFocused: false,
// isDesktop: widget.isDesktop,
// child: SizedBox(
// height: 40,
// child: DropdownSearch<String>(
// selectedItem: selectedLevel,
// enabled: !widget.isViewMode,
// popupProps: PopupProps.menu(
// // showSearchBox: true,
// fit: FlexFit.loose, // Allows flexible height
// constraints: BoxConstraints(maxHeight: 250),
// ),
// items: ["Level 1", "Level 2", "Level 3"],
// dropdownDecoratorProps: DropDownDecoratorProps(
// dropdownSearchDecoration: InputDecoration(
// border: InputBorder.none,
// contentPadding: EdgeInsets.symmetric(
// horizontal: 1,
// ),
// ),
// ),
// dropdownBuilder: (context, selectedItem) => Align(
// // Center-align selected item
// alignment: Alignment.centerLeft,
// child: Text(
// selectedItem ?? "Select",
// style: TextStyle(fontSize: 12, color: Colors.black),
// ),
// ),
// onChanged: (String? newValue) {
// setState(() {
// // Find the country_code based on selected country_name
// selectedLevel = newValue;
//
// // if (selectedCountry!.isNotEmpty) {
// // errorMessages.remove("country_code");
// // }
// });
// },
// ),
// ),
// ),
CustomTextFieldUserWrapper(
isFocused: _groupFocus,
padding: const EdgeInsets.symmetric(horizontal: 0),
isDesktop: widget.isDesktop,
child: SizedBox(
height: 40,
width: double.infinity,
child: Focus(
focusNode: _groupFocusNode,
onFocusChange: (hasFocus) {
setState(() {
_groupFocus = hasFocus;
});
},
child: GestureDetector(
onTap: () {
// Request focus when user taps
_groupFocusNode?.requestFocus();
},
child:
apiAllGroups == null
? Center(
child: Transform.scale(
scale: 0.5,
child: CircularProgressIndicator(),
),
)
: DropdownSearch<String>(
selectedItem: groupMap[selectedLevel],
enabled: !widget.isViewMode,
popupProps: PopupProps.menu(
menuProps: const MenuProps(
backgroundColor: Colors.white,
),
showSearchBox: true,
fit: FlexFit.loose, // Allows flexible height
itemBuilder:
(context, item, isSelected) => Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 6,
),
child: Text(
item,
style: GoogleFonts.poppins(fontSize: 11.5),
),
),
constraints: BoxConstraints(maxHeight: 250),
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
hintText: "Search Group...",
contentPadding: EdgeInsets.symmetric(
horizontal: 10,
),
),
),
),
// items: apiAllGroups!.map((group) {
// return "${group['name']} ";
// }).toList(),
items:
apiAllGroups!.map((group) {
return group['name']
.toString()
.trim(); // <-- trim spaces
}).toList(),
dropdownDecoratorProps: DropDownDecoratorProps(
dropdownSearchDecoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(
color:
(_groupFocus ?? false)
? (layoutColor ?? Colors.white)
: Colors.white,
width: 0.5,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color:
(_groupFocus ?? false)
? (layoutColor ?? Colors.white)
: Colors.white,
width: 0.5,
// const Color(0xFFD6D5E6),
),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: (layoutColor ?? Colors.grey),
width: 0.5,
),
),
contentPadding: EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
),
),
),
dropdownBuilder:
(context, selectedItem) => Align(
// Center-align selected item
alignment: Alignment.centerLeft,
child: Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(fontSize: 12),
),
),
onChanged: (String? newValue) {
if (newValue == null) return;
final levelId =
groupMap.entries
.firstWhere(
(entry) => entry.value == newValue,
)
.key;
setState(() {
selectedLevel = levelId;
});
widget.onLevelChanged?.call(
levelId,
); // ✅ pass the ID not the name
},
),
),
),
),
),
],
);
}
Widget buildApprover1(bool isDesktop) {
return Container(
color: Colors.white,
// child: Expanded(
// Allow first column to take available space
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"First Approver",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
SizedBox(height: 5),
CustomTextFieldUserWrapper(
isFocused: _firstApprovalFocus,
padding: const EdgeInsets.symmetric(horizontal: 0),
isDesktop: isDesktop,
child: SizedBox(
height: 40,
width: double.infinity,
child: Focus(
focusNode: _firstApprovalFocusNode,
onFocusChange: (hasFocus) {
setState(() {
_firstApprovalFocus = hasFocus;
});
},
child: GestureDetector(
onTap: () {
// Request focus when user taps
_firstApprovalFocusNode?.requestFocus();
},
child:
apiUserData == null
? Center(
child: Transform.scale(
scale: 0.5,
child: CircularProgressIndicator(),
),
)
: DropdownSearch<String>(
selectedItem:
userMap[selectedFirstApprover],
enabled: !widget.isViewMode,
popupProps: PopupProps.menu(
showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
menuProps: const MenuProps(
backgroundColor: Colors.white,
),
itemBuilder:
(context, item, isSelected) =>
Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 6,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize: 11.5,
),
),
),
constraints: BoxConstraints(
maxHeight: 250,
),
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
hintText: "Search User...",
contentPadding: EdgeInsets.symmetric(
horizontal: 10,
),
),
),
),
items:
apiUserData!.map((user) {
return "${user['first_name']} ${user['last_name']}";
}).toList(),
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(8),
borderSide: BorderSide(
color:
(_firstApprovalFocus ??
false)
? (layoutColor ??
Colors.white)
: Colors.white,
width: 0.5,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color:
(_firstApprovalFocus ??
false)
? (layoutColor ??
Colors.white)
: Colors.white,
width: 0.5,
// const Color(0xFFD6D5E6),
),
),
focusedBorder:
OutlineInputBorder(
borderSide: BorderSide(
color:
(layoutColor ??
Colors.grey),
width: 0.5,
),
),
contentPadding:
EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
),
),
),
dropdownBuilder:
(context, selectedItem) => Align(
// Center-align selected item
alignment: Alignment.centerLeft,
child: Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
),
),
),
// onChanged: (String? newValue) {
// setState(() {
// selectedFirstApprover = userMap.entries
// .firstWhere(
// (entry) => entry.value == newValue)
// .key;
//
// // if (selectedCountry!.isNotEmpty) {
// // errorMessages.remove("country_code");
// // }
// });
// widget.onFirstApproverChanged?.call(newValue);
// },
onChanged: (String? newValue) {
if (newValue == null) return;
final approverId =
userMap.entries
.firstWhere(
(entry) =>
entry.value == newValue,
)
.key;
setState(() {
selectedFirstApprover = approverId;
});
widget.onFirstApproverChanged?.call(
approverId,
); // ✅ not newValue, but approverId
},
),
),
),
),
),
],
),
],
),
],
),
// ),
);
}
Widget buildApprover2(bool isDesktop) {
return Container(
color: Colors.white,
// child: Expanded(
// Allow second column to take available space
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Second Approver",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
SizedBox(height: 5),
CustomTextFieldUserWrapper(
isFocused: _secondApprovalFocus,
padding: const EdgeInsets.symmetric(horizontal: 0),
isDesktop: isDesktop,
child: SizedBox(
height: 40,
width: double.infinity,
child: Focus(
focusNode: _secondApprovalFocusNode,
onFocusChange: (hasFocus) {
setState(() {
_secondApprovalFocus = hasFocus;
});
},
child: GestureDetector(
onTap: () {
// Request focus when user taps
_secondApprovalFocusNode?.requestFocus();
},
child:
apiUserData == null
? Center(
child: Transform.scale(
scale: 0.5,
child: CircularProgressIndicator(),
),
)
: DropdownSearch<String>(
selectedItem:
userMap[selectedSecondApprover],
enabled: !widget.isViewMode,
popupProps: PopupProps.menu(
showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
menuProps: const MenuProps(
backgroundColor: Colors.white,
),
itemBuilder:
(context, item, isSelected) =>
Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 6,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize: 11.5,
),
),
),
constraints: BoxConstraints(
maxHeight: 250,
),
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
hintText: "Search User...",
contentPadding: EdgeInsets.symmetric(
horizontal: 10,
),
),
),
),
items:
apiUserData!.map((user) {
return "${user['first_name']} ${user['last_name']}";
}).toList(),
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(8),
borderSide: BorderSide(
color:
(_secondApprovalFocus ??
false)
? (layoutColor ??
Colors.white)
: Colors.white,
width: 0.5,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color:
(_secondApprovalFocus ??
false)
? (layoutColor ??
Colors.white)
: Colors.white,
width: 0.5,
// const Color(0xFFD6D5E6),
),
),
focusedBorder:
OutlineInputBorder(
borderSide: BorderSide(
color:
(layoutColor ??
Colors.grey),
width: 0.5,
),
),
contentPadding:
EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
),
),
),
dropdownBuilder:
(context, selectedItem) => Align(
// Center-align selected item
alignment: Alignment.centerLeft,
child: Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
),
),
),
onChanged: (String? newValue) {
if (newValue == null) return;
final approverId =
userMap.entries
.firstWhere(
(entry) =>
entry.value == newValue,
)
.key;
setState(() {
selectedSecondApprover = approverId;
});
widget.onSecondApproverChanged?.call(
approverId,
); // ✅ not newValue, but approverId
},
// onChanged: (String? newValue) {
// setState(() {
// selectedSecondApprover = userMap.entries
// .firstWhere(
// (entry) => entry.value == newValue)
// .key;
//
// // if (selectedCountry!.isNotEmpty) {
// // errorMessages.remove("country_code");
// // }
// });
// },
),
),
),
),
),
],
),
],
),
],
),
// ),
);
}
Widget buildApprover3(bool isDesktop) {
return Container(
color: Colors.white,
// child: Expanded(
// Allow second column to take available space
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Third Approver",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
SizedBox(height: 5),
CustomTextFieldUserWrapper(
isFocused: _thirdApprovalFocus,
padding: const EdgeInsets.symmetric(horizontal: 0),
isDesktop: isDesktop,
child: SizedBox(
height: 40,
width: double.infinity,
child: Focus(
focusNode: _thirdApprovalFocusNode,
onFocusChange: (hasFocus) {
setState(() {
_thirdApprovalFocus = hasFocus;
});
},
child: GestureDetector(
onTap: () {
// Request focus when user taps
_thirdApprovalFocusNode?.requestFocus();
},
child:
apiUserData == null
? Center(
child: Transform.scale(
scale: 0.5,
child: CircularProgressIndicator(),
),
)
: DropdownSearch<String>(
selectedItem:
userMap[selectedThirdApprover],
enabled: !widget.isViewMode,
popupProps: PopupProps.menu(
showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
menuProps: const MenuProps(
backgroundColor: Colors.white,
),
itemBuilder:
(context, item, isSelected) =>
Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 6,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize: 11.5,
),
),
),
constraints: BoxConstraints(
maxHeight: 250,
),
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
hintText: "Search User...",
contentPadding: EdgeInsets.symmetric(
horizontal: 10,
),
),
),
),
items:
apiUserData!.map((user) {
return "${user['first_name']} ${user['last_name']}";
}).toList(),
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(8),
borderSide: BorderSide(
color:
(_thirdApprovalFocus ??
false)
? (layoutColor ??
Colors.white)
: Colors.white,
width: 0.5,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color:
(_thirdApprovalFocus ??
false)
? (layoutColor ??
Colors.white)
: Colors.white,
width: 0.5,
// const Color(0xFFD6D5E6),
),
),
focusedBorder:
OutlineInputBorder(
borderSide: BorderSide(
color:
(layoutColor ??
Colors.grey),
width: 0.5,
),
),
contentPadding:
EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
),
),
),
dropdownBuilder:
(context, selectedItem) => Align(
// Center-align selected item
alignment: Alignment.centerLeft,
child: Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
),
),
),
onChanged: (String? newValue) {
if (newValue == null) return;
final approverId =
userMap.entries
.firstWhere(
(entry) =>
entry.value == newValue,
)
.key;
setState(() {
selectedThirdApprover = approverId;
});
widget.onThirdApproverChanged?.call(
approverId,
); // ✅ not newValue, but approverId
},
// onChanged: (String? newValue) {
// setState(() {
// selectedThirdApprover = userMap.entries
// .firstWhere(
// (entry) => entry.value == newValue)
// .key;
//
// // if (selectedCountry!.isNotEmpty) {
// // errorMessages.remove("country_code");
// // }
// });
// },
),
),
),
),
),
],
),
],
),
],
),
// ),
);
}
Widget buildExceptionApprover(bool isDesktop) {
return Container(
color: Colors.white,
// child: Expanded(
// Allow first column to take available space
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Fourth Approver",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
SizedBox(height: 5),
CustomTextFieldUserWrapper(
isFocused: _exceptionalApprovalFocus,
padding: const EdgeInsets.symmetric(horizontal: 0),
isDesktop: isDesktop,
child: SizedBox(
height: 40,
width: double.infinity,
child: Focus(
focusNode: _exceptionalApprovalFocusNode,
onFocusChange: (hasFocus) {
setState(() {
_exceptionalApprovalFocus = hasFocus;
});
},
child: GestureDetector(
onTap: () {
// Request focus when user taps
_exceptionalApprovalFocusNode?.requestFocus();
},
child:
apiUserData == null
? Center(
child: Transform.scale(
scale: 0.5,
child: CircularProgressIndicator(),
),
)
: DropdownSearch<String>(
selectedItem:
userMap[selectedExceptionalApprover],
enabled: !widget.isViewMode,
popupProps: PopupProps.menu(
showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
menuProps: const MenuProps(
backgroundColor: Colors.white,
),
itemBuilder:
(context, item, isSelected) =>
Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 6,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize: 11.5,
),
),
),
constraints: BoxConstraints(
maxHeight: 250,
),
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
hintText: "Search User...",
contentPadding: EdgeInsets.symmetric(
horizontal: 10,
),
),
),
),
items:
apiUserData!.map((user) {
return "${user['first_name']} ${user['last_name']}";
}).toList(),
dropdownDecoratorProps: DropDownDecoratorProps(
dropdownSearchDecoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(
8,
),
borderSide: BorderSide(
color:
(_exceptionalApprovalFocus ??
false)
? (layoutColor ??
Colors.white)
: Colors.white,
width: 0.5,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color:
(_exceptionalApprovalFocus ??
false)
? (layoutColor ??
Colors.white)
: Colors.white,
width: 0.5,
// const Color(0xFFD6D5E6),
),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color:
(layoutColor ?? Colors.white),
width: 0.5,
),
),
contentPadding: EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
),
),
),
dropdownBuilder:
(context, selectedItem) => Align(
// Center-align selected item
alignment: Alignment.centerLeft,
child: Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
),
),
),
onChanged: (String? newValue) {
if (newValue == null) return;
final approverId =
userMap.entries
.firstWhere(
(entry) =>
entry.value == newValue,
)
.key;
setState(() {
selectedExceptionalApprover =
approverId;
});
widget.onExceptionalApproverChanged?.call(
approverId,
); // ✅ not newValue, but approverId
},
),
),
),
),
),
],
),
],
),
],
),
// ),
);
}
Widget buildApproverSubstitute1(bool isDesktop) {
return Container(
color: Colors.white,
// child: Expanded(
// Allow first column to take available space
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Delegate To",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
SizedBox(height: 5),
CustomTextFieldUserWrapper(
isFocused: _delegateFocus,
padding: const EdgeInsets.symmetric(horizontal: 0),
isDesktop: isDesktop,
child: SizedBox(
height: 40,
width: double.infinity,
child: Focus(
focusNode: _delegateFocusNode,
onFocusChange: (hasFocus) {
setState(() {
_delegateFocus = hasFocus;
});
},
child: GestureDetector(
onTap: () {
_delegateFocusNode?.requestFocus();
},
child:
apiUserData == null
? Center(
child: Transform.scale(
scale: 0.5,
child: CircularProgressIndicator(),
),
)
: DropdownSearch<String>(
// selectedItem: userMap[selectedSubstituteApprover],
selectedItem:
selectedSubstituteApprover != null
? userMap[selectedSubstituteApprover]
: null,
enabled: !widget.isViewMode,
popupProps: PopupProps.menu(
showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
menuProps: const MenuProps(
backgroundColor: Colors.white,
),
itemBuilder:
(context, item, isSelected) =>
Container(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 6,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize: 11.5,
),
),
),
constraints: BoxConstraints(
maxHeight: 133,
),
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
hintText: "Search User...",
contentPadding: EdgeInsets.symmetric(
horizontal: 10,
),
),
),
),
items:
apiUserData!.map((user) {
return "${user['first_name']} ${user['last_name']}";
}).toList(),
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(8),
borderSide: BorderSide(
color:
(_delegateFocus ??
false)
? (layoutColor ??
Colors.white)
: Colors.white,
width: 0.5,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color:
(_delegateFocus ??
false)
? (layoutColor ??
Colors.white)
: Colors.white,
width: 0.5,
// const Color(0xFFD6D5E6),
),
),
focusedBorder:
OutlineInputBorder(
borderSide: BorderSide(
color:
(layoutColor ??
Colors.grey),
width: 0.5,
),
),
contentPadding:
EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 8.0,
),
),
),
dropdownBuilder:
(context, selectedItem) => Align(
// Center-align selected item
alignment: Alignment.centerLeft,
child: Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
),
),
),
// onChanged: (String? newValue) {
// setState(() {
// selectedFirstApprover = userMap.entries
// .firstWhere(
// (entry) => entry.value == newValue)
// .key;
//
// // if (selectedCountry!.isNotEmpty) {
// // errorMessages.remove("country_code");
// // }
// });
// widget.onFirstApproverChanged?.call(newValue);
// },
onChanged: (String? newValue) {
if (newValue == null) return;
final approverId =
userMap.entries
.firstWhere(
(entry) =>
entry.value == newValue,
)
.key;
setState(() {
selectedSubstituteApprover = approverId;
});
widget.onFirstSubsApproverChanged?.call(
approverId,
); // ✅ not newValue, but approverId
},
),
),
),
),
),
],
),
],
),
],
),
// ),
);
}
Widget buildDelegationStartDateField(bool isDesktop) {
Future<void> _selectCheckOutDate(BuildContext context) async {
DateTime now = DateTime.now();
DateTime today = DateTime(now.year, now.month, now.day);
// Parse date from notifier if available, else use today
DateTime initialDate;
initialDate = today;
// // Use previously selected date if valid
// if (_selectedCheckOutDate != null &&
// _selectedCheckOutDate!.isAfter(today)) {
// initialDate = _selectedCheckOutDate!;
// }
//
// final pickedDate = await showDatePicker(
// context: context,
// initialDate: initialDate,
// firstDate: initialDate,
// lastDate: DateTime(2100),
// );
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate:
_selectedCheckOutDate != null &&
_selectedCheckOutDate!.isAfter(today)
? _selectedCheckOutDate!
: today,
firstDate: today,
lastDate: DateTime(2100),
initialEntryMode: DatePickerEntryMode.calendarOnly,
);
if (pickedDate != null && pickedDate != _selectedCheckOutDate) {
setState(() {
_selectedCheckOutDate = pickedDate;
widget.controllers["delegationStartDate"]?.text = DateFormat(
'dd-MM-yyyy',
).format(pickedDate);
if (_selectedEndDate != null &&
_selectedEndDate!.isBefore(_selectedCheckOutDate!)) {
_selectedEndDate = null;
widget.controllers["delegationEndDate"]?.text = '';
}
});
}
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Start Date",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
SizedBox(height: 5),
CustomTextFieldUserWrapper(
isFocused: _startDateFocus,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 40,
child: Focus(
focusNode: _startDateFocusNode,
onKeyEvent: (FocusNode node, KeyEvent event) {
// Only act on KeyDown and when Enter is pressed
if (event is KeyDownEvent &&
(event.logicalKey == LogicalKeyboardKey.enter ||
event.logicalKey == LogicalKeyboardKey.numpadEnter)) {
_startDateFocusNode?.requestFocus();
_selectCheckOutDate(context);
return KeyEventResult.handled; // Stop default behavior
}
return KeyEventResult.ignored; // Allow normal handling
},
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTapDown: (details) {
_startDateFocusNode?.requestFocus();
_selectCheckOutDate(context);
},
child: AbsorbPointer(
child: TextField(
controller: widget.controllers["delegationStartDate"],
readOnly: true,
style: GoogleFonts.poppins(
fontSize: 12,
color: Colors.black,
),
decoration: InputDecoration(
labelText: "Select Date",
labelStyle: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Colors.grey,
),
floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16),
suffixIcon: Icon(
Icons.calendar_today,
size: 16,
color: Color(0xFF8B8FB2),
),
),
),
),
),
),
// child: GestureDetector(
// // onTap: () async{
// // _selectCheckOutDate(context);
// //
// // },
// onTap: () async {
// _startDateFocusNode?.requestFocus();
// await _selectCheckOutDate(context);
// },
// child: AbsorbPointer(
// child: TextField(
// focusNode: _startDateFocusNode,
// controller: widget.controllers["delegationStartDate"],
// readOnly: true,
// style: const TextStyle(fontSize: 12),
// decoration: InputDecoration(
// labelText: "Select Date",
// labelStyle: const TextStyle(
// fontSize: 12,
// color: Colors.grey,
// ),
// floatingLabelBehavior: FloatingLabelBehavior.never,
// border: InputBorder.none,
// contentPadding: const EdgeInsets.symmetric(vertical: 16),
// suffixIcon: const Icon(
// Icons.calendar_today,
// size: 16,
// color: Colors.grey,
// ),
// ),
// ),
// ),
// ),
),
),
// if (errorMessages["start_date"] != null) ...[
// SizedBox(height: 5), // Space before error message
// Text(
// "Select Start Date",
// style: TextStyle(color: Colors.red, fontSize: 12),
// ),
// ],
],
);
}
Widget buildDelegationEndDateField(bool isDesktop) {
// DateTime? _selectedEndDate;
Future<void> _selectForexEndDate(BuildContext context) async {
DateTime now = DateTime.now();
DateTime today = DateTime(now.year, now.month, now.day);
DateTime minDate =
_selectedCheckOutDate != null ? _selectedCheckOutDate! : today;
// Parse date from notifier if available, else use today
DateTime initialDate;
initialDate = today;
//
// final pickedDate = await showDatePicker(
// context: context,
// initialDate: initialDate,
// firstDate: initialDate,
// lastDate: DateTime(2100),
// );
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate:
_selectedEndDate != null && _selectedEndDate!.isAfter(minDate)
? _selectedEndDate!
: minDate,
firstDate: minDate,
lastDate: DateTime(2100),
initialEntryMode: DatePickerEntryMode.calendarOnly,
);
if (pickedDate != null && pickedDate != _selectedEndDate) {
setState(() {
_selectedEndDate = pickedDate;
widget.controllers["delegationEndDate"]?.text = DateFormat(
'dd-MM-yyyy',
).format(pickedDate);
});
}
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"End Date",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
SizedBox(height: 5),
CustomTextFieldUserWrapper(
width: isDesktop ? MediaQuery.of(context).size.width * 0.2 : null,
isFocused: _endDateFocus,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 40,
child: Focus(
focusNode: _endDateFocusNode,
onKeyEvent: (FocusNode node, KeyEvent event) {
// Only act on KeyDown and when Enter is pressed
if (event is KeyDownEvent &&
(event.logicalKey == LogicalKeyboardKey.enter ||
event.logicalKey == LogicalKeyboardKey.numpadEnter)) {
if (!widget.isViewMode) {
_selectForexEndDate(context).then((_) {
_endDateFocusNode?.requestFocus();
});
}
return KeyEventResult.handled; // Stop default behavior
}
return KeyEventResult.ignored; // Allow normal handling
},
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTapDown: (details) {
if (!widget.isViewMode) {
_selectForexEndDate(context).then((_) {
_endDateFocusNode?.requestFocus();
});
}
},
child: AbsorbPointer(
child: TextField(
controller: widget.controllers["delegationEndDate"],
readOnly: true,
style: GoogleFonts.poppins(
fontSize: 12,
color: Colors.black,
),
decoration: InputDecoration(
labelText: "Select Date",
labelStyle: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Colors.grey,
),
floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 16),
suffixIcon: Icon(
Icons.calendar_today,
size: 16,
color: Color(0xFF8B8FB2),
),
),
),
),
),
),
// child: GestureDetector(
// // onTap: () async{
// // _selectCheckOutDate(context);
// //
// // },
// onTap: () async {
// _endDateFocusNode?.requestFocus();
// await _selectForexEndDate(context);
// },
// child: AbsorbPointer(
// child: TextField(
// focusNode: _endDateFocusNode,
// controller: widget.controllers["delegationEndDate"],
// readOnly: true,
// style: const TextStyle(fontSize: 12),
// decoration: InputDecoration(
// labelText: "Select Date",
// labelStyle: const TextStyle(
// fontSize: 12,
// color: Colors.grey,
// ),
// floatingLabelBehavior: FloatingLabelBehavior.never,
// border: InputBorder.none,
// contentPadding: const EdgeInsets.symmetric(vertical: 16),
// suffixIcon: const Icon(
// Icons.calendar_today,
// size: 16,
// color: Colors.grey,
// ),
// ),
// ),
// ),
// ),
),
),
// if (widget.errorMessages["employeeCode"] != null) ...[
// SizedBox(height: 5), // Space before error message
// Text(
// widget.errorMessages["employeeCode"]!,
// style: TextStyle(color: Colors.red, fontSize: 12),
// ),
// ],
],
);
}
Widget buildReset(bool isDesktop) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Colors.black,
),
),
SizedBox(height: 8),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF114D8B),
foregroundColor: Colors.white, // Keep original color
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 3),
),
onPressed: () {
handleReset();
},
child: Text("Reset", style: GoogleFonts.poppins(fontSize: 11)),
),
],
);
}
}