2026-01-18 02:22:05 -06:00
// Homepage Editor JavaScript - Updated for Hero Slides
let homepageData = {
heroSlides : [ ] ,
featuredProducts : {
enabled : true ,
title : "Featured Products" ,
count : 4 ,
} ,
blog : {
enabled : true ,
title : "Get Inspired" ,
count : 3 ,
} ,
about : {
enabled : true ,
title : "About Sky Art Shop" ,
description :
"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." ,
imageUrl : "" ,
} ,
} ;
let currentMediaTarget = null ;
let mediaLibrary = null ;
// Quill editors storage
2025-12-24 00:13:23 -06:00
let quillEditors = { } ;
2025-12-14 01:54:40 -06:00
2026-01-18 02:22:05 -06:00
// Quill toolbar configuration
const quillToolbarOptions = [
[ "bold" , "italic" , "underline" , "strike" ] ,
[ { list : "ordered" } , { list : "bullet" } ] ,
[ { header : [ 1 , 2 , 3 , false ] } ] ,
[ { color : [ ] } , { background : [ ] } ] ,
[ { align : [ ] } ] ,
[ "link" ] ,
[ "clean" ] ,
] ;
// Initialize on DOM load
2025-12-14 01:54:40 -06:00
document . addEventListener ( "DOMContentLoaded" , function ( ) {
2026-01-18 02:22:05 -06:00
// Initialize the modern media library
mediaLibrary = new MediaLibrary ( {
selectMode : true ,
multiple : false ,
onSelect : handleMediaSelection ,
} ) ;
2025-12-24 00:13:23 -06:00
2025-12-14 01:54:40 -06:00
checkAuth ( ) . then ( ( authenticated ) => {
if ( authenticated ) {
loadHomepageSettings ( ) ;
}
} ) ;
} ) ;
2026-01-18 02:22:05 -06:00
// Load homepage settings from backend
2025-12-14 01:54:40 -06:00
async function loadHomepageSettings ( ) {
try {
const response = await fetch ( "/api/admin/homepage/settings" , {
credentials : "include" ,
} ) ;
const data = await response . json ( ) ;
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
if ( data . success && data . settings ) {
// Migrate old format to new format if needed
if ( data . settings . hero && ! data . settings . heroSlides ) {
// Convert old single hero to slides
homepageData . heroSlides = [
{
id : generateSlideId ( ) ,
title : data . settings . hero . headline || "Welcome to Sky Art Shop" ,
description :
stripHtml ( data . settings . hero . description ) ||
"Discover our beautiful collection of stationery and crafting supplies." ,
buttonText : data . settings . hero . ctaText || "Shop Now" ,
buttonLink : data . settings . hero . ctaLink || "/shop" ,
imageUrl : data . settings . hero . backgroundUrl || "" ,
} ,
] ;
} else if ( data . settings . heroSlides ) {
homepageData . heroSlides = data . settings . heroSlides ;
}
// Load featured products settings
if ( data . settings . featuredProducts ) {
homepageData . featuredProducts = data . settings . featuredProducts ;
}
// Load blog settings
if ( data . settings . blog ) {
homepageData . blog = data . settings . blog ;
2025-12-24 00:13:23 -06:00
}
2026-01-18 02:22:05 -06:00
// Load about settings
if ( data . settings . about ) {
homepageData . about = data . settings . about ;
}
}
// Initialize with default slides if empty
if ( homepageData . heroSlides . length === 0 ) {
homepageData . heroSlides = getDefaultSlides ( ) ;
2025-12-14 01:54:40 -06:00
}
2026-01-18 02:22:05 -06:00
renderAllSections ( ) ;
showSuccess ( "Homepage settings loaded successfully!" ) ;
2025-12-14 01:54:40 -06:00
} catch ( error ) {
console . error ( "Failed to load homepage settings:" , error ) ;
2026-01-18 02:22:05 -06:00
// Load defaults
homepageData . heroSlides = getDefaultSlides ( ) ;
renderAllSections ( ) ;
2025-12-14 01:54:40 -06:00
}
}
2026-01-18 02:22:05 -06:00
// Get default slides
function getDefaultSlides ( ) {
return [
{
id : generateSlideId ( ) ,
title : "Welcome to Sky Art Shop" ,
2025-12-24 00:13:23 -06:00
description :
2026-01-18 02:22:05 -06:00
"Discover our beautiful collection of stationery, washi tapes, stickers, and crafting supplies. Perfect for bullet journaling, scrapbooking, and all your creative projects." ,
buttonText : "Shop Now" ,
buttonLink : "/shop" ,
imageUrl :
"https://images.unsplash.com/photo-1513519245088-0e12902e35a6?w=1920&q=80" ,
2025-12-24 00:13:23 -06:00
} ,
2026-01-18 02:22:05 -06:00
{
id : generateSlideId ( ) ,
title : "Express Your Creativity" ,
2025-12-24 00:13:23 -06:00
description :
2026-01-18 02:22:05 -06:00
"From vibrant markers to elegant journals, find everything you need to bring your artistic vision to life. Quality supplies for every crafter." ,
buttonText : "Explore Collection" ,
buttonLink : "/shop" ,
imageUrl :
"https://images.unsplash.com/photo-1456735190827-d1262f71b8a3?w=1920&q=80" ,
2025-12-24 00:13:23 -06:00
} ,
2026-01-18 02:22:05 -06:00
{
id : generateSlideId ( ) ,
title : "New Arrivals Every Week" ,
description :
"Stay inspired with our constantly updated selection of unique and trendy stationery. Be the first to discover our latest additions." ,
buttonText : "See What's New" ,
buttonLink : "/shop" ,
imageUrl :
"https://images.unsplash.com/photo-1452860606245-08befc0ff44b?w=1920&q=80" ,
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
// Strip HTML tags from text
function stripHtml ( html ) {
if ( ! html ) return "" ;
const tmp = document . createElement ( "DIV" ) ;
tmp . innerHTML = html ;
return tmp . textContent || tmp . innerText || "" ;
}
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Generate unique slide ID
function generateSlideId ( ) {
return "slide_" + Date . now ( ) + "_" + Math . random ( ) . toString ( 36 ) . substr ( 2 , 9 ) ;
}
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Render all sections
function renderAllSections ( ) {
renderSlides ( ) ;
renderFeaturedProducts ( ) ;
renderBlogSection ( ) ;
renderAboutSection ( ) ;
}
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Render hero slides
function renderSlides ( ) {
const container = document . getElementById ( "slidesContainer" ) ;
const countBadge = document . getElementById ( "slideCount" ) ;
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Destroy existing Quill editors for slides
Object . keys ( quillEditors ) . forEach ( ( key ) => {
if ( key . startsWith ( "slide_desc_" ) ) {
delete quillEditors [ key ] ;
2025-12-24 00:13:23 -06:00
}
2026-01-18 02:22:05 -06:00
} ) ;
countBadge . textContent = ` ${ homepageData . heroSlides . length } slides ` ;
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
if ( homepageData . heroSlides . length === 0 ) {
container . innerHTML =
'<p class="text-muted text-center py-4">No slides yet. Click "Add New Slide" to create one.</p>' ;
return ;
2025-12-14 01:54:40 -06:00
}
2026-01-18 02:22:05 -06:00
container . innerHTML = homepageData . heroSlides
. map (
( slide , index ) => `
< div class = "slide-card" data - slide - id = "${slide.id}" >
< div class = "slide-header" >
< span class = "slide-number" >
< i class = "bi bi-grip-vertical drag-handle me-2" > < / i >
Slide $ { index + 1 }
< / s p a n >
< div class = "slide-actions" >
$ {
index > 0
? ` <button class="btn btn-sm btn-outline-secondary" onclick="moveSlide(' ${ slide . id } ', -1)" title="Move Up"><i class="bi bi-arrow-up"></i></button> `
: ""
}
$ {
index < homepageData . heroSlides . length - 1
? ` <button class="btn btn-sm btn-outline-secondary" onclick="moveSlide(' ${ slide . id } ', 1)" title="Move Down"><i class="bi bi-arrow-down"></i></button> `
: ""
}
< button class = "btn btn-sm btn-outline-danger" onclick = " deleteSlide ( ' $ {
slide . id
} ' ) " title=" Delete Slide "><i class=" bi bi - trash " > < / i > < / b u t t o n >
< / d i v >
< / d i v >
< div class = "row" >
< div class = "col-md-6" >
< div class = "mb-3" >
< label class = "form-label" > Slide Title * < / l a b e l >
< input type = "text" class = "form-control" value = " $ { escapeHtml (
slide . title
) } " onchange=" updateSlide ( ' $ {
slide . id
} ', ' title ' , this . value ) " placeholder=" Enter slide title " >
< / d i v >
< div class = "mb-3" >
< label class = "form-label" > Description < / l a b e l >
< div class = "quill-container" >
< div id = "slideDesc_${slide.id}" > < / d i v >
< / d i v >
< / d i v >
< div class = "row" >
< div class = "col-6" >
< div class = "mb-3" >
< label class = "form-label" > Button Text < / l a b e l >
< input type = "text" class = "form-control" value = " $ { escapeHtml (
slide . buttonText
) } " onchange=" updateSlide ( ' $ {
slide . id
} ', ' buttonText ' , this . value ) " placeholder=" Shop Now " >
< / d i v >
< / d i v >
< div class = "col-6" >
< div class = "mb-3" >
< label class = "form-label" > Button Link < / l a b e l >
< input type = "text" class = "form-control" value = " $ { escapeHtml (
slide . buttonLink
) } " onchange=" updateSlide ( ' $ {
slide . id
} ', ' buttonLink ' , this . value ) " placeholder=" / shop " >
< / d i v >
< / d i v >
< / d i v >
< / d i v >
< div class = "col-md-6" >
< div class = "mb-3" >
< label class = "form-label" > Background Image * < / l a b e l >
< small class = "d-block text-muted mb-2" > < i class = "bi bi-info-circle" > < / i > R e c o m m e n d e d : < s t r o n g > 1 9 2 0 x 6 0 0 p x < / s t r o n g > ( l a n d s c a p e ) < / s m a l l >
< input type = "hidden" id = "slideImage_${slide.id}" value = " $ {
slide . imageUrl || ""
} " >
< button type = "button" class = "btn btn-outline-primary w-100" onclick = " openMediaLibrary ( 'slide' , ' $ {
slide . id
} ' ) " >
< i class = "bi bi-folder2-open" > < / i > C h o o s e I m a g e
< / b u t t o n >
< div class = " image - preview $ {
slide . imageUrl ? "" : "empty"
} " id=" slidePreview _$ { slide . id } " >
$ {
slide . imageUrl
? ` <img src=" ${ slide . imageUrl } " alt="Slide preview"> `
: '<i class="bi bi-image" style="font-size: 2rem"></i>'
}
< / d i v >
$ {
slide . imageUrl
? `
< button type = "button" class = "btn btn-sm btn-outline-danger mt-2" onclick = "clearSlideImage('${slide.id}')" >
< i class = "bi bi-x-circle" > < / i > C l e a r I m a g e
< / b u t t o n >
`
: ""
}
< / d i v >
< div class = "mb-3" >
< label class = "form-label" > Or enter image URL directly < / l a b e l >
< input type = "text" class = "form-control" value = " $ { escapeHtml (
slide . imageUrl || ""
) } " onchange=" updateSlideImage ( ' $ {
slide . id
} ' , this . value ) " placeholder=" https : //example.com/image.jpg">
< / d i v >
< / d i v >
< / d i v >
< / d i v >
`
)
. join ( "" ) ;
// Initialize Quill editors for each slide description
setTimeout ( ( ) => {
homepageData . heroSlides . forEach ( ( slide ) => {
initSlideQuillEditor ( slide . id , slide . description ) ;
} ) ;
} , 100 ) ;
}
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Add new slide
function addNewSlide ( ) {
const newSlide = {
id : generateSlideId ( ) ,
title : "" ,
description : "" ,
buttonText : "Shop Now" ,
buttonLink : "/shop" ,
imageUrl : "" ,
} ;
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
homepageData . heroSlides . push ( newSlide ) ;
renderSlides ( ) ;
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Scroll to the new slide
setTimeout ( ( ) => {
const newSlideEl = document . querySelector (
` [data-slide-id=" ${ newSlide . id } "] `
) ;
if ( newSlideEl ) {
newSlideEl . scrollIntoView ( { behavior : "smooth" , block : "center" } ) ;
newSlideEl . classList . add ( "active" ) ;
setTimeout ( ( ) => newSlideEl . classList . remove ( "active" ) , 2000 ) ;
2025-12-24 00:13:23 -06:00
}
2026-01-18 02:22:05 -06:00
} , 100 ) ;
}
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Update slide field
function updateSlide ( slideId , field , value ) {
const slide = homepageData . heroSlides . find ( ( s ) => s . id === slideId ) ;
if ( slide ) {
slide [ field ] = value ;
}
}
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Update slide image
function updateSlideImage ( slideId , url ) {
const slide = homepageData . heroSlides . find ( ( s ) => s . id === slideId ) ;
if ( slide ) {
slide . imageUrl = url ;
const preview = document . getElementById ( ` slidePreview_ ${ slideId } ` ) ;
if ( preview ) {
if ( url ) {
preview . classList . remove ( "empty" ) ;
preview . innerHTML = ` <img src=" ${ url } " alt="Slide preview"> ` ;
} else {
preview . classList . add ( "empty" ) ;
preview . innerHTML =
'<i class="bi bi-image" style="font-size: 2rem"></i>' ;
}
}
2025-12-14 01:54:40 -06:00
}
2026-01-18 02:22:05 -06:00
}
2025-12-14 01:54:40 -06:00
2026-01-18 02:22:05 -06:00
// Clear slide image
function clearSlideImage ( slideId ) {
updateSlide ( slideId , "imageUrl" , "" ) ;
document . getElementById ( ` slideImage_ ${ slideId } ` ) . value = "" ;
renderSlides ( ) ;
}
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Move slide up or down
function moveSlide ( slideId , direction ) {
const index = homepageData . heroSlides . findIndex ( ( s ) => s . id === slideId ) ;
if ( index === - 1 ) return ;
const newIndex = index + direction ;
if ( newIndex < 0 || newIndex >= homepageData . heroSlides . length ) return ;
// Swap
const temp = homepageData . heroSlides [ index ] ;
homepageData . heroSlides [ index ] = homepageData . heroSlides [ newIndex ] ;
homepageData . heroSlides [ newIndex ] = temp ;
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
renderSlides ( ) ;
}
// Delete slide
function deleteSlide ( slideId ) {
if ( homepageData . heroSlides . length <= 1 ) {
showError ( "You must have at least one slide" ) ;
return ;
2025-12-14 01:54:40 -06:00
}
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
showDeleteConfirm (
"Are you sure you want to delete this slide?" ,
( ) => {
homepageData . heroSlides = homepageData . heroSlides . filter (
( s ) => s . id !== slideId
) ;
renderSlides ( ) ;
showSuccess ( "Slide deleted" ) ;
} ,
{ title : "Delete Slide" , confirmText : "Delete Slide" }
2025-12-24 00:13:23 -06:00
) ;
}
2026-01-18 02:22:05 -06:00
// Render featured products section
function renderFeaturedProducts ( ) {
document . getElementById ( "featuredEnabled" ) . checked =
homepageData . featuredProducts . enabled ;
document . getElementById ( "featuredTitle" ) . value =
homepageData . featuredProducts . title || "Featured Products" ;
// Set active count button
document
. querySelectorAll ( "#featuredProductsSection .count-btn" )
. forEach ( ( btn ) => {
btn . classList . toggle (
"active" ,
parseInt ( btn . dataset . count ) === homepageData . featuredProducts . count
) ;
2025-12-24 00:13:23 -06:00
} ) ;
2025-12-14 01:54:40 -06:00
}
2026-01-18 02:22:05 -06:00
// Set featured products count
function setFeaturedCount ( count ) {
homepageData . featuredProducts . count = count ;
document
. querySelectorAll ( "#featuredProductsSection .count-btn" )
. forEach ( ( btn ) => {
btn . classList . toggle ( "active" , parseInt ( btn . dataset . count ) === count ) ;
2025-12-24 00:13:23 -06:00
} ) ;
}
2026-01-18 02:22:05 -06:00
// Render blog section
function renderBlogSection ( ) {
document . getElementById ( "blogEnabled" ) . checked = homepageData . blog . enabled ;
document . getElementById ( "blogTitle" ) . value =
homepageData . blog . title || "Get Inspired" ;
// Set active count button
document . querySelectorAll ( "#blogSection .count-btn" ) . forEach ( ( btn ) => {
btn . classList . toggle (
"active" ,
parseInt ( btn . dataset . count ) === homepageData . blog . count
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
// Set blog posts count
function setBlogCount ( count ) {
homepageData . blog . count = count ;
document . querySelectorAll ( "#blogSection .count-btn" ) . forEach ( ( btn ) => {
btn . classList . toggle ( "active" , parseInt ( btn . dataset . count ) === count ) ;
} ) ;
2025-12-24 00:13:23 -06:00
}
2026-01-18 02:22:05 -06:00
// Render about section
function renderAboutSection ( ) {
document . getElementById ( "aboutEnabled" ) . checked = homepageData . about . enabled ;
document . getElementById ( "aboutTitle" ) . value =
homepageData . about . title || "About Sky Art Shop" ;
// Initialize Quill for about description
initAboutQuillEditor ( homepageData . about . description || "" ) ;
const preview = document . getElementById ( "aboutPreview" ) ;
if ( homepageData . about . imageUrl ) {
document . getElementById ( "aboutImageUrl" ) . value =
homepageData . about . imageUrl ;
preview . classList . remove ( "empty" ) ;
preview . innerHTML = ` <img src=" ${ homepageData . about . imageUrl } " alt="About preview"> ` ;
2025-12-14 01:54:40 -06:00
}
}
2026-01-18 02:22:05 -06:00
// Initialize Quill editor for About section
function initAboutQuillEditor ( content ) {
const editorEl = document . getElementById ( "aboutDescriptionEditor" ) ;
if ( ! editorEl ) return ;
2025-12-14 01:54:40 -06:00
2026-01-18 02:22:05 -06:00
// Destroy existing editor if any
if ( quillEditors [ "about" ] ) {
delete quillEditors [ "about" ] ;
2025-12-14 01:54:40 -06:00
}
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
quillEditors [ "about" ] = new Quill ( "#aboutDescriptionEditor" , {
theme : "snow" ,
modules : {
toolbar : quillToolbarOptions ,
} ,
placeholder : "Write a short description about your shop..." ,
} ) ;
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Set initial content
if ( content ) {
quillEditors [ "about" ] . root . innerHTML = content ;
}
2025-12-14 01:54:40 -06:00
2026-01-18 02:22:05 -06:00
// Update data on change
quillEditors [ "about" ] . on ( "text-change" , function ( ) {
homepageData . about . description = quillEditors [ "about" ] . root . innerHTML ;
} ) ;
}
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Initialize Quill editor for slide description
function initSlideQuillEditor ( slideId , content ) {
const editorEl = document . getElementById ( ` slideDesc_ ${ slideId } ` ) ;
if ( ! editorEl ) return ;
const editorKey = ` slide_desc_ ${ slideId } ` ;
quillEditors [ editorKey ] = new Quill ( ` #slideDesc_ ${ slideId } ` , {
theme : "snow" ,
modules : {
toolbar : [
[ "bold" , "italic" , "underline" ] ,
[ { list : "ordered" } , { list : "bullet" } ] ,
[ "link" ] ,
[ "clean" ] ,
] ,
} ,
placeholder : "Enter slide description..." ,
} ) ;
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Set initial content
if ( content ) {
quillEditors [ editorKey ] . root . innerHTML = content ;
}
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Update slide data on change
quillEditors [ editorKey ] . on ( "text-change" , function ( ) {
const slide = homepageData . heroSlides . find ( ( s ) => s . id === slideId ) ;
if ( slide ) {
slide . description = quillEditors [ editorKey ] . root . innerHTML ;
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
// Open media library
function openMediaLibrary ( type , id = null ) {
currentMediaTarget = { type , id } ;
mediaLibrary . open ( ) ;
2025-12-24 00:13:23 -06:00
}
2026-01-18 02:22:05 -06:00
// Handle media selection
function handleMediaSelection ( media ) {
if ( ! currentMediaTarget ) return ;
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
// Media is now a single object with path property
if ( ! media || ! media . path ) {
showError ( "No image selected" ) ;
return ;
2025-12-24 00:13:23 -06:00
}
2026-01-18 02:22:05 -06:00
console . log ( "Selected media:" , media ) ;
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
const { type , id } = currentMediaTarget ;
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
if ( type === "slide" && id ) {
const slide = homepageData . heroSlides . find ( ( s ) => s . id === id ) ;
if ( slide ) {
slide . imageUrl = media . path ;
const hiddenInput = document . getElementById ( ` slideImage_ ${ id } ` ) ;
if ( hiddenInput ) {
hiddenInput . value = media . path ;
}
const preview = document . getElementById ( ` slidePreview_ ${ id } ` ) ;
if ( preview ) {
preview . classList . remove ( "empty" ) ;
preview . innerHTML = ` <img src=" ${ media . path } " alt="Slide preview"> ` ;
}
console . log ( "Updated slide:" , slide ) ;
// Don't re-render, just update the preview and data
}
} else if ( type === "about" ) {
homepageData . about . imageUrl = media . path ;
document . getElementById ( "aboutImageUrl" ) . value = media . path ;
const preview = document . getElementById ( "aboutPreview" ) ;
preview . classList . remove ( "empty" ) ;
preview . innerHTML = ` <img src=" ${ media . path } " alt="About preview"> ` ;
}
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
currentMediaTarget = null ;
showSuccess ( "Image selected successfully!" ) ;
2025-12-14 01:54:40 -06:00
}
2026-01-18 02:22:05 -06:00
// Escape HTML
function escapeHtml ( text ) {
if ( ! text ) return "" ;
const div = document . createElement ( "div" ) ;
div . textContent = text ;
return div . innerHTML ;
2025-12-14 01:54:40 -06:00
}
2026-01-18 02:22:05 -06:00
// Save all homepage settings
async function saveHomepage ( ) {
// Collect all data from form
homepageData . featuredProducts = {
enabled : document . getElementById ( "featuredEnabled" ) . checked ,
title : document . getElementById ( "featuredTitle" ) . value ,
count : homepageData . featuredProducts . count ,
} ;
2025-12-24 00:13:23 -06:00
2026-01-18 02:22:05 -06:00
homepageData . blog = {
enabled : document . getElementById ( "blogEnabled" ) . checked ,
title : document . getElementById ( "blogTitle" ) . value ,
count : homepageData . blog . count ,
} ;
2025-12-14 01:54:40 -06:00
2026-01-18 02:22:05 -06:00
// Get description from Quill editor
const aboutDescription = quillEditors [ "about" ]
? quillEditors [ "about" ] . root . innerHTML
: homepageData . about . description ;
homepageData . about = {
enabled : document . getElementById ( "aboutEnabled" ) . checked ,
title : document . getElementById ( "aboutTitle" ) . value ,
description : aboutDescription ,
imageUrl : document . getElementById ( "aboutImageUrl" ) . value ,
2025-12-14 01:54:40 -06:00
} ;
2026-01-18 02:22:05 -06:00
// Update slide descriptions from Quill editors
homepageData . heroSlides . forEach ( ( slide ) => {
const editorKey = ` slide_desc_ ${ slide . id } ` ;
if ( quillEditors [ editorKey ] ) {
slide . description = quillEditors [ editorKey ] . root . innerHTML ;
}
} ) ;
// Validate slides
for ( const slide of homepageData . heroSlides ) {
if ( ! slide . title ) {
showError ( "All slides must have a title" ) ;
return ;
}
}
2025-12-14 01:54:40 -06:00
try {
const response = await fetch ( "/api/admin/homepage/settings" , {
method : "POST" ,
headers : { "Content-Type" : "application/json" } ,
credentials : "include" ,
2026-01-18 02:22:05 -06:00
body : JSON . stringify ( homepageData ) ,
2025-12-14 01:54:40 -06:00
} ) ;
const data = await response . json ( ) ;
if ( data . success ) {
showSuccess (
2025-12-24 00:13:23 -06:00
"Homepage settings saved successfully! Changes are now live on the frontend."
2025-12-14 01:54:40 -06:00
) ;
} else {
showError ( data . message || "Failed to save homepage settings" ) ;
}
} catch ( error ) {
console . error ( "Failed to save homepage:" , error ) ;
showError ( "Failed to save homepage settings" ) ;
}
}
2026-01-18 02:22:05 -06:00
// Show success notification
2025-12-14 01:54:40 -06:00
function showSuccess ( message ) {
2025-12-24 00:13:23 -06:00
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 = `
2026-01-18 02:22:05 -06:00
< i class = "bi bi-check-circle me-2" > < / i > $ { m e s s a g e }
2025-12-24 00:13:23 -06:00
< button type = "button" class = "btn-close" data - bs - dismiss = "alert" > < / b u t t o n >
` ;
document . body . appendChild ( alert ) ;
setTimeout ( ( ) => alert . remove ( ) , 5000 ) ;
2025-12-14 01:54:40 -06:00
}
2026-01-18 02:22:05 -06:00
// Show error notification
2025-12-14 01:54:40 -06:00
function showError ( message ) {
2025-12-24 00:13:23 -06:00
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 = `
2026-01-18 02:22:05 -06:00
< i class = "bi bi-exclamation-circle me-2" > < / i > $ { m e s s a g e }
2025-12-24 00:13:23 -06:00
< button type = "button" class = "btn-close" data - bs - dismiss = "alert" > < / b u t t o n >
` ;
document . body . appendChild ( alert ) ;
setTimeout ( ( ) => alert . remove ( ) , 5000 ) ;
2025-12-14 01:54:40 -06:00
}