Skip to content

Commit 9f62191

Browse files
committed
feat: enhance KYC document upload and status management
- Added KYC document status handling in user summary mapping. - Updated file upload state to include user data loading status. - Improved UI interactions based on KYC document upload status, allowing re-upload for rejected files. - Localized messages for KYC upload statuses, including a new message for rejected uploads.
1 parent 8c412f2 commit 9f62191

5 files changed

Lines changed: 227 additions & 80 deletions

File tree

lib/core/exchange/data/mappers/user_summary_mapper.dart

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ class UserSummaryMapper {
1515
dca: model.dca.toEntity(),
1616
autoBuy: _mapUserAutoBuy(model.autoBuy),
1717
emailNotificationsEnabled: model.emailNotificationsEnabled,
18+
kycDocumentStatus: model.kycDocumentStatus != null
19+
? _mapKycDocumentStatus(model.kycDocumentStatus!)
20+
: null,
1821
);
1922
}
2023

@@ -42,4 +45,36 @@ class UserSummaryMapper {
4245
liquid: model.liquid,
4346
);
4447
}
48+
49+
static UserKycDocumentStatus _mapKycDocumentStatus(
50+
UserKycDocumentStatusModel model,
51+
) {
52+
return UserKycDocumentStatus(
53+
secureFileUpload: _parseKycDocumentStatus(model.secureFileUpload),
54+
documents: _mapKycDocuments(model.documents),
55+
);
56+
}
57+
58+
static UserKycDocuments _mapKycDocuments(UserKycDocumentsModel model) {
59+
return UserKycDocuments(
60+
id: _parseKycDocumentStatus(model.id),
61+
proofOfResidence: _parseKycDocumentStatus(model.proofOfResidence),
62+
selfie: _parseKycDocumentStatus(model.selfie),
63+
);
64+
}
65+
66+
/// Parse KYC document status string to enum
67+
static KycDocumentStatus _parseKycDocumentStatus(String status) {
68+
switch (status.toUpperCase()) {
69+
case 'ACCEPTED':
70+
return KycDocumentStatus.accepted;
71+
case 'UNDER_REVIEW':
72+
return KycDocumentStatus.underReview;
73+
case 'REJECTED':
74+
return KycDocumentStatus.rejected;
75+
case 'NOT_UPLOADED':
76+
default:
77+
return KycDocumentStatus.notUploaded;
78+
}
79+
}
4580
}

