This commit is contained in:
venba-Inspriron-3558 2025-06-30 18:23:02 +05:30
parent 12d11ed0d8
commit 3be15a71ef
5 changed files with 1393 additions and 1062 deletions

View File

@ -65,6 +65,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
Map<String, String?> FirstExceptionalApproverAction = {}; Map<String, String?> FirstExceptionalApproverAction = {};
Map<String, String?> SecondExceptionalApproverAction = {}; Map<String, String?> SecondExceptionalApproverAction = {};
Map<String, String?> ThirdExceptionalApproverAction = {}; Map<String, String?> ThirdExceptionalApproverAction = {};
Map<String, String?> FourthExceptionalApproverAction = {};
Map<String, String?> SelectedParallelExceptionalProcess = {}; Map<String, String?> SelectedParallelExceptionalProcess = {};
Map<String, String?> FirstAmendApproverAction = {}; Map<String, String?> FirstAmendApproverAction = {};
@ -157,7 +158,8 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
FirstExceptionalApproverAction.putIfAbsent(id, () => "None"); FirstExceptionalApproverAction.putIfAbsent(id, () => "None");
SecondExceptionalApproverAction.putIfAbsent(id, () => "None"); SecondExceptionalApproverAction.putIfAbsent(id, () => "None");
ThirdExceptionalApproverAction.putIfAbsent(id, () => "None"); ThirdExceptionalApproverAction.putIfAbsent(id, () => "None");
SelectedParallelExceptionalProcess.putIfAbsent(id, () => "3"); FourthExceptionalApproverAction.putIfAbsent(id, () => "None");
SelectedParallelExceptionalProcess.putIfAbsent(id, () => "4");
FirstAmendApproverAction.putIfAbsent(id, () => "None"); FirstAmendApproverAction.putIfAbsent(id, () => "None");
SecondAmendApproverAction.putIfAbsent(id, () => "None"); SecondAmendApproverAction.putIfAbsent(id, () => "None");
@ -176,6 +178,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"a1_exceptional_action": FirstExceptionalApproverAction[id], "a1_exceptional_action": FirstExceptionalApproverAction[id],
"a2_exceptional_action": SecondExceptionalApproverAction[id], "a2_exceptional_action": SecondExceptionalApproverAction[id],
"a3_exceptional_action": ThirdExceptionalApproverAction[id], "a3_exceptional_action": ThirdExceptionalApproverAction[id],
"a4_exceptional_action": FourthExceptionalApproverAction[id],
"exceptional_parallel_process_from": "exceptional_parallel_process_from":
SelectedParallelExceptionalProcess[id], SelectedParallelExceptionalProcess[id],
"a1_amendment_action": FirstAmendApproverAction[id], "a1_amendment_action": FirstAmendApproverAction[id],
@ -215,6 +218,8 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
item['a2_exceptional_action']?.toString(); item['a2_exceptional_action']?.toString();
ThirdExceptionalApproverAction[serviceId] = ThirdExceptionalApproverAction[serviceId] =
item['a3_exceptional_action']?.toString(); item['a3_exceptional_action']?.toString();
FourthExceptionalApproverAction[serviceId] =
item['a4_exceptional_action']?.toString();
SelectedParallelExceptionalProcess[serviceId] = SelectedParallelExceptionalProcess[serviceId] =
item['exceptional_parallel_process_from']?.toString() ?? "3"; item['exceptional_parallel_process_from']?.toString() ?? "3";
@ -269,6 +274,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
"a1_exceptional_action": FirstExceptionalApproverAction[serviceId], "a1_exceptional_action": FirstExceptionalApproverAction[serviceId],
"a2_exceptional_action": SecondExceptionalApproverAction[serviceId], "a2_exceptional_action": SecondExceptionalApproverAction[serviceId],
"a3_exceptional_action": ThirdExceptionalApproverAction[serviceId], "a3_exceptional_action": ThirdExceptionalApproverAction[serviceId],
"a4_exceptional_action": FourthExceptionalApproverAction[serviceId],
"exceptional_parallel_process_from": "exceptional_parallel_process_from":
SelectedParallelExceptionalProcess[serviceId], SelectedParallelExceptionalProcess[serviceId],
"a1_amendment_action": FirstAmendApproverAction[serviceId], "a1_amendment_action": FirstAmendApproverAction[serviceId],
@ -290,6 +296,7 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
final ae1 = FirstExceptionalApproverAction[serviceId]; final ae1 = FirstExceptionalApproverAction[serviceId];
final ae2 = SecondExceptionalApproverAction[serviceId]; final ae2 = SecondExceptionalApproverAction[serviceId];
final ae3 = ThirdExceptionalApproverAction[serviceId]; final ae3 = ThirdExceptionalApproverAction[serviceId];
final ae4 = FourthExceptionalApproverAction[serviceId];
final aa1 = FirstAmendApproverAction[serviceId]; final aa1 = FirstAmendApproverAction[serviceId];
final aa2 = SecondAmendApproverAction[serviceId]; final aa2 = SecondAmendApproverAction[serviceId];
@ -463,7 +470,8 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
FirstExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None"); FirstExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None");
SecondExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None"); SecondExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None");
ThirdExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None"); ThirdExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None");
SelectedParallelExceptionalProcess.putIfAbsent(ServiceId!, () => "3"); FourthExceptionalApproverAction.putIfAbsent(ServiceId!, () => "None");
SelectedParallelExceptionalProcess.putIfAbsent(ServiceId!, () => "4");
FirstAmendApproverAction.putIfAbsent(ServiceId!, () => "None"); FirstAmendApproverAction.putIfAbsent(ServiceId!, () => "None");
SecondAmendApproverAction.putIfAbsent(ServiceId!, () => "None"); SecondAmendApproverAction.putIfAbsent(ServiceId!, () => "None");
@ -1655,6 +1663,160 @@ class PolicyCriteriaState extends State<PolicyCriteria> {
], ],
), ),
), ),
Container(
padding: const EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
"A4",
style: GoogleFonts.poppins(
fontSize: 13,
),
),
Spacer(),
CustomTextFieldUserWrapper(
width:
MediaQuery.of(
context,
).size.width *
0.12,
isFocused: false,
isDesktop: widget.isDesktop,
child: SizedBox(
height: 35,
child: DropdownSearch<String>(
selectedItem:
FourthExceptionalApproverAction[ServiceId],
// enabled: !isViewMode,
popupProps: PopupProps.menu(
// showSearchBox: true,
fit:
FlexFit
.loose, // Allows flexible height
constraints: BoxConstraints(
maxHeight: 250,
),
itemBuilder:
(
context,
item,
isSelected,
) => Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Text(
item,
style: GoogleFonts.poppins(
fontSize:
12, // 👈 Smaller text size here
color:
Colors
.black, // You can customize this
),
),
),
),
items: [
"Approval",
"Notification",
"None",
],
dropdownDecoratorProps:
DropDownDecoratorProps(
dropdownSearchDecoration:
InputDecoration(
border:
InputBorder.none,
contentPadding:
EdgeInsets.symmetric(
horizontal: 1,
vertical: 5,
),
),
),
dropdownBuilder:
(context, selectedItem) =>
// Center-align selected item
Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xFF114D8B),
),
),
onChanged: (String? newValue) {
setState(() {
// Find the country_code based on selected country_name
FourthExceptionalApproverAction[ServiceId!] =
newValue;
// print("selectedUserType - $selectedUserType");
// if (selectedCountry!.isNotEmpty) {
// errorMessages.remove("country_code");
// }
});
},
),
),
),
Spacer(),
GestureDetector(
onTap: () {
setState(() {
SelectedParallelExceptionalProcess[ServiceId!] =
"4";
});
print(
"SelectedParallelExceptionalProcess - $SelectedParallelExceptionalProcess[ServiceId]",
);
},
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
((SelectedParallelExceptionalProcess[ServiceId] ==
"1") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"2") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"3") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"4"))
? Colors.green
: Colors.grey,
width: 2,
),
),
child: Icon(
Icons.check_circle,
size: 20,
color:
((SelectedParallelExceptionalProcess[ServiceId] ==
"1") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"2") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"3") ||
(SelectedParallelExceptionalProcess[ServiceId] ==
"4"))
? Colors.green
: Colors.grey,
// color: Colors.grey,
),
),
),
],
),
),
], ],
), ),
), ),

