feat: Enhance attire verification status system with more granular states and update related UI and data handling.

This commit is contained in:
Achintha Isuru
2026-02-25 19:05:03 -05:00
parent 6eafba311b
commit 4515d42cd3
9 changed files with 334 additions and 157 deletions

View File

@@ -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;
}
}
}

View File

@@ -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(),
),
),

View File

@@ -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,