From da81a99c7b0956da3e5681402cc9e716513bafc8 Mon Sep 17 00:00:00 2001 From: Rafael <1024481@stud.hs-mannheim.de> Date: Wed, 15 May 2024 23:24:26 +0200 Subject: [PATCH] Added FeedbackDialog --- lib/components/feedback_dialog.dart | 104 +++++++++++ lib/components/my_drawer.dart | 261 ++++++++++++++-------------- lib/constants.dart | 1 + 3 files changed, 239 insertions(+), 127 deletions(-) create mode 100644 lib/components/feedback_dialog.dart diff --git a/lib/components/feedback_dialog.dart b/lib/components/feedback_dialog.dart new file mode 100644 index 0000000..d58fe0e --- /dev/null +++ b/lib/components/feedback_dialog.dart @@ -0,0 +1,104 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/material.dart'; + +import '../constants.dart'; +import '../services/auth/auth_service.dart'; + +class FeedbackDialog extends StatefulWidget { + const FeedbackDialog({super.key}); + + @override + State createState() => _FeedbackDialogState(); +} + +class _FeedbackDialogState extends State { + final TextEditingController _feedbackController = TextEditingController(); + final GlobalKey _formKey = GlobalKey(); + + // get instance of firestore and auth + final FirebaseFirestore _firestore = FirebaseFirestore.instance; + final AuthService _authService = AuthService(); + + @override + void dispose() { + _feedbackController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + content: Form( + key: _formKey, + child: TextFormField( + controller: _feedbackController, + keyboardType: TextInputType.multiline, + decoration: const InputDecoration( + hintText: 'Please enter your feedback here', + filled: true, + ), + maxLines: 5, + maxLength: 4096, + textInputAction: TextInputAction.done, + validator: (String? text) { + if (text == null || text.isEmpty) { + return 'Please enter something'; + } + return null; + }, + ), + ), + actions: [ + TextButton( + child: const Text('Cancel'), + onPressed: () => Navigator.pop(context), + ), + TextButton( + style: TextButton.styleFrom( + backgroundColor: Theme.of(context).colorScheme.secondary, + ), + child: const Text( + 'Send feedback', + style: TextStyle( + color: Colors.blue, + ), + ), + onPressed: () async { + // Only if the input form is valid (the user has entered text) + if (_formKey.currentState!.validate()) { + String message; + bool error = false; + + try { + // Get a reference to the feedbacks collection + final collection = + _firestore.collection(Constants.dbCollectionFeedbacks); + + // Write the server's timestamp and the user's feedback + await collection.doc().set({ + 'timestamp': FieldValue.serverTimestamp(), + 'feedback': _feedbackController.text, + 'user': _authService.getCurrentUser()!.uid, + }); + + message = 'Feedback sent successfully. Thank you!'; + } catch (e) { + message = 'Error when sending feedback: ${e.toString()}'; + error = true; + } + + // Show a snackBar with the result + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(message), + backgroundColor: error ? Colors.red : Colors.green, + )); + Navigator.pop(context); + } + } + }, + ) + ], + ); + } +} diff --git a/lib/components/my_drawer.dart b/lib/components/my_drawer.dart index 047a85a..30fe25a 100644 --- a/lib/components/my_drawer.dart +++ b/lib/components/my_drawer.dart @@ -3,6 +3,8 @@ import 'package:cofounderella/services/auth/auth_service.dart'; import 'package:cofounderella/pages/settings_page.dart'; import 'package:flutter/material.dart'; +import 'feedback_dialog.dart'; + class MyDrawer extends StatelessWidget { const MyDrawer({super.key}); @@ -15,137 +17,142 @@ class MyDrawer extends StatelessWidget { @override Widget build(BuildContext context) { return Drawer( - backgroundColor: Theme.of(context).colorScheme.background, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - // logo - Column( - children: [ - DrawerHeader( - child: Center( - child: Icon( - Icons.people_alt, - color: Theme.of(context).colorScheme.primary, - size: 40, - ), - ), - ), - - // home list tile - Padding( - padding: const EdgeInsets.only(left: 25), - child: ListTile( - title: const Text("Home"), - leading: const Icon(Icons.home), - onTap: () { - // pop the drawer - Navigator.pop(context); - // TODO navigate to Homepage? - }, - ), - ), - - // matching list tile - Padding( - padding: const EdgeInsets.only(left: 25), - child: ListTile( - title: const Text("Find Matches"), - leading: const Icon(Icons.person_search), - onTap: () {}, // TODO - ), - ), - - // chats list tile - Padding( - padding: const EdgeInsets.only(left: 25), - child: ListTile( - title: const Text("Conversations"), - leading: const Icon(Icons.chat), - onTap: () {}, // TODO - ), - ), - - // settings list tile - Padding( - padding: const EdgeInsets.only(left: 25), - child: ListTile( - title: const Text("My Profile"), - leading: const Icon(Icons.settings), - onTap: () { - // pop the drawer - Navigator.pop(context); - - //navigate to settings page - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const SettingsPage(), - )); - }, - ), - ), - - // TODO TESTING - user data tile - Padding( - padding: const EdgeInsets.only(left: 25), - child: ListTile( - title: const Text("User Data"), - leading: const Icon(Icons.supervised_user_circle), - onTap: () { - // pop the drawer - Navigator.pop(context); - - //navigate to settings page - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const UserDataPage(), - )); - }, - ), - ), - - // horizontal line - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Divider( + backgroundColor: Theme.of(context).colorScheme.background, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // logo + Column( + children: [ + DrawerHeader( + child: Center( + child: Icon( + Icons.people_alt, color: Theme.of(context).colorScheme.primary, + size: 40, ), ), - - // about tile - Padding( - padding: const EdgeInsets.only(left: 25), - child: ListTile( - title: const Text("About the app"), - leading: const Icon(Icons.perm_device_info), - onTap: () {}, // TODO - ), - ), - - // feedback tile - Padding( - padding: const EdgeInsets.only(left: 25), - child: ListTile( - title: const Text("Send feedback"), - leading: const Icon(Icons.sentiment_neutral), - onTap: () {}, // TODO - ), - ), - ], - ), - - // logout list tile - Padding( - padding: const EdgeInsets.only(left: 25, bottom: 25), - child: ListTile( - title: const Text("L O G O U T"), - leading: const Icon(Icons.logout), - onTap: logout, ), + + // home list tile + Padding( + padding: const EdgeInsets.only(left: 25), + child: ListTile( + title: const Text("Home"), + leading: const Icon(Icons.home), + onTap: () { + // pop the drawer + Navigator.pop(context); + // TODO navigate to Homepage? + }, + ), + ), + + // matching list tile + Padding( + padding: const EdgeInsets.only(left: 25), + child: ListTile( + title: const Text("Find Matches"), + leading: const Icon(Icons.person_search), + onTap: () {}, // TODO + ), + ), + + // chats list tile + Padding( + padding: const EdgeInsets.only(left: 25), + child: ListTile( + title: const Text("Conversations"), + leading: const Icon(Icons.chat), + onTap: () {}, // TODO + ), + ), + + // settings list tile + Padding( + padding: const EdgeInsets.only(left: 25), + child: ListTile( + title: const Text("My Profile"), + leading: const Icon(Icons.settings), + onTap: () { + // pop the drawer + Navigator.pop(context); + + //navigate to settings page + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const SettingsPage(), + )); + }, + ), + ), + + // TODO TESTING - user data tile + Padding( + padding: const EdgeInsets.only(left: 25), + child: ListTile( + title: const Text("User Data"), + leading: const Icon(Icons.supervised_user_circle), + onTap: () { + // pop the drawer + Navigator.pop(context); + + //navigate to settings page + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const UserDataPage(), + )); + }, + ), + ), + + // horizontal line + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Divider( + color: Theme.of(context).colorScheme.primary, + ), + ), + + // about tile + Padding( + padding: const EdgeInsets.only(left: 25), + child: ListTile( + title: const Text("About the app"), + leading: const Icon(Icons.perm_device_info), + onTap: () {}, // TODO + ), + ), + + // feedback tile + Padding( + padding: const EdgeInsets.only(left: 25), + child: ListTile( + title: const Text("Send feedback"), + leading: const Icon(Icons.sentiment_satisfied_alt), + onTap: () { + showDialog( + context: context, + builder: (context) => const FeedbackDialog()); + }, + ), + ), + ], + ), + + // logout list tile + Padding( + padding: const EdgeInsets.only(left: 25, bottom: 25), + child: ListTile( + title: const Text("L O G O U T"), + leading: const Icon(Icons.logout), + onTap: logout, ), - ], - )); + ), + ], + ), + ); } } diff --git a/lib/constants.dart b/lib/constants.dart index a91759f..c196117 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -4,6 +4,7 @@ class Constants { /// Title of the app static const String appTitle = "Cofounderella"; + static const String dbCollectionFeedbacks = 'feedbacks'; static const String dbCollectionUsers = 'Users'; static const String dbCollectionLanguages = 'languages'; static const String dbCollectionLocations = 'locations';