diff --git a/lib/components.dart b/lib/components.dart deleted file mode 100644 index f1ff1b7..0000000 --- a/lib/components.dart +++ /dev/null @@ -1,60 +0,0 @@ -import 'package:flutter/material.dart'; - -class RestaurantCard extends StatelessWidget { - RestaurantCard( - {@required this.id, this.name, this.city, this.imgUrl, this.tags}); - - final id; - final name; - final city; - final imgUrl; - final tags; - - @override - Widget build(BuildContext context) { - return Card( - child: Row( - crossAxisAlignment: CrossAxisAlignment.baseline, - children: [ - Container( - child: ClipRRect( - child: Image.asset( - "img/bg_tile.jpg", - width: 80, - height: 80, - ), - borderRadius: BorderRadius.all(Radius.circular(8)), - ), - padding: EdgeInsets.all(8), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - name, - style: TextStyle( - color: Colors.orange[600], fontSize: 16, height: 1.7), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Miasto: $city', - style: TextStyle(color: Colors.grey, fontSize: 14), - ), - Text( - 'Opis...', - style: TextStyle(color: Colors.grey, fontSize: 14), - ), - ], - ) - ], - ) - ], - ), - color: Color.fromRGBO(50, 50, 50, 0.8), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), - ); - } -} diff --git a/lib/components/restaurantCard.dart b/lib/components/restaurantCard.dart new file mode 100644 index 0000000..d5cf049 --- /dev/null +++ b/lib/components/restaurantCard.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:menui_mobile/services.dart'; + +class RestaurantCard extends StatelessWidget { + RestaurantCard({@required this.restaurant}); + + final Restaurant restaurant; + + @override + Widget build(BuildContext context) { + return Card( + child: InkWell( + onTap: () {}, + child: Row( + crossAxisAlignment: CrossAxisAlignment.baseline, + children: [ + Container( + child: ClipRRect( + child: Image.network( + restaurant.imgUrl, + width: 80, + height: 80, + fit: BoxFit.cover, + ), + borderRadius: BorderRadius.all(Radius.circular(8)), + ), + padding: EdgeInsets.all(8), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + restaurant.name, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Colors.orange[600], fontSize: 16, height: 1.6), + ), + Container( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Miasto: ${restaurant.city}', + overflow: TextOverflow.ellipsis, + style: TextStyle(color: Colors.grey, fontSize: 14), + ), + Text( + restaurant.description, + overflow: TextOverflow.ellipsis, + maxLines: 2, + style: TextStyle(color: Colors.grey, fontSize: 14), + ), + ], + )), + ], + )), + Container( + child: Icon( + Icons.arrow_right, + color: Colors.orange, + ), + ) + ], + ), + ), + color: Color.fromRGBO(50, 50, 50, 0.8), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + margin: EdgeInsets.symmetric(horizontal: 12), + ); + } +} diff --git a/lib/components/searchBar.dart b/lib/components/searchBar.dart index b9bda86..6d9e4e6 100644 --- a/lib/components/searchBar.dart +++ b/lib/components/searchBar.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:menui_mobile/main.dart'; import '../services.dart'; class MenuiSearchBar extends StatefulWidget { @@ -18,32 +19,50 @@ class MenuiSearchBarState extends State { var suggestions = []; bool suggestionsOpen = false; - Future fetchAutocomplete(text) async { - final List results = await services.fetchAutocomplete(text); + @override + void initState() { + super.initState(); + _controller.addListener(fetchAutocomplete); + } - setState(() { - suggestions = results; - }); + Future fetchAutocomplete() async { + if (_controller.text.isNotEmpty) { + final List results = + await services.fetchAutocomplete(_controller.text); - if (!suggestionsOpen && results.isNotEmpty) { setState(() { - suggestionsOpen = true; + suggestions = results; }); - _overlayEntry = _createOverlayEntry(); - Overlay.of(context).insert(_overlayEntry); + + if (!suggestionsOpen && results.isNotEmpty) { + setState(() { + suggestionsOpen = true; + }); + _overlayEntry = _createOverlayEntry(); + Overlay.of(context).insert(_overlayEntry); + } else if (results.isEmpty) { + hideSuggestions(); + } + print(suggestions); + } else { + hideSuggestions(); } - print(suggestions); } Future searchRestaurantsByString() async { final List results = await services.fetchSearchByString(_controller.text); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SearchResults(restaurants: results))); } void hideSuggestions() { if (suggestionsOpen) { _overlayEntry.remove(); setState(() { + suggestions = []; suggestionsOpen = false; }); } @@ -82,6 +101,7 @@ class MenuiSearchBarState extends State { return ListTile( onTap: () { _controller.text = suggestions[index]; + searchRestaurantsByString(); }, title: Text( suggestions[index], @@ -115,7 +135,7 @@ class MenuiSearchBarState extends State { padding: const EdgeInsets.all(12), child: TextFormField( controller: _controller, - onChanged: (text) => fetchAutocomplete(text), + //onChanged: (text) => fetchAutocomplete(text), style: TextStyle(color: Colors.orange), decoration: InputDecoration( hintStyle: TextStyle(color: Colors.grey), diff --git a/lib/main.dart b/lib/main.dart index 68bc761..6fb3822 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:menui_mobile/components/restaurantCard.dart'; import 'components/searchBar.dart'; +import 'services.dart'; void main() { runApp(App()); @@ -18,20 +20,22 @@ class App extends StatelessWidget { child: MaterialApp( title: 'Menui', theme: ThemeData( + platform: TargetPlatform.iOS, primarySwatch: Colors.orange, primaryColor: Colors.orange, accentColor: Colors.grey, backgroundColor: Colors.grey, visualDensity: VisualDensity.adaptivePlatformDensity, ), - home: HomePage(title: 'Menui - food guide'), + home: HomePage(), )); } } +// ROUTE --- HOME + class HomePage extends StatefulWidget { - HomePage({Key key, this.title}) : super(key: key); - final String title; + HomePage({Key key}) : super(key: key); @override _HomePageState createState() => _HomePageState(); @@ -58,6 +62,66 @@ class _HomePageState extends State { ), ), ), + floatingActionButton: FloatingActionButton( + onPressed: () {}, + child: Icon( + Icons.settings, + color: Colors.orange, + ), + backgroundColor: Colors.grey[850], + ), + ); + } +} + +// ROUTE --- SEARCH RESULTS + +class SearchResults extends StatelessWidget { + final List restaurants; + + SearchResults({@required this.restaurants}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage("img/bg_tile.jpg"), fit: BoxFit.cover)), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox( + height: 30, + ), + Image.asset( + "img/logo_mint.png", + width: 60, + ), + MenuiSearchBar(), + Row(children: [ + Container( + padding: EdgeInsets.only(left: 12), + child: Text( + 'Znaleziono: ${restaurants.length}', + style: TextStyle(color: Colors.grey), + ), + ) + ]), + Expanded( + child: ListView.builder( + itemCount: restaurants.length, + itemBuilder: (context, index) { + return RestaurantCard( + restaurant: restaurants[index], + ); + }, + )) + ], + ), + ), + ), ); } } diff --git a/lib/services.dart b/lib/services.dart index 2c8fbcf..829b98f 100644 --- a/lib/services.dart +++ b/lib/services.dart @@ -9,8 +9,11 @@ class MenuiServices { 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 citiesDynamic = jsonDecode(response.body)['cities']; + final List restaurantsDynamic = jsonDecode(response.body)['restaurants']; + final List cities = citiesDynamic.cast().toList(); + final List restaurants = + restaurantsDynamic.cast().toList(); final List result = [...cities, ...restaurants]; return result; @@ -39,17 +42,55 @@ class MenuiServices { final response = await http.get('${backendURL}search?string=$text'); if (response.statusCode == 200 || response.statusCode == 304) { final List decoded = jsonDecode(response.body); - List results; + List results = []; for (var restaurant in decoded) { + final workingHours = restaurant['workingHours']; + final tags = restaurant['tags']; + final links = restaurant['links']; + final List responseLunchMenu = restaurant['lunchMenu']; + List lunchMenu = []; + if (responseLunchMenu != null) { + for (var lunchSet in responseLunchMenu) { + final MenuiLunchMenuSet thisSet = new MenuiLunchMenuSet( + lunchSet['lunchSetName'], + lunchSet['lunchSetPrice'], + lunchSet['lunchSetDishes']); + lunchMenu.add(thisSet); + } + } final result = new Restaurant( id: restaurant['_id'], name: restaurant['name'], city: restaurant['city'], adress: restaurant['adress'], coordinates: restaurant['coordinates'], - imgUrl: restaurant['imgUrl']); + imgUrl: restaurant['imgUrl'], + placesId: restaurant['placesId'], + workingHours: new MenuiWorkingHours( + workingHours['pn'], + workingHours['wt'], + workingHours['sr'], + workingHours['cz'], + workingHours['pt'], + workingHours['sb'], + workingHours['nd']), + description: restaurant['description'], + tags: new MenuiTags( + tags['cardPayments'], + tags['petFriendly'], + tags['glutenFree'], + tags['vegan'], + tags['vegetarian'], + tags['alcohol'], + tags['delivery']), + links: new MenuiLinks( + links['facebook'], links['instagram'], links['www']), + phone: restaurant['phone'], + categories: restaurant['categories'], + lunchHours: restaurant['lunchHours'], + lunchMenu: lunchMenu, + dishes: restaurant['dishes']); results.add(result); - print(result.name); } return results; } else { @@ -75,7 +116,7 @@ class Restaurant { String phone; List categories; String lunchHours; - MenuiLunchMenu lunchMenu; + List lunchMenu; List dishes; Restaurant( @@ -143,12 +184,12 @@ class MenuiAllergens { this.peanuts, this.sesame); } -class MenuiLunchMenu { +class MenuiLunchMenuSet { String lunchSetName; String lunchSetPrice; List lunchSetDishes; - MenuiLunchMenu(this.lunchSetName, this.lunchSetPrice, this.lunchSetDishes); + MenuiLunchMenuSet(this.lunchSetName, this.lunchSetPrice, this.lunchSetDishes); } class MenuiLinks {