I am trying to make an tracker app in witch I an user can create a group and when clicked on "show on map" it would show all of members position. I have made group info page in witch there is a Add members button. When clicked it takes the user to a new page. In that new page he searches for an different user witch he wants to add. When clicked on search icon under the TextFormField there is an ListTile. When tapped on that ListTile searched user should be added to that group and the searcher should be redirected back to group info page.
I am stuck at the part in which I try to add users to an existing group but I get an error:
Bad state: field does not exist within the DocumentSnapshotPlatform.
Here is the code for adding different users to a group
import 'package:cloud_firestore/cloud_firestore.dart';
class DatabaseService {
final String? uid;
DatabaseService({this.uid});
// reference for collection
final CollectionReference userCollection =
FirebaseFirestore.instance.collection("users");
final CollectionReference groupCollection =
FirebaseFirestore.instance.collection("groups");
// saving the user data
Future savingUserData(String name, String email) async {
return await userCollection.doc(uid).set({
"name": name,
"email": email,
"friends": [],
"groups": [],
"profilePicture": "",
"uid": uid,
"latitude": "",
"longitude": "",
});
}
//getting user data
Future gettingUserData(String email) async {
QuerySnapshot snapshot =
await userCollection.where("email", isEqualTo: email).get();
return snapshot;
}
// create a group
Future createGroup(String name, String groupName, String id) async {
DocumentReference groupDocumentReference = await groupCollection.add({
"groupName": groupName,
"groupIcon": "",
"groupCreator": "",
"admins": [],
"members": [],
"groupId": "",
});
await groupDocumentReference.update({
"admins": FieldValue.arrayUnion(["${uid}_$name"]),
"groupCreator": FieldValue.arrayUnion(["${id}_$name"]),
"groupId": groupDocumentReference.id
});
DocumentReference userDocumentReference = userCollection.doc(uid);
return await userDocumentReference.update({
"groups":
FieldValue.arrayUnion(["${groupDocumentReference.id}_$groupName"])
});
}
getUserGroups() async {
return userCollection.doc(uid).snapshots();
}
//search
searchByEmail(String userEmail) async {
return userCollection.where('email', isEqualTo: userEmail).get();
}
//get group admins
getGroupAdmins(String groupId) async {
return groupCollection.doc(groupId).snapshots();
}
getGroupMembers(String groupId) async {
return groupCollection.doc(groupId).snapshots();
}
Future addMember(
String groupId,
String groupName,
String memeberId,
memberName,
) async {
DocumentReference userDocumentReference = userCollection.doc(memeberId);
DocumentReference groupDocumentReference = groupCollection.doc(groupId);
DocumentSnapshot userdocumentSnapshot = await userDocumentReference.get();
List<dynamic> groups = await userdocumentSnapshot['groups'];
DocumentSnapshot groupDocumentSnapshot = await groupDocumentReference.get();
List<dynamic> members = await groupDocumentSnapshot['members'];
if (groups.contains("${groupId}_$groupName") &
members.contains("${memeberId}_$memberName")) {
return null;
} else {
await groupCollection.doc(groupId).update({
"members": FieldValue.arrayUnion(["${memeberId}_$memberName"])
});
}
}
}
Here is the AddMemberPage
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:tracker_app/page_changer/page_changer.dart';
import 'package:tracker_app/pages/app_pages/info_page.dart';
import 'package:tracker_app/services/database_service.dart';
import '../../theme/theme.dart';
class AddMembers extends StatefulWidget {
final String groupId;
final String groupName;
const AddMembers({super.key, required this.groupId, required this.groupName});
@override
State<AddMembers> createState() => _AddMembersState();
}
class _AddMembersState extends State<AddMembers> {
QuerySnapshot? searchSnapshot;
TextEditingController emailController = TextEditingController();
String email = "";
String friendId = "";
String friendName = "";
bool isLoading = false;
bool hasUserSearched = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
"Add members",
style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500),
),
centerTitle: true,
),
body: SingleChildScrollView(
child: Column(children: [
const Divider(
height: 5,
indent: 5,
endIndent: 5,
thickness: 1.5,
),
Container(
height: 10,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: TextFormField(
controller: emailController,
cursorColor: AppColors.secondary,
decoration: InputDecoration(
errorBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.red),
borderRadius: BorderRadius.circular(50)),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppColors.secondary,
),
borderRadius: BorderRadius.circular(50)),
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppColors.secondary,
),
borderRadius: BorderRadius.circular(50)),
labelText: "email",
labelStyle: const TextStyle(
color: AppColors.secondary,
fontWeight: FontWeight.w500,
),
suffixIcon: InkWell(
splashColor: AppColors.secondary,
borderRadius: BorderRadius.circular(360),
onTap: () {
initiateSearchMethod();
},
child: const Icon(
Icons.search,
color: AppColors.secondary,
),
),
hintText: "Enter persons email"),
onChanged: (value) {
setState(() {
email = value;
});
},
),
),
userList(),
]),
),
);
}
initiateSearchMethod() async {
if (emailController != null) {
setState(() {
isLoading = true;
});
await DatabaseService(uid: FirebaseAuth.instance.currentUser!.uid)
.searchByEmail(email)
.then((snapshot) {
setState(() {
searchSnapshot = snapshot;
isLoading = false;
hasUserSearched = true;
friendId = snapshot!.docs[0]['id'];
friendName = snapshot!.docs[0]['name'];
});
});
}
}
userList() {
return hasUserSearched
? ListView.builder(
shrinkWrap: true,
itemCount: searchSnapshot!.docs.length,
itemBuilder: (context, index) {
return friendSearchTile();
},
)
: Container();
}
friendSearchTile() {
// check if user is friend
//GdzhH8YGCsTMhmPf6aAeXvb09GH3
return ListTile(
leading: CircleAvatar(
radius: 25,
backgroundColor: AppColors.secondary,
child: Text(
searchSnapshot!.docs[0]['name'].substring(0, 1).toUpperCase(),
style: const TextStyle(color: Colors.white)),
),
title: Text(friendName),
subtitle: Text(searchSnapshot!.docs[0]['email']),
trailing: InkWell(
borderRadius: BorderRadius.circular(360),
onTap: () {
DatabaseService(uid: FirebaseAuth.instance.currentUser!.uid)
.addMember(
widget.groupId,
widget.groupName,
searchSnapshot!.docs[0]['id'],
searchSnapshot!.docs[0]['name']);
nextScreenReplace(context,
InfoPage(groupName: widget.groupName, groupId: widget.groupId));
print("friendId: $friendId");
},
splashColor: AppColors.secondary,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
child: const Icon(
Icons.add,
),
),
),
);
}
}
CodePudding user response:
After more searching I found the solution. In AddMembers page when clicked to add an user required groupId, groupName, friendId(that users id), friendName(that friends name). The problem was with firendId. The line searchSnapshot!.docs[0]['id] was wrong. In the firebase I marked the users id as 'uid'.After changing that it started working. The line:
DatabaseService(uid: FirebaseAuth.instance.currentUser!.uid)
.addMember(
widget.groupId,
widget.groupName,
searchSnapshot!.docs[0]['id'],
searchSnapshot!.docs[0]['name']);
I changed to:
DatabaseService(uid: FirebaseAuth.instance.currentUser!.uid)
.addMember(
widget.groupId,
widget.groupName,
searchSnapshot!.docs[0]['uid'],
searchSnapshot!.docs[0]['name']);
CodePudding user response:
It looks like the issue is with how you are getting the groups and members arrays from the DocumentSnapshot objects for the user and group documents. In your addMember() function, you are using the await keyword to get the values of the groups and members fields from the DocumentSnapshot objects, but these fields are not async, so using await with them will not work.
To fix this, you can simply remove the await keywords when getting the values of the groups and members fields, like this:
List<dynamic> groups = userdocumentSnapshot['groups'];
List<dynamic> members = groupDocumentSnapshot['members'];
You can then use the contains() method on the groups and members lists to check if they already contain the new member and group, and add the new member to the group if they do not already exist in the lists.
Here is how your addMember() function should look like after making these changes:
Future addMember(
String groupId,
String groupName,
String memeberId,
memberName,
) async {
DocumentReference userDocumentReference = userCollection.doc(memeberId);
DocumentReference groupDocumentReference = groupCollection.doc(groupId);
DocumentSnapshot userdocumentSnapshot = await userDocumentReference.get();
List<dynamic> groups = userdocumentSnapshot['groups'];
DocumentSnapshot groupDocumentSnapshot = await groupDocumentReference.get();
List<dynamic> members = groupDocumentSnapshot['members'];
if (!groups.contains("${groupId}_$groupName") ||
!members.contains("${memeberId}_$memberName")) {
await groupCollection.doc(groupId).update({
"members": FieldValue.arrayUnion(["${memeberId}_$memberName"])
});
}
}
I hope this helps!