bare implementation of comuncation with the api
All checks were successful
Build and push docker image / Build (pull_request) Successful in 2m6s
Build and release APK / Build APK (pull_request) Successful in 4m32s

This commit is contained in:
Remy Moll 2024-08-01 22:48:28 +02:00
parent 016622c7af
commit 5748630b99
5 changed files with 94 additions and 39 deletions

View File

@ -20,26 +20,40 @@ class Greeter extends StatefulWidget {
class _GreeterState extends State<Greeter> {
Widget greeterBuild (BuildContext context, AsyncSnapshot<Trip> 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(

View File

@ -63,9 +63,8 @@ class _NewTripPageState extends State<NewTripPage> {
double.parse(latController.text),
double.parse(lonController.text)
];
UserPreferences preferences = UserPreferences();
preferences.load();
Future<Trip> trip = fetchTrip(startPoint, preferences);
Future<UserPreferences> preferences = loadUserPreferences();
Future<Trip>? trip = fetchTrip(startPoint, preferences);
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => BasePage(mainScreen: "map", trip: trip)

View File

@ -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<String, dynamic> 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
};
}
''';
}
}

View File

@ -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<Landmark> 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<String, dynamic> 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<String, dynamic> toJson() => {
'uuid': uuid,
'city_name': cityName,
'entry_uuid': landmarks.first?.uuid ?? ''
'first_landmark_uuid': landmarks.first.uuid
};

View File

@ -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<Trip> fetchTrip(
Future<Trip>? fetchTrip(
List<double> startPoint,
UserPreferences preferences,
Future<UserPreferences> preferences,
) 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(
"/trip/new",
data: {
'preferences': preferences.toJson(),
'start': startPoint
}
data: data
);
// handle errors
@ -40,6 +49,37 @@ Future<Trip> fetchTrip(
if (response.data["error"] != null) {
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);
}