import 'dart:convert'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:http/http.dart'; import 'package:seshat/config/constants.dart'; import 'package:seshat/domain/models/bal.dart'; import 'package:seshat/domain/models/book.dart'; import 'package:seshat/domain/models/book_instance.dart'; import 'package:seshat/domain/models/owner.dart'; import 'package:seshat/utils/command.dart'; import 'package:seshat/utils/result.dart'; typedef AuthHeaderProvider = String? Function(); class ApiClient { ApiClient({String? host, int? port}); late final Command0 load; String? token; bool isReady = false; FlutterSecureStorage? _secureStorage; Future _initStore() async { _secureStorage ??= const FlutterSecureStorage( aOptions: AndroidOptions(encryptedSharedPreferences: true), ); } Future> _getHeaders([ Map? additionalHeaders, ]) async { await _initStore(); final token = await _secureStorage!.read(key: "token"); final headers = {"Authorization": "Bearer $token", ...?additionalHeaders}; return headers; } /* * =================== * =====[ BOOKS ]===== * =================== */ Future> getBookByEAN(String ean) async { final client = Client(); try { final headers = await _getHeaders(); final response = await client.get( Uri.parse("https://$apiBasePath/book/ean/$ean"), headers: headers, ); if (response.statusCode == 200) { final json = jsonDecode(response.body); return Result.ok(Book.fromJSON(json)); } else { return Result.error(Exception("The book was not found")); } } catch (e) { return Result.error(Exception("API $e")); } finally { client.close(); } } /* * ============================= * =====[ BOOKS INSTANCES ]===== * ============================= */ Future> sendBook( Book book, Owner owner, Bal bal, double price, ) async { final client = Client(); try { final headers = await _getHeaders({"Content-Type": "application/json"}); final body = jsonEncode({ "bal_id": bal.id, "book_id": book.id, "owner_id": owner.id, "price": price, }); final response = await client.post( Uri.parse("https://$apiBasePath/book_instance"), headers: headers, body: body, ); if (response.statusCode == 201) { final json = jsonDecode(response.body); return Result.ok(BookInstance.fromJSON(json)); } else if (response.statusCode == 403) { return Result.error(Exception("You don't own that book instance")); } else { return Result.error(Exception("Something wrong happened")); } } catch (e) { return Result.error(Exception(e)); } finally { client.close(); } } /* * ==================== * =====[ OWNERS ]===== * ==================== */ /// Call on `/owners` to get a list of all [Owner]s Future>> getOwners() async { final client = Client(); try { final headers = await _getHeaders(); final response = await client.get( Uri.parse("https://$apiBasePath/owners"), headers: headers, ); if (response.statusCode == 200) { final json = jsonDecode(response.body) as List; return Result.ok( json.map((element) => Owner.fromJSON(element)).toList(), ); } else { return Result.error(Exception("Invalid request")); } } on Exception catch (error) { return Result.error(error); } finally { client.close(); } } /// Adds an owner to the database Future> addOwner( String firstName, String lastName, String contact, ) async { final client = Client(); try { final headers = await _getHeaders({"Content-Type": "application/json"}); final body = { "first_name": firstName, "last_name": lastName, "contact": contact, }; final response = await client.post( Uri.parse("https://$apiBasePath/owner"), headers: headers, body: jsonEncode(body), ); if (response.statusCode == 201) { final json = jsonDecode(response.body); return Result.ok(Owner.fromJSON(json)); } else { return Result.error(Exception("Invalid request")); } } on Exception catch (error) { return Result.error(error); } finally { client.close(); } } }