webupdate

This commit is contained in:
Local Server
2026-01-18 02:22:05 -06:00
parent 6fc159051a
commit 2a2a3d99e5
135 changed files with 54897 additions and 9825 deletions

View File

@@ -0,0 +1,434 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Security Headers -->
<title>About - Sky Art Shop</title>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&display=swap"
rel="stylesheet"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"
/>
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
<link rel="stylesheet" href="/assets/css/main.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/navbar.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/page-overrides.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/cart-wishlist.css" />
<link rel="stylesheet" href="/assets/css/shopping.css" />
<link rel="stylesheet" href="/assets/css/responsive.css" />
</head>
<body>
<script>
window.__bodyReady = true;
</script>
<!-- Modern Navigation -->
<div class="sticky-banner-wrapper">
<nav class="modern-navbar">
<div class="navbar-wrapper">
<div class="navbar-brand">
<a href="/home" class="brand-link">
<img
src="/uploads/cat-png-1767324141436-368259437.png"
alt="Sky Art Shop Logo"
class="brand-logo"
/>
<span class="brand-name">Sky' Art Shop</span>
</a>
</div>
<div class="navbar-menu">
<ul class="nav-menu-list">
<li class="nav-item">
<a href="/home" class="nav-link">Home</a>
</li>
<li class="nav-item">
<a href="/shop" class="nav-link">Shop</a>
</li>
<li class="nav-item">
<a href="/portfolio" class="nav-link">Portfolio</a>
</li>
<li class="nav-item">
<a href="/about" class="nav-link active">About</a>
</li>
<li class="nav-item">
<a href="/blog" class="nav-link">Blog</a>
</li>
<li class="nav-item">
<a href="/contact" class="nav-link">Contact</a>
</li>
</ul>
</div>
<div class="navbar-actions">
<div class="action-item wishlist-dropdown-wrapper">
<button
class="action-btn"
id="wishlistToggle"
aria-label="Wishlist"
>
<i class="bi bi-heart"></i>
<span class="action-badge" id="wishlistCount">0</span>
</button>
<div class="action-dropdown wishlist-dropdown" id="wishlistPanel">
<div class="dropdown-head">
<h3>My Wishlist</h3>
<button class="dropdown-close" id="wishlistClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="wishlistContent">
<p class="empty-state">Your wishlist is empty</p>
</div>
<div class="dropdown-foot">
<a href="/shop" class="btn-outline">Continue Shopping</a>
</div>
</div>
</div>
<div class="action-item cart-dropdown-wrapper">
<button
class="action-btn"
id="cartToggle"
aria-label="Shopping Cart"
>
<i class="bi bi-cart3"></i>
<span class="action-badge" id="cartCount">0</span>
</button>
<div class="action-dropdown cart-dropdown" id="cartPanel">
<div class="dropdown-head">
<h3>Shopping Cart</h3>
<button class="dropdown-close" id="cartClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="cartContent">
<p class="empty-state">Your cart is empty</p>
</div>
<div class="dropdown-foot">
<a href="/shop" class="btn-outline">Continue Shopping</a>
</div>
</div>
</div>
<button
class="mobile-toggle"
id="mobileMenuToggle"
aria-label="Menu"
>
<span class="toggle-line"></span>
<span class="toggle-line"></span>
<span class="toggle-line"></span>
</button>
</div>
</div>
<div class="mobile-menu" id="mobileMenu">
<div class="mobile-menu-header">
<span class="mobile-brand">Sky' Art Shop</span>
<button class="mobile-close" id="mobileMenuClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<ul class="mobile-menu-list">
<li><a href="/home" class="mobile-link">Home</a></li>
<li><a href="/shop" class="mobile-link">Shop</a></li>
<li><a href="/portfolio" class="mobile-link">Portfolio</a></li>
<li><a href="/about" class="mobile-link">About</a></li>
<li><a href="/blog" class="mobile-link">Blog</a></li>
<li><a href="/contact" class="mobile-link">Contact</a></li>
</ul>
</div>
</nav>
</div>
<section class="about-hero">
<div class="container">
<h1>About Sky Art Shop</h1>
<p class="hero-subtitle">Your creative journey starts here</p>
</div>
</section>
<section class="about-content">
<div class="container">
<div class="about-layout">
<div class="about-main-content">
<div class="about-text" id="aboutContent">
<div style="text-align: center; padding: 40px">
<div
class="loading-spinner"
style="
border: 4px solid #f3f3f3;
border-top: 4px solid #667eea;
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
"
></div>
<p>Loading content...</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Team Members Section -->
<section class="team-section" id="teamSection" style="display: none">
<div class="container">
<div class="team-header">
<h2 class="section-title">Meet Our Team</h2>
<p class="section-subtitle">
The talented people behind Sky Art Shop
</p>
</div>
<div class="team-grid" id="teamMembersGrid">
<div style="text-align: center; padding: 40px">
<div
class="loading-spinner"
style="
border: 4px solid #f3f3f3;
border-top: 4px solid #667eea;
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
"
></div>
<p>Loading team...</p>
</div>
</div>
</div>
</section>
<footer class="footer">
<div class="container">
<div class="footer-grid">
<div class="footer-col">
<h3 class="footer-title">Sky Art Shop</h3>
<p class="footer-text">
Your destination for unique art pieces and creative supplies.
</p>
<div class="social-links">
<a href="#" class="social-link"><i class="bi bi-facebook"></i></a>
<a href="#" class="social-link"
><i class="bi bi-instagram"></i
></a>
<a href="#" class="social-link"><i class="bi bi-twitter"></i></a>
<a href="#" class="social-link"
><i class="bi bi-pinterest"></i
></a>
</div>
</div>
<div class="footer-col">
<h4 class="footer-heading">Shop</h4>
<ul class="footer-links">
<li><a href="/shop">All Products</a></li>
<li><a href="/shop?category=paintings">Paintings</a></li>
<li><a href="/shop?category=prints">Prints</a></li>
<li><a href="/shop?category=supplies">Art Supplies</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-heading">About</h4>
<ul class="footer-links">
<li><a href="/about">Our Story</a></li>
<li><a href="/portfolio">Portfolio</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-heading">Customer Service</h4>
<ul class="footer-links">
<li><a href="/shipping-info">Shipping Info</a></li>
<li><a href="/returns">Returns</a></li>
<li><a href="/faq">FAQ</a></li>
<li><a href="/privacy">Privacy Policy</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2025 Sky Art Shop. All rights reserved.</p>
</div>
</div>
</footer>
<!-- Core utilities and state management -->
<script src="/assets/js/api-cache.js"></script>
<script src="/assets/js/main.js"></script>
<!-- Shopping system (handles cart & wishlist) -->
<script src="/assets/js/shop-system.js"></script>
<!-- Page interactions -->
<script src="/assets/js/page-transitions.js?v=1766709739"></script>
<script src="/assets/js/back-button-control.js?v=1766723554"></script>
<script src="/assets/js/navigation.js"></script>
<!-- Page-specific content loading -->
<script>
// Load about page content from API
async function loadAboutContent() {
try {
const response = await fetch("/api/pages/about");
const data = await response.json();
if (data.success && data.page) {
const contentDiv = document.getElementById("aboutContent");
// Check if content is Quill Delta format (JSON)
if (data.page.content) {
try {
const delta = JSON.parse(data.page.content);
// Convert Delta to HTML
contentDiv.innerHTML = convertDeltaToHTML(delta);
} catch {
// If not JSON, treat as plain HTML
contentDiv.innerHTML = data.page.content;
}
} else {
contentDiv.innerHTML = "<p>Content not available.</p>";
}
// Update meta tags if available
if (data.page.metatitle) {
document.title = data.page.metatitle;
}
if (data.page.metadescription) {
const metaDesc = document.querySelector(
'meta[name="description"]'
);
if (metaDesc) {
metaDesc.content = data.page.metadescription;
}
}
} else {
document.getElementById("aboutContent").innerHTML =
"<p>Unable to load content.</p>";
}
} catch (error) {
console.error("Error loading about content:", error);
document.getElementById("aboutContent").innerHTML =
"<p>Error loading content.</p>";
}
}
// Convert Quill Delta to HTML
function convertDeltaToHTML(delta) {
if (!delta || !delta.ops) return "";
let html = "";
let currentBlock = "";
delta.ops.forEach((op) => {
if (typeof op.insert === "string") {
let text = op.insert;
// Apply text formatting
if (op.attributes) {
if (op.attributes.bold) text = `<strong>${text}</strong>`;
if (op.attributes.italic) text = `<em>${text}</em>`;
if (op.attributes.underline) text = `<u>${text}</u>`;
if (op.attributes.strike) text = `<s>${text}</s>`;
if (op.attributes.code) text = `<code>${text}</code>`;
if (op.attributes.link)
text = `<a href="${op.attributes.link}" target="_blank">${text}</a>`;
if (op.attributes.color)
text = `<span style="color: ${op.attributes.color}">${text}</span>`;
if (op.attributes.background)
text = `<span style="background-color: ${op.attributes.background}">${text}</span>`;
}
// Handle line breaks
const lines = text.split("\n");
lines.forEach((line, index) => {
currentBlock += line;
if (index < lines.length - 1) {
// New paragraph
if (currentBlock.trim()) {
html += `<p>${currentBlock}</p>`;
}
currentBlock = "";
}
});
}
});
// Add remaining content
if (currentBlock.trim()) {
html += `<p>${currentBlock}</p>`;
}
return html || "<p>Content not available.</p>";
}
// Load team members
async function loadTeamMembers() {
try {
const response = await fetch("/api/team-members");
const data = await response.json();
if (data.success && data.teamMembers && data.teamMembers.length > 0) {
displayTeamMembers(data.teamMembers);
document.getElementById("teamSection").style.display = "block";
}
} catch (error) {
console.error("Error loading team members:", error);
}
}
// Display team members
function displayTeamMembers(members) {
const grid = document.getElementById("teamMembersGrid");
grid.innerHTML = members
.map(
(member) => `
<div class="team-card">
<div class="team-image-wrapper">
<div class="team-image">
${
member.image_url
? `<img src="${member.image_url}" alt="${escapeHtml(
member.name
)}" />`
: `<i class="bi bi-person-circle"></i>`
}
</div>
</div>
<h3 class="team-name">${escapeHtml(member.name)}</h3>
<div class="team-position">${escapeHtml(member.position)}</div>
${
member.bio
? `<p class="team-bio">${escapeHtml(member.bio)}</p>`
: ""
}
</div>
`
)
.join("");
}
// Escape HTML to prevent XSS
function escapeHtml(text) {
if (!text) return "";
const div = document.createElement("div");
div.textContent = text;
return div.innerHTML;
}
// Load content when page loads
document.addEventListener("DOMContentLoaded", function () {
loadAboutContent();
loadTeamMembers();
});
</script>
</body>
</html>

View File

@@ -0,0 +1,329 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Security Headers -->
<title>About - Sky Art Shop</title>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&display=swap"
rel="stylesheet"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"
/>
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
<link rel="stylesheet" href="/assets/css/main.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/navbar.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/page-overrides.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/cart-wishlist.css" />
<link rel="stylesheet" href="/assets/css/shopping.css" />
<link rel="stylesheet" href="/assets/css/responsive.css" />
</head>
<body>
<script>window.__bodyReady=true</script>
<div class="sticky-banner-wrapper">
<!-- Modern Navigation -->
<nav class="modern-navbar">
<div class="navbar-wrapper">
<div class="navbar-brand">
<a href="/home" class="brand-link">
<img
src="/uploads/cat-png-1767324141436-368259437.png"
alt="Sky Art Shop Logo"
class="brand-logo"
/>
<span class="brand-name">Sky' Art Shop</span>
</a>
</div>
<div class="navbar-menu">
<ul class="nav-menu-list">
<li class="nav-item">
<a href="/home" class="nav-link">Home</a>
</li>
<li class="nav-item">
<a href="/shop" class="nav-link">Shop</a>
</li>
<li class="nav-item">
<a href="/portfolio" class="nav-link">Portfolio</a>
</li>
<li class="nav-item">
<a href="/about" class="nav-link">About</a>
</li>
<li class="nav-item">
<a href="/blog" class="nav-link active">Blog</a>
</li>
<li class="nav-item">
<a href="/contact" class="nav-link">Contact</a>
</li>
</ul>
</div>
<div class="navbar-actions">
<div class="action-item wishlist-dropdown-wrapper">
<button
class="action-btn"
id="wishlistToggle"
aria-label="Wishlist"
>
<i class="bi bi-heart"></i>
<span class="action-badge" id="wishlistCount">0</span>
</button>
<div class="action-dropdown wishlist-dropdown" id="wishlistPanel">
<div class="dropdown-head">
<h3>My Wishlist</h3>
<button class="dropdown-close" id="wishlistClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="wishlistContent">
<p class="empty-state">Your wishlist is empty</p>
</div>
<div class="dropdown-foot">
<a href="/shop" class="btn-outline">Continue Shopping</a>
</div>
</div>
</div>
<div class="action-item cart-dropdown-wrapper">
<button
class="action-btn"
id="cartToggle"
aria-label="Shopping Cart"
>
<i class="bi bi-cart3"></i>
<span class="action-badge" id="cartCount">0</span>
</button>
<div class="action-dropdown cart-dropdown" id="cartPanel">
<div class="dropdown-head">
<h3>Shopping Cart</h3>
<button class="dropdown-close" id="cartClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="cartContent">
<p class="empty-state"><i class="bi bi-cart-x"></i><br>Your cart is empty</p>
</div>
<div class="dropdown-foot">
<a href="/shop" class="btn-outline">Continue Shopping</a>
</div>
</div>
</div>
<button class="mobile-toggle" id="mobileMenuToggle" aria-label="Menu">
<span class="toggle-line"></span>
<span class="toggle-line"></span>
<span class="toggle-line"></span>
</button>
</div>
</div>
<div class="mobile-menu" id="mobileMenu">
<div class="mobile-menu-header">
<span class="mobile-brand">Sky' Art Shop</span>
<button class="mobile-close" id="mobileMenuClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<ul class="mobile-menu-list">
<li><a href="/home" class="mobile-link">Home</a></li>
<li><a href="/shop" class="mobile-link">Shop</a></li>
<li><a href="/portfolio" class="mobile-link">Portfolio</a></li>
<li><a href="/about" class="mobile-link">About</a></li>
<li><a href="/blog" class="mobile-link">Blog</a></li>
<li><a href="/contact" class="mobile-link">Contact</a></li>
</ul>
</div>
<div class="mobile-menu-overlay" id="mobileMenuOverlay"></div>
</nav>
<script>
// Mobile Menu Toggle
(function() {
const mobileToggle = document.getElementById('mobileMenuToggle');
const mobileMenu = document.getElementById('mobileMenu');
const mobileClose = document.getElementById('mobileMenuClose');
const overlay = document.getElementById('mobileMenuOverlay');
function openMenu() {
mobileMenu.classList.add('active');
overlay.classList.add('active');
document.body.style.overflow = 'hidden';
}
function closeMenu() {
mobileMenu.classList.remove('active');
overlay.classList.remove('active');
document.body.style.overflow = '';
}
if (mobileToggle) mobileToggle.addEventListener('click', openMenu);
if (mobileClose) mobileClose.addEventListener('click', closeMenu);
if (overlay) overlay.addEventListener('click', closeMenu);
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && mobileMenu.classList.contains('active')) closeMenu();
});
})();
</script>
<section class="about-hero">
<div class="container">
<h1>Blog</h1>
<p class="hero-subtitle">Inspiration, tips, and creative ideas</p>
</div>
</section>
<section class="blog-section" style="padding: 60px 0; background: #ffebeb">
<div class="container">
<div id="loadingMessage" style="text-align: center; padding: 40px">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p style="margin-top: 15px; color: #666">Loading blog posts...</p>
</div>
<div
id="blogGrid"
style="
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 30px;
"
></div>
<div
id="noPosts"
style="display: none; text-align: center; padding: 40px; color: #666"
>
<i
class="bi bi-journal-text"
style="font-size: 48px; color: #ccc; margin-bottom: 15px"
></i>
<p>No blog posts available at the moment.</p>
</div>
</div>
</section>
<footer class="footer">
<div class="container">
<div class="footer-grid">
<div class="footer-col">
<h3 class="footer-title">Sky Art Shop</h3>
<p class="footer-text">
Your destination for unique art pieces and creative supplies.
</p>
<div class="social-links">
<a href="#" class="social-link"><i class="bi bi-facebook"></i></a>
<a href="#" class="social-link"><i class="bi bi-instagram"></i></a>
<a href="#" class="social-link"><i class="bi bi-twitter"></i></a>
<a href="#" class="social-link"><i class="bi bi-pinterest"></i></a>
</div>
</div>
<div class="footer-col">
<h4 class="footer-heading">Shop</h4>
<ul class="footer-links">
<li><a href="/shop">All Products</a></li>
<li><a href="/shop?category=paintings">Paintings</a></li>
<li><a href="/shop?category=prints">Prints</a></li>
<li><a href="/shop?category=supplies">Art Supplies</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-heading">About</h4>
<ul class="footer-links">
<li><a href="/about">Our Story</a></li>
<li><a href="/portfolio">Portfolio</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-heading">Customer Service</h4>
<ul class="footer-links">
<li><a href="/shipping-info">Shipping Info</a></li>
<li><a href="/returns">Returns</a></li>
<li><a href="/faq">FAQ</a></li>
<li><a href="/privacy">Privacy Policy</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2025 Sky Art Shop. All rights reserved.</p>
</div>
</div>
</footer>
<!-- Core dependencies (load in order) -->
<script src="/assets/js/api-cache.js"></script>
<script src="/assets/js/main.js"></script>
<script src="/assets/js/shop-system.js"></script>
<!-- UI enhancements -->
<script src="/assets/js/page-transitions.js?v=1766709739"></script>
<script src="/assets/js/back-button-control.js?v=1766723554"></script>
<script src="/assets/js/navigation.js"></script>
<!-- Page-specific functionality -->
<script>
// Load blog posts from API
async function loadBlog() {
try {
const response = await window.apiCache.fetch("/api/blog/posts");
if (response.ok) {
const data = await response.json();
const posts = data.posts || [];
document.getElementById("loadingMessage").style.display = "none";
if (posts.length === 0) {
document.getElementById("noPosts").style.display = "block";
return;
}
const grid = document.getElementById("blogGrid");
grid.innerHTML = posts
.map(
(post) => `
<article class="blog-card" style="background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); transition: transform 0.3s; cursor: pointer;" onclick="window.location.href='/blog/${
post.slug
}'">
${
post.imageurl
? `
<div class="blog-image" style="position: relative; padding-top: 56.25%; overflow: hidden; background: #f5f5f5;">
<img src="${post.imageurl}"
alt="${post.title}"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;"
loading="lazy" />
</div>
`
: ""
}
<div style="padding: 25px;">
<div style="display: flex; align-items: center; gap: 15px; margin-bottom: 12px; color: #999; font-size: 13px;">
<span><i class="bi bi-calendar"></i> ${post.createdat && Object.keys(post.createdat).length > 0 ? new Date(post.createdat).toLocaleDateString() : 'Recent'}</span>
</div>
<h2 style="font-size: 22px; font-weight: 600; margin-bottom: 12px; color: #333; line-height: 1.3;">${
post.title
}</h2>
<p style="color: #666; font-size: 15px; line-height: 1.6; margin-bottom: 20px;">${
post.excerpt ||
post.content?.substring(0, 150) + "..." ||
""
}</p>
<a href="/blog/${
post.slug
}" style="display: inline-flex; align-items: center; color: #667eea; font-weight: 500; text-decoration: none; transition: gap 0.3s;" onclick="event.stopPropagation()">
Read More <i class="bi bi-arrow-right" style="margin-left: 8px;"></i>
</a>
</article>
`
)
.join("");
} else {
document.getElementById("noPosts").style.display = "block";
}
} catch (error) {
console.error("Error loading blog:", error);
document.getElementById("loadingMessage").innerHTML =
'<p style="color: #dc3545;">Error loading blog posts. Please try again later.</p>';
}
}
// Initialize
loadBlog();
</script>
</body>
</html>

View File

@@ -0,0 +1,642 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Security Headers -->
<title>Contact Us - Sky Art Shop</title>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&display=swap"
rel="stylesheet"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"
/>
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
<link rel="stylesheet" href="/assets/css/main.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/navbar.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/page-overrides.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/cart-wishlist.css" />
<link rel="stylesheet" href="/assets/css/shopping.css" />
<link rel="stylesheet" href="/assets/css/responsive.css" />
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
</head>
<body>
<script>
window.__bodyReady = true;
</script>
<!-- Modern Navigation -->
<div class="sticky-banner-wrapper">
<nav class="modern-navbar">
<div class="navbar-wrapper">
<div class="navbar-brand">
<a href="/home" class="brand-link">
<img
src="/uploads/cat-png-1767324141436-368259437.png"
alt="Sky Art Shop Logo"
class="brand-logo"
/>
<span class="brand-name">Sky' Art Shop</span>
</a>
</div>
<div class="navbar-menu">
<ul class="nav-menu-list">
<li class="nav-item">
<a href="/home" class="nav-link">Home</a>
</li>
<li class="nav-item">
<a href="/shop" class="nav-link">Shop</a>
</li>
<li class="nav-item">
<a href="/portfolio" class="nav-link">Portfolio</a>
</li>
<li class="nav-item">
<a href="/about" class="nav-link">About</a>
</li>
<li class="nav-item">
<a href="/blog" class="nav-link">Blog</a>
</li>
<li class="nav-item">
<a href="/contact" class="nav-link active">Contact</a>
</li>
</ul>
</div>
<div class="navbar-actions">
<div class="action-item wishlist-dropdown-wrapper">
<button
class="action-btn"
id="wishlistToggle"
aria-label="Wishlist"
>
<i class="bi bi-heart"></i>
<span class="action-badge" id="wishlistCount">0</span>
</button>
<div class="action-dropdown wishlist-dropdown" id="wishlistPanel">
<div class="dropdown-head">
<h3>My Wishlist</h3>
<button class="dropdown-close" id="wishlistClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="wishlistContent">
<p class="empty-state">Your wishlist is empty</p>
</div>
<div class="dropdown-foot">
<a href="/shop" class="btn-outline">Continue Shopping</a>
</div>
</div>
</div>
<div class="action-item cart-dropdown-wrapper">
<button
class="action-btn"
id="cartToggle"
aria-label="Shopping Cart"
>
<i class="bi bi-cart3"></i>
<span class="action-badge" id="cartCount">0</span>
</button>
<div class="action-dropdown cart-dropdown" id="cartPanel">
<div class="dropdown-head">
<h3>Shopping Cart</h3>
<button class="dropdown-close" id="cartClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="cartContent">
<p class="empty-state">Your cart is empty</p>
</div>
<div class="dropdown-foot">
<a href="/shop" class="btn-outline">Continue Shopping</a>
</div>
</div>
</div>
<button
class="mobile-toggle"
id="mobileMenuToggle"
aria-label="Menu"
>
<span class="toggle-line"></span>
<span class="toggle-line"></span>
<span class="toggle-line"></span>
</button>
</div>
</div>
<div class="mobile-menu" id="mobileMenu">
<div class="mobile-menu-header">
<span class="mobile-brand">Sky' Art Shop</span>
<button class="mobile-close" id="mobileMenuClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<ul class="mobile-menu-list">
<li><a href="/home" class="mobile-link">Home</a></li>
<li><a href="/shop" class="mobile-link">Shop</a></li>
<li><a href="/portfolio" class="mobile-link">Portfolio</a></li>
<li><a href="/about" class="mobile-link">About</a></li>
<li><a href="/blog" class="mobile-link">Blog</a></li>
<li><a href="/contact" class="mobile-link">Contact</a></li>
</ul>
</div>
</nav>
</div>
<!-- Contact Hero -->
<section
class="contact-hero"
style="
background: linear-gradient(135deg, #f6ccde 0%, #fcb1d8 100%);
padding: 40px 0 30px;
color: #202023;
text-align: center;
"
>
<div class="container">
<h1
style="
font-size: 2.5rem;
margin-bottom: 16px;
font-weight: 700;
color: #202023;
"
>
Get In Touch
</h1>
<p
style="
font-size: 1.1rem;
color: #202023;
opacity: 0.9;
max-width: 600px;
margin: 0 auto;
"
>
Have questions or feedback? We'd love to hear from you. Send us a
message and we'll respond as soon as possible.
</p>
</div>
</section>
<!-- Business Contact Information -->
<section
style="padding: 60px 0 40px; background: white"
id="contactInfoSection"
>
<div class="container" style="max-width: 1000px">
<div style="text-align: center; padding: 40px">
<div
class="loading-spinner"
style="
border: 4px solid #f3f3f3;
border-top: 4px solid #fcb1d8;
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
"
></div>
<p>Loading contact information...</p>
</div>
</div>
</section>
<!-- Contact Form Section -->
<section
class="contact-section"
style="padding: 80px 0; background: #f8f9fa"
>
<div class="container" style="max-width: 800px">
<div style="text-align: center; margin-bottom: 40px">
<h2
style="
font-size: 2rem;
font-weight: 700;
color: #202023;
margin-bottom: 12px;
"
>
Send Us a Message
</h2>
<p style="font-size: 1rem; color: #202023">
Fill out the form below and we'll get back to you within 24 hours
</p>
</div>
<div
class="contact-form-wrapper"
style="
background: white;
border-radius: 16px;
padding: 48px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
"
>
<form
id="contactForm"
style="display: flex; flex-direction: column; gap: 16px"
>
<!-- Name and Email Row -->
<div
style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px"
>
<!-- Name Field -->
<div class="form-group">
<label
for="name"
style="
display: block;
font-weight: 600;
margin-bottom: 8px;
color: #2d3436;
font-size: 15px;
"
>
Full Name <span style="color: #ff6b6b">*</span>
</label>
<input
type="text"
id="name"
name="name"
required
placeholder="John Doe"
style="
width: 100%;
padding: 14px 16px;
border: 2px solid #e1e8ed;
border-radius: 8px;
font-size: 15px;
transition: all 0.3s;
font-family: 'Roboto', sans-serif;
"
onfocus="this.style.borderColor='#FCB1D8'; this.style.outline='none';"
onblur="this.style.borderColor='#e1e8ed';"
/>
</div>
<!-- Email Field -->
<div class="form-group">
<label
for="email"
style="
display: block;
font-weight: 600;
margin-bottom: 8px;
color: #202023;
font-size: 15px;
"
>
Email Address <span style="color: #fcb1d8">*</span>
</label>
<input
type="email"
id="email"
name="email"
required
placeholder="john@example.com"
style="
width: 100%;
padding: 14px 16px;
border: 2px solid #e1e8ed;
border-radius: 8px;
font-size: 15px;
transition: all 0.3s;
font-family: 'Roboto', sans-serif;
"
onfocus="this.style.borderColor='#FCB1D8'; this.style.outline='none';"
onblur="this.style.borderColor='#e1e8ed';"
/>
</div>
</div>
<!-- Phone and Subject Row -->
<div
style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px"
>
<!-- Phone Field -->
<div class="form-group">
<label
for="phone"
style="
display: block;
font-weight: 600;
margin-bottom: 8px;
color: #202023;
font-size: 15px;
"
>
Phone Number
<span style="color: #202023; font-weight: 400; opacity: 0.6"
>(Optional)</span
>
</label>
<input
type="tel"
id="phone"
name="phone"
placeholder="(123) 456-7890"
style="
width: 100%;
padding: 14px 16px;
border: 2px solid #e1e8ed;
border-radius: 8px;
font-size: 15px;
transition: all 0.3s;
font-family: 'Roboto', sans-serif;
"
onfocus="this.style.borderColor='#FCB1D8'; this.style.outline='none';"
onblur="this.style.borderColor='#e1e8ed';"
/>
</div>
<!-- Subject Field -->
<div class="form-group">
<label
for="subject"
style="
display: block;
font-weight: 600;
margin-bottom: 8px;
color: #2d3436;
font-size: 15px;
"
>
Subject <span style="color: #ff6b6b">*</span>
</label>
<input
type="text"
id="subject"
name="subject"
required
placeholder="How can we help you?"
style="
width: 100%;
padding: 14px 16px;
border: 2px solid #e1e8ed;
border-radius: 8px;
font-size: 15px;
transition: all 0.3s;
font-family: 'Roboto', sans-serif;
"
onfocus="this.style.borderColor='#FCB1D8'; this.style.outline='none';"
onblur="this.style.borderColor='#e1e8ed';"
/>
</div>
</div>
<!-- Message Field -->
<div class="form-group">
<label
for="message"
style="
display: block;
font-weight: 600;
margin-bottom: 8px;
color: #202023;
font-size: 15px;
"
>
Full Name <span style="color: #fcb1d8">*</span>
</label>
<textarea
id="message"
name="message"
required
rows="6"
placeholder="Tell us more about your inquiry..."
style="
width: 100%;
padding: 14px 16px;
border: 2px solid #e1e8ed;
border-radius: 8px;
font-size: 15px;
transition: all 0.3s;
resize: vertical;
font-family: 'Roboto', sans-serif;
line-height: 1.6;
"
onfocus="this.style.borderColor='#FCB1D8'; this.style.outline='none';"
onblur="this.style.borderColor='#e1e8ed';"
></textarea>
</div>
<!-- Submit Button -->
<div style="margin-top: 8px">
<button
type="submit"
style="
width: 100%;
padding: 16px 32px;
background: linear-gradient(135deg, #f6ccde 0%, #fcb1d8 100%);
color: #202023;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
font-family: 'Roboto', sans-serif;
"
onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 8px 20px rgba(252,177,216,0.4)';"
onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='none';"
>
<i class="bi bi-send" style="margin-right: 8px"></i>
Send Message
</button>
</div>
<!-- Success/Error Message -->
<div
id="formMessage"
style="
display: none;
padding: 16px;
border-radius: 8px;
text-align: center;
font-weight: 500;
"
></div>
</form>
</div>
</div>
</section>
<footer class="footer">
<div class="container">
<div class="footer-grid">
<div class="footer-col">
<h3 class="footer-title">Sky Art Shop</h3>
<p class="footer-text">
Your destination for unique art pieces and creative supplies.
</p>
<div class="social-links">
<a href="#" class="social-link"><i class="bi bi-facebook"></i></a>
<a href="#" class="social-link"
><i class="bi bi-instagram"></i
></a>
<a href="#" class="social-link"><i class="bi bi-twitter"></i></a>
<a href="#" class="social-link"
><i class="bi bi-pinterest"></i
></a>
</div>
</div>
<div class="footer-col">
<h4 class="footer-heading">Shop</h4>
<ul class="footer-links">
<li><a href="/shop">All Products</a></li>
<li><a href="/shop?category=paintings">Paintings</a></li>
<li><a href="/shop?category=prints">Prints</a></li>
<li><a href="/shop?category=supplies">Art Supplies</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-heading">About</h4>
<ul class="footer-links">
<li><a href="/about">Our Story</a></li>
<li><a href="/portfolio">Portfolio</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-heading">Customer Service</h4>
<ul class="footer-links">
<li><a href="/shipping-info">Shipping Info</a></li>
<li><a href="/returns">Returns</a></li>
<li><a href="/faq">FAQ</a></li>
<li><a href="/privacy">Privacy Policy</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2025 Sky Art Shop. All rights reserved.</p>
</div>
</div>
</footer>
<!-- Core utilities and state management -->
<script src="/assets/js/api-cache.js"></script>
<script src="/assets/js/main.js"></script>
<!-- Shopping system (handles cart & wishlist) -->
<script src="/assets/js/shop-system.js"></script>
<!-- Page interactions -->
<script src="/assets/js/page-transitions.js?v=1766709739"></script>
<script src="/assets/js/back-button-control.js?v=1766723554"></script>
<script src="/assets/js/navigation.js"></script>
<!-- Page-specific functionality -->
<script>
// Handle contact form submission
document
.getElementById("contactForm")
.addEventListener("submit", async function (e) {
e.preventDefault();
const formMessage = document.getElementById("formMessage");
const submitButton = e.target.querySelector('button[type="submit"]');
const originalButtonText = submitButton.innerHTML;
// Disable button and show loading state
submitButton.disabled = true;
submitButton.innerHTML =
'<i class="bi bi-hourglass-split" style="margin-right: 8px;"></i>Sending...';
// Get form data
const formData = {
name: document.getElementById("name").value,
email: document.getElementById("email").value,
phone: document.getElementById("phone").value,
subject: document.getElementById("subject").value,
message: document.getElementById("message").value,
timestamp: new Date().toISOString(),
};
try {
// Simulate API call (replace with actual endpoint when ready)
await new Promise((resolve) => setTimeout(resolve, 1500));
// Show success message
formMessage.style.display = "block";
formMessage.style.background = "#d4edda";
formMessage.style.color = "#155724";
formMessage.style.border = "1px solid #c3e6cb";
formMessage.innerHTML =
'<i class="bi bi-check-circle" style="margin-right: 8px;"></i>Thank you! Your message has been sent successfully. We\'ll get back to you soon.';
// Reset form
e.target.reset();
// Log to console (for now)
console.log("Contact form submitted:", formData);
} catch (error) {
// Show error message
formMessage.style.display = "block";
formMessage.style.background = "#f8d7da";
formMessage.style.color = "#721c24";
formMessage.style.border = "1px solid #f5c6cb";
formMessage.innerHTML =
'<i class="bi bi-exclamation-circle" style="margin-right: 8px;"></i>Oops! Something went wrong. Please try again or email us directly.';
console.error("Contact form error:", error);
} finally {
// Re-enable button
submitButton.disabled = false;
submitButton.innerHTML = originalButtonText;
// Hide message after 5 seconds
setTimeout(() => {
formMessage.style.display = "none";
}, 5000);
}
});
// Load contact information from API
async function loadContactInfo() {
try {
const response = await fetch("/api/pages/contact");
const data = await response.json();
if (data.success && data.page) {
const section = document.getElementById("contactInfoSection");
section.innerHTML = `
<div class="container" style="max-width: 1000px">
${data.page.content}
</div>
`;
// Update meta tags
if (data.page.metatitle) {
document.title = data.page.metatitle;
}
if (data.page.metadescription) {
const metaDesc = document.querySelector(
'meta[name="description"]'
);
if (metaDesc) {
metaDesc.content = data.page.metadescription;
}
}
}
} catch (error) {
console.error("Error loading contact info:", error);
document.getElementById("contactInfoSection").innerHTML =
'<div class="container"><p style="text-align:center;">Error loading contact information.</p></div>';
}
}
// Load content when page loads
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", loadContactInfo);
} else {
loadContactInfo();
}
</script>
</body>
</html>

View File

@@ -0,0 +1,625 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Security Headers -->
<meta
name="description"
content="Sky Art Shop - Scrapbooking, journaling, cardmaking, and collaging stationery."
/>
<title>Home - Sky Art Shop</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&display=swap"
rel="stylesheet"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"
/>
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
<link rel="stylesheet" href="/assets/css/main.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/navbar.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/page-overrides.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/cart-wishlist.css" />
<link rel="stylesheet" href="/assets/css/shopping.css" />
<link rel="stylesheet" href="/assets/css/responsive.css" />
<style>
/* Body Reset */
body {
margin: 0;
padding: 0;
background-color: #ffebeb;
min-height: 100vh;
}
/* Sticky Banner Container */
.sticky-banner-wrapper {
position: sticky;
top: 0;
z-index: 1000;
background: #ffd0d0;
}
/* Override navbar position when inside sticky wrapper */
.sticky-banner-wrapper .modern-navbar {
position: relative;
box-shadow: none;
}
</style>
</head>
<body>
<script>window.__bodyReady=true</script>
<!-- Sticky Banner Wrapper -->
<div class="sticky-banner-wrapper">
<!-- Modern Navigation -->
<nav class="modern-navbar">
<div class="navbar-wrapper">
<div class="navbar-brand">
<a href="/home" class="brand-link">
<img
src="/uploads/cat-png-1767324141436-368259437.png"
alt="Sky Art Shop Logo"
class="brand-logo"
/>
<span class="brand-name">Sky' Art Shop</span>
</a>
</div>
<div class="navbar-menu">
<ul class="nav-menu-list">
<li class="nav-item">
<a href="/home" class="nav-link">Home</a>
</li>
<li class="nav-item">
<a href="/shop" class="nav-link">Shop</a>
</li>
<li class="nav-item">
<a href="/portfolio" class="nav-link">Portfolio</a>
</li>
<li class="nav-item">
<a href="/about" class="nav-link">About</a>
</li>
<li class="nav-item">
<a href="/blog" class="nav-link">Blog</a>
</li>
<li class="nav-item">
<a href="/contact" class="nav-link">Contact</a>
</li>
</ul>
</div>
<div class="navbar-actions">
<div class="action-item wishlist-dropdown-wrapper">
<button
class="action-btn"
id="wishlistToggle"
aria-label="Wishlist"
>
<i class="bi bi-heart"></i>
<span class="action-badge" id="wishlistCount">0</span>
</button>
<div class="action-dropdown wishlist-dropdown" id="wishlistPanel">
<div class="dropdown-head">
<h3>My Wishlist</h3>
<button class="dropdown-close" id="wishlistClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="wishlistContent">
<p class="empty-state">Your wishlist is empty</p>
</div>
<div class="dropdown-foot">
<a href="/shop" class="btn-outline">Continue Shopping</a>
</div>
</div>
</div>
<div class="action-item cart-dropdown-wrapper">
<button
class="action-btn"
id="cartToggle"
aria-label="Shopping Cart"
>
<i class="bi bi-cart3"></i>
<span class="action-badge" id="cartCount">0</span>
</button>
<div class="action-dropdown cart-dropdown" id="cartPanel">
<div class="dropdown-head">
<h3>Shopping Cart</h3>
<button class="dropdown-close" id="cartClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="cartContent">
<p class="empty-state"><i class="bi bi-cart-x"></i><br>Your cart is empty</p>
</div>
<div class="dropdown-foot">
<a href="/shop" class="btn-outline">Continue Shopping</a>
</div>
</div>
</div>
<button class="mobile-toggle" id="mobileMenuToggle" aria-label="Menu">
<span class="toggle-line"></span>
<span class="toggle-line"></span>
<span class="toggle-line"></span>
</button>
</div>
</div>
<div class="mobile-menu" id="mobileMenu">
<div class="mobile-menu-header">
<span class="mobile-brand">Sky' Art Shop</span>
<button class="mobile-close" id="mobileMenuClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<ul class="mobile-menu-list">
<li><a href="/home" class="mobile-link">Home</a></li>
<li><a href="/shop" class="mobile-link">Shop</a></li>
<li><a href="/portfolio" class="mobile-link">Portfolio</a></li>
<li><a href="/about" class="mobile-link">About</a></li>
<li><a href="/blog" class="mobile-link">Blog</a></li>
<li><a href="/contact" class="mobile-link">Contact</a></li>
</ul>
</div>
<div class="mobile-menu-overlay" id="mobileMenuOverlay"></div>
</nav>
<script>
// Mobile Menu Toggle
(function() {
const mobileToggle = document.getElementById('mobileMenuToggle');
const mobileMenu = document.getElementById('mobileMenu');
const mobileClose = document.getElementById('mobileMenuClose');
const overlay = document.getElementById('mobileMenuOverlay');
function openMenu() {
mobileMenu.classList.add('active');
overlay.classList.add('active');
document.body.style.overflow = 'hidden';
}
function closeMenu() {
mobileMenu.classList.remove('active');
overlay.classList.remove('active');
document.body.style.overflow = '';
}
if (mobileToggle) mobileToggle.addEventListener('click', openMenu);
if (mobileClose) mobileClose.addEventListener('click', closeMenu);
if (overlay) overlay.addEventListener('click', closeMenu);
// Close on ESC key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && mobileMenu.classList.contains('active')) {
closeMenu();
}
});
})();
</script>
<!-- Hero Section -->
<section class="hero" id="heroSection">
<div class="hero-content" id="heroContent">
<h2 id="heroHeadline">Welcome to Sky Art Shop</h2>
<p id="heroSubheading">
Your destination for creative stationery and supplies
</p>
<div class="hero-description" id="heroDescription">
<p>
Discover our curated collection of scrapbooking, journaling,
cardmaking, and collaging supplies. Express your creativity and
bring your artistic vision to life.
</p>
</div>
<a href="/shop" class="btn btn-primary" id="heroCtaBtn">Shop Now</a>
</div>
<div class="hero-image" id="heroImageContainer">
<img
src="/assets/images/hero-image.jpg"
alt="Sky Art Shop"
loading="lazy"
onerror="this.style.display='none'"
/>
</div>
</section>
<!-- Promotion/Inspiration Section -->
<section class="inspiration" id="promotionSection">
<div class="container">
<h2 id="promotionTitle">Get Inspired</h2>
<div class="inspiration-content" id="promotionContent">
<div class="inspiration-text" id="promotionText">
<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>
</div>
<div class="inspiration-image" id="promotionImage">
<img
src="/assets/images/inspiration.jpg"
alt="Creative Inspiration"
loading="lazy"
onerror="this.style.display='none'"
/>
</div>
</div>
<a href="/portfolio" class="btn btn-secondary">View Portfolio</a>
</div>
</section>
<!-- Featured Products / Portfolio Section -->
<section class="collection" id="portfolioSection">
<div class="container">
<h2 id="portfolioTitle">Featured Products</h2>
<p class="section-subtitle" id="portfolioDescription">
Discover our most popular items
</p>
<div class="products-grid" id="featuredProducts">
<div class="product-card">
<div class="product-image">
<img
src="/assets/images/placeholder.svg"
alt="Product"
loading="lazy"
/>
</div>
<h3>Loading products...</h3>
</div>
</div>
<div style="margin-top: 40px">
<a href="/shop" class="btn btn-secondary">View All Products</a>
</div>
</div>
</section>
<!-- Footer -->
<footer class="footer">
<div class="container">
<div class="footer-grid">
<div class="footer-col">
<h3 class="footer-title" id="footerSiteName">Sky Art Shop</h3>
<p class="footer-text">
Your destination for unique art pieces and creative supplies.
</p>
<div class="social-links">
<a href="#" class="social-link"><i class="bi bi-facebook"></i></a>
<a href="#" class="social-link"
><i class="bi bi-instagram"></i
></a>
<a href="#" class="social-link"><i class="bi bi-twitter"></i></a>
<a href="#" class="social-link"
><i class="bi bi-pinterest"></i
></a>
</div>
</div>
<div class="footer-col">
<h4 class="footer-heading">Shop</h4>
<ul class="footer-links">
<li><a href="/shop">All Products</a></li>
<li><a href="/shop?category=paintings">Paintings</a></li>
<li><a href="/shop?category=prints">Prints</a></li>
<li><a href="/shop?category=supplies">Art Supplies</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-heading">About</h4>
<ul class="footer-links">
<li><a href="/about">Our Story</a></li>
<li><a href="/portfolio">Portfolio</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-heading">Customer Service</h4>
<ul class="footer-links">
<li><a href="/shipping-info">Shipping Info</a></li>
<li><a href="/returns">Returns</a></li>
<li><a href="/faq">FAQ</a></li>
<li><a href="/privacy">Privacy Policy</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p id="footerText">&copy; 2025 Sky Art Shop. All rights reserved.</p>
</div>
</div>
</footer>
<script src="/assets/js/api-cache.js"></script>
<script src="/assets/js/main.js"></script>
<script src="/assets/js/shop-system.js"></script>
<script src="/assets/js/page-transitions.js?v=1766709739"></script>
<script src="/assets/js/back-button-control.js?v=1766723554"></script>
<script>
// Load homepage settings
async function loadHomepageSettings() {
try {
const response = await fetch("/api/homepage/settings");
if (response.ok) {
const data = await response.json();
if (data.success && data.settings) {
applyHomepageSettings(data.settings);
}
}
} catch (error) {
console.log("Using default homepage settings");
}
}
function applyHomepageSettings(settings) {
// Apply Hero Section
if (settings.hero) {
const heroSection = document.getElementById("heroSection");
const heroContent = document.getElementById("heroContent");
if (!settings.hero.enabled) {
heroSection.style.display = "none";
return;
}
if (settings.hero.headline) {
document.getElementById("heroHeadline").textContent =
settings.hero.headline;
}
if (settings.hero.subheading) {
document.getElementById("heroSubheading").textContent =
settings.hero.subheading;
}
if (settings.hero.description) {
document.getElementById("heroDescription").innerHTML =
settings.hero.description;
}
if (settings.hero.ctaText && settings.hero.ctaLink) {
const ctaBtn = document.getElementById("heroCtaBtn");
ctaBtn.textContent = settings.hero.ctaText;
ctaBtn.href = settings.hero.ctaLink;
}
if (settings.hero.backgroundUrl) {
const isVideo =
settings.hero.backgroundUrl.match(/\.(mp4|webm|ogg)$/i);
const heroImageContainer =
document.getElementById("heroImageContainer");
if (isVideo) {
heroImageContainer.innerHTML = `
<video autoplay muted loop playsinline style="width: 100%; height: 100%; object-fit: cover;">
<source src="${settings.hero.backgroundUrl}" type="video/mp4">
</video>
`;
} else {
heroImageContainer.innerHTML = `<img src="${settings.hero.backgroundUrl}" alt="Hero Background" loading="lazy" />`;
}
}
// Apply layout
if (settings.hero.layout) {
heroContent.style.textAlign = settings.hero.layout.replace(
"text-",
""
);
}
}
// Apply Promotion Section
if (settings.promotion) {
const promotionSection = document.getElementById("promotionSection");
if (!settings.promotion.enabled) {
promotionSection.style.display = "none";
} else {
if (settings.promotion.title) {
document.getElementById("promotionTitle").textContent =
settings.promotion.title;
}
if (settings.promotion.description) {
document.getElementById("promotionText").innerHTML =
settings.promotion.description;
}
if (settings.promotion.imageUrl) {
const promotionImage = document.getElementById("promotionImage");
promotionImage.innerHTML = `<img src="${
settings.promotion.imageUrl
}" alt="${
settings.promotion.title || "Promotion"
}" loading="lazy" />`;
}
// Apply text alignment
if (settings.promotion.textAlignment) {
document.getElementById("promotionText").style.textAlign =
settings.promotion.textAlignment;
}
// Apply image position (you can customize CSS classes for this)
const promotionContent =
document.getElementById("promotionContent");
if (settings.promotion.imagePosition === "right") {
promotionContent.style.flexDirection = "row-reverse";
} else if (settings.promotion.imagePosition === "center") {
promotionContent.style.flexDirection = "column";
}
}
}
// Apply Portfolio Section
if (settings.portfolio) {
const portfolioSection = document.getElementById("portfolioSection");
if (!settings.portfolio.enabled) {
portfolioSection.style.display = "none";
} else {
if (settings.portfolio.title) {
document.getElementById("portfolioTitle").textContent =
settings.portfolio.title;
}
if (settings.portfolio.description) {
const descEl = document.getElementById("portfolioDescription");
if (descEl) {
descEl.innerHTML = settings.portfolio.description;
}
}
// Portfolio count is handled by existing featured products logic
}
}
}
// Load site settings
async function loadSiteSettings() {
try {
const response = await fetch("/api/settings");
if (response.ok) {
const data = await response.json();
if (data.settings) {
document.getElementById("siteName").textContent =
data.settings.sitename || "Sky Art Shop";
document.getElementById("footerSiteName").textContent =
data.settings.sitename || "Sky Art Shop";
document.getElementById("footerText").textContent =
data.settings.footertext ||
"© 2025 by Sky Art Shop. All rights reserved.";
}
}
} catch (error) {
console.log("Using default site settings");
}
}
// Load featured products
async function loadFeaturedProducts() {
try {
const response = await window.apiCache.fetch("/api/products/featured?limit=4");
if (response.ok) {
const data = await response.json();
if (data.products && data.products.length > 0) {
const container = document.getElementById("featuredProducts");
container.innerHTML = data.products
.map((product) => {
// Get product image (primary or first from images array)
let productImage = "/assets/images/placeholder.svg";
if (
product.images &&
Array.isArray(product.images) &&
product.images.length > 0
) {
const primaryImg = product.images.find(
(img) => img.is_primary
);
productImage = primaryImg
? primaryImg.image_url
: product.images[0].image_url;
} else if (product.imageurl) {
productImage = product.imageurl;
}
return `
<div class="product-card">
<a href="/product?id=${
product.id
}" class="product-link">
<div class="product-image">
<img src="${productImage}" alt="${
product.name
}" loading="lazy" onerror="this.src='/assets/images/placeholder.svg'" />
</div>
</a>
<div class="product-info">
<a href="/product?id=${
product.id
}" class="product-title-link">
<h3>${product.name}</h3>
</a>
${
product.shortdescription ||
product.description
? `<div class="product-description">${
product.shortdescription ||
(product.description
? product.description.substring(
0,
100
) + "..."
: "")
}</div>`
: ""
}
<p class="price">$${parseFloat(
product.price
).toFixed(2)}</p>
</div>
<div class="product-actions">
<button class="btn btn-small btn-icon" onclick="addToWishlist('${
product.id
}', '${product.name}', ${
product.price
}, '${productImage}')" aria-label="Add to wishlist">
<i class="bi bi-heart"></i>
</button>
<button class="btn btn-small btn-icon" onclick="addToCart('${
product.id
}', '${product.name}', ${
product.price
}, '${productImage}')" aria-label="Add to cart">
<i class="bi bi-cart-plus"></i>
</button>
</div>
</div>
`;
})
.join("");
}
}
} catch (error) {
console.log("Could not load featured products");
}
}
// Cart and Wishlist Functions
function addToCart(productId, name, price, imageurl) {
window.ShopSystem.addToCart(
{
id: String(productId),
name,
price: parseFloat(price),
imageurl,
},
1
);
}
function addToWishlist(productId, name, price, imageurl) {
window.ShopSystem.addToWishlist({
id: String(productId),
name,
price: parseFloat(price),
imageurl,
});
}
// Initialize
loadSiteSettings();
loadHomepageSettings();
loadFeaturedProducts();
</script>
</body>
</html>

