import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:marco/helpers/theme/app_theme.dart'; import 'package:marco/helpers/utils/mixins/ui_mixin.dart'; import 'package:marco/helpers/utils/my_shadow.dart'; import 'package:marco/helpers/widgets/my_breadcrumb.dart'; import 'package:marco/helpers/widgets/my_breadcrumb_item.dart'; import 'package:marco/helpers/widgets/my_card.dart'; import 'package:marco/helpers/widgets/my_spacing.dart'; import 'package:marco/helpers/widgets/my_text.dart'; import 'package:marco/controller/permission_controller.dart'; import 'package:marco/model/employees/add_employee_bottom_sheet.dart'; import 'package:marco/controller/dashboard/employees_screen_controller.dart'; import 'package:marco/helpers/widgets/avatar.dart'; import 'package:marco/model/employees/employee_detail_bottom_sheet.dart'; import 'package:marco/controller/project_controller.dart'; import 'package:marco/helpers/widgets/my_custom_skeleton.dart'; class EmployeesScreen extends StatefulWidget { const EmployeesScreen({super.key}); @override State createState() => _EmployeesScreenState(); } class _EmployeesScreenState extends State with UIMixin { final EmployeesScreenController employeeScreenController = Get.put(EmployeesScreenController()); final PermissionController permissionController = Get.put(PermissionController()); Future _refreshEmployees() async { try { final selectedProjectId = Get.find().selectedProject?.id; final isAllSelected = employeeScreenController.isAllEmployeeSelected.value; if (isAllSelected) { employeeScreenController.selectedProjectId = null; await employeeScreenController.fetchAllEmployees(); } else if (selectedProjectId != null) { employeeScreenController.selectedProjectId = selectedProjectId; await employeeScreenController .fetchEmployeesByProject(selectedProjectId); } else { // ❗ Clear employees if neither selected employeeScreenController.clearEmployees(); } employeeScreenController.update(['employee_screen_controller']); } catch (e, stackTrace) { debugPrint('Error refreshing employee data: ${e.toString()}'); debugPrintStack(stackTrace: stackTrace); } } @override void initState() { super.initState(); final selectedProjectId = Get.find().selectedProject?.id; if (selectedProjectId != null) { employeeScreenController.selectedProjectId = selectedProjectId; employeeScreenController.fetchEmployeesByProject(selectedProjectId); } else if (employeeScreenController.isAllEmployeeSelected.value) { employeeScreenController.selectedProjectId = null; employeeScreenController.fetchAllEmployees(); } else { employeeScreenController.clearEmployees(); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF5F5F5), appBar: PreferredSize( preferredSize: const Size.fromHeight(80), child: AppBar( backgroundColor: const Color(0xFFF5F5F5), elevation: 0.5, foregroundColor: Colors.black, titleSpacing: 0, centerTitle: false, leading: Padding( padding: const EdgeInsets.only(top: 15.0), // Aligns with title child: IconButton( icon: const Icon(Icons.arrow_back_ios_new, color: Colors.black, size: 20), onPressed: () { Get.offNamed('/dashboard'); }, ), ), title: Padding( padding: const EdgeInsets.only(top: 15.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ MyText.titleLarge( 'Employees', fontWeight: 700, color: Colors.black, ), const SizedBox(height: 2), GetBuilder( builder: (projectController) { final projectName = projectController.selectedProject?.name ?? 'Select Project'; return MyText.bodySmall( projectName, fontWeight: 600, maxLines: 1, overflow: TextOverflow.ellipsis, color: Colors.grey[700], ); }, ), ], ), ), ), ), floatingActionButton: InkWell( onTap: () async { final result = await showModalBottomSheet( context: context, isScrollControlled: true, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), backgroundColor: Colors.transparent, builder: (context) => AddEmployeeBottomSheet(), ); if (result == true) { await _refreshEmployees(); } }, borderRadius: BorderRadius.circular(28), child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: Colors.blueAccent, 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)), ], ), ), ), body: SafeArea( child: GetBuilder( init: employeeScreenController, tag: 'employee_screen_controller', builder: (controller) { return SingleChildScrollView( padding: const EdgeInsets.only(bottom: 80), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: MySpacing.x(flexSpacing), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ MyBreadcrumb( children: [ MyBreadcrumbItem(name: 'Dashboard'), MyBreadcrumbItem(name: 'Employees', active: true), ], ), ], ), ), MySpacing.height(flexSpacing), Padding( padding: MySpacing.x(flexSpacing), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Obx(() { return Row( children: [ Checkbox( value: employeeScreenController .isAllEmployeeSelected.value, activeColor: Colors.blueAccent, fillColor: MaterialStateProperty.resolveWith( (states) { if (states.contains(MaterialState.selected)) { return Colors.blueAccent; } return Colors.transparent; }), checkColor: Colors.white, side: BorderSide( color: Colors.black, width: 2, ), onChanged: (value) async { employeeScreenController .isAllEmployeeSelected.value = value!; if (value) { employeeScreenController.selectedProjectId = null; await employeeScreenController .fetchAllEmployees(); } else { final selectedProjectId = Get.find() .selectedProject ?.id; if (selectedProjectId != null) { employeeScreenController .selectedProjectId = selectedProjectId; await employeeScreenController .fetchEmployeesByProject( selectedProjectId); } else { // ✅ THIS is your critical path employeeScreenController.clearEmployees(); } } employeeScreenController .update(['employee_screen_controller']); }, ), MyText.bodyMedium( "All Employees", fontWeight: 600, ), ], ); }), const SizedBox(width: 16), MyText.bodyMedium("Refresh", fontWeight: 600), Tooltip( message: 'Refresh Data', child: InkWell( borderRadius: BorderRadius.circular(24), onTap: _refreshEmployees, child: MouseRegion( cursor: SystemMouseCursors.click, child: const Padding( padding: EdgeInsets.all(8), child: Icon( Icons.refresh, color: Colors.green, size: 28, ), ), ), ), ), ], ), ), Padding( padding: MySpacing.x(flexSpacing), child: dailyProgressReportTab(), ), ], ), ); }, ), ), ); } Widget dailyProgressReportTab() { return Obx(() { final isLoading = employeeScreenController.isLoading.value; final employees = employeeScreenController.employees; if (isLoading) { return SkeletonLoaders.employeeListSkeletonLoader(); } if (employees.isEmpty) { return Padding( padding: const EdgeInsets.only(top: 50), child: Center( child: MyText.bodySmall( "No Assigned Employees Found", fontWeight: 600, ), ), ); } return SingleChildScrollView( padding: const EdgeInsets.only(bottom: 80), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: employees.map((employee) { return InkWell( onTap: () { showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (context) => EmployeeDetailBottomSheet(employeeId: employee.id), ); }, child: MyCard.bordered( borderRadiusAll: 12, paddingAll: 10, margin: MySpacing.bottom(12), shadow: MyShadow(elevation: 3), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Avatar( firstName: employee.firstName, lastName: employee.lastName, size: 41, ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Wrap( crossAxisAlignment: WrapCrossAlignment.center, spacing: 6, children: [ MyText.titleMedium( employee.name, fontWeight: 600, overflow: TextOverflow.visible, maxLines: null, ), MyText.titleSmall( '(${employee.jobRole})', fontWeight: 400, overflow: TextOverflow.visible, maxLines: null, ), ], ), const SizedBox(height: 8), if (employee.email.isNotEmpty && employee.email != '-') ...[ Row( children: [ const Icon(Icons.email, size: 16, color: Colors.red), const SizedBox(width: 4), Flexible( child: MyText.titleSmall( employee.email, fontWeight: 400, overflow: TextOverflow.ellipsis, ), ), ], ), const SizedBox(height: 8), ], Row( children: [ const Icon(Icons.phone, size: 16, color: Colors.blueAccent), const SizedBox(width: 4), MyText.titleSmall( employee.phoneNumber, fontWeight: 400, ), ], ), ], ), ), ], ) ], ), )); }).toList(), ), ); }); } }