LikedUsersPage: Sort View
parent
fec48737c7
commit
cddb2078ed
|
@ -116,29 +116,10 @@ class MyDrawer extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// settings list tile
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 25),
|
padding: const EdgeInsets.only(left: 25),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
title: const Text("My Profile"),
|
title: const Text('My Profile'),
|
||||||
leading: const Icon(Icons.settings),
|
|
||||||
onTap: () {
|
|
||||||
// pop the drawer and navigate to settings page
|
|
||||||
Navigator.pop(context);
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const SettingsPage(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 25),
|
|
||||||
child: ListTile(
|
|
||||||
title: const Text('My Profile Settings'),
|
|
||||||
leading: const Icon(Icons.edit_note),
|
leading: const Icon(Icons.edit_note),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// pop the drawer first, then navigate to destination
|
// pop the drawer first, then navigate to destination
|
||||||
|
@ -153,6 +134,25 @@ class MyDrawer extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// settings list tile
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 25),
|
||||||
|
child: ListTile(
|
||||||
|
title: const Text("App Settings"),
|
||||||
|
leading: const Icon(Icons.settings),
|
||||||
|
onTap: () {
|
||||||
|
// pop the drawer and navigate to settings page
|
||||||
|
Navigator.pop(context);
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => const SettingsPage(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
// TODO TESTING - user data tile
|
// TODO TESTING - user data tile
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 25),
|
padding: const EdgeInsets.only(left: 25),
|
||||||
|
|
|
@ -1,21 +1,13 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../models/message.dart';
|
|
||||||
import '../services/chat/chat_service.dart';
|
|
||||||
import '../utils/helper.dart';
|
|
||||||
|
|
||||||
class UserTile extends StatelessWidget {
|
class UserTile extends StatelessWidget {
|
||||||
final String headerText;
|
final String text;
|
||||||
final String? currentUserId;
|
|
||||||
final String? otherUserId;
|
|
||||||
final String? profileImageUrl;
|
final String? profileImageUrl;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
|
|
||||||
const UserTile({
|
const UserTile({
|
||||||
super.key,
|
super.key,
|
||||||
required this.headerText,
|
required this.text,
|
||||||
this.currentUserId,
|
|
||||||
this.otherUserId,
|
|
||||||
this.profileImageUrl,
|
this.profileImageUrl,
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
});
|
});
|
||||||
|
@ -30,110 +22,26 @@ class UserTile extends StatelessWidget {
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 25),
|
margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 25),
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(20),
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
buildProfileIcon(),
|
// Profile image
|
||||||
buildMsgContent(),
|
if (profileImageUrl != null && profileImageUrl!.isNotEmpty)
|
||||||
|
CircleAvatar(
|
||||||
|
backgroundImage: NetworkImage(profileImageUrl!),
|
||||||
|
radius: 24,
|
||||||
|
),
|
||||||
|
// Icon if profile image is not set
|
||||||
|
if (profileImageUrl == null || profileImageUrl!.isEmpty)
|
||||||
|
const Icon(Icons.person),
|
||||||
|
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
|
||||||
|
// user name
|
||||||
|
Text(text),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildProfileIcon() {
|
|
||||||
return Row(
|
|
||||||
children: [
|
|
||||||
// Profile image
|
|
||||||
if (profileImageUrl != null && profileImageUrl!.isNotEmpty)
|
|
||||||
CircleAvatar(
|
|
||||||
backgroundImage: NetworkImage(profileImageUrl!),
|
|
||||||
radius: 24,
|
|
||||||
),
|
|
||||||
// Icon if profile image is not set
|
|
||||||
if (profileImageUrl == null || profileImageUrl!.isEmpty)
|
|
||||||
const Icon(Icons.person),
|
|
||||||
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget buildMsgContent() {
|
|
||||||
String msgDateString = '';
|
|
||||||
String msgContent = '';
|
|
||||||
bool? outgoing;
|
|
||||||
String chatRoomID = getCompoundId([currentUserId ?? '', otherUserId ?? '']);
|
|
||||||
|
|
||||||
return FutureBuilder<Message?>(
|
|
||||||
future: ChatService().getLastMessage(chatRoomID),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
||||||
return const CircularProgressIndicator();
|
|
||||||
} else if (snapshot.hasError) {
|
|
||||||
return Text(
|
|
||||||
'Error: ${snapshot.error}',
|
|
||||||
style: const TextStyle(color: Colors.red),
|
|
||||||
);
|
|
||||||
} else if (!snapshot.hasData || snapshot.data == null) {
|
|
||||||
return const Text('No messages yet');
|
|
||||||
} else {
|
|
||||||
Message lastMessage = snapshot.data!;
|
|
||||||
msgDateString = formatTimestamp(lastMessage.timestamp);
|
|
||||||
|
|
||||||
if (lastMessage.senderID == currentUserId) {
|
|
||||||
msgContent = 'Me: ${lastMessage.message}';
|
|
||||||
outgoing = true;
|
|
||||||
} else if (lastMessage.senderID == otherUserId) {
|
|
||||||
msgContent = lastMessage.message;
|
|
||||||
outgoing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
// user name
|
|
||||||
Text(
|
|
||||||
headerText,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 4),
|
|
||||||
Text(msgContent, overflow: TextOverflow.ellipsis, maxLines: 1),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
if (outgoing == true)
|
|
||||||
const Icon(
|
|
||||||
Icons.call_made,
|
|
||||||
color: Colors.green,
|
|
||||||
size: 16,
|
|
||||||
),
|
|
||||||
if (outgoing == false)
|
|
||||||
const Icon(
|
|
||||||
Icons.call_received,
|
|
||||||
color: Colors.blue,
|
|
||||||
size: 16,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 4),
|
|
||||||
Flexible(
|
|
||||||
child: Text(
|
|
||||||
msgDateString,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
maxLines: 1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../models/message.dart';
|
||||||
|
import '../services/chat/chat_service.dart';
|
||||||
|
import '../utils/helper.dart';
|
||||||
|
|
||||||
|
class UserTileChats extends StatelessWidget {
|
||||||
|
final String headerText;
|
||||||
|
final String? currentUserId;
|
||||||
|
final String? otherUserId;
|
||||||
|
final String? profileImageUrl;
|
||||||
|
final void Function()? onTap;
|
||||||
|
|
||||||
|
const UserTileChats({
|
||||||
|
super.key,
|
||||||
|
required this.headerText,
|
||||||
|
this.currentUserId,
|
||||||
|
this.otherUserId,
|
||||||
|
this.profileImageUrl,
|
||||||
|
required this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 25),
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
buildProfileIcon(),
|
||||||
|
buildMsgContent(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildProfileIcon() {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
// Profile image
|
||||||
|
if (profileImageUrl != null && profileImageUrl!.isNotEmpty)
|
||||||
|
CircleAvatar(
|
||||||
|
backgroundImage: NetworkImage(profileImageUrl!),
|
||||||
|
radius: 24,
|
||||||
|
),
|
||||||
|
// Icon if profile image is not set
|
||||||
|
if (profileImageUrl == null || profileImageUrl!.isEmpty)
|
||||||
|
const Icon(Icons.person),
|
||||||
|
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildMsgContent() {
|
||||||
|
String msgDateString = '';
|
||||||
|
String msgContent = '';
|
||||||
|
bool? outgoing;
|
||||||
|
String chatRoomID = getCompoundId([currentUserId ?? '', otherUserId ?? '']);
|
||||||
|
|
||||||
|
return FutureBuilder<Message?>(
|
||||||
|
future: ChatService().getLastMessage(chatRoomID),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
return const CircularProgressIndicator();
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
return Text(
|
||||||
|
'Error: ${snapshot.error}',
|
||||||
|
style: const TextStyle(color: Colors.red),
|
||||||
|
);
|
||||||
|
} else if (!snapshot.hasData || snapshot.data == null) {
|
||||||
|
return const Text('No messages yet');
|
||||||
|
} else {
|
||||||
|
Message lastMessage = snapshot.data!;
|
||||||
|
msgDateString = formatTimestamp(lastMessage.timestamp);
|
||||||
|
|
||||||
|
if (lastMessage.senderID == currentUserId) {
|
||||||
|
msgContent = 'Me: ${lastMessage.message}';
|
||||||
|
outgoing = true;
|
||||||
|
} else if (lastMessage.senderID == otherUserId) {
|
||||||
|
msgContent = lastMessage.message;
|
||||||
|
outgoing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
// user name
|
||||||
|
Text(
|
||||||
|
headerText,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(msgContent, overflow: TextOverflow.ellipsis, maxLines: 1),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
if (outgoing == true)
|
||||||
|
const Icon(
|
||||||
|
Icons.call_made,
|
||||||
|
color: Colors.green,
|
||||||
|
size: 16,
|
||||||
|
),
|
||||||
|
if (outgoing == false)
|
||||||
|
const Icon(
|
||||||
|
Icons.call_received,
|
||||||
|
color: Colors.blue,
|
||||||
|
size: 16,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
msgDateString,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../constants.dart';
|
||||||
|
|
||||||
|
class UserTileLikes extends StatelessWidget {
|
||||||
|
final DocumentSnapshot user;
|
||||||
|
final bool hasMatch;
|
||||||
|
final VoidCallback onUnlike;
|
||||||
|
final VoidCallback onShowMatchMessage;
|
||||||
|
final VoidCallback onViewInfo;
|
||||||
|
|
||||||
|
const UserTileLikes({
|
||||||
|
super.key,
|
||||||
|
required this.user,
|
||||||
|
required this.hasMatch,
|
||||||
|
required this.onUnlike,
|
||||||
|
required this.onShowMatchMessage,
|
||||||
|
required this.onViewInfo,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
Map<String, dynamic> userMap = user.data() as Map<String, dynamic>;
|
||||||
|
bool hasPictureUrl = userMap.containsKey(Constants.dbFieldUsersProfilePic);
|
||||||
|
bool hasName = userMap.containsKey(Constants.dbFieldUsersName);
|
||||||
|
bool hasBio = userMap.containsKey(Constants.dbFieldUsersBio);
|
||||||
|
|
||||||
|
return Card(
|
||||||
|
margin: const EdgeInsets.all(8.0),
|
||||||
|
child: ListTile(
|
||||||
|
leading: hasPictureUrl == true &&
|
||||||
|
user[Constants.dbFieldUsersProfilePic] != null
|
||||||
|
? CircleAvatar(
|
||||||
|
backgroundImage: NetworkImage(
|
||||||
|
user[Constants.dbFieldUsersProfilePic],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const CircleAvatar(
|
||||||
|
child: Icon(Icons.person),
|
||||||
|
),
|
||||||
|
title: hasName
|
||||||
|
? Text(
|
||||||
|
'${user[Constants.dbFieldUsersName]}',
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
subtitle: hasBio
|
||||||
|
? Text(
|
||||||
|
user[Constants.dbFieldUsersBio],
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 3,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
trailing: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.contact_page_outlined),
|
||||||
|
onPressed: onViewInfo,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: hasMatch
|
||||||
|
? const Icon(Icons.lock_outline)
|
||||||
|
: const Icon(Icons.delete_outline, color: Colors.red),
|
||||||
|
onPressed: hasMatch ? onShowMatchMessage : onUnlike,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../components/user_tile.dart';
|
import '../components/user_tile_chats.dart';
|
||||||
import '../constants.dart';
|
import '../constants.dart';
|
||||||
import '../services/auth/auth_service.dart';
|
import '../services/auth/auth_service.dart';
|
||||||
import '../services/user_service.dart';
|
import '../services/user_service.dart';
|
||||||
|
@ -67,7 +67,7 @@ class ConversationsPage extends StatelessWidget {
|
||||||
// build individual user list item
|
// build individual user list item
|
||||||
Widget _buildUserListItem(String currentUserId, Map<String, dynamic> userData,
|
Widget _buildUserListItem(String currentUserId, Map<String, dynamic> userData,
|
||||||
BuildContext context) {
|
BuildContext context) {
|
||||||
return UserTile(
|
return UserTileChats(
|
||||||
headerText: userData[Constants.dbFieldUsersName],
|
headerText: userData[Constants.dbFieldUsersName],
|
||||||
currentUserId: currentUserId,
|
currentUserId: currentUserId,
|
||||||
otherUserId: userData[Constants.dbFieldUsersID],
|
otherUserId: userData[Constants.dbFieldUsersID],
|
||||||
|
|
|
@ -59,7 +59,7 @@ class HomePage extends StatelessWidget {
|
||||||
if (userData[Constants.dbFieldUsersEmail] !=
|
if (userData[Constants.dbFieldUsersEmail] !=
|
||||||
_authService.getCurrentUser()!.email) {
|
_authService.getCurrentUser()!.email) {
|
||||||
return UserTile(
|
return UserTile(
|
||||||
headerText: userData[Constants.dbFieldUsersEmail],
|
text: userData[Constants.dbFieldUsersEmail],
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// tapped on a user -> go to chat page
|
// tapped on a user -> go to chat page
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
|
||||||
|
import '../components/user_tile_likes.dart';
|
||||||
import '../constants.dart';
|
import '../constants.dart';
|
||||||
import '../services/auth/auth_service.dart';
|
import '../services/auth/auth_service.dart';
|
||||||
import '../utils/helper.dart';
|
import '../utils/helper.dart';
|
||||||
|
|
||||||
|
enum MenuSort { nameAsc, nameDesc, timestampAsc, timestampDesc }
|
||||||
|
|
||||||
|
enum ViewOrder { swipedFirst, matchedFirst }
|
||||||
|
|
||||||
class LikedUsersPage extends StatefulWidget {
|
class LikedUsersPage extends StatefulWidget {
|
||||||
const LikedUsersPage({super.key});
|
const LikedUsersPage({super.key});
|
||||||
|
|
||||||
|
@ -15,6 +20,9 @@ class LikedUsersPage extends StatefulWidget {
|
||||||
class LikedUsersPageState extends State<LikedUsersPage> {
|
class LikedUsersPageState extends State<LikedUsersPage> {
|
||||||
final String currentUserId = AuthService().getCurrentUser()!.uid;
|
final String currentUserId = AuthService().getCurrentUser()!.uid;
|
||||||
|
|
||||||
|
ViewOrder _orderPreference = ViewOrder.swipedFirst;
|
||||||
|
MenuSort _sortPreference = MenuSort.nameAsc;
|
||||||
|
|
||||||
Future<List<DocumentSnapshot>> _fetchLikedUsers() async {
|
Future<List<DocumentSnapshot>> _fetchLikedUsers() async {
|
||||||
QuerySnapshot likedUsersSnapshot = await FirebaseFirestore.instance
|
QuerySnapshot likedUsersSnapshot = await FirebaseFirestore.instance
|
||||||
.collection(Constants.dbCollectionUsers)
|
.collection(Constants.dbCollectionUsers)
|
||||||
|
@ -134,14 +142,119 @@ class LikedUsersPageState extends State<LikedUsersPage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<DocumentSnapshot>> _fetchSortedLikedUsers() async {
|
||||||
|
List<DocumentSnapshot> likedUsers = await _fetchLikedUsers();
|
||||||
|
List<DocumentSnapshot> likedOnlyUsers = [];
|
||||||
|
List<DocumentSnapshot> matchedUsers = [];
|
||||||
|
|
||||||
|
for (DocumentSnapshot user in likedUsers) {
|
||||||
|
bool hasMatch = await _hasMatch(user.id);
|
||||||
|
if (hasMatch) {
|
||||||
|
matchedUsers.add(user);
|
||||||
|
} else {
|
||||||
|
likedOnlyUsers.add(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sortPreference == MenuSort.nameAsc) {
|
||||||
|
likedOnlyUsers.sort((a, b) => (a[Constants.dbFieldUsersName] as String)
|
||||||
|
.compareTo(b[Constants.dbFieldUsersName] as String));
|
||||||
|
matchedUsers.sort((a, b) => (a[Constants.dbFieldUsersName] as String)
|
||||||
|
.compareTo(b[Constants.dbFieldUsersName] as String));
|
||||||
|
} else if (_sortPreference == MenuSort.nameDesc) {
|
||||||
|
likedOnlyUsers.sort((a, b) => (b[Constants.dbFieldUsersName] as String)
|
||||||
|
.compareTo(a[Constants.dbFieldUsersName] as String));
|
||||||
|
matchedUsers.sort((a, b) => (b[Constants.dbFieldUsersName] as String)
|
||||||
|
.compareTo(a[Constants.dbFieldUsersName] as String));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_orderPreference == ViewOrder.swipedFirst) {
|
||||||
|
return [...likedOnlyUsers, ...matchedUsers];
|
||||||
|
} else {
|
||||||
|
return [...matchedUsers, ...likedOnlyUsers];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Liked Users'),
|
title: const Text('Liked Users'),
|
||||||
),
|
),
|
||||||
body: FutureBuilder<List<DocumentSnapshot>>(
|
body: Column(
|
||||||
future: _fetchLikedUsers(),
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
DropdownButton<ViewOrder>(
|
||||||
|
value: _orderPreference,
|
||||||
|
items: const [
|
||||||
|
DropdownMenuItem(
|
||||||
|
value: ViewOrder.swipedFirst,
|
||||||
|
child: Text('Swiped First')),
|
||||||
|
DropdownMenuItem(
|
||||||
|
value: ViewOrder.matchedFirst,
|
||||||
|
child: Text('Matched First')),
|
||||||
|
],
|
||||||
|
onChanged: (value) {
|
||||||
|
// update UI on change only
|
||||||
|
if (_orderPreference != value) {
|
||||||
|
setState(() {
|
||||||
|
_orderPreference = value!;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: PopupMenuButton<MenuSort>(
|
||||||
|
icon: const Icon(Icons.sort),
|
||||||
|
onSelected: (MenuSort item) {
|
||||||
|
// update UI on change only
|
||||||
|
if (_sortPreference != item) {
|
||||||
|
setState(() {
|
||||||
|
_sortPreference = item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
itemBuilder: (BuildContext context) =>
|
||||||
|
<PopupMenuEntry<MenuSort>>[
|
||||||
|
PopupMenuItem<MenuSort>(
|
||||||
|
value: MenuSort.nameAsc,
|
||||||
|
child: ListTile(
|
||||||
|
leading: _sortPreference == MenuSort.nameAsc
|
||||||
|
? const Icon(Icons.check)
|
||||||
|
: const Icon(null),
|
||||||
|
title: const Text('Name Ascending'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
PopupMenuItem<MenuSort>(
|
||||||
|
value: MenuSort.nameDesc,
|
||||||
|
child: ListTile(
|
||||||
|
leading: _sortPreference == MenuSort.nameDesc
|
||||||
|
? const Icon(Icons.check)
|
||||||
|
: const Icon(null),
|
||||||
|
title: const Text('Name Descending'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
buildLikedUserList(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildLikedUserList() {
|
||||||
|
return Expanded(
|
||||||
|
child: FutureBuilder<List<DocumentSnapshot>>(
|
||||||
|
future: _fetchSortedLikedUsers(),
|
||||||
builder: (BuildContext context,
|
builder: (BuildContext context,
|
||||||
AsyncSnapshot<List<DocumentSnapshot>> snapshot) {
|
AsyncSnapshot<List<DocumentSnapshot>> snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
@ -162,7 +275,7 @@ class LikedUsersPageState extends State<LikedUsersPage> {
|
||||||
return const CircularProgressIndicator();
|
return const CircularProgressIndicator();
|
||||||
}
|
}
|
||||||
bool hasMatch = snapshot.data ?? false;
|
bool hasMatch = snapshot.data ?? false;
|
||||||
return UserInfoTile(
|
return UserTileLikes(
|
||||||
user: user,
|
user: user,
|
||||||
hasMatch: hasMatch,
|
hasMatch: hasMatch,
|
||||||
onUnlike: () {
|
onUnlike: () {
|
||||||
|
@ -191,68 +304,3 @@ class LikedUsersPageState extends State<LikedUsersPage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserInfoTile extends StatelessWidget {
|
|
||||||
final DocumentSnapshot user;
|
|
||||||
final bool hasMatch;
|
|
||||||
final VoidCallback onUnlike;
|
|
||||||
final VoidCallback onShowMatchMessage;
|
|
||||||
final VoidCallback onViewInfo;
|
|
||||||
|
|
||||||
const UserInfoTile({
|
|
||||||
super.key,
|
|
||||||
required this.user,
|
|
||||||
required this.hasMatch,
|
|
||||||
required this.onUnlike,
|
|
||||||
required this.onShowMatchMessage,
|
|
||||||
required this.onViewInfo,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
Map<String, dynamic> userMap = user.data() as Map<String, dynamic>;
|
|
||||||
bool hasPictureUrl = userMap.containsKey(Constants.dbFieldUsersProfilePic);
|
|
||||||
bool hasName = userMap.containsKey(Constants.dbFieldUsersName);
|
|
||||||
bool hasBio = userMap.containsKey(Constants.dbFieldUsersBio);
|
|
||||||
|
|
||||||
return Card(
|
|
||||||
margin: const EdgeInsets.all(8.0),
|
|
||||||
child: ListTile(
|
|
||||||
leading: hasPictureUrl == true &&
|
|
||||||
user[Constants.dbFieldUsersProfilePic] != null
|
|
||||||
? CircleAvatar(
|
|
||||||
backgroundImage:
|
|
||||||
NetworkImage(user[Constants.dbFieldUsersProfilePic]),
|
|
||||||
)
|
|
||||||
: const CircleAvatar(child: Icon(Icons.person)),
|
|
||||||
title: hasName
|
|
||||||
? Text(
|
|
||||||
'${user[Constants.dbFieldUsersName]} ${user[Constants.dbFieldUsersName]} ${user[Constants.dbFieldUsersName]}',
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
maxLines: 1,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
subtitle: hasBio
|
|
||||||
? Text(
|
|
||||||
user[Constants.dbFieldUsersBio],
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
maxLines: 3,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
trailing: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.contact_page_outlined),
|
|
||||||
onPressed: onViewInfo,
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(hasMatch ? Icons.lock_outline : Icons.delete_outline),
|
|
||||||
onPressed: hasMatch ? onShowMatchMessage : onUnlike,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue