import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import '../constants.dart'; import '../enumerations.dart'; import '../models/language.dart'; import '../models/location.dart'; import '../models/user_profile.dart'; class UserService { UserService._(); // Private constructor to prevent instantiation static Future saveUserRegistrationData(UserCredential userCredential, String email, String firstname, String lastname) async { // create full name String fullName = (firstname.isNotEmpty && lastname.isNotEmpty) ? '$firstname $lastname' : (firstname.isNotEmpty ? firstname : (lastname.isNotEmpty ? lastname : '')); // save user info to users document await FirebaseFirestore.instance .collection(Constants.dbCollectionUsers) .doc(userCredential.user!.uid) .set( { Constants.dbFieldUsersID: userCredential.user!.uid, Constants.dbFieldUsersEmail: email, Constants.dbFieldUsersFirstName: firstname, Constants.dbFieldUsersLastName: lastname, Constants.dbFieldUsersName: fullName, }, ); } static Future> getSkillsFromFirebase( bool skillsSought, String userId) async { // Fetch skills from Firestore DocumentSnapshot userDoc = await FirebaseFirestore.instance .collection(Constants.dbCollectionUsers) .doc(userId) .get(); if (userDoc.exists && userDoc.data() != null) { Map userData = userDoc.data()! as Map; List? skills; if (skillsSought) { skills = userData[Constants.dbFieldUsersSkillsSought]; } else { skills = userData[Constants.dbFieldUsersSkills]; } return convertSkillStringToEnum(skills); } return []; } static List convertSkillStringToEnum(List? skills) { if (skills != null && skills.isNotEmpty) { // Convert skills from strings to enum values List userSkills = skills .map((skill) => SkillOption.values .firstWhere((x) => x.toString() == 'SkillOption.$skill')) .toList(); return userSkills; } return []; } static List convertVisionStringToEnum(List? visions) { if (visions != null && visions.isNotEmpty) { List userVisions = visions .map((vision) => VisionOption.values.firstWhere((x) => x.toString() == vision)) .toList(); return userVisions; } return []; } static List convertWorkValuesStringToEnum( List? values) { if (values != null && values.isNotEmpty) { List userWorkValues = values .map((workValue) => WorkValueOption.values .firstWhere((x) => x.toString() == workValue)) .toList(); return userWorkValues; } return []; } static Future saveSkillsToFirebase(List selectedOptions, bool skillsSought, String userId) async { try { // Convert enum values to strings, removing leading EnumType with split List skills = selectedOptions .map((option) => option.toString().split('.').last) .toList(); // Update the corresponding 'skills' field in the user's document String keyToUpdate = skillsSought ? Constants.dbFieldUsersSkillsSought : Constants.dbFieldUsersSkills; FirebaseFirestore.instance .collection(Constants.dbCollectionUsers) .doc(userId) .update({keyToUpdate: skills}); return true; } catch (e) { return false; } } /// Get UserProfile for given [userId] static Future getUserProfileById(String userId) async { FirebaseFirestore firestore = FirebaseFirestore.instance; DocumentSnapshot userDoc = await firestore .collection(Constants.dbCollectionUsers) .doc(userId) .get(); QuerySnapshot languagesSnapshot = await firestore .collection(Constants.dbCollectionUsers) .doc(userId) .collection(Constants.dbCollectionLanguages) .get(); List languages = languagesSnapshot.docs .map((doc) => Language.fromDocument(doc)) .toList(); QuerySnapshot locationsSnapshot = await firestore .collection(Constants.dbCollectionUsers) .doc(userId) .collection(Constants.dbCollectionLocations) .get(); Map locations = { for (var doc in locationsSnapshot.docs) doc.id: MyLocation.fromDocument(doc) }; // Fill UserProfile including its sub collections UserProfile userProfile = UserProfile.fromDocument(userDoc); userProfile.languages.addAll(languages); userProfile.locations.addAll(locations); return userProfile; } // get users stream static Stream>> getUsersStream() { return FirebaseFirestore.instance .collection(Constants.dbCollectionUsers) .snapshots() .map((snapshot) { return snapshot.docs.map((doc) { // iterate each user final user = doc.data(); //return user return user; }).toList(); }); } // Get list of matched user ids for a given user static Future> getMatchedUserIds(String userId) async { List matchedUserIds = []; final snapshot = await FirebaseFirestore.instance .collection(Constants.dbCollectionUsers) .doc(userId) .collection(Constants.dbCollectionMatches) .get(); for (var doc in snapshot.docs) { final data = doc.data(); final otherUserId = data['otherUserId'] as String?; if (otherUserId != null && otherUserId.isNotEmpty) { matchedUserIds.add(otherUserId); } // assuming the match document ID is the matched user's ID // it would just be an one liner: // matchedUserIds.add(doc.id); } return matchedUserIds; } // Get matched users data for a given user as stream static Stream>> getMatchedUsersStream( String userId) { return FirebaseFirestore.instance .collection(Constants.dbCollectionUsers) .doc(userId) .collection(Constants.dbCollectionMatches) .snapshots() .asyncMap((snapshot) async { final matchedUserIds = snapshot.docs .map((doc) => doc.data()['otherUserId'] as String?) .where((otherUserId) => otherUserId != null && otherUserId.isNotEmpty) .toList(); if (matchedUserIds.isEmpty) { return []; } final matchedUsersSnapshot = await FirebaseFirestore.instance .collection(Constants.dbCollectionUsers) .where(FieldPath.documentId, whereIn: matchedUserIds) .get(); return matchedUsersSnapshot.docs.map((doc) => doc.data()).toList(); }); } }