diff --git a/frontend/lib/modules/greeter.dart b/frontend/lib/modules/greeter.dart index f07f9f7..77e55de 100644 --- a/frontend/lib/modules/greeter.dart +++ b/frontend/lib/modules/greeter.dart @@ -20,26 +20,40 @@ class Greeter extends StatefulWidget { class _GreeterState extends State { Widget greeterBuild (BuildContext context, AsyncSnapshot snapshot) { ThemeData theme = Theme.of(context); - String cityName = ""; + Widget topGreeter; if (snapshot.hasData) { - cityName = snapshot.data?.cityName ?? '...'; + topGreeter = Padding( + padding: const EdgeInsets.only(top: 20, bottom: 20), + child: Text( + 'Welcome to ${snapshot.data?.cityName}!', + style: TextStyle(color: theme.primaryColor, fontWeight: FontWeight.bold, fontSize: 24), + ) + ); } else if (snapshot.hasError) { - cityName = "error"; - } else { // still awaiting the cityname - cityName = "..."; + topGreeter = const Padding( + padding: EdgeInsets.only(top: 20, bottom: 20), + child: Text('Error while fetching trip') + ); + } else { + // still awaiting the cityname + // Show a linear loader at the bottom and an info message above + topGreeter = Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only(top: 20, bottom: 20), + child: const Text('Generating your trip...', style: TextStyle(fontSize: 20),) + ), + const LinearProgressIndicator() + ] + ); } - Widget topGreeter = Text( - 'Welcome to $cityName!', - style: TextStyle(color: theme.primaryColor, fontWeight: FontWeight.bold, fontSize: 24), - ); + if (widget.standalone) { return Center( - child: Padding( - padding: EdgeInsets.only(top: 24.0), - child: topGreeter, - ), + child: topGreeter, ); } else { return Center( diff --git a/frontend/lib/pages/new_trip.dart b/frontend/lib/pages/new_trip.dart index a10a046..2464177 100644 --- a/frontend/lib/pages/new_trip.dart +++ b/frontend/lib/pages/new_trip.dart @@ -63,9 +63,8 @@ class _NewTripPageState extends State { double.parse(latController.text), double.parse(lonController.text) ]; - UserPreferences preferences = UserPreferences(); - preferences.load(); - Future trip = fetchTrip(startPoint, preferences); + Future preferences = loadUserPreferences(); + Future? trip = fetchTrip(startPoint, preferences); Navigator.of(context).push( MaterialPageRoute( builder: (context) => BasePage(mainScreen: "map", trip: trip) diff --git a/frontend/lib/structs/preferences.dart b/frontend/lib/structs/preferences.dart index d86b361..074bbde 100644 --- a/frontend/lib/structs/preferences.dart +++ b/frontend/lib/structs/preferences.dart @@ -82,18 +82,16 @@ class UserPreferences { } } - String toJson() { - // This is "opinionated" JSON, corresponding to the backend's expectations - return ''' - { - "sightseeing": {"type": "sightseeing", "score": ${sightseeing.value}}, - "shopping": {"type": "shopping", "score": ${shopping.value}}, - "nature": {"type": "nature", "score": ${nature.value}}, - "max_time_minutes": ${maxTime.value}, - "detour_tolerance_minute": ${maxDetour.value} + Map toJson() { + // This is "opinionated" JSON, corresponding to the backend's expectations + return { + "sightseeing": {"type": "sightseeing", "score": sightseeing.value}, + "shopping": {"type": "shopping", "score": shopping.value}, + "nature": {"type": "nature", "score": nature.value}, + "max_time_minute": maxTime.value, + "detour_tolerance_minute": maxDetour.value + }; } - '''; - } } diff --git a/frontend/lib/structs/trip.dart b/frontend/lib/structs/trip.dart index c43188c..f6d94e3 100644 --- a/frontend/lib/structs/trip.dart +++ b/frontend/lib/structs/trip.dart @@ -11,6 +11,7 @@ class Trip { final String uuid; final String cityName; // TODO: cityName should be inferred from coordinates of the Landmarks + final int totalTime; final LinkedList landmarks; // could be empty as well @@ -19,15 +20,18 @@ class Trip { required this.uuid, required this.cityName, required this.landmarks, + this.totalTime = 0 }); factory Trip.fromJson(Map json) { - return Trip( + Trip trip = Trip( uuid: json['uuid'], - cityName: json['city_name'], + cityName: json['city_name'] ?? 'Not communicated', landmarks: LinkedList() ); + + return trip; } @@ -44,7 +48,7 @@ class Trip { Map toJson() => { 'uuid': uuid, 'city_name': cityName, - 'entry_uuid': landmarks.first?.uuid ?? '' + 'first_landmark_uuid': landmarks.first.uuid }; diff --git a/frontend/lib/utils/fetch_trip.dart b/frontend/lib/utils/fetch_trip.dart index c1d17e7..aeba3b8 100644 --- a/frontend/lib/utils/fetch_trip.dart +++ b/frontend/lib/utils/fetch_trip.dart @@ -1,16 +1,19 @@ +import "dart:convert"; +import "dart:developer"; + import 'package:dio/dio.dart'; import 'package:anyway/constants.dart'; import "package:anyway/structs/landmark.dart"; import "package:anyway/structs/trip.dart"; import "package:anyway/structs/preferences.dart"; -import "package:anyway/structs/linked_landmarks.dart"; Dio dio = Dio( BaseOptions( baseUrl: API_URL_BASE, + // baseUrl: 'http://localhost:8000', connectTimeout: const Duration(seconds: 5), - receiveTimeout: const Duration(seconds: 60), + receiveTimeout: const Duration(seconds: 120), // api is notoriously slow // headers: { // HttpHeaders.userAgentHeader: 'dio', @@ -18,19 +21,25 @@ Dio dio = Dio( // }, contentType: Headers.jsonContentType, responseType: ResponseType.json, + ), ); -Future fetchTrip( +Future? fetchTrip( List startPoint, - UserPreferences preferences, + Future preferences, ) async { + UserPreferences prefs = await preferences; + Map data = { + "preferences": prefs.toJson(), + "start": startPoint + }; + String dataString = jsonEncode(data); + log(dataString); + final response = await dio.post( "/trip/new", - data: { - 'preferences': preferences.toJson(), - 'start': startPoint - } + data: data ); // handle errors @@ -40,6 +49,37 @@ Future fetchTrip( if (response.data["error"] != null) { throw Exception(response.data["error"]); } - return Trip.fromJson(response.data); + log(response.data.toString()); + Map json = response.data; + + // only fetch the trip "meta" data for now + Trip trip = Trip.fromJson(json); + + String? nextUUID = json["first_landmark_uuid"]; + while (nextUUID != null) { + var (landmark, newUUID) = await fetchLandmark(nextUUID); + trip.landmarks.add(landmark); + nextUUID = newUUID; + } + return trip; } + + +Future<(Landmark, String?)> fetchLandmark(String uuid) async { + final response = await dio.get( + "/landmark/$uuid" + ); + + // handle errors + if (response.statusCode != 200) { + throw Exception('Failed to load landmark'); + } + if (response.data["error"] != null) { + throw Exception(response.data["error"]); + } + log(response.data.toString()); + Map json = response.data; + String? nextUUID = json["next_uuid"]; + return (Landmark.fromJson(json), nextUUID); +}