import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:marco/controller/dashboard/employees_screen_controller.dart'; import 'package:marco/controller/project_controller.dart'; import 'package:marco/helpers/widgets/avatar.dart'; import 'package:marco/helpers/widgets/my_spacing.dart'; import 'package:marco/helpers/widgets/my_text.dart'; import 'package:marco/view/employees/assign_employee_bottom_sheet.dart'; import 'package:marco/helpers/utils/launcher_utils.dart'; class EmployeeDetailPage extends StatefulWidget { final String employeeId; const EmployeeDetailPage({super.key, required this.employeeId}); @override State createState() => _EmployeeDetailPageState(); } class _EmployeeDetailPageState extends State { final EmployeesScreenController controller = Get.put(EmployeesScreenController()); @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { controller.fetchEmployeeDetails(widget.employeeId); }); } @override void dispose() { controller.selectedEmployeeDetails.value = null; super.dispose(); } String _getDisplayValue(dynamic value) { 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'; try { return DateFormat('d/M/yyyy').format(date); } catch (_) { return 'NA'; } } /// Row builder with email/phone tap & copy support Widget _buildLabelValueRow(String label, String value, {bool isMultiLine = false}) { final lowerLabel = label.toLowerCase(); final isEmail = lowerLabel == 'email'; final isPhone = lowerLabel == 'phone number' || lowerLabel == 'emergency phone number'; void handleTap() { if (value == 'NA') return; if (isEmail) { LauncherUtils.launchEmail(value); } else if (isPhone) { LauncherUtils.launchPhone(value); } } void handleLongPress() { if (value == 'NA') return; LauncherUtils.copyToClipboard(value, typeLabel: label); } final valueWidget = GestureDetector( onTap: (isEmail || isPhone) ? handleTap : null, onLongPress: (isEmail || isPhone) ? handleLongPress : null, child: Text( value, style: TextStyle( fontWeight: FontWeight.normal, color: (isEmail || isPhone) ? Colors.indigo : Colors.black54, fontSize: 14, decoration: (isEmail || isPhone) ? TextDecoration.underline : TextDecoration.none, ), ), ); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (isMultiLine) ...[ Text( label, style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.black87, fontSize: 14, ), ), MySpacing.height(4), valueWidget, ] else GestureDetector( onTap: (isEmail || isPhone) ? handleTap : null, onLongPress: (isEmail || isPhone) ? handleLongPress : null, child: RichText( text: TextSpan( text: "$label: ", style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.black87, fontSize: 14, ), children: [ TextSpan( text: value, style: TextStyle( fontWeight: FontWeight.normal, color: (isEmail || isPhone) ? Colors.indigo : Colors.black54, decoration: (isEmail || isPhone) ? TextDecoration.underline : TextDecoration.none, ), ), ], ), ), ), MySpacing.height(10), Divider(color: Colors.grey[300], height: 1), MySpacing.height(10), ], ); } /// Info card Widget _buildInfoCard(employee) { return Card( elevation: 3, shadowColor: Colors.black12, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.fromLTRB(12, 16, 12, 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MySpacing.height(12), _buildLabelValueRow('Email', _getDisplayValue(employee.email)), _buildLabelValueRow( 'Phone Number', _getDisplayValue(employee.phoneNumber)), _buildLabelValueRow('Emergency Contact Person', _getDisplayValue(employee.emergencyContactPerson)), _buildLabelValueRow('Emergency Phone Number', _getDisplayValue(employee.emergencyPhoneNumber)), _buildLabelValueRow('Gender', _getDisplayValue(employee.gender)), _buildLabelValueRow('Birth Date', _formatDate(employee.birthDate)), _buildLabelValueRow( 'Joining Date', _formatDate(employee.joiningDate)), _buildLabelValueRow( 'Current Address', _getDisplayValue(employee.currentAddress), isMultiLine: true, ), _buildLabelValueRow( 'Permanent Address', _getDisplayValue(employee.permanentAddress), isMultiLine: true, ), ], ), ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF1F1F1), 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/employees'), ), MySpacing.width(8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ MyText.titleLarge( 'Employee Details', 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], ), ), ], ); }, ), ], ), ), ], ), ), ), ), body: Obx(() { if (controller.isLoadingEmployeeDetails.value) { return const Center(child: CircularProgressIndicator()); } final employee = controller.selectedEmployeeDetails.value; if (employee == null) { return const Center(child: Text('No employee details found.')); } return SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.fromLTRB(12, 20, 12, 80), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Row( children: [ Avatar( firstName: employee.firstName, lastName: employee.lastName, size: 45, ), MySpacing.width(16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.titleMedium( '${employee.firstName} ${employee.lastName}', fontWeight: 700, ), MySpacing.height(6), MyText.bodySmall( _getDisplayValue(employee.jobRole), fontWeight: 500, ), ], ), ), ], ), MySpacing.height(14), _buildInfoCard(employee), ], ), ), ); }), floatingActionButton: Obx(() { if (controller.isLoadingEmployeeDetails.value || controller.selectedEmployeeDetails.value == null) { return const SizedBox.shrink(); } final employee = controller.selectedEmployeeDetails.value!; return FloatingActionButton.extended( onPressed: () { showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (context) => AssignProjectBottomSheet( employeeId: widget.employeeId, jobRoleId: employee.jobRoleId, ), ); }, backgroundColor: Colors.red, icon: const Icon(Icons.assignment), label: const Text( 'Assign to Project', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w500), ), ); }), ); } }