Initial upload: fin65-mobile
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../config/app_config.dart';
|
||||
import '../models/account.dart';
|
||||
import '../models/category.dart';
|
||||
import '../models/dashboard.dart';
|
||||
import '../models/transaction_item.dart';
|
||||
import 'offline_store.dart';
|
||||
|
||||
class ApiService {
|
||||
ApiService({OfflineStore? store}) : _store = store ?? OfflineStore.instance;
|
||||
|
||||
final OfflineStore _store;
|
||||
static const String _baseUrlKey = 'api_base_url';
|
||||
|
||||
Future<String> getBaseUrl() async {
|
||||
return await _store.getSetting(_baseUrlKey) ?? AppConfig.defaultApiBaseUrl;
|
||||
}
|
||||
|
||||
Future<void> setBaseUrl(String value) async {
|
||||
await _store.setSetting(
|
||||
_baseUrlKey,
|
||||
value.trim().replaceAll(RegExp(r'/$'), ''),
|
||||
);
|
||||
}
|
||||
|
||||
Future<Uri> _uri(String path) async {
|
||||
final baseUrl = await getBaseUrl();
|
||||
return Uri.parse('$baseUrl$path');
|
||||
}
|
||||
|
||||
Future<dynamic> _getJson(String path) async {
|
||||
final res = await http.get(await _uri(path)).timeout(const Duration(seconds: 5));
|
||||
return _handleResponse(res);
|
||||
}
|
||||
|
||||
Future<dynamic> _postJson(String path, Map<String, dynamic> body) async {
|
||||
final res = await http
|
||||
.post(
|
||||
await _uri(path),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: jsonEncode(body),
|
||||
)
|
||||
.timeout(const Duration(seconds: 8));
|
||||
return _handleResponse(res);
|
||||
}
|
||||
|
||||
dynamic _handleResponse(http.Response res) {
|
||||
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||
if (res.body.isEmpty) return null;
|
||||
return jsonDecode(utf8.decode(res.bodyBytes));
|
||||
}
|
||||
|
||||
String message = 'Erreur HTTP ${res.statusCode}';
|
||||
try {
|
||||
final body = jsonDecode(utf8.decode(res.bodyBytes));
|
||||
message = body['detail']?.toString() ?? body.toString();
|
||||
} catch (_) {}
|
||||
throw Exception(message);
|
||||
}
|
||||
|
||||
Future<bool> healthCheck() async {
|
||||
final data = await _getJson('/health');
|
||||
return data is Map && data['status'] == 'ok';
|
||||
}
|
||||
|
||||
Future<DashboardData> getDashboard() async {
|
||||
final data = await _getJson('/dashboard');
|
||||
return DashboardData.fromJson(data as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Future<List<Account>> getAccounts() async {
|
||||
final data = await _getJson('/accounts?active_only=true') as List<dynamic>;
|
||||
return data.map((e) => Account.fromJson(e as Map<String, dynamic>)).toList();
|
||||
}
|
||||
|
||||
Future<List<Category>> getCategories() async {
|
||||
final data = await _getJson('/categories') as List<dynamic>;
|
||||
return data.map((e) => Category.fromJson(e as Map<String, dynamic>)).toList();
|
||||
}
|
||||
|
||||
Future<List<TransactionItem>> getTransactions({int limit = AppConfig.defaultTransactionLimit}) async {
|
||||
final data = await _getJson('/transactions?limit=$limit') as List<dynamic>;
|
||||
return data.map((e) => TransactionItem.fromJson(e as Map<String, dynamic>)).toList();
|
||||
}
|
||||
|
||||
Future<TransactionItem> createTransactionFromPayload(Map<String, dynamic> payload) async {
|
||||
final cleanPayload = Map<String, dynamic>.from(payload);
|
||||
cleanPayload.removeWhere((_, value) => value == null);
|
||||
|
||||
final data = await _postJson('/transactions', cleanPayload);
|
||||
return TransactionItem.fromJson(data as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Future<TransactionItem> createTransaction({
|
||||
required String label,
|
||||
required double amount,
|
||||
required String type,
|
||||
required int accountId,
|
||||
int? targetAccountId,
|
||||
int? categoryId,
|
||||
String? note,
|
||||
DateTime? date,
|
||||
}) async {
|
||||
return createTransactionFromPayload({
|
||||
'date': (date ?? DateTime.now()).toIso8601String(),
|
||||
'label': label,
|
||||
'amount': amount,
|
||||
'type': type,
|
||||
'account_id': accountId,
|
||||
'target_account_id': targetAccountId,
|
||||
'category_id': categoryId,
|
||||
'created_from': 'android',
|
||||
'note': note,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user