create submission
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
/// Project Progress Local Data Source
|
||||
///
|
||||
/// Handles local caching of project progress list using Hive.
|
||||
library;
|
||||
|
||||
import 'package:hive_ce/hive.dart';
|
||||
import 'package:worker/core/constants/storage_constants.dart';
|
||||
import 'package:worker/features/projects/data/models/project_progress_model.dart';
|
||||
|
||||
/// Project Progress Local Data Source
|
||||
class ProjectProgressLocalDataSource {
|
||||
/// Get Hive box for project progress
|
||||
Box<dynamic> get _box => Hive.box(HiveBoxNames.projectProgressBox);
|
||||
|
||||
/// Save project progress list to cache
|
||||
Future<void> cacheProgressList(List<ProjectProgressModel> progressList) async {
|
||||
// Clear existing cache
|
||||
await _box.clear();
|
||||
|
||||
// Save each progress with its id as key
|
||||
for (final progress in progressList) {
|
||||
await _box.put(progress.id, progress);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get cached project progress list
|
||||
List<ProjectProgressModel> getCachedProgressList() {
|
||||
try {
|
||||
final values = _box.values.whereType<ProjectProgressModel>().toList();
|
||||
return values;
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if cache exists and is not empty
|
||||
bool hasCachedData() {
|
||||
return _box.isNotEmpty;
|
||||
}
|
||||
|
||||
/// Clear all cached progress
|
||||
Future<void> clearCache() async {
|
||||
await _box.clear();
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,13 @@
|
||||
/// Handles remote API calls for project submissions.
|
||||
library;
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:worker/core/constants/api_constants.dart';
|
||||
import 'package:worker/core/network/dio_client.dart';
|
||||
import 'package:worker/features/projects/data/models/project_progress_model.dart';
|
||||
import 'package:worker/features/projects/data/models/project_status_model.dart';
|
||||
import 'package:worker/features/projects/data/models/project_submission_model.dart';
|
||||
import 'package:worker/features/projects/data/models/project_submission_request.dart';
|
||||
|
||||
/// Submissions Remote Data Source
|
||||
///
|
||||
@@ -15,11 +18,27 @@ abstract class SubmissionsRemoteDataSource {
|
||||
/// Fetch project status list from API
|
||||
Future<List<ProjectStatusModel>> getProjectStatusList();
|
||||
|
||||
/// Fetch project progress list from API (construction stages)
|
||||
Future<List<ProjectProgressModel>> getProjectProgressList();
|
||||
|
||||
/// Fetch all submissions from remote API
|
||||
Future<List<ProjectSubmissionModel>> getSubmissions({
|
||||
int limitStart = 0,
|
||||
int limitPageLength = 0,
|
||||
});
|
||||
|
||||
/// Create or update a project submission
|
||||
/// Returns the project name (ID) from the API response
|
||||
Future<String> saveSubmission(ProjectSubmissionRequest request);
|
||||
|
||||
/// Upload a file for a project submission
|
||||
/// [projectName] is the project ID returned from saveSubmission
|
||||
/// [filePath] is the local path to the file
|
||||
/// Returns the uploaded file URL
|
||||
Future<String> uploadProjectFile({
|
||||
required String projectName,
|
||||
required String filePath,
|
||||
});
|
||||
}
|
||||
|
||||
/// Submissions Remote Data Source Implementation
|
||||
@@ -67,6 +86,50 @@ class SubmissionsRemoteDataSourceImpl implements SubmissionsRemoteDataSource {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get project progress list (construction stages)
|
||||
///
|
||||
/// Calls: POST /api/method/frappe.client.get_list
|
||||
/// Body: {
|
||||
/// "doctype": "Progress of construction",
|
||||
/// "fields": ["name", "status"],
|
||||
/// "order_by": "number_of_display asc",
|
||||
/// "limit_page_length": 0
|
||||
/// }
|
||||
/// Returns: List of construction progress stages
|
||||
@override
|
||||
Future<List<ProjectProgressModel>> getProjectProgressList() async {
|
||||
try {
|
||||
final response = await _dioClient.post<Map<String, dynamic>>(
|
||||
'${ApiConstants.frappeApiMethod}${ApiConstants.frappeGetList}',
|
||||
data: {
|
||||
'doctype': 'Progress of construction',
|
||||
'fields': ['name', 'status'],
|
||||
'order_by': 'number_of_display asc',
|
||||
'limit_page_length': 0,
|
||||
},
|
||||
);
|
||||
|
||||
final data = response.data;
|
||||
if (data == null) {
|
||||
throw Exception('No data received from getProjectProgressList API');
|
||||
}
|
||||
|
||||
// API returns: { "message": [...] }
|
||||
final message = data['message'];
|
||||
if (message == null) {
|
||||
throw Exception('No message field in getProjectProgressList response');
|
||||
}
|
||||
|
||||
final List<dynamic> progressList = message as List<dynamic>;
|
||||
return progressList
|
||||
.map((json) =>
|
||||
ProjectProgressModel.fromJson(json as Map<String, dynamic>))
|
||||
.toList();
|
||||
} catch (e) {
|
||||
throw Exception('Failed to get project progress list: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Get list of project submissions
|
||||
///
|
||||
/// Calls: POST /api/method/building_material.building_material.api.project.get_list
|
||||
@@ -106,4 +169,98 @@ class SubmissionsRemoteDataSourceImpl implements SubmissionsRemoteDataSource {
|
||||
throw Exception('Failed to get project submissions: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Save (create/update) a project submission
|
||||
///
|
||||
/// Calls: POST /api/method/building_material.building_material.api.project.save
|
||||
/// Body: ProjectSubmissionRequest.toJson()
|
||||
/// Returns: Project name (ID) from response
|
||||
@override
|
||||
Future<String> saveSubmission(ProjectSubmissionRequest request) async {
|
||||
try {
|
||||
final response = await _dioClient.post<Map<String, dynamic>>(
|
||||
'${ApiConstants.frappeApiMethod}${ApiConstants.saveProject}',
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
final data = response.data;
|
||||
if (data == null) {
|
||||
throw Exception('No data received from saveProject API');
|
||||
}
|
||||
|
||||
// Check for error in response
|
||||
if (data['exc_type'] != null || data['exception'] != null) {
|
||||
final errorMessage =
|
||||
data['_server_messages'] ?? data['exception'] ?? 'Unknown error';
|
||||
throw Exception('API error: $errorMessage');
|
||||
}
|
||||
|
||||
// Extract project name from response
|
||||
// Response format: { "message": { "success": true, "data": { "name": "#DA00007" } } }
|
||||
final message = data['message'] as Map<String, dynamic>?;
|
||||
if (message == null) {
|
||||
throw Exception('No message in saveProject response');
|
||||
}
|
||||
|
||||
final messageData = message['data'] as Map<String, dynamic>?;
|
||||
if (messageData == null || messageData['name'] == null) {
|
||||
throw Exception('No project name in saveProject response');
|
||||
}
|
||||
|
||||
return messageData['name'] as String;
|
||||
} catch (e) {
|
||||
throw Exception('Failed to save project submission: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Upload a file for a project submission
|
||||
///
|
||||
/// Calls: POST /api/method/upload_file
|
||||
/// Form-data: file, is_private, folder, doctype, docname, optimize
|
||||
/// Returns: Uploaded file URL
|
||||
@override
|
||||
Future<String> uploadProjectFile({
|
||||
required String projectName,
|
||||
required String filePath,
|
||||
}) async {
|
||||
try {
|
||||
final fileName = filePath.split('/').last;
|
||||
final formData = FormData.fromMap({
|
||||
'file': await MultipartFile.fromFile(filePath, filename: fileName),
|
||||
'is_private': '1',
|
||||
'folder': 'Home/Attachments',
|
||||
'doctype': 'Architectural Project',
|
||||
'docname': projectName,
|
||||
'optimize': 'true',
|
||||
});
|
||||
|
||||
final response = await _dioClient.post<Map<String, dynamic>>(
|
||||
'${ApiConstants.frappeApiMethod}${ApiConstants.uploadFile}',
|
||||
data: formData,
|
||||
);
|
||||
|
||||
final data = response.data;
|
||||
if (data == null) {
|
||||
throw Exception('No data received from uploadFile API');
|
||||
}
|
||||
|
||||
// Check for error in response
|
||||
if (data['exc_type'] != null || data['exception'] != null) {
|
||||
final errorMessage =
|
||||
data['_server_messages'] ?? data['exception'] ?? 'Unknown error';
|
||||
throw Exception('API error: $errorMessage');
|
||||
}
|
||||
|
||||
// Extract file URL from response
|
||||
// Response format: { "message": { "file_url": "/files/...", ... } }
|
||||
final message = data['message'];
|
||||
if (message == null || message['file_url'] == null) {
|
||||
throw Exception('No file URL in uploadFile response');
|
||||
}
|
||||
|
||||
return message['file_url'] as String;
|
||||
} catch (e) {
|
||||
throw Exception('Failed to upload project file: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user