feat: Enhance attire verification status system with more granular states and update related UI and data handling.
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
import 'package:krow_data_connect/krow_data_connect.dart';
|
||||
import 'package:krow_data_connect/krow_data_connect.dart'
|
||||
hide AttireVerificationStatus;
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
|
||||
import '../../domain/repositories/attire_repository.dart';
|
||||
@@ -72,6 +73,7 @@ class AttireRepositoryImpl implements AttireRepository {
|
||||
rules: <String, dynamic>{'dressCode': dressCode},
|
||||
);
|
||||
final String verificationId = verifyRes.verificationId;
|
||||
VerificationStatus currentStatus = verifyRes.status;
|
||||
|
||||
// 4. Poll for status until it's finished or timeout (max 10 seconds)
|
||||
try {
|
||||
@@ -81,8 +83,9 @@ class AttireRepositoryImpl implements AttireRepository {
|
||||
await Future<void>.delayed(const Duration(seconds: 2));
|
||||
final VerificationResponse statusRes = await verificationService
|
||||
.getStatus(verificationId);
|
||||
final String status = statusRes.status;
|
||||
if (status != 'PENDING' && status != 'QUEUED') {
|
||||
currentStatus = statusRes.status;
|
||||
if (currentStatus != VerificationStatus.pending &&
|
||||
currentStatus != VerificationStatus.processing) {
|
||||
isFinished = true;
|
||||
}
|
||||
attempts++;
|
||||
@@ -97,10 +100,32 @@ class AttireRepositoryImpl implements AttireRepository {
|
||||
attireOptionId: itemId,
|
||||
photoUrl: photoUrl,
|
||||
verificationId: verificationId,
|
||||
verificationStatus: _mapToAttireStatus(currentStatus),
|
||||
);
|
||||
|
||||
// 6. Return updated AttireItem by re-fetching to get the PENDING/SUCCESS status
|
||||
final List<AttireItem> finalOptions = await _connector.getAttireOptions();
|
||||
return finalOptions.firstWhere((AttireItem e) => e.id == itemId);
|
||||
}
|
||||
|
||||
AttireVerificationStatus _mapToAttireStatus(VerificationStatus status) {
|
||||
switch (status) {
|
||||
case VerificationStatus.pending:
|
||||
return AttireVerificationStatus.pending;
|
||||
case VerificationStatus.processing:
|
||||
return AttireVerificationStatus.processing;
|
||||
case VerificationStatus.autoPass:
|
||||
return AttireVerificationStatus.autoPass;
|
||||
case VerificationStatus.autoFail:
|
||||
return AttireVerificationStatus.autoFail;
|
||||
case VerificationStatus.needsReview:
|
||||
return AttireVerificationStatus.needsReview;
|
||||
case VerificationStatus.approved:
|
||||
return AttireVerificationStatus.approved;
|
||||
case VerificationStatus.rejected:
|
||||
return AttireVerificationStatus.rejected;
|
||||
case VerificationStatus.error:
|
||||
return AttireVerificationStatus.error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,22 @@ class _AttireCapturePageState extends State<AttireCapturePage> {
|
||||
}
|
||||
}
|
||||
|
||||
String _getStatusText(bool hasUploadedPhoto) {
|
||||
return switch (widget.item.verificationStatus) {
|
||||
AttireVerificationStatus.approved => 'Approved',
|
||||
AttireVerificationStatus.rejected => 'Rejected',
|
||||
_ => hasUploadedPhoto ? 'Pending Verification' : 'Not Uploaded',
|
||||
};
|
||||
}
|
||||
|
||||
Color _getStatusColor(bool hasUploadedPhoto) {
|
||||
return switch (widget.item.verificationStatus) {
|
||||
AttireVerificationStatus.approved => UiColors.textSuccess,
|
||||
AttireVerificationStatus.rejected => UiColors.textError,
|
||||
_ => hasUploadedPhoto ? UiColors.textWarning : UiColors.textInactive,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider<AttireCaptureCubit>(
|
||||
@@ -145,26 +161,9 @@ class _AttireCapturePageState extends State<AttireCapturePage> {
|
||||
state.photoUrl ?? widget.initialPhotoUrl;
|
||||
final bool hasUploadedPhoto = currentPhotoUrl != null;
|
||||
|
||||
final String statusText = switch (widget
|
||||
.item
|
||||
.verificationStatus) {
|
||||
AttireVerificationStatus.success => 'Approved',
|
||||
AttireVerificationStatus.failed => 'Rejected',
|
||||
AttireVerificationStatus.pending => 'Pending Verification',
|
||||
_ =>
|
||||
hasUploadedPhoto ? 'Pending Verification' : 'Not Uploaded',
|
||||
};
|
||||
final String statusText = _getStatusText(hasUploadedPhoto);
|
||||
|
||||
final Color statusColor =
|
||||
switch (widget.item.verificationStatus) {
|
||||
AttireVerificationStatus.success => UiColors.textSuccess,
|
||||
AttireVerificationStatus.failed => UiColors.textError,
|
||||
AttireVerificationStatus.pending => UiColors.textWarning,
|
||||
_ =>
|
||||
hasUploadedPhoto
|
||||
? UiColors.textWarning
|
||||
: UiColors.textInactive,
|
||||
};
|
||||
final Color statusColor = _getStatusColor(hasUploadedPhoto);
|
||||
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
@@ -196,7 +195,7 @@ class _AttireCapturePageState extends State<AttireCapturePage> {
|
||||
widget.item.imageUrl ?? '',
|
||||
height: 120,
|
||||
fit: BoxFit.cover,
|
||||
errorBuilder: (_, __, ___) =>
|
||||
errorBuilder: (_, _, _) =>
|
||||
const SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
@@ -223,7 +222,7 @@ class _AttireCapturePageState extends State<AttireCapturePage> {
|
||||
widget.item.imageUrl ?? '',
|
||||
height: 120,
|
||||
fit: BoxFit.cover,
|
||||
errorBuilder: (_, __, ___) =>
|
||||
errorBuilder: (_, _, _) =>
|
||||
const SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -3,11 +3,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
|
||||
class AttireItemCard extends StatelessWidget {
|
||||
final AttireItem item;
|
||||
final String? uploadedPhotoUrl;
|
||||
final bool isUploading;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const AttireItemCard({
|
||||
super.key,
|
||||
required this.item,
|
||||
@@ -16,12 +11,17 @@ class AttireItemCard extends StatelessWidget {
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
final AttireItem item;
|
||||
final String? uploadedPhotoUrl;
|
||||
final bool isUploading;
|
||||
final VoidCallback onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bool hasPhoto = item.photoUrl != null;
|
||||
final String statusText = switch (item.verificationStatus) {
|
||||
AttireVerificationStatus.success => 'Approved',
|
||||
AttireVerificationStatus.failed => 'Rejected',
|
||||
AttireVerificationStatus.approved => 'Approved',
|
||||
AttireVerificationStatus.rejected => 'Rejected',
|
||||
AttireVerificationStatus.pending => 'Pending',
|
||||
_ => hasPhoto ? 'Pending' : 'To Do',
|
||||
};
|
||||
@@ -91,7 +91,7 @@ class AttireItemCard extends StatelessWidget {
|
||||
size: UiChipSize.xSmall,
|
||||
variant:
|
||||
item.verificationStatus ==
|
||||
AttireVerificationStatus.success
|
||||
AttireVerificationStatus.approved
|
||||
? UiChipVariant.primary
|
||||
: UiChipVariant.secondary,
|
||||
),
|
||||
@@ -114,12 +114,12 @@ class AttireItemCard extends StatelessWidget {
|
||||
)
|
||||
else if (hasPhoto && !isUploading)
|
||||
Icon(
|
||||
item.verificationStatus == AttireVerificationStatus.success
|
||||
item.verificationStatus == AttireVerificationStatus.approved
|
||||
? UiIcons.check
|
||||
: UiIcons.clock,
|
||||
color:
|
||||
item.verificationStatus ==
|
||||
AttireVerificationStatus.success
|
||||
AttireVerificationStatus.approved
|
||||
? UiColors.textPrimary
|
||||
: UiColors.textWarning,
|
||||
size: 24,
|
||||
|
||||
Reference in New Issue
Block a user