diff --git a/lib/constants.dart b/lib/constants.dart index 48e5ff9..fe97c7d 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -20,6 +20,8 @@ class Constants { static const String dbFieldUsersSkillsSought = 'skills_sought'; static const String dbFieldUsersAvailability = 'availability'; static const String dbFieldUsersVisions = 'visions'; + static const String dbFieldUsersWorkValues = 'work_values'; + static const String dbFieldUsersCorpCulture = 'corp_culture'; static const String pathLanguagesJson = 'lib/assets/languages.json'; } diff --git a/lib/enumerations.dart b/lib/enumerations.dart index ea1f6be..ed29e2b 100644 --- a/lib/enumerations.dart +++ b/lib/enumerations.dart @@ -76,3 +76,43 @@ enum AvailabilityOption { } } } + +enum WorkValueOption { + transparency, + innovation, + teamwork, + workLifeBalance; + + String get displayName { + switch (this) { + case WorkValueOption.transparency: + return 'Transparency and openness'; + case WorkValueOption.innovation: + return 'Innovation and creativity'; + case WorkValueOption.teamwork: + return 'Teamwork and collaboration'; + case WorkValueOption.workLifeBalance: + return 'Work-life balance'; + } + } +} + +enum CultureOption { + performanceOriented, + supportive, + flexible, + traditional; + + String get displayName { + switch (this) { + case CultureOption.performanceOriented: + return 'Performance-oriented and competitive'; + case CultureOption.supportive: + return 'Supportive and collegial'; + case CultureOption.flexible: + return 'Flexible and adaptable'; + case CultureOption.traditional: + return 'Traditional and structured'; + } + } +} diff --git a/lib/forms/corporate_culture_form.dart b/lib/forms/corporate_culture_form.dart new file mode 100644 index 0000000..ec0cbc0 --- /dev/null +++ b/lib/forms/corporate_culture_form.dart @@ -0,0 +1,191 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/material.dart'; +import '../constants.dart'; +import '../enumerations.dart'; +import '../pages/registration_complete_page.dart'; +import '../services/auth/auth_service.dart'; + +class CultureValuesFormPage extends StatefulWidget { + const CultureValuesFormPage({super.key, required this.isRegProcess}); + + final bool isRegProcess; + + @override + CultureValuesFormPageState createState() => CultureValuesFormPageState(); +} + +class CultureValuesFormPageState extends State { + Map selectedValueOptions = { + WorkValueOption.transparency: false, + WorkValueOption.innovation: false, + WorkValueOption.teamwork: false, + WorkValueOption.workLifeBalance: false, + }; + CultureOption? selectedCultureOption; + + final AuthService _authService = AuthService(); + + final int minWorkValueOption = 1; + final int maxWorkValueOption = 2; + + @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(() { + // Load WorkValue options + if (data != null) { + if (data[Constants.dbFieldUsersWorkValues] != null) { + for (var option in WorkValueOption.values) { + selectedValueOptions[option] = + data[Constants.dbFieldUsersWorkValues] + .contains(option.toString()); + } + } + // Load Culture option + if (data[Constants.dbFieldUsersCorpCulture] != null) { + selectedCultureOption = CultureOption.values.firstWhere( + (e) => e.toString() == data[Constants.dbFieldUsersCorpCulture], + ); + } + } + }); + } + } + + Future _saveDataToFirebase() async { + 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 + } + + bool isWorkValueSelected() { + int selectedCount = + selectedValueOptions.values.where((value) => value).length; + return selectedCount >= minWorkValueOption && + selectedCount <= maxWorkValueOption; + } + + void handleSubmit() { + if (!isWorkValueSelected()) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + 'Please select at least ${minWorkValueOption.toString()} and at most ${maxWorkValueOption.toString()} work life values.'), + )); + return; + } + if (selectedCultureOption == null) { + ScaffoldMessenger.of(context).showSnackBar(const SnackBar( + content: Text('Please select a corporate culture.'), + )); + 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( + children: [ + const Text( + 'Work life and corporate culture', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const Text( + 'What values are most important to you in your working environment?', + ), + ...WorkValueOption.values.map((option) { + return CheckboxListTile( + title: Text(option.displayName), + value: selectedValueOptions[option], + onChanged: (bool? value) { + setState(() { + int selectedCount = selectedValueOptions.values + .where((value) => value) + .length; + if (value == false || + selectedCount < maxWorkValueOption) { + selectedValueOptions[option] = value!; + } else if (value == true && + selectedCount >= maxWorkValueOption) { + ScaffoldMessenger.of(context) + .showSnackBar(const SnackBar( + content: Text( + 'You can only select a maximum of two values.', + ), + )); + } + }); + }, + ); + }), + const SizedBox(height: 40), + const Align( + alignment: Alignment.centerLeft, + child: Text('Which corporate culture suits you best?')), + DropdownButton( + hint: const Text('Choose a corporate culture'), + value: selectedCultureOption, + onChanged: (CultureOption? newValue) { + setState(() { + selectedCultureOption = newValue; + }); + }, + items: CultureOption.values.map((CultureOption option) { + return DropdownMenuItem( + value: option, + child: Text(option.displayName), + ); + }).toList(), + ), + const SizedBox(height: 20), + ElevatedButton( + onPressed: handleSubmit, + child: Text(widget.isRegProcess ? 'Save and continue' : 'Save'), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/user_vision_page.dart b/lib/pages/user_vision_page.dart index a854425..84bbe23 100644 --- a/lib/pages/user_vision_page.dart +++ b/lib/pages/user_vision_page.dart @@ -2,7 +2,7 @@ import "package:cloud_firestore/cloud_firestore.dart"; import "package:flutter/material.dart"; import "../constants.dart"; import "../enumerations.dart"; -import "registration_complete_page.dart"; +import "../forms/corporate_culture_form.dart"; import "../services/auth/auth_service.dart"; class MatchingForm extends StatefulWidget { @@ -82,7 +82,7 @@ class MatchingFormState extends State { void handleSubmit() { if (!isVisionSelected()) { ScaffoldMessenger.of(context).showSnackBar(const SnackBar( - content: Text('Please choose at least one long-term vision.'), + content: Text('Please select at least one long-term vision.'), )); return; } @@ -97,8 +97,12 @@ class MatchingFormState extends State { Navigator.push( context, MaterialPageRoute( - // TODO set following registration page HERE - builder: (context) => const RegistrationCompletePage(), + // + // set following registration page HERE + // + builder: (context) => CultureValuesFormPage( + isRegProcess: widget.isRegProcess, + ), ), ); } @@ -111,59 +115,59 @@ class MatchingFormState extends State { ), body: Padding( padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Vision and goals', - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - const Text('What is your long-term vision for a startup?'), - ...VisionOption.values.map((option) { - return CheckboxListTile( - title: Text(option.displayName), - value: selectedVisionOptions[option], - controlAffinity: ListTileControlAffinity.platform, - onChanged: (bool? value) { - if (value != null) { - setState(() { - selectedVisionOptions[option] = value; - }); - } - }, - ); - }), - const SizedBox(height: 40), - const Align( - alignment: Alignment.centerLeft, - child: Text( + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Vision and goals', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const Text('What is your long-term vision for a startup?'), + ...VisionOption.values.map((option) { + return CheckboxListTile( + title: Text(option.displayName), + value: selectedVisionOptions[option], + controlAffinity: ListTileControlAffinity.platform, + onChanged: (bool? value) { + if (value != null) { + setState(() { + selectedVisionOptions[option] = value; + }); + } + }, + ); + }), + const SizedBox(height: 40), + const Text( 'Availability and commitment', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), - ), - const Text( - 'How much time can you devote to the startup each week?', - ), - ...AvailabilityOption.values.map((option) { - return RadioListTile( - title: Text(option.displayName), - value: option, - groupValue: availability, - onChanged: (AvailabilityOption? value) { - setState(() { - availability = value; - }); - }, - ); - }), - const SizedBox(height: 20), - Center( - child: ElevatedButton( - onPressed: handleSubmit, - child: Text(widget.isRegProcess ? 'Save and continue' : 'Save'), + const Text( + 'How much time can you devote to the startup each week?', ), - ), - ], + ...AvailabilityOption.values.map((option) { + return RadioListTile( + title: Text(option.displayName), + value: option, + groupValue: availability, + onChanged: (AvailabilityOption? value) { + setState(() { + availability = value; + }); + }, + ); + }), + const SizedBox(height: 20), + Center( + child: ElevatedButton( + onPressed: handleSubmit, + child: + Text(widget.isRegProcess ? 'Save and continue' : 'Save'), + ), + ), + ], + ), ), ), );