Appearance of the swipe card revised

master
Rafael 2024-06-09 00:04:13 +02:00
parent 15a6556ac0
commit e2096b4989
5 changed files with 165 additions and 83 deletions

View File

@ -8,8 +8,10 @@ class MyLocation {
/// DE: Bundesland /// DE: Bundesland
final String? administrativeArea; final String? administrativeArea;
/// City /// City
final String locality; final String locality;
/// DE: Stadtteil /// DE: Stadtteil
final String? subLocality; final String? subLocality;
final String? postalCode; final String? postalCode;
@ -67,10 +69,18 @@ class MyLocation {
} }
} }
/// Returns: locality, country /// Returns the location formatted as 'locality, country'
/// if both values are present or an empty string if both values are empty.
@override @override
String toString() { String toString() {
if (locality.isNotEmpty && country.isNotEmpty) {
return '$locality, $country'; return '$locality, $country';
} else if (country.isNotEmpty) {
return country;
} else if (locality.isNotEmpty) {
return locality;
}
return '';
} }
@override @override

View File

@ -1,12 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../components/my_drawer.dart'; import '../components/my_drawer.dart';
import '../services/auth/auth_service.dart';
class HomePage extends StatelessWidget { class HomePage extends StatelessWidget {
HomePage({super.key}); const HomePage({super.key});
final AuthService _authService = AuthService();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -45,7 +45,7 @@ class RegistrationCompletePage extends StatelessWidget {
onPressed: () { onPressed: () {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute(builder: (context) => HomePage()), MaterialPageRoute(builder: (context) => const HomePage()),
); );
}, },
child: const Text('S T A R T'), child: const Text('S T A R T'),

View File

@ -1,6 +1,8 @@
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/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:swipable_stack/swipable_stack.dart'; import 'package:swipable_stack/swipable_stack.dart';
import '../constants.dart'; import '../constants.dart';
@ -69,7 +71,7 @@ class UserMatchingPageState extends State<UserMatchingPage> {
.get(); .get();
final Set<String> likedUserIds = swipesSnapshot.docs final Set<String> likedUserIds = swipesSnapshot.docs
.where((doc) => doc['liked'] == true) .where((doc) => doc[Constants.dbFieldSwipesLike] == true)
.map((doc) => doc.id) .map((doc) => doc.id)
.toSet(); .toSet();
@ -77,8 +79,10 @@ class UserMatchingPageState extends State<UserMatchingPage> {
DateTime.now().subtract(const Duration(hours: 24)); DateTime.now().subtract(const Duration(hours: 24));
final Set<String> dislikedUserIds = swipesSnapshot.docs final Set<String> dislikedUserIds = swipesSnapshot.docs
.where((doc) => .where((doc) =>
doc['liked'] == false && doc[Constants.dbFieldSwipesLike] == false &&
(doc['timestamp'] as Timestamp).toDate().isAfter(thresholdDate)) (doc[Constants.dbFieldSwipesTimestamp] as Timestamp)
.toDate()
.isAfter(thresholdDate))
.map((doc) => doc.id) .map((doc) => doc.id)
.toSet(); .toSet();
@ -178,9 +182,9 @@ class UserMatchingPageState extends State<UserMatchingPage> {
.doc(swipedUserId) // UserID instead of autogenerated ID .doc(swipedUserId) // UserID instead of autogenerated ID
.set( .set(
{ {
'swipedId': swipedUserId, Constants.dbFieldSwipesSwipedId: swipedUserId,
'liked': direction == SwipeDirection.right, Constants.dbFieldSwipesLike: direction == SwipeDirection.right,
'timestamp': FieldValue.serverTimestamp(), Constants.dbFieldSwipesTimestamp: FieldValue.serverTimestamp(),
}, },
); );
} }
@ -197,8 +201,8 @@ class UserMatchingPageState extends State<UserMatchingPage> {
.collection(Constants.dbCollectionUsers) .collection(Constants.dbCollectionUsers)
.doc(swipedUserId) .doc(swipedUserId)
.collection(Constants.dbCollectionSwipes) .collection(Constants.dbCollectionSwipes)
.where('swipedId', isEqualTo: currentUserId) .where(Constants.dbFieldSwipesSwipedId, isEqualTo: currentUserId)
.where('liked', isEqualTo: true) .where(Constants.dbFieldSwipesLike, isEqualTo: true)
.get(); .get();
if (matchSnapshot.docs.isNotEmpty) { if (matchSnapshot.docs.isNotEmpty) {
@ -384,32 +388,105 @@ class UserMatchingPageState extends State<UserMatchingPage> {
} }
Widget _buildUserCard(UserProfile userProfile) { Widget _buildUserCard(UserProfile userProfile) {
String? profileImageUrl = userProfile.profilePictureUrl;
int age = calcAge(userProfile.born);
String ageInfo = age > 0 ? ' ($age)' : '';
// 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 shortDist =
shortestDistanceBetweenUsers(currentUserProfile!, userProfile)
.toStringAsFixed(0);
return Card( return Card(
child: Padding( child: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(userProfile.name, style: const TextStyle(fontSize: 24)), if (kDebugMode)
Text(userProfile.email, style: const TextStyle(fontSize: 24)), Center(
child: Text(
userProfile.email,
style: const TextStyle(fontSize: 12),
),
),
Center(
child: CircleAvatar(
radius: 50,
backgroundImage:
((profileImageUrl != null && profileImageUrl.isNotEmpty))
? NetworkImage(profileImageUrl)
: null,
child: (profileImageUrl == null || profileImageUrl.isEmpty)
? const Icon(Icons.person_pin, size: 50)
: null,
),
),
const SizedBox(height: 8),
Center(
child: Text('${userProfile.name}$ageInfo',
style: const TextStyle(fontSize: 24)),
),
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
'Has skills and experience in: ${userProfile.skills.map((x) => x.displayName).join(', ')}'), 'Would like to team up with someone who has experience in '
'${userProfile.skillsSought.map((x) => x.displayName).join(', ')}.',
),
Text( Text(
'Seeks someone with skills in: ${userProfile.skillsSought.map((x) => x.displayName).join(', ')}'), 'He/She brings skills and experience in '
Text('Availability: ${userProfile.availability.displayName}'), '${userProfile.skills.map((x) => x.displayName).join(', ')}',
Text('Risk type: ${userProfile.risk.displayName}'), ),
Text( Text(
'Speaks: ${userProfile.languages.map((lang) => lang.name).join(', ')}'), 'and is willing to commit in '
'${userProfile.availability.commitmentText}.',
),
Text( Text(
'Lives in: ${userProfile.locations[Constants.dbDocMainLocation]?.locality ?? 'N/A'}'), 'Lives in ${userProfile.locations[Constants.dbDocMainLocation]?.toString() ?? 'N/A'}'
Text( ' and ${userProfile.locations[Constants.dbDocSecondLocation]?.toString() ?? 'N/A'}'
'Coordinates: ${userProfile.locations[Constants.dbDocMainLocation]?.latitude} ${userProfile.locations[Constants.dbDocMainLocation]?.longitude}'), ' which is only/about $shortDist km away from you.',
Text( ),
'Second home: ${userProfile.locations[Constants.dbDocSecondLocation]?.locality ?? 'N/A'}'), const SizedBox(height: 8),
Text( const Row(
'Shortest distance: ${shortestDistanceBetweenUsers(currentUserProfile!, userProfile).toStringAsFixed(0)} km'), children: [
Text('Spoken languages '),
Expanded(child: Divider()),
],
),
const SizedBox(height: 4),
Wrap(
children: sortedLanguages.map(
(language) {
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}'),
], ],
), ),
), ),
@ -554,9 +631,7 @@ class CardOverlay extends StatelessWidget {
child: Icon( child: Icon(
direction == SwipeDirection.right direction == SwipeDirection.right
? Icons.thumb_up ? Icons.thumb_up
: (direction == SwipeDirection.left : (direction == SwipeDirection.left ? Icons.thumb_down : null),
? Icons.thumb_down
: Icons.skip_next),
size: 100, size: 100,
color: direction == SwipeDirection.right color: direction == SwipeDirection.right
? Colors.green ? Colors.green

View File

@ -34,7 +34,7 @@ class AuthGate extends StatelessWidget {
if (snapshot.connectionState == ConnectionState.waiting) { if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator(); return const CircularProgressIndicator();
} else if (snapshot.hasData && snapshot.data == true) { } else if (snapshot.hasData && snapshot.data == true) {
return HomePage(); return const HomePage();
} else { } else {
// also in case of (snapshot.hasError) // also in case of (snapshot.hasError)
return const UserDataPage( return const UserDataPage(