feat(wip): Update entities and adopt a proper repository workflow for trip "obtention"
This commit is contained in:
142
frontend/lib/data/datasources/trip_remote_datasource.dart
Normal file
142
frontend/lib/data/datasources/trip_remote_datasource.dart
Normal file
@@ -0,0 +1,142 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
abstract class TripRemoteDataSource {
|
||||
/// Fetch available landmarks for the provided preferences/start payload.
|
||||
Future<List<Map<String, dynamic>>> fetchLandmarks(Map<String, dynamic> body);
|
||||
|
||||
/// Create a new trip using the optimizer payload (that includes landmarks).
|
||||
Future<Map<String, dynamic>> createTrip(Map<String, dynamic> body);
|
||||
|
||||
/// Fetch an existing trip by UUID
|
||||
Future<Map<String, dynamic>> fetchTrip(String uuid);
|
||||
}
|
||||
|
||||
class TripRemoteDataSourceImpl implements TripRemoteDataSource {
|
||||
final Dio dio;
|
||||
|
||||
TripRemoteDataSourceImpl({required this.dio});
|
||||
|
||||
@override
|
||||
Future<List<Map<String, dynamic>>> fetchLandmarks(Map<String, dynamic> body) async {
|
||||
final response = await dio.post('/get/landmarks', data: body);
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Server error fetching landmarks: ${response.statusCode}');
|
||||
}
|
||||
|
||||
if (response.data is! List) {
|
||||
throw Exception('Unexpected landmarks response format');
|
||||
}
|
||||
|
||||
return _normalizeLandmarks(List<dynamic>.from(response.data as List));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>> createTrip(Map<String, dynamic> body) async {
|
||||
log('Creating trip with body: $body');
|
||||
// convert body to actual json
|
||||
String bodyJson = jsonEncode(body);
|
||||
log('Trip request JSON: $bodyJson');
|
||||
final response = await dio.post('/optimize/trip', data: body);
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Server error: ${response.statusCode}');
|
||||
}
|
||||
|
||||
if (response.data is! Map<String, dynamic>) {
|
||||
throw Exception('Unexpected response format');
|
||||
}
|
||||
|
||||
final Map<String, dynamic> json = Map<String, dynamic>.from(response.data as Map);
|
||||
|
||||
_ensureLandmarks(json);
|
||||
if (json.containsKey('landmarks') && json['landmarks'] is List) {
|
||||
return json;
|
||||
}
|
||||
|
||||
final String? firstUuid = json['first_landmark_uuid'] as String?;
|
||||
if (firstUuid == null) {
|
||||
return json;
|
||||
}
|
||||
|
||||
final List<Map<String, dynamic>> landmarks = [];
|
||||
String? next = firstUuid;
|
||||
while (next != null) {
|
||||
final lm = await _fetchLandmarkByUuid(next);
|
||||
landmarks.add(lm);
|
||||
final dynamic nxt = lm['next_uuid'];
|
||||
next = (nxt is String) ? nxt : null;
|
||||
}
|
||||
|
||||
json['landmarks'] = landmarks;
|
||||
return json;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>> fetchTrip(String uuid) async {
|
||||
final response = await dio.get('/trip/$uuid');
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Server error: ${response.statusCode}');
|
||||
}
|
||||
if (response.data is! Map<String, dynamic>) {
|
||||
throw Exception('Unexpected response format');
|
||||
}
|
||||
|
||||
final Map<String, dynamic> json = Map<String, dynamic>.from(response.data as Map);
|
||||
// Normalize same as createTrip: if trip contains first_landmark_uuid, expand chain
|
||||
if (json.containsKey('landmarks') && json['landmarks'] is List) {
|
||||
_ensureLandmarks(json);
|
||||
return json;
|
||||
}
|
||||
|
||||
final String? firstUuid = json['first_landmark_uuid'] as String?;
|
||||
if (firstUuid == null) return json;
|
||||
|
||||
final List<Map<String, dynamic>> landmarks = [];
|
||||
String? next = firstUuid;
|
||||
while (next != null) {
|
||||
final lm = await _fetchLandmarkByUuid(next);
|
||||
landmarks.add(lm);
|
||||
final dynamic nxt = lm['next_uuid'];
|
||||
next = (nxt is String) ? nxt : null;
|
||||
}
|
||||
|
||||
json['landmarks'] = landmarks;
|
||||
return json;
|
||||
}
|
||||
|
||||
// Fetch a single landmark by uuid via the /landmark/{landmark_uuid} endpoint
|
||||
Future<Map<String, dynamic>> _fetchLandmarkByUuid(String uuid) async {
|
||||
final response = await dio.get('/landmark/$uuid');
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Failed to fetch landmark $uuid: ${response.statusCode}');
|
||||
}
|
||||
if (response.data is! Map<String, dynamic>) {
|
||||
throw Exception('Unexpected landmark response format');
|
||||
}
|
||||
return _normalizeLandmark(Map<String, dynamic>.from(response.data as Map));
|
||||
}
|
||||
|
||||
static void _ensureLandmarks(Map<String, dynamic> json) {
|
||||
final raw = json['landmarks'];
|
||||
if (raw is List) {
|
||||
json['landmarks'] = _normalizeLandmarks(raw);
|
||||
}
|
||||
}
|
||||
|
||||
static List<Map<String, dynamic>> _normalizeLandmarks(List<dynamic> rawList) {
|
||||
return rawList
|
||||
.map((item) => _normalizeLandmark(Map<String, dynamic>.from(item as Map)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
static Map<String, dynamic> _normalizeLandmark(Map<String, dynamic> source) {
|
||||
final normalized = Map<String, dynamic>.from(source);
|
||||
final typeValue = normalized['type'];
|
||||
if (typeValue is String) {
|
||||
normalized['type'] = {'type': typeValue};
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user