diff --git a/lib/helpers/services/api_endpoints.dart b/lib/helpers/services/api_endpoints.dart index 44a7474..6f6cfe6 100644 --- a/lib/helpers/services/api_endpoints.dart +++ b/lib/helpers/services/api_endpoints.dart @@ -1,7 +1,8 @@ class ApiEndpoints { - static const String baseUrl = "https://stageapi.marcoaiot.com/api"; + // static const String baseUrl = "https://stageapi.marcoaiot.com/api"; + // static const String baseUrl = "https://stageapi.marcoaiot.com/api"; // static const String baseUrl = "https://api.marcoaiot.com/api"; - //static const String baseUrl = "https://devapi.marcoaiot.com/api"; + static const String baseUrl = "https://devapi.marcoaiot.com/api"; static const String getMasterCurrencies = "/Master/currencies/list"; static const String getMasterExpensesCategories = @@ -134,6 +135,7 @@ class ApiEndpoints { static const String manageOrganizationHierarchy = "/organization/hierarchy/manage"; + // Service Project Module API Endpoints static const String getServiceProjectsList = "/serviceproject/list"; static const String getServiceProjectDetail = "/serviceproject/details"; diff --git a/lib/helpers/services/api_service.dart b/lib/helpers/services/api_service.dart index db01dd4..3f57fcb 100644 --- a/lib/helpers/services/api_service.dart +++ b/lib/helpers/services/api_service.dart @@ -305,7 +305,6 @@ class ApiService { } } - /// Create a new Service Project Job static Future createServiceProjectJobApi({ required String title, @@ -425,7 +424,6 @@ class ApiService { return null; } - /// Get details of a single service project /// Get details of a single service project static Future getServiceProjectDetailApi( String projectId) async { diff --git a/lib/view/employees/employee_detail_screen.dart b/lib/view/employees/employee_detail_screen.dart index baa59fa..4e32211 100644 --- a/lib/view/employees/employee_detail_screen.dart +++ b/lib/view/employees/employee_detail_screen.dart @@ -49,18 +49,18 @@ class _EmployeeDetailPageState extends State with UIMixin { } String _getDisplayValue(dynamic value) { - if (value == null || value.toString().trim().isEmpty || value == 'null') { - return 'NA'; + if (value == null || value.toString().trim().isEmpty || value == "null") { + return "NA"; } return value.toString(); } String _formatDate(DateTime? date) { - if (date == null || date == DateTime(1)) return 'NA'; + if (date == null || date == DateTime(1)) return "NA"; try { return DateFormat('d/M/yyyy').format(date); } catch (_) { - return 'NA'; + return "NA"; } } @@ -75,18 +75,15 @@ class _EmployeeDetailPageState extends State with UIMixin { return Padding( padding: const EdgeInsets.symmetric(vertical: 12), child: InkWell( - onTap: isActionable && value != 'NA' ? onTap : null, - onLongPress: isActionable && value != 'NA' ? onLongPress : null, + onTap: isActionable && value != "NA" ? onTap : null, + onLongPress: isActionable && value != "NA" ? onLongPress : null, borderRadius: BorderRadius.circular(5), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.all(8), - child: Icon( - icon, - size: 20, - ), + child: Icon(icon, size: 20), ), MySpacing.width(16), Expanded( @@ -101,23 +98,19 @@ class _EmployeeDetailPageState extends State with UIMixin { MySpacing.height(4), MyText( value, - color: isActionable && value != 'NA' + color: isActionable && value != "NA" ? Colors.blueAccent : Colors.black87, fontWeight: 500, - decoration: isActionable && value != 'NA' + decoration: isActionable && value != "NA" ? TextDecoration.underline : TextDecoration.none, ), ], ), ), - if (isActionable && value != 'NA') - Icon( - Icons.chevron_right, - color: Colors.grey[400], - size: 20, - ), + if (isActionable && value != "NA") + Icon(Icons.chevron_right, color: Colors.grey[400], size: 20), ], ), ), @@ -140,10 +133,7 @@ class _EmployeeDetailPageState extends State with UIMixin { children: [ Row( children: [ - Icon( - titleIcon, - size: 20, - ), + Icon(titleIcon, size: 20), MySpacing.width(8), MyText( title, @@ -170,7 +160,7 @@ class _EmployeeDetailPageState extends State with UIMixin { backgroundColor: const Color(0xFFF1F1F1), appBar: showAppBar ? CustomAppBar( - title: 'Employee Details', + title: "Employee Details", onBackPressed: () { if (widget.fromProfile) { Get.back(); @@ -187,7 +177,7 @@ class _EmployeeDetailPageState extends State with UIMixin { final employee = controller.selectedEmployeeDetails.value; if (employee == null) { - return Center(child: MyText('No employee details found.')); + return const Center(child: MyText("No employee details found.")); } return SafeArea( @@ -202,7 +192,7 @@ class _EmployeeDetailPageState extends State with UIMixin { child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - // Header Section + /// ------------------ HEADER CARD ------------------ Card( elevation: 2, shadowColor: Colors.black12, @@ -255,8 +245,8 @@ class _EmployeeDetailPageState extends State with UIMixin { employee.hasApplicationAccess, 'gender': employee.gender.toLowerCase(), 'job_role_id': employee.jobRoleId, - 'joining_date': - employee.joiningDate?.toIso8601String(), + 'joining_date': employee.joiningDate + ?.toIso8601String(), }, ), ); @@ -271,8 +261,10 @@ class _EmployeeDetailPageState extends State with UIMixin { ), ), ), + MySpacing.height(16), + /// ------------------ MANAGE REPORTING ------------------ _buildSectionCard( title: 'Manage Reporting', titleIcon: Icons.people_outline, @@ -306,7 +298,6 @@ class _EmployeeDetailPageState extends State with UIMixin { ), ); - // 🔄 Refresh reporting managers after editing await controller.fetchReportingManagers(employee.id); }, child: Padding( @@ -353,41 +344,32 @@ class _EmployeeDetailPageState extends State with UIMixin { } return Padding( - padding: const EdgeInsets.only( - top: 8.0, left: 8, right: 8, bottom: 8), + padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Padding( - padding: - const EdgeInsets.symmetric(vertical: 4.0), - child: Text( - 'Primary → ${_getManagerNames(primary)}', - style: const TextStyle( + Text( + 'Primary → ${_getManagerNames(primary)}', + style: const TextStyle( fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), + fontWeight: FontWeight.w600), ), - Padding( - padding: - const EdgeInsets.symmetric(vertical: 4.0), - child: Text( - 'Secondary → ${_getManagerNames(secondary)}', - style: const TextStyle( + Text( + 'Secondary → ${_getManagerNames(secondary)}', + style: const TextStyle( fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), + fontWeight: FontWeight.w600), ), ], ), ); - }) + }), ], ), - // Contact Information Section + MySpacing.height(16), + + /// ------------------ CONTACT INFO ------------------ _buildSectionCard( title: 'Contact Information', titleIcon: Icons.contact_phone, @@ -406,7 +388,8 @@ class _EmployeeDetailPageState extends State with UIMixin { onLongPress: () { if (employee.email != null && employee.email.toString().trim().isNotEmpty) { - LauncherUtils.copyToClipboard(employee.email!, + LauncherUtils.copyToClipboard( + employee.email!, typeLabel: 'Email'); } }, @@ -432,9 +415,10 @@ class _EmployeeDetailPageState extends State with UIMixin { ), ], ), + MySpacing.height(16), - // Emergency Contact Section + /// ------------------ EMERGENCY CONTACT ------------------ _buildSectionCard( title: 'Emergency Contact', titleIcon: Icons.emergency, @@ -444,17 +428,16 @@ class _EmployeeDetailPageState extends State with UIMixin { label: 'Contact Person', value: _getDisplayValue(employee.emergencyContactPerson), - isActionable: false, ), _buildDetailRow( icon: Icons.phone_in_talk_outlined, label: 'Emergency Phone', - value: _getDisplayValue(employee.emergencyPhoneNumber), + value: + _getDisplayValue(employee.emergencyPhoneNumber), isActionable: true, onTap: () { if (employee.emergencyPhoneNumber != null && - employee.emergencyPhoneNumber - .toString() + employee.emergencyPhoneNumber! .trim() .isNotEmpty) { LauncherUtils.launchPhone( @@ -463,8 +446,7 @@ class _EmployeeDetailPageState extends State with UIMixin { }, onLongPress: () { if (employee.emergencyPhoneNumber != null && - employee.emergencyPhoneNumber - .toString() + employee.emergencyPhoneNumber! .trim() .isNotEmpty) { LauncherUtils.copyToClipboard( @@ -475,9 +457,10 @@ class _EmployeeDetailPageState extends State with UIMixin { ), ], ), + MySpacing.height(16), - // Personal Information Section + /// ------------------ PERSONAL INFO ------------------ _buildSectionCard( title: 'Personal Information', titleIcon: Icons.person, @@ -486,25 +469,23 @@ class _EmployeeDetailPageState extends State with UIMixin { icon: Icons.wc_outlined, label: 'Gender', value: _getDisplayValue(employee.gender), - isActionable: false, ), _buildDetailRow( icon: Icons.cake_outlined, label: 'Birth Date', value: _formatDate(employee.birthDate), - isActionable: false, ), _buildDetailRow( icon: Icons.work_outline, label: 'Joining Date', value: _formatDate(employee.joiningDate), - isActionable: false, ), ], ), + MySpacing.height(16), - // Address Information Section + /// ------------------ ADDRESS INFO ------------------ _buildSectionCard( title: 'Address Information', titleIcon: Icons.location_on, @@ -513,13 +494,11 @@ class _EmployeeDetailPageState extends State with UIMixin { icon: Icons.home_outlined, label: 'Current Address', value: _getDisplayValue(employee.currentAddress), - isActionable: false, ), _buildDetailRow( icon: Icons.home_work_outlined, label: 'Permanent Address', value: _getDisplayValue(employee.permanentAddress), - isActionable: false, ), ], ), @@ -530,7 +509,7 @@ class _EmployeeDetailPageState extends State with UIMixin { ); }), - // Floating “Assign to Project” FAB + /// ------------------ FLOATING BUTTON ------------------ floatingActionButton: Obx(() { final employee = controller.selectedEmployeeDetails.value; if (employee == null) return const SizedBox.shrink(); @@ -548,17 +527,18 @@ class _EmployeeDetailPageState extends State with UIMixin { ); }, backgroundColor: contentTheme.primary, - label: MyText( + icon: const Icon(Icons.add), + label: MyText( 'Assign to Project', fontSize: 14, fontWeight: 500, ), - icon: const Icon(Icons.add), ); }), ); } + /// ------------------ UTIL ------------------ String _getManagerNames(List managers) { if (managers.isEmpty) return '—'; return managers