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/screens/echoboard/controllers/connection_and_tribe_controller.dart'; import 'package:onufitness/screens/echoboard/controllers/tribe_member_controller.dart'; import 'package:onufitness/screens/echoboard/models/get_all_tribr_list_with_members_response_model.dart'; import 'package:onufitness/screens/echoboard/views/tribe_echoboard/tribe_echoboard_post_list_screen.dart'; import 'package:onufitness/services/local_storage_services/shared_services.dart'; import 'package:onufitness/widgets/appbars/custom_appbar.dart'; import 'package:onufitness/widgets/others/button_action_bottom_sheet.dart'; class ViewTribeScreen extends StatefulWidget { const ViewTribeScreen({super.key}); @override State createState() => _ViewTribeScreenState(); } class _ViewTribeScreenState extends State { final SocialConnectionController controller = Get.find(); final ScrollController _scrollController = ScrollController(); late final TribeMemberController tribeMemberController; @override void initState() { super.initState(); _scrollController.addListener(_onScroll); WidgetsBinding.instance.addPostFrameCallback((_) { controller.getAllTribesWithMembers(refresh: true); }); if (!Get.isRegistered()) { tribeMemberController = Get.put(TribeMemberController()); } else { tribeMemberController = Get.find(); } } void _onScroll() { if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent - 300) { if (controller.hasMoreTribes.value && !controller.isTribePaginationLoading.value) { controller.getAllTribesWithMembers(); } } } Future _onRefresh() async { await controller.getAllTribesWithMembers(refresh: true); return Future.value(); } void onTribeTap({ required String? agoraGroupId, required String? groupName, required String? groupImage, required int? tribeId, required List? members, }) { if (members != null && members.isNotEmpty) { Get.to( () => TribeEchoboardPostListScreen( tribeName: groupName!, tribeImage: groupImage!, tribeId: tribeId!, ), ); } else { Get.snackbar( 'Info', 'No members found for this tribe', snackPosition: SnackPosition.BOTTOM, ); } } @override void dispose() { _scrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: pageBackGroundColor, appBar: CustomAppBar( title: 'View Tribes', textColor: appbarTextColor, titleFontSize: appBarHeardingText, backgroundColor: Colors.white, leading: IconButton( icon: Icon(Icons.arrow_back_ios, color: Colors.black), onPressed: () => Get.back(), ), ), body: Column( children: [ Padding( padding: EdgeInsets.symmetric(horizontal: 16.w), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox(height: 10.h), /// SEARCH BAR TextField( controller: controller.tribeSearchController, decoration: InputDecoration( hintText: 'Search for tribes', hintStyle: TextStyle( fontWeight: FontWeight.w600, color: lightGreyColor, ), prefixIcon: const Padding( padding: EdgeInsets.only(left: 20), child: Icon(Icons.search, color: Colors.black), ), suffixIcon: IconButton( icon: const Padding( padding: EdgeInsets.only(right: 10), child: Icon(Icons.close, color: Colors.black), ), onPressed: () => controller.clearTribeSearch(), ), filled: true, fillColor: Colors.white, border: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: BorderSide(color: lightGreyColor, width: 1), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: BorderSide(color: lightGreyColor, width: 1), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(30), borderSide: BorderSide(color: lightGreyColor, width: 1.2), ), ), onChanged: (newValue) { controller.tribeSearchValue.value = newValue; }, onSubmitted: (_) { controller.getAllTribesWithMembers(refresh: true); }, ), SizedBox(height: 12), ], ), ), Expanded( child: Obx(() { final tribes = controller.tribesData.value?.data?.items ?? []; if (controller.isTribesLoading.value) { return const Center( child: CircularProgressIndicator( color: Colors.black, strokeWidth: 3, ), ); } if (tribes.isEmpty) { return Center( child: RefreshIndicator( onRefresh: _onRefresh, color: Colors.black, child: ListView( physics: const AlwaysScrollableScrollPhysics(), children: [ SizedBox(height: 150.h), Center( child: Text( 'No tribes found', style: TextStyle( fontSize: 16.sp, color: Colors.grey[600], ), ), ), ], ), ), ); } return RefreshIndicator( backgroundColor: Colors.white, color: Colors.black, onRefresh: _onRefresh, child: ListView.builder( physics: const AlwaysScrollableScrollPhysics(), controller: _scrollController, padding: EdgeInsets.symmetric(horizontal: 16.w), itemCount: tribes.length + (controller.isTribePaginationLoading.value ? 1 : 0), itemBuilder: (_, i) { if (i == tribes.length) { return Padding( padding: EdgeInsets.symmetric(vertical: 16.h), child: const Center( child: CircularProgressIndicator( color: Colors.black, strokeWidth: 3, ), ), ); } final tribe = tribes[i]; return SingleTribeTile( name: tribe.tribeName ?? 'Unknown Tribe', members: tribe.totalMembers, imageUrl: tribe.tribeImage ?? '', onTap: () { onTribeTap( agoraGroupId: tribe.agoraGroupId, groupName: tribe.tribeName, groupImage: tribe.tribeImage, members: tribe.members, tribeId: tribe.tribeId, ); }, longTap: () { if (tribe.adminUserId?.toString() == SharedServices.getUserDetails()?.data?.userId) { actionButtonBottomSheet( context: context, title: "Delete Tribe", subtitle: "Are ypu sure you want to delete the '${tribe.tribeName}' ?", submitButtonText: "Delete Tribe", onPressed: () { tribeMemberController .deleteTribe(tribeID: tribe.tribeId!) .then((value) { if (value) { Get.back(); controller.getAllTribesWithMembers( refresh: true, ); } }); }, cancelButtonText: "Cancel", onCancelPressed: () { Get.back(); }, assetPath: AssetConstants.delete, primaryColor: Color(primaryColor), cancelBorderColor: lightGreyColor, isLoading: tribeMemberController.isDeleteTribeLoading, ); } }, ); }, ), ); }), ), ], ), ); } } class SingleTribeTile extends StatelessWidget { final String name; final int? members; final String imageUrl; final VoidCallback onTap; final VoidCallback longTap; const SingleTribeTile({ required this.name, this.members, required this.imageUrl, required this.onTap, required this.longTap, super.key, }); @override Widget build(BuildContext context) { return InkWell( onTap: onTap, onLongPress: longTap, borderRadius: BorderRadius.circular(14.r), child: Container( margin: EdgeInsets.symmetric(vertical: 6.h, horizontal: 8.w), padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16.r), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 6, spreadRadius: 1, offset: const Offset(0, 3), ), ], ), child: Row( children: [ // Avatar Stack( children: [ Container( width: 55.r, height: 55.r, decoration: BoxDecoration( shape: BoxShape.circle, image: imageUrl.isNotEmpty ? DecorationImage( image: NetworkImage(imageUrl), fit: BoxFit.cover, ) : null, color: Colors.grey[200], ), child: imageUrl.isEmpty ? Icon( Icons.group, size: 28.sp, color: Colors.grey[700], ) : null, ), // Member count bubble Positioned( right: -2.w, bottom: -2.h, child: Container( padding: EdgeInsets.symmetric( horizontal: 4.w, vertical: 4.h, ), decoration: BoxDecoration( color: Color(primaryColor), borderRadius: BorderRadius.circular(20.r), border: Border.all(color: Colors.white, width: 2), ), child: Icon(Icons.group, size: 15.sp), ), ), ], ), SizedBox(width: 12.w), // Text section Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( name, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 15.sp, fontWeight: FontWeight.w600, color: Colors.black, ), ), SizedBox(height: 4.h), Text( '${members ?? 0} members', style: TextStyle(fontSize: 12.sp, color: Colors.grey[600]), ), ], ), ), ], ), ), ); } }