diff --git a/lib/features/profile/presentation/widgets/notifications_tab.dart b/lib/features/profile/presentation/widgets/notifications_tab.dart index 46c20ff..e12ca71 100644 --- a/lib/features/profile/presentation/widgets/notifications_tab.dart +++ b/lib/features/profile/presentation/widgets/notifications_tab.dart @@ -26,6 +26,17 @@ class _NotificationsTabState extends ConsumerState { Map> _originalPrefs = {}; String _originalFrequency = 'instant'; + bool get _hasNotificationChanges { + if (_digestFrequency != _originalFrequency) return true; + for (final key in _notificationPrefs.keys) { + final current = _notificationPrefs[key]; + final original = _originalPrefs[key]; + if (current == null || original == null) return true; + if (current['email'] != original['email'] || current['inApp'] != original['inApp']) return true; + } + return false; + } + @override void initState() { super.initState(); @@ -154,6 +165,7 @@ class _NotificationsTabState extends ConsumerState { ProfileActionButtons( onSave: _saveNotificationSettings, onCancel: () { + if (!_hasNotificationChanges) return; setState(() { for (final key in _originalPrefs.keys) { _notificationPrefs[key] = Map.from(_originalPrefs[key]!); @@ -162,6 +174,7 @@ class _NotificationsTabState extends ConsumerState { }); }, isSaving: _isSavingNotifications, + hasChanges: _hasNotificationChanges, ), ], ); @@ -180,6 +193,12 @@ class _NotificationsTabState extends ConsumerState { }, 'digestFrequency': _digestFrequency, }); + // Update saved snapshot so Cancel won't revert after successful save + _originalPrefs = { + for (final e in _notificationPrefs.entries) + e.key: Map.from(e.value), + }; + _originalFrequency = _digestFrequency; _showSnackBar('Notification settings saved'); } catch (e) { _showSnackBar('Failed to save: $e', isError: true); diff --git a/lib/features/profile/presentation/widgets/profile_settings_tab.dart b/lib/features/profile/presentation/widgets/profile_settings_tab.dart index 9455908..0ceaf9f 100644 --- a/lib/features/profile/presentation/widgets/profile_settings_tab.dart +++ b/lib/features/profile/presentation/widgets/profile_settings_tab.dart @@ -28,6 +28,7 @@ class _ProfileSettingsTabState extends ConsumerState { bool _controllersInitialized = false; bool _isUploadingAvatar = false; File? _localAvatarFile; + Map _savedValues = {}; @override void initState() { @@ -81,6 +82,21 @@ class _ProfileSettingsTabState extends ConsumerState { final parts = [city, stateName, country].where((s) => s.isNotEmpty); _locationController.text = parts.join(', '); } + + _savedValues = { + 'fullName': _fullNameController.text, + 'title': _titleController.text, + 'email': _emailController.text, + 'phone': _phoneController.text, + 'location': _locationController.text, + }; + } + + bool get _hasChanges { + return _fullNameController.text != (_savedValues['fullName'] ?? '') || + _titleController.text != (_savedValues['title'] ?? '') || + _phoneController.text != (_savedValues['phone'] ?? '') || + _locationController.text != (_savedValues['location'] ?? ''); } @override @@ -262,6 +278,7 @@ class _ProfileSettingsTabState extends ConsumerState { onSave: _saveProfileSettings, onCancel: _resetForm, isSaving: profileState.isSaving, + hasChanges: _hasChanges, ), ], ); @@ -338,16 +355,16 @@ class _ProfileSettingsTabState extends ConsumerState { } void _resetForm() { - _controllersInitialized = false; - _localAvatarFile = null; - final profileState = ref.read(profileProvider); - if (profileState.profile.isNotEmpty) { - _initControllersFromProfile(profileState); - } + if (!_hasChanges) return; + // Revert to last saved values + _fullNameController.text = _savedValues['fullName'] ?? ''; + _titleController.text = _savedValues['title'] ?? ''; + _phoneController.text = _savedValues['phone'] ?? ''; + _locationController.text = _savedValues['location'] ?? ''; setState(() {}); } - void _saveProfileSettings() { + Future _saveProfileSettings() async { final profileState = ref.read(profileProvider); final isAgent = profileState.isAgent; @@ -366,7 +383,6 @@ class _ProfileSettingsTabState extends ConsumerState { final location = _locationController.text.trim(); if (location.isNotEmpty) data['serviceAreas'] = [location]; } else { - // Note: headline is not a field on UserProfile — don't send it final locationParts = _locationController.text .split(',') .map((s) => s.trim()) @@ -377,7 +393,20 @@ class _ProfileSettingsTabState extends ConsumerState { if (locationParts.length > 2) data['country'] = locationParts[2]; } - ref.read(profileProvider.notifier).updateProfile(data); + await ref.read(profileProvider.notifier).updateProfile(data); + + // Update saved values so Cancel won't revert after successful save + if (mounted) { + setState(() { + _savedValues = { + 'fullName': _fullNameController.text, + 'title': _titleController.text, + 'email': _emailController.text, + 'phone': _phoneController.text, + 'location': _locationController.text, + }; + }); + } } void _showSnackBar(String message, {bool isError = false}) { diff --git a/lib/features/profile/presentation/widgets/profile_shared_widgets.dart b/lib/features/profile/presentation/widgets/profile_shared_widgets.dart index 9dc3c4c..fbad9e5 100644 --- a/lib/features/profile/presentation/widgets/profile_shared_widgets.dart +++ b/lib/features/profile/presentation/widgets/profile_shared_widgets.dart @@ -87,6 +87,7 @@ class ProfileActionButtons extends StatelessWidget { final VoidCallback onSave; final VoidCallback onCancel; final bool isSaving; + final bool hasChanges; final String saveLabel; const ProfileActionButtons({ @@ -94,6 +95,7 @@ class ProfileActionButtons extends StatelessWidget { required this.onSave, required this.onCancel, this.isSaving = false, + this.hasChanges = true, this.saveLabel = 'Save Changes', }); @@ -114,26 +116,29 @@ class ProfileActionButtons extends StatelessWidget { Expanded( flex: 2, child: GestureDetector( - onTap: onCancel, - child: Container( - height: 31, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(7), - border: Border.all( - color: AppColors.primaryDark.withValues(alpha: 0.1), - width: 1, + onTap: hasChanges ? onCancel : null, + child: Opacity( + opacity: hasChanges ? 1.0 : 0.5, + child: Container( + height: 31, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(7), + border: Border.all( + color: AppColors.primaryDark.withValues(alpha: 0.1), + width: 1, + ), ), + alignment: Alignment.center, + child: const Text('Cancel', + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontFamily: 'Fractul', + fontSize: 14, + fontWeight: FontWeight.w400, + color: AppColors.primaryDark, + )), ), - alignment: Alignment.center, - child: const Text('Cancel', - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontFamily: 'Fractul', - fontSize: 14, - fontWeight: FontWeight.w400, - color: AppColors.primaryDark, - )), ), ), ),