diff --git a/lib/view/service_project/service_project_details_screen.dart b/lib/view/service_project/service_project_details_screen.dart index 0b9911b..01895bf 100644 --- a/lib/view/service_project/service_project_details_screen.dart +++ b/lib/view/service_project/service_project_details_screen.dart @@ -470,67 +470,95 @@ class _ServiceProjectDetailsScreenState }); } - Widget _buildTeamsTab() { - return Obx(() { - if (controller.isTeamLoading.value) { - return const Center(child: CircularProgressIndicator()); - } + Widget _buildTeamsTab() { + return Obx(() { + if (controller.isTeamLoading.value) { + return const Center(child: CircularProgressIndicator()); + } - if (controller.teamErrorMessage.value.isNotEmpty && - controller.teamList.isEmpty) { - return Center( - child: MyText.bodyMedium(controller.teamErrorMessage.value)); - } + if (controller.teamErrorMessage.value.isNotEmpty && + controller.teamList.isEmpty) { + return Center(child: MyText.bodyMedium(controller.teamErrorMessage.value)); + } - if (controller.teamList.isEmpty) { - return Center(child: MyText.bodyMedium("No team members found")); - } + if (controller.teamList.isEmpty) { + return Center(child: MyText.bodyMedium("No team members found")); + } - return ListView.separated( - padding: const EdgeInsets.all(12), - itemCount: controller.teamList.length, - separatorBuilder: (_, __) => const SizedBox(height: 12), - itemBuilder: (context, index) { - final team = controller.teamList[index]; - return Card( - shape: - RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Avatar( - firstName: team.employee.firstName, - lastName: team.employee.lastName, - size: 32, - imageUrl: (team.employee.photo?.isNotEmpty ?? false) - ? team.employee.photo - : null, - ), - MySpacing.width(12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + // Group team members by their role ID + final Map roleGroups = {}; + for (var team in controller.teamList) { + roleGroups.putIfAbsent(team.teamRole.id, () => []).add(team); + } + + return ListView.separated( + padding: const EdgeInsets.all(12), + itemCount: roleGroups.keys.length, + separatorBuilder: (_, __) => const SizedBox(height: 12), + itemBuilder: (context, index) { + final roleId = roleGroups.keys.elementAt(index); + final teamMembers = roleGroups[roleId]!; + final roleName = teamMembers.first.teamRole.name; + + return Card( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + elevation: 3, + shadowColor: Colors.black26, + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Role header + MyText.bodyLarge( + roleName, + fontWeight: 700, + color: Colors.black87, + ), + const Divider(height: 20, thickness: 1), + // List of team members inside this role card + ...teamMembers.map((team) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( children: [ - MyText.titleMedium( - "${team.employee.firstName} ${team.employee.lastName}", - fontWeight: 700), - MyText.bodySmall(team.teamRole.name, - color: Colors.grey[700]), - MyText.bodySmall( - "Status: ${team.isActive ? 'Active' : 'Inactive'}", - color: Colors.grey[700]), + Avatar( + firstName: team.employee.firstName, + lastName: team.employee.lastName, + size: 32, + imageUrl: (team.employee.photo?.isNotEmpty ?? false) + ? team.employee.photo + : null, + ), + MySpacing.width(12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MyText.titleMedium( + "${team.employee.firstName} ${team.employee.lastName}", + fontWeight: 600, + ), + MyText.bodySmall( + "Status: ${team.isActive ? 'Active' : 'Inactive'}", + color: Colors.grey[700], + ), + ], + ), + ), ], ), - ), - ], - ), + ); + }).toList(), + ], ), - ); - }, - ); - }); - } + ), + ); + }, + ); + }); +} + @override Widget build(BuildContext context) {