import 'dart:convert'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; import 'package:logging/logging.dart'; import 'package:path_provider/path_provider.dart'; // For cache storage import 'sheet.dart'; class ApiClient { final log = Logger("ApiClient"); final String baseUrl; String? token; ApiClient({required this.baseUrl, this.token}); Future login(String username, String password) async { log.info("Logging in..."); final url = '$baseUrl/login'; final response = await http.post( Uri.parse(url), headers: {'Content-Type': 'application/json'}, body: jsonEncode({'email': username, 'password': password}), ); if (response.statusCode == 200) { token = jsonDecode(response.body); log.info('Login successful'); } else { throw Exception( "Failed logging in: Response code ${response.statusCode}\nResponse: ${response.body}", ); } } void logout() { token = null; log.info('Logged out successfully.'); } Future get( String endpoint, { bool isBinary = false, bool throwExceptionIfStatusCodeNot200 = false, }) async { final url = '$baseUrl$endpoint'; final headers = { 'Authorization': 'Bearer $token', if (!isBinary) 'Content-Type': 'application/json', }; final response = await http.get(Uri.parse(url), headers: headers); if (!throwExceptionIfStatusCodeNot200 || response.statusCode == 200) { return response; } else { throw Exception( 'GET request failed: ${response.statusCode} ${response.body}', ); } } Future post( String endpoint, Map body, ) async { try { final url = '$baseUrl$endpoint'; final headers = { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', }; final response = await http.post( Uri.parse(url), headers: headers, body: jsonEncode(body), ); if (response.statusCode == 200 || response.statusCode == 201) { return response; } else { log.info( 'POST request failed: ${response.statusCode} ${response.body}', ); } } catch (e) { log.info('Error during POST request: $e'); } return null; } Future postFormData(String endpoint, String body) async { try { final url = '$baseUrl$endpoint'; final headers = { 'Authorization': 'Bearer $token', 'Content-Type': 'application/x-www-form-urlencoded', }; final response = await http.post( Uri.parse(url), headers: headers, body: body, ); if (response.statusCode == 200 || response.statusCode == 201) { return response; } else { log.info( 'POST Form Data request failed: ${response.statusCode} ${response.body}', ); } } catch (e) { log.info('Error during POST Form Data request: $e'); } return null; } Future> fetchSheets() async { final response = await get( "/list/sheets", throwExceptionIfStatusCodeNot200: true, ); final data = jsonDecode(response.body); return (data as List) .map((sheet) => Sheet.fromJson(sheet as Map)) .toList(); } Future fetchPdfFileData(String sheetUuid) async { final response = await get( '/sheet/pdf/$sheetUuid', isBinary: true, throwExceptionIfStatusCodeNot200: true, ); log.info("PDF downloaded"); return response.bodyBytes; } Future getPdfFileCached(String sheetUuid) async { final cacheDir = await getTemporaryDirectory(); final cachedPdfPath = '${cacheDir.path}/$sheetUuid.pdf'; final cachedFile = File(cachedPdfPath); if (await cachedFile.exists()) { log.info("PDF found in cache: $cachedPdfPath"); return cachedFile; } final pdfFileData = await fetchPdfFileData(sheetUuid); await cachedFile.writeAsBytes(pdfFileData); log.info("PDF cached at: $cachedPdfPath"); return cachedFile; } }