Files
calminer/static/js/theme.js
zwitschi 7385bdad3e
Some checks failed
Run Tests / e2e tests (push) Failing after 20s
Run Tests / lint tests (push) Failing after 21s
Run Tests / unit tests (push) Failing after 21s
feat: Add theme normalization and API integration for theme settings
2025-10-27 18:04:15 +01:00

135 lines
4.0 KiB
JavaScript

// static/js/theme.js
document.addEventListener('DOMContentLoaded', () => {
const themeSettingsForm = document.getElementById('theme-settings-form');
const colorInputs = themeSettingsForm
? themeSettingsForm.querySelectorAll('input[type="color"]')
: [];
// Function to apply theme settings to CSS variables
function applyTheme(theme) {
const root = document.documentElement;
if (theme.primary_color)
root.style.setProperty('--color-primary', theme.primary_color);
if (theme.secondary_color)
root.style.setProperty('--color-secondary', theme.secondary_color);
if (theme.accent_color)
root.style.setProperty('--color-accent', theme.accent_color);
if (theme.background_color)
root.style.setProperty('--color-background', theme.background_color);
if (theme.text_color)
root.style.setProperty('--color-text-primary', theme.text_color);
// Add other theme properties as needed
}
// Save theme to local storage
function saveTheme(theme) {
localStorage.setItem('user-theme', JSON.stringify(theme));
}
// Load theme from local storage
function loadTheme() {
const savedTheme = localStorage.getItem('user-theme');
return savedTheme ? JSON.parse(savedTheme) : null;
}
// Real-time preview for color inputs
colorInputs.forEach((input) => {
input.addEventListener('input', (event) => {
const cssVar = `--color-${event.target.id.replace('-', '_')}`;
document.documentElement.style.setProperty(cssVar, event.target.value);
});
});
const THEME_API_URL = '/api/settings/theme';
const normalizeTheme = (theme) => {
if (!theme || typeof theme !== 'object') {
return {};
}
const {
theme_name,
primary_color,
secondary_color,
accent_color,
background_color,
text_color,
} = theme;
return {
theme_name,
primary_color,
secondary_color,
accent_color,
background_color,
text_color,
};
};
if (themeSettingsForm) {
themeSettingsForm.addEventListener('submit', async (event) => {
event.preventDefault();
const formData = new FormData(themeSettingsForm);
const themeData = Object.fromEntries(formData.entries());
try {
const response = await fetch(THEME_API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(themeData),
});
if (response.ok) {
const payload = await response.json();
const savedTheme = normalizeTheme(payload?.theme ?? themeData);
alert('Theme settings saved successfully!');
applyTheme(savedTheme);
saveTheme(savedTheme);
} else {
const errorData = await response.json();
alert(`Error saving theme settings: ${errorData.detail}`);
}
} catch (error) {
console.error('Error:', error);
alert('An error occurred while saving theme settings.');
}
});
}
// Load and apply theme on page load
const initialTheme = loadTheme();
if (initialTheme) {
applyTheme(initialTheme);
// Populate form fields if on the theme settings page
if (themeSettingsForm) {
for (const key in initialTheme) {
const input = themeSettingsForm.querySelector(
`#${key.replace('_', '-')}`
);
if (input) {
input.value = initialTheme[key];
}
}
}
} else {
// If no saved theme, load from backend (if available)
async function loadAndApplyThemeFromServer() {
try {
const response = await fetch(THEME_API_URL);
if (response.ok) {
const theme = normalizeTheme(await response.json());
applyTheme(theme);
saveTheme(theme); // Save to local storage for future use
} else {
console.error('Failed to load theme settings from server');
}
} catch (error) {
console.error('Error loading theme settings from server:', error);
}
}
loadAndApplyThemeFromServer();
}
});