onufitness_mobile/lib/screens/echoboard/views/tribe_member_details_page.dart
2026-01-13 11:36:24 +05:30

409 lines
16 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:onufitness/constants/asset_constants.dart';
import 'package:onufitness/constants/color_constant.dart';
import 'package:onufitness/constants/text_constant.dart';
import 'package:onufitness/routes/route_constant.dart';
import 'package:onufitness/screens/chat/views/chat_inside_screen.dart';
import 'package:onufitness/screens/echoboard/controllers/connection_and_tribe_controller.dart';
import 'package:onufitness/screens/echoboard/controllers/profile_controller.dart';
import 'package:onufitness/screens/echoboard/controllers/tribe_member_controller.dart';
import 'package:onufitness/screens/echoboard/views/tribe_echoboard/tribe_member_add_screen.dart';
import 'package:onufitness/screens/echoboard/widget/friend_request_send_user_card.dart';
import 'package:onufitness/screens/echoboard/widget/pagination_widget.dart';
import 'package:onufitness/services/local_storage_services/shared_services.dart';
import 'package:onufitness/widgets/others/button_action_bottom_sheet.dart';
class TribeMemberDetailsScreen extends StatefulWidget {
final String tribeName;
final int tribeId;
final String tribeImage;
const TribeMemberDetailsScreen({
super.key,
required this.tribeName,
required this.tribeImage,
required this.tribeId,
});
@override
State<TribeMemberDetailsScreen> createState() =>
_TribeMemberDetailsScreenState();
}
class _TribeMemberDetailsScreenState extends State<TribeMemberDetailsScreen> {
late final ProfileController profileController;
late final SocialConnectionController controller;
late final TribeMemberController tribeMemberController;
@override
void initState() {
super.initState();
//Initialize Tribe Member Controller..................................................
if (!Get.isRegistered<TribeMemberController>()) {
Get.put(TribeMemberController());
}
tribeMemberController = Get.find<TribeMemberController>();
// Initialize profile controller..................................................
if (!Get.isRegistered<ProfileController>()) {
Get.put(ProfileController());
}
profileController = Get.find<ProfileController>();
// Initialize social connection controller..................................................
if (!Get.isRegistered<SocialConnectionController>()) {
controller = Get.put(SocialConnectionController());
} else {
controller = Get.find<SocialConnectionController>();
}
// ✅ Set tab and fetch data after build..................................................
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
controller.currentTab.value = "TribeMembers";
controller.clearCurrentTabData(); // Clear any old data
controller.searchUsers(tribeId: widget.tribeId);
controller.getSingleTribeDetails(tribeId: widget.tribeId);
}
});
}
@override
void dispose() {
super.dispose();
}
// Handle search with proper data clearing
void _handleSearch() {
controller.clearCurrentTabData();
controller.searchUsers(tribeId: widget.tribeId);
}
// Handle clear search
void _handleClearSearch() {
controller.clearSearch();
// Manually trigger search for tribe members
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
controller.currentTab.value = "TribeMembers";
controller.searchUsers(tribeId: widget.tribeId);
}
});
}
void navigateToAddMembers() async {
final result = await Get.to(
() => AddTribeMembersScreen(
tribeName: widget.tribeName,
tribeId: widget.tribeId,
tribeImage: widget.tribeImage,
adminUserId:
controller.usersData.value!.data!.items![0].tribAdminUserId!,
),
);
// Refresh the member list if members were added
if (result == true && mounted) {
controller.clearCurrentTabData();
controller.searchUsers(tribeId: widget.tribeId);
}
}
@override
Widget build(BuildContext context) {
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) {
if (didPop) return;
controller.searchValue.value = "";
controller.searchController.clear();
controller.currentTab.value = "Friends";
controller.searchUsers(clearOldData: true);
Get.back(result: result);
},
child: Scaffold(
backgroundColor: pageBackGroundColor,
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.white,
automaticallyImplyLeading: true,
titleSpacing: 0,
leading: IconButton(
onPressed: () {
controller.searchValue.value = "";
controller.searchController.clear();
controller.currentTab.value = "Friends";
controller.searchUsers(clearOldData: true);
Get.back();
},
icon: const Icon(Icons.arrow_back_ios),
),
title: Row(
children: [
// Tribe profile image
CircleAvatar(
radius: 18,
backgroundImage:
widget.tribeImage.isNotEmpty
? NetworkImage(widget.tribeImage)
: null,
child:
widget.tribeImage.isEmpty
? const Icon(Icons.group, size: 18)
: null,
),
const SizedBox(width: 10),
// Tribe name + member count
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
widget.tribeName,
style: const TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16,
color: Colors.black,
),
overflow: TextOverflow.ellipsis,
),
Row(
children: [
Icon(
Icons.group_outlined,
size: 16.sp,
color: Colors.grey,
),
const SizedBox(width: 4),
Obx(
() =>
controller.isSingleTribeLoading.value
? Text(
"Loading...",
style: TextStyle(
fontSize: verySmallSizeText,
color: Colors.grey,
),
)
: Text(
'${controller.singleTribeDetails.value?.data?.totalMembers ?? 0} Members',
style: TextStyle(
fontSize: verySmallSizeText,
color: Colors.grey,
),
),
),
],
),
],
),
),
],
),
actions: [
Obx(() {
final items = controller.usersData.value?.data?.items;
final currentUserId =
SharedServices.getUserDetails()?.data?.userId;
final isAdmin =
items != null &&
items.isNotEmpty &&
items.first.tribAdminUserId == currentUserId;
return isAdmin
? Padding(
padding: EdgeInsets.only(right: 10.w),
child: IconButton(
onPressed: navigateToAddMembers,
icon: const Icon(Icons.add),
tooltip: 'Add Members',
),
)
: const SizedBox.shrink();
}),
],
),
body: Column(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 15.sp, vertical: 15.h),
child: TextField(
controller: controller.searchController,
decoration: InputDecoration(
hintText: 'Search for members',
hintStyle: TextStyle(
fontWeight: FontWeight.w600,
color: greyBorderColor,
),
prefixIcon: const Padding(
padding: EdgeInsets.only(left: 20),
child: Icon(Icons.search),
),
suffixIcon: IconButton(
icon: const Padding(
padding: EdgeInsets.only(right: 10),
child: Icon(Icons.close),
),
onPressed: _handleClearSearch,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: BorderSide(color: lightGreyColor, width: 1),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: const BorderSide(
color: lightGreyColor,
width: 1.2,
),
),
filled: true,
fillColor: Colors.white,
),
onChanged: (value) => controller.onSearchChanged(value),
onSubmitted: (_) => _handleSearch(),
),
),
Expanded(
child: Obx(() {
// Show loading indicator
if (controller.isLoading.value) {
return const Center(
child: CircularProgressIndicator(color: Colors.black),
);
}
// Safely access users with null checks
final usersData = controller.usersData.value;
final data = usersData?.data;
final users = data?.items;
// Show empty state
if (users == null || users.isEmpty) {
return Center(
child: Text(
controller.searchValue.value.isNotEmpty
? 'No members found matching "${controller.searchValue.value}"'
: 'No members found',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: regularSizeText,
color: Colors.grey[600],
),
),
);
}
// Check if current user is admin
final currentUserId =
SharedServices.getUserDetails()?.data?.userId;
final adminUserId =
users.isNotEmpty ? users.first.tribAdminUserId : null;
final isAdmin =
currentUserId != null && currentUserId == adminUserId;
return ListView.builder(
itemCount: users.length,
padding: const EdgeInsets.all(10),
itemBuilder: (context, index) {
final user = users[index];
final isCurrentUserAdmin = isAdmin;
final canDeleteMember =
isCurrentUserAdmin && user.userId != adminUserId;
return InkWell(
onTap: () {
if (user.userId != null) {
profileController.selectedUserId.value =
user.userId.toString();
Get.toNamed(RouteConstant.userSocialProfileScreen);
}
},
// long press for admin delete functionality
onLongPress:
canDeleteMember
? () {
if (user.userId != null) {
actionButtonBottomSheet(
context: context,
title: "Delete Member",
subtitle:
"Are you sure you want to delete this user ?",
submitButtonText: "Delete Member",
onPressed: () async {
final success =
await tribeMemberController
.deleteTribeMember(
tribeId: widget.tribeId,
memberId: user.userId!,
);
if (success && mounted) {
// Refresh the member list after deletion
Get.back();
controller.clearCurrentTabData();
controller.currentTab.value =
"TribeMembers";
controller.searchUsers(
tribeId: widget.tribeId,
);
controller.getSingleTribeDetails(
tribeId: widget.tribeId,
);
}
},
cancelButtonText: "Cancel",
onCancelPressed: () {
Get.back();
},
assetPath: AssetConstants.delete,
primaryColor: Color(primaryColor),
cancelBorderColor: lightGreyColor,
isLoading:
tribeMemberController
.deleteTribeMemberLoading,
);
}
}
: null,
child: ConnectUserCard(
user: user,
onConnect: () async {},
onMessageUser: () {
final agoraUserId = user.userId!.replaceAll("-", "");
Get.to(
() => ChatDetailScreen(
targetUserId: agoraUserId,
targetUserName: user.fullName ?? "Unknown user",
targetUserAvatar: user.userProfileImage,
isGroupMessage: false,
),
);
},
connectionStatus: user.connectionStatus ?? 'Accepted',
loadingContains:
controller.sendConnectionRequestLoading,
isYourFriend: true,
isTribeMemberPage: true,
),
);
},
);
}),
),
// Pagination widget
showsUserListPagination(controller),
],
),
),
);
}
}