diff --git a/lib/constants.dart b/lib/constants.dart index fe97c7d..f93cefe 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -22,6 +22,8 @@ class Constants { static const String dbFieldUsersVisions = 'visions'; static const String dbFieldUsersWorkValues = 'work_values'; static const String dbFieldUsersCorpCulture = 'corp_culture'; + static const String dbFieldUsersCommunication = 'communication'; + static const String dbFieldUsersRiskTolerance = 'risk_tolerance'; static const String pathLanguagesJson = 'lib/assets/languages.json'; } diff --git a/lib/enumerations.dart b/lib/enumerations.dart index ed29e2b..280f3bf 100644 --- a/lib/enumerations.dart +++ b/lib/enumerations.dart @@ -116,3 +116,46 @@ enum CultureOption { } } } + +enum CommunicationPreference { + daily, + weekly, + adhoc, + formal; + + String get displayName { + switch (this) { + case CommunicationPreference.daily: + return 'Frequent updates and daily meetings'; + case CommunicationPreference.weekly: + return 'Weekly summaries and updates'; + case CommunicationPreference.adhoc: + return 'Ad-hoc communication as needed'; + case CommunicationPreference.formal: + return 'Formal reports and documentation'; + } + } +} + +enum RiskTolerance { + riskAverse, + cautious, + balanced, + adaptive, + riskTaker; + + String get displayName { + switch (this) { + case RiskTolerance.riskAverse: + return 'Prefer avoiding risks whenever possible'; + case RiskTolerance.cautious: + return 'Exercising caution to minimize potential losses'; + case RiskTolerance.balanced: + return 'Neutral, carefully weighing potential opportunities and hazards'; + case RiskTolerance.adaptive: + return 'Flexibly responding to changing risk scenarios'; + case RiskTolerance.riskTaker: + return 'Proactively taking risks to maximize rewards'; + } + } +} diff --git a/lib/forms/corporate_culture_form.dart b/lib/forms/corporate_culture_form.dart index ec0cbc0..b036789 100644 --- a/lib/forms/corporate_culture_form.dart +++ b/lib/forms/corporate_culture_form.dart @@ -1,8 +1,9 @@ import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import '../constants.dart'; import '../enumerations.dart'; -import '../pages/registration_complete_page.dart'; +import '../forms/risks_form.dart'; import '../services/auth/auth_service.dart'; class CultureValuesFormPage extends StatefulWidget { @@ -55,7 +56,7 @@ class CultureValuesFormPageState extends State { } // Load Culture option if (data[Constants.dbFieldUsersCorpCulture] != null) { - selectedCultureOption = CultureOption.values.firstWhere( + selectedCultureOption = CultureOption.values.firstWhereOrNull( (e) => e.toString() == data[Constants.dbFieldUsersCorpCulture], ); } @@ -108,9 +109,9 @@ class CultureValuesFormPageState extends State { context, MaterialPageRoute( // - // TODO set following registration page HERE + // set following registration page HERE // - builder: (context) => const RegistrationCompletePage(), + builder: (context) => RisksFormPage(isRegProcess: widget.isRegProcess), ), ); } diff --git a/lib/forms/risks_form.dart b/lib/forms/risks_form.dart new file mode 100644 index 0000000..abd8b21 --- /dev/null +++ b/lib/forms/risks_form.dart @@ -0,0 +1,158 @@ +import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import '../constants.dart'; +import '../enumerations.dart'; +import '../pages/registration_complete_page.dart'; +import '../services/auth/auth_service.dart'; + +class RisksFormPage extends StatefulWidget { + const RisksFormPage({super.key, required this.isRegProcess}); + + final bool isRegProcess; + + @override + RisksFormPageState createState() => RisksFormPageState(); +} + +class RisksFormPageState extends State { + CommunicationPreference? communicationPreference; + RiskTolerance? riskTolerance; + + final AuthService _authService = AuthService(); + + @override + void initState() { + super.initState(); + _loadDataFromFirebase(); + } + + Future _loadDataFromFirebase() async { + final userDoc = FirebaseFirestore.instance + .collection(Constants.dbCollectionUsers) + .doc(_authService.getCurrentUser()!.uid); + final snapshot = await userDoc.get(); + + if (snapshot.exists) { + final data = snapshot.data(); + setState(() { + if (data != null) { + // Load Communication Preference + if (data[Constants.dbFieldUsersCommunication] != null) { + communicationPreference = CommunicationPreference.values + .firstWhereOrNull((x) => + x.toString() == data[Constants.dbFieldUsersCommunication]); + } + // Load Risk Tolerance + if (data[Constants.dbFieldUsersRiskTolerance] != null) { + riskTolerance = RiskTolerance.values.firstWhereOrNull((x) => + x.toString() == data[Constants.dbFieldUsersRiskTolerance]); + } + } + }); + } + } + + Future _saveDataToFirebase() async { + final userDoc = FirebaseFirestore.instance + .collection(Constants.dbCollectionUsers) + .doc(_authService.getCurrentUser()!.uid); + + await userDoc.set( + { + Constants.dbFieldUsersCommunication: + communicationPreference?.toString(), + Constants.dbFieldUsersRiskTolerance: riskTolerance?.toString(), + }, + SetOptions(merge: true), // avoid overwriting existing data + ); + } + + void handleSubmit() { + if (communicationPreference == null) { + ScaffoldMessenger.of(context).showSnackBar(const SnackBar( + content: Text('Please select a communication preference.'), + )); + return; + } + if (riskTolerance == null) { + ScaffoldMessenger.of(context).showSnackBar(const SnackBar( + content: Text('Please select the willingness to take risks.'), + )); + return; + } + _saveDataToFirebase(); + // Handle the form submission logic here + Navigator.push( + context, + MaterialPageRoute( + // + // TODO set following registration page HERE + // + builder: (context) => const RegistrationCompletePage(), + ), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Personal preferences'), + ), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Communication preference', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const Text('How do you prefer to communicate in a team?'), + ...CommunicationPreference.values.map((option) { + return RadioListTile( + title: Text(option.displayName), + value: option, + groupValue: communicationPreference, + onChanged: (CommunicationPreference? value) { + setState(() { + communicationPreference = value; + }); + }, + ); + }), + const SizedBox(height: 40), + const Text( + 'Risk tolerance', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const Text('How do you deal with uncertainty and risk?'), + ...RiskTolerance.values.map((option) { + return RadioListTile( + title: Text(option.displayName), + value: option, + groupValue: riskTolerance, + onChanged: (RiskTolerance? value) { + setState(() { + riskTolerance = value; + }); + }, + ); + }), + const SizedBox(height: 20), + Center( + child: ElevatedButton( + onPressed: handleSubmit, + child: + Text(widget.isRegProcess ? 'Save and continue' : 'Save'), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart index 228a9f2..784bcfb 100644 --- a/lib/pages/login_page.dart +++ b/lib/pages/login_page.dart @@ -52,73 +52,78 @@ class LoginPage extends StatelessWidget { return Scaffold( backgroundColor: Theme.of(context).colorScheme.background, body: Center( - child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [ - // logo - Icon( - Icons.people_alt, - size: 60, - color: Theme.of(context).colorScheme.primary, - ), - - const SizedBox(height: 50), - - //welcome back message - Text( - "Welcome back, you've been missed", - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontSize: 16, - ), - ), - - const SizedBox(height: 25), - - // email textfield - MyTextField( - hintText: "E-Mail", - obscureText: false, - controller: _emailController, - ), - - //const SizedBox(height: 25), - - // password textfield - MyTextField( - hintText: "Password", - obscureText: true, - controller: _passwordController, - ), - - const SizedBox(height: 25), - - // login button - MyButton( - text: "Login", - onTap: () => login(context), - ), - - const SizedBox(height: 25), - - // register now - Row( + child: SingleChildScrollView( + child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - "Not a member? ", - style: TextStyle(color: Theme.of(context).colorScheme.primary), + // logo + Icon( + Icons.people_alt, + size: 60, + color: Theme.of(context).colorScheme.primary, ), - GestureDetector( - onTap: onTap, - child: const Text( - "Register now", - style: TextStyle( - fontWeight: FontWeight.bold, - ), + + const SizedBox(height: 50), + + //welcome back message + Text( + "Welcome back, you've been missed", + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontSize: 16, ), ), + + const SizedBox(height: 25), + + // email textfield + MyTextField( + hintText: "E-Mail", + obscureText: false, + controller: _emailController, + ), + + // password textfield + MyTextField( + hintText: "Password", + obscureText: true, + controller: _passwordController, + ), + + const SizedBox(height: 25), + + // login button + MyButton( + text: "Login", + onTap: () => login(context), + ), + + const SizedBox(height: 25), + + // register now + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Not a member? ", + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + ), + ), + GestureDetector( + onTap: onTap, + child: const Text( + "Register now", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ) ], - ) - ]), + ), + ), ), ); } diff --git a/lib/pages/registration_complete_page.dart b/lib/pages/registration_complete_page.dart index 803a563..7e4ffc5 100644 --- a/lib/pages/registration_complete_page.dart +++ b/lib/pages/registration_complete_page.dart @@ -12,35 +12,37 @@ class RegistrationCompletePage extends StatelessWidget { title: const Text('Registration Complete'), ), body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon( - Icons.check_circle, - color: Colors.green, - size: 100, - ), - const SizedBox(height: 20), - const Text( - 'Registration completed!', - style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 80), - const Text( - "You can enjoy the app now.", - style: TextStyle(fontSize: 18), - ), - const SizedBox(height: 20), - ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => HomePage()), - ); - }, - child: const Text("S T A R T"), - ), - ], + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.check_circle, + color: Colors.green, + size: 100, + ), + const SizedBox(height: 20), + const Text( + 'Registration completed!', + style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 80), + const Text( + "You can enjoy the app now.", + style: TextStyle(fontSize: 18), + ), + const SizedBox(height: 20), + ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => HomePage()), + ); + }, + child: const Text("S T A R T"), + ), + ], + ), ), ), ); diff --git a/lib/pages/user_data_page.dart b/lib/pages/user_data_page.dart index 8d11343..f17ace9 100644 --- a/lib/pages/user_data_page.dart +++ b/lib/pages/user_data_page.dart @@ -182,7 +182,7 @@ class _UserDataPageState extends State { if (_selectedYear != _yearFromDb) { await userRef.update( - {'born': _selectedYear}, + {Constants.dbFieldUsersYearBorn: _selectedYear}, ); // update local value _yearFromDb = _selectedYear; @@ -191,7 +191,7 @@ class _UserDataPageState extends State { // Update Gender in database - only if value has changed if (_genderFromDb != genderView.index) { await userRef.update( - {'gender': genderView.index}, + {Constants.dbFieldUsersGender: genderView.index}, ); // update local value _genderFromDb = genderView.index; diff --git a/lib/pages/user_vision_page.dart b/lib/pages/user_vision_page.dart index 84bbe23..0430768 100644 --- a/lib/pages/user_vision_page.dart +++ b/lib/pages/user_vision_page.dart @@ -1,9 +1,10 @@ -import "package:cloud_firestore/cloud_firestore.dart"; -import "package:flutter/material.dart"; -import "../constants.dart"; -import "../enumerations.dart"; -import "../forms/corporate_culture_form.dart"; -import "../services/auth/auth_service.dart"; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import '../constants.dart'; +import '../enumerations.dart'; +import '../forms/corporate_culture_form.dart'; +import '../services/auth/auth_service.dart'; class MatchingForm extends StatefulWidget { const MatchingForm({super.key, required this.isRegProcess}); @@ -50,7 +51,7 @@ class MatchingFormState extends State { } // Load Availability option if (data?[Constants.dbFieldUsersAvailability] != null) { - availability = AvailabilityOption.values.firstWhere( + availability = AvailabilityOption.values.firstWhereOrNull( (e) => e.toString() == data?[Constants.dbFieldUsersAvailability], ); }