382 lines
16 KiB
Dart
382 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/api_enum_constant.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/echoboard/controllers/connection_and_tribe_controller.dart';
|
|
import 'package:onufitness/screens/echoboard/controllers/profile_controller.dart';
|
|
import 'package:onufitness/screens/echoboard/widget/friend_request_send_user_card.dart';
|
|
import 'package:onufitness/screens/echoboard/widget/invitation_card.dart';
|
|
import 'package:onufitness/screens/echoboard/widget/pagination_widget.dart';
|
|
import 'package:onufitness/widgets/appbars/custom_appbar.dart';
|
|
|
|
class FriendRequestScreen extends StatefulWidget {
|
|
final bool isFriendTab;
|
|
const FriendRequestScreen({super.key, this.isFriendTab = false});
|
|
|
|
@override
|
|
State<FriendRequestScreen> createState() => _FriendRequestScreenState();
|
|
}
|
|
|
|
class _FriendRequestScreenState extends State<FriendRequestScreen> {
|
|
late final SocialConnectionController controller;
|
|
late final ProfileController profileController;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
// Get existing controller or create new one
|
|
if (!Get.isRegistered<SocialConnectionController>()) {
|
|
Get.put(SocialConnectionController());
|
|
}
|
|
controller = Get.find<SocialConnectionController>();
|
|
|
|
if (!Get.isRegistered<ProfileController>()) {
|
|
Get.put(ProfileController());
|
|
}
|
|
profileController = Get.find<ProfileController>();
|
|
|
|
// Load data for current tab after widget builds
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
if (mounted) {
|
|
// If we're not already on the correct tab, switch to it
|
|
if (controller.currentTab.value != "Invitations" &&
|
|
widget.isFriendTab == false) {
|
|
controller.changeTab("Invitations");
|
|
} else {
|
|
// Just refresh current data
|
|
controller.clearCurrentTabData();
|
|
controller.searchUsers();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void _navigateToFriendsList() {
|
|
controller.currentTab.value = "Friends";
|
|
controller.clearSearch();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return PopScope(
|
|
canPop: true,
|
|
onPopInvokedWithResult: (didPop, result) {
|
|
// Clean up search state when leaving
|
|
controller.searchValue.value = "";
|
|
controller.searchController.clear();
|
|
},
|
|
child: Container(
|
|
color: Colors.white,
|
|
child: SafeArea(
|
|
child: Scaffold(
|
|
appBar: CustomAppBar(
|
|
title: "Connections",
|
|
leading: IconButton(
|
|
onPressed: () {
|
|
controller.searchValue.value = "";
|
|
controller.searchController.clear();
|
|
Get.back();
|
|
},
|
|
icon: const Icon(Icons.arrow_back_ios),
|
|
),
|
|
textColor: appbarTextColor,
|
|
backgroundColor: Colors.white,
|
|
titleFontSize: appBarHeardingText,
|
|
actions: [
|
|
Padding(
|
|
padding: EdgeInsets.only(right: 12.w),
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
color: Color(primaryColor),
|
|
borderRadius: BorderRadius.circular(12),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withValues(alpha: 0.15),
|
|
blurRadius: 3,
|
|
offset: const Offset(0, 3),
|
|
),
|
|
],
|
|
),
|
|
child: Material(
|
|
color: Colors.transparent,
|
|
child: InkWell(
|
|
borderRadius: BorderRadius.circular(12),
|
|
onTap: () {
|
|
Get.toNamed(RouteConstant.viewTribeScreen);
|
|
},
|
|
child: Padding(
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: 16.w,
|
|
vertical: 12.h,
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(
|
|
Icons.groups_rounded,
|
|
color: appbarTextColor,
|
|
size: mediumSizeText,
|
|
),
|
|
SizedBox(width: 8.w),
|
|
Text(
|
|
"Tribes",
|
|
style: TextStyle(
|
|
color: appbarTextColor,
|
|
fontWeight: FontWeight.w700,
|
|
fontSize: verySmallSizeText,
|
|
letterSpacing: 0.3,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
body: Column(
|
|
children: [
|
|
// Tab selector
|
|
Padding(
|
|
padding: EdgeInsets.all(15.sp),
|
|
child: Obx(
|
|
() => Row(
|
|
children: [
|
|
Expanded(
|
|
child: InkWell(
|
|
onTap: () => controller.changeTab("Invitations"),
|
|
child: Container(
|
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
|
decoration: BoxDecoration(
|
|
color:
|
|
controller.currentTab.value == "Invitations"
|
|
? Colors.black
|
|
: Colors.white,
|
|
borderRadius: BorderRadius.circular(25),
|
|
border: Border.all(color: Colors.grey.shade300),
|
|
),
|
|
child: Center(
|
|
child: Text(
|
|
"Invitations",
|
|
style: TextStyle(
|
|
color:
|
|
controller.currentTab.value ==
|
|
"Invitations"
|
|
? Colors.white
|
|
: Colors.black,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(width: 10),
|
|
Expanded(
|
|
child: InkWell(
|
|
onTap: () => controller.changeTab("Friends"),
|
|
child: Container(
|
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
|
decoration: BoxDecoration(
|
|
color:
|
|
controller.currentTab.value == "Friends"
|
|
? Colors.black
|
|
: Colors.white,
|
|
borderRadius: BorderRadius.circular(25),
|
|
border: Border.all(color: Colors.grey.shade300),
|
|
),
|
|
child: Center(
|
|
child: Text(
|
|
"Friends",
|
|
style: TextStyle(
|
|
color:
|
|
controller.currentTab.value == "Friends"
|
|
? Colors.white
|
|
: Colors.black,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(width: 10),
|
|
InkWell(
|
|
onTap: () {
|
|
Get.toNamed(
|
|
RouteConstant.userListViewScreenForTribe,
|
|
);
|
|
_navigateToFriendsList();
|
|
},
|
|
child: Row(
|
|
children: [
|
|
Icon(Icons.add, size: regularSizeText),
|
|
const SizedBox(width: 5),
|
|
Text(
|
|
"Create tribe",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: smallSizeText,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
|
|
// Search Field
|
|
Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 15.sp),
|
|
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: () {
|
|
controller.clearSearch();
|
|
},
|
|
),
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(30),
|
|
borderSide: BorderSide.none,
|
|
),
|
|
filled: true,
|
|
fillColor: textFieldFillColor,
|
|
),
|
|
onChanged: (value) => controller.onSearchChanged(value),
|
|
onSubmitted: (_) {
|
|
controller.clearCurrentTabData();
|
|
controller.searchUsers();
|
|
},
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 10),
|
|
|
|
// User List
|
|
Expanded(
|
|
child: Obx(() {
|
|
if (controller.isLoading.value) {
|
|
return const Center(
|
|
child: CircularProgressIndicator(color: Colors.black),
|
|
);
|
|
}
|
|
|
|
final users = controller.usersData.value?.data?.items;
|
|
|
|
if (users == null || users.isEmpty) {
|
|
return Center(
|
|
child: Text(
|
|
controller.currentTab.value == "Invitations"
|
|
? 'No invitation requests'
|
|
: 'No friends found',
|
|
style: TextStyle(
|
|
fontSize: regularSizeText,
|
|
color: Colors.grey[600],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
return ListView.builder(
|
|
itemCount: users.length,
|
|
padding: const EdgeInsets.all(10),
|
|
itemBuilder: (context, index) {
|
|
final user = users[index];
|
|
|
|
// Show different UI based on the current tab
|
|
if (controller.currentTab.value == "Invitations") {
|
|
return InkWell(
|
|
onTap: () {
|
|
if (user.userId != null) {
|
|
profileController.selectedUserId.value =
|
|
user.userId.toString();
|
|
Get.toNamed(
|
|
RouteConstant.userSocialProfileScreen,
|
|
);
|
|
}
|
|
},
|
|
child: InvitationCard(
|
|
user: user,
|
|
onAccept: () async {
|
|
await controller.respondToConnectionRequest(
|
|
user.userId!,
|
|
ApiEnum.accepted,
|
|
);
|
|
},
|
|
onReject: () async {
|
|
await controller.respondToConnectionRequest(
|
|
user.userId!,
|
|
ApiEnum.rejected,
|
|
);
|
|
},
|
|
loadingIds:
|
|
controller.responseToInvitationLoading,
|
|
),
|
|
);
|
|
} else {
|
|
return InkWell(
|
|
onTap: () {
|
|
if (user.userId != null) {
|
|
profileController.selectedUserId.value =
|
|
user.userId.toString();
|
|
Get.toNamed(
|
|
RouteConstant.userSocialProfileScreen,
|
|
);
|
|
}
|
|
},
|
|
child: ConnectUserCard(
|
|
user: user,
|
|
onConnect: () async {
|
|
if (user.userId != null) {
|
|
await controller.sendConnectionRequest(
|
|
user.userId!,
|
|
);
|
|
}
|
|
},
|
|
connectionStatus:
|
|
user.connectionStatus ?? 'Accepted',
|
|
loadingContains:
|
|
controller.sendConnectionRequestLoading,
|
|
isYourFriend: true,
|
|
),
|
|
);
|
|
}
|
|
},
|
|
);
|
|
}),
|
|
),
|
|
|
|
//Pagination widget.....................................................
|
|
showsUserListPagination(controller),
|
|
//......................................................................
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|