diff --git a/lib/components.dart b/lib/components.dart index 67558a0..f1ff1b7 100644 --- a/lib/components.dart +++ b/lib/components.dart @@ -1,7 +1,4 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; -import 'package:http/http.dart' as http; class RestaurantCard extends StatelessWidget { RestaurantCard( @@ -61,135 +58,3 @@ class RestaurantCard extends StatelessWidget { ); } } - -class MenuiSearchBar extends StatefulWidget { - @override - MenuiSearchBarState createState() { - return MenuiSearchBarState(); - } -} - -class MenuiSearchBarState extends State { - final _formKey = GlobalKey(); - var suggestions = []; - bool suggestionsOpen = false; - final LayerLink layerLink = LayerLink(); - OverlayEntry _overlayEntry; - - Future fetchAutocomplete(text) async { - final response = await http.get( - 'https://menui.azurewebsites.net/search/autocomplete?string=$text'); - final cities = jsonDecode(response.body)['cities']; - final restaurants = jsonDecode(response.body)['restaurants']; - final List result = [...cities, ...restaurants]; - - setState(() { - suggestions = result; - }); - - if (!suggestionsOpen && result.isNotEmpty) { - setState(() { - suggestionsOpen = true; - }); - _overlayEntry = _createOverlayEntry(); - Overlay.of(context).insert(_overlayEntry); - } - print(suggestions); - } - - void hideSuggestions() { - if (suggestionsOpen) { - _overlayEntry.remove(); - setState(() { - suggestionsOpen = false; - }); - } - } - - OverlayEntry _createOverlayEntry() { - RenderBox renderBox = context.findRenderObject(); - var size = renderBox.size; - - return OverlayEntry( - builder: (context) => GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: () { - hideSuggestions(); - }, - child: Align( - alignment: Alignment.topCenter, - child: Stack( - children: [ - Positioned( - width: size.width, - child: CompositedTransformFollower( - offset: Offset(0.0, size.height + 5.0), - link: layerLink, - showWhenUnlinked: false, - child: Material( - color: Colors.grey[800], - elevation: 4.0, - child: ConstrainedBox( - constraints: new BoxConstraints(maxHeight: 200), - child: ListView.builder( - padding: EdgeInsets.zero, - shrinkWrap: true, - itemCount: suggestions.length, - itemBuilder: (context, index) { - return ListTile( - title: Text( - suggestions[index], - style: TextStyle(color: Colors.orange), - ), - ); - }), - ), - ), - ), - ) - ], - )))); - } - - @override - Widget build(BuildContext context) { - return Form( - key: _formKey, - child: CompositedTransformTarget( - link: layerLink, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(12), - child: TextFormField( - onChanged: (text) => fetchAutocomplete(text), - style: TextStyle(color: Colors.orange), - decoration: InputDecoration( - hintStyle: TextStyle(color: Colors.grey), - enabledBorder: OutlineInputBorder( - borderSide: - BorderSide(color: Colors.grey, width: 1.0), - borderRadius: BorderRadius.circular(12)), - focusedBorder: OutlineInputBorder( - borderSide: - BorderSide(color: Colors.orange, width: 2.0), - borderRadius: BorderRadius.circular(12)), - hintText: 'Wyszukaj miasto lub nazwę restauracji.', - suffixIcon: Icon( - Icons.search, - color: Colors.orange, - )), - validator: (value) { - if (value.isEmpty) { - return 'Wpisz coś w pole wyszukiwania.'; - } - return null; - }, - cursorColor: Colors.orange, - ), - ), - ], - ), - )); - } -} diff --git a/lib/components/searchBar.dart b/lib/components/searchBar.dart new file mode 100644 index 0000000..b9bda86 --- /dev/null +++ b/lib/components/searchBar.dart @@ -0,0 +1,148 @@ +import 'package:flutter/material.dart'; +import '../services.dart'; + +class MenuiSearchBar extends StatefulWidget { + @override + MenuiSearchBarState createState() { + return MenuiSearchBarState(); + } +} + +class MenuiSearchBarState extends State { + final MenuiServices services = new MenuiServices(); + final _formKey = GlobalKey(); + final LayerLink layerLink = LayerLink(); + OverlayEntry _overlayEntry; + final _controller = TextEditingController(); + + var suggestions = []; + bool suggestionsOpen = false; + + Future fetchAutocomplete(text) async { + final List results = await services.fetchAutocomplete(text); + + setState(() { + suggestions = results; + }); + + if (!suggestionsOpen && results.isNotEmpty) { + setState(() { + suggestionsOpen = true; + }); + _overlayEntry = _createOverlayEntry(); + Overlay.of(context).insert(_overlayEntry); + } + print(suggestions); + } + + Future searchRestaurantsByString() async { + final List results = + await services.fetchSearchByString(_controller.text); + } + + void hideSuggestions() { + if (suggestionsOpen) { + _overlayEntry.remove(); + setState(() { + suggestionsOpen = false; + }); + } + } + + OverlayEntry _createOverlayEntry() { + RenderBox renderBox = context.findRenderObject(); + var size = renderBox.size; + + return OverlayEntry( + builder: (context) => GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () { + hideSuggestions(); + }, + child: Align( + alignment: Alignment.topCenter, + child: Stack( + children: [ + Positioned( + width: size.width, + child: CompositedTransformFollower( + offset: Offset(0.0, size.height + 5.0), + link: layerLink, + showWhenUnlinked: false, + child: Material( + color: Colors.grey[800], + elevation: 4.0, + child: ConstrainedBox( + constraints: new BoxConstraints(maxHeight: 200), + child: ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: suggestions.length, + itemBuilder: (context, index) { + return ListTile( + onTap: () { + _controller.text = suggestions[index]; + }, + title: Text( + suggestions[index], + style: TextStyle(color: Colors.orange), + ), + ); + }), + ), + ), + ), + ) + ], + )))); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Form( + key: _formKey, + child: CompositedTransformTarget( + link: layerLink, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(12), + child: TextFormField( + controller: _controller, + onChanged: (text) => fetchAutocomplete(text), + style: TextStyle(color: Colors.orange), + decoration: InputDecoration( + hintStyle: TextStyle(color: Colors.grey), + enabledBorder: OutlineInputBorder( + borderSide: + BorderSide(color: Colors.grey, width: 1.0), + borderRadius: BorderRadius.circular(12)), + focusedBorder: OutlineInputBorder( + borderSide: + BorderSide(color: Colors.orange, width: 2.0), + borderRadius: BorderRadius.circular(12)), + hintText: 'Wyszukaj miasto lub nazwę restauracji.', + suffixIcon: Icon( + Icons.search, + color: Colors.orange, + )), + validator: (value) { + if (value.isEmpty) { + return 'Wpisz coś w pole wyszukiwania.'; + } + return null; + }, + cursorColor: Colors.orange, + ), + ), + ], + ), + )); + } +} diff --git a/lib/dataTypes.dart b/lib/dataTypes.dart deleted file mode 100644 index 8b13789..0000000 --- a/lib/dataTypes.dart +++ /dev/null @@ -1 +0,0 @@ - diff --git a/lib/main.dart b/lib/main.dart index e7d6785..68bc761 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'components.dart'; +import 'components/searchBar.dart'; void main() { runApp(App()); diff --git a/lib/services.dart b/lib/services.dart new file mode 100644 index 0000000..2c8fbcf --- /dev/null +++ b/lib/services.dart @@ -0,0 +1,186 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; +import 'package:flutter/foundation.dart'; + +class MenuiServices { + final String backendURL = 'https://menui.azurewebsites.net/'; + + Future> fetchAutocomplete(String text) async { + final response = + await http.get('${backendURL}search/autocomplete?string=$text'); + if (response.statusCode == 200 || response.statusCode == 304) { + final List cities = jsonDecode(response.body)['cities']; + final List restaurants = jsonDecode(response.body)['restaurants']; + final List result = [...cities, ...restaurants]; + + return result; + } else { + print("coś tu nie zagrało podczas pobierania sugestii"); + return []; + } + } + + Future fetchDish(String id) async { + final response = await http.get('${backendURL}dish?dishId=$id'); + if (response.statusCode == 200 || response.statusCode == 304) { + final decoded = jsonDecode(response.body); + final result = new Dish( + id: decoded['_id'], + restaurantId: decoded['restaurantId'], + name: decoded['name'], + category: decoded['category']); + return result; + } else { + throw "Nie udało się pobrać"; + } + } + + Future> fetchSearchByString(String text) async { + final response = await http.get('${backendURL}search?string=$text'); + if (response.statusCode == 200 || response.statusCode == 304) { + final List decoded = jsonDecode(response.body); + List results; + for (var restaurant in decoded) { + final result = new Restaurant( + id: restaurant['_id'], + name: restaurant['name'], + city: restaurant['city'], + adress: restaurant['adress'], + coordinates: restaurant['coordinates'], + imgUrl: restaurant['imgUrl']); + results.add(result); + print(result.name); + } + return results; + } else { + return []; + } + } +} + +// DATA TYPES + +class Restaurant { + String id; + String name; + String city; + String adress; + List coordinates; + String placesId; + String imgUrl; + MenuiWorkingHours workingHours; + String description; + MenuiTags tags; + MenuiLinks links; + String phone; + List categories; + String lunchHours; + MenuiLunchMenu lunchMenu; + List dishes; + + Restaurant( + {@required this.id, + @required this.name, + @required this.city, + @required this.adress, + @required this.coordinates, + this.placesId, + @required this.imgUrl, + this.workingHours, + this.description, + this.tags, + this.links, + this.phone, + this.categories, + this.lunchHours, + this.lunchMenu, + this.dishes}); +} + +class Dish { + String id; + String restaurantId; + String name; + String category; + String price; + String notes; + String imgUrl; + String weight; + MenuiAllergens allergens; + String ingredients; + String glicemicIndex; + String kCal; + bool vegan; + bool vegetarian; + + Dish( + {@required this.id, + @required this.restaurantId, + @required this.name, + @required this.category, + this.price, + this.notes, + this.imgUrl, + this.weight, + this.allergens, + this.ingredients, + this.glicemicIndex, + this.kCal, + this.vegan, + this.vegetarian}); +} + +class MenuiAllergens { + bool gluten; + bool lactose; + bool soy; + bool eggs; + bool seaFood; + bool peanuts; + bool sesame; + + MenuiAllergens(this.gluten, this.lactose, this.soy, this.eggs, this.seaFood, + this.peanuts, this.sesame); +} + +class MenuiLunchMenu { + String lunchSetName; + String lunchSetPrice; + List lunchSetDishes; + + MenuiLunchMenu(this.lunchSetName, this.lunchSetPrice, this.lunchSetDishes); +} + +class MenuiLinks { + String facebook; + String instagram; + String www; + + MenuiLinks(this.facebook, this.instagram, this.www); +} + +class MenuiTags { + bool cardPayments; + bool petFriendly; + bool glutenFree; + bool vegan; + bool vegetarian; + bool alcohol; + bool delivery; + + MenuiTags(this.cardPayments, this.petFriendly, this.glutenFree, this.vegan, + this.vegetarian, this.alcohol, this.delivery); +} + +class MenuiWorkingHours { + String pn; + String wt; + String sr; + String cz; + String pt; + String sb; + String nd; + + MenuiWorkingHours( + this.pn, this.wt, this.sr, this.cz, this.pt, this.sb, this.nd); +}