From ed8f1b810b5eb7d9e723b29e29b58a818d03c2b7 Mon Sep 17 00:00:00 2001 From: Rafael <1024481@stud.hs-mannheim.de> Date: Sun, 26 May 2024 17:33:28 +0200 Subject: [PATCH] Added MyAboutDialog. Swipes left will be hidden for 24 hours. --- lib/components/my_about_dialog.dart | 79 +++++++++++++++++++++++++++ lib/components/my_drawer.dart | 8 ++- lib/constants.dart | 4 +- lib/pages/user_profile_page.dart | 85 +++++++++++++++++++---------- 4 files changed, 145 insertions(+), 31 deletions(-) create mode 100644 lib/components/my_about_dialog.dart diff --git a/lib/components/my_about_dialog.dart b/lib/components/my_about_dialog.dart new file mode 100644 index 0000000..dca66e0 --- /dev/null +++ b/lib/components/my_about_dialog.dart @@ -0,0 +1,79 @@ +import 'package:flutter/material.dart'; + +import '../constants.dart'; + +class MyAboutDialog extends StatelessWidget { + const MyAboutDialog({super.key}); + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Row( + children: [ + Icon(Icons.info), + SizedBox(width: 10), + Text('About the app', style: TextStyle(fontSize: 18)), + ], + ), + content: SingleChildScrollView( + child: ListBody( + children: [ + const Row( + children: [ + Icon(Icons.apps, size: 50), + SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + Constants.appTitle, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), + Text( + 'Version ${Constants.appVersion} (${Constants.appCompilationDate})'), + ], + ), + ], + ), + const SizedBox(height: 20), + const Text( + '© 2024 Team ${Constants.appTitle}. All rights reserved.'), + const SizedBox(height: 20), + GestureDetector( + onTap: () => {}, + child: const Text( + 'https://www.no-website.yet', + style: TextStyle( + color: Colors.blue, + decoration: TextDecoration.underline, + ), + ), + ), + const SizedBox(height: 20), + const Text( + '${Constants.appTitle} helps entrepreneurs find the right co-founders who complement their skills and also share their interests and business goals. ' + 'Whether you are looking for a tech expert, a marketing guru, or a visionary partner. This app aims to help you finding a perfect co-founder to bring your startup ideas to life.', + ), + ], + ), + ), + actions: [ + TextButton( + onPressed: () { + showLicensePage(context: context); + }, + child: const Text('View licenses'), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Close'), + ), + ], + ); + } +} diff --git a/lib/components/my_drawer.dart b/lib/components/my_drawer.dart index 1146f3e..278e77e 100644 --- a/lib/components/my_drawer.dart +++ b/lib/components/my_drawer.dart @@ -5,6 +5,7 @@ import '../pages/settings_page.dart'; import '../pages/user_profile_page.dart'; import '../services/auth/auth_service.dart'; import 'feedback_dialog.dart'; +import 'my_about_dialog.dart'; class MyDrawer extends StatelessWidget { const MyDrawer({super.key}); @@ -137,7 +138,12 @@ class MyDrawer extends StatelessWidget { child: ListTile( title: const Text("About the app"), leading: const Icon(Icons.perm_device_info), - onTap: () {}, // TODO + onTap: () { + Navigator.pop(context); + showDialog( + context: context, + builder: (context) => const MyAboutDialog()); + }, ), ), diff --git a/lib/constants.dart b/lib/constants.dart index b17a254..ed2664e 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -2,7 +2,9 @@ class Constants { Constants._(); /// Title of the app - static const String appTitle = "Cofounderella"; + static const String appTitle = 'Cofounderella'; + static const String appVersion = '1.0.0'; + static const String appCompilationDate = '2024-05-26'; static const String dbCollectionFeedbacks = 'feedbacks'; static const String dbCollectionUsers = 'Users'; diff --git a/lib/pages/user_profile_page.dart b/lib/pages/user_profile_page.dart index d69e987..8302d00 100644 --- a/lib/pages/user_profile_page.dart +++ b/lib/pages/user_profile_page.dart @@ -19,14 +19,14 @@ class UserProfilePage extends StatefulWidget { } class UserProfilePageState extends State { - /// List with [all] user profiles - List userProfiles = []; - /// The current's user profile UserProfile? currentUserProfile; - /// Other users that yet did either not receive a swipe status - List potentialUserProfiles = []; // potential users for matching + /// List with [all] user profiles + List userProfiles = []; + + /// List of user profiles to show. + List potentialUserProfiles = []; late final SwipableStackController _controller; @@ -52,10 +52,13 @@ class UserProfilePageState extends State { } Future _fetchUserProfiles() async { + final String currentUserId = _authService.getCurrentUser()!.uid; + List allUsers = []; + List showProfiles = []; + final usersSnapshot = await FirebaseFirestore.instance .collection(Constants.dbCollectionUsers) .get(); - final String currentUserId = _authService.getCurrentUser()!.uid; // Fetch the list of profiles the current user has already swiped final QuerySnapshot swipesSnapshot = await FirebaseFirestore.instance @@ -63,13 +66,20 @@ class UserProfilePageState extends State { .doc(currentUserId) .collection(Constants.dbCollectionSwipes) .get(); + final Set likedUserIds = swipesSnapshot.docs .where((doc) => doc['liked'] == true) .map((doc) => doc.id) .toSet(); - List allUsers = []; - List showProfiles = []; + final DateTime thresholdDate = + DateTime.now().subtract(const Duration(hours: 24)); + final Set dislikedUserIds = swipesSnapshot.docs + .where((doc) => + doc['liked'] == false && + (doc['timestamp'] as Timestamp).toDate().isAfter(thresholdDate)) + .map((doc) => doc.id) + .toSet(); for (var userDoc in usersSnapshot.docs) { final languagesSnapshot = await userDoc.reference @@ -119,18 +129,21 @@ class UserProfilePageState extends State { // add profiles accordingly allUsers.add(userProfile); - // Exclude the current user's profile and the already liked profiles - if (userDoc.id != currentUserId && !likedUserIds.contains(userDoc.id)) { + // Exclude (1) the current user's profile, (2) the already liked profiles + // and (3) users that were disliked less than 24 hours ago + if (userDoc.id != currentUserId && + !likedUserIds.contains(userDoc.id) && + !dislikedUserIds.contains(userDoc.id)) { showProfiles.add(userProfile); } + } // end for - setState(() { - userProfiles = allUsers; - potentialUserProfiles = showProfiles; - currentUserProfile = - allUsers.firstWhereOrNull((x) => x.uid == currentUserId); - }); - } + setState(() { + userProfiles = allUsers; + potentialUserProfiles = showProfiles; + currentUserProfile = + allUsers.firstWhereOrNull((x) => x.uid == currentUserId); + }); } MyLocation? _createLocationFromDoc(Map? data) { @@ -269,17 +282,31 @@ class UserProfilePageState extends State { children: [ const Icon(Icons.person_search, size: 64), const SizedBox(height: 20), - Text( - '${userProfiles.length > 1 ? 'No new' : 'No'} profiles available at the moment.', - style: const TextStyle( - fontWeight: FontWeight.bold, fontSize: 18), - ), - const SizedBox(height: 60), - const Text( - 'Please check back later, perhaps tomorrow.', - textAlign: TextAlign.center, - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), - ), + // Loading... + if (userProfiles.isEmpty) ...[ + const CircularProgressIndicator(), + const SizedBox(height: 20), + const Text( + 'Loading data, please wait...', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), + ), + ] else ...[ + Text( + userProfiles.length > 1 + ? 'No new profiles available yet.' + : 'No profiles available at the moment.', + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + const SizedBox(height: 60), + const Text( + 'Please check back later, perhaps tomorrow.', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18), + ), + ], ], ), ), @@ -288,7 +315,7 @@ class UserProfilePageState extends State { } return Scaffold( - appBar: AppBar(title: const Text('User Profiles')), + appBar: AppBar(title: const Text('Find your Match')), body: SafeArea( top: false, child: Stack(