import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:marco/helpers/widgets/my_spacing.dart'; import 'package:marco/helpers/widgets/my_text.dart'; import 'package:marco/helpers/widgets/avatar.dart'; import 'package:intl/intl.dart'; import 'package:marco/controller/employee/employees_screen_controller.dart'; import 'package:marco/view/employees/assign_employee_bottom_sheet.dart'; class EmployeeDetailBottomSheet extends StatefulWidget { final String employeeId; const EmployeeDetailBottomSheet({super.key, required this.employeeId}); @override State createState() => _EmployeeDetailBottomSheetState(); } class _EmployeeDetailBottomSheetState 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'; } } Widget _buildLabelValueRow(IconData icon, String label, String value) { return Padding( padding: const EdgeInsets.only(bottom: 12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon(icon, size: 20, color: Colors.grey[700]), MySpacing.width(8), MyText.bodyMedium('$label:', fontWeight: 600), MySpacing.width(8), Expanded(child: MyText.bodyMedium(value, fontWeight: 400)), ], ), ); } @override Widget build(BuildContext context) { return DraggableScrollableSheet( expand: false, maxChildSize: 0.85, minChildSize: 0.4, initialChildSize: 0.6, builder: (_, controllerScroll) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), boxShadow: const [ BoxShadow( color: Colors.black26, blurRadius: 10, offset: Offset(0, -3), ), ], ), child: 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 SingleChildScrollView( controller: controllerScroll, padding: MySpacing.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ // Drag Handle Container( width: 50, height: 5, decoration: BoxDecoration( color: Colors.grey[400], borderRadius: BorderRadius.circular(3), ), ), MySpacing.height(20), // Row 1: Avatar + Name Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ CircleAvatar( radius: 40, backgroundColor: Colors.blueGrey[200], child: Avatar( firstName: employee.firstName, lastName: employee.lastName, size: 60, ), ), MySpacing.width(16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.titleLarge( '${employee.firstName} ${employee.lastName}', fontWeight: 700, ), MySpacing.height(6), MyText.bodyMedium( _getDisplayValue(employee.jobRole), fontWeight: 500, color: Colors.grey[700], ), ], ), ), ], ), MySpacing.height(12), // Row 2: Minimal Button Align( alignment: Alignment.centerRight, child: TextButton( style: TextButton.styleFrom( padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 6), backgroundColor: Colors.blueAccent, minimumSize: const Size(0, 32), tapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(6), ), ), onPressed: () { showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (context) => AssignProjectBottomSheet( employeeId: widget.employeeId, jobRoleId: employee.jobRoleId, ), ); }, child: const Text( 'Assign to Project', style: TextStyle( color: Colors.white, fontSize: 13, fontWeight: FontWeight.w500, ), ), ), ), MySpacing.height(20), // Contact Info Card _buildInfoCard('Contact Information', [ _buildLabelValueRow( Icons.email, 'Email', _getDisplayValue(employee.email)), _buildLabelValueRow(Icons.phone, 'Phone Number', _getDisplayValue(employee.phoneNumber)), ]), MySpacing.height(10), // Emergency Contact Info Card _buildInfoCard('Emergency Contact', [ _buildLabelValueRow(Icons.person, 'Contact Person', _getDisplayValue(employee.emergencyContactPerson)), _buildLabelValueRow(Icons.phone_android, 'Contact Number', _getDisplayValue(employee.emergencyPhoneNumber)), ]), MySpacing.height(10), // Personal Info Card _buildInfoCard('Personal Information', [ _buildLabelValueRow(Icons.transgender, 'Gender', _getDisplayValue(employee.gender)), _buildLabelValueRow(Icons.cake, 'Birth Date', _formatDate(employee.birthDate)), _buildLabelValueRow(Icons.work, 'Joining Date', _formatDate(employee.joiningDate)), ]), MySpacing.height(10), // Address Card _buildInfoCard('Address', [ _buildLabelValueRow(Icons.home, 'Current Address', _getDisplayValue(employee.currentAddress)), _buildLabelValueRow(Icons.home_filled, 'Permanent Address', _getDisplayValue(employee.permanentAddress)), ]), ], ), ); }), ); }, ); } Widget _buildInfoCard(String title, List children) { return Card( elevation: 1, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.titleMedium(title, fontWeight: 700), MySpacing.height(12), ...children, ], ), ), ); } }