feat: Introduce AttireVerificationStatus enum and add verificationId to staff attire items.

This commit is contained in:
Achintha Isuru
2026-02-24 17:31:41 -05:00
parent 616f23fec9
commit fd0208efa0
10 changed files with 64 additions and 14 deletions

View File

@@ -1,6 +1,7 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs, implementation_imports
import 'package:firebase_data_connect/firebase_data_connect.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';
/// Implementation of [StaffConnectorRepository].
@@ -233,17 +234,28 @@ class StaffConnectorRepositoryImpl implements StaffConnectorRepository {
description: e.description,
imageUrl: e.imageUrl,
isMandatory: e.isMandatory ?? false,
verificationStatus: userAttire?.verificationStatus?.stringValue,
verificationStatus: _mapAttireStatus(
userAttire?.verificationStatus?.stringValue,
),
photoUrl: userAttire?.verificationPhotoUrl,
);
}).toList();
});
}
AttireVerificationStatus? _mapAttireStatus(String? status) {
if (status == null) return null;
return AttireVerificationStatus.values.firstWhere(
(e) => e.name.toUpperCase() == status.toUpperCase(),
orElse: () => AttireVerificationStatus.pending,
);
}
@override
Future<void> upsertStaffAttire({
required String attireOptionId,
required String photoUrl,
String? verificationId,
}) async {
await _service.run(() async {
final String staffId = await _service.getStaffId();
@@ -251,6 +263,7 @@ class StaffConnectorRepositoryImpl implements StaffConnectorRepository {
await _service.connector
.upsertStaffAttire(staffId: staffId, attireOptionId: attireOptionId)
.verificationPhotoUrl(photoUrl)
// .verificationId(verificationId) // Uncomment after SDK regeneration
.execute();
});
}

View File

@@ -54,6 +54,7 @@ abstract interface class StaffConnectorRepository {
Future<void> upsertStaffAttire({
required String attireOptionId,
required String photoUrl,
String? verificationId,
});
/// Signs out the current user.

View File

@@ -68,6 +68,7 @@ export 'src/adapters/financial/bank_account/bank_account_adapter.dart';
// Profile
export 'src/entities/profile/staff_document.dart';
export 'src/entities/profile/attire_item.dart';
export 'src/entities/profile/attire_verification_status.dart';
export 'src/entities/profile/relationship_type.dart';
export 'src/entities/profile/industry.dart';
export 'src/entities/profile/tax_form.dart';

View File

@@ -1,5 +1,7 @@
import 'package:equatable/equatable.dart';
import 'attire_verification_status.dart';
/// Represents an attire item that a staff member might need or possess.
///
/// Attire items are specific clothing or equipment required for jobs.
@@ -13,6 +15,7 @@ class AttireItem extends Equatable {
this.isMandatory = false,
this.verificationStatus,
this.photoUrl,
this.verificationId,
});
/// Unique identifier of the attire item.
@@ -31,11 +34,14 @@ class AttireItem extends Equatable {
final bool isMandatory;
/// The current verification status of the uploaded photo.
final String? verificationStatus;
final AttireVerificationStatus? verificationStatus;
/// The URL of the photo uploaded by the staff member.
final String? photoUrl;
/// The ID of the verification record.
final String? verificationId;
@override
List<Object?> get props => <Object?>[
id,
@@ -45,5 +51,6 @@ class AttireItem extends Equatable {
isMandatory,
verificationStatus,
photoUrl,
verificationId,
];
}

View File

@@ -0,0 +1,11 @@
/// Represents the verification status of an attire item photo.
enum AttireVerificationStatus {
/// The photo is waiting for review.
pending,
/// The photo was rejected.
failed,
/// The photo was approved.
success,
}

View File

@@ -74,18 +74,26 @@ class _AttireCapturePageState extends State<AttireCapturePage> {
state.photoUrl ?? widget.initialPhotoUrl;
final bool hasUploadedPhoto = currentPhotoUrl != null;
final String statusText =
widget.item.verificationStatus ??
(hasUploadedPhoto
? 'Pending Verification'
: 'Not Uploaded');
final String statusText = switch (widget
.item
.verificationStatus) {
AttireVerificationStatus.success => 'Approved',
AttireVerificationStatus.failed => 'Rejected',
AttireVerificationStatus.pending => 'Pending Verification',
_ =>
hasUploadedPhoto ? 'Pending Verification' : 'Not Uploaded',
};
final Color statusColor =
widget.item.verificationStatus == 'SUCCESS'
? UiColors.textPrimary
: (hasUploadedPhoto
? UiColors.textWarning
: UiColors.textInactive);
switch (widget.item.verificationStatus) {
AttireVerificationStatus.success => UiColors.textSuccess,
AttireVerificationStatus.failed => UiColors.textError,
AttireVerificationStatus.pending => UiColors.textWarning,
_ =>
hasUploadedPhoto
? UiColors.textWarning
: UiColors.textInactive,
};
return Column(
children: <Widget>[

View File

@@ -19,7 +19,12 @@ class AttireItemCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final bool hasPhoto = item.photoUrl != null;
final String statusText = item.verificationStatus ?? 'Not Uploaded';
final String statusText = switch (item.verificationStatus) {
AttireVerificationStatus.success => 'Approved',
AttireVerificationStatus.failed => 'Rejected',
AttireVerificationStatus.pending => 'Pending',
_ => hasPhoto ? 'Pending' : 'To Do',
};
return GestureDetector(
onTap: onTap,

View File

@@ -2,12 +2,14 @@ mutation upsertStaffAttire(
$staffId: UUID!
$attireOptionId: UUID!
$verificationPhotoUrl: String
$verificationId: String
) @auth(level: USER) {
staffAttire_upsert(
data: {
staffId: $staffId
attireOptionId: $attireOptionId
verificationPhotoUrl: $verificationPhotoUrl
verificationId: $verificationId
verificationStatus: PENDING
}
)

View File

@@ -3,5 +3,6 @@ query getStaffAttire($staffId: UUID!) @auth(level: USER) {
attireOptionId
verificationStatus
verificationPhotoUrl
verificationId
}
}

View File

@@ -15,6 +15,7 @@ type StaffAttire @table(name: "staff_attires", key: ["staffId", "attireOptionId"
verificationStatus: AttireVerificationStatus @default(expr: "'PENDING'")
verifiedAt: Timestamp
verificationPhotoUrl: String # Proof of ownership
verificationId: String
createdAt: Timestamp @default(expr: "request.time")
updatedAt: Timestamp @default(expr: "request.time")