View File

@ -102,6 +102,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
String? selectedSecondApprover; String? selectedSecondApprover;
String? selectedThirdApprover; String? selectedThirdApprover;
String? selectedSubstituteApprover; String? selectedSubstituteApprover;
String? selectedExceptionalApprover;
String? selectedFileNames; String? selectedFileNames;
Uint8List? passportDocumentBytes; Uint8List? passportDocumentBytes;
@ -174,6 +175,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
"first_approver": selectedFirstApprover, "first_approver": selectedFirstApprover,
"second_approver": selectedSecondApprover, "second_approver": selectedSecondApprover,
"third_approver": selectedThirdApprover, "third_approver": selectedThirdApprover,
"exceptional_approver" : selectedExceptionalApprover,
"delegated_to_user_id": selectedSubstituteApprover, "delegated_to_user_id": selectedSubstituteApprover,
// "passport_number": controllers["passportNumber"]?.text, // "passport_number": controllers["passportNumber"]?.text,
// "place_of_issue": controllers["placeOfIssue"]?.text, // "place_of_issue": controllers["placeOfIssue"]?.text,
@ -292,6 +294,11 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
apiselectedUser?["third_approver"]?.toString() ?? ""; apiselectedUser?["third_approver"]?.toString() ?? "";
} }
if (apiselectedUser?["exceptional_approver"] != null) {
selectedExceptionalApprover =
apiselectedUser?["exceptional_approver"]?.toString() ?? "";
}
if (apiselectedUser?["delegated_to_user_id"] != null) { if (apiselectedUser?["delegated_to_user_id"] != null) {
print( print(
"UPDADele- ${apiselectedUser?["delegated_to_user_id"]?.toString()}", "UPDADele- ${apiselectedUser?["delegated_to_user_id"]?.toString()}",
@ -814,6 +821,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
Map<String, dynamic> data = userDetials; Map<String, dynamic> data = userDetials;
print("userDetials ====> $userDetials");
if (!isValidData(data)) { if (!isValidData(data)) {
print("USERDETAILS : $userDetials"); print("USERDETAILS : $userDetials");
print("Validation Failed: Required fields are missing."); print("Validation Failed: Required fields are missing.");
@ -1447,6 +1455,7 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
selectedFirstApprover: selectedFirstApprover, selectedFirstApprover: selectedFirstApprover,
selectedSecondApprover: selectedSecondApprover, selectedSecondApprover: selectedSecondApprover,
selectedThirdApprover: selectedThirdApprover, selectedThirdApprover: selectedThirdApprover,
selectedExceptionalApprover: selectedExceptionalApprover,
selectedSubstituteApprover: selectedSubstituteApprover, selectedSubstituteApprover: selectedSubstituteApprover,
onLevelChanged: (gender) { onLevelChanged: (gender) {
setState(() { setState(() {
@ -1473,6 +1482,11 @@ class _CreateUserFormDetialsState extends State<CreateUserFormDetials> {
selectedThirdApprover = role; selectedThirdApprover = role;
}); });
}, },
onExceptionalApproverChanged: (role) {
setState(() {
selectedExceptionalApprover = role;
});
},
onFirstSubsApproverChanged: (role) { onFirstSubsApproverChanged: (role) {
setState(() { setState(() {
selectedSubstituteApprover = role; selectedSubstituteApprover = role;

View File

@ -23,6 +23,7 @@ class OfficeDetails extends StatefulWidget {
final ValueChanged<String?>? onSecondApproverChanged; final ValueChanged<String?>? onSecondApproverChanged;
final ValueChanged<String?>? onThirdApproverChanged; final ValueChanged<String?>? onThirdApproverChanged;
final ValueChanged<String?>? onFirstSubsApproverChanged; final ValueChanged<String?>? onFirstSubsApproverChanged;
final ValueChanged<String?>? onExceptionalApproverChanged;
final String? selectedLevel; final String? selectedLevel;
final String? selectedDepartment; final String? selectedDepartment;
@ -30,6 +31,7 @@ class OfficeDetails extends StatefulWidget {
final String? selectedSecondApprover; final String? selectedSecondApprover;
final String? selectedThirdApprover; final String? selectedThirdApprover;
final String? selectedSubstituteApprover; final String? selectedSubstituteApprover;
final String? selectedExceptionalApprover;
const OfficeDetails({ const OfficeDetails({
Key? key, Key? key,
@ -48,6 +50,8 @@ class OfficeDetails extends StatefulWidget {
this.onSecondApproverChanged, this.onSecondApproverChanged,
this.onThirdApproverChanged, this.onThirdApproverChanged,
this.selectedSubstituteApprover, this.selectedSubstituteApprover,
this.selectedExceptionalApprover,
this.onExceptionalApproverChanged,
this.onFirstSubsApproverChanged, this.onFirstSubsApproverChanged,
this.userIdApi, this.userIdApi,
}) : super(key: key); }) : super(key: key);
@ -94,6 +98,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
String? selectedSecondApprover; String? selectedSecondApprover;
String? selectedThirdApprover; String? selectedThirdApprover;
String? selectedSubstituteApprover; String? selectedSubstituteApprover;
String? selectedExceptionalApprover;
String? selectedFileNames; String? selectedFileNames;
Uint8List? passportDocumentBytes; Uint8List? passportDocumentBytes;
@ -125,6 +130,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
"firstApproval", "firstApproval",
"secondApproval", "secondApproval",
"thirdApproval", "thirdApproval",
"exceptional_approver",
"employeeCode", "employeeCode",
"dateOfIssue", "dateOfIssue",
"dateOfExpiry", "dateOfExpiry",
@ -151,6 +157,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
selectedSecondApprover = widget.selectedSecondApprover; selectedSecondApprover = widget.selectedSecondApprover;
selectedThirdApprover = widget.selectedThirdApprover; selectedThirdApprover = widget.selectedThirdApprover;
selectedSubstituteApprover = widget.selectedSubstituteApprover; selectedSubstituteApprover = widget.selectedSubstituteApprover;
selectedExceptionalApprover = widget.selectedExceptionalApprover;
fetchDepartment(); fetchDepartment();
fetchUsers(); fetchUsers();
@ -307,6 +314,8 @@ class _OfficeDetailsState extends State<OfficeDetails> {
if (widget.isDesktop) SizedBox(height: 10), if (widget.isDesktop) SizedBox(height: 10),
_buildSecondRow(widget.isDesktop), _buildSecondRow(widget.isDesktop),
if (widget.isDesktop) SizedBox(height: 10), if (widget.isDesktop) SizedBox(height: 10),
_buildThirdRow(widget.isDesktop),
if (widget.isDesktop) SizedBox(height: 10),
Divider(thickness: 0.2, color: Colors.blueGrey.shade100), Divider(thickness: 0.2, color: Colors.blueGrey.shade100),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -321,7 +330,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
], ],
), ),
SizedBox(height: 15), SizedBox(height: 15),
_buildThirdRow(widget.isDesktop), _buildFourthRow(widget.isDesktop),
], ],
), ),
); );
@ -384,6 +393,28 @@ class _OfficeDetailsState extends State<OfficeDetails> {
} }
Widget _buildThirdRow(bool 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( return Container(
color: Colors.white, color: Colors.white,
child: child:
@ -1185,6 +1216,130 @@ class _OfficeDetailsState extends State<OfficeDetails> {
); );
} }
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(
"Exceptional Approver",
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Color(0xFF575A74),
),
),
SizedBox(height: 5),
CustomTextFieldUserWrapper(
isFocused: false,
isDesktop: isDesktop,
child: SizedBox(
height: 40,
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: InputBorder.none,
contentPadding: EdgeInsets.symmetric(
horizontal: 1,
),
),
),
dropdownBuilder:
(context, selectedItem) => Align(
// Center-align selected item
alignment: Alignment.centerLeft,
child: Text(
selectedItem ?? "Select",
style: GoogleFonts.poppins(
fontSize: 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) { Widget buildApproverSubstitute1(bool isDesktop) {
return Container( return Container(
color: Colors.white, color: Colors.white,
@ -1246,7 +1401,7 @@ class _OfficeDetailsState extends State<OfficeDetails> {
), ),
), ),
), ),
constraints: BoxConstraints(maxHeight: 250), constraints: BoxConstraints(maxHeight: 133),
searchFieldProps: TextFieldProps( searchFieldProps: TextFieldProps(
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search User...", hintText: "Search User...",

View File

@ -46,36 +46,36 @@ class Plan {
factory Plan.fromJson(Map<String, dynamic> json) { factory Plan.fromJson(Map<String, dynamic> json) {
print('Parsing Plan from JSON: $json'); print('Parsing Plan from JSON: $json');
return Plan( return Plan(
planId: json['plan_id']!.toString(), planId: json['plan_id']?.toString() ?? "",
employeeCode: json['employee_code']!.toString(), employeeCode: json['employee_code']?.toString() ?? "",
tripTitle: json['trip_title']!.toString(), tripTitle: json['trip_title']?.toString() ?? "",
tripType: json['trip_type_value']!.toString(), tripType: json['trip_type_value']?.toString() ?? "",
approver_status: approver_status:
json["approver_status"] == null json["approver_status"] == null
? '' ? ''
: json['approver_status']!.toString(), : json['approver_status']?.toString() ?? "",
status: json['status'] == "0" ? "Inactive" : "Active", status: json['status'] == "0" ? "Inactive" : "Active",
costCenter: json['cost_center_value']!.toString(), costCenter: json['cost_center_value']?.toString() ?? "" ,
functionalDepartment: json['functional_department_value']!.toString(), functionalDepartment: json['functional_department_value']?.toString() ?? "",
purposeOfTravel: json['purpose_of_travel_value']!.toString(), purposeOfTravel: json['purpose_of_travel_value']?.toString() ?? "",
soNumber: json['so_number']!.toString(), soNumber: json['so_number']?.toString() ?? "",
description: json['description']!.toString(), description: json['description']?.toString() ?? "",
isBillable: json['is_billable_value']!.toString(), isBillable: json['is_billable_value']?.toString() ?? "",
userName: json["user_name"]!.toString(), userName: json["user_name"]?.toString() ?? "",
travellerName: travellerName:
json["traveller_name"] == null json["traveller_name"] == null
? '' ? ''
: json["traveller_name"]!.toString(), : json["traveller_name"]?.toString() ?? "",
approverName: approverName:
json["approver_name"] == null json["approver_name"] == null
? '' ? ''
: json["approver_name"]!.toString(), : json["approver_name"]?.toString() ?? "",
statusValue: json["status_value"]!.toString(), statusValue: json["status_value"]?.toString() ?? "",
createdOn: json["created_on"], createdOn: json["created_on"]?.toString() ?? "",
approverId: approverId:
json["approver_id"] == null ? '' : json['approver_id']!.toString(), json["approver_id"] == null ? '' : json['approver_id']?.toString() ?? "",
delegaterId: delegaterId:
json["delegater_id"] == null ? '' : json['delegater_id']!.toString(), json["delegater_id"] == null ? '' : json['delegater_id']?.toString() ?? "",
); );
} }
} }