Edit Visions and Work values.

master
Rafael 2024-05-31 23:16:15 +02:00
parent 3aa5f2b5d3
commit cfff83d734
7 changed files with 377 additions and 64 deletions

View File

@ -7,9 +7,11 @@ import '../forms/risks_form.dart';
import '../services/auth/auth_service.dart'; import '../services/auth/auth_service.dart';
class CultureValuesFormPage extends StatefulWidget { 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 isRegProcess;
final bool isEditMode;
@override @override
CultureValuesFormPageState createState() => CultureValuesFormPageState(); CultureValuesFormPageState createState() => CultureValuesFormPageState();
@ -65,21 +67,33 @@ class CultureValuesFormPageState extends State<CultureValuesFormPage> {
} }
} }
Future<void> _saveDataToFirebase() async { Future<bool> _saveDataToFirebase() async {
final userDoc = FirebaseFirestore.instance try {
.collection(Constants.dbCollectionUsers) final userDoc = FirebaseFirestore.instance
.doc(_authService.getCurrentUser()!.uid); .collection(Constants.dbCollectionUsers)
.doc(_authService.getCurrentUser()!.uid);
await userDoc.set( await userDoc.set(
{ {
Constants.dbFieldUsersWorkValues: selectedValueOptions.entries Constants.dbFieldUsersWorkValues: selectedValueOptions.entries
.where((entry) => entry.value) .where((entry) => entry.value)
.map((entry) => entry.key.toString()) .map((entry) => entry.key.toString())
.toList(), .toList(),
Constants.dbFieldUsersCorpCulture: selectedCultureOption?.toString(), Constants.dbFieldUsersCorpCulture: selectedCultureOption?.toString(),
}, },
SetOptions(merge: true), SetOptions(merge: true), // avoid overwriting existing data
); // 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() { bool isWorkValueSelected() {
@ -89,11 +103,13 @@ class CultureValuesFormPageState extends State<CultureValuesFormPage> {
selectedCount <= maxWorkValueOption; selectedCount <= maxWorkValueOption;
} }
void handleSubmit() { Future<void> handleSubmit() async {
if (!isWorkValueSelected()) { if (!isWorkValueSelected()) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar( ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text( 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; return;
} }
@ -103,17 +119,35 @@ class CultureValuesFormPageState extends State<CultureValuesFormPage> {
)); ));
return; return;
} }
_saveDataToFirebase();
// Handle the form submission logic here // Handle the form submission logic here
Navigator.push( bool success = await _saveDataToFirebase();
context, if (success) {
MaterialPageRoute( if (widget.isRegProcess) {
// Navigator.push(
// set following registration page HERE context,
// MaterialPageRoute(
builder: (context) => RisksFormPage(isRegProcess: widget.isRegProcess), //
), // 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 @override

View File

@ -66,8 +66,10 @@ class SkillsForm extends StatelessWidget {
context, context,
MaterialPageRoute( MaterialPageRoute(
// set following registration page HERE // set following registration page HERE
builder: (context) => builder: (context) => UserVisionPage(
UserVisionPage(isRegProcess: isRegProcess), isRegProcess: isRegProcess,
isEditMode: false,
),
), ),
); );
} else if (isRegProcess) { } else if (isRegProcess) {

View File

@ -1,8 +1,8 @@
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:cofounderella/services/user_service.dart';
import '../constants.dart'; import '../constants.dart';
import '../enumerations.dart'; import '../enumerations.dart';
import '../services/user_service.dart';
import 'language.dart'; import 'language.dart';
import 'location.dart'; import 'location.dart';
@ -17,9 +17,13 @@ class UserProfile {
String? bio; String? bio;
Gender? gender; Gender? gender;
int? born; int? born;
final String risk; RiskTolerance risk;
AvailabilityOption availability;
CultureOption culture;
List<SkillOption> skills; List<SkillOption> skills;
List<SkillOption> skillsSought; List<SkillOption> skillsSought;
List<VisionOption> visions;
List<WorkValueOption> workValues;
List<Language> languages; List<Language> languages;
Map<String, MyLocation?> locations; Map<String, MyLocation?> locations;
@ -35,8 +39,12 @@ class UserProfile {
this.gender, this.gender,
this.born, this.born,
required this.risk, required this.risk,
required this.availability,
required this.culture,
required this.skills, required this.skills,
required this.skillsSought, required this.skillsSought,
required this.visions,
required this.workValues,
required this.languages, required this.languages,
required this.locations, required this.locations,
}); });
@ -48,6 +56,16 @@ class UserProfile {
data[Constants.dbFieldUsersSkills]); data[Constants.dbFieldUsersSkills]);
List<SkillOption> skillsSought = UserService.convertSkillStringToEnum( List<SkillOption> skillsSought = UserService.convertSkillStringToEnum(
data[Constants.dbFieldUsersSkillsSought]); data[Constants.dbFieldUsersSkillsSought]);
List<VisionOption> visions = UserService.convertVisionStringToEnum(
data[Constants.dbFieldUsersVisions]);
List<WorkValueOption> 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( return UserProfile(
id: doc.id, id: doc.id,
@ -58,7 +76,11 @@ class UserProfile {
lastName: data[Constants.dbFieldUsersLastName] ?? '', lastName: data[Constants.dbFieldUsersLastName] ?? '',
skills: skillsOffered, skills: skillsOffered,
skillsSought: skillsSought, skillsSought: skillsSought,
risk: data[Constants.dbFieldUsersRiskTolerance] ?? '', visions: visions,
risk: risk,
availability: availability,
culture: culture,
workValues: works,
profilePictureUrl: data[Constants.dbFieldUsersProfilePic], profilePictureUrl: data[Constants.dbFieldUsersProfilePic],
bio: data[Constants.dbFieldUsersBio], bio: data[Constants.dbFieldUsersBio],
gender: Gender.values[data[Constants.dbFieldUsersGender] ?? 0], gender: Gender.values[data[Constants.dbFieldUsersGender] ?? 0],

View File

@ -395,10 +395,11 @@ class UserMatchingPageState extends State<UserMatchingPage> {
Text(userProfile.email, style: const TextStyle(fontSize: 24)), Text(userProfile.email, style: const TextStyle(fontSize: 24)),
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
'Has skills and experience in: ${userProfile.skills.join(', ')}'), 'Has skills and experience in: ${userProfile.skills.map((x) => x.displayName).join(', ')}'),
Text( Text(
'Seeks someone with skills in: ${userProfile.skillsSought.join(', ')}'), 'Seeks someone with skills in: ${userProfile.skillsSought.map((x) => x.displayName).join(', ')}'),
Text('Risk type: ${userProfile.risk}'), Text('Availability: ${userProfile.availability.displayName}'),
Text('Risk type: ${userProfile.risk.displayName}'),
Text( Text(
'Speaks: ${userProfile.languages.map((lang) => lang.name).join(', ')}'), 'Speaks: ${userProfile.languages.map((lang) => lang.name).join(', ')}'),
Text( Text(

View File

@ -1,15 +1,17 @@
import 'package:cofounderella/enumerations.dart';
import 'package:cofounderella/forms/skills_form.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_auth/firebase_auth.dart';
import '../constants.dart'; import '../constants.dart';
import '../enumerations.dart';
import '../forms/corporate_culture_form.dart';
import '../forms/skills_form.dart';
import '../models/user_profile.dart'; import '../models/user_profile.dart';
import '../services/user_service.dart'; import '../services/user_service.dart';
import '../utils/helper.dart'; import '../utils/helper.dart';
import '../utils/math.dart'; import '../utils/math.dart';
import 'edit_profile_page.dart'; import 'edit_profile_page.dart';
import 'user_data_page.dart'; import 'user_data_page.dart';
import 'user_vision_page.dart';
class UserProfilePage extends StatefulWidget { class UserProfilePage extends StatefulWidget {
const UserProfilePage({super.key}); const UserProfilePage({super.key});
@ -119,6 +121,52 @@ class _UserProfilePageState extends State<UserProfilePage> {
_editSkills(skillsSought: true); _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<dynamic> 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<dynamic> dynamicList =
updatedUserData[Constants.dbFieldUsersWorkValues];
myData.workValues =
dynamicList.map((e) => e as WorkValueOption).toList();
myData.culture = updatedUserData[Constants.dbFieldUsersCorpCulture];
});
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -144,6 +192,14 @@ class _UserProfilePageState extends State<UserProfilePage> {
const SizedBox(height: 16), const SizedBox(height: 16),
Divider(color: Theme.of(context).colorScheme.primary), Divider(color: Theme.of(context).colorScheme.primary),
const SizedBox(height: 16), 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<UserProfilePage> {
); );
} }
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) { Widget _buildSkills(BuildContext context) {
return Column( return Column(
children: [ children: [

View File

@ -7,9 +7,11 @@ import '../forms/corporate_culture_form.dart';
import '../services/auth/auth_service.dart'; import '../services/auth/auth_service.dart';
class UserVisionPage extends StatefulWidget { 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 isRegProcess;
final bool isEditMode;
@override @override
UserVisionPageState createState() => UserVisionPageState(); UserVisionPageState createState() => UserVisionPageState();
@ -59,28 +61,40 @@ class UserVisionPageState extends State<UserVisionPage> {
} }
} }
Future<void> _saveDataToFirebase() async { Future<bool> _saveDataToFirebase() async {
final userDoc = FirebaseFirestore.instance try {
.collection(Constants.dbCollectionUsers) final userDoc = FirebaseFirestore.instance
.doc(_authService.getCurrentUser()!.uid); .collection(Constants.dbCollectionUsers)
.doc(_authService.getCurrentUser()!.uid);
await userDoc.set( await userDoc.set(
{ {
Constants.dbFieldUsersVisions: selectedVisionOptions.entries Constants.dbFieldUsersVisions: selectedVisionOptions.entries
.where((entry) => entry.value) .where((entry) => entry.value)
.map((entry) => entry.key.toString()) .map((entry) => entry.key.toString())
.toList(), .toList(),
Constants.dbFieldUsersAvailability: availability?.toString(), Constants.dbFieldUsersAvailability: availability?.toString(),
}, },
SetOptions(merge: true), // avoid overwriting existing data 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() { bool isVisionSelected() {
return selectedVisionOptions.containsValue(true); return selectedVisionOptions.containsValue(true);
} }
void handleSubmit() { Future<void> handleSubmit() async {
if (!isVisionSelected()) { if (!isVisionSelected()) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar( ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('Please select at least one long-term vision.'), content: Text('Please select at least one long-term vision.'),
@ -93,19 +107,43 @@ class UserVisionPageState extends State<UserVisionPage> {
)); ));
return; return;
} }
_saveDataToFirebase();
// Handle the form submission logic here // Handle the form submission logic here
Navigator.push( bool success = await _saveDataToFirebase();
context, if (success) {
MaterialPageRoute( if (widget.isRegProcess) {
// Navigator.push(
// set following registration page HERE context,
// MaterialPageRoute(
builder: (context) => CultureValuesFormPage( //
isRegProcess: widget.isRegProcess, // 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 @override

View File

@ -69,6 +69,29 @@ class UserService {
return []; return [];
} }
static List<VisionOption> convertVisionStringToEnum(List<dynamic>? visions) {
if (visions != null && visions.isNotEmpty) {
List<VisionOption> userVisions = visions
.map((vision) =>
VisionOption.values.firstWhere((x) => x.toString() == vision))
.toList();
return userVisions;
}
return [];
}
static List<WorkValueOption> convertWorkValuesStringToEnum(
List<dynamic>? values) {
if (values != null && values.isNotEmpty) {
List<WorkValueOption> userWorkValues = values
.map((workValue) => WorkValueOption.values
.firstWhere((x) => x.toString() == workValue))
.toList();
return userWorkValues;
}
return [];
}
static Future<bool> saveSkillsToFirebase(List<SkillOption> selectedOptions, static Future<bool> saveSkillsToFirebase(List<SkillOption> selectedOptions,
bool skillsSought, String userId) async { bool skillsSought, String userId) async {
try { try {