implementation of manage reporting inside employee profile
This commit is contained in:
parent
01d7a2fd3b
commit
548ecb33a6
@ -13,14 +13,16 @@ class ManageReportingBottomSheet extends StatefulWidget {
|
||||
final EmployeeModel? initialEmployee;
|
||||
final bool hideMainSelector;
|
||||
final bool renderAsCard;
|
||||
final bool hideLoggedUserFromSelection; // ✅ new
|
||||
final bool hideLoggedUserFromSelection;
|
||||
final String? loggedUserId;
|
||||
|
||||
const ManageReportingBottomSheet({
|
||||
super.key,
|
||||
this.initialEmployee,
|
||||
this.hideMainSelector = false,
|
||||
this.renderAsCard = false,
|
||||
this.hideLoggedUserFromSelection = false, // default false
|
||||
this.hideLoggedUserFromSelection = false,
|
||||
this.loggedUserId,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -211,21 +213,76 @@ class _ManageReportingBottomSheetState
|
||||
Future<void> _handleSubmit() async {
|
||||
if (_selectedEmployee == null) {
|
||||
showAppSnackbar(
|
||||
title: 'Error',
|
||||
message: 'Please select the employee.',
|
||||
type: SnackbarType.error);
|
||||
title: 'Error',
|
||||
message: 'Please select the employee.',
|
||||
type: SnackbarType.error,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_selectedPrimary.isEmpty) {
|
||||
showAppSnackbar(
|
||||
title: 'Error',
|
||||
message: 'Please select at least one primary employee.',
|
||||
type: SnackbarType.error);
|
||||
title: 'Error',
|
||||
message: 'Please select at least one primary employee.',
|
||||
type: SnackbarType.error,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final employeeId = _selectedEmployee!.id;
|
||||
|
||||
// === BUILD PAYLOAD (updated logic) ===
|
||||
|
||||
// fetch current assignments so we can deactivate old ones
|
||||
List<dynamic>? currentAssignments;
|
||||
try {
|
||||
currentAssignments =
|
||||
await ApiService.getOrganizationHierarchyList(employeeId);
|
||||
} catch (_) {
|
||||
currentAssignments = null;
|
||||
}
|
||||
|
||||
// helper sets of newly selected ids
|
||||
final newPrimaryIds = _selectedPrimary.map((e) => e.id).toSet();
|
||||
final newSecondaryIds = _selectedSecondary.map((e) => e.id).toSet();
|
||||
|
||||
final List<Map<String, dynamic>> payload = [];
|
||||
|
||||
// 1) For current active assignments: if they are not in new selections -> add isActive:false
|
||||
if (currentAssignments != null && currentAssignments.isNotEmpty) {
|
||||
for (final item in currentAssignments) {
|
||||
try {
|
||||
final reportTo = item['reportTo'];
|
||||
if (reportTo == null) continue;
|
||||
final reportToId = reportTo['id'] as String?;
|
||||
if (reportToId == null) continue;
|
||||
final isPrimary = item['isPrimary'] == true;
|
||||
final currentlyActive =
|
||||
item['isActive'] == true || item['isActive'] == null; // be safe
|
||||
|
||||
// if currently active and not included in new selection -> mark false
|
||||
if (currentlyActive) {
|
||||
if (isPrimary && !newPrimaryIds.contains(reportToId)) {
|
||||
payload.add({
|
||||
"reportToId": reportToId,
|
||||
"isPrimary": true,
|
||||
"isActive": false,
|
||||
});
|
||||
} else if (!isPrimary && !newSecondaryIds.contains(reportToId)) {
|
||||
payload.add({
|
||||
"reportToId": reportToId,
|
||||
"isPrimary": false,
|
||||
"isActive": false,
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (_) {
|
||||
// ignore malformed items (same behavior as before)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2) Add new primary (active)
|
||||
for (final emp in _selectedPrimary) {
|
||||
payload.add({
|
||||
"reportToId": emp.id,
|
||||
@ -233,6 +290,8 @@ class _ManageReportingBottomSheetState
|
||||
"isActive": true,
|
||||
});
|
||||
}
|
||||
|
||||
// 3) Add new secondary (active)
|
||||
for (final emp in _selectedSecondary) {
|
||||
payload.add({
|
||||
"reportToId": emp.id,
|
||||
@ -242,11 +301,13 @@ class _ManageReportingBottomSheetState
|
||||
}
|
||||
|
||||
setState(() => _isSubmitting = true);
|
||||
// show loader
|
||||
Get.dialog(const Center(child: CircularProgressIndicator()),
|
||||
barrierDismissible: false);
|
||||
|
||||
final employeeId = _selectedEmployee!.id;
|
||||
// show loader
|
||||
Get.dialog(
|
||||
const Center(child: CircularProgressIndicator()),
|
||||
barrierDismissible: false,
|
||||
);
|
||||
|
||||
final success = await ApiService.manageOrganizationHierarchy(
|
||||
employeeId: employeeId,
|
||||
payload: payload,
|
||||
@ -254,14 +315,14 @@ class _ManageReportingBottomSheetState
|
||||
|
||||
// hide loader
|
||||
if (Get.isDialogOpen == true) Get.back();
|
||||
|
||||
setState(() => _isSubmitting = false);
|
||||
|
||||
if (success) {
|
||||
showAppSnackbar(
|
||||
title: 'Success',
|
||||
message: 'Reporting assigned successfully',
|
||||
type: SnackbarType.success);
|
||||
title: 'Success',
|
||||
message: 'Reporting assigned successfully',
|
||||
type: SnackbarType.success,
|
||||
);
|
||||
|
||||
// ✅ Refresh both the organization hierarchy and employee details so UI shows updated managers
|
||||
try {
|
||||
@ -283,9 +344,10 @@ class _ManageReportingBottomSheetState
|
||||
}
|
||||
} else {
|
||||
showAppSnackbar(
|
||||
title: 'Error',
|
||||
message: 'Failed to assign reporting. Please try again.',
|
||||
type: SnackbarType.error);
|
||||
title: 'Error',
|
||||
message: 'Failed to assign reporting. Please try again.',
|
||||
type: SnackbarType.error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,11 +429,6 @@ class _ManageReportingBottomSheetState
|
||||
backgroundColor: Colors.indigo.shade50,
|
||||
labelStyle: TextStyle(color: AppTheme.primaryColor),
|
||||
deleteIcon: const Icon(Icons.close, size: 16),
|
||||
onDeleted: () => setState(() {
|
||||
_selectedEmployee = null;
|
||||
_selectEmployeeController.clear();
|
||||
_resetReportersOnly();
|
||||
}),
|
||||
),
|
||||
)
|
||||
else
|
||||
@ -473,12 +530,21 @@ class _ManageReportingBottomSheetState
|
||||
spacing: 6,
|
||||
runSpacing: 6,
|
||||
children: selectedList.map((emp) {
|
||||
final isProfileEmployee = widget.initialEmployee != null &&
|
||||
emp.id == widget.initialEmployee!.id;
|
||||
|
||||
return Chip(
|
||||
label: Text(emp.name, style: const TextStyle(fontSize: 12)),
|
||||
backgroundColor: Colors.indigo.shade50,
|
||||
backgroundColor: isProfileEmployee
|
||||
? Colors.indigo.shade50
|
||||
: Colors.indigo.shade50,
|
||||
labelStyle: TextStyle(color: AppTheme.primaryColor),
|
||||
deleteIcon: const Icon(Icons.close, size: 16),
|
||||
onDeleted: () => selectedList.remove(emp),
|
||||
// Only show delete icon / action for non-profile employees
|
||||
deleteIcon: isProfileEmployee
|
||||
? null
|
||||
: const Icon(Icons.close, size: 16),
|
||||
onDeleted:
|
||||
isProfileEmployee ? null : () => selectedList.remove(emp),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user