First step of registration process
parent
bf20cbbd1f
commit
1cb7970982
|
@ -104,7 +104,7 @@ class MyDrawer extends StatelessWidget {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => const UserDataPage(),
|
builder: (context) => const UserDataPage(isRegProcess: false,),
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
enum Gender {
|
||||||
|
none,
|
||||||
|
male,
|
||||||
|
female,
|
||||||
|
divers,
|
||||||
|
}
|
||||||
|
|
||||||
enum SkillOption {
|
enum SkillOption {
|
||||||
product,
|
product,
|
||||||
finance,
|
finance,
|
||||||
|
|
|
@ -3,6 +3,7 @@ import '../../helper.dart';
|
||||||
|
|
||||||
class ProfileCategoryForm<T> extends StatefulWidget {
|
class ProfileCategoryForm<T> extends StatefulWidget {
|
||||||
final String title;
|
final String title;
|
||||||
|
final String header;
|
||||||
final String description;
|
final String description;
|
||||||
final List<T> options; // T to make it work with our different Enums
|
final List<T> options; // T to make it work with our different Enums
|
||||||
final int minSelections;
|
final int minSelections;
|
||||||
|
@ -15,6 +16,7 @@ class ProfileCategoryForm<T> extends StatefulWidget {
|
||||||
const ProfileCategoryForm({
|
const ProfileCategoryForm({
|
||||||
super.key,
|
super.key,
|
||||||
required this.title,
|
required this.title,
|
||||||
|
required this.header,
|
||||||
required this.description,
|
required this.description,
|
||||||
required this.options,
|
required this.options,
|
||||||
required this.minSelections,
|
required this.minSelections,
|
||||||
|
@ -51,17 +53,15 @@ class ProfileCategoryFormState<T> extends State<ProfileCategoryForm<T>> {
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'${widget.title}',
|
widget.header,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 18.0,
|
fontSize: 18.0,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16,),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(widget.description),
|
||||||
'${widget.description}',
|
const SizedBox(height: 16),
|
||||||
),
|
|
||||||
const SizedBox(height: 16,),
|
|
||||||
Wrap(
|
Wrap(
|
||||||
spacing: 8.0,
|
spacing: 8.0,
|
||||||
children: List.generate(widget.options.length, (index) {
|
children: List.generate(widget.options.length, (index) {
|
||||||
|
|
|
@ -6,12 +6,17 @@ import '../../services/auth/auth_service.dart';
|
||||||
import 'profile_category_form.dart';
|
import 'profile_category_form.dart';
|
||||||
|
|
||||||
class SkillsForm extends StatelessWidget {
|
class SkillsForm extends StatelessWidget {
|
||||||
SkillsForm({super.key, required this.skillsSought});
|
SkillsForm({
|
||||||
|
super.key,
|
||||||
|
required this.isRegProcess,
|
||||||
|
required this.skillsSought,
|
||||||
|
});
|
||||||
|
|
||||||
// get instance of firestore and auth
|
// get instance of firestore and auth
|
||||||
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
|
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
|
||||||
final AuthService _authService = AuthService();
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
|
final bool isRegProcess;
|
||||||
final bool skillsSought; // flag to toggle offered and sought skills
|
final bool skillsSought; // flag to toggle offered and sought skills
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -28,18 +33,42 @@ class SkillsForm extends StatelessWidget {
|
||||||
List<SkillOption>? userSkills = snapshot.data;
|
List<SkillOption>? userSkills = snapshot.data;
|
||||||
return ProfileCategoryForm(
|
return ProfileCategoryForm(
|
||||||
title: 'Skills',
|
title: 'Skills',
|
||||||
|
header:
|
||||||
|
skillsSought ? 'Skills you are looking for' : 'Your own skills',
|
||||||
description: skillsSought
|
description: skillsSought
|
||||||
? 'Choose up to 3 areas you are looking for in a cofounder'
|
? 'Choose up to 3 areas you are looking for in a co-founder'
|
||||||
: 'Select up to 3 areas in which you are skilled',
|
: 'Select up to 3 areas in which you are skilled',
|
||||||
|
saveButtonText: isRegProcess ? 'Save and continue' : 'Save',
|
||||||
options: SkillOption.values.toList(), // Convert enum values to list
|
options: SkillOption.values.toList(), // Convert enum values to list
|
||||||
minSelections: 1,
|
minSelections: 1,
|
||||||
maxSelections: 3,
|
maxSelections: 3,
|
||||||
preSelectedOptions:
|
preSelectedOptions:
|
||||||
userSkills ?? [], // Pass pre-selected skills to the form
|
userSkills ?? [], // Pass pre-selected skills to the form
|
||||||
onSave: (selectedOptions) {
|
onSave: (selectedOptions) async {
|
||||||
// Handle saving selected options
|
// Handle saving selected options
|
||||||
saveSkillsToFirebase(selectedOptions.cast<SkillOption>());
|
bool success = await saveSkillsToFirebase(
|
||||||
|
selectedOptions.cast<SkillOption>());
|
||||||
|
|
||||||
// Then navigate to another screen or perform any other action???
|
// Then navigate to another screen or perform any other action???
|
||||||
|
if (context.mounted) {
|
||||||
|
if (success) {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => SkillsForm(
|
||||||
|
isRegProcess: isRegProcess,
|
||||||
|
skillsSought: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('Failed to save user skills.'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -80,28 +109,34 @@ class SkillsForm extends StatelessWidget {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveSkillsToFirebase(List<SkillOption> selectedOptions) {
|
Future<bool> saveSkillsToFirebase(List<SkillOption> selectedOptions) async {
|
||||||
String currentUserId = _authService.getCurrentUser()!.uid;
|
try {
|
||||||
|
String currentUserId = _authService.getCurrentUser()!.uid;
|
||||||
|
|
||||||
// Convert enum values to strings, removing leading EnumType with split
|
// Convert enum values to strings, removing leading EnumType with split
|
||||||
List<String> skills = selectedOptions
|
List<String> skills = selectedOptions
|
||||||
.map((option) => option.toString().split('.').last)
|
.map((option) => option.toString().split('.').last)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
// Update the corresponding 'skills' field in the user's document
|
// Update the corresponding 'skills' field in the user's document
|
||||||
String keyToUpdate = skillsSought
|
String keyToUpdate = skillsSought
|
||||||
? Constants.dbFieldUsersSkillsSought
|
? Constants.dbFieldUsersSkillsSought
|
||||||
: Constants.dbFieldUsersSkills;
|
: Constants.dbFieldUsersSkills;
|
||||||
|
|
||||||
_firestore
|
_firestore
|
||||||
.collection(Constants.dbCollectionUsers)
|
.collection(Constants.dbCollectionUsers)
|
||||||
.doc(currentUserId)
|
.doc(currentUserId)
|
||||||
.update({
|
.update({
|
||||||
keyToUpdate: skills,
|
keyToUpdate: skills,
|
||||||
}).then((_) {
|
}).then((_) {
|
||||||
print('$keyToUpdate saved to Firebase: $skills');
|
print('$keyToUpdate saved to Firebase: $skills');
|
||||||
}).catchError((error) {
|
}).catchError((error) {
|
||||||
print('Failed to save $keyToUpdate: $error');
|
print('Failed to save $keyToUpdate: $error');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,28 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import '../components/my_button.dart';
|
|
||||||
import '../constants.dart';
|
|
||||||
import '../models/language.dart';
|
|
||||||
import '../models/language_setting.dart';
|
|
||||||
import '../components/location_dialog.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import '../services/auth/auth_service.dart';
|
import '../components/location_dialog.dart';
|
||||||
|
import '../components/my_button.dart';
|
||||||
|
import '../components/my_drawer.dart';
|
||||||
|
import '../constants.dart';
|
||||||
|
import '../enumerations.dart';
|
||||||
|
import '../forms/skills_form.dart';
|
||||||
|
import '../models/language.dart';
|
||||||
|
import '../models/language_setting.dart';
|
||||||
import '../models/location.dart';
|
import '../models/location.dart';
|
||||||
|
import '../services/auth/auth_service.dart';
|
||||||
|
|
||||||
class UserDataPage extends StatefulWidget {
|
class UserDataPage extends StatefulWidget {
|
||||||
const UserDataPage({super.key});
|
final bool isRegProcess;
|
||||||
|
|
||||||
|
const UserDataPage({super.key, required this.isRegProcess});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<UserDataPage> createState() => _UserDataPageState();
|
State<UserDataPage> createState() => _UserDataPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Gender { none, male, female, divers }
|
|
||||||
|
|
||||||
class _UserDataPageState extends State<UserDataPage> {
|
class _UserDataPageState extends State<UserDataPage> {
|
||||||
MyLocation? _mainLocation;
|
MyLocation? _mainLocation;
|
||||||
MyLocation? _secondaryLocation;
|
MyLocation? _secondaryLocation;
|
||||||
|
@ -129,7 +132,7 @@ class _UserDataPageState extends State<UserDataPage> {
|
||||||
// Load data from JSON file when the widget initializes
|
// Load data from JSON file when the widget initializes
|
||||||
loadLanguagesFromJson();
|
loadLanguagesFromJson();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
print("Error fetching settings: $error");
|
_showSnackBar("Error fetching settings: $error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,103 +167,99 @@ class _UserDataPageState extends State<UserDataPage> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveUserData(BuildContext context) async {
|
Future<bool> saveUserData(BuildContext context) async {
|
||||||
// Get userID from auth service
|
try {
|
||||||
String currentUserID = _authService.getCurrentUser()!.uid;
|
// Get userID from auth service
|
||||||
|
String currentUserID = _authService.getCurrentUser()!.uid;
|
||||||
|
|
||||||
// Get references to the current users Firebase collections
|
// Get references to the current users Firebase collections
|
||||||
DocumentReference userRef =
|
DocumentReference userRef =
|
||||||
_firestore.collection(Constants.dbCollectionUsers).doc(currentUserID);
|
_firestore.collection(Constants.dbCollectionUsers).doc(currentUserID);
|
||||||
CollectionReference languagesRef =
|
CollectionReference languagesRef =
|
||||||
userRef.collection(Constants.dbCollectionLanguages);
|
userRef.collection(Constants.dbCollectionLanguages);
|
||||||
CollectionReference locationsRef =
|
CollectionReference locationsRef =
|
||||||
userRef.collection(Constants.dbCollectionLocations);
|
userRef.collection(Constants.dbCollectionLocations);
|
||||||
|
|
||||||
if (_selectedYear != _yearFromDb) {
|
if (_selectedYear != _yearFromDb) {
|
||||||
await userRef.update(
|
await userRef.update(
|
||||||
{'born': _selectedYear},
|
{'born': _selectedYear},
|
||||||
);
|
);
|
||||||
// update local value
|
// update local value
|
||||||
_yearFromDb = _selectedYear;
|
_yearFromDb = _selectedYear;
|
||||||
} else {
|
|
||||||
print("birth year did NOT change");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Gender in database - only if value has changed
|
|
||||||
if (_genderFromDb != genderView.index) {
|
|
||||||
await userRef.update(
|
|
||||||
{'gender': genderView.index},
|
|
||||||
);
|
|
||||||
// update local value
|
|
||||||
_genderFromDb = genderView.index;
|
|
||||||
} else {
|
|
||||||
print("gender did NOT change");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save locations
|
|
||||||
if (_mainLocation != _mainLocationFromDb) {
|
|
||||||
if (_mainLocation != null) {
|
|
||||||
// Update existing user document with new locations
|
|
||||||
await locationsRef
|
|
||||||
.doc(Constants.dbDocMainLocation)
|
|
||||||
.set(_mainLocation!.toMap());
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
print("main location did NOT change");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_secondaryLocation != _secondaryLocationFromDb) {
|
// Update Gender in database - only if value has changed
|
||||||
if (_secondaryLocation != null) {
|
if (_genderFromDb != genderView.index) {
|
||||||
await locationsRef
|
await userRef.update(
|
||||||
.doc(Constants.dbDocSecondLocation)
|
{'gender': genderView.index},
|
||||||
.set(_secondaryLocation!.toMap())
|
);
|
||||||
.then((value) => {
|
// update local value
|
||||||
print("Document secondary location updated"),
|
_genderFromDb = genderView.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save locations
|
||||||
|
if (_mainLocation != _mainLocationFromDb) {
|
||||||
|
if (_mainLocation != null) {
|
||||||
|
// Update existing user document with new locations
|
||||||
|
await locationsRef
|
||||||
|
.doc(Constants.dbDocMainLocation)
|
||||||
|
.set(_mainLocation!.toMap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_secondaryLocation != _secondaryLocationFromDb) {
|
||||||
|
if (_secondaryLocation != null) {
|
||||||
|
await locationsRef
|
||||||
|
.doc(Constants.dbDocSecondLocation)
|
||||||
|
.set(_secondaryLocation!.toMap())
|
||||||
|
.then((value) => {
|
||||||
|
// update local values
|
||||||
|
_secondaryLocationFromDb = _secondaryLocation,
|
||||||
|
_secondLocationExists = true
|
||||||
|
});
|
||||||
|
} else if (_secondLocationExists) {
|
||||||
|
// secondLocationExists but is null here -> delete secondary in DB
|
||||||
|
await locationsRef.doc(Constants.dbDocSecondLocation).delete().then(
|
||||||
|
(doc) => {
|
||||||
// update local values
|
// update local values
|
||||||
_secondaryLocationFromDb = _secondaryLocation,
|
_secondaryLocationFromDb = null,
|
||||||
_secondLocationExists = true
|
_secondLocationExists = false
|
||||||
});
|
},
|
||||||
} else if (_secondLocationExists) {
|
onError: (e) => _showSnackBar("Error updating document: $e"),
|
||||||
// secondLocationExists but is null here -> delete secondary in DB
|
);
|
||||||
await locationsRef.doc(Constants.dbDocSecondLocation).delete().then(
|
}
|
||||||
(doc) => {
|
|
||||||
print("Document secondary location deleted"),
|
|
||||||
// update local values
|
|
||||||
_secondaryLocationFromDb = null,
|
|
||||||
_secondLocationExists = false
|
|
||||||
},
|
|
||||||
onError: (e) => print("Error updating document $e"),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
print("secondary location did NOT change");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save Languages - only if selected values changed
|
// Save Languages - only if selected values changed
|
||||||
if (_selectedLanguages.isEmpty) {
|
if (_selectedLanguages.isEmpty) {
|
||||||
print("no language selected");
|
_showSnackBar("No language selected");
|
||||||
} else if (_languagesFromDb.length != _selectedLanguages.length ||
|
return false;
|
||||||
_selectedLanguages
|
} else if (_languagesFromDb.length != _selectedLanguages.length ||
|
||||||
.any((element) => !_languagesFromDb.contains(element))) {
|
_selectedLanguages
|
||||||
// Loop through each Language object and save it to the collection
|
.any((element) => !_languagesFromDb.contains(element))) {
|
||||||
for (int i = 0; i < _selectedLanguages.length; i++) {
|
// Loop through each Language object and save it to the collection
|
||||||
// Convert Language object to a map and add the map to the collection,
|
for (int i = 0; i < _selectedLanguages.length; i++) {
|
||||||
// using .doc(myID).set() instead of .add() to avoid duplicates.
|
// Convert Language object to a map and add the map to the collection,
|
||||||
await languagesRef
|
// using .doc(myID).set() instead of .add() to avoid duplicates.
|
||||||
.doc(_selectedLanguages[i].code)
|
await languagesRef
|
||||||
.set(_selectedLanguages[i].toMap());
|
.doc(_selectedLanguages[i].code)
|
||||||
|
.set(_selectedLanguages[i].toMap());
|
||||||
|
}
|
||||||
|
// update local variable (only if selection is not empty)
|
||||||
|
_languagesFromDb.clear();
|
||||||
|
_languagesFromDb.addAll(_selectedLanguages);
|
||||||
|
|
||||||
|
// List to store language codes from the provided list
|
||||||
|
List<String> languageCodes =
|
||||||
|
_selectedLanguages.map((language) => language.code).toList();
|
||||||
|
// Clean up languages that were not part of the provided list
|
||||||
|
await deleteUnusedDocuments(languagesRef, languageCodes);
|
||||||
}
|
}
|
||||||
// update local variable (only if selection is not empty)
|
|
||||||
_languagesFromDb.clear();
|
|
||||||
_languagesFromDb.addAll(_selectedLanguages);
|
|
||||||
|
|
||||||
// List to store language codes from the provided list
|
return true;
|
||||||
List<String> languageCodes =
|
} catch (e) {
|
||||||
_selectedLanguages.map((language) => language.code).toList();
|
_showSnackBar(e.toString());
|
||||||
// Clean up languages that were not part of the provided list
|
return false;
|
||||||
await deleteUnusedDocuments(languagesRef, languageCodes);
|
|
||||||
} else {
|
|
||||||
print("languages did NOT change");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,141 +325,185 @@ class _UserDataPageState extends State<UserDataPage> {
|
||||||
title: const Text("User Data"),
|
title: const Text("User Data"),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
),
|
),
|
||||||
body: ListView(
|
drawer: const MyDrawer(),
|
||||||
children: [
|
body: Padding(
|
||||||
const Text(
|
padding: const EdgeInsets.all(16.0),
|
||||||
'Location',
|
child: ListView(
|
||||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
children: [
|
||||||
),
|
if (widget.isRegProcess) ...[
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 10),
|
||||||
// Display selected main location
|
const Text(
|
||||||
const Text(
|
'Please fill in the following fields to proceed with the registration process.',
|
||||||
'Main Location:',
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
),
|
||||||
),
|
const SizedBox(height: 20),
|
||||||
if (_mainLocation != null) ...[
|
const Divider(),
|
||||||
Text(_mainLocation!.toString()),
|
],
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
] else ...[
|
|
||||||
const Text('n/a'),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
],
|
|
||||||
// Button to set main location
|
|
||||||
Center(
|
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: () {
|
|
||||||
_showLocationDialog(true);
|
|
||||||
},
|
|
||||||
child: Text(_mainLocation != null
|
|
||||||
? 'Change Main Location'
|
|
||||||
: 'Set Main Location'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
// Display selected secondary location
|
|
||||||
if (_secondaryLocation != null) ...[
|
|
||||||
const Text(
|
const Text(
|
||||||
'Secondary Location:',
|
'Location',
|
||||||
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
// Display selected main location
|
||||||
|
const Text(
|
||||||
|
'Main Location:',
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
Text(_secondaryLocation!.toString()),
|
if (_mainLocation != null) ...[
|
||||||
const SizedBox(height: 10),
|
Text(_mainLocation!.toString()),
|
||||||
],
|
const SizedBox(height: 10),
|
||||||
if (_mainLocation != null) ...[
|
] else ...[
|
||||||
// Button to set secondary location
|
const Text('n/a'),
|
||||||
ElevatedButton(
|
const SizedBox(height: 10),
|
||||||
onPressed: () {
|
],
|
||||||
_showLocationDialog(false);
|
// Button to set main location
|
||||||
},
|
Center(
|
||||||
child: Text(_secondaryLocation != null
|
child: ElevatedButton(
|
||||||
? 'Change Secondary Location'
|
onPressed: () {
|
||||||
: 'Add Secondary Location'),
|
_showLocationDialog(true);
|
||||||
),
|
|
||||||
],
|
|
||||||
// Display selected secondary location or remove button
|
|
||||||
if (_secondaryLocation != null) ...[
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: _removeSecondaryLocation,
|
|
||||||
child: const Text('Remove Secondary Location'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
const Text(
|
|
||||||
'Age',
|
|
||||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
const Padding(padding: EdgeInsets.symmetric(horizontal: 8)),
|
|
||||||
Text(_selectedYear != null
|
|
||||||
? '${DateTime.now().year - (_selectedYear ?? 0)} years old'
|
|
||||||
: 'undefined'),
|
|
||||||
const SizedBox(width: 20),
|
|
||||||
DropdownMenu(
|
|
||||||
initialSelection: _selectedYear,
|
|
||||||
onSelected: (int? newValue) {
|
|
||||||
setState(() {
|
|
||||||
_selectedYear = newValue;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
dropdownMenuEntries: List.generate(50, (index) {
|
child: Text(_mainLocation != null
|
||||||
return DropdownMenuEntry<int>(
|
? 'Change Main Location'
|
||||||
value: DateTime.now().year - 16 - index,
|
: 'Set Main Location'),
|
||||||
label: '${DateTime.now().year - 16 - index}',
|
),
|
||||||
);
|
),
|
||||||
}),
|
const SizedBox(height: 20),
|
||||||
label: const Text('birth year'),
|
// Display selected secondary location
|
||||||
|
if (_secondaryLocation != null) ...[
|
||||||
|
const Text(
|
||||||
|
'Secondary Location:',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
Text(_secondaryLocation!.toString()),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
],
|
||||||
|
if (_mainLocation != null) ...[
|
||||||
|
// Button to set secondary location
|
||||||
|
Center(
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
_showLocationDialog(false);
|
||||||
|
},
|
||||||
|
child: Text(_secondaryLocation != null
|
||||||
|
? 'Change Secondary Location'
|
||||||
|
: 'Add Secondary Location'),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
// Display selected secondary location or remove button
|
||||||
const SizedBox(height: 20),
|
if (_secondaryLocation != null) ...[
|
||||||
Text(
|
Center(
|
||||||
'Gender (${genderView.name} selected)',
|
child: ElevatedButton(
|
||||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
onPressed: _removeSecondaryLocation,
|
||||||
),
|
child: const Text('Remove Secondary Location'),
|
||||||
Center(
|
),
|
||||||
child: SegmentedButton<Gender>(
|
|
||||||
style: SegmentedButton.styleFrom(
|
|
||||||
selectedBackgroundColor: Colors.blue,
|
|
||||||
),
|
),
|
||||||
segments: const <ButtonSegment<Gender>>[
|
],
|
||||||
ButtonSegment<Gender>(
|
const SizedBox(height: 20),
|
||||||
value: Gender.none,
|
const Text(
|
||||||
label: Text('none'),
|
'Age',
|
||||||
),
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
ButtonSegment<Gender>(
|
),
|
||||||
value: Gender.male,
|
Row(
|
||||||
label: Text('male'),
|
children: [
|
||||||
//icon: Icon(Icons.male_sharp),
|
const Padding(padding: EdgeInsets.symmetric(horizontal: 8)),
|
||||||
),
|
Text(_selectedYear != null
|
||||||
ButtonSegment<Gender>(
|
? '${DateTime.now().year - (_selectedYear ?? 0)} years old'
|
||||||
value: Gender.female,
|
: 'undefined age'),
|
||||||
label: Text('female'),
|
const SizedBox(width: 20),
|
||||||
//icon: Icon(Icons.female_sharp),
|
DropdownMenu(
|
||||||
),
|
initialSelection: _selectedYear,
|
||||||
ButtonSegment<Gender>(
|
onSelected: (int? newValue) {
|
||||||
value: Gender.divers,
|
setState(() {
|
||||||
label: Text('divers'),
|
_selectedYear = newValue;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
dropdownMenuEntries: List.generate(50, (index) {
|
||||||
|
return DropdownMenuEntry<int>(
|
||||||
|
value: DateTime.now().year - 16 - index,
|
||||||
|
label: '${DateTime.now().year - 16 - index}',
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
label: const Text('birth year'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
selected: <Gender>{genderView},
|
|
||||||
showSelectedIcon: false,
|
|
||||||
onSelectionChanged: updateSelectedGender,
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 20),
|
||||||
const SizedBox(height: 20),
|
Text(
|
||||||
const Divider(),
|
'Gender (${genderView.name} selected)',
|
||||||
Text(
|
style:
|
||||||
'Language: (${_selectedLanguages.length} selected)',
|
const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
),
|
||||||
),
|
Center(
|
||||||
...languagesList.map(buildSingleCheckbox), // ... spread operator
|
child: SegmentedButton<Gender>(
|
||||||
const Divider(),
|
style: SegmentedButton.styleFrom(
|
||||||
Padding(
|
selectedBackgroundColor: Colors.blue,
|
||||||
padding: const EdgeInsets.all(8.0),
|
),
|
||||||
child: MyButton(text: "Save", onTap: () => saveUserData(context)),
|
segments: const <ButtonSegment<Gender>>[
|
||||||
)
|
ButtonSegment<Gender>(
|
||||||
],
|
value: Gender.none,
|
||||||
|
label: Text('none'),
|
||||||
|
),
|
||||||
|
ButtonSegment<Gender>(
|
||||||
|
value: Gender.male,
|
||||||
|
label: Text('male'),
|
||||||
|
//icon: Icon(Icons.male_sharp),
|
||||||
|
),
|
||||||
|
ButtonSegment<Gender>(
|
||||||
|
value: Gender.female,
|
||||||
|
label: Text('female'),
|
||||||
|
//icon: Icon(Icons.female_sharp),
|
||||||
|
),
|
||||||
|
ButtonSegment<Gender>(
|
||||||
|
value: Gender.divers,
|
||||||
|
label: Text('divers'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
selected: <Gender>{genderView},
|
||||||
|
showSelectedIcon: false,
|
||||||
|
onSelectionChanged: updateSelectedGender,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
const Divider(),
|
||||||
|
Text(
|
||||||
|
'Language: (${_selectedLanguages.length} selected)',
|
||||||
|
style:
|
||||||
|
const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
...languagesList.map(buildSingleCheckbox), // ... spread operator
|
||||||
|
const Divider(),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: MyButton(
|
||||||
|
text: widget.isRegProcess ? 'Save and continue' : "Save",
|
||||||
|
onTap: () async {
|
||||||
|
bool success = await saveUserData(context);
|
||||||
|
if (context.mounted) {
|
||||||
|
if (success) {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => SkillsForm(
|
||||||
|
isRegProcess: widget.isRegProcess,
|
||||||
|
skillsSought: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('Failed to save user data.'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -508,4 +551,19 @@ class _UserDataPageState extends State<UserDataPage> {
|
||||||
onChanged: (value) => onClicked(),
|
onChanged: (value) => onClicked(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void _showSnackBar(String message) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(message),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
action: SnackBarAction(
|
||||||
|
label: 'Dismiss',
|
||||||
|
onPressed: () {
|
||||||
|
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:cofounderella/services/auth/login_or_register.dart';
|
import 'auth_service.dart';
|
||||||
import 'package:cofounderella/pages/home_page.dart';
|
import 'login_or_register.dart';
|
||||||
|
import '../../constants.dart';
|
||||||
|
import '../../pages/home_page.dart';
|
||||||
|
import '../../pages/user_data_page.dart';
|
||||||
|
|
||||||
class AuthGate extends StatelessWidget{
|
class AuthGate extends StatelessWidget {
|
||||||
const AuthGate({super.key});
|
const AuthGate({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -11,17 +15,48 @@ class AuthGate extends StatelessWidget{
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: StreamBuilder(
|
body: StreamBuilder(
|
||||||
stream: FirebaseAuth.instance.authStateChanges(),
|
stream: FirebaseAuth.instance.authStateChanges(),
|
||||||
builder: (context, snapshot){
|
builder: (context, snapshot) {
|
||||||
|
|
||||||
// check if user is logged in or not
|
// check if user is logged in or not
|
||||||
if(snapshot.hasData){
|
if (snapshot.hasData) {
|
||||||
return HomePage();
|
return FutureBuilder(
|
||||||
}
|
// check database entries, if data is missing
|
||||||
else {
|
// then complete registration process
|
||||||
|
// else go to HomePage
|
||||||
|
future: _checkCollectionsExist(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
return const CircularProgressIndicator();
|
||||||
|
} else if (snapshot.hasData && snapshot.data == true) {
|
||||||
|
return HomePage();
|
||||||
|
} else {
|
||||||
|
// also in case (snapshot.hasError)
|
||||||
|
return const UserDataPage(isRegProcess: true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
return const LoginOrRegister();
|
return const LoginOrRegister();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
Future<bool> _checkCollectionsExist() async {
|
||||||
|
bool languagesExist =
|
||||||
|
await _checkUsersCollectionExists(Constants.dbCollectionLanguages);
|
||||||
|
bool locationsExist =
|
||||||
|
await _checkUsersCollectionExists(Constants.dbCollectionLocations);
|
||||||
|
return languagesExist && locationsExist;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _checkUsersCollectionExists(String collectionName) async {
|
||||||
|
String currentUserId = AuthService().getCurrentUser()!.uid;
|
||||||
|
final collection = FirebaseFirestore.instance
|
||||||
|
.collection(Constants.dbCollectionUsers)
|
||||||
|
.doc(currentUserId)
|
||||||
|
.collection(collectionName);
|
||||||
|
final snapshot = await collection.limit(1).get();
|
||||||
|
return snapshot.docs.isNotEmpty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue