fixed permissions loading issue on employee screen

This commit is contained in:
Vaibhav Surve 2025-10-08 11:20:50 +05:30
parent 45bc492683
commit 7e75431feb
2 changed files with 111 additions and 83 deletions

View File

@ -13,6 +13,7 @@ class PermissionController extends GetxController {
var employeeInfo = Rxn<EmployeeInfo>(); var employeeInfo = Rxn<EmployeeInfo>();
var projectsInfo = <ProjectInfo>[].obs; var projectsInfo = <ProjectInfo>[].obs;
Timer? _refreshTimer; Timer? _refreshTimer;
var isLoading = true.obs;
@override @override
void onInit() { void onInit() {
@ -26,7 +27,8 @@ class PermissionController extends GetxController {
await loadData(token!); await loadData(token!);
_startAutoRefresh(); _startAutoRefresh();
} else { } else {
logSafe("Token is null or empty. Skipping API load and auto-refresh.", level: LogLevel.warning); logSafe("Token is null or empty. Skipping API load and auto-refresh.",
level: LogLevel.warning);
} }
} }
@ -37,19 +39,24 @@ class PermissionController extends GetxController {
logSafe("Auth token retrieved: $token", level: LogLevel.debug); logSafe("Auth token retrieved: $token", level: LogLevel.debug);
return token; return token;
} catch (e, stacktrace) { } catch (e, stacktrace) {
logSafe("Error retrieving auth token", level: LogLevel.error, error: e, stackTrace: stacktrace); logSafe("Error retrieving auth token",
level: LogLevel.error, error: e, stackTrace: stacktrace);
return null; return null;
} }
} }
Future<void> loadData(String token) async { Future<void> loadData(String token) async {
try { try {
isLoading.value = true;
final userData = await PermissionService.fetchAllUserData(token); final userData = await PermissionService.fetchAllUserData(token);
_updateState(userData); _updateState(userData);
await _storeData(); await _storeData();
logSafe("Data loaded and state updated successfully."); logSafe("Data loaded and state updated successfully.");
} catch (e, stacktrace) { } catch (e, stacktrace) {
logSafe("Error loading data from API", level: LogLevel.error, error: e, stackTrace: stacktrace); logSafe("Error loading data from API",
level: LogLevel.error, error: e, stackTrace: stacktrace);
} finally {
isLoading.value = false;
} }
} }
@ -60,7 +67,8 @@ class PermissionController extends GetxController {
projectsInfo.assignAll(userData['projects']); projectsInfo.assignAll(userData['projects']);
logSafe("State updated with user data."); logSafe("State updated with user data.");
} catch (e, stacktrace) { } catch (e, stacktrace) {
logSafe("Error updating state", level: LogLevel.error, error: e, stackTrace: stacktrace); logSafe("Error updating state",
level: LogLevel.error, error: e, stackTrace: stacktrace);
} }
} }
@ -89,7 +97,8 @@ class PermissionController extends GetxController {
logSafe("User data successfully stored in SharedPreferences."); logSafe("User data successfully stored in SharedPreferences.");
} catch (e, stacktrace) { } catch (e, stacktrace) {
logSafe("Error storing data", level: LogLevel.error, error: e, stackTrace: stacktrace); logSafe("Error storing data",
level: LogLevel.error, error: e, stackTrace: stacktrace);
} }
} }
@ -100,20 +109,23 @@ class PermissionController extends GetxController {
if (token?.isNotEmpty ?? false) { if (token?.isNotEmpty ?? false) {
await loadData(token!); await loadData(token!);
} else { } else {
logSafe("Token missing during auto-refresh. Skipping.", level: LogLevel.warning); logSafe("Token missing during auto-refresh. Skipping.",
level: LogLevel.warning);
} }
}); });
} }
bool hasPermission(String permissionId) { bool hasPermission(String permissionId) {
final hasPerm = permissions.any((p) => p.id == permissionId); final hasPerm = permissions.any((p) => p.id == permissionId);
logSafe("Checking permission $permissionId: $hasPerm", level: LogLevel.debug); logSafe("Checking permission $permissionId: $hasPerm",
level: LogLevel.debug);
return hasPerm; return hasPerm;
} }
bool isUserAssignedToProject(String projectId) { bool isUserAssignedToProject(String projectId) {
final assigned = projectsInfo.any((project) => project.id == projectId); final assigned = projectsInfo.any((project) => project.id == projectId);
logSafe("Checking project assignment for $projectId: $assigned", level: LogLevel.debug); logSafe("Checking project assignment for $projectId: $assigned",
level: LogLevel.debug);
return assigned; return assigned;
} }

View File

@ -248,33 +248,46 @@ class _EmployeesScreenState extends State<EmployeesScreen> with UIMixin {
} }
Widget _buildFloatingActionButton() { Widget _buildFloatingActionButton() {
if (!permissionController.hasPermission(Permissions.manageEmployees)) { return Obx(() {
return const SizedBox.shrink(); // Show nothing while permissions are loading
} if (permissionController.isLoading.value) {
return const SizedBox.shrink();
}
return InkWell( // Show FAB only if user has Manage Employees permission
onTap: _onAddNewEmployee, final hasPermission =
borderRadius: BorderRadius.circular(28), permissionController.hasPermission(Permissions.manageEmployees);
child: Container( if (!hasPermission) {
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), return const SizedBox.shrink();
decoration: BoxDecoration( }
color: Colors.red,
borderRadius: BorderRadius.circular(28), return InkWell(
boxShadow: const [ onTap: _onAddNewEmployee,
BoxShadow( borderRadius: BorderRadius.circular(28),
color: Colors.black26, blurRadius: 6, offset: Offset(0, 3)) child: Container(
], padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(28),
boxShadow: const [
BoxShadow(
color: Colors.black26,
blurRadius: 6,
offset: Offset(0, 3),
)
],
),
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.add, color: Colors.white),
SizedBox(width: 8),
Text('Add New Employee', style: TextStyle(color: Colors.white)),
],
),
), ),
child: const Row( );
mainAxisSize: MainAxisSize.min, });
children: [
Icon(Icons.add, color: Colors.white),
SizedBox(width: 8),
Text('Add New Employee', style: TextStyle(color: Colors.white)),
],
),
),
);
} }
Widget _buildSearchAndActionRow() { Widget _buildSearchAndActionRow() {
@ -371,60 +384,63 @@ class _EmployeesScreenState extends State<EmployeesScreen> with UIMixin {
} }
Widget _buildPopupMenu() { Widget _buildPopupMenu() {
if (!permissionController.hasPermission(Permissions.viewAllEmployees)) { return Obx(() {
return const SizedBox.shrink(); if (permissionController.isLoading.value ||
} !permissionController.hasPermission(Permissions.viewAllEmployees)) {
return const SizedBox.shrink();
}
return PopupMenuButton<String>( return PopupMenuButton<String>(
icon: Stack( icon: Stack(
clipBehavior: Clip.none, clipBehavior: Clip.none,
children: [ children: [
const Icon(Icons.tune, color: Colors.black), const Icon(Icons.tune, color: Colors.black),
Obx(() => _employeeController.isAllEmployeeSelected.value Obx(() => _employeeController.isAllEmployeeSelected.value
? Positioned( ? Positioned(
right: -1, right: -1,
top: -1, top: -1,
child: Container( child: Container(
width: 10, width: 10,
height: 10, height: 10,
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Colors.red, shape: BoxShape.circle), color: Colors.red, shape: BoxShape.circle),
),
)
: const SizedBox.shrink()),
],
),
onSelected: (value) async {
if (value == 'all_employees') {
_employeeController.isAllEmployeeSelected.toggle();
await _initEmployees();
_employeeController.update(['employee_screen_controller']);
}
},
itemBuilder: (_) => [
PopupMenuItem<String>(
value: 'all_employees',
child: Obx(
() => Row(
children: [
Checkbox(
value: _employeeController.isAllEmployeeSelected.value,
onChanged: (_) => Navigator.pop(context, 'all_employees'),
checkColor: Colors.white,
activeColor: Colors.blueAccent,
side: const BorderSide(color: Colors.black, width: 1.5),
fillColor: MaterialStateProperty.resolveWith<Color>(
(states) => states.contains(MaterialState.selected)
? Colors.blueAccent
: Colors.white),
), ),
) const Text('All Employees'),
: const SizedBox.shrink()), ],
], ),
),
onSelected: (value) async {
if (value == 'all_employees') {
_employeeController.isAllEmployeeSelected.toggle();
await _initEmployees();
_employeeController.update(['employee_screen_controller']);
}
},
itemBuilder: (_) => [
PopupMenuItem<String>(
value: 'all_employees',
child: Obx(
() => Row(
children: [
Checkbox(
value: _employeeController.isAllEmployeeSelected.value,
onChanged: (_) => Navigator.pop(context, 'all_employees'),
checkColor: Colors.white,
activeColor: Colors.blueAccent,
side: const BorderSide(color: Colors.black, width: 1.5),
fillColor: MaterialStateProperty.resolveWith<Color>(
(states) => states.contains(MaterialState.selected)
? Colors.blueAccent
: Colors.white),
),
const Text('All Employees'),
],
), ),
), ),
), ],
], );
); });
} }
Widget _buildEmployeeList() { Widget _buildEmployeeList() {