Tentatively enable communication between front + backend #15
@@ -20,26 +20,40 @@ class Greeter extends StatefulWidget {
 | 
				
			|||||||
class _GreeterState extends State<Greeter> {
 | 
					class _GreeterState extends State<Greeter> {
 | 
				
			||||||
  Widget greeterBuild (BuildContext context, AsyncSnapshot<Trip> snapshot) {
 | 
					  Widget greeterBuild (BuildContext context, AsyncSnapshot<Trip> snapshot) {
 | 
				
			||||||
    ThemeData theme = Theme.of(context);
 | 
					    ThemeData theme = Theme.of(context);
 | 
				
			||||||
    String cityName = "";
 | 
					    Widget topGreeter;
 | 
				
			||||||
    if (snapshot.hasData) {
 | 
					    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) {
 | 
					    } else if (snapshot.hasError) {
 | 
				
			||||||
      cityName = "error";
 | 
					      topGreeter = const Padding(
 | 
				
			||||||
    } else { // still awaiting the cityname
 | 
					        padding: EdgeInsets.only(top: 20, bottom: 20),
 | 
				
			||||||
      cityName = "...";
 | 
					        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) {
 | 
					    if (widget.standalone) {
 | 
				
			||||||
      return Center(
 | 
					      return Center(
 | 
				
			||||||
        child: Padding(
 | 
					 | 
				
			||||||
          padding: EdgeInsets.only(top: 24.0),
 | 
					 | 
				
			||||||
        child: topGreeter,
 | 
					        child: topGreeter,
 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      return Center(
 | 
					      return Center(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -63,9 +63,8 @@ class _NewTripPageState extends State<NewTripPage> {
 | 
				
			|||||||
                        double.parse(latController.text),
 | 
					                        double.parse(latController.text),
 | 
				
			||||||
                        double.parse(lonController.text)
 | 
					                        double.parse(lonController.text)
 | 
				
			||||||
                      ];
 | 
					                      ];
 | 
				
			||||||
                      UserPreferences preferences = UserPreferences();
 | 
					                      Future<UserPreferences> preferences = loadUserPreferences();
 | 
				
			||||||
                      preferences.load();
 | 
					                      Future<Trip>? trip = fetchTrip(startPoint, preferences);
 | 
				
			||||||
                      Future<Trip> trip = fetchTrip(startPoint, preferences);
 | 
					 | 
				
			||||||
                        Navigator.of(context).push(
 | 
					                        Navigator.of(context).push(
 | 
				
			||||||
                          MaterialPageRoute(
 | 
					                          MaterialPageRoute(
 | 
				
			||||||
                            builder: (context) => BasePage(mainScreen: "map", trip: trip)
 | 
					                            builder: (context) => BasePage(mainScreen: "map", trip: trip)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,17 +82,15 @@ class UserPreferences {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  String toJson() {
 | 
					  Map<String, dynamic> toJson() {
 | 
				
			||||||
      // This is "opinionated" JSON, corresponding to the backend's expectations
 | 
					      // This is "opinionated" JSON, corresponding to the backend's expectations
 | 
				
			||||||
    return '''
 | 
					      return {
 | 
				
			||||||
    {
 | 
					        "sightseeing": {"type": "sightseeing", "score": sightseeing.value},
 | 
				
			||||||
      "sightseeing": {"type": "sightseeing", "score": ${sightseeing.value}},
 | 
					        "shopping": {"type": "shopping", "score": shopping.value},
 | 
				
			||||||
      "shopping": {"type": "shopping", "score": ${shopping.value}},
 | 
					        "nature": {"type": "nature", "score": nature.value},
 | 
				
			||||||
      "nature": {"type": "nature", "score": ${nature.value}},
 | 
					        "max_time_minute": maxTime.value,
 | 
				
			||||||
      "max_time_minutes": ${maxTime.value},
 | 
					        "detour_tolerance_minute": maxDetour.value
 | 
				
			||||||
      "detour_tolerance_minute": ${maxDetour.value}
 | 
					      };
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    ''';
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,6 +11,7 @@ class Trip {
 | 
				
			|||||||
  final String uuid;
 | 
					  final String uuid;
 | 
				
			||||||
  final String cityName;
 | 
					  final String cityName;
 | 
				
			||||||
  // TODO: cityName should be inferred from coordinates of the Landmarks
 | 
					  // TODO: cityName should be inferred from coordinates of the Landmarks
 | 
				
			||||||
 | 
					  final int totalTime;
 | 
				
			||||||
  final LinkedList<Landmark> landmarks;
 | 
					  final LinkedList<Landmark> landmarks;
 | 
				
			||||||
  // could be empty as well
 | 
					  // could be empty as well
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -19,15 +20,18 @@ class Trip {
 | 
				
			|||||||
    required this.uuid,
 | 
					    required this.uuid,
 | 
				
			||||||
    required this.cityName,
 | 
					    required this.cityName,
 | 
				
			||||||
    required this.landmarks,
 | 
					    required this.landmarks,
 | 
				
			||||||
 | 
					    this.totalTime = 0
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  factory Trip.fromJson(Map<String, dynamic> json) {
 | 
					  factory Trip.fromJson(Map<String, dynamic> json) {
 | 
				
			||||||
    return Trip(
 | 
					    Trip trip = Trip(
 | 
				
			||||||
      uuid: json['uuid'],
 | 
					      uuid: json['uuid'],
 | 
				
			||||||
      cityName: json['city_name'],
 | 
					      cityName: json['city_name'] ?? 'Not communicated',
 | 
				
			||||||
      landmarks: LinkedList()
 | 
					      landmarks: LinkedList()
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return trip;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -44,7 +48,7 @@ class Trip {
 | 
				
			|||||||
  Map<String, dynamic> toJson() => {
 | 
					  Map<String, dynamic> toJson() => {
 | 
				
			||||||
    'uuid': uuid,
 | 
					    'uuid': uuid,
 | 
				
			||||||
    'city_name': cityName,
 | 
					    'city_name': cityName,
 | 
				
			||||||
    'entry_uuid': landmarks.first?.uuid ?? ''
 | 
					    'first_landmark_uuid': landmarks.first.uuid
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +1,19 @@
 | 
				
			|||||||
 | 
					import "dart:convert";
 | 
				
			||||||
 | 
					import "dart:developer";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'package:dio/dio.dart';
 | 
					import 'package:dio/dio.dart';
 | 
				
			||||||
import 'package:anyway/constants.dart';
 | 
					import 'package:anyway/constants.dart';
 | 
				
			||||||
import "package:anyway/structs/landmark.dart";
 | 
					import "package:anyway/structs/landmark.dart";
 | 
				
			||||||
import "package:anyway/structs/trip.dart";
 | 
					import "package:anyway/structs/trip.dart";
 | 
				
			||||||
import "package:anyway/structs/preferences.dart";
 | 
					import "package:anyway/structs/preferences.dart";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "package:anyway/structs/linked_landmarks.dart";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Dio dio = Dio(
 | 
					Dio dio = Dio(
 | 
				
			||||||
    BaseOptions(
 | 
					    BaseOptions(
 | 
				
			||||||
      baseUrl: API_URL_BASE,
 | 
					      baseUrl: API_URL_BASE,
 | 
				
			||||||
 | 
					      // baseUrl: 'http://localhost:8000',
 | 
				
			||||||
      connectTimeout: const Duration(seconds: 5),
 | 
					      connectTimeout: const Duration(seconds: 5),
 | 
				
			||||||
      receiveTimeout: const Duration(seconds: 60),
 | 
					      receiveTimeout: const Duration(seconds: 120),
 | 
				
			||||||
      // api is notoriously slow
 | 
					      // api is notoriously slow
 | 
				
			||||||
      // headers: {
 | 
					      // headers: {
 | 
				
			||||||
      //   HttpHeaders.userAgentHeader: 'dio',
 | 
					      //   HttpHeaders.userAgentHeader: 'dio',
 | 
				
			||||||
@@ -18,19 +21,25 @@ Dio dio = Dio(
 | 
				
			|||||||
      // },
 | 
					      // },
 | 
				
			||||||
      contentType: Headers.jsonContentType,
 | 
					      contentType: Headers.jsonContentType,
 | 
				
			||||||
      responseType: ResponseType.json,
 | 
					      responseType: ResponseType.json,
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
  ),
 | 
					  ),
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Future<Trip> fetchTrip(
 | 
					Future<Trip>? fetchTrip(
 | 
				
			||||||
  List<double> startPoint,
 | 
					  List<double> startPoint,
 | 
				
			||||||
  UserPreferences preferences,
 | 
					  Future<UserPreferences> preferences,
 | 
				
			||||||
) async {
 | 
					) async {
 | 
				
			||||||
 | 
					  UserPreferences prefs = await preferences;
 | 
				
			||||||
 | 
					  Map<String, dynamic> data = {
 | 
				
			||||||
 | 
					    "preferences": prefs.toJson(),
 | 
				
			||||||
 | 
					    "start": startPoint
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  String dataString = jsonEncode(data);
 | 
				
			||||||
 | 
					  log(dataString);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  final response = await dio.post(
 | 
					  final response = await dio.post(
 | 
				
			||||||
    "/trip/new",
 | 
					    "/trip/new",
 | 
				
			||||||
    data: {
 | 
					    data: data
 | 
				
			||||||
      'preferences': preferences.toJson(),
 | 
					 | 
				
			||||||
      'start': startPoint
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // handle errors
 | 
					  // handle errors
 | 
				
			||||||
@@ -40,6 +49,37 @@ Future<Trip> fetchTrip(
 | 
				
			|||||||
  if (response.data["error"] != null) {
 | 
					  if (response.data["error"] != null) {
 | 
				
			||||||
    throw Exception(response.data["error"]);
 | 
					    throw Exception(response.data["error"]);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return Trip.fromJson(response.data);
 | 
					  log(response.data.toString());
 | 
				
			||||||
 | 
					  Map<String, dynamic> 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<String, dynamic> json = response.data;
 | 
				
			||||||
 | 
					  String? nextUUID = json["next_uuid"];
 | 
				
			||||||
 | 
					  return (Landmark.fromJson(json), nextUUID);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user