583 lines
17 KiB
JavaScript
583 lines
17 KiB
JavaScript
|
|
// Homepage Editor JavaScript
|
||
|
|
|
||
|
|
let homepageData = {};
|
||
|
|
let quillEditors = {};
|
||
|
|
let currentMediaPicker = null;
|
||
|
|
|
||
|
|
// Initialize Quill editors
|
||
|
|
function initializeQuillEditors() {
|
||
|
|
// Check if Quill is loaded
|
||
|
|
if (typeof Quill === "undefined") {
|
||
|
|
console.error("Quill.js is not loaded!");
|
||
|
|
alert("Text editor failed to load. Please refresh the page.");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const toolbarOptions = [
|
||
|
|
["bold", "italic", "underline", "strike"],
|
||
|
|
["blockquote", "code-block"],
|
||
|
|
[{ header: 1 }, { header: 2 }],
|
||
|
|
[{ list: "ordered" }, { list: "bullet" }],
|
||
|
|
[{ script: "sub" }, { script: "super" }],
|
||
|
|
[{ indent: "-1" }, { indent: "+1" }],
|
||
|
|
[{ direction: "rtl" }],
|
||
|
|
[{ size: ["small", false, "large", "huge"] }],
|
||
|
|
[{ header: [1, 2, 3, 4, 5, 6, false] }],
|
||
|
|
[{ color: [] }, { background: [] }],
|
||
|
|
[{ font: [] }],
|
||
|
|
[{ align: [] }],
|
||
|
|
["link"],
|
||
|
|
["clean"],
|
||
|
|
];
|
||
|
|
|
||
|
|
try {
|
||
|
|
// Initialize Quill for each description field
|
||
|
|
quillEditors.hero = new Quill("#heroDescription", {
|
||
|
|
theme: "snow",
|
||
|
|
modules: { toolbar: toolbarOptions },
|
||
|
|
placeholder: "Enter hero section description...",
|
||
|
|
});
|
||
|
|
|
||
|
|
quillEditors.promotion = new Quill("#promotionDescription", {
|
||
|
|
theme: "snow",
|
||
|
|
modules: { toolbar: toolbarOptions },
|
||
|
|
placeholder: "Enter promotion description...",
|
||
|
|
});
|
||
|
|
|
||
|
|
quillEditors.portfolio = new Quill("#portfolioDescription", {
|
||
|
|
theme: "snow",
|
||
|
|
modules: { toolbar: toolbarOptions },
|
||
|
|
placeholder: "Enter portfolio description...",
|
||
|
|
});
|
||
|
|
|
||
|
|
console.log("Quill editors initialized successfully");
|
||
|
|
} catch (error) {
|
||
|
|
console.error("Error initializing Quill editors:", error);
|
||
|
|
alert(
|
||
|
|
"Failed to initialize text editors. Please check the console for errors."
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
document.addEventListener("DOMContentLoaded", function () {
|
||
|
|
initializeQuillEditors();
|
||
|
|
|
||
|
|
checkAuth().then((authenticated) => {
|
||
|
|
if (authenticated) {
|
||
|
|
loadHomepageSettings();
|
||
|
|
setupMediaLibraryListener();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// Setup media library selection listener
|
||
|
|
function setupMediaLibraryListener() {
|
||
|
|
window.addEventListener("message", function (event) {
|
||
|
|
// Security: verify origin if needed
|
||
|
|
if (
|
||
|
|
event.data &&
|
||
|
|
event.data.type === "mediaSelected" &&
|
||
|
|
currentMediaPicker
|
||
|
|
) {
|
||
|
|
const { section, field } = currentMediaPicker;
|
||
|
|
handleMediaSelection(section, field, event.data.media);
|
||
|
|
currentMediaPicker = null;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
async function loadHomepageSettings() {
|
||
|
|
try {
|
||
|
|
const response = await fetch("/api/admin/homepage/settings", {
|
||
|
|
credentials: "include",
|
||
|
|
});
|
||
|
|
const data = await response.json();
|
||
|
|
if (data.success) {
|
||
|
|
homepageData = data.settings || {};
|
||
|
|
|
||
|
|
// If no data exists, load defaults from the frontend
|
||
|
|
if (Object.keys(homepageData).length === 0) {
|
||
|
|
console.log("No homepage data found, loading defaults from frontend");
|
||
|
|
await loadDefaultsFromFrontend();
|
||
|
|
}
|
||
|
|
|
||
|
|
populateFields();
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error("Failed to load homepage settings:", error);
|
||
|
|
// Load defaults if API fails
|
||
|
|
await loadDefaultsFromFrontend();
|
||
|
|
populateFields();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Load default content from the current homepage
|
||
|
|
async function loadDefaultsFromFrontend() {
|
||
|
|
homepageData = {
|
||
|
|
hero: {
|
||
|
|
enabled: true,
|
||
|
|
headline: "Welcome to Sky Art Shop",
|
||
|
|
subheading: "Your destination for creative stationery and supplies",
|
||
|
|
description:
|
||
|
|
"<p>Discover our curated collection of scrapbooking, journaling, cardmaking, and collaging supplies. Express your creativity and bring your artistic vision to life.</p>",
|
||
|
|
ctaText: "Shop Now",
|
||
|
|
ctaLink: "/shop.html",
|
||
|
|
backgroundUrl: "",
|
||
|
|
layout: "text-left",
|
||
|
|
},
|
||
|
|
promotion: {
|
||
|
|
enabled: true,
|
||
|
|
title: "Get Inspired",
|
||
|
|
description:
|
||
|
|
"<p>At Sky Art Shop, we believe in the power of creativity to transform and inspire. Whether you're an experienced crafter or just beginning your creative journey, we have everything you need to bring your ideas to life.</p><p>Explore our collection of washi tapes, stickers, stamps, and more. Each item is carefully selected to help you create something beautiful and meaningful.</p>",
|
||
|
|
imageUrl: "",
|
||
|
|
imagePosition: "left",
|
||
|
|
textAlignment: "left",
|
||
|
|
},
|
||
|
|
portfolio: {
|
||
|
|
enabled: true,
|
||
|
|
title: "Featured Products",
|
||
|
|
description: "<p>Discover our most popular items</p>",
|
||
|
|
count: 6,
|
||
|
|
},
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
function populateFields() {
|
||
|
|
console.log("Populating fields with data:", homepageData);
|
||
|
|
|
||
|
|
// Hero Section
|
||
|
|
if (homepageData.hero) {
|
||
|
|
document.getElementById("heroEnabled").checked =
|
||
|
|
homepageData.hero.enabled !== false;
|
||
|
|
document.getElementById("heroHeadline").value =
|
||
|
|
homepageData.hero.headline || "";
|
||
|
|
document.getElementById("heroSubheading").value =
|
||
|
|
homepageData.hero.subheading || "";
|
||
|
|
|
||
|
|
if (homepageData.hero.description) {
|
||
|
|
quillEditors.hero.root.innerHTML = homepageData.hero.description;
|
||
|
|
}
|
||
|
|
|
||
|
|
document.getElementById("heroCtaText").value =
|
||
|
|
homepageData.hero.ctaText || "";
|
||
|
|
document.getElementById("heroCtaLink").value =
|
||
|
|
homepageData.hero.ctaLink || "";
|
||
|
|
|
||
|
|
if (homepageData.hero.backgroundUrl) {
|
||
|
|
document.getElementById("heroBackgroundUrl").value =
|
||
|
|
homepageData.hero.backgroundUrl;
|
||
|
|
displayMediaPreview(
|
||
|
|
"hero",
|
||
|
|
"background",
|
||
|
|
homepageData.hero.backgroundUrl
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (homepageData.hero.layout) {
|
||
|
|
const heroSection = document.getElementById("heroSection");
|
||
|
|
heroSection.setAttribute("data-layout", homepageData.hero.layout);
|
||
|
|
setActiveButton(`heroSection`, `layout-${homepageData.hero.layout}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
toggleSection("hero");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Promotion Section
|
||
|
|
if (homepageData.promotion) {
|
||
|
|
document.getElementById("promotionEnabled").checked =
|
||
|
|
homepageData.promotion.enabled !== false;
|
||
|
|
document.getElementById("promotionTitle").value =
|
||
|
|
homepageData.promotion.title || "";
|
||
|
|
|
||
|
|
if (homepageData.promotion.description) {
|
||
|
|
quillEditors.promotion.root.innerHTML =
|
||
|
|
homepageData.promotion.description;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (homepageData.promotion.imageUrl) {
|
||
|
|
document.getElementById("promotionImageUrl").value =
|
||
|
|
homepageData.promotion.imageUrl;
|
||
|
|
displayMediaPreview(
|
||
|
|
"promotion",
|
||
|
|
"image",
|
||
|
|
homepageData.promotion.imageUrl
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (homepageData.promotion.imagePosition) {
|
||
|
|
const promotionSection = document.getElementById("promotionSection");
|
||
|
|
promotionSection.setAttribute(
|
||
|
|
"data-image-position",
|
||
|
|
homepageData.promotion.imagePosition
|
||
|
|
);
|
||
|
|
setActiveButton(
|
||
|
|
`promotionSection`,
|
||
|
|
`position-${homepageData.promotion.imagePosition}`
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (homepageData.promotion.textAlignment) {
|
||
|
|
const promotionSection = document.getElementById("promotionSection");
|
||
|
|
promotionSection.setAttribute(
|
||
|
|
"data-text-alignment",
|
||
|
|
homepageData.promotion.textAlignment
|
||
|
|
);
|
||
|
|
setActiveButton(
|
||
|
|
`promotionSection`,
|
||
|
|
`align-${homepageData.promotion.textAlignment}`
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
toggleSection("promotion");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Portfolio Section
|
||
|
|
if (homepageData.portfolio) {
|
||
|
|
document.getElementById("portfolioEnabled").checked =
|
||
|
|
homepageData.portfolio.enabled !== false;
|
||
|
|
document.getElementById("portfolioTitle").value =
|
||
|
|
homepageData.portfolio.title || "";
|
||
|
|
|
||
|
|
if (homepageData.portfolio.description) {
|
||
|
|
quillEditors.portfolio.root.innerHTML =
|
||
|
|
homepageData.portfolio.description;
|
||
|
|
}
|
||
|
|
|
||
|
|
document.getElementById("portfolioCount").value =
|
||
|
|
homepageData.portfolio.count || 6;
|
||
|
|
toggleSection("portfolio");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Show success message
|
||
|
|
showSuccess(
|
||
|
|
"Homepage content loaded! You can now edit and preview your changes."
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
function setActiveButton(sectionId, className) {
|
||
|
|
const section = document.getElementById(sectionId);
|
||
|
|
if (section) {
|
||
|
|
const buttons = section.querySelectorAll(".alignment-btn");
|
||
|
|
buttons.forEach((btn) => {
|
||
|
|
if (btn.classList.contains(className)) {
|
||
|
|
btn.classList.add("active");
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function toggleSection(sectionName) {
|
||
|
|
const enabled = document.getElementById(`${sectionName}Enabled`).checked;
|
||
|
|
const section = document.getElementById(`${sectionName}Section`);
|
||
|
|
const content = section.querySelector(".section-content");
|
||
|
|
|
||
|
|
if (enabled) {
|
||
|
|
section.classList.remove("disabled");
|
||
|
|
content.querySelectorAll("input, button, select").forEach((el) => {
|
||
|
|
el.disabled = false;
|
||
|
|
});
|
||
|
|
// Enable Quill editor
|
||
|
|
if (quillEditors[sectionName]) {
|
||
|
|
quillEditors[sectionName].enable();
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
section.classList.add("disabled");
|
||
|
|
content.querySelectorAll("input, button, select").forEach((el) => {
|
||
|
|
el.disabled = true;
|
||
|
|
});
|
||
|
|
// Disable Quill editor
|
||
|
|
if (quillEditors[sectionName]) {
|
||
|
|
quillEditors[sectionName].disable();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Open media library in a modal
|
||
|
|
function openMediaLibrary(section, field) {
|
||
|
|
currentMediaPicker = { section, field };
|
||
|
|
|
||
|
|
// Create modal backdrop
|
||
|
|
const backdrop = document.createElement("div");
|
||
|
|
backdrop.id = "mediaLibraryBackdrop";
|
||
|
|
backdrop.style.cssText = `
|
||
|
|
position: fixed;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
background: rgba(0,0,0,0.7);
|
||
|
|
z-index: 9998;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
`;
|
||
|
|
|
||
|
|
// Create modal container
|
||
|
|
const modal = document.createElement("div");
|
||
|
|
modal.id = "mediaLibraryModal";
|
||
|
|
modal.style.cssText = `
|
||
|
|
position: relative;
|
||
|
|
width: 90%;
|
||
|
|
max-width: 1200px;
|
||
|
|
height: 85vh;
|
||
|
|
background: white;
|
||
|
|
border-radius: 12px;
|
||
|
|
overflow: hidden;
|
||
|
|
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
|
||
|
|
`;
|
||
|
|
|
||
|
|
// Create close button
|
||
|
|
const closeBtn = document.createElement("button");
|
||
|
|
closeBtn.innerHTML = '<i class="bi bi-x-lg"></i>';
|
||
|
|
closeBtn.style.cssText = `
|
||
|
|
position: absolute;
|
||
|
|
top: 15px;
|
||
|
|
right: 15px;
|
||
|
|
z-index: 10000;
|
||
|
|
background: #dc3545;
|
||
|
|
color: white;
|
||
|
|
border: none;
|
||
|
|
width: 40px;
|
||
|
|
height: 40px;
|
||
|
|
border-radius: 50%;
|
||
|
|
cursor: pointer;
|
||
|
|
font-size: 18px;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
`;
|
||
|
|
closeBtn.onclick = closeMediaLibrary;
|
||
|
|
|
||
|
|
// Create iframe
|
||
|
|
const iframe = document.createElement("iframe");
|
||
|
|
iframe.id = "mediaLibraryFrame";
|
||
|
|
iframe.src = "/admin/media-library.html?selectMode=true";
|
||
|
|
iframe.style.cssText = `
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
border: none;
|
||
|
|
`;
|
||
|
|
|
||
|
|
// Setup iframe message listener
|
||
|
|
iframe.onload = function () {
|
||
|
|
iframe.contentWindow.postMessage(
|
||
|
|
{
|
||
|
|
type: "initSelectMode",
|
||
|
|
section: section,
|
||
|
|
field: field,
|
||
|
|
},
|
||
|
|
"*"
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
modal.appendChild(closeBtn);
|
||
|
|
modal.appendChild(iframe);
|
||
|
|
backdrop.appendChild(modal);
|
||
|
|
document.body.appendChild(backdrop);
|
||
|
|
|
||
|
|
// Close on backdrop click
|
||
|
|
backdrop.onclick = function (e) {
|
||
|
|
if (e.target === backdrop) {
|
||
|
|
closeMediaLibrary();
|
||
|
|
}
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
function closeMediaLibrary() {
|
||
|
|
const backdrop = document.getElementById("mediaLibraryBackdrop");
|
||
|
|
if (backdrop) {
|
||
|
|
backdrop.remove();
|
||
|
|
}
|
||
|
|
currentMediaPicker = null;
|
||
|
|
}
|
||
|
|
|
||
|
|
function handleMediaSelection(section, field, media) {
|
||
|
|
closeMediaLibrary();
|
||
|
|
|
||
|
|
const urlField = document.getElementById(
|
||
|
|
`${section}${field === "background" ? "Background" : "Image"}Url`
|
||
|
|
);
|
||
|
|
if (urlField) {
|
||
|
|
urlField.value = media.url;
|
||
|
|
}
|
||
|
|
|
||
|
|
displayMediaPreview(section, field, media.url);
|
||
|
|
|
||
|
|
showSuccess(`Media selected successfully!`);
|
||
|
|
}
|
||
|
|
|
||
|
|
function displayMediaPreview(section, field, url) {
|
||
|
|
const previewId = `${section}Preview`;
|
||
|
|
const preview = document.getElementById(previewId);
|
||
|
|
const clearBtnId = `${section}${
|
||
|
|
field === "background" ? "Background" : "Image"
|
||
|
|
}Clear`;
|
||
|
|
const clearBtn = document.getElementById(clearBtnId);
|
||
|
|
|
||
|
|
if (preview) {
|
||
|
|
preview.classList.remove("empty");
|
||
|
|
|
||
|
|
// Check if it's a video
|
||
|
|
const isVideo = url.match(/\.(mp4|webm|ogg)$/i);
|
||
|
|
|
||
|
|
if (isVideo) {
|
||
|
|
preview.innerHTML = `<video src="${url}" style="max-width: 100%; max-height: 100%;" controls></video>`;
|
||
|
|
} else {
|
||
|
|
preview.innerHTML = `<img src="${url}" alt="Preview" />`;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (clearBtn) {
|
||
|
|
clearBtn.style.display = "inline-block";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function clearMedia(section, field) {
|
||
|
|
const urlField = document.getElementById(
|
||
|
|
`${section}${field === "background" ? "Background" : "Image"}Url`
|
||
|
|
);
|
||
|
|
if (urlField) {
|
||
|
|
urlField.value = "";
|
||
|
|
}
|
||
|
|
|
||
|
|
const previewId = `${section}Preview`;
|
||
|
|
const preview = document.getElementById(previewId);
|
||
|
|
if (preview) {
|
||
|
|
preview.classList.add("empty");
|
||
|
|
preview.innerHTML = '<i class="bi bi-image" style="font-size: 3rem"></i>';
|
||
|
|
}
|
||
|
|
|
||
|
|
const clearBtnId = `${section}${
|
||
|
|
field === "background" ? "Background" : "Image"
|
||
|
|
}Clear`;
|
||
|
|
const clearBtn = document.getElementById(clearBtnId);
|
||
|
|
if (clearBtn) {
|
||
|
|
clearBtn.style.display = "none";
|
||
|
|
}
|
||
|
|
|
||
|
|
showSuccess("Media cleared");
|
||
|
|
}
|
||
|
|
|
||
|
|
function setLayout(sectionName, layout) {
|
||
|
|
const section = document.getElementById(`${sectionName}Section`);
|
||
|
|
const buttons = section.querySelectorAll(".alignment-btn");
|
||
|
|
buttons.forEach((btn) => btn.classList.remove("active"));
|
||
|
|
event.target.closest(".alignment-btn").classList.add("active");
|
||
|
|
|
||
|
|
// Store in a data attribute
|
||
|
|
section.setAttribute(`data-layout`, layout);
|
||
|
|
}
|
||
|
|
|
||
|
|
function setImagePosition(sectionName, position) {
|
||
|
|
const section = document.getElementById(`${sectionName}Section`);
|
||
|
|
const buttons = event.target
|
||
|
|
.closest(".alignment-selector")
|
||
|
|
.querySelectorAll(".alignment-btn");
|
||
|
|
buttons.forEach((btn) => btn.classList.remove("active"));
|
||
|
|
event.target.closest(".alignment-btn").classList.add("active");
|
||
|
|
|
||
|
|
section.setAttribute(`data-image-position`, position);
|
||
|
|
}
|
||
|
|
|
||
|
|
function setTextAlignment(sectionName, alignment) {
|
||
|
|
const section = document.getElementById(`${sectionName}Section`);
|
||
|
|
const buttons = event.target
|
||
|
|
.closest(".alignment-selector")
|
||
|
|
.querySelectorAll(".alignment-btn");
|
||
|
|
buttons.forEach((btn) => btn.classList.remove("active"));
|
||
|
|
event.target.closest(".alignment-btn").classList.add("active");
|
||
|
|
|
||
|
|
section.setAttribute(`data-text-alignment`, alignment);
|
||
|
|
}
|
||
|
|
|
||
|
|
async function saveHomepage() {
|
||
|
|
// Get hero layout
|
||
|
|
const heroSection = document.getElementById("heroSection");
|
||
|
|
const heroLayout = heroSection.getAttribute("data-layout") || "text-left";
|
||
|
|
|
||
|
|
// Get promotion layout settings
|
||
|
|
const promotionSection = document.getElementById("promotionSection");
|
||
|
|
const promotionImagePosition =
|
||
|
|
promotionSection.getAttribute("data-image-position") || "left";
|
||
|
|
const promotionTextAlignment =
|
||
|
|
promotionSection.getAttribute("data-text-alignment") || "left";
|
||
|
|
|
||
|
|
const settings = {
|
||
|
|
hero: {
|
||
|
|
enabled: document.getElementById("heroEnabled").checked,
|
||
|
|
headline: document.getElementById("heroHeadline").value,
|
||
|
|
subheading: document.getElementById("heroSubheading").value,
|
||
|
|
description: quillEditors.hero.root.innerHTML,
|
||
|
|
ctaText: document.getElementById("heroCtaText").value,
|
||
|
|
ctaLink: document.getElementById("heroCtaLink").value,
|
||
|
|
backgroundUrl: document.getElementById("heroBackgroundUrl")?.value || "",
|
||
|
|
layout: heroLayout,
|
||
|
|
},
|
||
|
|
promotion: {
|
||
|
|
enabled: document.getElementById("promotionEnabled").checked,
|
||
|
|
title: document.getElementById("promotionTitle").value,
|
||
|
|
description: quillEditors.promotion.root.innerHTML,
|
||
|
|
imageUrl: document.getElementById("promotionImageUrl")?.value || "",
|
||
|
|
imagePosition: promotionImagePosition,
|
||
|
|
textAlignment: promotionTextAlignment,
|
||
|
|
},
|
||
|
|
portfolio: {
|
||
|
|
enabled: document.getElementById("portfolioEnabled").checked,
|
||
|
|
title: document.getElementById("portfolioTitle").value,
|
||
|
|
description: quillEditors.portfolio.root.innerHTML,
|
||
|
|
count: parseInt(document.getElementById("portfolioCount").value) || 6,
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
try {
|
||
|
|
const response = await fetch("/api/admin/homepage/settings", {
|
||
|
|
method: "POST",
|
||
|
|
headers: { "Content-Type": "application/json" },
|
||
|
|
credentials: "include",
|
||
|
|
body: JSON.stringify(settings),
|
||
|
|
});
|
||
|
|
|
||
|
|
const data = await response.json();
|
||
|
|
if (data.success) {
|
||
|
|
showSuccess(
|
||
|
|
"Homepage settings saved successfully! Changes are now live on the frontend."
|
||
|
|
);
|
||
|
|
homepageData = settings;
|
||
|
|
} else {
|
||
|
|
showError(data.message || "Failed to save homepage settings");
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error("Failed to save homepage:", error);
|
||
|
|
showError("Failed to save homepage settings");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function showSuccess(message) {
|
||
|
|
const alert = document.createElement("div");
|
||
|
|
alert.className =
|
||
|
|
"alert alert-success alert-dismissible fade show position-fixed";
|
||
|
|
alert.style.cssText =
|
||
|
|
"top: 20px; right: 20px; z-index: 9999; min-width: 300px;";
|
||
|
|
alert.innerHTML = `
|
||
|
|
${message}
|
||
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||
|
|
`;
|
||
|
|
document.body.appendChild(alert);
|
||
|
|
setTimeout(() => alert.remove(), 5000);
|
||
|
|
}
|
||
|
|
|
||
|
|
function showError(message) {
|
||
|
|
const alert = document.createElement("div");
|
||
|
|
alert.className =
|
||
|
|
"alert alert-danger alert-dismissible fade show position-fixed";
|
||
|
|
alert.style.cssText =
|
||
|
|
"top: 20px; right: 20px; z-index: 9999; min-width: 300px;";
|
||
|
|
alert.innerHTML = `
|
||
|
|
${message}
|
||
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||
|
|
`;
|
||
|
|
document.body.appendChild(alert);
|
||
|
|
setTimeout(() => alert.remove(), 5000);
|
||
|
|
}
|