From cfff83d7343348c3bee277088ec3d4a8835f6160 Mon Sep 17 00:00:00 2001 From: Rafael <1024481@stud.hs-mannheim.de> Date: Fri, 31 May 2024 23:16:15 +0200 Subject: [PATCH] Edit Visions and Work values. --- lib/forms/corporate_culture_form.dart | 88 ++++++++---- lib/forms/skills_form.dart | 6 +- lib/models/user_profile.dart | 28 +++- lib/pages/user_matching_page.dart | 7 +- lib/pages/user_profile_page.dart | 197 +++++++++++++++++++++++++- lib/pages/user_vision_page.dart | 92 ++++++++---- lib/services/user_service.dart | 23 +++ 7 files changed, 377 insertions(+), 64 deletions(-) diff --git a/lib/forms/corporate_culture_form.dart b/lib/forms/corporate_culture_form.dart index b036789..99b9aac 100644 --- a/lib/forms/corporate_culture_form.dart +++ b/lib/forms/corporate_culture_form.dart @@ -7,9 +7,11 @@ import '../forms/risks_form.dart'; import '../services/auth/auth_service.dart'; class CultureValuesFormPage extends StatefulWidget { - const CultureValuesFormPage({super.key, required this.isRegProcess}); + const CultureValuesFormPage( + {super.key, required this.isRegProcess, required this.isEditMode}); final bool isRegProcess; + final bool isEditMode; @override CultureValuesFormPageState createState() => CultureValuesFormPageState(); @@ -65,21 +67,33 @@ class CultureValuesFormPageState extends State { } } - Future _saveDataToFirebase() async { - final userDoc = FirebaseFirestore.instance - .collection(Constants.dbCollectionUsers) - .doc(_authService.getCurrentUser()!.uid); + Future _saveDataToFirebase() async { + try { + final userDoc = FirebaseFirestore.instance + .collection(Constants.dbCollectionUsers) + .doc(_authService.getCurrentUser()!.uid); - await userDoc.set( - { - Constants.dbFieldUsersWorkValues: selectedValueOptions.entries - .where((entry) => entry.value) - .map((entry) => entry.key.toString()) - .toList(), - Constants.dbFieldUsersCorpCulture: selectedCultureOption?.toString(), - }, - SetOptions(merge: true), - ); // avoid overwriting existing data + await userDoc.set( + { + Constants.dbFieldUsersWorkValues: selectedValueOptions.entries + .where((entry) => entry.value) + .map((entry) => entry.key.toString()) + .toList(), + Constants.dbFieldUsersCorpCulture: selectedCultureOption?.toString(), + }, + SetOptions(merge: true), // avoid overwriting existing data + ); + return true; + } catch (e) { + _showSnackBar(e.toString()); + return false; + } + } + + void _showSnackBar(String message) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(message), + )); } bool isWorkValueSelected() { @@ -89,11 +103,13 @@ class CultureValuesFormPageState extends State { selectedCount <= maxWorkValueOption; } - void handleSubmit() { + Future handleSubmit() async { if (!isWorkValueSelected()) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( - 'Please select at least ${minWorkValueOption.toString()} and at most ${maxWorkValueOption.toString()} work life values.'), + 'Please select at least ${minWorkValueOption.toString()} and ' + 'at most ${maxWorkValueOption.toString()} work life values.', + ), )); return; } @@ -103,17 +119,35 @@ class CultureValuesFormPageState extends State { )); return; } - _saveDataToFirebase(); // Handle the form submission logic here - Navigator.push( - context, - MaterialPageRoute( - // - // set following registration page HERE - // - builder: (context) => RisksFormPage(isRegProcess: widget.isRegProcess), - ), - ); + bool success = await _saveDataToFirebase(); + if (success) { + if (widget.isRegProcess) { + Navigator.push( + context, + MaterialPageRoute( + // + // set following registration page HERE + // + builder: (context) => + RisksFormPage(isRegProcess: widget.isRegProcess), + ), + ); + } else { + if (widget.isEditMode == true) { + // pass selectedOptions data back to caller + Navigator.pop(context, { + Constants.dbFieldUsersWorkValues: selectedValueOptions.entries + .where((entry) => entry.value) + .map((entry) => entry.key) + .toList(), + Constants.dbFieldUsersCorpCulture: selectedCultureOption, + }); + } else { + Navigator.pop(context); + } + } + } } @override diff --git a/lib/forms/skills_form.dart b/lib/forms/skills_form.dart index 43277ba..cbd4dad 100644 --- a/lib/forms/skills_form.dart +++ b/lib/forms/skills_form.dart @@ -66,8 +66,10 @@ class SkillsForm extends StatelessWidget { context, MaterialPageRoute( // set following registration page HERE - builder: (context) => - UserVisionPage(isRegProcess: isRegProcess), + builder: (context) => UserVisionPage( + isRegProcess: isRegProcess, + isEditMode: false, + ), ), ); } else if (isRegProcess) { diff --git a/lib/models/user_profile.dart b/lib/models/user_profile.dart index fb28d8c..cfc2959 100644 --- a/lib/models/user_profile.dart +++ b/lib/models/user_profile.dart @@ -1,8 +1,8 @@ import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:cofounderella/services/user_service.dart'; import '../constants.dart'; import '../enumerations.dart'; +import '../services/user_service.dart'; import 'language.dart'; import 'location.dart'; @@ -17,9 +17,13 @@ class UserProfile { String? bio; Gender? gender; int? born; - final String risk; + RiskTolerance risk; + AvailabilityOption availability; + CultureOption culture; List skills; List skillsSought; + List visions; + List workValues; List languages; Map locations; @@ -35,8 +39,12 @@ class UserProfile { this.gender, this.born, required this.risk, + required this.availability, + required this.culture, required this.skills, required this.skillsSought, + required this.visions, + required this.workValues, required this.languages, required this.locations, }); @@ -48,6 +56,16 @@ class UserProfile { data[Constants.dbFieldUsersSkills]); List skillsSought = UserService.convertSkillStringToEnum( data[Constants.dbFieldUsersSkillsSought]); + List visions = UserService.convertVisionStringToEnum( + data[Constants.dbFieldUsersVisions]); + List works = UserService.convertWorkValuesStringToEnum( + data[Constants.dbFieldUsersWorkValues]); + RiskTolerance risk = + RiskTolerance.fromString(data[Constants.dbFieldUsersRiskTolerance]); + AvailabilityOption availability = + AvailabilityOption.fromString(data[Constants.dbFieldUsersAvailability]); + CultureOption culture = + CultureOption.fromString(data[Constants.dbFieldUsersCorpCulture]); return UserProfile( id: doc.id, @@ -58,7 +76,11 @@ class UserProfile { lastName: data[Constants.dbFieldUsersLastName] ?? '', skills: skillsOffered, skillsSought: skillsSought, - risk: data[Constants.dbFieldUsersRiskTolerance] ?? '', + visions: visions, + risk: risk, + availability: availability, + culture: culture, + workValues: works, profilePictureUrl: data[Constants.dbFieldUsersProfilePic], bio: data[Constants.dbFieldUsersBio], gender: Gender.values[data[Constants.dbFieldUsersGender] ?? 0], diff --git a/lib/pages/user_matching_page.dart b/lib/pages/user_matching_page.dart index 7c548c8..6d8bf7f 100644 --- a/lib/pages/user_matching_page.dart +++ b/lib/pages/user_matching_page.dart @@ -395,10 +395,11 @@ class UserMatchingPageState extends State { Text(userProfile.email, style: const TextStyle(fontSize: 24)), const SizedBox(height: 8), Text( - 'Has skills and experience in: ${userProfile.skills.join(', ')}'), + 'Has skills and experience in: ${userProfile.skills.map((x) => x.displayName).join(', ')}'), Text( - 'Seeks someone with skills in: ${userProfile.skillsSought.join(', ')}'), - Text('Risk type: ${userProfile.risk}'), + 'Seeks someone with skills in: ${userProfile.skillsSought.map((x) => x.displayName).join(', ')}'), + Text('Availability: ${userProfile.availability.displayName}'), + Text('Risk type: ${userProfile.risk.displayName}'), Text( 'Speaks: ${userProfile.languages.map((lang) => lang.name).join(', ')}'), Text( diff --git a/lib/pages/user_profile_page.dart b/lib/pages/user_profile_page.dart index f7d8615..dd87e0e 100644 --- a/lib/pages/user_profile_page.dart +++ b/lib/pages/user_profile_page.dart @@ -1,15 +1,17 @@ -import 'package:cofounderella/enumerations.dart'; -import 'package:cofounderella/forms/skills_form.dart'; import 'package:flutter/material.dart'; import 'package:firebase_auth/firebase_auth.dart'; import '../constants.dart'; +import '../enumerations.dart'; +import '../forms/corporate_culture_form.dart'; +import '../forms/skills_form.dart'; import '../models/user_profile.dart'; import '../services/user_service.dart'; import '../utils/helper.dart'; import '../utils/math.dart'; import 'edit_profile_page.dart'; import 'user_data_page.dart'; +import 'user_vision_page.dart'; class UserProfilePage extends StatefulWidget { const UserProfilePage({super.key}); @@ -119,6 +121,52 @@ class _UserProfilePageState extends State { _editSkills(skillsSought: true); } + void editUserVisionInfo() async { + final updatedUserData = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const UserVisionPage( + isRegProcess: false, + isEditMode: true, + ), + ), + ); + + if (updatedUserData != null) { + setState(() { + // above Type of updatedUserData is dynamic, so convert + List dynamicList = + updatedUserData[Constants.dbFieldUsersVisions]; + myData.visions = dynamicList.map((e) => e as VisionOption).toList(); + myData.availability = + updatedUserData[Constants.dbFieldUsersAvailability]; + }); + } + } + + void editUserWorkCultureInfo() async { + final updatedUserData = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const CultureValuesFormPage( + isRegProcess: false, + isEditMode: true, + ), + ), + ); + + if (updatedUserData != null) { + setState(() { + // above Type of updatedUserData is dynamic, so convert + List dynamicList = + updatedUserData[Constants.dbFieldUsersWorkValues]; + myData.workValues = + dynamicList.map((e) => e as WorkValueOption).toList(); + myData.culture = updatedUserData[Constants.dbFieldUsersCorpCulture]; + }); + } + } + @override Widget build(BuildContext context) { return Scaffold( @@ -144,6 +192,14 @@ class _UserProfilePageState extends State { const SizedBox(height: 16), Divider(color: Theme.of(context).colorScheme.primary), const SizedBox(height: 16), + _buildVision(context), + const SizedBox(height: 16), + Divider(color: Theme.of(context).colorScheme.primary), + const SizedBox(height: 16), + _buildWorkCulture(context), + const SizedBox(height: 16), + Divider(color: Theme.of(context).colorScheme.primary), + const SizedBox(height: 16), ], ), ), @@ -151,6 +207,143 @@ class _UserProfilePageState extends State { ); } + Widget _buildWorkCulture(BuildContext context) { + return Column( + children: [ + Align( + alignment: Alignment.centerLeft, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Corporate culture', + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + ), + ), + Text(myData.culture.displayName, + style: const TextStyle(fontSize: 16)), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Align( + alignment: Alignment.topRight, + child: OutlinedButton.icon( + label: const Text('Edit'), + icon: const Icon(Icons.edit), + onPressed: editUserWorkCultureInfo, + ), + ), + ), + ], + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Vision and Goals', + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + ), + ), + Text( + myData.workValues + .map((x) => x.displayName) + .join(',\n'), + style: const TextStyle(fontSize: 16)), + ], + ), + ), + ], + ), + ], + ), + ), + ], + ); + } + + Widget _buildVision(BuildContext context) { + return Column( + children: [ + Align( + alignment: Alignment.centerLeft, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Availability', + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + ), + ), + Text(myData.availability.displayName, + style: const TextStyle(fontSize: 16)), + ], + ), + ), + Align( + alignment: Alignment.topRight, + child: OutlinedButton.icon( + label: const Text('Edit'), + icon: const Icon(Icons.edit), + onPressed: editUserVisionInfo, + ), + ), + ], + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Vision and Goals', + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + ), + ), + Text( + myData.visions + .map((x) => x.displayName) + .join(',\n'), + style: const TextStyle(fontSize: 16)), + ], + ), + ), + ], + ), + ], + ), + ), + ], + ); + } + Widget _buildSkills(BuildContext context) { return Column( children: [ diff --git a/lib/pages/user_vision_page.dart b/lib/pages/user_vision_page.dart index fa78dda..a41bb7b 100644 --- a/lib/pages/user_vision_page.dart +++ b/lib/pages/user_vision_page.dart @@ -7,9 +7,11 @@ import '../forms/corporate_culture_form.dart'; import '../services/auth/auth_service.dart'; class UserVisionPage extends StatefulWidget { - const UserVisionPage({super.key, required this.isRegProcess}); + const UserVisionPage( + {super.key, required this.isRegProcess, required this.isEditMode}); final bool isRegProcess; + final bool isEditMode; @override UserVisionPageState createState() => UserVisionPageState(); @@ -59,28 +61,40 @@ class UserVisionPageState extends State { } } - Future _saveDataToFirebase() async { - final userDoc = FirebaseFirestore.instance - .collection(Constants.dbCollectionUsers) - .doc(_authService.getCurrentUser()!.uid); + Future _saveDataToFirebase() async { + try { + final userDoc = FirebaseFirestore.instance + .collection(Constants.dbCollectionUsers) + .doc(_authService.getCurrentUser()!.uid); - await userDoc.set( - { - Constants.dbFieldUsersVisions: selectedVisionOptions.entries - .where((entry) => entry.value) - .map((entry) => entry.key.toString()) - .toList(), - Constants.dbFieldUsersAvailability: availability?.toString(), - }, - SetOptions(merge: true), // avoid overwriting existing data - ); + await userDoc.set( + { + Constants.dbFieldUsersVisions: selectedVisionOptions.entries + .where((entry) => entry.value) + .map((entry) => entry.key.toString()) + .toList(), + Constants.dbFieldUsersAvailability: availability?.toString(), + }, + SetOptions(merge: true), // avoid overwriting existing data + ); + return true; + } catch (e) { + _showSnackBar(e.toString()); + return false; + } + } + + void _showSnackBar(String message) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(message), + )); } bool isVisionSelected() { return selectedVisionOptions.containsValue(true); } - void handleSubmit() { + Future handleSubmit() async { if (!isVisionSelected()) { ScaffoldMessenger.of(context).showSnackBar(const SnackBar( content: Text('Please select at least one long-term vision.'), @@ -93,19 +107,43 @@ class UserVisionPageState extends State { )); return; } - _saveDataToFirebase(); // Handle the form submission logic here - Navigator.push( - context, - MaterialPageRoute( - // - // set following registration page HERE - // - builder: (context) => CultureValuesFormPage( - isRegProcess: widget.isRegProcess, + bool success = await _saveDataToFirebase(); + if (success) { + if (widget.isRegProcess) { + Navigator.push( + context, + MaterialPageRoute( + // + // set following registration page HERE + // + builder: (context) => CultureValuesFormPage( + isRegProcess: widget.isRegProcess, + isEditMode: false, + ), + ), + ); + } else { + if (widget.isEditMode == true) { + // pass selectedOptions data back to caller + Navigator.pop(context, { + Constants.dbFieldUsersVisions: selectedVisionOptions.entries + .where((entry) => entry.value) + .map((entry) => entry.key) + .toList(), + Constants.dbFieldUsersAvailability: availability, + }); + } else { + Navigator.pop(context); + } + } + } else { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Failed to save data.'), ), - ), - ); + ); + } } @override diff --git a/lib/services/user_service.dart b/lib/services/user_service.dart index aca47cd..b037a72 100644 --- a/lib/services/user_service.dart +++ b/lib/services/user_service.dart @@ -69,6 +69,29 @@ class UserService { 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 {