feat: implement settings API integration for fetching and updating user settings

This commit is contained in:
Sam Chau
2025-02-02 09:08:27 +10:30
parent 3757cbdb21
commit ff575f5a2a
3 changed files with 320 additions and 26 deletions

View File

@@ -0,0 +1,137 @@
// @api/settings.js
import Alert from '@ui/Alert';
const API_PREFIX = '/api';
// Helper function to mark errors that have already been handled
const createHandledError = message => {
const error = new Error(message);
error.isHandled = true;
return error;
};
export const fetchSettings = async () => {
try {
const response = await fetch(`${API_PREFIX}/settings`, {
credentials: 'include'
});
const data = await response.json();
if (!response.ok) {
const errorMessage = data.error || 'Failed to fetch settings';
Alert.error(errorMessage);
throw createHandledError(errorMessage);
}
return data;
} catch (error) {
if (!error.isHandled) {
Alert.error(error.message || 'Failed to fetch settings');
}
throw error;
}
};
export const fetchGeneralSettings = async () => {
try {
const response = await fetch(`${API_PREFIX}/settings/general`, {
credentials: 'include'
});
const data = await response.json();
if (!response.ok) {
const errorMessage =
data.error || 'Failed to fetch general settings';
Alert.error(errorMessage);
throw createHandledError(errorMessage);
}
return data;
} catch (error) {
if (!error.isHandled) {
Alert.error(error.message || 'Failed to fetch general settings');
}
throw error;
}
};
export const updateUsername = async (username, currentPassword) => {
try {
const response = await fetch(`${API_PREFIX}/settings/username`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
credentials: 'include',
body: JSON.stringify({username, current_password: currentPassword})
});
const data = await response.json();
if (!response.ok) {
const errorMessage = data.error || 'Failed to update username';
Alert.error(errorMessage);
throw createHandledError(errorMessage);
}
Alert.success('Username updated successfully');
return data;
} catch (error) {
if (!error.isHandled) {
Alert.error(error.message || 'Failed to update username');
}
throw error;
}
};
export const updatePassword = async (currentPassword, newPassword) => {
try {
const response = await fetch(`${API_PREFIX}/settings/password`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
credentials: 'include',
body: JSON.stringify({
current_password: currentPassword,
new_password: newPassword
})
});
const data = await response.json();
if (!response.ok) {
const errorMessage = data.error || 'Failed to update password';
Alert.error(errorMessage);
throw createHandledError(errorMessage);
}
Alert.success('Password updated successfully');
return data;
} catch (error) {
if (!error.isHandled) {
Alert.error(error.message || 'Failed to update password');
}
throw error;
}
};
export const resetApiKey = async currentPassword => {
try {
const response = await fetch(`${API_PREFIX}/settings/api-key`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
credentials: 'include',
body: JSON.stringify({current_password: currentPassword})
});
const data = await response.json();
if (!response.ok) {
const errorMessage = data.error || 'Failed to reset API key';
Alert.error(errorMessage);
throw createHandledError(errorMessage);
}
Alert.success('API key reset successfully');
return data;
} catch (error) {
if (!error.isHandled) {
Alert.error(error.message || 'Failed to reset API key');
}
throw error;
}
};

View File

@@ -1,6 +1,13 @@
// settings/general/GeneralContainer.jsx
import React, {useState, useEffect} from 'react';
import {Eye, EyeOff, Copy, RefreshCw, Check} from 'lucide-react';
import {
fetchGeneralSettings,
updateUsername,
updatePassword,
resetApiKey
} from '@api/settings';
import Alert from '@ui/Alert';
const GeneralContainer = () => {
const [loading, setLoading] = useState(true);
@@ -28,16 +35,17 @@ const GeneralContainer = () => {
const fetchSettings = async () => {
setLoading(true);
try {
console.log('Fetching general settings');
setFormData({
apiKey: 'sk-1234567890abcdef',
username: 'admin',
const {username, api_key} = await fetchGeneralSettings();
setFormData(prev => ({
...prev,
apiKey: api_key,
username: username,
currentUsername: username,
usernameCurrentPassword: '',
password: '',
confirmPassword: '',
currentPassword: '',
currentUsername: 'admin'
});
currentPassword: ''
}));
} catch (error) {
console.error('Error fetching settings:', error);
} finally {
@@ -51,12 +59,21 @@ const GeneralContainer = () => {
setTimeout(() => setCopySuccess(false), 1000);
};
const handleResetApiKey = () => {
const handleResetApiKey = async () => {
const confirmed = window.confirm(
'Are you sure you want to reset your API key? This action cannot be undone and your current key will stop working immediately.'
);
if (confirmed) {
console.log('Will reset API key');
try {
const response = await resetApiKey(formData.currentPassword);
setFormData(prev => ({
...prev,
apiKey: response.api_key
}));
} catch (error) {
console.error('Error resetting API key:', error);
}
}
};
@@ -96,31 +113,45 @@ const GeneralContainer = () => {
}));
};
const handleSaveUsername = () => {
console.log('Will save username:', {
newUsername: formData.username,
currentPassword: formData.usernameCurrentPassword
});
setFormData(prev => ({
...prev,
currentUsername: formData.username,
usernameCurrentPassword: ''
}));
const handleSaveUsername = async () => {
try {
await updateUsername(
formData.username,
formData.usernameCurrentPassword
);
setFormData(prev => ({
...prev,
currentUsername: formData.username,
usernameCurrentPassword: ''
}));
} catch (error) {
console.error('Error updating username:', error);
}
};
const handleSavePassword = () => {
const handleSavePassword = async () => {
if (formData.password !== formData.confirmPassword) {
alert('Passwords do not match');
Alert.error('Passwords do not match');
return;
}
const confirmed = window.confirm(
'Are you sure you want to change your password?'
'Are you sure you want to change your password? You will need to log in again.'
);
if (confirmed) {
console.log('Will save password with verification', {
newPassword: formData.password,
currentPassword: formData.currentPassword
});
try {
const response = await updatePassword(
formData.currentPassword,
formData.password
);
if (response.requireRelogin) {
window.location.href = '/login';
}
} catch (error) {
console.error('Error updating password:', error);
}
}
};