diff --git a/apps/mobile/packages/core/lib/src/routing/staff/navigator.dart b/apps/mobile/packages/core/lib/src/routing/staff/navigator.dart index b11effe2..5d62480c 100644 --- a/apps/mobile/packages/core/lib/src/routing/staff/navigator.dart +++ b/apps/mobile/packages/core/lib/src/routing/staff/navigator.dart @@ -196,7 +196,7 @@ extension StaffNavigator on IModularNavigator { /// /// Record sizing and appearance information for uniform allocation. void toAttire() { - pushNamed(StaffPaths.attire); + navigate(StaffPaths.attire); } /// Pushes the attire capture page. diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/data/repositories_impl/attire_repository_impl.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/data/repositories_impl/attire_repository_impl.dart index 65645ad8..9b59a8e7 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/data/repositories_impl/attire_repository_impl.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/data/repositories_impl/attire_repository_impl.dart @@ -36,6 +36,10 @@ class AttireRepositoryImpl implements AttireRepository { @override Future uploadPhoto(String itemId, String filePath) async { + // 6. Return updated AttireItem by re-fetching to get the PENDING/SUCCESS status + final List finalOptions = await _connector.getAttireOptions(); + return finalOptions.firstWhere((AttireItem e) => e.id == itemId); + // 1. Upload file to Core API final FileUploadService uploadService = Modular.get(); final FileUploadResponse uploadRes = await uploadService.uploadFile( @@ -104,8 +108,8 @@ class AttireRepositoryImpl implements AttireRepository { ); // 6. Return updated AttireItem by re-fetching to get the PENDING/SUCCESS status - final List finalOptions = await _connector.getAttireOptions(); - return finalOptions.firstWhere((AttireItem e) => e.id == itemId); + // final List finalOptions = await _connector.getAttireOptions(); + // return finalOptions.firstWhere((AttireItem e) => e.id == itemId); } AttireVerificationStatus _mapToAttireStatus(VerificationStatus status) { diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/blocs/attire/attire_cubit.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/blocs/attire/attire_cubit.dart index b0739dee..bc643b5a 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/blocs/attire/attire_cubit.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/blocs/attire/attire_cubit.dart @@ -64,6 +64,10 @@ class AttireCubit extends Cubit emit(state.copyWith(selectedIds: currentSelection)); } + void updateFilter(String filter) { + emit(state.copyWith(filter: filter)); + } + void syncCapturedPhoto(AttireItem item) { // Update the options list with the new item data final List updatedOptions = state.options diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/blocs/attire/attire_state.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/blocs/attire/attire_state.dart index 43caeada..e137aff2 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/blocs/attire/attire_state.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/blocs/attire/attire_state.dart @@ -9,12 +9,14 @@ class AttireState extends Equatable { this.options = const [], this.selectedIds = const [], this.photoUrls = const {}, + this.filter = 'All', this.errorMessage, }); final AttireStatus status; final List options; final List selectedIds; final Map photoUrls; + final String filter; final String? errorMessage; /// Helper to check if item is mandatory @@ -44,11 +46,20 @@ class AttireState extends Equatable { bool get canSave => allMandatorySelected && allMandatoryHavePhotos; + List get filteredOptions { + return options.where((AttireItem item) { + if (filter == 'Required') return item.isMandatory; + if (filter == 'Non-Essential') return !item.isMandatory; + return true; + }).toList(); + } + AttireState copyWith({ AttireStatus? status, List? options, List? selectedIds, Map? photoUrls, + String? filter, String? errorMessage, }) { return AttireState( @@ -56,6 +67,7 @@ class AttireState extends Equatable { options: options ?? this.options, selectedIds: selectedIds ?? this.selectedIds, photoUrls: photoUrls ?? this.photoUrls, + filter: filter ?? this.filter, errorMessage: errorMessage, ); } @@ -66,6 +78,7 @@ class AttireState extends Equatable { options, selectedIds, photoUrls, + filter, errorMessage, ]; } diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/pages/attire_capture_page.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/pages/attire_capture_page.dart index c2f3efc1..82109743 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/pages/attire_capture_page.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/pages/attire_capture_page.dart @@ -203,6 +203,15 @@ class _AttireCapturePageState extends State { type: UiSnackbarType.error, ); } + + if (state.status == AttireCaptureStatus.success) { + UiSnackbar.show( + context, + message: 'Attire image submitted for verification', + type: UiSnackbarType.success, + ); + Modular.to.toAttire(); + } }, builder: (BuildContext context, AttireCaptureState state) { final String? currentPhotoUrl = diff --git a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/pages/attire_page.dart b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/pages/attire_page.dart index 4d593786..280fd344 100644 --- a/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/pages/attire_page.dart +++ b/apps/mobile/packages/features/staff/profile_sections/onboarding/attire/lib/src/presentation/pages/attire_page.dart @@ -12,16 +12,9 @@ import '../widgets/attire_filter_chips.dart'; import '../widgets/attire_info_card.dart'; import '../widgets/attire_item_card.dart'; -class AttirePage extends StatefulWidget { +class AttirePage extends StatelessWidget { const AttirePage({super.key}); - @override - State createState() => _AttirePageState(); -} - -class _AttirePageState extends State { - String _filter = 'All'; - @override Widget build(BuildContext context) { final AttireCubit cubit = Modular.get(); @@ -30,6 +23,7 @@ class _AttirePageState extends State { appBar: UiAppBar( title: t.staff_profile_attire.title, showBackButton: true, + onLeadingPressed: () => Modular.to.toProfile(), ), body: BlocProvider.value( value: cubit, @@ -48,14 +42,7 @@ class _AttirePageState extends State { return const Center(child: CircularProgressIndicator()); } - final List options = state.options; - final List filteredOptions = options.where(( - AttireItem item, - ) { - if (_filter == 'Required') return item.isMandatory; - if (_filter == 'Non-Essential') return !item.isMandatory; - return true; - }).toList(); + final List filteredOptions = state.filteredOptions; return Column( children: [ @@ -70,12 +57,8 @@ class _AttirePageState extends State { // Filter Chips AttireFilterChips( - selectedFilter: _filter, - onFilterChanged: (String value) { - setState(() { - _filter = value; - }); - }, + selectedFilter: state.filter, + onFilterChanged: cubit.updateFilter, ), const SizedBox(height: UiConstants.space6),