From 008d35d57627c6e3bfdf4ea571b7091ee1debc79 Mon Sep 17 00:00:00 2001 From: Vaibhav Surve Date: Wed, 23 Jul 2025 15:16:41 +0530 Subject: [PATCH] feat: Refactor employee screen initialization and enhance loading states --- .../employees_screen_controller.dart | 71 +- lib/view/employees/employees_screen.dart | 697 +++++++++--------- 2 files changed, 380 insertions(+), 388 deletions(-) diff --git a/lib/controller/dashboard/employees_screen_controller.dart b/lib/controller/dashboard/employees_screen_controller.dart index 273e080..dd3cd93 100644 --- a/lib/controller/dashboard/employees_screen_controller.dart +++ b/lib/controller/dashboard/employees_screen_controller.dart @@ -17,24 +17,25 @@ class EmployeesScreenController extends GetxController { RxBool isLoading = false.obs; RxMap uploadingStates = {}.obs; - Rxn selectedEmployeeDetails = Rxn(); + Rxn selectedEmployeeDetails = + Rxn(); RxBool isLoadingEmployeeDetails = false.obs; @override void onInit() { super.onInit(); - fetchAllProjects(); - - final projectId = Get.find().selectedProject?.id; - - if (projectId != null) { - selectedProjectId = projectId; - fetchEmployeesByProject(projectId); - } else if (isAllEmployeeSelected.value) { - fetchAllEmployees(); - } else { - clearEmployees(); - } + isLoading.value = true; + fetchAllProjects().then((_) { + final projectId = Get.find().selectedProject?.id; + if (projectId != null) { + selectedProjectId = projectId; + fetchEmployeesByProject(projectId); + } else if (isAllEmployeeSelected.value) { + fetchAllEmployees(); + } else { + clearEmployees(); + } + }); } Future fetchAllProjects() async { @@ -50,7 +51,8 @@ class EmployeesScreenController extends GetxController { ); }, onEmpty: () { - logSafe("No project data found or API call failed.", level: LogLevel.warning); + logSafe("No project data found or API call failed.", + level: LogLevel.warning); }, ); @@ -66,19 +68,19 @@ class EmployeesScreenController extends GetxController { Future fetchAllEmployees() async { isLoading.value = true; + update(['employee_screen_controller']); await _handleApiCall( ApiService.getAllEmployees, onSuccess: (data) { employees.assignAll(data.map((json) => EmployeeModel.fromJson(json))); - logSafe( - "All Employees fetched: ${employees.length} employees loaded.", - level: LogLevel.info, - ); + logSafe("All Employees fetched: ${employees.length} employees loaded.", + level: LogLevel.info); }, onEmpty: () { employees.clear(); - logSafe("No Employee data found or API call failed.", level: LogLevel.warning); + logSafe("No Employee data found or API call failed.", + level: LogLevel.warning); }, ); @@ -88,7 +90,8 @@ class EmployeesScreenController extends GetxController { Future fetchEmployeesByProject(String? projectId) async { if (projectId == null || projectId.isEmpty) { - logSafe("Project ID is required but was null or empty.", level: LogLevel.error); + logSafe("Project ID is required but was null or empty.", + level: LogLevel.error); return; } @@ -106,15 +109,21 @@ class EmployeesScreenController extends GetxController { logSafe( "Employees fetched: ${employees.length} for project $projectId", level: LogLevel.info, - ); }, onEmpty: () { employees.clear(); - logSafe("No employees found for project $projectId.", level: LogLevel.warning, ); + logSafe( + "No employees found for project $projectId.", + level: LogLevel.warning, + ); }, onError: (e) { - logSafe("Error fetching employees for project $projectId", level: LogLevel.error, error: e, ); + logSafe( + "Error fetching employees for project $projectId", + level: LogLevel.error, + error: e, + ); }, ); @@ -131,15 +140,25 @@ class EmployeesScreenController extends GetxController { () => ApiService.getEmployeeDetails(employeeId), onSuccess: (data) { selectedEmployeeDetails.value = EmployeeDetailsModel.fromJson(data); - logSafe("Employee details loaded for $employeeId", level: LogLevel.info, ); + logSafe( + "Employee details loaded for $employeeId", + level: LogLevel.info, + ); }, onEmpty: () { selectedEmployeeDetails.value = null; - logSafe("No employee details found for $employeeId", level: LogLevel.warning, ); + logSafe( + "No employee details found for $employeeId", + level: LogLevel.warning, + ); }, onError: (e) { selectedEmployeeDetails.value = null; - logSafe("Error fetching employee details for $employeeId", level: LogLevel.error, error: e, ); + logSafe( + "Error fetching employee details for $employeeId", + level: LogLevel.error, + error: e, + ); }, ); diff --git a/lib/view/employees/employees_screen.dart b/lib/view/employees/employees_screen.dart index a1a59a9..2c2c1ad 100644 --- a/lib/view/employees/employees_screen.dart +++ b/lib/view/employees/employees_screen.dart @@ -4,7 +4,6 @@ import 'package:marco/helpers/theme/app_theme.dart'; import 'package:marco/helpers/utils/mixins/ui_mixin.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'; @@ -23,210 +22,117 @@ class EmployeesScreen extends StatefulWidget { } class _EmployeesScreenState extends State with UIMixin { - final EmployeesScreenController employeeScreenController = + final EmployeesScreenController _employeeController = Get.put(EmployeesScreenController()); - final PermissionController permissionController = - Get.put(PermissionController()); - final TextEditingController _searchController = TextEditingController(); final RxList _filteredEmployees = [].obs; @override void initState() { super.initState(); - WidgetsBinding.instance.addPostFrameCallback((_) { - 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(); - } - + _initEmployees(); _searchController.addListener(() { _filterEmployees(_searchController.text); }); }); } + Future _initEmployees() async { + final selectedProjectId = Get.find().selectedProject?.id; + + if (selectedProjectId != null) { + _employeeController.selectedProjectId = selectedProjectId; + await _employeeController.fetchEmployeesByProject(selectedProjectId); + } else if (_employeeController.isAllEmployeeSelected.value) { + _employeeController.selectedProjectId = null; + await _employeeController.fetchAllEmployees(); + } else { + _employeeController.clearEmployees(); + } + _filterEmployees(_searchController.text); + } + Future _refreshEmployees() async { try { final selectedProjectId = Get.find().selectedProject?.id; - final isAllSelected = - employeeScreenController.isAllEmployeeSelected.value; + final isAllSelected = _employeeController.isAllEmployeeSelected.value; if (isAllSelected) { - employeeScreenController.selectedProjectId = null; - await employeeScreenController.fetchAllEmployees(); + _employeeController.selectedProjectId = null; + await _employeeController.fetchAllEmployees(); } else if (selectedProjectId != null) { - employeeScreenController.selectedProjectId = selectedProjectId; - await employeeScreenController - .fetchEmployeesByProject(selectedProjectId); + _employeeController.selectedProjectId = selectedProjectId; + await _employeeController.fetchEmployeesByProject(selectedProjectId); } else { - employeeScreenController.clearEmployees(); + _employeeController.clearEmployees(); } _filterEmployees(_searchController.text); - employeeScreenController.update(['employee_screen_controller']); + _employeeController.update(['employee_screen_controller']); } catch (e, stackTrace) { - debugPrint('Error refreshing employee data: ${e.toString()}'); + debugPrint('Error refreshing employee data: $e'); debugPrintStack(stackTrace: stackTrace); } } void _filterEmployees(String query) { - final employees = employeeScreenController.employees; + final employees = _employeeController.employees; if (query.isEmpty) { _filteredEmployees.assignAll(employees); - } else { - final lowerQuery = query.toLowerCase(); - _filteredEmployees.assignAll( - employees.where((e) { - return e.name.toLowerCase().contains(lowerQuery) || - e.email.toLowerCase().contains(lowerQuery) || - e.phoneNumber.toLowerCase().contains(lowerQuery) || - e.jobRole.toLowerCase().contains(lowerQuery); - }), - ); + return; } + final lowerQuery = query.toLowerCase(); + _filteredEmployees.assignAll( + employees.where((e) => + e.name.toLowerCase().contains(lowerQuery) || + e.email.toLowerCase().contains(lowerQuery) || + e.phoneNumber.toLowerCase().contains(lowerQuery) || + e.jobRole.toLowerCase().contains(lowerQuery)), + ); + } + + Future _onAddNewEmployee() 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 == null || result['success'] != true) return; + + final employeeData = result['data']; + final employeeId = employeeData['id'] as String; + final jobRoleId = employeeData['jobRoleId'] as String?; + + await showModalBottomSheet( + context: context, + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(24))), + backgroundColor: Colors.transparent, + builder: (context) => AssignProjectBottomSheet( + employeeId: employeeId, + jobRoleId: jobRoleId ?? '', + ), + ); + + await _refreshEmployees(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, - appBar: PreferredSize( - preferredSize: const Size.fromHeight(72), - child: AppBar( - backgroundColor: const Color(0xFFF5F5F5), - elevation: 0.5, - automaticallyImplyLeading: false, - titleSpacing: 0, - title: Padding( - padding: MySpacing.xy(16, 0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - IconButton( - icon: const Icon(Icons.arrow_back_ios_new, - color: Colors.black, size: 20), - onPressed: () => Get.offNamed('/dashboard'), - ), - MySpacing.width(8), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - MyText.titleLarge( - 'Employees', - fontWeight: 700, - color: Colors.black, - ), - MySpacing.height(2), - GetBuilder( - builder: (projectController) { - final projectName = - projectController.selectedProject?.name ?? - 'Select Project'; - return Row( - children: [ - const Icon(Icons.work_outline, - size: 14, color: Colors.grey), - MySpacing.width(4), - Expanded( - child: MyText.bodySmall( - projectName, - fontWeight: 600, - overflow: TextOverflow.ellipsis, - color: Colors.grey[700], - ), - ), - ], - ); - }, - ), - ], - ), - ), - ], - ), - ), - ), - ), - floatingActionButton: InkWell( - onTap: () async { - // Step 1: Open AddEmployeeBottomSheet - final result = await showModalBottomSheet>( - context: context, - isScrollControlled: true, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(top: Radius.circular(16)), - ), - backgroundColor: Colors.transparent, - builder: (context) => AddEmployeeBottomSheet(), - ); - - // Step 2: Check if employee creation was successful - if (result != null && result['success'] == true) { - print("Employee data from bottom sheet: $result"); - - final employeeData = result['data']; - final employeeId = employeeData['id'] as String; - final jobRoleId = employeeData['jobRoleId'] as String?; - - // Step 3: Open AssignProjectBottomSheet for the new employee - await showModalBottomSheet( - context: context, - isScrollControlled: true, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(top: Radius.circular(24)), - ), - backgroundColor: Colors.transparent, - builder: (context) => AssignProjectBottomSheet( - employeeId: employeeId, - jobRoleId: jobRoleId ?? '', - ), - ); - - // Step 4: Refresh employee list after project assignment - await _refreshEmployees(); - } - }, - borderRadius: BorderRadius.circular(28), - 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)), - ], - ), - ), - ), + appBar: _buildAppBar(), + floatingActionButton: _buildFloatingActionButton(), body: SafeArea( child: GetBuilder( - init: employeeScreenController, + init: _employeeController, tag: 'employee_screen_controller', builder: (controller) { _filterEmployees(_searchController.text); @@ -236,180 +142,11 @@ class _EmployeesScreenState extends State with UIMixin { crossAxisAlignment: CrossAxisAlignment.start, children: [ MySpacing.height(flexSpacing), - - // Search Bar + Actions Row - Padding( - padding: MySpacing.x(flexSpacing), - child: Row( - children: [ - // Search Field - Expanded( - child: SizedBox( - height: 36, - child: TextField( - controller: _searchController, - style: const TextStyle(fontSize: 13, height: 1.2), - decoration: InputDecoration( - isDense: true, - contentPadding: const EdgeInsets.symmetric( - horizontal: 8, vertical: 8), - prefixIcon: const Icon(Icons.search, - size: 18, color: Colors.grey), - prefixIconConstraints: const BoxConstraints( - minWidth: 32, - minHeight: 32, - ), - hintText: 'Search contacts...', - hintStyle: const TextStyle( - fontSize: 13, color: Colors.grey), - filled: true, - fillColor: Colors.white, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: Colors.grey.shade300, width: 1), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: Colors.grey.shade300, width: 1), - ), - suffixIcon: _searchController.text.isNotEmpty - ? GestureDetector( - onTap: () { - _searchController.clear(); - _filterEmployees(''); - setState(() {}); - }, - child: const Icon(Icons.close, - size: 18, color: Colors.grey), - ) - : null, - ), - onChanged: (value) => setState(() {}), - ), - ), - ), - - const SizedBox(width: 8), - - // Refresh Button - Tooltip( - message: 'Refresh Data', - child: InkWell( - borderRadius: BorderRadius.circular(24), - onTap: _refreshEmployees, - child: const Padding( - padding: EdgeInsets.all(10), - child: Icon(Icons.refresh, - color: Colors.green, size: 28), - ), - ), - ), - const SizedBox(width: 4), - - // Three-dot Menu - PopupMenuButton( - icon: Stack( - clipBehavior: Clip.none, - children: [ - const Icon(Icons.tune, color: Colors.black), - Obx(() { - return employeeScreenController - .isAllEmployeeSelected.value - ? Positioned( - right: -1, - top: -1, - child: Container( - width: 10, - height: 10, - decoration: const BoxDecoration( - color: Colors.red, - shape: BoxShape.circle, - ), - ), - ) - : const SizedBox.shrink(); - }), - ], - ), - onSelected: (value) async { - if (value == 'all_employees') { - employeeScreenController - .isAllEmployeeSelected.value = - !employeeScreenController - .isAllEmployeeSelected.value; - - if (employeeScreenController - .isAllEmployeeSelected.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 { - employeeScreenController.clearEmployees(); - } - } - _filterEmployees(_searchController.text); - employeeScreenController - .update(['employee_screen_controller']); - } - }, - itemBuilder: (context) => [ - PopupMenuItem( - value: 'all_employees', - child: Obx( - () => Row( - children: [ - Checkbox( - value: employeeScreenController - .isAllEmployeeSelected.value, - onChanged: (bool? value) { - Navigator.pop(context, 'all_employees'); - }, - checkColor: Colors.white, - activeColor: Colors.red, - side: const BorderSide( - color: Colors.black, - width: 1.5, - ), - fillColor: - MaterialStateProperty.resolveWith( - (states) { - if (states - .contains(MaterialState.selected)) { - return Colors.red; - } - return Colors.white; - }), - ), - const Text('All Employees'), - ], - ), - ), - ), - ], - ) - ], - ), - ), + _buildSearchAndActionRow(), MySpacing.height(flexSpacing), - - // Employee List Padding( padding: MySpacing.x(flexSpacing), - child: dailyProgressReportTab(), + child: _buildEmployeeList(), ), ], ), @@ -420,33 +157,272 @@ class _EmployeesScreenState extends State with UIMixin { ); } - Widget dailyProgressReportTab() { + PreferredSizeWidget _buildAppBar() { + return PreferredSize( + preferredSize: const Size.fromHeight(72), + child: AppBar( + backgroundColor: const Color(0xFFF5F5F5), + elevation: 0.5, + automaticallyImplyLeading: false, + titleSpacing: 0, + title: Padding( + padding: MySpacing.xy(16, 0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + IconButton( + icon: const Icon(Icons.arrow_back_ios_new, + color: Colors.black, size: 20), + onPressed: () => Get.offNamed('/dashboard'), + ), + MySpacing.width(8), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + MyText.titleLarge( + 'Employees', + fontWeight: 700, + color: Colors.black, + ), + MySpacing.height(2), + GetBuilder( + builder: (projectController) { + final projectName = + projectController.selectedProject?.name ?? + 'Select Project'; + return Row( + children: [ + const Icon(Icons.work_outline, + size: 14, color: Colors.grey), + MySpacing.width(4), + Expanded( + child: MyText.bodySmall( + projectName, + fontWeight: 600, + overflow: TextOverflow.ellipsis, + color: Colors.grey[700], + ), + ), + ], + ); + }, + ), + ], + ), + ), + ], + ), + ), + ), + ); + } + + Widget _buildFloatingActionButton() { + return InkWell( + onTap: _onAddNewEmployee, + borderRadius: BorderRadius.circular(28), + 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)), + ], + ), + ), + ); + } + + Widget _buildSearchAndActionRow() { + return Padding( + padding: MySpacing.x(flexSpacing), + child: Row( + children: [ + Expanded(child: _buildSearchField()), + const SizedBox(width: 8), + _buildRefreshButton(), + const SizedBox(width: 4), + _buildPopupMenu(), + ], + ), + ); + } + + Widget _buildSearchField() { + return SizedBox( + height: 36, + child: TextField( + controller: _searchController, + style: const TextStyle(fontSize: 13, height: 1.2), + decoration: InputDecoration( + isDense: true, + contentPadding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + prefixIcon: const Icon(Icons.search, size: 18, color: Colors.grey), + prefixIconConstraints: + const BoxConstraints(minWidth: 32, minHeight: 32), + hintText: 'Search contacts...', + hintStyle: const TextStyle(fontSize: 13, color: Colors.grey), + filled: true, + fillColor: Colors.white, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: Colors.grey.shade300, width: 1), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: Colors.grey.shade300, width: 1), + ), + suffixIcon: _searchController.text.isNotEmpty + ? GestureDetector( + onTap: () { + _searchController.clear(); + _filterEmployees(''); + setState(() {}); + }, + child: const Icon(Icons.close, size: 18, color: Colors.grey), + ) + : null, + ), + onChanged: (_) => setState(() {}), + ), + ); + } + + Widget _buildRefreshButton() { + return Tooltip( + message: 'Refresh Data', + child: InkWell( + borderRadius: BorderRadius.circular(24), + onTap: _refreshEmployees, + child: const Padding( + padding: EdgeInsets.all(10), + child: Icon(Icons.refresh, color: Colors.green, size: 28), + ), + ), + ); + } + + Widget _buildPopupMenu() { + return PopupMenuButton( + icon: Stack( + clipBehavior: Clip.none, + children: [ + const Icon(Icons.tune, color: Colors.black), + Obx(() { + return _employeeController.isAllEmployeeSelected.value + ? Positioned( + right: -1, + top: -1, + child: Container( + width: 10, + height: 10, + decoration: const BoxDecoration( + color: Colors.red, shape: BoxShape.circle), + ), + ) + : const SizedBox.shrink(); + }), + ], + ), + onSelected: (value) async { + if (value == 'all_employees') { + _employeeController.isAllEmployeeSelected.value = + !_employeeController.isAllEmployeeSelected.value; + + if (_employeeController.isAllEmployeeSelected.value) { + _employeeController.selectedProjectId = null; + await _employeeController.fetchAllEmployees(); + } else { + final selectedProjectId = + Get.find().selectedProject?.id; + if (selectedProjectId != null) { + _employeeController.selectedProjectId = selectedProjectId; + await _employeeController + .fetchEmployeesByProject(selectedProjectId); + } else { + _employeeController.clearEmployees(); + } + } + _filterEmployees(_searchController.text); + _employeeController.update(['employee_screen_controller']); + } + }, + itemBuilder: (context) => [ + PopupMenuItem( + value: 'all_employees', + child: Obx( + () => Row( + children: [ + Checkbox( + value: _employeeController.isAllEmployeeSelected.value, + onChanged: (bool? value) => + Navigator.pop(context, 'all_employees'), + checkColor: Colors.white, + activeColor: Colors.red, + side: const BorderSide(color: Colors.black, width: 1.5), + fillColor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.selected)) { + return Colors.red; + } + return Colors.white; + }), + ), + const Text('All Employees'), + ], + ), + ), + ), + ], + ); + } + + Widget _buildEmployeeList() { return Obx(() { - final isLoading = employeeScreenController.isLoading.value; + final isLoading = _employeeController.isLoading.value; final employees = _filteredEmployees; + // Show skeleton loader while data is being fetched if (isLoading) { return ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemCount: 10, + itemCount: 8, // number of skeleton items separatorBuilder: (_, __) => MySpacing.height(12), itemBuilder: (_, __) => SkeletonLoaders.employeeSkeletonCard(), ); } + // Show empty state when no employees are found if (employees.isEmpty) { return Padding( - padding: const EdgeInsets.only(top: 50), + padding: const EdgeInsets.only(top: 60), child: Center( child: MyText.bodySmall( "No Employees Found", fontWeight: 600, + color: Colors.grey[700], ), ), ); } + // Show the actual employee list return ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), @@ -455,16 +431,15 @@ class _EmployeesScreenState extends State with UIMixin { separatorBuilder: (_, __) => MySpacing.height(12), itemBuilder: (context, index) { final employee = employees[index]; - final nameParts = employee.name.trim().split(" "); + final nameParts = employee.name.trim().split(' '); final firstName = nameParts.first; - final lastName = nameParts.length > 1 ? nameParts.last : ""; + final lastName = nameParts.length > 1 ? nameParts.last : ''; return InkWell( - onTap: () { - Get.to(() => EmployeeDetailPage(employeeId: employee.id)); - }, + onTap: () => + Get.to(() => EmployeeDetailPage(employeeId: employee.id)), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 0), + padding: const EdgeInsets.symmetric(vertical: 0), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -474,16 +449,19 @@ class _EmployeesScreenState extends State with UIMixin { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - MyText.titleSmall(employee.name, - fontWeight: 600, overflow: TextOverflow.ellipsis), - if (employee.jobRole.isNotEmpty) ...[ - MyText.bodySmall(employee.jobRole, - color: Colors.grey[700], - overflow: TextOverflow.ellipsis), - ], + MyText.titleSmall( + employee.name, + fontWeight: 600, + overflow: TextOverflow.ellipsis, + ), + if (employee.jobRole.isNotEmpty) + MyText.bodySmall( + employee.jobRole, + color: Colors.grey[700], + overflow: TextOverflow.ellipsis, + ), MySpacing.height(8), - if (employee.email.isNotEmpty && - employee.email != '-') ...[ + if (employee.email.isNotEmpty && employee.email != '-') GestureDetector( onTap: () => LauncherUtils.launchEmail(employee.email), @@ -508,9 +486,9 @@ class _EmployeesScreenState extends State with UIMixin { ], ), ), + if (employee.email.isNotEmpty && employee.email != '-') MySpacing.height(6), - ], - if (employee.phoneNumber.isNotEmpty) ...[ + if (employee.phoneNumber.isNotEmpty) GestureDetector( onTap: () => LauncherUtils.launchPhone(employee.phoneNumber), @@ -530,16 +508,11 @@ class _EmployeesScreenState extends State with UIMixin { ], ), ), - ], ], ), ), - Column( - children: const [ - Icon(Icons.arrow_forward_ios, - color: Colors.grey, size: 16), - ], - ), + const Icon(Icons.arrow_forward_ios, + color: Colors.grey, size: 16), ], ), ),