409 lines
16 KiB
Dart
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),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|