From 3f3579067cca25d8299631b4fe43ecd682404062 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Wed, 18 Feb 2026 16:30:22 -0500 Subject: [PATCH] feat: Implement profile visibility update feedback and localization updates --- .../lib/src/l10n/en.i18n.json | 5 +- .../lib/src/l10n/es.i18n.json | 5 +- .../blocs/privacy_security_bloc.dart | 12 ++- .../blocs/privacy_security_event.dart | 4 + .../blocs/privacy_security_state.dart | 7 ++ .../widgets/legal/legal_section_widget.dart | 2 +- .../privacy/privacy_section_widget.dart | 84 +++++++++++-------- 7 files changed, 81 insertions(+), 38 deletions(-) diff --git a/apps/mobile/packages/core_localization/lib/src/l10n/en.i18n.json b/apps/mobile/packages/core_localization/lib/src/l10n/en.i18n.json index 81a04a66..9fb4251f 100644 --- a/apps/mobile/packages/core_localization/lib/src/l10n/en.i18n.json +++ b/apps/mobile/packages/core_localization/lib/src/l10n/en.i18n.json @@ -1131,13 +1131,16 @@ "legal_section": "Legal", "profile_visibility": { "title": "Profile Visibility", - "subtitle": "Show your profile to other users" + "subtitle": "Let clients see your profile" }, "terms_of_service": { "title": "Terms of Service" }, "privacy_policy": { "title": "Privacy Policy" + }, + "success": { + "profile_visibility_updated": "Profile visibility updated successfully!" } }, "success": { diff --git a/apps/mobile/packages/core_localization/lib/src/l10n/es.i18n.json b/apps/mobile/packages/core_localization/lib/src/l10n/es.i18n.json index 23257957..77370c8e 100644 --- a/apps/mobile/packages/core_localization/lib/src/l10n/es.i18n.json +++ b/apps/mobile/packages/core_localization/lib/src/l10n/es.i18n.json @@ -1131,13 +1131,16 @@ "legal_section": "Legal", "profile_visibility": { "title": "Visibilidad del Perfil", - "subtitle": "Mostrar tu perfil a otros usuarios" + "subtitle": "Deja que los clientes vean tu perfil" }, "terms_of_service": { "title": "Términos de Servicio" }, "privacy_policy": { "title": "Política de Privacidad" + }, + "success": { + "profile_visibility_updated": "¡Visibilidad del perfil actualizada exitosamente!" } }, "success": { diff --git a/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/blocs/privacy_security_bloc.dart b/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/blocs/privacy_security_bloc.dart index c7e350d7..d333824d 100644 --- a/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/blocs/privacy_security_bloc.dart +++ b/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/blocs/privacy_security_bloc.dart @@ -31,6 +31,7 @@ class PrivacySecurityBloc on(_onUpdateProfileVisibility); on(_onFetchTerms); on(_onFetchPrivacyPolicy); + on(_onClearProfileVisibilityUpdated); } Future _onFetchProfileVisibility( @@ -61,7 +62,7 @@ class PrivacySecurityBloc UpdateProfileVisibilityEvent event, Emitter emit, ) async { - emit(state.copyWith(isUpdating: true, error: null)); + emit(state.copyWith(isUpdating: true, error: null, profileVisibilityUpdated: false)); try { final bool isVisible = await _updateProfileVisibilityUseCase.call( @@ -71,6 +72,7 @@ class PrivacySecurityBloc state.copyWith( isUpdating: false, isProfileVisible: isVisible, + profileVisibilityUpdated: true, ), ); } catch (e) { @@ -78,6 +80,7 @@ class PrivacySecurityBloc state.copyWith( isUpdating: false, error: 'Failed to update profile visibility', + profileVisibilityUpdated: false, ), ); } @@ -130,4 +133,11 @@ class PrivacySecurityBloc ); } } + + void _onClearProfileVisibilityUpdated( + ClearProfileVisibilityUpdatedEvent event, + Emitter emit, + ) { + emit(state.copyWith(profileVisibilityUpdated: false)); + } } diff --git a/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/blocs/privacy_security_event.dart b/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/blocs/privacy_security_event.dart index 8960ac53..6dbfcfdd 100644 --- a/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/blocs/privacy_security_event.dart +++ b/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/blocs/privacy_security_event.dart @@ -34,3 +34,7 @@ class FetchPrivacyPolicyEvent extends PrivacySecurityEvent { const FetchPrivacyPolicyEvent(); } +/// Event to clear the profile visibility updated flag after showing snackbar +class ClearProfileVisibilityUpdatedEvent extends PrivacySecurityEvent { + const ClearProfileVisibilityUpdatedEvent(); +} diff --git a/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/blocs/privacy_security_state.dart b/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/blocs/privacy_security_state.dart index a52d1c38..a84666ad 100644 --- a/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/blocs/privacy_security_state.dart +++ b/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/blocs/privacy_security_state.dart @@ -11,6 +11,9 @@ class PrivacySecurityState extends Equatable { /// Whether profile visibility is currently being updated final bool isUpdating; + /// Whether the profile visibility was just successfully updated + final bool profileVisibilityUpdated; + /// Terms of service content final String? termsContent; @@ -30,6 +33,7 @@ class PrivacySecurityState extends Equatable { this.isProfileVisible = true, this.isLoading = false, this.isUpdating = false, + this.profileVisibilityUpdated = false, this.termsContent, this.isLoadingTerms = false, this.privacyPolicyContent, @@ -42,6 +46,7 @@ class PrivacySecurityState extends Equatable { bool? isProfileVisible, bool? isLoading, bool? isUpdating, + bool? profileVisibilityUpdated, String? termsContent, bool? isLoadingTerms, String? privacyPolicyContent, @@ -52,6 +57,7 @@ class PrivacySecurityState extends Equatable { isProfileVisible: isProfileVisible ?? this.isProfileVisible, isLoading: isLoading ?? this.isLoading, isUpdating: isUpdating ?? this.isUpdating, + profileVisibilityUpdated: profileVisibilityUpdated ?? this.profileVisibilityUpdated, termsContent: termsContent ?? this.termsContent, isLoadingTerms: isLoadingTerms ?? this.isLoadingTerms, privacyPolicyContent: privacyPolicyContent ?? this.privacyPolicyContent, @@ -66,6 +72,7 @@ class PrivacySecurityState extends Equatable { isProfileVisible, isLoading, isUpdating, + profileVisibilityUpdated, termsContent, isLoadingTerms, privacyPolicyContent, diff --git a/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/widgets/legal/legal_section_widget.dart b/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/widgets/legal/legal_section_widget.dart index e1dfc013..d50540a3 100644 --- a/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/widgets/legal/legal_section_widget.dart +++ b/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/widgets/legal/legal_section_widget.dart @@ -23,7 +23,7 @@ class LegalSectionWidget extends StatelessWidget { // Legal Section Header SettingsSectionHeader( title: t.staff_privacy_security.legal_section, - icon: Icons.shield, + icon: UiIcons.shield, ), Container( diff --git a/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/widgets/privacy/privacy_section_widget.dart b/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/widgets/privacy/privacy_section_widget.dart index 3ad0ec45..c8a54a63 100644 --- a/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/widgets/privacy/privacy_section_widget.dart +++ b/apps/mobile/packages/features/staff/profile_sections/settings/privacy_security/lib/src/presentation/widgets/privacy/privacy_section_widget.dart @@ -13,42 +13,58 @@ class PrivacySectionWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (BuildContext context, PrivacySecurityState state) { - return Column( - children: [ - // Privacy Section Header - SettingsSectionHeader( - title: t.staff_privacy_security.privacy_section, - icon: UiIcons.eye, - ), - const SizedBox(height: 12.0), - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(UiConstants.radiusBase), - border: Border.all( - color: UiColors.border, + return BlocListener( + listener: (BuildContext context, PrivacySecurityState state) { + // Show success message when profile visibility update just completed + if (state.profileVisibilityUpdated && state.error == null) { + UiSnackbar.show( + context, + message: t.staff_privacy_security.success.profile_visibility_updated, + type: UiSnackbarType.success, + ); + // Clear the flag after showing the snackbar + context.read().add( + const ClearProfileVisibilityUpdatedEvent(), + ); + } + }, + child: BlocBuilder( + builder: (BuildContext context, PrivacySecurityState state) { + return Column( + children: [ + // Privacy Section Header + SettingsSectionHeader( + title: t.staff_privacy_security.privacy_section, + icon: UiIcons.eye, + ), + const SizedBox(height: 12.0), + Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(UiConstants.radiusBase), + border: Border.all( + color: UiColors.border, + ), + ), + child: Column( + children: [ + SettingsSwitchTile( + title: t.staff_privacy_security.profile_visibility.title, + subtitle: t.staff_privacy_security.profile_visibility.subtitle, + value: state.isProfileVisible, + onChanged: (bool value) { + BlocProvider.of(context).add( + UpdateProfileVisibilityEvent(isVisible: value), + ); + }, + ), + ], ), ), - child: Column( - children: [ - SettingsSwitchTile( - title: t.staff_privacy_security.profile_visibility.title, - subtitle: t.staff_privacy_security.profile_visibility.subtitle, - value: state.isProfileVisible, - onChanged: (bool value) { - BlocProvider.of(context).add( - UpdateProfileVisibilityEvent(isVisible: value), - ); - }, - ), - ], - ), - ), - ], - ); - }, + ], + ); + }, + ), ); } }