feat(contribute): upload event images to OneDrive before submission

- ApiClient.uploadFile() — multipart POST to /v1/upload/file (60s timeout)
- ApiEndpoints.uploadFile — points to Node.js upload endpoint
- GamificationService.submitContribution() now uploads each picked image
  to OneDrive via the server upload pipeline, then passes the returned
  { fileId, url, ... } objects as `media` in the submission body
  (replaces broken behaviour of sending local device paths as strings)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-08 21:12:49 +05:30
parent 479fe5e119
commit c40e600937
7 changed files with 190 additions and 9 deletions

View File

@@ -152,11 +152,28 @@ class GamificationService {
// ---------------------------------------------------------------------------
// Submit Contribution
// POST /v1/gamification/submit-event body: event data
// 1. Upload each image to /v1/upload/file → get back { url, fileId, ... }
// 2. POST /v1/gamification/submit-event with `media` (uploaded objects)
// ---------------------------------------------------------------------------
Future<void> submitContribution(Map<String, dynamic> data) async {
final email = await _getUserEmail();
final body = <String, dynamic>{'user_id': email, ...data};
// Upload images if present
final rawPaths = (data['images'] as List?)?.cast<String>() ?? [];
final List<Map<String, dynamic>> uploadedMedia = [];
for (final path in rawPaths) {
final result = await _api.uploadFile(ApiEndpoints.uploadFile, path);
uploadedMedia.add(result);
}
// Build submission body — use `media` (server canonical field)
final body = <String, dynamic>{
'user_id': email,
...Map.from(data)..remove('images'),
if (uploadedMedia.isNotEmpty) 'media': uploadedMedia,
};
await _api.post(
ApiEndpoints.contributeSubmit,
body: body,