Files
receipity/lib/services/item_api.dart
T
2026-08-28 18:23:56 +02:00

62 lines
1.6 KiB
Dart

/// HTTP client placeholder that talks to a public sample API.
library;
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../models/item.dart';
/// Fetches catalog items from JSONPlaceholder.
///
/// This is intentionally a thin, replaceable client. Swap [baseUrl] and
/// [Item.fromJson] when you point the app at a real backend.
class ItemApi {
ItemApi({http.Client? client, this.baseUrl = defaultBaseUrl})
: _client = client ?? http.Client();
static const defaultBaseUrl = 'https://jsonplaceholder.typicode.com';
final http.Client _client;
final String baseUrl;
/// GET `/posts` and map each record to an [Item].
Future<List<Item>> fetchItems({int limit = 12}) async {
final uri = Uri.parse('$baseUrl/posts');
final response = await _client.get(
uri,
headers: const {'Accept': 'application/json'},
);
if (response.statusCode < 200 || response.statusCode >= 300) {
throw ItemApiException(
'Request failed (${response.statusCode})',
statusCode: response.statusCode,
);
}
final decoded = jsonDecode(response.body);
if (decoded is! List) {
throw const ItemApiException('Unexpected response shape');
}
return decoded
.whereType<Map<String, dynamic>>()
.take(limit)
.map(Item.fromJson)
.toList(growable: false);
}
void close() => _client.close();
}
class ItemApiException implements Exception {
const ItemApiException(this.message, {this.statusCode});
final String message;
final int? statusCode;
@override
String toString() => message;
}