Files
flutter/lib/api/mapflow_api.dart
Ruslan Bakiev 277888c407
All checks were successful
Build and deploy Flutter Web / build (push) Successful in 3m17s
Use ontology traits in map UI
2026-05-08 16:22:36 +07:00

143 lines
3.6 KiB
Dart

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:latlong2/latlong.dart';
import '../models/place_models.dart';
class MapflowApi {
MapflowApi({
http.Client? client,
String endpoint = const String.fromEnvironment(
'API_BASE_URL',
defaultValue: '/graphql',
),
}) : _client = client ?? http.Client(),
_endpoint = Uri.base.resolve(endpoint);
final http.Client _client;
final Uri _endpoint;
Future<List<PlaceRecommendation>> fetchPlaces() async {
final data = await _graphql('''
query Places {
places {
id
googlePlaceId
name
latitude
longitude
experiences {
id
status
analysis
createdAt
}
}
}
''');
final places = data['places'] as List<dynamic>;
return places.map((item) {
final place = item as Map<String, dynamic>;
return PlaceRecommendation(
id: place['id'] as String,
name: place['name'] as String,
area: '',
photoUrls: const [],
coordinate: LatLng(
(place['latitude'] as num).toDouble(),
(place['longitude'] as num).toDouble(),
),
traits: _traitsFromExperiences(place['experiences'] as List<dynamic>),
);
}).toList();
}
Future<void> createVoiceExperience({
required String googlePlaceId,
required String googleName,
required LatLng coordinate,
required int durationSeconds,
required String audioObjectKey,
}) async {
await _graphql(
'''
mutation CreateVoiceExperience(\$input: CreateVoiceExperienceInput!) {
createVoiceExperience(input: \$input) {
id
}
}
''',
variables: {
'input': {
'googlePlaceId': googlePlaceId,
'googleName': googleName,
'latitude': coordinate.latitude,
'longitude': coordinate.longitude,
'durationSeconds': durationSeconds,
'audioObjectKey': audioObjectKey,
},
},
);
}
Future<Map<String, dynamic>> _graphql(
String query, {
Map<String, dynamic>? variables,
}) async {
final response = await _client.post(
_endpoint,
headers: const {'content-type': 'application/json'},
body: jsonEncode({'query': query, 'variables': variables ?? {}}),
);
if (response.statusCode < 200 || response.statusCode >= 300) {
throw StateError('GraphQL request failed with ${response.statusCode}.');
}
final payload = jsonDecode(response.body) as Map<String, dynamic>;
final errors = payload['errors'];
if (errors is List && errors.isNotEmpty) {
throw StateError(jsonEncode(errors));
}
return payload['data'] as Map<String, dynamic>;
}
Set<PlaceTrait> _traitsFromExperiences(List<dynamic> experiences) {
final traits = <PlaceTrait>{};
for (final item in experiences) {
final experience = item as Map<String, dynamic>;
final analysis = experience['analysis'];
if (analysis is! Map<String, dynamic>) {
continue;
}
final tags = analysis['tags'];
if (tags is! List) {
continue;
}
for (final tag in tags) {
final trait = _traitByTag(tag.toString());
if (trait != null) {
traits.add(trait);
}
}
}
return traits;
}
PlaceTrait? _traitByTag(String tag) {
final name = tag.contains(':') ? tag.split(':').last : tag;
for (final trait in PlaceTrait.values) {
if (trait.name == name) {
return trait;
}
}
return null;
}
}