Some visual adjustments.
parent
94e78e91da
commit
9a7a8f9f39
|
@ -0,0 +1,42 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
|
||||||
|
import '../models/language.dart';
|
||||||
|
import '../utils/list_utils.dart';
|
||||||
|
|
||||||
|
class MyLanguageList extends StatelessWidget {
|
||||||
|
final List<Language> langList;
|
||||||
|
final double? iconHeight;
|
||||||
|
final double? textSize;
|
||||||
|
|
||||||
|
const MyLanguageList(
|
||||||
|
{super.key, required this.langList, this.iconHeight = 16, this.textSize});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<Language> sortedLanguages = sortLanguageList(langList);
|
||||||
|
|
||||||
|
return Wrap(
|
||||||
|
children: sortedLanguages.map(
|
||||||
|
(language) {
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(
|
||||||
|
language.iconFile,
|
||||||
|
height: iconHeight,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 4.0),
|
||||||
|
Text(
|
||||||
|
language.name,
|
||||||
|
style: TextStyle(fontSize: textSize),
|
||||||
|
),
|
||||||
|
// Space between each language icon pair
|
||||||
|
const SizedBox(width: 8.0),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import '../constants.dart';
|
||||||
import '../enumerations.dart';
|
import '../enumerations.dart';
|
||||||
import '../forms/risks_form.dart';
|
import '../forms/risks_form.dart';
|
||||||
import '../services/auth/auth_service.dart';
|
import '../services/auth/auth_service.dart';
|
||||||
|
import '../utils/helper_dialogs.dart';
|
||||||
|
|
||||||
class CultureValuesFormPage extends StatefulWidget {
|
class CultureValuesFormPage extends StatefulWidget {
|
||||||
const CultureValuesFormPage(
|
const CultureValuesFormPage(
|
||||||
|
@ -85,15 +86,13 @@ class CultureValuesFormPageState extends State<CultureValuesFormPage> {
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_showSnackBar(e.toString());
|
_showSnackBar('Error saving data: ${e.toString()}');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showSnackBar(String message) {
|
void _showSnackBar(String message) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
showErrorSnackBar(context, message);
|
||||||
content: Text(message),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isWorkValueSelected() {
|
bool isWorkValueSelected() {
|
||||||
|
@ -105,18 +104,12 @@ class CultureValuesFormPageState extends State<CultureValuesFormPage> {
|
||||||
|
|
||||||
Future<void> handleSubmit() async {
|
Future<void> handleSubmit() async {
|
||||||
if (!isWorkValueSelected()) {
|
if (!isWorkValueSelected()) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
_showSnackBar(
|
||||||
content: Text(
|
'Please select at least ${minWorkValueOption.toString()} and at most ${maxWorkValueOption.toString()} work life values.');
|
||||||
'Please select at least ${minWorkValueOption.toString()} and '
|
|
||||||
'at most ${maxWorkValueOption.toString()} work life values.',
|
|
||||||
),
|
|
||||||
));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (selectedCultureOption == null) {
|
if (selectedCultureOption == null) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
_showSnackBar('Please select a corporate culture.');
|
||||||
content: Text('Please select a corporate culture.'),
|
|
||||||
));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Handle the form submission logic here
|
// Handle the form submission logic here
|
||||||
|
@ -167,9 +160,29 @@ class CultureValuesFormPageState extends State<CultureValuesFormPage> {
|
||||||
'Work life and corporate culture',
|
'Work life and corporate culture',
|
||||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
const Text(
|
const Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text('Which corporate culture suits you best?'),
|
||||||
|
),
|
||||||
|
...CultureOption.values.map((option) {
|
||||||
|
return RadioListTile(
|
||||||
|
title: Text(option.displayName),
|
||||||
|
value: option,
|
||||||
|
groupValue: selectedCultureOption,
|
||||||
|
onChanged: (CultureOption? value) {
|
||||||
|
setState(() {
|
||||||
|
selectedCultureOption = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
const SizedBox(height: 40),
|
||||||
|
const Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
'What values are most important to you in your working environment?',
|
'What values are most important to you in your working environment?',
|
||||||
),
|
),
|
||||||
|
),
|
||||||
...WorkValueOption.values.map((option) {
|
...WorkValueOption.values.map((option) {
|
||||||
return CheckboxListTile(
|
return CheckboxListTile(
|
||||||
title: Text(option.displayName),
|
title: Text(option.displayName),
|
||||||
|
@ -184,36 +197,14 @@ class CultureValuesFormPageState extends State<CultureValuesFormPage> {
|
||||||
selectedValueOptions[option] = value!;
|
selectedValueOptions[option] = value!;
|
||||||
} else if (value == true &&
|
} else if (value == true &&
|
||||||
selectedCount >= maxWorkValueOption) {
|
selectedCount >= maxWorkValueOption) {
|
||||||
ScaffoldMessenger.of(context)
|
_showSnackBar(
|
||||||
.showSnackBar(const SnackBar(
|
|
||||||
content: Text(
|
|
||||||
'You can only select a maximum of two values.',
|
'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<CultureOption>(
|
|
||||||
hint: const Text('Choose a corporate culture'),
|
|
||||||
value: selectedCultureOption,
|
|
||||||
onChanged: (CultureOption? newValue) {
|
|
||||||
setState(() {
|
|
||||||
selectedCultureOption = newValue;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
items: CultureOption.values.map((CultureOption option) {
|
|
||||||
return DropdownMenuItem<CultureOption>(
|
|
||||||
value: option,
|
|
||||||
child: Text(option.displayName),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: handleSubmit,
|
onPressed: handleSubmit,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import '../constants.dart';
|
||||||
import '../enumerations.dart';
|
import '../enumerations.dart';
|
||||||
import '../models/swipe.dart';
|
import '../models/swipe.dart';
|
||||||
import '../services/auth/auth_service.dart';
|
import '../services/auth/auth_service.dart';
|
||||||
import '../utils/helper.dart';
|
import '../utils/helper_dialogs.dart';
|
||||||
import 'user_profile_page.dart';
|
import 'user_profile_page.dart';
|
||||||
|
|
||||||
class LikedUsersPage extends StatefulWidget {
|
class LikedUsersPage extends StatefulWidget {
|
||||||
|
@ -125,8 +125,9 @@ class LikedUsersPageState extends State<LikedUsersPage> {
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: const Text('Confirm Unlike'),
|
title: const Text('Confirm Removal'),
|
||||||
content: Text('Are you sure you want to unlike $userName?'),
|
content:
|
||||||
|
Text('Are you sure you want to remove $userName from your list?'),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(false),
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../components/my_button.dart';
|
import '../components/my_button.dart';
|
||||||
import '../components/my_textfield.dart';
|
import '../components/my_textfield.dart';
|
||||||
import '../utils/helper.dart';
|
import '../utils/helper_dialogs.dart';
|
||||||
import '../services/auth/auth_service.dart';
|
import '../services/auth/auth_service.dart';
|
||||||
|
|
||||||
class LoginPage extends StatelessWidget {
|
class LoginPage extends StatelessWidget {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import '../components/my_button.dart';
|
import '../components/my_button.dart';
|
||||||
import '../components/my_textfield.dart';
|
import '../components/my_textfield.dart';
|
||||||
import '../utils/helper.dart';
|
import '../utils/helper_dialogs.dart';
|
||||||
import '../services/auth/auth_service.dart';
|
import '../services/auth/auth_service.dart';
|
||||||
import '../services/user_service.dart';
|
import '../services/user_service.dart';
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import '../models/language.dart';
|
||||||
import '../models/language_setting.dart';
|
import '../models/language_setting.dart';
|
||||||
import '../models/location.dart';
|
import '../models/location.dart';
|
||||||
import '../services/auth/auth_service.dart';
|
import '../services/auth/auth_service.dart';
|
||||||
import '../utils/helper.dart';
|
import '../utils/helper_dialogs.dart';
|
||||||
import '../utils/math.dart';
|
import '../utils/math.dart';
|
||||||
|
|
||||||
class UserDataPage extends StatefulWidget {
|
class UserDataPage extends StatefulWidget {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
|
||||||
import 'package:percent_indicator/circular_percent_indicator.dart';
|
import 'package:percent_indicator/circular_percent_indicator.dart';
|
||||||
import 'package:swipable_stack/swipable_stack.dart';
|
import 'package:swipable_stack/swipable_stack.dart';
|
||||||
|
|
||||||
import '../components/card_overlay.dart';
|
import '../components/card_overlay.dart';
|
||||||
|
import '../components/language_list.dart';
|
||||||
import '../constants.dart';
|
import '../constants.dart';
|
||||||
import '../forms/matched_screen.dart';
|
import '../forms/matched_screen.dart';
|
||||||
import '../models/language.dart';
|
import '../models/language.dart';
|
||||||
|
@ -409,16 +409,6 @@ class UserMatchingPageState extends State<UserMatchingPage> {
|
||||||
Widget _buildUserCard(UserProfile userProfile) {
|
Widget _buildUserCard(UserProfile userProfile) {
|
||||||
String? profileImageUrl = userProfile.profilePictureUrl;
|
String? profileImageUrl = userProfile.profilePictureUrl;
|
||||||
|
|
||||||
// Sort the languages according to the given order below
|
|
||||||
List<Language> sortedLanguages = List.from(userProfile.languages);
|
|
||||||
sortedLanguages.sort((a, b) {
|
|
||||||
if (a.code == 'de') return -1; // German first
|
|
||||||
if (b.code == 'de') return 1; // German first
|
|
||||||
if (a.code == 'en') return -1; // English second
|
|
||||||
if (b.code == 'en') return 1; // English second
|
|
||||||
return a.name.compareTo(b.name); // All others by name ascending
|
|
||||||
});
|
|
||||||
|
|
||||||
String pronoun = getPronoun(userProfile.gender);
|
String pronoun = getPronoun(userProfile.gender);
|
||||||
|
|
||||||
double shortDist =
|
double shortDist =
|
||||||
|
@ -499,27 +489,10 @@ class UserMatchingPageState extends State<UserMatchingPage> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Wrap(
|
MyLanguageList(
|
||||||
children: sortedLanguages.map(
|
langList: userProfile.languages,
|
||||||
(language) {
|
iconHeight: 12,
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
SvgPicture.asset(
|
|
||||||
language.iconFile,
|
|
||||||
height: 12.0,
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4.0),
|
|
||||||
Text(language.name),
|
|
||||||
// Space between each language icon pair
|
|
||||||
const SizedBox(width: 8.0),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
).toList(),
|
|
||||||
),
|
|
||||||
|
|
||||||
//Text('Risk type: ${userProfile.risk.displayName}'),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
|
|
||||||
|
import '../components/language_list.dart';
|
||||||
import '../constants.dart';
|
import '../constants.dart';
|
||||||
import '../enumerations.dart';
|
import '../enumerations.dart';
|
||||||
import '../forms/corporate_culture_form.dart';
|
import '../forms/corporate_culture_form.dart';
|
||||||
|
@ -350,7 +351,7 @@ class _UserProfilePageState extends State<UserProfilePage> {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Vision and Goals',
|
'Corporate values',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
),
|
),
|
||||||
|
@ -502,29 +503,53 @@ class _UserProfilePageState extends State<UserProfilePage> {
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (isOwner)
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
Text(
|
||||||
|
'Locations',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (myData.locations.isEmpty)
|
||||||
|
const Text('n/a', style: TextStyle(fontSize: 16)),
|
||||||
|
if (myData.locations
|
||||||
|
.containsKey(Constants.dbDocMainLocation))
|
||||||
|
Text(
|
||||||
|
myData.locations[Constants.dbDocMainLocation]
|
||||||
|
.toString(),
|
||||||
|
style: const TextStyle(fontSize: 16),
|
||||||
|
),
|
||||||
|
if (myData.locations
|
||||||
|
.containsKey(Constants.dbDocSecondLocation))
|
||||||
|
Text(
|
||||||
|
myData.locations[Constants.dbDocSecondLocation]
|
||||||
|
.toString(),
|
||||||
|
style: const TextStyle(fontSize: 16),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (isOwner)
|
||||||
|
_editButton(context, editUserDataInfo,
|
||||||
|
alignment: Alignment.bottomRight),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (isOwner) const SizedBox(height: 16),
|
||||||
|
if (isOwner)
|
||||||
Text(
|
Text(
|
||||||
'Age',
|
'Age',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (isOwner)
|
||||||
Text(
|
Text(
|
||||||
(age > 0
|
(age > 0 ? '$age years old, born ${myData.born}' : 'n/a'),
|
||||||
? '$age years old, born ${myData.born}'
|
style: const TextStyle(fontSize: 16),
|
||||||
: 'n/a'),
|
|
||||||
style: const TextStyle(fontSize: 16)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
_editButton(context, editUserDataInfo,
|
|
||||||
alignment: Alignment.bottomRight),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
if (isOwner) const SizedBox(height: 16),
|
if (isOwner) const SizedBox(height: 16),
|
||||||
if (isOwner)
|
if (isOwner)
|
||||||
|
@ -544,28 +569,9 @@ class _UserProfilePageState extends State<UserProfilePage> {
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
MyLanguageList(
|
||||||
myData.languages.map((lang) => lang.name).join(', '),
|
langList: myData.languages,
|
||||||
style: const TextStyle(fontSize: 16),
|
textSize: 16,
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Text(
|
|
||||||
'Locations',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (myData.locations.isEmpty)
|
|
||||||
const Text('n/a', style: TextStyle(fontSize: 16)),
|
|
||||||
if (myData.locations.containsKey(Constants.dbDocMainLocation))
|
|
||||||
Text(
|
|
||||||
myData.locations[Constants.dbDocMainLocation].toString(),
|
|
||||||
style: const TextStyle(fontSize: 16),
|
|
||||||
),
|
|
||||||
if (myData.locations.containsKey(Constants.dbDocSecondLocation))
|
|
||||||
Text(
|
|
||||||
myData.locations[Constants.dbDocSecondLocation].toString(),
|
|
||||||
style: const TextStyle(fontSize: 16),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -603,12 +609,14 @@ class _UserProfilePageState extends State<UserProfilePage> {
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Flexible(
|
||||||
|
child: Text(
|
||||||
isOwner
|
isOwner
|
||||||
? myData.name
|
? myData.name
|
||||||
: '${myData.name} ${ageInfo(myData.born)}'.trim(),
|
: '${myData.name} ${ageInfo(myData.born)}'.trim(),
|
||||||
style: const TextStyle(fontSize: 24),
|
style: const TextStyle(fontSize: 24),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
genderIcon,
|
genderIcon,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -637,8 +645,7 @@ class _UserProfilePageState extends State<UserProfilePage> {
|
||||||
{Alignment alignment = Alignment.topRight}) {
|
{Alignment alignment = Alignment.topRight}) {
|
||||||
return Align(
|
return Align(
|
||||||
alignment: alignment,
|
alignment: alignment,
|
||||||
child: OutlinedButton.icon(
|
child: IconButton(
|
||||||
label: const Text('Edit'),
|
|
||||||
icon: const Icon(Icons.edit),
|
icon: const Icon(Icons.edit),
|
||||||
onPressed: onPressedFunction,
|
onPressed: onPressedFunction,
|
||||||
),
|
),
|
||||||
|
|
|
@ -5,7 +5,7 @@ import '../constants.dart';
|
||||||
import '../enumerations.dart';
|
import '../enumerations.dart';
|
||||||
import '../forms/corporate_culture_form.dart';
|
import '../forms/corporate_culture_form.dart';
|
||||||
import '../services/auth/auth_service.dart';
|
import '../services/auth/auth_service.dart';
|
||||||
import '../utils/helper.dart';
|
import '../utils/helper_dialogs.dart';
|
||||||
|
|
||||||
class UserVisionPage extends StatefulWidget {
|
class UserVisionPage extends StatefulWidget {
|
||||||
const UserVisionPage(
|
const UserVisionPage(
|
||||||
|
@ -155,26 +155,6 @@ class UserVisionPageState extends State<UserVisionPage> {
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
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(
|
const Text(
|
||||||
'Availability and commitment',
|
'Availability and commitment',
|
||||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
|
@ -194,6 +174,26 @@ class UserVisionPageState extends State<UserVisionPage> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
const SizedBox(height: 40),
|
||||||
|
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: 20),
|
const SizedBox(height: 20),
|
||||||
Center(
|
Center(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||||
import 'dart:io' show Platform;
|
import 'dart:io' show Platform;
|
||||||
import '../enumerations.dart';
|
import '../enumerations.dart';
|
||||||
|
@ -14,11 +12,6 @@ bool get isMobile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare two lists by their content ignoring their elements order.
|
|
||||||
bool equalContent(List<dynamic> list1, List<dynamic> list2) {
|
|
||||||
return const DeepCollectionEquality.unordered().equals(list1, list2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a composite ID from the passed [ids].
|
/// Creates a composite ID from the passed [ids].
|
||||||
/// In the format id(1)_id(n)
|
/// In the format id(1)_id(n)
|
||||||
String getCompoundId(List<String> ids) {
|
String getCompoundId(List<String> ids) {
|
||||||
|
@ -94,38 +87,3 @@ String getDisplayText(dynamic option) {
|
||||||
// Fallback to default toString if not an enum
|
// Fallback to default toString if not an enum
|
||||||
return option.toString().split('.').last;
|
return option.toString().split('.').last;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show a simple message dialog
|
|
||||||
void showMsg(BuildContext context, String title, String content) {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => AlertDialog(
|
|
||||||
title: Text(title),
|
|
||||||
content: Text(content),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
child: const Text('OK'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Show a red colored SnackBar with a [Dismiss] Button
|
|
||||||
void showErrorSnackBar(BuildContext context, String message) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text(message),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
action: SnackBarAction(
|
|
||||||
label: 'Dismiss',
|
|
||||||
onPressed: () {
|
|
||||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// Show a simple message dialog
|
||||||
|
void showMsg(BuildContext context, String title, String content) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: Text(title),
|
||||||
|
content: Text(content),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Show a red colored SnackBar with a [Dismiss] Button
|
||||||
|
void showErrorSnackBar(BuildContext context, String message) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(message),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
action: SnackBarAction(
|
||||||
|
label: 'Dismiss',
|
||||||
|
onPressed: () {
|
||||||
|
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
import '../models/language.dart';
|
||||||
|
|
||||||
|
/// Compare two lists by their content ignoring their elements order.
|
||||||
|
bool equalContent(List<dynamic> list1, List<dynamic> list2) {
|
||||||
|
return const DeepCollectionEquality.unordered().equals(list1, list2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sort the given list of languages so that German appears first, English second, and all other languages follow in alphabetical order.
|
||||||
|
List<Language> sortLanguageList(List<Language> langList) {
|
||||||
|
List<Language> sortedLanguages = List.from(langList);
|
||||||
|
sortedLanguages.sort((a, b) {
|
||||||
|
// German first
|
||||||
|
if (a.code == 'de') return -1;
|
||||||
|
if (b.code == 'de') return 1;
|
||||||
|
// English second
|
||||||
|
if (a.code == 'en') return -1;
|
||||||
|
if (b.code == 'en') return 1;
|
||||||
|
// All others by name ascending
|
||||||
|
return a.name.compareTo(b.name);
|
||||||
|
});
|
||||||
|
return sortedLanguages;
|
||||||
|
}
|
|
@ -19,9 +19,7 @@ String ageInfo(int? birthYear) {
|
||||||
return ageInfo;
|
return ageInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// Convert decimal coordinate to degrees minutes seconds (DMS).
|
/// Convert decimal coordinate to degrees minutes seconds (DMS).
|
||||||
///
|
|
||||||
String convertDecimalToDMS(double decimalValue, {required bool isLatitude}) {
|
String convertDecimalToDMS(double decimalValue, {required bool isLatitude}) {
|
||||||
bool isNegative = decimalValue < 0;
|
bool isNegative = decimalValue < 0;
|
||||||
double absoluteValue = decimalValue.abs();
|
double absoluteValue = decimalValue.abs();
|
||||||
|
@ -43,9 +41,7 @@ String convertDecimalToDMS(double decimalValue, {required bool isLatitude}) {
|
||||||
return '${degrees.abs()}° ${minutes.abs()}\' ${seconds.abs().toStringAsFixed(2)}" $direction';
|
return '${degrees.abs()}° ${minutes.abs()}\' ${seconds.abs().toStringAsFixed(2)}" $direction';
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// Distance in kilometers between two location coordinates
|
/// Distance in kilometers between two location coordinates
|
||||||
///
|
|
||||||
double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
|
double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
|
||||||
const R = 6371; // earth radius in kilometers
|
const R = 6371; // earth radius in kilometers
|
||||||
|
|
||||||
|
@ -67,9 +63,7 @@ double _degreesToRadians(double degrees) {
|
||||||
return degrees * pi / 180;
|
return degrees * pi / 180;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// Shortest distance between two users locations
|
/// Shortest distance between two users locations
|
||||||
///
|
|
||||||
double shortestDistanceBetweenUsers(
|
double shortestDistanceBetweenUsers(
|
||||||
UserProfile currentUser, UserProfile otherUser) {
|
UserProfile currentUser, UserProfile otherUser) {
|
||||||
try {
|
try {
|
||||||
|
@ -122,7 +116,7 @@ double calculateMatchScore(UserProfile currentUser, UserProfile otherUser) {
|
||||||
communicationWeight);
|
communicationWeight);
|
||||||
if (weightSum != 1) {
|
if (weightSum != 1) {
|
||||||
debugPrint(
|
debugPrint(
|
||||||
'Warning --> calculateMatchScore : Weights Sum $weightSum != 1');
|
'DEBUG Info --> calculateMatchScore : Weights Sum $weightSum != 1');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,51 +35,6 @@ void main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group('equalContent', () {
|
|
||||||
test('returns true for lists with the same content in the same order', () {
|
|
||||||
List<dynamic> list1 = [1, 2, 3];
|
|
||||||
List<dynamic> list2 = [1, 2, 3];
|
|
||||||
bool result = equalContent(list1, list2);
|
|
||||||
expect(result, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('returns true for lists with the same content in different orders',
|
|
||||||
() {
|
|
||||||
List<dynamic> list1 = [1, 2, 3];
|
|
||||||
List<dynamic> list2 = [3, 1, 2];
|
|
||||||
bool result = equalContent(list1, list2);
|
|
||||||
expect(result, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('returns false for lists with different content', () {
|
|
||||||
List<dynamic> list1 = [1, 2, 3];
|
|
||||||
List<dynamic> list2 = [1, 2, 4];
|
|
||||||
bool result = equalContent(list1, list2);
|
|
||||||
expect(result, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('returns false for lists with different lengths', () {
|
|
||||||
List<dynamic> list1 = [1, 2, 3];
|
|
||||||
List<dynamic> list2 = [1, 2];
|
|
||||||
bool result = equalContent(list1, list2);
|
|
||||||
expect(result, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('returns true for empty lists', () {
|
|
||||||
List<dynamic> list1 = [];
|
|
||||||
List<dynamic> list2 = [];
|
|
||||||
bool result = equalContent(list1, list2);
|
|
||||||
expect(result, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('returns false for one empty and one non-empty list', () {
|
|
||||||
List<dynamic> list1 = [];
|
|
||||||
List<dynamic> list2 = [1];
|
|
||||||
bool result = equalContent(list1, list2);
|
|
||||||
expect(result, false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
group('formatTimestamp', () {
|
group('formatTimestamp', () {
|
||||||
test('formatTimestamp returns the expected formatted date for 01.01.1970',
|
test('formatTimestamp returns the expected formatted date for 01.01.1970',
|
||||||
() {
|
() {
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
import 'package:cofounderella/utils/list_utils.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('equalContent', () {
|
||||||
|
test('returns true for lists with the same content in the same order', () {
|
||||||
|
List<dynamic> list1 = [1, 2, 3];
|
||||||
|
List<dynamic> list2 = [1, 2, 3];
|
||||||
|
bool result = equalContent(list1, list2);
|
||||||
|
expect(result, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns true for lists with the same content in different orders',
|
||||||
|
() {
|
||||||
|
List<dynamic> list1 = [1, 2, 3];
|
||||||
|
List<dynamic> list2 = [3, 1, 2];
|
||||||
|
bool result = equalContent(list1, list2);
|
||||||
|
expect(result, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns false for lists with different content', () {
|
||||||
|
List<dynamic> list1 = [1, 2, 3];
|
||||||
|
List<dynamic> list2 = [1, 2, 4];
|
||||||
|
bool result = equalContent(list1, list2);
|
||||||
|
expect(result, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns false for lists with different lengths', () {
|
||||||
|
List<dynamic> list1 = [1, 2, 3];
|
||||||
|
List<dynamic> list2 = [1, 2];
|
||||||
|
bool result = equalContent(list1, list2);
|
||||||
|
expect(result, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns true for empty lists', () {
|
||||||
|
List<dynamic> list1 = [];
|
||||||
|
List<dynamic> list2 = [];
|
||||||
|
bool result = equalContent(list1, list2);
|
||||||
|
expect(result, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns false for one empty and one non-empty list', () {
|
||||||
|
List<dynamic> list1 = [];
|
||||||
|
List<dynamic> list2 = [1];
|
||||||
|
bool result = equalContent(list1, list2);
|
||||||
|
expect(result, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue