feat: Implement profile visibility update feedback and localization updates

This commit is contained in:
Achintha Isuru
2026-02-18 16:30:22 -05:00
parent 7ce1c6f6e3
commit 3f3579067c
7 changed files with 81 additions and 38 deletions

View File

@@ -1131,13 +1131,16 @@
"legal_section": "Legal", "legal_section": "Legal",
"profile_visibility": { "profile_visibility": {
"title": "Profile Visibility", "title": "Profile Visibility",
"subtitle": "Show your profile to other users" "subtitle": "Let clients see your profile"
}, },
"terms_of_service": { "terms_of_service": {
"title": "Terms of Service" "title": "Terms of Service"
}, },
"privacy_policy": { "privacy_policy": {
"title": "Privacy Policy" "title": "Privacy Policy"
},
"success": {
"profile_visibility_updated": "Profile visibility updated successfully!"
} }
}, },
"success": { "success": {

View File

@@ -1131,13 +1131,16 @@
"legal_section": "Legal", "legal_section": "Legal",
"profile_visibility": { "profile_visibility": {
"title": "Visibilidad del Perfil", "title": "Visibilidad del Perfil",
"subtitle": "Mostrar tu perfil a otros usuarios" "subtitle": "Deja que los clientes vean tu perfil"
}, },
"terms_of_service": { "terms_of_service": {
"title": "Términos de Servicio" "title": "Términos de Servicio"
}, },
"privacy_policy": { "privacy_policy": {
"title": "Política de Privacidad" "title": "Política de Privacidad"
},
"success": {
"profile_visibility_updated": "¡Visibilidad del perfil actualizada exitosamente!"
} }
}, },
"success": { "success": {

View File

@@ -31,6 +31,7 @@ class PrivacySecurityBloc
on<UpdateProfileVisibilityEvent>(_onUpdateProfileVisibility); on<UpdateProfileVisibilityEvent>(_onUpdateProfileVisibility);
on<FetchTermsEvent>(_onFetchTerms); on<FetchTermsEvent>(_onFetchTerms);
on<FetchPrivacyPolicyEvent>(_onFetchPrivacyPolicy); on<FetchPrivacyPolicyEvent>(_onFetchPrivacyPolicy);
on<ClearProfileVisibilityUpdatedEvent>(_onClearProfileVisibilityUpdated);
} }
Future<void> _onFetchProfileVisibility( Future<void> _onFetchProfileVisibility(
@@ -61,7 +62,7 @@ class PrivacySecurityBloc
UpdateProfileVisibilityEvent event, UpdateProfileVisibilityEvent event,
Emitter<PrivacySecurityState> emit, Emitter<PrivacySecurityState> emit,
) async { ) async {
emit(state.copyWith(isUpdating: true, error: null)); emit(state.copyWith(isUpdating: true, error: null, profileVisibilityUpdated: false));
try { try {
final bool isVisible = await _updateProfileVisibilityUseCase.call( final bool isVisible = await _updateProfileVisibilityUseCase.call(
@@ -71,6 +72,7 @@ class PrivacySecurityBloc
state.copyWith( state.copyWith(
isUpdating: false, isUpdating: false,
isProfileVisible: isVisible, isProfileVisible: isVisible,
profileVisibilityUpdated: true,
), ),
); );
} catch (e) { } catch (e) {
@@ -78,6 +80,7 @@ class PrivacySecurityBloc
state.copyWith( state.copyWith(
isUpdating: false, isUpdating: false,
error: 'Failed to update profile visibility', error: 'Failed to update profile visibility',
profileVisibilityUpdated: false,
), ),
); );
} }
@@ -130,4 +133,11 @@ class PrivacySecurityBloc
); );
} }
} }
void _onClearProfileVisibilityUpdated(
ClearProfileVisibilityUpdatedEvent event,
Emitter<PrivacySecurityState> emit,
) {
emit(state.copyWith(profileVisibilityUpdated: false));
}
} }

View File

@@ -34,3 +34,7 @@ class FetchPrivacyPolicyEvent extends PrivacySecurityEvent {
const FetchPrivacyPolicyEvent(); const FetchPrivacyPolicyEvent();
} }
/// Event to clear the profile visibility updated flag after showing snackbar
class ClearProfileVisibilityUpdatedEvent extends PrivacySecurityEvent {
const ClearProfileVisibilityUpdatedEvent();
}

View File

@@ -11,6 +11,9 @@ class PrivacySecurityState extends Equatable {
/// Whether profile visibility is currently being updated /// Whether profile visibility is currently being updated
final bool isUpdating; final bool isUpdating;
/// Whether the profile visibility was just successfully updated
final bool profileVisibilityUpdated;
/// Terms of service content /// Terms of service content
final String? termsContent; final String? termsContent;
@@ -30,6 +33,7 @@ class PrivacySecurityState extends Equatable {
this.isProfileVisible = true, this.isProfileVisible = true,
this.isLoading = false, this.isLoading = false,
this.isUpdating = false, this.isUpdating = false,
this.profileVisibilityUpdated = false,
this.termsContent, this.termsContent,
this.isLoadingTerms = false, this.isLoadingTerms = false,
this.privacyPolicyContent, this.privacyPolicyContent,
@@ -42,6 +46,7 @@ class PrivacySecurityState extends Equatable {
bool? isProfileVisible, bool? isProfileVisible,
bool? isLoading, bool? isLoading,
bool? isUpdating, bool? isUpdating,
bool? profileVisibilityUpdated,
String? termsContent, String? termsContent,
bool? isLoadingTerms, bool? isLoadingTerms,
String? privacyPolicyContent, String? privacyPolicyContent,
@@ -52,6 +57,7 @@ class PrivacySecurityState extends Equatable {
isProfileVisible: isProfileVisible ?? this.isProfileVisible, isProfileVisible: isProfileVisible ?? this.isProfileVisible,
isLoading: isLoading ?? this.isLoading, isLoading: isLoading ?? this.isLoading,
isUpdating: isUpdating ?? this.isUpdating, isUpdating: isUpdating ?? this.isUpdating,
profileVisibilityUpdated: profileVisibilityUpdated ?? this.profileVisibilityUpdated,
termsContent: termsContent ?? this.termsContent, termsContent: termsContent ?? this.termsContent,
isLoadingTerms: isLoadingTerms ?? this.isLoadingTerms, isLoadingTerms: isLoadingTerms ?? this.isLoadingTerms,
privacyPolicyContent: privacyPolicyContent ?? this.privacyPolicyContent, privacyPolicyContent: privacyPolicyContent ?? this.privacyPolicyContent,
@@ -66,6 +72,7 @@ class PrivacySecurityState extends Equatable {
isProfileVisible, isProfileVisible,
isLoading, isLoading,
isUpdating, isUpdating,
profileVisibilityUpdated,
termsContent, termsContent,
isLoadingTerms, isLoadingTerms,
privacyPolicyContent, privacyPolicyContent,

View File

@@ -23,7 +23,7 @@ class LegalSectionWidget extends StatelessWidget {
// Legal Section Header // Legal Section Header
SettingsSectionHeader( SettingsSectionHeader(
title: t.staff_privacy_security.legal_section, title: t.staff_privacy_security.legal_section,
icon: Icons.shield, icon: UiIcons.shield,
), ),
Container( Container(

View File

@@ -13,42 +13,58 @@ class PrivacySectionWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<PrivacySecurityBloc, PrivacySecurityState>( return BlocListener<PrivacySecurityBloc, PrivacySecurityState>(
builder: (BuildContext context, PrivacySecurityState state) { listener: (BuildContext context, PrivacySecurityState state) {
return Column( // Show success message when profile visibility update just completed
children: <Widget>[ if (state.profileVisibilityUpdated && state.error == null) {
// Privacy Section Header UiSnackbar.show(
SettingsSectionHeader( context,
title: t.staff_privacy_security.privacy_section, message: t.staff_privacy_security.success.profile_visibility_updated,
icon: UiIcons.eye, type: UiSnackbarType.success,
), );
const SizedBox(height: 12.0), // Clear the flag after showing the snackbar
Container( context.read<PrivacySecurityBloc>().add(
decoration: BoxDecoration( const ClearProfileVisibilityUpdatedEvent(),
color: Colors.white, );
borderRadius: BorderRadius.circular(UiConstants.radiusBase), }
border: Border.all( },
color: UiColors.border, child: BlocBuilder<PrivacySecurityBloc, PrivacySecurityState>(
builder: (BuildContext context, PrivacySecurityState state) {
return Column(
children: <Widget>[
// 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: <Widget>[
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<PrivacySecurityBloc>(context).add(
UpdateProfileVisibilityEvent(isVisible: value),
);
},
),
],
), ),
), ),
child: Column( ],
children: <Widget>[ );
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<PrivacySecurityBloc>(context).add(
UpdateProfileVisibilityEvent(isVisible: value),
);
},
),
],
),
),
],
);
},
); );
} }
} }