Compare commits
	
		
			4 Commits
		
	
	
		
			c389381b1e
			...
			68c8064083
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 68c8064083 | |||
| 0ab5fee8b2 | |||
| eca2b6324b | |||
| 90fccde9e6 | 
| @ -13,7 +13,7 @@ enum ApiService { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Future<String?> request(BuildContext? context, ApiService service, String method, String path, dynamic body) async { | Future<String?> request(BuildContext? context, ApiService service, String method, String path, dynamic body) async { | ||||||
|   debugPrint('$method $path'); |   var debug = '$method $path\n    $body\n'; | ||||||
| 
 | 
 | ||||||
|   final messenger = context != null ? ScaffoldMessenger.of(context) : null; |   final messenger = context != null ? ScaffoldMessenger.of(context) : null; | ||||||
|   final prefs = await SharedPreferences.getInstance(); |   final prefs = await SharedPreferences.getInstance(); | ||||||
| @ -49,18 +49,22 @@ Future<String?> request(BuildContext? context, ApiService service, String method | |||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|   } catch (e) { |   } catch (e) { | ||||||
|     debugPrint('Can\'t send requst: ' + e.toString()); |  | ||||||
|     messenger?.showSnackBar(const SnackBar(content: Text('Unable to connect to server'))); |     messenger?.showSnackBar(const SnackBar(content: Text('Unable to connect to server'))); | ||||||
|  | 
 | ||||||
|  |     debug += 'FAILED\n    $e'; | ||||||
|  |     debugPrint(debug); | ||||||
|  | 
 | ||||||
|     return null; |     return null; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   debug += 'HTTP ${response.statusCode}\n    ${response.body}'; | ||||||
|  |   debugPrint(debug); | ||||||
|  | 
 | ||||||
|   if (response.statusCode < 200 || response.statusCode >= 300) { |   if (response.statusCode < 200 || response.statusCode >= 300) { | ||||||
|     try { |     try { | ||||||
|       final json = jsonDecode(response.body); |       final json = jsonDecode(response.body); | ||||||
|       messenger?.showSnackBar(SnackBar(content: Text(json['message'] ?? json['title']))); |       messenger?.showSnackBar(SnackBar(content: Text(json['message'] ?? json['title']))); | ||||||
|       debugPrint('API error: ' + json['message']); |  | ||||||
|     } catch (e) { |     } catch (e) { | ||||||
|       debugPrint('Can\'t parse response: ' + response.body); |  | ||||||
|       messenger?.showSnackBar(SnackBar(content: Text('Something went wrong (HTTP ${response.statusCode})'))); |       messenger?.showSnackBar(SnackBar(content: Text('Something went wrong (HTTP ${response.statusCode})'))); | ||||||
|     } |     } | ||||||
|     return null; |     return null; | ||||||
|  | |||||||
| @ -14,10 +14,14 @@ class ReviewListPage extends StatefulWidget { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class _ReviewListState extends State<ReviewListPage> { | class _ReviewListState extends State<ReviewListPage> { | ||||||
|   List<models.User> users = []; |   List<models.User> _users = []; | ||||||
| 
 | 
 | ||||||
|   models.User? _getReviewUser(models.Review review) { |   models.User? _getReviewUser(models.Review review) { | ||||||
|     return users.firstWhere((user) => user.id == review.userId); |     try { | ||||||
|  |       return _users.firstWhere((user) => user.id == review.userId); | ||||||
|  |     } catch(e) { | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
| @ -27,14 +31,18 @@ class _ReviewListState extends State<ReviewListPage> { | |||||||
|     final arg = ModalRoute.of(context)!.settings.arguments as models.ReviewList; |     final arg = ModalRoute.of(context)!.settings.arguments as models.ReviewList; | ||||||
|     final reviews = arg.reviews; |     final reviews = arg.reviews; | ||||||
| 
 | 
 | ||||||
|  |     if (reviews.isEmpty) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     final userIds = reviews.map((review) => review.userId).toSet().toList(); |     final userIds = reviews.map((review) => review.userId).toSet().toList(); | ||||||
| 
 | 
 | ||||||
|     final response = await api.request(context, api.ApiService.auth, 'GET', '/api/Users/UsersByIds?userIds=' + userIds.join(','), null); |     final response = await api.request(context, api.ApiService.auth, 'GET', '/api/Users/UsersByIds?userIds=' + userIds.join(','), null); | ||||||
|     if (response == null) return; |     if (response == null) return; | ||||||
| 
 | 
 | ||||||
|     debugPrint('response: ' + response); |     setState(() { | ||||||
| 
 |       _users = (jsonDecode(response) as List<dynamic>).map((user) => models.User.fromJson(user)).toList(); | ||||||
|     users = (jsonDecode(response) as List<dynamic>).map((user) => models.User.fromJson(user)).toList(); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
| @ -47,56 +55,73 @@ class _ReviewListState extends State<ReviewListPage> { | |||||||
|       selectedIndex: -1, |       selectedIndex: -1, | ||||||
|       body: Scaffold( |       body: Scaffold( | ||||||
|         backgroundColor: const Color(0xFFF9F9F9), |         backgroundColor: const Color(0xFFF9F9F9), | ||||||
|         body: SingleChildScrollView(child: Container( |         body: reviews.isEmpty | ||||||
|           decoration: const BoxDecoration(color: Color(0xFFF9F9F9)), |           ? const Center(child: Text('No reviews yet. Be the first to review this place')) | ||||||
|           width: MediaQuery.of(context).size.width, |           : SingleChildScrollView(child: Container( | ||||||
|           padding: const EdgeInsets.all(20.0), |             decoration: const BoxDecoration(color: Color(0xFFF9F9F9)), | ||||||
|           child: Column(children: |             width: MediaQuery.of(context).size.width, | ||||||
|             reviews.map((review) => Container( |             padding: const EdgeInsets.all(20.0), | ||||||
|               width: double.infinity, |             child: Column(children: [ | ||||||
|               padding: const EdgeInsets.all(20), |               for (final review in reviews) | ||||||
|               margin: const EdgeInsets.only(bottom: 10), |                 Container( | ||||||
|               decoration: const BoxDecoration( |                   width: double.infinity, | ||||||
|                 boxShadow: [ |                   padding: const EdgeInsets.all(20), | ||||||
|                   BoxShadow( |                   margin: const EdgeInsets.only(bottom: 10), | ||||||
|                     color: Color(0x20000000), |                   decoration: const BoxDecoration( | ||||||
|                     offset: Offset(0,1), |                     boxShadow: [ | ||||||
|                     blurRadius: 4, |                       BoxShadow( | ||||||
|  |                         color: Color(0x20000000), | ||||||
|  |                         offset: Offset(0,1), | ||||||
|  |                         blurRadius: 4, | ||||||
|  |                       ), | ||||||
|  |                     ], | ||||||
|  |                     color: Colors.white, | ||||||
|                   ), |                   ), | ||||||
|                 ], |                   child: Row( | ||||||
|                 color: Colors.white, |                     crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|               ), |                     children: [ | ||||||
|               child: Row( |                       Padding( | ||||||
|                 crossAxisAlignment: CrossAxisAlignment.start, |                         padding: const EdgeInsets.only(top: 3), | ||||||
|                 children: [ |                         child: | ||||||
|                   const Padding( |                           _getReviewUser(review)?.profilePicture.isNotEmpty == true | ||||||
|                     padding: EdgeInsets.only(top: 3), |                           ? ClipOval( | ||||||
|                     child: Icon(Icons.rate_review, color: Colors.purple, size: 36), |                               child: Image( | ||||||
|  |                                 image: NetworkImage(_getReviewUser(review)!.profilePicture), | ||||||
|  |                                 height: 36, | ||||||
|  |                                 width: 36, | ||||||
|  |                                 fit: BoxFit.cover, | ||||||
|  |                               ), | ||||||
|  |                             ) | ||||||
|  |                           : const Icon( | ||||||
|  |                             Icons.account_circle, | ||||||
|  |                             size: 36, | ||||||
|  |                             color: Colors.grey, | ||||||
|  |                           ) | ||||||
|  |                       ), | ||||||
|  |                       const SizedBox(width: 20), | ||||||
|  |                       Expanded( | ||||||
|  |                         child: Column( | ||||||
|  |                           crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |                           children: [ | ||||||
|  |                             Text(review.title, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 24)), | ||||||
|  |                             Text(review.content), | ||||||
|  |                             const SizedBox(height: 10), | ||||||
|  |                             if (review.image != null) Image.network(review.image!.imageUrl, height: 200), | ||||||
|  |                             if (review.image != null) const SizedBox(height: 15), | ||||||
|  |                             Row(children: [ | ||||||
|  |                               for (var i = 0; i < review.rating; i++) const Icon(Icons.star, color: Colors.yellow), | ||||||
|  |                               for (var i = review.rating; i < 5; i++) const Icon(Icons.star_border), | ||||||
|  |                             ]), | ||||||
|  |                             const SizedBox(height: 10), | ||||||
|  |                             Text('Submitted by ' + (_getReviewUser(review)?.username ?? ''), style: const TextStyle(color: Colors.grey, fontSize: 12)), | ||||||
|  |                           ], | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|  |                     ], | ||||||
|                   ), |                   ), | ||||||
|                   const SizedBox(width: 20), |                 ), | ||||||
|                   Expanded( |             ]), | ||||||
|                     child: Column( |           )), | ||||||
|                       crossAxisAlignment: CrossAxisAlignment.start, |  | ||||||
|                       children: [ |  | ||||||
|                         Text(review.title, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 24)), |  | ||||||
|                         Text(review.content), |  | ||||||
|                         const SizedBox(height: 10), |  | ||||||
|                         if (review.image != null) Image.network(review.image!.imageUrl, height: 200), |  | ||||||
|                         if (review.image != null) const SizedBox(height: 15), |  | ||||||
|                         Row(children: [ |  | ||||||
|                           for (var i = 0; i < review.rating; i++) const Icon(Icons.star, color: Colors.yellow), |  | ||||||
|                           for (var i = review.rating; i < 5; i++) const Icon(Icons.star_border), |  | ||||||
|                         ]), |  | ||||||
|                         const SizedBox(height: 10), |  | ||||||
|                         Text('Submitted by ' + (_getReviewUser(review)?.username ?? ''), style: const TextStyle(color: Colors.grey, fontSize: 12)), |  | ||||||
|                       ], |  | ||||||
|                     ), |  | ||||||
|                   ), |  | ||||||
|                 ], |  | ||||||
|               ), |  | ||||||
|             )).toList(), |  | ||||||
|           ), |  | ||||||
|         )), |  | ||||||
|         floatingActionButton: FloatingActionButton( |         floatingActionButton: FloatingActionButton( | ||||||
|           onPressed: () async { |           onPressed: () async { | ||||||
|             if (!await api.isLoggedIn(context)) { |             if (!await api.isLoggedIn(context)) { | ||||||
|  | |||||||
| @ -217,9 +217,11 @@ async fn create_review(auth: AuthorizedUser, data: web::Data<AppData>, input: we | |||||||
|             place_description: input.place_description.clone(), |             place_description: input.place_description.clone(), | ||||||
|             title: input.title.clone(), |             title: input.title.clone(), | ||||||
|             content: input.content.clone(), |             content: input.content.clone(), | ||||||
|             rating: input.rating.clone(), 
 |             rating: input.rating.clone(), | ||||||
|             image_id: input.image_id, |             image_id: input.image_id, | ||||||
|             image: None, |             image: input.image_id.and_then(|image_id| { | ||||||
|  |                 db.query_row("SELECT * FROM images WHERE id = :id LIMIT 1", &[(":id", &image_id.to_string())], |row| Image::from_row(row)).ok() | ||||||
|  |             }), | ||||||
|         }), |         }), | ||||||
|         Err(_) => HttpResponse::InternalServerError().finish(), |         Err(_) => HttpResponse::InternalServerError().finish(), | ||||||
|     } |     } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user