View File

@@ -0,0 +1,482 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Security Headers -->
<title>About - Sky Art Shop</title>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&display=swap"
rel="stylesheet"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"
/>
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
<link rel="stylesheet" href="/assets/css/main.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/navbar.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/page-overrides.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/cart-wishlist.css" />
<link rel="stylesheet" href="/assets/css/shopping.css" />
<link rel="stylesheet" href="/assets/css/responsive.css" />
</head>
<body>
<script>window.__bodyReady=true</script>
<div class="sticky-banner-wrapper">
<!-- Modern Navigation -->
<nav class="modern-navbar">
<div class="navbar-wrapper">
<div class="navbar-brand">
<a href="/home" class="brand-link">
<img
src="/uploads/cat-png-1767324141436-368259437.png"
alt="Sky Art Shop Logo"
class="brand-logo"
/>
<span class="brand-name">Sky' Art Shop</span>
</a>
</div>
<div class="navbar-menu">
<ul class="nav-menu-list">
<li class="nav-item">
<a href="/home" class="nav-link">Home</a>
</li>
<li class="nav-item">
<a href="/shop" class="nav-link">Shop</a>
</li>
<li class="nav-item">
<a href="/portfolio" class="nav-link active">Portfolio</a>
</li>
<li class="nav-item">
<a href="/about" class="nav-link">About</a>
</li>
<li class="nav-item">
<a href="/blog" class="nav-link">Blog</a>
</li>
<li class="nav-item">
<a href="/contact" class="nav-link">Contact</a>
</li>
</ul>
</div>
<div class="navbar-actions">
<div class="action-item wishlist-dropdown-wrapper">
<button
class="action-btn"
id="wishlistToggle"
aria-label="Wishlist"
>
<i class="bi bi-heart"></i>
<span class="action-badge" id="wishlistCount">0</span>
</button>
<div class="action-dropdown wishlist-dropdown" id="wishlistPanel">
<div class="dropdown-head">
<h3>My Wishlist</h3>
<button class="dropdown-close" id="wishlistClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="wishlistContent">
<p class="empty-state">Your wishlist is empty</p>
</div>
<div class="dropdown-foot">
<a href="/shop" class="btn-outline">Continue Shopping</a>
</div>
</div>
</div>
<div class="action-item cart-dropdown-wrapper">
<button
class="action-btn"
id="cartToggle"
aria-label="Shopping Cart"
>
<i class="bi bi-cart3"></i>
<span class="action-badge" id="cartCount">0</span>
</button>
<div class="action-dropdown cart-dropdown" id="cartPanel">
<div class="dropdown-head">
<h3>Shopping Cart</h3>
<button class="dropdown-close" id="cartClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="cartContent">
<p class="empty-state"><i class="bi bi-cart-x"></i><br>Your cart is empty</p>
</div>
<div class="dropdown-foot">
<a href="/shop" class="btn-outline">Continue Shopping</a>
</div>
</div>
</div>
<button class="mobile-toggle" id="mobileMenuToggle" aria-label="Menu">
<span class="toggle-line"></span>
<span class="toggle-line"></span>
<span class="toggle-line"></span>
</button>
</div>
</div>
<div class="mobile-menu" id="mobileMenu">
<div class="mobile-menu-header">
<span class="mobile-brand">Sky' Art Shop</span>
<button class="mobile-close" id="mobileMenuClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<ul class="mobile-menu-list">
<li><a href="/home" class="mobile-link">Home</a></li>
<li><a href="/shop" class="mobile-link">Shop</a></li>
<li><a href="/portfolio" class="mobile-link">Portfolio</a></li>
<li><a href="/about" class="mobile-link">About</a></li>
<li><a href="/blog" class="mobile-link">Blog</a></li>
<li><a href="/contact" class="mobile-link">Contact</a></li>
</ul>
</div>
<div class="mobile-menu-overlay" id="mobileMenuOverlay"></div>
</nav>
<script>
// Mobile Menu Toggle
(function() {
const mobileToggle = document.getElementById('mobileMenuToggle');
const mobileMenu = document.getElementById('mobileMenu');
const mobileClose = document.getElementById('mobileMenuClose');
const overlay = document.getElementById('mobileMenuOverlay');
function openMenu() {
mobileMenu.classList.add('active');
overlay.classList.add('active');
document.body.style.overflow = 'hidden';
}
function closeMenu() {
mobileMenu.classList.remove('active');
overlay.classList.remove('active');
document.body.style.overflow = '';
}
if (mobileToggle) mobileToggle.addEventListener('click', openMenu);
if (mobileClose) mobileClose.addEventListener('click', closeMenu);
if (overlay) overlay.addEventListener('click', closeMenu);
// Close on ESC key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && mobileMenu.classList.contains('active')) {
closeMenu();
}
});
})();
</script>
<section class="about-hero">
<div class="container">
<h1>Portfolio</h1>
<p class="hero-subtitle">Explore our creative projects and artwork</p>
</section>
<section
class="portfolio-section"
style="padding: 60px 0; background: #ffebeb"
>
<div class="container">
<div id="loadingMessage" style="text-align: center; padding: 40px">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p style="margin-top: 15px; color: #666">
Loading portfolio projects...
</p>
</div>
<div
id="portfolioGrid"
class="products-grid"
style="
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 30px;
"
></div>
<div
id="noProjects"
style="display: none; text-align: center; padding: 40px; color: #666"
>
<i
class="bi bi-images"
style="font-size: 48px; color: #ccc; margin-bottom: 15px"
></i>
<p>No portfolio projects available at the moment.</p>
</div>
</div>
</section>
<footer class="footer">
<div class="container">
<div class="footer-grid">
<div class="footer-col">
<h3 class="footer-title">Sky Art Shop</h3>
<p class="footer-text">
Your destination for unique art pieces and creative supplies.
</p>
<div class="social-links">
<a href="#" class="social-link"><i class="bi bi-facebook"></i></a>
<a href="#" class="social-link"><i class="bi bi-instagram"></i></a>
<a href="#" class="social-link"><i class="bi bi-twitter"></i></a>
<a href="#" class="social-link"><i class="bi bi-pinterest"></i></a>
</div>
</div>
<div class="footer-col">
<h4 class="footer-heading">Shop</h4>
<ul class="footer-links">
<li><a href="/shop">All Products</a></li>
<li><a href="/shop?category=paintings">Paintings</a></li>
<li><a href="/shop?category=prints">Prints</a></li>
<li><a href="/shop?category=supplies">Art Supplies</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-heading">About</h4>
<ul class="footer-links">
<li><a href="/about">Our Story</a></li>
<li><a href="/portfolio">Portfolio</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-heading">Customer Service</h4>
<ul class="footer-links">
<li><a href="/shipping-info">Shipping Info</a></li>
<li><a href="/returns">Returns</a></li>
<li><a href="/faq">FAQ</a></li>
<li><a href="/privacy">Privacy Policy</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2025 Sky Art Shop. All rights reserved.</p>
</div>
</div>
</footer>
<!-- Project Modal -->
<div
id="projectModal"
style="
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.85);
z-index: 9999;
overflow-y: auto;
overflow-x: hidden;
padding: 40px 0;
"
onclick="if(event.target.id === 'projectModal') closeProjectModal();"
>
<div
style="
position: relative;
margin: auto;
width: 90%;
max-width: 900px;
background: white;
border-radius: 20px;
overflow: hidden;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
"
onclick="event.stopPropagation();"
>
<button
onclick="closeProjectModal()"
style="
position: absolute;
top: 20px;
right: 20px;
background: white;
border: none;
width: 44px;
height: 44px;
border-radius: 50%;
cursor: pointer;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
transition: all 0.2s;
"
onmouseover="this.style.transform='scale(1.1)'; this.style.background='#f8f9fa';"
onmouseout="this.style.transform='scale(1)'; this.style.background='white';"
>
<i class="bi bi-x-lg"></i>
</button>
<div
id="modalContent"
></div>
</div>
</div>
<!-- Core dependencies (load in order) -->
<script src="/assets/js/api-cache.js"></script>
<script src="/assets/js/main.js"></script>
<script src="/assets/js/shop-system.js"></script>
<!-- UI enhancements -->
<script src="/assets/js/page-transitions.js?v=1766709739"></script>
<script src="/assets/js/back-button-control.js?v=1766723554"></script>
<script src="/assets/js/navigation.js"></script>
<!-- Page-specific functionality -->
<script>
let portfolioProjects = [];
// Open project modal
function openProjectModal(projectId) {
const project = portfolioProjects.find((p) => p.id === projectId);
if (!project) {
console.error('[Portfolio] Project not found:', projectId);
return;
}
if (!project.title) {
console.error('[Portfolio] Invalid project data - missing title:', project);
return;
}
const modal = document.getElementById("projectModal");
const modalContent = document.getElementById("modalContent");
if (!modal || !modalContent) {
console.error('[Portfolio] Modal elements not found');
return;
}
// Build category badge HTML
const categoryBadge = project.category
? `<span style="display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 8px 18px; border-radius: 24px; font-size: 13px; font-weight: 600; margin-bottom: 24px; letter-spacing: 0.5px; text-transform: uppercase;">${project.category}</span>`
: '';
// Build modal content
modalContent.innerHTML = `
<div class="project-image" style="width: 100%; height: 450px; overflow: hidden; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); flex-shrink: 0;">
<img src="${project.featuredimage || project.imageurl || '/assets/images/placeholder.svg'}"
alt="${project.title}"
onerror="this.src='/assets/images/placeholder.svg'"
style="width: 100%; height: 100%; object-fit: cover;" />
</div>
<div style="padding: 40px; background: white;">
${categoryBadge}
<h2 style="font-size: 36px; font-weight: 700; margin: 0 0 24px 0; color: #1a1a1a; line-height: 1.2;">${project.title}</h2>
<div style="color: #555; font-size: 17px; line-height: 1.9; margin-bottom: 32px; font-weight: 400;">
${project.description || 'No description available.'}
</div>
</div>
`;
modal.style.display = "block";
document.body.style.overflow = "hidden";
document.documentElement.style.overflow = "hidden";
}
// Close project modal
function closeProjectModal() {
document.getElementById("projectModal").style.display = "none";
document.body.style.overflow = "auto";
document.documentElement.style.overflow = "auto";
}
// Close modal on outside click
document.addEventListener("click", (e) => {
const modal = document.getElementById("projectModal");
if (e.target === modal) {
closeProjectModal();
}
});
// Close modal on Escape key
document.addEventListener("keydown", (e) => {
if (e.key === "Escape") {
closeProjectModal();
}
});
// Load portfolio projects from API
async function loadPortfolio() {
try {
const response = await window.apiCache.fetch("/api/portfolio/projects");
if (response.ok) {
const data = await response.json();
portfolioProjects = data.projects || [];
document.getElementById("loadingMessage").style.display = "none";
if (portfolioProjects.length === 0) {
document.getElementById("noProjects").style.display = "block";
return;
}
// Validate and filter projects
const validProjects = portfolioProjects.filter(project => {
if (!project || !project.id || !project.title) {
console.warn('[Portfolio] Skipping invalid project:', project);
return false;
}
return true;
});
if (validProjects.length === 0) {
document.getElementById("noProjects").style.display = "block";
return;
}
const grid = document.getElementById("portfolioGrid");
grid.innerHTML = validProjects
.map(
(project) => `
<div class="product-card" onclick="openProjectModal('${
project.id
}')" style="background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); transition: all 0.3s; cursor: pointer;">
<div class="product-image" style="position: relative; padding-top: 100%; overflow: hidden; background: #f5f5f5;">
<img src="${
project.featuredimage || project.imageurl || "/assets/images/placeholder.svg"
}"
alt="${project.title}"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; transition: transform 0.3s;"
loading="lazy"
onerror="this.src='/assets/images/placeholder.svg'"
onmouseover="this.style.transform='scale(1.05)'"
onmouseout="this.style.transform='scale(1)'" />
${
project.category
? `<span style="position: absolute; top: 10px; right: 10px; background: rgba(102, 126, 234, 0.9); color: white; padding: 4px 12px; border-radius: 20px; font-size: 12px; font-weight: 500;">${project.category}</span>`
: ""
}
</div>
<div style="padding: 20px; text-align: center;">
<h3 style="font-size: 18px; font-weight: 600; margin: 0; color: #333;">${
project.title
}</h3>
${
project.description && project.description.replace(/<[^>]*>/g, '').trim()
? `<p style="font-size: 14px; color: #666; margin: 8px 0 0 0; line-height: 1.5;">${project.description.replace(/<[^>]*>/g, '').substring(0, 80)}${project.description.length > 80 ? '...' : ''}</p>`
: ""
}
</div>
</div>
`
)
.join("");
} else {
document.getElementById("noProjects").style.display = "block";
}
} catch (error) {
console.error("Error loading portfolio:", error);
document.getElementById("loadingMessage").innerHTML =
'<p style="color: #dc3545;">Error loading portfolio projects. Please try again later.</p>';
}
}
// Initialize
loadPortfolio();
</script>
</body>
</html>

