diff --git a/lib/controller/task_planing/report_task_controller.dart b/lib/controller/task_planing/report_task_controller.dart index 51bc584..6b22049 100644 --- a/lib/controller/task_planing/report_task_controller.dart +++ b/lib/controller/task_planing/report_task_controller.dart @@ -10,6 +10,7 @@ import 'package:marco/controller/task_planing/daily_task_planing_controller.dart import 'package:image_picker/image_picker.dart'; import 'dart:io'; import 'dart:convert'; +import 'package:marco/helpers/widgets/my_image_compressor.dart'; final Logger logger = Logger(); @@ -136,14 +137,27 @@ class ReportTaskController extends MyController { isLoading.value = true; List>? imageData; if (images != null && images.isNotEmpty) { - imageData = await Future.wait(images.map((file) async { - final bytes = await file.readAsBytes(); - final base64Image = base64Encode(bytes); - return { - "fileName": file.path.split('/').last, - "fileData": base64Image, - }; - })); + if (images != null && images.isNotEmpty) { + final imageFutures = images.map((file) async { + final compressedBytes = await compressImageToUnder100KB(file); + if (compressedBytes == null) return null; + + final base64Image = base64Encode(compressedBytes); + final fileName = file.path.split('/').last; + final contentType = _getContentTypeFromFileName(fileName); + + return { + "fileName": fileName, + "base64Data": base64Image, + "contentType": contentType, + "fileSize": compressedBytes.lengthInBytes, + "description": "Image uploaded for task report", + }; + }).toList(); + + final results = await Future.wait(imageFutures); + imageData = results.whereType>().toList(); + } } final success = await ApiService.reportTask( @@ -180,6 +194,23 @@ class ReportTaskController extends MyController { } } + String _getContentTypeFromFileName(String fileName) { + final ext = fileName.split('.').last.toLowerCase(); + switch (ext) { + case 'jpg': + case 'jpeg': + return 'image/jpeg'; + case 'png': + return 'image/png'; + case 'webp': + return 'image/webp'; + case 'gif': + return 'image/gif'; + default: + return 'application/octet-stream'; + } + } + Future commentTask({ required String projectId, required String comment, @@ -200,22 +231,37 @@ class ReportTaskController extends MyController { try { isLoading.value = true; List>? imageData; + if (images != null && images.isNotEmpty) { - imageData = await Future.wait(images.map((file) async { - final bytes = await file.readAsBytes(); - final base64Image = base64Encode(bytes); + final imageFutures = images.map((file) async { + final compressedBytes = await compressImageToUnder100KB(file); + if (compressedBytes == null) return null; + + final base64Image = base64Encode(compressedBytes); + final fileName = file.path.split('/').last; + final contentType = _getContentTypeFromFileName(fileName); + return { - "fileName": file.path.split('/').last, - "fileData": base64Image, + "fileName": fileName, + "base64Data": base64Image, + "contentType": contentType, + "fileSize": compressedBytes.lengthInBytes, + "description": "Image uploaded for task comment", }; - })); + }).toList(); + + final results = await Future.wait(imageFutures); + imageData = results.whereType>().toList(); } final success = await ApiService.commentTask( id: projectId, comment: commentField, images: imageData, - ); + ).timeout(const Duration(seconds: 30), onTimeout: () { + logger.e("Request timed out."); + throw Exception("Request timed out."); + }); if (success) { showAppSnackbar( @@ -223,7 +269,6 @@ class ReportTaskController extends MyController { message: "Task commented successfully!", type: SnackbarType.success, ); - await taskController.fetchTaskData(projectId); } else { showAppSnackbar( diff --git a/lib/helpers/services/api_service.dart b/lib/helpers/services/api_service.dart index 1b5a4f5..a734477 100644 --- a/lib/helpers/services/api_service.dart +++ b/lib/helpers/services/api_service.dart @@ -95,7 +95,10 @@ class ApiService { } static Future _postRequest( - String endpoint, dynamic body) async { + String endpoint, + dynamic body, { + Duration customTimeout = timeout, + }) async { String? token = await _getToken(); if (token == null) return null; @@ -108,7 +111,7 @@ class ApiService { try { final response = await http .post(uri, headers: _headers(token), body: jsonEncode(body)) - .timeout(timeout); + .timeout(customTimeout); _log("Response Status: ${response.statusCode}"); return response; @@ -117,6 +120,7 @@ class ApiService { return null; } } + // ===== Attendence Screen API Calls ===== static Future?> getProjects() async { @@ -354,22 +358,35 @@ class ApiService { if (images != null && images.isNotEmpty) "images": images, }; - final response = await _postRequest(ApiEndpoints.reportTask, body); + String? token = await _getToken(); + if (token == null) return false; - if (response == null) { - _log("Error: No response from server."); - return false; + final uri = Uri.parse("${ApiEndpoints.baseUrl}${ApiEndpoints.reportTask}"); + + _log("POST $uri"); + _log("Headers: ${_headers(token)}"); + _log("Body: $body"); + + try { + final response = await http + .post(uri, headers: _headers(token), body: jsonEncode(body)) + .timeout(const Duration(seconds: 30)); + + _log("Response Status: ${response.statusCode}"); + + final json = jsonDecode(response.body); + + if (response.statusCode == 200 && json['success'] == true) { + Get.back(); + return true; + } else { + _log("Failed to report task: ${json['message'] ?? 'Unknown error'}"); + } + } catch (e) { + _log("HTTP POST Exception (reportTask): $e"); } - final json = jsonDecode(response.body); - - if (response.statusCode == 200 && json['success'] == true) { - Get.back(); - return true; - } else { - _log("Failed to report task: ${json['message'] ?? 'Unknown error'}"); - return false; - } + return false; } static Future commentTask({ @@ -384,21 +401,33 @@ class ApiService { if (images != null && images.isNotEmpty) "images": images, }; - final response = await _postRequest(ApiEndpoints.commentTask, body); + String? token = await _getToken(); + if (token == null) return false; - if (response == null) { - _log("Error: No response from server."); - return false; + final uri = Uri.parse("${ApiEndpoints.baseUrl}${ApiEndpoints.commentTask}"); + + _log("POST $uri"); + _log("Headers: ${_headers(token)}"); + _log("Body: $body"); + + try { + final response = await http + .post(uri, headers: _headers(token), body: jsonEncode(body)) + .timeout(const Duration(seconds: 30)); + + _log("Response Status: ${response.statusCode}"); + + final json = jsonDecode(response.body); + if (response.statusCode == 200 && json['success'] == true) { + return true; + } else { + _log("Failed to comment task: ${json['message'] ?? 'Unknown error'}"); + } + } catch (e) { + _log("HTTP POST Exception (commentTask): $e"); } - final json = jsonDecode(response.body); - - if (response.statusCode == 200 && json['success'] == true) { - return true; - } else { - _log("Failed to comment task: ${json['message'] ?? 'Unknown error'}"); - return false; - } + return false; } // Daily Task Planing //