lib/features/exchange_settings/presentation/file_upload_cubit.dart

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,29 +26,21 @@ class FileUploadCubit extends Cubit<FileUploadState> {
2626
try {
2727
final userSummary = await _getExchangeUserSummaryUsecase.execute();
2828

29-
// Determine server submitted count based on status
30-
// If secureFileUpload is underReview, assume max files are submitted
31-
// This is a simplification - ideally we'd query the actual KYC list
32-
final status = userSummary.kycDocumentStatus?.secureFileUpload;
33-
final serverCount =
34-
status?.isUnderReview == true || status?.isAccepted == true
35-
? FileToUpload.maxFileCount
36-
: 0;
37-
3829
emit(
3930
state.copyWith(
4031
isLoadingUser: false,
32+
isUserDataLoaded: true,
4133
userId: userSummary.userId,
4234
secureFileUploadStatus:
4335
userSummary.kycDocumentStatus?.secureFileUpload,
44-
serverSubmittedCount: serverCount,
4536
),
4637
);
4738
} catch (e) {
4839
log.severe('Error loading user data: $e');
4940
emit(
5041
state.copyWith(
5142
isLoadingUser: false,
43+
isUserDataLoaded: false,
5244
error: 'Failed to load user data',
5345
),
5446
);
@@ -97,31 +89,22 @@ class FileUploadCubit extends Cubit<FileUploadState> {
9789
}
9890

9991
if (file.bytes == null) {
100-
emit(
101-
state.copyWith(
102-
isUploading: false,
103-
error: 'Failed to read file',
104-
),
105-
);
92+
emit(state.copyWith(isUploading: false, error: 'Failed to read file'));
10693
return;
10794
}
10895

10996
// Generate standardized filename like BB-Exchange
110-
final standardizedFileName =
111-
state.userId != null ? 'doc-${state.userId}-ID' : file.name;
97+
final standardizedFileName = state.userId != null
98+
? 'doc-${state.userId}-ID'
99+
: file.name;
112100

113101
final uploadResult = await _uploadKycDocumentUsecase.execute(
114102
fileBytes: file.bytes!,
115103
fileName: standardizedFileName,
116104
);
117105

118106
if (uploadResult.isSuccess) {
119-
emit(
120-
state.copyWith(
121-
isUploading: false,
122-
uploadComplete: true,
123-
),
124-
);
107+
emit(state.copyWith(isUploading: false, uploadComplete: true));
125108
// Refresh user data to update the secure file upload status
126109
await refreshUserData();
127110
} else {
@@ -159,4 +142,3 @@ class FileUploadCubit extends Cubit<FileUploadState> {
159142
emit(state.copyWith(error: null));
160143
}
161144
}
162-
Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import 'package:bb_mobile/core/exchange/domain/entity/file_upload.dart';
21
import 'package:bb_mobile/core/exchange/domain/entity/user_summary.dart';
32
import 'package:freezed_annotation/freezed_annotation.dart';
43

@@ -14,6 +13,9 @@ enum SecureUploadStatus {
1413

1514
/// Files have been accepted
1615
accepted,
16+
17+
/// Files were rejected - can re-upload
18+
rejected,
1719
}
1820

1921
@freezed
@@ -24,37 +26,49 @@ abstract class FileUploadState with _$FileUploadState {
2426
String? error,
2527
@Default(false) bool uploadComplete,
2628

29+
/// Whether user data was successfully loaded from the API
30+
@Default(false) bool isUserDataLoaded,
31+
2732
/// User ID for generating standardized filenames
2833
String? userId,
2934

30-
/// Secure file upload status from the API
35+
/// Secure file upload status from the API (from UserSummary)
3136
KycDocumentStatus? secureFileUploadStatus,
32-
33-
/// Number of files already submitted on the server
34-
@Default(0) int serverSubmittedCount,
3537
}) = _FileUploadState;
3638

3739
const FileUploadState._();
3840

39-
/// Whether user can add more files (only 1 file allowed now)
41+
/// Whether user can upload files
42+
/// Only allowed when data is loaded and status permits uploading
4043
bool get canAddMoreFiles =>
41-
serverSubmittedCount < FileToUpload.maxFileCount &&
42-
secureUploadStatus == SecureUploadStatus.upload;
44+
isUserDataLoaded &&
45+
(secureUploadStatus == SecureUploadStatus.upload ||
46+
secureUploadStatus == SecureUploadStatus.rejected);
4347

4448
/// Get the UI status for the secure upload feature
49+
/// Uses only the secureFileUploadStatus from UserSummary API response
4550
SecureUploadStatus get secureUploadStatus {
46-
// If status from API indicates accepted, show accepted
47-
if (secureFileUploadStatus == KycDocumentStatus.accepted) {
48-
return SecureUploadStatus.accepted;
49-
}
51+
// Handle each status explicitly based on API response
52+
switch (secureFileUploadStatus) {
53+
case KycDocumentStatus.accepted:
54+
// File was accepted - show accepted status
55+
return SecureUploadStatus.accepted;
5056

51-
// If status from API indicates under review OR max files submitted, show in review
52-
if (secureFileUploadStatus == KycDocumentStatus.underReview ||
53-
serverSubmittedCount >= FileToUpload.maxFileCount) {
54-
return SecureUploadStatus.inReview;
55-
}
57+
case KycDocumentStatus.underReview:
58+
// File is under review - cannot upload new files
59+
return SecureUploadStatus.inReview;
60+
61+
case KycDocumentStatus.notUploaded:
62+
// No file uploaded yet - can upload
63+
return SecureUploadStatus.upload;
5664

57-
// Otherwise, can upload
58-
return SecureUploadStatus.upload;
65+
case KycDocumentStatus.rejected:
66+
// File was rejected - show rejected status with re-upload option
67+
return SecureUploadStatus.rejected;
68+
69+
case null:
70+
// Status is null - show upload button (loading state handled separately in UI)
71+
return SecureUploadStatus.upload;
72+
}
5973
}
6074
}

0 commit comments

Comments
 (0)