View File

@@ -0,0 +1,853 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Security Headers -->
<title>Product Details - Sky Art Shop</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&display=swap"
rel="stylesheet"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"
/>
<link rel="stylesheet" href="/assets/css/main.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/navbar.css?v=1768450104" />
<link rel="stylesheet" href="/assets/css/cart-wishlist.css" />
<link rel="stylesheet" href="/assets/css/shopping.css" />
<link rel="stylesheet" href="/assets/css/responsive.css" />
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
</head>
<body>
<!-- Modern Navigation -->
<nav class="modern-navbar">
<div class="navbar-wrapper">
<div class="navbar-brand">
<a href="/home" class="brand-link">
<img
src="/uploads/cat-png-1767324141436-368259437.png"
alt="Sky Art Shop Logo"
class="brand-logo"
/>
<span class="brand-name">Sky' Art Shop</span>
</a>
</div>
<div class="navbar-menu">
<ul class="nav-menu-list">
<li class="nav-item">
<a href="/home" class="nav-link">Home</a>
</li>
<li class="nav-item">
<a href="/shop" class="nav-link">Shop</a>
</li>
<li class="nav-item">
<a href="/portfolio" class="nav-link">Portfolio</a>
</li>
<li class="nav-item">
<a href="/about" class="nav-link">About</a>
</li>
<li class="nav-item">
<a href="/blog" class="nav-link">Blog</a>
</li>
<li class="nav-item">
<a href="/contact" class="nav-link">Contact</a>
</li>
</ul>
</div>
<div class="navbar-actions">
<div class="action-item wishlist-dropdown-wrapper">
<button
class="action-btn"
id="wishlistToggle"
aria-label="Wishlist"
>
<i class="bi bi-heart"></i>
<span class="action-badge" id="wishlistCount">0</span>
</button>
<div class="action-dropdown wishlist-dropdown" id="wishlistPanel">
<div class="dropdown-head">
<h3>My Wishlist</h3>
<button class="dropdown-close" id="wishlistClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="wishlistContent">
<p class="empty-state">Your wishlist is empty</p>
</div>
<div class="dropdown-foot">
<a href="/shop" class="btn-outline">Continue Shopping</a>
</div>
</div>
</div>
<div class="action-item cart-dropdown-wrapper">
<button
class="action-btn"
id="cartToggle"
aria-label="Shopping Cart"
>
<i class="bi bi-cart3"></i>
<span class="action-badge" id="cartCount">0</span>
</button>
<div class="action-dropdown cart-dropdown" id="cartPanel">
<div class="dropdown-head">
<h3>Shopping Cart</h3>
<button class="dropdown-close" id="cartClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="dropdown-body" id="cartContent">
<p class="empty-state">Your cart is empty</p>
</div>
<div class="dropdown-foot">
<a href="/shop" class="btn-outline">Continue Shopping</a>
</div>
</div>
</div>
<button class="mobile-toggle" id="mobileMenuToggle" aria-label="Menu">
<span class="toggle-line"></span>
<span class="toggle-line"></span>
<span class="toggle-line"></span>
</button>
</div>
</div>
<div class="mobile-menu" id="mobileMenu">
<div class="mobile-menu-header">
<span class="mobile-brand">Sky' Art Shop</span>
<button class="mobile-close" id="mobileMenuClose">
<i class="bi bi-x-lg"></i>
</button>
</div>
<ul class="mobile-menu-list">
<li><a href="/home" class="mobile-link">Home</a></li>
<li><a href="/shop" class="mobile-link">Shop</a></li>
<li><a href="/portfolio" class="mobile-link">Portfolio</a></li>
<li><a href="/about" class="mobile-link">About</a></li>
<li><a href="/blog" class="mobile-link">Blog</a></li>
<li><a href="/contact" class="mobile-link">Contact</a></li>
</ul>
</div>
</nav>
<div
id="loading"
style="
text-align: center;
padding: 100px 20px;
font-size: 18px;
color: #202023;
background: #ffebeb;
"
>
<i
class="bi bi-hourglass-split"
style="font-size: 48px; display: block; margin-bottom: 20px"
></i>
Loading product...
</div>
<div id="productDetail" style="display: none"></div>
<!-- Core Scripts (load in dependency order) -->
<script src="/assets/js/api-cache.js"></script>
<script src="/assets/js/main.js"></script>
<script src="/assets/js/shop-system.js"></script>
<script src="/assets/js/api-client.js"></script>
<script src="/assets/js/notifications.js"></script>
<script src="/assets/js/page-transitions.js?v=1766709739"></script>
<script src="/assets/js/back-button-control.js?v=1766723554"></script>
<script src="/assets/js/navigation.js?v=1766708114"></script>
<script>
// Function to change primary image
function changePrimaryImage(imageUrl, index) {
const primaryImg = document.getElementById("primaryImage");
if (primaryImg) {
primaryImg.src = imageUrl;
}
// Update thumbnail borders
const thumbnails = document.querySelectorAll(".thumbnail-item");
thumbnails.forEach((thumb, idx) => {
if (idx === index) {
thumb.style.border = "2px solid #6b46c1";
} else {
thumb.style.border = "1px solid #e5e7eb";
}
});
// Update color variant borders
const variants = document.querySelectorAll(".color-variant-circle");
variants.forEach((variant) => {
const onclick = variant.getAttribute("onclick");
if (onclick && onclick.includes(imageUrl)) {
variant.style.border = "3px solid #6b46c1";
} else {
variant.style.border = "3px solid #e5e7eb";
}
});
}
async function loadProduct() {
const params = new URLSearchParams(window.location.search);
const productId = params.get("id");
console.log("Product page loaded. URL:", window.location.href);
console.log("Product ID from URL:", productId);
if (!productId) {
console.error("No product ID in URL");
document.getElementById("loading").innerHTML =
'<p style="text-align: center; padding: 40px; color: #ef4444; font-size: 18px;">Product not found - No product ID in URL</p><div style="text-align: center;"><a href="/shop" style="color: #FCB1D8; text-decoration: none; font-weight: 600;">← Back to Shop</a></div>';
return;
}
try {
console.log(
"Fetching product from API:",
`/api/products/${productId}`
);
const response = await window.apiCache.fetch(
`/api/products/${productId}`
);
const data = await response.json();
console.log("API response:", data);
if (!data.success || !data.product) {
throw new Error("Product not found");
}
const product = data.product;
document.title = `${product.name} - Sky Art Shop`;
// Get primary image or first image from images array
let primaryImage = "/assets/images/placeholder.svg";
let imageGallery = [];
if (
product.images &&
Array.isArray(product.images) &&
product.images.length > 0
) {
// Find primary image
const primary = product.images.find((img) => img.is_primary);
if (primary) {
primaryImage = primary.image_url;
} else {
primaryImage = product.images[0].image_url;
}
imageGallery = product.images;
}
// Build image gallery HTML
let galleryHTML = "";
if (imageGallery.length > 0) {
galleryHTML = `
<div style="display: flex; gap: 12px; margin-top: 16px; overflow-x: auto; padding: 8px 0;">
${imageGallery
.map(
(img, idx) => `
<img src="${img.image_url}"
alt="${img.alt_text || product.name}"
onclick="changePrimaryImage('${img.image_url}')"
style="width: 80px; height: 80px; object-fit: cover; border-radius: 8px; cursor: pointer; border: ${
img.image_url === primaryImage
? "3px solid #6b46c1"
: "1px solid #e5e7eb"
};"
onerror="this.src='/assets/images/placeholder.svg'" />
`
)
.join("")}
</div>
`;
}
// Build product details HTML
let detailsHTML = "";
if (
product.sku ||
product.weight ||
product.dimensions ||
product.material
) {
detailsHTML = `
<div style="margin-bottom: 24px; padding: 20px; background: #FFD0D0; border-radius: 8px; border: 1px solid #FCB1D8;">
<h3 style="font-size: 16px; font-weight: 600; color: #202023; margin-bottom: 16px;">Product Details</h3>
${
product.sku
? `
<p style="margin-bottom: 8px; color: #202023; opacity: 0.8;">
<span style="font-weight: 500;">SKU:</span> ${product.sku}
</p>
`
: ""
}
${
product.weight
? `
<p style="margin-bottom: 8px; color: #202023; opacity: 0.8;">
<span style="font-weight: 500;">Weight:</span> ${product.weight}
</p>
`
: ""
}
${
product.dimensions
? `
<p style="margin-bottom: 8px; color: #202023; opacity: 0.8;">
<span style="font-weight: 500;">Dimensions:</span> ${product.dimensions}
</p>
`
: ""
}
${
product.material
? `
<p style="margin-bottom: 8px; color: #6b7280;">
<span style="font-weight: 500;">Material:</span> ${product.material}
</p>
`
: ""
}
</div>
`;
}
// Build badges HTML
let badgesHTML = "";
if (product.isfeatured || product.isbestseller) {
badgesHTML = `
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
${
product.isfeatured
? `
<span style="display: inline-block; padding: 6px 12px; background: #FCB1D8; color: #202023; border-radius: 6px; font-size: 12px; font-weight: 600; box-shadow: 0 2px 4px rgba(252, 177, 216, 0.4);">
<i class="bi bi-star-fill"></i> Featured
</span>
`
: ""
}
${
product.isbestseller
? `
<span style="display: inline-block; padding: 6px 12px; background: #F6CCDE; color: #202023; border-radius: 6px; font-size: 12px; font-weight: 600; box-shadow: 0 2px 4px rgba(252, 177, 216, 0.4);">
<i class="bi bi-trophy-fill"></i> Best Seller
</span>
`
: ""
}
</div>
`;
}
document.getElementById("productDetail").innerHTML = `
<div style="font-family: 'Roboto', sans-serif;">
<nav style="background: #F6CCDE; padding: 16px 24px; box-shadow: 0 1px 3px rgba(252, 177, 216, 0.3);">
<div style="max-width: 1400px; margin: 0 auto; display: flex; align-items: center; gap: 20px;">
<a href="/home" style="font-size: 20px; font-weight: 600; color: #202023; text-decoration: none;">Sky Art Shop</a>
<span style="color: #202023; opacity: 0.5;">/</span>
<a href="/shop" style="color: #202023; opacity: 0.8; text-decoration: none; transition: opacity 0.3s;" onmouseover="this.style.opacity='1'" onmouseout="this.style.opacity='0.8'">Shop</a>
<span style="color: #202023; opacity: 0.5;">/</span>
<span style="color: #202023; opacity: 0.7;">${
product.name
}</span>
</div>
</nav>
<div style="max-width: 1400px; margin: 40px auto; padding: 0 24px; background: #FFEBEB; border-radius: 12px; padding: 40px 24px;">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 60px;">
<!-- LEFT COLUMN: Image & Description -->
<div>
<!-- Back to Shop Link -->
<a href="/shop" style="display: inline-flex; align-items: center; gap: 8px; margin-bottom: 20px; color: #FCB1D8; text-decoration: none; font-weight: 600; font-size: 15px; transition: all 0.3s;"
onmouseover="this.style.gap='12px'; this.style.color='#d896c0'"
onmouseout="this.style.gap='8px'; this.style.color='#FCB1D8'">
<i class="bi bi-arrow-left"></i> Back to Shop
</a>
<!-- Image Section with Thumbnails -->
<div style="display: flex; gap: 16px;">
<!-- Thumbnail Gallery (Vertical Left) -->
${
imageGallery.length > 1
? `
<div id="thumbnailGallery" style="display: flex; flex-direction: column; gap: 12px; max-height: 600px; overflow-y: auto;">
${imageGallery
.map(
(img, idx) => `
<div onclick="changePrimaryImage('${
img.image_url
}', ${idx})"
class="thumbnail-item"
data-index="${idx}"
style="width: 70px; height: 70px; border-radius: 4px; overflow: hidden; cursor: pointer; border: ${
img.image_url === primaryImage
? "2px solid #6b46c1"
: "1px solid #e5e7eb"
}; transition: all 0.3s; flex-shrink: 0;">
<img src="${img.image_url}"
alt="${img.alt_text || product.name}"
style="width: 100%; height: 100%; object-fit: cover;"
onerror="this.src='/assets/images/placeholder.svg'" />
</div>
`
)
.join("")}
</div>
`
: ""
}
<!-- Main Product Image -->
<div style="flex: 1; background: white; border-radius: 12px; box-shadow: 0 2px 8px rgba(252, 177, 216, 0.2); border: 1px solid #FFD0D0; padding: 20px; display: flex; align-items: center; justify-content: center; min-height: 500px; max-height: 600px;">
<img id="primaryImage"
src="${primaryImage}"
alt="${product.name}"
style="max-width: 100%; max-height: 560px; width: auto; height: auto; object-fit: contain; display: block;"
onerror="this.src='/assets/images/placeholder.svg'" />
</div>
</div>
<!-- Color Variants Section -->
${
imageGallery.some(
(img) => img.color_variant && img.color_code
)
? `
<div style="margin-top: 24px; padding: 20px; background: #FFD0D0; border-radius: 12px;">
<h4 style="font-size: 14px; font-weight: 600; color: #1a1a1a; margin-bottom: 12px; display: flex; align-items: center; gap: 8px;">
<i class="bi bi-palette"></i>
Available Colors (${
imageGallery.filter((img) => img.color_variant).length
})
</h4>
<div style="display: flex; gap: 12px; flex-wrap: wrap;">
${imageGallery
.filter((img) => img.color_variant && img.color_code)
.map(
(img, idx) => `
<div onclick="changePrimaryImage('${
img.image_url
}', ${imageGallery.indexOf(img)})"
class="color-variant-circle"
title="${img.color_variant}"
style="position: relative; width: 48px; height: 48px; border-radius: 50%; cursor: pointer; border: 3px solid ${
img.image_url === primaryImage
? "#FCB1D8"
: "#FFEBEB"
}; transition: all 0.3s; overflow: hidden; box-shadow: 0 2px 4px rgba(252, 177, 216, 0.3);"
onmouseover="this.querySelector('.color-name-tooltip').style.opacity='1'; this.querySelector('.color-name-tooltip').style.transform='translateY(0)'; this.style.transform='scale(1.15)'"
onmouseout="this.querySelector('.color-name-tooltip').style.opacity='0'; this.querySelector('.color-name-tooltip').style.transform='translateY(-5px)'; this.style.transform='scale(1)'">
<div style="width: 100%; height: 100%; background: ${
img.color_code
};"></div>
<div class="color-name-tooltip" style="position: absolute; bottom: -35px; left: 50%; transform: translateX(-50%) translateY(-5px); background: rgba(0,0,0,0.9); color: white; padding: 6px 12px; border-radius: 6px; font-size: 12px; white-space: nowrap; pointer-events: none; opacity: 0; transition: all 0.3s; z-index: 10;">
${img.color_variant}
</div>
</div>
`
)
.join("")}
</div>
</div>
`
: ""
}
<!-- Description Box -->
${
product.description
? `
<div style="margin-top: 24px; padding: 20px; background: white; border-radius: 12px; box-shadow: 0 2px 8px rgba(252, 177, 216, 0.2); border: 1px solid #FFD0D0;">
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 12px; padding-bottom: 12px; border-bottom: 2px solid #FCB1D8;">
<i class="bi bi-pin-angle-fill" style="color: #FCB1D8; font-size: 18px;"></i>
<h3 style="font-size: 16px; font-weight: 600; color: #202023; margin: 0;">Description</h3>
</div>
<div style="max-height: 200px; overflow-y: auto; color: #4b5563; line-height: 1.7; font-size: 15px; padding-right: 8px;">
${product.description}
</div>
</div>
`
: ""
}
</div>
<!-- RIGHT COLUMN: Product Info & Actions -->
<div style="padding: 20px 0;">
${badgesHTML}
<h1 style="font-size: 36px; font-weight: 700; color: #1a1a1a; margin: 0 0 16px 0; line-height: 1.2;">${
product.name
}</h1>
<div style="display: flex; align-items: baseline; gap: 16px; margin-bottom: 24px;">
<p style="font-size: 36px; font-weight: 700; color: #FCB1D8; margin: 0;">$${parseFloat(
product.price
).toFixed(2)}</p>
${
product.stockquantity > 0
? `<span style="color: #10b981; font-weight: 500; display: flex; align-items: center; gap: 6px;"><i class="bi bi-check-circle-fill"></i> In Stock (${product.stockquantity} available)</span>`
: `<span style="color: #ef4444; font-weight: 500; display: flex; align-items: center; gap: 6px;"><i class="bi bi-x-circle-fill"></i> Out of Stock</span>`
}
</div>
${
product.shortdescription
? `
<p style="font-size: 18px; color: #4b5563; line-height: 1.6; margin-bottom: 24px;">${product.shortdescription}</p>
`
: ""
}
${
product.category
? `
<p style="margin-bottom: 24px;">
<span style="font-weight: 500; color: #6b7280;">Category:</span>
<span style="display: inline-block; margin-left: 8px; padding: 6px 14px; background: #FFD0D0; border-radius: 6px; font-size: 14px; color: #202023;">
<i class="bi bi-tag"></i> ${product.category}
</span>
</p>
`
: ""
}
<!-- Product Details (Moved from description area) -->
${detailsHTML}
<!-- Add to Cart & Wishlist Buttons -->
<div style="display: flex; gap: 12px; margin-top: 32px; margin-bottom: 24px;">
<button onclick="addToCart()"
${product.stockquantity <= 0 ? "disabled" : ""}
style="padding: 14px 24px; background: ${
product.stockquantity <= 0 ? "#9ca3af" : "#FCB1D8"
}; color: #202023; border: none; border-radius: 10px; font-size: 15px; font-weight: 600; cursor: ${
product.stockquantity <= 0 ? "not-allowed" : "pointer"
}; transition: all 0.3s; display: flex; align-items: center; justify-content: center; gap: 8px; box-shadow: 0 4px 12px rgba(252, 177, 216, 0.3);"
onmouseover="if(${
product.stockquantity > 0
}) this.style.transform='translateY(-2px)'; this.style.background='#F6CCDE'; this.style.boxShadow='0 6px 16px rgba(252, 177, 216, 0.4)'"
onmouseout="if(${
product.stockquantity > 0
}) this.style.transform='translateY(0)'; this.style.background='#FCB1D8'; this.style.boxShadow='0 4px 12px rgba(252, 177, 216, 0.3)'">
<i class="bi bi-cart-plus" style="font-size: 20px;"></i>
${
product.stockquantity <= 0
? "Out of Stock"
: "Add to Cart"
}
</button>
<button onclick="addToWishlist()"
style="padding: 14px 20px; background: white; color: #FCB1D8; border: 2px solid #FCB1D8; border-radius: 10px; font-size: 18px; cursor: pointer; transition: all 0.3s;"
onmouseover="this.style.background='#FCB1D8'; this.style.color='white'; this.style.transform='scale(1.05)'"
onmouseout="this.style.background='white'; this.style.color='#FCB1D8'; this.style.transform='scale(1)'">
<i class="bi bi-heart"></i>
</button>
</div>
</div>
</div>
<!-- Related Products Section -->
<div id="relatedProducts" style="margin-top: 60px; padding-top: 40px; border-top: 2px solid #e5e7eb;">
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 32px;">
<h2 style="font-size: 28px; font-weight: 700; color: #1a1a1a; margin: 0; display: flex; align-items: center; gap: 12px;">
<i class="bi bi-box-seam" style="color: #6b46c1;"></i>
You May Also Like
</h2>
</div>
<div id="relatedProductsGrid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 24px;">
<!-- Products will be loaded here -->
</div>
</div>
</div>
</div>
`;
document.getElementById("loading").style.display = "none";
document.getElementById("productDetail").style.display = "block";
// Store product data with imageurl for shopping cart
window.currentProduct = {
...product,
imageurl: primaryImage, // Add the primary image URL for cart display
};
// Track viewed product for smart recommendations
trackViewedProduct({
...product,
imageurl: primaryImage,
});
// Load related products
loadRelatedProducts(product.category, product.id);
console.log("Product loaded successfully:", product.name);
} catch (error) {
console.error("Error loading product:", error);
document.getElementById("loading").innerHTML =
'<div style="text-align: center; padding: 40px;"><p style="color: #ef4444; font-size: 18px; margin-bottom: 16px;">Error loading product</p><p style="color: #6b7280; margin-bottom: 20px;">' +
error.message +
'</p><a href="/shop" style="color: #FCB1D8; text-decoration: none; font-weight: 600;">← Back to Shop</a></div>';
}
}
function addToCart() {
if (!window.currentProduct) {
alert("Product not loaded. Please refresh the page.");
return;
}
window.ShopSystem.addToCart(window.currentProduct, 1);
}
function addToWishlist() {
if (!window.currentProduct) {
alert("Product not loaded. Please refresh the page.");
return;
}
window.ShopSystem.addToWishlist(window.currentProduct);
}
// Track viewed products for smart recommendations
function trackViewedProduct(product) {
try {
let viewedProducts = JSON.parse(
localStorage.getItem("skyart_viewed_products") || "[]"
);
// Remove if already exists (to update timestamp)
viewedProducts = viewedProducts.filter((p) => p.id !== product.id);
// Add to beginning of array
viewedProducts.unshift({
id: product.id,
name: product.name,
category: product.category,
imageurl: product.imageurl,
price: product.price,
viewedAt: new Date().toISOString(),
});
// Keep only last 20 viewed products
viewedProducts = viewedProducts.slice(0, 20);
localStorage.setItem(
"skyart_viewed_products",
JSON.stringify(viewedProducts)
);
} catch (e) {
console.error("Error tracking viewed product:", e);
}
}
// Load related products (same category + recently viewed)
async function loadRelatedProducts(category, currentProductId) {
try {
const container = document.getElementById("relatedProductsGrid");
if (!container) return;
// Show loading
container.innerHTML =
'<div style="grid-column: 1/-1; text-align: center; padding: 40px; color: #6b7280;">Loading recommendations...</div>';
// Fetch products from same category
const response = await window.apiCache.fetch("/api/products");
const data = await response.json();
if (data.success && data.products) {
let relatedProducts = [];
// Get products from same category (excluding current)
const sameCategoryProducts = data.products.filter(
(p) => p.category === category && p.id !== currentProductId
);
// Get recently viewed products
const viewedProducts = JSON.parse(
localStorage.getItem("skyart_viewed_products") || "[]"
);
const viewedIds = viewedProducts
.map((p) => p.id)
.filter((id) => id !== currentProductId);
const recentlyViewedProducts = data.products.filter(
(p) => viewedIds.includes(p.id) && p.id !== currentProductId
);
// Combine: prioritize same category, then recently viewed
relatedProducts = [...sameCategoryProducts];
recentlyViewedProducts.forEach((p) => {
if (!relatedProducts.find((rp) => rp.id === p.id)) {
relatedProducts.push(p);
}
});
// Shuffle and limit to 4-8 products
relatedProducts = shuffleArray(relatedProducts).slice(0, 8);
if (relatedProducts.length === 0) {
container.innerHTML =
'<div style="grid-column: 1/-1; text-align: center; padding: 40px; color: #6b7280;">No related products found.</div>';
return;
}
// Render products
container.innerHTML = relatedProducts
.map((product) => {
// Get product image (primary or first from images array)
let productImage = "/assets/images/placeholder.svg";
if (
product.images &&
Array.isArray(product.images) &&
product.images.length > 0
) {
const primaryImg = product.images.find(
(img) => img.is_primary
);
productImage = primaryImg
? primaryImg.image_url
: product.images[0].image_url;
} else if (product.imageurl) {
productImage = product.imageurl;
}
return `
<a href="/product?id=${
product.id
}" style="text-decoration: none; color: inherit; display: block; background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.08); transition: all 0.3s; border: 1px solid #e5e7eb;"
onmouseover="this.style.transform='translateY(-4px)'; this.style.boxShadow='0 8px 16px rgba(0,0,0,0.12)'"
onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 2px 8px rgba(0,0,0,0.08)'">
<div style="aspect-ratio: 1; overflow: hidden; background: #f9fafb;">
<img src="${productImage}"
alt="${product.name}"
style="width: 100%; height: 100%; object-fit: cover;"
onerror="this.src='/assets/images/placeholder.svg'" />
</div>
<div style="padding: 16px;">
<h3 style="font-size: 16px; font-weight: 600; color: #1a1a1a; margin: 0 0 8px 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
${product.name}
</h3>
${
product.shortdescription || product.description
? `
<p style="font-size: 14px; color: #636e72; margin: 0 0 12px 0; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;">
${
product.shortdescription ||
(product.description
? product.description.substring(0, 80) + "..."
: "")
}
</p>
`
: ""
}
${
product.category
? `
<p style="font-size: 13px; color: #6b7280; margin: 0 0 12px 0;">
<i class="bi bi-tag"></i> ${product.category}
</p>
`
: ""
}
<div style="display: flex; align-items: center; justify-content: space-between;">
<p style="font-size: 20px; font-weight: 700; color: #6b46c1; margin: 0;">
$${parseFloat(product.price).toFixed(2)}
</p>
${
product.stockquantity > 0
? '<span style="font-size: 12px; color: #10b981; font-weight: 500;"><i class="bi bi-check-circle-fill"></i> In Stock</span>'
: '<span style="font-size: 12px; color: #ef4444; font-weight: 500;"><i class="bi bi-x-circle-fill"></i> Out of Stock</span>'
}
</div>
</div>
</a>
`;
})
.join("");
}
} catch (error) {
console.error("Error loading related products:", error);
const container = document.getElementById("relatedProductsGrid");
if (container) {
container.innerHTML =
'<div style="grid-column: 1/-1; text-align: center; padding: 40px; color: #ef4444;">Error loading recommendations.</div>';
}
}
}
// Shuffle array utility
function shuffleArray(array) {
const arr = [...array];
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
loadProduct();
</script>
<!-- Footer -->
<footer class="footer">
<div class="container">
<div class="footer-grid">
<div class="footer-col">
<h3 class="footer-title" id="footerSiteName">Sky Art Shop</h3>
<p class="footer-text">
Your destination for unique art pieces and creative supplies.
</p>
<div class="social-links">
<a href="#" class="social-link"><i class="bi bi-facebook"></i></a>
<a href="#" class="social-link"
><i class="bi bi-instagram"></i
></a>
<a href="#" class="social-link"><i class="bi bi-twitter"></i></a>
<a href="#" class="social-link"
><i class="bi bi-pinterest"></i
></a>
</div>
</div>
<div class="footer-col">
<h4 class="footer-heading">Shop</h4>
<ul class="footer-links">
<li><a href="/shop">All Products</a></li>
<li><a href="/shop?category=paintings">Paintings</a></li>
<li><a href="/shop?category=prints">Prints</a></li>
<li><a href="/shop?category=supplies">Art Supplies</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-heading">About</h4>
<ul class="footer-links">
<li><a href="/about">Our Story</a></li>
<li><a href="/portfolio">Portfolio</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-heading">Customer Service</h4>
<ul class="footer-links">
<li><a href="/shipping-info">Shipping Info</a></li>
<li><a href="/returns">Returns</a></li>
<li><a href="/faq">FAQ</a></li>
<li><a href="/privacy">Privacy Policy</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p id="footerText">&copy; 2025 Sky Art Shop. All rights reserved.</p>
</div>
</div>
</footer>
</body>
</html>

File diff suppressed because it is too large Load Diff