import 'dart:convert'; import 'dart:developer'; import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; import 'package:open_file/open_file.dart'; import 'package:path_provider/path_provider.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/modules/export_module/models/export_form_model.dart'; import 'package:test_sa/modules/export_module/models/export_module_type.dart'; class ExportApiProvider extends ChangeNotifier { bool _isExporting = false; bool get isExporting => _isExporting; int? _stateCode; int? get stateCode => _stateCode; String? _errorMessage; String? get errorMessage => _errorMessage; Future exportData(ExportRequest exportRequest, ExportModuleType moduleType) async { _isExporting = true; _errorMessage = null; notifyListeners(); try { final String apiUrl = _getApiUrlForModule(moduleType); final Map body = _buildRequestBody(exportRequest, moduleType); Response response = await ApiManager.instance.post(apiUrl, body: body); _stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { String ext = _getFileExtension(exportRequest.format); String encodedStr = base64.encode(response.bodyBytes); String filePath = await _createFileFromString(encodedStr, ext); await OpenFile.open(filePath); return true; } else { try { final responseData = json.decode(response.body); _errorMessage = responseData['message'] ?? 'Export failed'; } catch (e) { _errorMessage = 'Export failed with status: ${response.statusCode}'; } return false; } } catch (error, stackTrace) { log('Error exporting data: $error'); _stateCode = -1; _errorMessage = 'An error occurred during export: $error'; return false; } finally { _isExporting = false; notifyListeners(); } } String _getApiUrlForModule(ExportModuleType moduleType) { switch (moduleType) { case ExportModuleType.asset: return URLs.exportAsset; case ExportModuleType.callRequest: return URLs.exportAllWorkOrder; default: return URLs.exportAsset; } } String _getFileExtension(String format) { final formatLower = format.toLowerCase(); switch (formatLower) { case 'excel': return 'xlsx'; case 'pdf': return 'pdf'; case 'word': case 'doc': return 'docx'; case 'text': case 'txt': return 'txt'; case 'csv': return 'csv'; default: return formatLower; } } Map _buildRequestBody(ExportRequest exportRequest, ExportModuleType moduleType) { final Map body = {}; if (exportRequest.searchModel != null) { try { final searchModelJson = (exportRequest.searchModel as dynamic).toJson() as Map; body.addAll(searchModelJson); } catch (e) { body['searchModel'] = exportRequest.searchModel; } } // Add CallRequest-specific fields only for callRequest type if (moduleType == ExportModuleType.callRequest) { _addCallRequestFields(body); } body['pageNo'] = exportRequest.pageNo; body['pageSize'] = exportRequest.pageSize; body['exportRequest'] = { 'selectedColumns': exportRequest.selectedColumns, 'format': exportRequest.format, }; return body; } void _addCallRequestFields(Map body) { //This is if no filter is selected we will send all the options to the backend to filter accordingly as per we are sending on allworkorder api if (!body.containsKey('typeTransaction') || (body['typeTransaction'] as List?)?.isEmpty == true) { body['typeTransaction'] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; } if (!body.containsKey('statusTransaction') || (body['statusTransaction'] as List?)?.isEmpty == true) { body['statusTransaction'] = [1, 2, 4]; } if (!body.containsKey('priority')) { body['priority'] = []; } if (!body.containsKey('displayData')) { body['displayData'] = []; } } Future _createFileFromString(String encodedStr, String ext) async { Uint8List bytes = base64.decode(encodedStr); String dir = (await getApplicationDocumentsDirectory()).path; File file = File("$dir/${DateTime.now().millisecondsSinceEpoch}.$ext"); await file.writeAsBytes(bytes); return file.path; } void resetError() { _errorMessage = null; notifyListeners(); } }