183 lines
5.3 KiB
Dart
183 lines
5.3 KiB
Dart
part of 'data_service.dart';
|
|
|
|
extension DataServiceTraction on DataService {
|
|
Future<void> fetchHadTraction({int offset = 0, int limit = 100}) async {
|
|
await fetchTraction(
|
|
hadOnly: true,
|
|
offset: offset,
|
|
limit: limit,
|
|
append: offset > 0,
|
|
);
|
|
}
|
|
|
|
Future<void> fetchTraction({
|
|
bool hadOnly = false,
|
|
int offset = 0,
|
|
int limit = 50,
|
|
String? locoClass,
|
|
String? locoNumber,
|
|
bool mileageFirst = true,
|
|
bool append = false,
|
|
Map<String, dynamic>? filters,
|
|
}) async {
|
|
_isTractionLoading = true;
|
|
|
|
try {
|
|
final params = StringBuffer('?limit=$limit&offset=$offset');
|
|
if (hadOnly) params.write('&had_only=true');
|
|
if (!mileageFirst) params.write('&mileage_first=false');
|
|
|
|
final payload = <String, dynamic>{};
|
|
if (locoClass != null && locoClass.isNotEmpty) {
|
|
payload['class'] = locoClass;
|
|
}
|
|
if (locoNumber != null && locoNumber.isNotEmpty) {
|
|
payload['number'] = locoNumber;
|
|
}
|
|
if (filters != null) {
|
|
filters.forEach((key, value) {
|
|
if (value == null) return;
|
|
if (value is String && value.trim().isEmpty) return;
|
|
payload[key] = value;
|
|
});
|
|
}
|
|
|
|
final json = await api.post(
|
|
'/locos/search/v2${params.toString()}',
|
|
payload.isEmpty ? null : payload,
|
|
);
|
|
|
|
if (json is List) {
|
|
final newItems = json.map((e) => LocoSummary.fromJson(e)).toList();
|
|
_traction = append ? [..._traction, ...newItems] : newItems;
|
|
_tractionHasMore = newItems.length >= limit - 1;
|
|
} else {
|
|
throw Exception('Unexpected traction response: $json');
|
|
}
|
|
} catch (e) {
|
|
debugPrint('Failed to fetch traction: $e');
|
|
if (!append) {
|
|
_traction = [];
|
|
}
|
|
_tractionHasMore = false;
|
|
} finally {
|
|
_isTractionLoading = false;
|
|
_notifyAsync();
|
|
}
|
|
}
|
|
|
|
Future<List<LocoAttrVersion>> fetchLocoTimeline(int locoId) async {
|
|
_isLocoTimelineLoading[locoId] = true;
|
|
_notifyAsync();
|
|
try {
|
|
final json = await api.get('/loco/get-timeline/$locoId');
|
|
final timeline = LocoAttrVersion.fromGroupedJson(json);
|
|
_locoTimelines[locoId] = timeline;
|
|
return timeline;
|
|
} catch (e) {
|
|
debugPrint('Failed to fetch loco timeline for $locoId: $e');
|
|
_locoTimelines[locoId] = [];
|
|
return [];
|
|
} finally {
|
|
_isLocoTimelineLoading[locoId] = false;
|
|
_notifyAsync();
|
|
}
|
|
}
|
|
|
|
Future<dynamic> createLoco(Map<String, dynamic> payload) async {
|
|
try {
|
|
final response = await api.put('/loco/new', payload);
|
|
final locoClass = payload['class']?.toString();
|
|
if (locoClass != null &&
|
|
locoClass.isNotEmpty &&
|
|
!_locoClasses.contains(locoClass)) {
|
|
_locoClasses = [..._locoClasses, locoClass];
|
|
}
|
|
_notifyAsync();
|
|
return response;
|
|
} catch (e) {
|
|
debugPrint('Failed to create loco: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
Future<List<String>> fetchClassList() async {
|
|
if (_locoClasses.isNotEmpty) return _locoClasses;
|
|
try {
|
|
final json = await api.get('/loco/classlist');
|
|
if (json is List) {
|
|
_locoClasses = json.map((e) => e.toString()).toList();
|
|
_notifyAsync();
|
|
}
|
|
} catch (e) {
|
|
debugPrint('Failed to fetch class list: $e');
|
|
}
|
|
return _locoClasses;
|
|
}
|
|
|
|
Future<void> fetchLatestLocoChanges({
|
|
int limit = 100,
|
|
int offset = 0,
|
|
bool append = false,
|
|
}) async {
|
|
_isLatestLocoChangesLoading = true;
|
|
_notifyAsync();
|
|
try {
|
|
final json =
|
|
await api.get('/loco/changes/latest?limit=$limit&offset=$offset');
|
|
dynamic results = json;
|
|
if (json is Map && json['data'] is List) {
|
|
results = json['data'];
|
|
}
|
|
if (results is List) {
|
|
final parsed = <LocoChange>[];
|
|
for (final item in results) {
|
|
if (item is Map<String, dynamic>) {
|
|
parsed.add(LocoChange.fromJson(item));
|
|
} else if (item is Map) {
|
|
parsed.add(
|
|
LocoChange.fromJson(
|
|
item.map((key, value) => MapEntry(key.toString(), value)),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
if (append) {
|
|
_latestLocoChanges = [..._latestLocoChanges, ...parsed];
|
|
} else {
|
|
_latestLocoChanges = parsed;
|
|
}
|
|
final fetchedCount = parsed.length;
|
|
_latestLocoChangesFetched = append
|
|
? offset + fetchedCount
|
|
: fetchedCount;
|
|
_latestLocoChangesHasMore = _latestLocoChangesFetched < 5000;
|
|
} else {
|
|
throw Exception('Unexpected latest loco changes response: $json');
|
|
}
|
|
} catch (e) {
|
|
debugPrint('Failed to fetch latest loco changes: $e');
|
|
_latestLocoChanges = [];
|
|
_latestLocoChangesHasMore = false;
|
|
_latestLocoChangesFetched = 0;
|
|
} finally {
|
|
_isLatestLocoChangesLoading = false;
|
|
_notifyAsync();
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>?> fetchClassStats(String locoClass) async {
|
|
try {
|
|
final path = Uri.encodeComponent(locoClass);
|
|
final json = await api.get('/loco/class/stats/$path/user');
|
|
if (json is Map) {
|
|
return Map<String, dynamic>.from(json);
|
|
}
|
|
debugPrint('Unexpected class stats response for $locoClass: $json');
|
|
} catch (e) {
|
|
debugPrint('Failed to fetch class stats for $locoClass: $e');
|
|
}
|
|
return null;
|
|
}
|
|
}
|