Files
SkyArtShop/website/admin/js/settings.js

388 lines
12 KiB
JavaScript
Raw Normal View History

2025-12-14 01:54:40 -06:00
// Settings Management JavaScript
let currentSettings = {};
2026-01-18 02:22:05 -06:00
let settingsMediaLibrary = null;
2025-12-24 00:13:23 -06:00
let currentMediaTarget = null;
2025-12-14 01:54:40 -06:00
2026-01-18 02:22:05 -06:00
// Initialize settings media library
function initSettingsMediaLibrary() {
if (typeof MediaLibrary !== "undefined" && !settingsMediaLibrary) {
settingsMediaLibrary = new MediaLibrary({
selectMode: true,
multiple: false,
onSelect: function (media) {
if (!currentMediaTarget) return;
// Set the selected URL to the target field
document.getElementById(currentMediaTarget).value = media.path;
// Update preview
if (currentMediaTarget === "siteLogo") {
document.getElementById(
"logoPreview"
).innerHTML = `<img src="${media.path}" alt="Logo" />`;
} else if (currentMediaTarget === "siteFavicon") {
document.getElementById(
"faviconPreview"
).innerHTML = `<img src="${media.path}" alt="Favicon" />`;
}
showToast("Image selected successfully", "success");
},
});
2025-12-24 00:13:23 -06:00
}
2026-01-18 02:22:05 -06:00
}
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
document.addEventListener("DOMContentLoaded", function () {
// Initialize media library
initSettingsMediaLibrary();
2025-12-24 00:13:23 -06:00
// Load saved theme
loadTheme();
2025-12-14 01:54:40 -06:00
checkAuth().then((authenticated) => {
if (authenticated) {
loadSettings();
}
});
});
2025-12-24 00:13:23 -06:00
// Toast Notification System - Make global for onclick handlers
window.showToast = function (message, type = "success") {
const container = document.getElementById("toastContainer");
if (!container) {
console.error("Toast container not found!");
return;
}
const icons = {
success: "bi-check-circle-fill",
error: "bi-x-circle-fill",
warning: "bi-exclamation-triangle-fill",
info: "bi-info-circle-fill",
};
const toast = document.createElement("div");
toast.className = `toast toast-${type}`;
toast.innerHTML = `
<div class="toast-icon">
<i class="bi ${icons[type] || icons.info}"></i>
</div>
<div class="toast-message">${message}</div>
<button class="toast-close" onclick="window.closeToast(this)">
<i class="bi bi-x"></i>
</button>
`;
container.appendChild(toast);
// Trigger animation
setTimeout(() => toast.classList.add("toast-show"), 10);
// Add visual feedback for success saves
if (type === "success" && message.includes("saved")) {
const saveBtn = document.querySelector('button[onclick*="saveSettings"]');
if (saveBtn) {
const originalBg = saveBtn.style.background;
const originalTransform = saveBtn.style.transform;
saveBtn.style.background =
"linear-gradient(135deg, #10b981 0%, #059669 100%)";
saveBtn.style.transform = "scale(1.05)";
saveBtn.innerHTML = '<i class="bi bi-check-lg"></i> Saved!';
setTimeout(() => {
saveBtn.style.background = originalBg;
saveBtn.style.transform = originalTransform;
saveBtn.innerHTML = '<i class="bi bi-save"></i> Save All Settings';
}, 2000);
}
}
// Auto remove after 5 seconds
setTimeout(() => {
toast.classList.add("toast-hide");
setTimeout(() => toast.remove(), 300);
}, 5000);
};
window.closeToast = function (button) {
const toast = button.closest(".toast");
toast.classList.add("toast-hide");
setTimeout(() => toast.remove(), 300);
};
// Theme Management - Make global for onclick handlers
function loadTheme() {
const savedTheme = localStorage.getItem("adminTheme") || "light";
applyTheme(savedTheme);
}
window.selectTheme = function (theme) {
console.log("selectTheme called with:", theme);
// Update UI
document.querySelectorAll(".theme-selector .theme-option").forEach((el) => {
el.classList.remove("active");
});
event.target.closest(".theme-option").classList.add("active");
// Save and apply theme
localStorage.setItem("adminTheme", theme);
applyTheme(theme);
window.showToast(`Theme changed to ${theme} mode`, "success");
};
function applyTheme(theme) {
console.log("applyTheme called with:", theme);
const body = document.body;
if (theme === "dark") {
body.classList.add("dark-mode");
body.classList.remove("light-mode");
} else if (theme === "light") {
body.classList.add("light-mode");
body.classList.remove("dark-mode");
} else if (theme === "auto") {
// Check system preference
const prefersDark = window.matchMedia(
"(prefers-color-scheme: dark)"
).matches;
if (prefersDark) {
body.classList.add("dark-mode");
body.classList.remove("light-mode");
} else {
body.classList.add("light-mode");
body.classList.remove("dark-mode");
}
}
// Update active state in UI
const themeOptions = document.querySelectorAll(
".theme-selector .theme-option"
);
themeOptions.forEach((option, index) => {
const themes = ["light", "dark", "auto"];
if (themes[index] === theme) {
option.classList.add("active");
} else {
option.classList.remove("active");
}
});
}
2025-12-14 01:54:40 -06:00
async function loadSettings() {
try {
const response = await fetch("/api/admin/settings", {
credentials: "include",
});
const data = await response.json();
if (data.success) {
currentSettings = data.settings || {};
populateSettings();
}
} catch (error) {
console.error("Failed to load settings:", error);
}
}
function populateSettings() {
// General Settings
if (currentSettings.general) {
document.getElementById("siteName").value =
currentSettings.general.siteName || "";
document.getElementById("siteTagline").value =
currentSettings.general.siteTagline || "";
document.getElementById("siteEmail").value =
currentSettings.general.siteEmail || "";
document.getElementById("sitePhone").value =
currentSettings.general.sitePhone || "";
document.getElementById("timezone").value =
currentSettings.general.timezone || "UTC";
2025-12-24 00:13:23 -06:00
// Logo and Favicon
if (currentSettings.general.siteLogo) {
document.getElementById("siteLogo").value =
currentSettings.general.siteLogo;
document.getElementById(
"logoPreview"
).innerHTML = `<img src="${currentSettings.general.siteLogo}" alt="Logo" />`;
}
if (currentSettings.general.siteFavicon) {
document.getElementById("siteFavicon").value =
currentSettings.general.siteFavicon;
document.getElementById(
"faviconPreview"
).innerHTML = `<img src="${currentSettings.general.siteFavicon}" alt="Favicon" />`;
}
2025-12-14 01:54:40 -06:00
}
// Homepage Settings
if (currentSettings.homepage) {
document.getElementById("showHero").checked =
currentSettings.homepage.showHero !== false;
document.getElementById("showPromotions").checked =
currentSettings.homepage.showPromotions !== false;
document.getElementById("showPortfolio").checked =
currentSettings.homepage.showPortfolio !== false;
document.getElementById("showBlog").checked =
currentSettings.homepage.showBlog !== false;
}
// Product Settings
if (currentSettings.product) {
document.getElementById("defaultProductStatus").value =
currentSettings.product.defaultStatus || "active";
document.getElementById("productsPerPage").value =
currentSettings.product.perPage || 12;
document.getElementById("bestSellerLogic").value =
currentSettings.product.bestSellerLogic || "manual";
document.getElementById("enableInventory").checked =
currentSettings.product.enableInventory !== false;
document.getElementById("showOutOfStock").checked =
currentSettings.product.showOutOfStock !== false;
}
// Security Settings
if (currentSettings.security) {
document.getElementById("passwordExpiration").value =
currentSettings.security.passwordExpiration || 90;
document.getElementById("sessionTimeout").value =
currentSettings.security.sessionTimeout || 60;
document.getElementById("loginAttempts").value =
currentSettings.security.loginAttempts || 5;
document.getElementById("requireStrongPassword").checked =
currentSettings.security.requireStrongPassword !== false;
document.getElementById("enableTwoFactor").checked =
currentSettings.security.enableTwoFactor || false;
}
// Appearance Settings
if (currentSettings.appearance) {
document.getElementById("accentColor").value =
currentSettings.appearance.accentColor || "#667eea";
updateColorPreview();
}
}
2025-12-24 00:13:23 -06:00
// Media Library Functions - Make global for onclick handlers
2026-01-18 02:22:05 -06:00
window.openMediaLibrary = function (targetField) {
2025-12-24 00:13:23 -06:00
console.log("openMediaLibrary called for:", targetField);
currentMediaTarget = targetField;
2026-01-18 02:22:05 -06:00
// Initialize if not already
initSettingsMediaLibrary();
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
if (settingsMediaLibrary) {
settingsMediaLibrary.open();
} else {
showToast("Media library not available", "error");
2025-12-24 00:13:23 -06:00
}
2026-01-18 02:22:05 -06:00
};
2025-12-24 00:13:23 -06:00
window.selectMediaFile = function () {
2026-01-18 02:22:05 -06:00
// This is now handled by the MediaLibrary component's onSelect callback
showToast("Please click on an image to select it", "info");
2025-12-24 00:13:23 -06:00
};
function formatFileSize(bytes) {
if (!bytes) return "0 B";
const k = 1024;
const sizes = ["B", "KB", "MB", "GB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + " " + sizes[i];
}
2025-12-14 01:54:40 -06:00
2025-12-24 00:13:23 -06:00
function previewLogo() {
const url = document.getElementById("siteLogo").value;
const preview = document.getElementById("logoPreview");
if (url) {
preview.innerHTML = `<img src="${url}" alt="Logo" />`;
2025-12-14 01:54:40 -06:00
}
}
2025-12-24 00:13:23 -06:00
function previewFavicon() {
const url = document.getElementById("siteFavicon").value;
const preview = document.getElementById("faviconPreview");
if (url) {
preview.innerHTML = `<img src="${url}" alt="Favicon" />`;
}
2025-12-14 01:54:40 -06:00
}
2025-12-24 00:13:23 -06:00
window.selectLayout = function (layout) {
2025-12-14 01:54:40 -06:00
document.querySelectorAll(".theme-selector .theme-option").forEach((el) => {
el.classList.remove("active");
});
event.target.closest(".theme-option").classList.add("active");
2025-12-24 00:13:23 -06:00
};
2025-12-14 01:54:40 -06:00
function updateColorPreview() {
const color = document.getElementById("accentColor").value;
document.getElementById("colorPreview").style.backgroundColor = color;
document.getElementById("colorValue").textContent = color;
}
2025-12-24 00:13:23 -06:00
window.saveSettings = async function () {
console.log("saveSettings called");
2025-12-14 01:54:40 -06:00
const settings = {
general: {
siteName: document.getElementById("siteName").value,
siteTagline: document.getElementById("siteTagline").value,
siteEmail: document.getElementById("siteEmail").value,
sitePhone: document.getElementById("sitePhone").value,
timezone: document.getElementById("timezone").value,
2025-12-24 00:13:23 -06:00
siteLogo: document.getElementById("siteLogo").value,
siteFavicon: document.getElementById("siteFavicon").value,
2025-12-14 01:54:40 -06:00
},
homepage: {
showHero: document.getElementById("showHero").checked,
showPromotions: document.getElementById("showPromotions").checked,
showPortfolio: document.getElementById("showPortfolio").checked,
showBlog: document.getElementById("showBlog").checked,
},
product: {
defaultStatus: document.getElementById("defaultProductStatus").value,
perPage: parseInt(document.getElementById("productsPerPage").value),
bestSellerLogic: document.getElementById("bestSellerLogic").value,
enableInventory: document.getElementById("enableInventory").checked,
showOutOfStock: document.getElementById("showOutOfStock").checked,
},
security: {
passwordExpiration: parseInt(
document.getElementById("passwordExpiration").value
),
sessionTimeout: parseInt(document.getElementById("sessionTimeout").value),
loginAttempts: parseInt(document.getElementById("loginAttempts").value),
requireStrongPassword: document.getElementById("requireStrongPassword")
.checked,
enableTwoFactor: document.getElementById("enableTwoFactor").checked,
},
appearance: {
accentColor: document.getElementById("accentColor").value,
},
};
2025-12-24 00:13:23 -06:00
console.log("Settings to save:", settings);
2025-12-14 01:54:40 -06:00
try {
const response = await fetch("/api/admin/settings", {
method: "POST",
headers: { "Content-Type": "application/json" },
credentials: "include",
body: JSON.stringify(settings),
});
const data = await response.json();
2025-12-24 00:13:23 -06:00
console.log("Save response:", data);
2025-12-14 01:54:40 -06:00
if (data.success) {
2025-12-24 00:13:23 -06:00
window.showToast("Settings saved successfully!", "success");
2025-12-14 01:54:40 -06:00
currentSettings = settings;
} else {
2025-12-24 00:13:23 -06:00
window.showToast(data.message || "Failed to save settings", "error");
2025-12-14 01:54:40 -06:00
}
} catch (error) {
console.error("Failed to save settings:", error);
2025-12-24 00:13:23 -06:00
window.showToast("Failed to save settings. Please try again.", "error");
2025-12-14 01:54:40 -06:00
}
2025-12-24 00:13:23 -06:00
};