Added Sectors of Interest and Save Button to AppBars.
parent
e79bfd5b7e
commit
87beb2dace
|
@ -54,6 +54,7 @@ class Constants {
|
||||||
static const String dbFieldUsersCorpCulture = 'corp_culture';
|
static const String dbFieldUsersCorpCulture = 'corp_culture';
|
||||||
static const String dbFieldUsersCommunication = 'communication';
|
static const String dbFieldUsersCommunication = 'communication';
|
||||||
static const String dbFieldUsersRiskTolerance = 'risk_tolerance';
|
static const String dbFieldUsersRiskTolerance = 'risk_tolerance';
|
||||||
|
static const String dbFieldUsersSectors = 'sectors_of_interest';
|
||||||
|
|
||||||
static const String dbStoragePathProfiles = 'profile_images';
|
static const String dbStoragePathProfiles = 'profile_images';
|
||||||
|
|
||||||
|
|
|
@ -252,3 +252,98 @@ enum RiskTolerance {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum SectorOption {
|
||||||
|
agriculture,
|
||||||
|
ai,
|
||||||
|
vr,
|
||||||
|
automotive,
|
||||||
|
bigdata,
|
||||||
|
blockchain,
|
||||||
|
cloud,
|
||||||
|
crypto,
|
||||||
|
cybersecurity,
|
||||||
|
education,
|
||||||
|
energy,
|
||||||
|
fashion,
|
||||||
|
finance,
|
||||||
|
food,
|
||||||
|
gaming,
|
||||||
|
healthcare,
|
||||||
|
home,
|
||||||
|
industry,
|
||||||
|
insurance,
|
||||||
|
iot,
|
||||||
|
legal,
|
||||||
|
ml,
|
||||||
|
media,
|
||||||
|
pharma,
|
||||||
|
retail,
|
||||||
|
robotics,
|
||||||
|
saas,
|
||||||
|
sports,
|
||||||
|
travel;
|
||||||
|
|
||||||
|
String get displayName {
|
||||||
|
switch (this) {
|
||||||
|
case SectorOption.agriculture:
|
||||||
|
return 'Agriculture';
|
||||||
|
case SectorOption.ai:
|
||||||
|
return 'Artificial Intelligence';
|
||||||
|
case SectorOption.vr:
|
||||||
|
return 'Augmented/Virtual Reality';
|
||||||
|
case SectorOption.automotive:
|
||||||
|
return 'Automotive';
|
||||||
|
case SectorOption.bigdata:
|
||||||
|
return 'Big Data';
|
||||||
|
case SectorOption.blockchain:
|
||||||
|
return 'Blockchain';
|
||||||
|
case SectorOption.cloud:
|
||||||
|
return 'Cloud Computing';
|
||||||
|
case SectorOption.crypto:
|
||||||
|
return 'Cryptocurrencies/Digital Assets';
|
||||||
|
case SectorOption.cybersecurity:
|
||||||
|
return 'Cybersecurity';
|
||||||
|
case SectorOption.education:
|
||||||
|
return 'Education';
|
||||||
|
case SectorOption.energy:
|
||||||
|
return 'Energy and Environment';
|
||||||
|
case SectorOption.fashion:
|
||||||
|
return 'Fashion and Lifestyle';
|
||||||
|
case SectorOption.finance:
|
||||||
|
return 'Finance';
|
||||||
|
case SectorOption.food:
|
||||||
|
return 'Food and Beverage';
|
||||||
|
case SectorOption.gaming:
|
||||||
|
return 'Gaming';
|
||||||
|
case SectorOption.healthcare:
|
||||||
|
return 'Healthcare';
|
||||||
|
case SectorOption.home:
|
||||||
|
return 'Home and Garden';
|
||||||
|
case SectorOption.industry:
|
||||||
|
return 'Industry';
|
||||||
|
case SectorOption.insurance:
|
||||||
|
return 'Insurance';
|
||||||
|
case SectorOption.iot:
|
||||||
|
return 'Internet of Things';
|
||||||
|
case SectorOption.legal:
|
||||||
|
return 'Legal and Compliance';
|
||||||
|
case SectorOption.ml:
|
||||||
|
return 'Machine Learning';
|
||||||
|
case SectorOption.media:
|
||||||
|
return 'Media and Entertainment';
|
||||||
|
case SectorOption.pharma:
|
||||||
|
return 'Pharma';
|
||||||
|
case SectorOption.retail:
|
||||||
|
return 'Retail';
|
||||||
|
case SectorOption.robotics:
|
||||||
|
return 'Robotics';
|
||||||
|
case SectorOption.saas:
|
||||||
|
return 'SaaS';
|
||||||
|
case SectorOption.sports:
|
||||||
|
return 'Sports and Fitness';
|
||||||
|
case SectorOption.travel:
|
||||||
|
return 'Travel';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -151,6 +151,13 @@ class CultureValuesFormPageState extends State<CultureValuesFormPage> {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Personal preferences'),
|
title: const Text('Personal preferences'),
|
||||||
|
actions: [
|
||||||
|
if (widget.isEditMode && !widget.isRegProcess)
|
||||||
|
IconButton(
|
||||||
|
onPressed: handleSubmit,
|
||||||
|
icon: const Icon(Icons.save),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
|
|
@ -25,7 +25,7 @@ class ProfileCategoryForm<T> extends StatefulWidget {
|
||||||
required this.onSave,
|
required this.onSave,
|
||||||
required this.preSelectedOptions,
|
required this.preSelectedOptions,
|
||||||
this.saveButtonText,
|
this.saveButtonText,
|
||||||
this.hideSaveButton = false, // Initialize hideSaveButton parameter
|
this.hideSaveButton = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -47,6 +47,13 @@ class ProfileCategoryFormState<T> extends State<ProfileCategoryForm<T>> {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(widget.title),
|
title: Text(widget.title),
|
||||||
|
actions: [
|
||||||
|
if (!widget.hideSaveButton)
|
||||||
|
IconButton(
|
||||||
|
onPressed: _saveButtonClicked,
|
||||||
|
icon: const Icon(Icons.save),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
@ -70,9 +77,9 @@ class ProfileCategoryFormState<T> extends State<ProfileCategoryForm<T>> {
|
||||||
if (_selectedOptions.length < widget.maxSelections) {
|
if (_selectedOptions.length < widget.maxSelections) {
|
||||||
_selectedOptions.add(option);
|
_selectedOptions.add(option);
|
||||||
} else {
|
} else {
|
||||||
// Provide feedback that maximum selections reached
|
|
||||||
_showSnackBar(
|
_showSnackBar(
|
||||||
'Maximum selections reached for ${widget.title}');
|
'Maximum selections reached for ${widget.title}',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_selectedOptions.remove(option);
|
_selectedOptions.remove(option);
|
||||||
|
@ -85,13 +92,7 @@ class ProfileCategoryFormState<T> extends State<ProfileCategoryForm<T>> {
|
||||||
const SizedBox(height: 16.0),
|
const SizedBox(height: 16.0),
|
||||||
if (!widget.hideSaveButton)
|
if (!widget.hideSaveButton)
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: _saveButtonClicked,
|
||||||
if (_selectedOptions.length >= widget.minSelections) {
|
|
||||||
widget.onSave(_selectedOptions);
|
|
||||||
} else {
|
|
||||||
_showSnackBar('No selection made for ${widget.title}');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text(widget.saveButtonText ?? 'Save'),
|
child: Text(widget.saveButtonText ?? 'Save'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -100,6 +101,14 @@ class ProfileCategoryFormState<T> extends State<ProfileCategoryForm<T>> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _saveButtonClicked() {
|
||||||
|
if (_selectedOptions.length >= widget.minSelections) {
|
||||||
|
widget.onSave(_selectedOptions);
|
||||||
|
} else {
|
||||||
|
_showSnackBar('No selection made for ${widget.title}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _showSnackBar(String message) {
|
void _showSnackBar(String message) {
|
||||||
if (!_isSnackBarVisible) {
|
if (!_isSnackBarVisible) {
|
||||||
_isSnackBarVisible = true;
|
_isSnackBarVisible = true;
|
||||||
|
|
|
@ -129,6 +129,13 @@ class RisksFormPageState extends State<RisksFormPage> {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Personal preferences'),
|
title: const Text('Personal preferences'),
|
||||||
|
actions: [
|
||||||
|
if (widget.isEditMode && !widget.isRegProcess)
|
||||||
|
IconButton(
|
||||||
|
onPressed: handleSubmit,
|
||||||
|
icon: const Icon(Icons.save),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../../enumerations.dart';
|
||||||
|
import '../../services/auth/auth_service.dart';
|
||||||
|
import '../../services/user_service.dart';
|
||||||
|
import '../constants.dart';
|
||||||
|
import '../pages/user_vision_page.dart';
|
||||||
|
import 'profile_category_form.dart';
|
||||||
|
|
||||||
|
class SectorsForm extends StatelessWidget {
|
||||||
|
SectorsForm({
|
||||||
|
super.key,
|
||||||
|
required this.isRegProcess,
|
||||||
|
required this.isEditMode,
|
||||||
|
});
|
||||||
|
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
|
final bool isRegProcess;
|
||||||
|
final bool isEditMode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FutureBuilder<List<SectorOption>>(
|
||||||
|
future: UserService.getSectorsFromFirebase(
|
||||||
|
_authService.getCurrentUser()!.uid,
|
||||||
|
),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
return const CircularProgressIndicator();
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
return Text('Error: ${snapshot.error}');
|
||||||
|
} else {
|
||||||
|
List<SectorOption>? userSectors = snapshot.data;
|
||||||
|
int max = 10;
|
||||||
|
return ProfileCategoryForm(
|
||||||
|
title: 'Sectors of interest',
|
||||||
|
header: 'Sectors of interest',
|
||||||
|
description: 'Select up to $max sectors that match your interests.',
|
||||||
|
saveButtonText: isRegProcess ? 'Save and continue' : 'Save',
|
||||||
|
options: SectorOption.values.toList(), // Convert enum to list
|
||||||
|
minSelections: 1,
|
||||||
|
maxSelections: max,
|
||||||
|
preSelectedOptions: userSectors ?? [],
|
||||||
|
onSave: (selectedOptions) async {
|
||||||
|
// Handle saving selected options
|
||||||
|
bool success = await UserService.saveSectorsToFirebase(
|
||||||
|
selectedOptions.cast<SectorOption>(),
|
||||||
|
_authService.getCurrentUser()!.uid,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
if (success) {
|
||||||
|
if (isRegProcess) {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
// set following registration page HERE
|
||||||
|
builder: (context) => UserVisionPage(
|
||||||
|
isRegProcess: isRegProcess,
|
||||||
|
isEditMode: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (isEditMode == true) {
|
||||||
|
// pass selectedOptions data back to caller
|
||||||
|
Navigator.pop(context, {
|
||||||
|
Constants.dbFieldUsersSectors: selectedOptions,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Navigate back after saving
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('Failed to save sectors of interest.'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,8 +3,8 @@ import '../../enumerations.dart';
|
||||||
import '../../services/auth/auth_service.dart';
|
import '../../services/auth/auth_service.dart';
|
||||||
import '../../services/user_service.dart';
|
import '../../services/user_service.dart';
|
||||||
import '../constants.dart';
|
import '../constants.dart';
|
||||||
import '../pages/user_vision_page.dart';
|
|
||||||
import 'profile_category_form.dart';
|
import 'profile_category_form.dart';
|
||||||
|
import 'sectors_form.dart';
|
||||||
|
|
||||||
class SkillsForm extends StatelessWidget {
|
class SkillsForm extends StatelessWidget {
|
||||||
SkillsForm({
|
SkillsForm({
|
||||||
|
@ -14,7 +14,6 @@ class SkillsForm extends StatelessWidget {
|
||||||
required this.isEditMode,
|
required this.isEditMode,
|
||||||
});
|
});
|
||||||
|
|
||||||
// get instance of auth
|
|
||||||
final AuthService _authService = AuthService();
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
final bool isRegProcess;
|
final bool isRegProcess;
|
||||||
|
@ -27,7 +26,7 @@ class SkillsForm extends StatelessWidget {
|
||||||
future: UserService.getSkillsFromFirebase(
|
future: UserService.getSkillsFromFirebase(
|
||||||
skillsSought,
|
skillsSought,
|
||||||
_authService.getCurrentUser()!.uid,
|
_authService.getCurrentUser()!.uid,
|
||||||
), // Fetch skills from Firebase
|
),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
// Show loading indicator while fetching data
|
// Show loading indicator while fetching data
|
||||||
|
@ -58,7 +57,7 @@ class SkillsForm extends StatelessWidget {
|
||||||
_authService.getCurrentUser()!.uid,
|
_authService.getCurrentUser()!.uid,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Then navigate to another screen or perform any other action???
|
// Then navigate to another screen or perform any other action
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
if (success) {
|
if (success) {
|
||||||
if (isRegProcess && skillsSought) {
|
if (isRegProcess && skillsSought) {
|
||||||
|
@ -66,7 +65,7 @@ class SkillsForm extends StatelessWidget {
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
// set following registration page HERE
|
// set following registration page HERE
|
||||||
builder: (context) => UserVisionPage(
|
builder: (context) => SectorsForm(
|
||||||
isRegProcess: isRegProcess,
|
isRegProcess: isRegProcess,
|
||||||
isEditMode: false,
|
isEditMode: false,
|
||||||
),
|
),
|
||||||
|
|
|
@ -160,6 +160,12 @@ class EditProfilePageState extends State<EditProfilePage> {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Edit Profile'),
|
title: const Text('Edit Profile'),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: _saveProfile,
|
||||||
|
icon: const Icon(Icons.save),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
|
|
@ -149,6 +149,13 @@ class UserVisionPageState extends State<UserVisionPage> {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Personal preferences'),
|
title: const Text('Personal preferences'),
|
||||||
|
actions: [
|
||||||
|
if (widget.isEditMode && !widget.isRegProcess)
|
||||||
|
IconButton(
|
||||||
|
onPressed: handleSubmit,
|
||||||
|
icon: const Icon(Icons.save),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
|
|
@ -10,17 +10,16 @@ class WelcomePage extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(title: const Text('Welcome to ${Constants.appTitle}'),),
|
||||||
title: const Text('Start now'),
|
body: SafeArea(
|
||||||
),
|
child: Padding(
|
||||||
body: Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const TextBold(
|
const TextBold(
|
||||||
text: 'Welcome to ${Constants.appTitle}',
|
text: 'Connect with Potential Co-Founders Here',
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
@ -80,6 +79,7 @@ class WelcomePage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,4 +284,42 @@ class UserService {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<bool> saveSectorsToFirebase(
|
||||||
|
List<SectorOption> sectors, String userId) async {
|
||||||
|
try {
|
||||||
|
List<String> sectorStrings = sectors.map((x) => x.toString()).toList();
|
||||||
|
await FirebaseFirestore.instance
|
||||||
|
.collection(Constants.dbCollectionUsers)
|
||||||
|
.doc(userId)
|
||||||
|
.update({
|
||||||
|
Constants.dbFieldUsersSectors: sectorStrings,
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<List<SectorOption>> getSectorsFromFirebase(
|
||||||
|
String userId) async {
|
||||||
|
try {
|
||||||
|
DocumentSnapshot userDoc = await FirebaseFirestore.instance
|
||||||
|
.collection(Constants.dbCollectionUsers)
|
||||||
|
.doc(userId)
|
||||||
|
.get();
|
||||||
|
if (userDoc.exists && userDoc.data() != null) {
|
||||||
|
var data = userDoc.data() as Map<String, dynamic>;
|
||||||
|
List<dynamic> sectors = data[Constants.dbFieldUsersSectors] ?? [];
|
||||||
|
return sectors
|
||||||
|
.map((x) => SectorOption.values
|
||||||
|
.firstWhere((option) => option.toString() == x))
|
||||||
|
.toList();
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw Exception('Error fetching sectors from Firebase: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue