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

@@ -77,6 +77,10 @@ class EventModel {
final String? contributorName;
final String? contributorTier;
// Curation flags
final bool isFeatured;
final bool isTopEvent;
EventModel({
required this.id,
required this.name,
@@ -105,6 +109,8 @@ class EventModel {
this.contributorId,
this.contributorName,
this.contributorTier,
this.isFeatured = false,
this.isTopEvent = false,
});
/// Safely parse a double from backend (may arrive as String or num)
@@ -167,6 +173,8 @@ class EventModel {
contributorId: j['contributor_id']?.toString(),
contributorName: j['contributor_name'] as String?,
contributorTier: j['contributor_tier'] as String?,
isFeatured: j['is_featured'] == true || j['is_featured']?.toString().toLowerCase() == 'true',
isTopEvent: j['is_top_event'] == true || j['is_top_event']?.toString().toLowerCase() == 'true',
);
}
}