Registration: availability and vision
parent
0c0bf431e2
commit
017cf363d4
|
@ -18,6 +18,8 @@ class Constants {
|
|||
static const String dbFieldUsersYearBorn = 'born';
|
||||
static const String dbFieldUsersSkills = 'skills';
|
||||
static const String dbFieldUsersSkillsSought = 'skills_sought';
|
||||
static const String dbFieldUsersAvailability = 'availability';
|
||||
static const String dbFieldUsersVisions = 'visions';
|
||||
|
||||
static const String pathLanguagesJson = 'lib/assets/languages.json';
|
||||
}
|
||||
|
|
|
@ -36,3 +36,43 @@ enum SkillOption {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum VisionOption {
|
||||
marketLeader,
|
||||
sustainableBusiness,
|
||||
innovativeProduct,
|
||||
exitStrategy;
|
||||
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case VisionOption.marketLeader:
|
||||
return 'Become market leader';
|
||||
case VisionOption.sustainableBusiness:
|
||||
return 'Build a sustainable and ethical business';
|
||||
case VisionOption.innovativeProduct:
|
||||
return "Develop an innovative product that improves people's lives";
|
||||
case VisionOption.exitStrategy:
|
||||
return 'Pursue an exit strategy through sale or IPO';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum AvailabilityOption {
|
||||
lessThan10Hours,
|
||||
tenTo20Hours,
|
||||
twentyTo40Hours,
|
||||
fullTime;
|
||||
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case AvailabilityOption.lessThan10Hours:
|
||||
return 'Less than 10 hours';
|
||||
case AvailabilityOption.tenTo20Hours:
|
||||
return 'Part time (10 - 20 hours)';
|
||||
case AvailabilityOption.twentyTo40Hours:
|
||||
return 'Part time (20 - 40 hours)';
|
||||
case AvailabilityOption.fullTime:
|
||||
return 'Full time (40 hours or more)';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import '../helper.dart';
|
||||
|
||||
class ProfileCategoryForm<T> extends StatefulWidget {
|
||||
final String title;
|
||||
|
@ -66,7 +67,7 @@ class ProfileCategoryFormState<T> extends State<ProfileCategoryForm<T>> {
|
|||
children: List.generate(widget.options.length, (index) {
|
||||
final option = widget.options[index];
|
||||
return ChoiceChip(
|
||||
label: Text(_getDisplayText(option)),
|
||||
label: Text(getDisplayText(option)),
|
||||
selected: _selectedOptions.contains(option),
|
||||
onSelected: (selected) {
|
||||
setState(() {
|
||||
|
@ -110,18 +111,6 @@ class ProfileCategoryFormState<T> extends State<ProfileCategoryForm<T>> {
|
|||
);
|
||||
}
|
||||
|
||||
String _getDisplayText(dynamic option) {
|
||||
// Check if the option is an enum and has a displayName property
|
||||
if (option is Enum) {
|
||||
final dynamicEnum = option as dynamic;
|
||||
if (dynamicEnum.displayName != null) {
|
||||
return dynamicEnum.displayName;
|
||||
}
|
||||
}
|
||||
// Fallback to default toString if not an enum
|
||||
return option.toString().split('.').last;
|
||||
}
|
||||
|
||||
void _showSnackBar(String message) {
|
||||
if (!_isSnackBarVisible) {
|
||||
_isSnackBarVisible = true;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:cofounderella/pages/user_vision_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../enumerations.dart';
|
||||
import '../../services/auth/auth_service.dart';
|
||||
import '../../services/user_service.dart';
|
||||
import '../pages/registration_complete_page.dart';
|
||||
import 'profile_category_form.dart';
|
||||
|
||||
class SkillsForm extends StatelessWidget {
|
||||
|
@ -62,8 +62,8 @@ class SkillsForm extends StatelessWidget {
|
|||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
// TODO set following registration page HERE
|
||||
builder: (context) => const RegistrationCompletePage(),
|
||||
// set following registration page HERE
|
||||
builder: (context) => MatchingForm(isRegProcess: isRegProcess),
|
||||
),
|
||||
);
|
||||
} else if (isRegProcess) {
|
||||
|
|
|
@ -29,6 +29,21 @@ String convertDecimalToDMS(double decimalValue) {
|
|||
return '${degrees.abs()}° ${minutes.abs()}\' ${seconds.abs()}" $direction';
|
||||
}
|
||||
|
||||
///
|
||||
/// Get the displayName of our own Enumerations.
|
||||
///
|
||||
String getDisplayText(dynamic option) {
|
||||
// Check if the option is an enum and has a displayName property
|
||||
if (option is Enum) {
|
||||
final dynamicEnum = option as dynamic;
|
||||
if (dynamicEnum.displayName != null) {
|
||||
return dynamicEnum.displayName;
|
||||
}
|
||||
}
|
||||
// Fallback to default toString if not an enum
|
||||
return option.toString().split('.').last;
|
||||
}
|
||||
|
||||
///
|
||||
/// Show a simple message dialog
|
||||
///
|
||||
|
|
|
@ -27,7 +27,7 @@ class RegistrationCompletePage extends StatelessWidget {
|
|||
),
|
||||
const SizedBox(height: 80),
|
||||
const Text(
|
||||
"You can now use the app.",
|
||||
"You can enjoy the app now.",
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
import "package:cloud_firestore/cloud_firestore.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "../constants.dart";
|
||||
import "../enumerations.dart";
|
||||
import "registration_complete_page.dart";
|
||||
import "../services/auth/auth_service.dart";
|
||||
|
||||
class MatchingForm extends StatefulWidget {
|
||||
const MatchingForm({super.key, required this.isRegProcess});
|
||||
|
||||
final bool isRegProcess;
|
||||
|
||||
@override
|
||||
MatchingFormState createState() => MatchingFormState();
|
||||
}
|
||||
|
||||
class MatchingFormState extends State<MatchingForm> {
|
||||
Map<VisionOption, bool> selectedVisionOptions = {
|
||||
VisionOption.marketLeader: false,
|
||||
VisionOption.sustainableBusiness: false,
|
||||
VisionOption.innovativeProduct: false,
|
||||
VisionOption.exitStrategy: false,
|
||||
};
|
||||
AvailabilityOption? availability;
|
||||
|
||||
// get instance of auth
|
||||
final AuthService _authService = AuthService();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadDataFromFirebase();
|
||||
}
|
||||
|
||||
Future<void> _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 Vision options
|
||||
if (data?[Constants.dbFieldUsersVisions] != null) {
|
||||
for (var option in VisionOption.values) {
|
||||
selectedVisionOptions[option] = data?[Constants.dbFieldUsersVisions]
|
||||
.contains(option.toString());
|
||||
}
|
||||
}
|
||||
// Load Availability option
|
||||
if (data?[Constants.dbFieldUsersAvailability] != null) {
|
||||
availability = AvailabilityOption.values.firstWhere(
|
||||
(e) => e.toString() == data?[Constants.dbFieldUsersAvailability],
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _saveDataToFirebase() async {
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
bool isVisionSelected() {
|
||||
return selectedVisionOptions.containsValue(true);
|
||||
}
|
||||
|
||||
void handleSubmit() {
|
||||
if (!isVisionSelected()) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||
content: Text('Please choose at least one long-term vision.'),
|
||||
));
|
||||
return;
|
||||
}
|
||||
if (availability == null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||
content: Text('Please select an availability option.'),
|
||||
));
|
||||
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: 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(
|
||||
'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'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue