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';
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<CultureValuesFormPage> {
}
}
Future<void> _saveDataToFirebase() async {
final userDoc = FirebaseFirestore.instance
.collection(Constants.dbCollectionUsers)
.doc(_authService.getCurrentUser()!.uid);
Future<bool> _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<CultureValuesFormPage> {
selectedCount <= maxWorkValueOption;
}
void handleSubmit() {
Future<void> 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<CultureValuesFormPage> {
));
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

View File

@ -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) {

View File

@ -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<SkillOption> skills;
List<SkillOption> skillsSought;
List<VisionOption> visions;
List<WorkValueOption> workValues;
List<Language> languages;
Map<String, MyLocation?> 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<SkillOption> skillsSought = UserService.convertSkillStringToEnum(
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(
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],

View File

@ -395,10 +395,11 @@ class UserMatchingPageState extends State<UserMatchingPage> {
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(

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: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<UserProfilePage> {
_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
Widget build(BuildContext context) {
return Scaffold(
@ -144,6 +192,14 @@ class _UserProfilePageState extends State<UserProfilePage> {
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<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) {
return Column(
children: [

View File

@ -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<UserVisionPage> {
}
}
Future<void> _saveDataToFirebase() async {
final userDoc = FirebaseFirestore.instance
.collection(Constants.dbCollectionUsers)
.doc(_authService.getCurrentUser()!.uid);
Future<bool> _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<void> 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<UserVisionPage> {
));
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

View File

@ -69,6 +69,29 @@ class UserService {
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,
bool skillsSought, String userId) async {
try {