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/view/layouts/layout.dart'; import 'package:marco/controller/permission_controller.dart'; import 'package:marco/model/employees/employees_screen_filter_sheet.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'; 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 _openFilterSheet() async { final result = await showModalBottomSheet>( context: context, isScrollControlled: true, backgroundColor: Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(12)), ), builder: (context) => EmployeesScreenFilterSheet( controller: employeeScreenController, permissionController: permissionController, ), ); if (result != null) { final selectedProjectId = result['projectId'] as String?; if (selectedProjectId != employeeScreenController.selectedProjectId) { employeeScreenController.selectedProjectId = selectedProjectId; try { if (selectedProjectId == null) { await employeeScreenController.fetchAllEmployees(); } else { await employeeScreenController .fetchEmployeesByProject(selectedProjectId); } } catch (e) { debugPrint('Error fetching employees: ${e.toString()}'); } employeeScreenController.update(['employee_screen_controller']); } } } Future _refreshEmployees() async { try { final projectId = employeeScreenController.selectedProjectId; if (projectId == null) { await employeeScreenController.fetchAllEmployees(); } else { await employeeScreenController.fetchEmployeesByProject(projectId); } } catch (e) { debugPrint('Error refreshing employee data: ${e.toString()}'); } } @override Widget build(BuildContext context) { return Layout( 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)), ], ), ), ), child: GetBuilder( init: employeeScreenController, tag: 'employee_screen_controller', builder: (controller) { return Stack( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: MySpacing.x(flexSpacing), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ MyText.titleMedium( "Employees", fontSize: 18, fontWeight: 600, ), MyBreadcrumb( children: [ MyBreadcrumbItem(name: 'Dashboard'), MyBreadcrumbItem(name: 'Employees', active: true), ], ), ], ), ), MySpacing.height(flexSpacing), Padding( padding: MySpacing.x(flexSpacing), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ MyText.bodyMedium( "Filter", fontWeight: 600, ), Tooltip( message: 'Project', child: InkWell( borderRadius: BorderRadius.circular(24), onTap: _openFilterSheet, child: MouseRegion( cursor: SystemMouseCursors.click, child: const Padding( padding: EdgeInsets.all(8), child: Icon( Icons.filter_list_alt, color: Colors.blueAccent, size: 28, ), ), ), ), ), const SizedBox(width: 8), 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 const Center(child: CircularProgressIndicator()); } if (employees.isEmpty) { return 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: [ Row( children: [ MyText.titleMedium( employee.name, fontWeight: 600, ), const SizedBox(width: 6), MyText.titleSmall( '(${employee.jobRole})', fontWeight: 400, ), ], ), 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(), ), ); }); } }