refactor: Unify all settings into single Save Preferences button

Simplified the settings page by consolidating all save buttons into one
global "Save Preferences" button at the bottom of the page.

## Changes Made

### Unified Save Handler
- Merged `handleSaveProfile` and `handleSavePreferences` into single `handleSaveAll` function
- Single save handler now updates:
  * Profile name
  * Timezone
  * Time format (12h/24h)
  * Notification preferences
- One API call to save all settings at once

### Removed Individual Save Buttons
- Removed "Save Profile" button from Profile Information section
- Removed "Save Preferences" button from Preferences section
- Removed "Save Notification Settings" button from Notifications section

### Added Global Save Button
- Centered "Save Preferences" button at bottom of settings
- Positioned above Account Actions (Logout) section
- Large, prominent button (minWidth: 200px)
- Single source of truth for all settings changes

### User Experience Benefits
- **Simpler**: One clear action to save all changes
- **Fewer clicks**: No need to save each section separately
- **Clear feedback**: Single success/error message for all updates
- **Better UX**: Users can make multiple changes and save once
- **Consistent**: All settings treated as unified preferences

Files changed: 1 file (settings page)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-03 12:01:29 +00:00
parent c27f72e41d
commit 16084c414d

View File

@@ -56,34 +56,7 @@ export default function SettingsPage() {
}
}, [user]);
const handleSavePreferences = async () => {
setIsLoading(true);
setError(null);
try {
const response = await usersApi.updateProfile({
timezone,
preferences: {
...settings,
timeFormat,
}
});
console.log('✅ Preferences updated successfully:', response);
// Refresh user to get latest data from server
await refreshUser();
setSuccessMessage('Preferences saved successfully!');
} catch (err: any) {
console.error('❌ Failed to update preferences:', err);
console.error('Error response:', err.response);
setError(err.response?.data?.message || err.message || 'Failed to save preferences. Please try again.');
} finally {
setIsLoading(false);
}
};
const handleSaveProfile = async () => {
const handleSaveAll = async () => {
// Validate name
if (!name || name.trim() === '') {
setNameError('Name cannot be empty');
@@ -97,17 +70,22 @@ export default function SettingsPage() {
try {
const response = await usersApi.updateProfile({
name: name.trim(),
timezone,
preferences: {
...settings,
timeFormat,
}
});
console.log('✅ Profile updated successfully:', response);
console.log('✅ All settings saved successfully:', response);
// Refresh user to get latest data from server
await refreshUser();
setSuccessMessage('Profile updated successfully!');
setSuccessMessage('Settings saved successfully!');
} catch (err: any) {
console.error('❌ Failed to update profile:', err);
console.error('❌ Failed to save settings:', err);
console.error('Error response:', err.response);
setError(err.response?.data?.message || err.message || 'Failed to update profile. Please try again.');
setError(err.response?.data?.message || err.message || 'Failed to save settings. Please try again.');
} finally {
setIsLoading(false);
}
@@ -172,15 +150,6 @@ export default function SettingsPage() {
disabled
helperText="Email cannot be changed"
/>
<Button
variant="contained"
startIcon={isLoading ? <CircularProgress size={20} color="inherit" /> : <Save />}
onClick={handleSaveProfile}
disabled={isLoading}
sx={{ alignSelf: 'flex-start' }}
>
{isLoading ? 'Saving...' : 'Save Profile'}
</Button>
</Box>
</CardContent>
</Card>
@@ -206,15 +175,6 @@ export default function SettingsPage() {
<Divider />
<TimeFormatSelector value={timeFormat} onChange={setTimeFormat} />
</Box>
<Button
variant="contained"
startIcon={isLoading ? <CircularProgress size={20} color="inherit" /> : <Save />}
onClick={handleSavePreferences}
disabled={isLoading}
sx={{ mt: 3, alignSelf: 'flex-start' }}
>
{isLoading ? 'Saving...' : 'Save Preferences'}
</Button>
</CardContent>
</Card>
</motion.div>
@@ -252,15 +212,6 @@ export default function SettingsPage() {
label="Email Updates"
/>
</Box>
<Button
variant="contained"
startIcon={isLoading ? <CircularProgress size={20} color="inherit" /> : <Save />}
onClick={handleSavePreferences}
disabled={isLoading}
sx={{ mt: 2, alignSelf: 'flex-start' }}
>
{isLoading ? 'Saving...' : 'Save Notification Settings'}
</Button>
</CardContent>
</Card>
</motion.div>
@@ -358,6 +309,26 @@ export default function SettingsPage() {
</Box>
</motion.div>
{/* Global Save Button */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.4, delay: 0.44 }}
>
<Box sx={{ mb: 3, display: 'flex', justifyContent: 'center' }}>
<Button
variant="contained"
size="large"
startIcon={isLoading ? <CircularProgress size={20} color="inherit" /> : <Save />}
onClick={handleSaveAll}
disabled={isLoading}
sx={{ minWidth: 200 }}
>
{isLoading ? 'Saving...' : 'Save Preferences'}
</Button>
</Box>
</motion.div>
{/* Account Actions */}
<motion.div
initial={{ opacity: 0, y: 20 }}