Fix: Restore website functionality - all pages and APIs working
This commit is contained in:
408
website/assets/css/navbar-mobile-fix.css
Normal file
408
website/assets/css/navbar-mobile-fix.css
Normal file
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* Mobile Navbar Fix
|
||||
* Ensures hamburger menu, cart, and wishlist are always visible on mobile
|
||||
* Also ensures dropdowns appear below navbar properly
|
||||
* Date: January 13, 2026
|
||||
*/
|
||||
|
||||
/* ========================================
|
||||
FORCE MOBILE NAVBAR ELEMENTS VISIBLE
|
||||
======================================== */
|
||||
|
||||
/* Ensure navbar has overflow visible for dropdowns */
|
||||
.modern-navbar {
|
||||
overflow: visible !important;
|
||||
/* Transform creates stacking context - remove it */
|
||||
transform: none !important;
|
||||
/* Ensure proper z-index without creating new stacking context */
|
||||
isolation: auto !important;
|
||||
}
|
||||
|
||||
/* Ensure navbar wrapper has overflow visible */
|
||||
.modern-navbar .navbar-wrapper {
|
||||
overflow: visible !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
/* Ensure navbar wrapper uses flexbox properly */
|
||||
.modern-navbar .navbar-wrapper {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: space-between !important;
|
||||
flex-wrap: nowrap !important;
|
||||
gap: 8px !important;
|
||||
}
|
||||
|
||||
/* Mobile: Ensure brand doesn't take all space */
|
||||
.modern-navbar .navbar-brand {
|
||||
flex: 0 1 auto !important;
|
||||
margin-right: 0 !important;
|
||||
min-width: auto !important;
|
||||
}
|
||||
|
||||
/* Hide desktop menu on mobile */
|
||||
.modern-navbar .navbar-menu {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.modern-navbar .navbar-menu {
|
||||
display: flex !important;
|
||||
flex: 1 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* FORCE navbar actions to be visible and aligned right */
|
||||
.modern-navbar .navbar-actions {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
gap: 4px !important;
|
||||
flex-shrink: 0 !important;
|
||||
margin-left: auto !important;
|
||||
flex: 0 0 auto !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
@media (min-width: 480px) {
|
||||
.modern-navbar .navbar-actions {
|
||||
gap: 8px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.modern-navbar .navbar-actions {
|
||||
gap: 12px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* FORCE wishlist and cart to be visible with proper positioning context */
|
||||
.modern-navbar .wishlist-dropdown-wrapper,
|
||||
.modern-navbar .cart-dropdown-wrapper,
|
||||
.modern-navbar .action-item {
|
||||
display: block !important;
|
||||
position: relative !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
/* FORCE action buttons to be visible */
|
||||
.modern-navbar .action-btn,
|
||||
.modern-navbar #wishlistToggle,
|
||||
.modern-navbar #cartToggle {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
width: 36px !important;
|
||||
height: 36px !important;
|
||||
min-width: 36px !important;
|
||||
flex-shrink: 0 !important;
|
||||
}
|
||||
|
||||
@media (min-width: 480px) {
|
||||
.modern-navbar .action-btn,
|
||||
.modern-navbar #wishlistToggle,
|
||||
.modern-navbar #cartToggle {
|
||||
width: 40px !important;
|
||||
height: 40px !important;
|
||||
min-width: 40px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.modern-navbar .action-btn,
|
||||
.modern-navbar #wishlistToggle,
|
||||
.modern-navbar #cartToggle {
|
||||
width: 44px !important;
|
||||
height: 44px !important;
|
||||
min-width: 44px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* FORCE mobile toggle (hamburger) to be visible on mobile */
|
||||
.modern-navbar .mobile-toggle,
|
||||
.modern-navbar #mobileMenuToggle {
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
width: 36px !important;
|
||||
height: 36px !important;
|
||||
min-width: 36px !important;
|
||||
flex-shrink: 0 !important;
|
||||
gap: 4px !important;
|
||||
padding: 6px !important;
|
||||
}
|
||||
|
||||
@media (min-width: 480px) {
|
||||
.modern-navbar .mobile-toggle,
|
||||
.modern-navbar #mobileMenuToggle {
|
||||
width: 40px !important;
|
||||
height: 40px !important;
|
||||
min-width: 40px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.modern-navbar .mobile-toggle,
|
||||
.modern-navbar #mobileMenuToggle {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hamburger lines */
|
||||
.modern-navbar .toggle-line {
|
||||
display: block !important;
|
||||
width: 18px !important;
|
||||
height: 2px !important;
|
||||
background: #202023 !important;
|
||||
border-radius: 2px !important;
|
||||
transition: all 0.3s ease !important;
|
||||
}
|
||||
|
||||
@media (min-width: 480px) {
|
||||
.modern-navbar .toggle-line {
|
||||
width: 20px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Action badges */
|
||||
.modern-navbar .action-badge,
|
||||
.modern-navbar #wishlistCount,
|
||||
.modern-navbar #cartCount {
|
||||
position: absolute !important;
|
||||
top: 0 !important;
|
||||
right: 0 !important;
|
||||
min-width: 16px !important;
|
||||
height: 16px !important;
|
||||
background: #FCB1D8 !important;
|
||||
color: #202023 !important;
|
||||
font-size: 10px !important;
|
||||
font-weight: 700 !important;
|
||||
border-radius: 8px !important;
|
||||
display: none !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
padding: 0 4px !important;
|
||||
border: 2px solid #FFD0D0 !important;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.modern-navbar .action-badge,
|
||||
.modern-navbar #wishlistCount,
|
||||
.modern-navbar #cartCount {
|
||||
min-width: 18px !important;
|
||||
height: 18px !important;
|
||||
font-size: 11px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.modern-navbar .action-badge.show,
|
||||
.modern-navbar #wishlistCount.show,
|
||||
.modern-navbar #cartCount.show {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
MOBILE DROPDOWN POSITIONING
|
||||
======================================== */
|
||||
.modern-navbar .action-dropdown,
|
||||
.modern-navbar .cart-dropdown,
|
||||
.modern-navbar .wishlist-dropdown,
|
||||
.modern-navbar #cartPanel,
|
||||
.modern-navbar #wishlistPanel {
|
||||
position: fixed !important;
|
||||
top: 60px !important;
|
||||
right: 8px !important;
|
||||
left: 8px !important;
|
||||
width: auto !important;
|
||||
max-width: 400px !important;
|
||||
margin-left: auto !important;
|
||||
max-height: calc(100vh - 70px) !important;
|
||||
max-height: calc(100dvh - 70px) !important;
|
||||
z-index: 10001 !important;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.modern-navbar .action-dropdown,
|
||||
.modern-navbar .cart-dropdown,
|
||||
.modern-navbar .wishlist-dropdown,
|
||||
.modern-navbar #cartPanel,
|
||||
.modern-navbar #wishlistPanel {
|
||||
position: absolute !important;
|
||||
top: calc(100% + 8px) !important;
|
||||
right: 0 !important;
|
||||
left: auto !important;
|
||||
width: 400px !important;
|
||||
max-height: 500px !important;
|
||||
z-index: 10001 !important;
|
||||
background: white !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
MOBILE MENU SIDEBAR
|
||||
======================================== */
|
||||
.modern-navbar .mobile-menu,
|
||||
.modern-navbar #mobileMenu {
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
right: -100% !important;
|
||||
width: 280px !important;
|
||||
max-width: 85vw !important;
|
||||
height: 100vh !important;
|
||||
height: 100dvh !important;
|
||||
background: #FFFFFF !important;
|
||||
z-index: 10002 !important;
|
||||
transition: right 0.3s ease !important;
|
||||
box-shadow: -4px 0 20px rgba(0, 0, 0, 0.2) !important;
|
||||
overflow-y: auto !important;
|
||||
-webkit-overflow-scrolling: touch !important;
|
||||
}
|
||||
|
||||
.modern-navbar .mobile-menu.active,
|
||||
.modern-navbar #mobileMenu.active {
|
||||
right: 0 !important;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.modern-navbar .mobile-menu,
|
||||
.modern-navbar #mobileMenu {
|
||||
width: 320px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile menu overlay */
|
||||
.mobile-menu-overlay,
|
||||
#mobileMenuOverlay {
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
bottom: 0 !important;
|
||||
background: rgba(0, 0, 0, 0.5) !important;
|
||||
z-index: 10001 !important;
|
||||
display: none !important;
|
||||
opacity: 0 !important;
|
||||
transition: opacity 0.3s ease !important;
|
||||
}
|
||||
|
||||
.mobile-menu-overlay.active,
|
||||
#mobileMenuOverlay.active {
|
||||
display: block !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
BRAND LOGO & TEXT RESPONSIVE
|
||||
======================================== */
|
||||
.modern-navbar .brand-logo {
|
||||
width: 32px !important;
|
||||
height: 32px !important;
|
||||
}
|
||||
|
||||
@media (min-width: 480px) {
|
||||
.modern-navbar .brand-logo {
|
||||
width: 36px !important;
|
||||
height: 36px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.modern-navbar .brand-logo {
|
||||
width: 44px !important;
|
||||
height: 44px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.modern-navbar .brand-logo {
|
||||
width: 56px !important;
|
||||
height: 56px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.modern-navbar .brand-name {
|
||||
font-size: 13px !important;
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
@media (max-width: 374px) {
|
||||
.modern-navbar .brand-name {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 480px) {
|
||||
.modern-navbar .brand-name {
|
||||
font-size: 15px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.modern-navbar .brand-name {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.modern-navbar .brand-name {
|
||||
font-size: 20px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
TOUCH IMPROVEMENTS
|
||||
======================================== */
|
||||
@media (hover: none) and (pointer: coarse) {
|
||||
/* Touch devices */
|
||||
.modern-navbar .action-btn:active,
|
||||
.modern-navbar .mobile-toggle:active {
|
||||
transform: scale(0.92) !important;
|
||||
background: rgba(252, 177, 216, 0.3) !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prevent text selection on buttons */
|
||||
.modern-navbar .action-btn,
|
||||
.modern-navbar .mobile-toggle {
|
||||
-webkit-user-select: none !important;
|
||||
user-select: none !important;
|
||||
-webkit-tap-highlight-color: transparent !important;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
ENSURE ICONS ARE VISIBLE
|
||||
======================================== */
|
||||
.modern-navbar .action-btn i,
|
||||
.modern-navbar .mobile-toggle i {
|
||||
display: inline-block !important;
|
||||
pointer-events: none !important;
|
||||
font-size: 18px !important;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.modern-navbar .action-btn i,
|
||||
.modern-navbar .mobile-toggle i {
|
||||
font-size: 22px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Z-INDEX HIERARCHY
|
||||
======================================== */
|
||||
.modern-navbar {
|
||||
z-index: 1000 !important;
|
||||
}
|
||||
|
||||
.modern-navbar .action-dropdown.active,
|
||||
.modern-navbar .cart-dropdown.active,
|
||||
.modern-navbar .wishlist-dropdown.active {
|
||||
z-index: 10001 !important;
|
||||
}
|
||||
|
||||
.mobile-menu-overlay.active {
|
||||
z-index: 10001 !important;
|
||||
}
|
||||
|
||||
.modern-navbar .mobile-menu.active {
|
||||
z-index: 10002 !important;
|
||||
}
|
||||
1274
website/assets/css/responsive-complete.css
Normal file
1274
website/assets/css/responsive-complete.css
Normal file
File diff suppressed because it is too large
Load Diff
@@ -232,18 +232,18 @@
|
||||
.mobile-menu {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
right: -100%;
|
||||
width: 280px;
|
||||
height: 100vh;
|
||||
background: white;
|
||||
z-index: 9999;
|
||||
transition: left 0.3s ease;
|
||||
transition: right 0.3s ease;
|
||||
overflow-y: auto;
|
||||
box-shadow: 2px 0 10px rgba(0,0,0,0.1);
|
||||
box-shadow: -2px 0 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.mobile-menu.active {
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.mobile-menu-overlay {
|
||||
|
||||
@@ -12,134 +12,148 @@
|
||||
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=1735692100" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css?v=1767233028" />
|
||||
<link rel="stylesheet" href="/assets/css/page-overrides.css?v=1736790001" />
|
||||
<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" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="/assets/css/navbar-mobile-fix.css?v=1736790000"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.__bodyReady = true;
|
||||
</script>
|
||||
<!-- 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 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">
|
||||
<div class="cart-summary">
|
||||
<span class="summary-label">Subtotal:</span>
|
||||
<span class="summary-value" id="cartSubtotal">$0.00</span>
|
||||
</div>
|
||||
<a href="/checkout" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop" class="btn-text">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="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>
|
||||
<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="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">
|
||||
<div class="cart-summary">
|
||||
<span class="summary-label">Subtotal:</span>
|
||||
<span class="summary-value" id="cartSubtotal">$0.00</span>
|
||||
</div>
|
||||
<a href="/checkout" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop" class="btn-text">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>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<section class="about-hero">
|
||||
<div class="container">
|
||||
@@ -591,5 +605,6 @@
|
||||
loadTeamMembers();
|
||||
});
|
||||
</script>
|
||||
<script src="/assets/js/shop-system.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -188,6 +188,53 @@
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
/* Button Styles for Cart/Wishlist Dropdowns */
|
||||
.action-dropdown .btn-outline,
|
||||
.action-dropdown .btn-text,
|
||||
.action-dropdown .btn-primary-full {
|
||||
display: inline-block;
|
||||
padding: 10px 16px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.action-dropdown .btn-outline {
|
||||
background: transparent;
|
||||
color: #6b46c1;
|
||||
border: 1px solid #6b46c1;
|
||||
}
|
||||
|
||||
.action-dropdown .btn-outline:hover {
|
||||
background: #f3f0ff;
|
||||
}
|
||||
|
||||
.action-dropdown .btn-text {
|
||||
background: transparent;
|
||||
color: #6b7280;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.action-dropdown .btn-text:hover {
|
||||
color: #FCB1D8;
|
||||
}
|
||||
|
||||
.action-dropdown .btn-primary-full {
|
||||
background: #6b46c1;
|
||||
color: white;
|
||||
width: 100%;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.action-dropdown .btn-primary-full:hover {
|
||||
background: #5a38a3;
|
||||
}
|
||||
|
||||
/* Scrollbar for dropdown body */
|
||||
.dropdown-body::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
|
||||
3131
website/public/assets/css/main.css
Normal file
3131
website/public/assets/css/main.css
Normal file
File diff suppressed because it is too large
Load Diff
280
website/public/assets/css/navbar-mobile-fix.css
Normal file
280
website/public/assets/css/navbar-mobile-fix.css
Normal file
@@ -0,0 +1,280 @@
|
||||
/**
|
||||
* Mobile Navbar Fixes
|
||||
* Ensures hamburger menu, cart, and wishlist are visible on mobile devices
|
||||
*/
|
||||
|
||||
/* Mobile hamburger menu - always visible on small screens */
|
||||
@media (max-width: 768px) {
|
||||
.mobile-toggle {
|
||||
display: flex !important;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.toggle-line {
|
||||
width: 24px;
|
||||
height: 3px;
|
||||
background-color: #202023;
|
||||
border-radius: 2px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
/* Hide desktop menu on mobile */
|
||||
.navbar-menu {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Ensure cart and wishlist icons are visible */
|
||||
.navbar-actions {
|
||||
display: flex !important;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.action-item {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
color: #202023;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.action-btn i {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.action-badge {
|
||||
display: flex !important;
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
background: #fcb1d8;
|
||||
color: #202023;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.action-badge.show {
|
||||
opacity: 1 !important;
|
||||
visibility: visible !important;
|
||||
}
|
||||
|
||||
/* Mobile menu overlay */
|
||||
.mobile-menu-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all 0.3s ease;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.mobile-menu-overlay.active {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* Mobile menu sidebar */
|
||||
.mobile-menu {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: -100%;
|
||||
width: 80%;
|
||||
max-width: 300px;
|
||||
height: 100vh;
|
||||
background: white;
|
||||
box-shadow: -4px 0 12px rgba(0, 0, 0, 0.1);
|
||||
transition: right 0.3s ease;
|
||||
z-index: 1000;
|
||||
overflow-y: auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.mobile-menu.active {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.mobile-menu-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.mobile-brand {
|
||||
font-family: "Roboto", sans-serif;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #202023;
|
||||
}
|
||||
|
||||
.mobile-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 24px;
|
||||
color: #202023;
|
||||
cursor: pointer;
|
||||
padding: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.mobile-menu-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mobile-menu-list li {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.mobile-link {
|
||||
display: block;
|
||||
padding: 12px 16px;
|
||||
color: #202023;
|
||||
text-decoration: none;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.mobile-link:hover,
|
||||
.mobile-link:focus {
|
||||
background: #ffebeb;
|
||||
color: #fcb1d8;
|
||||
}
|
||||
|
||||
/* Dropdown menus on mobile */
|
||||
.action-dropdown {
|
||||
position: fixed !important;
|
||||
right: 0;
|
||||
left: 0;
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
max-height: 70vh;
|
||||
border-radius: 16px 16px 0 0 !important;
|
||||
transform: translateY(100%) !important;
|
||||
}
|
||||
|
||||
.action-dropdown.show {
|
||||
transform: translateY(0) !important;
|
||||
}
|
||||
|
||||
/* Compact dropdown on mobile */
|
||||
.dropdown-head {
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.dropdown-head h3 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.dropdown-body {
|
||||
max-height: calc(70vh - 140px);
|
||||
overflow-y: auto;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.dropdown-foot {
|
||||
padding: 12px 16px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
/* Prevent body scroll when menu is open */
|
||||
body.menu-open {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablet adjustments */
|
||||
@media (min-width: 769px) and (max-width: 1024px) {
|
||||
.navbar-actions {
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.action-dropdown {
|
||||
max-width: 360px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktop - hide mobile elements */
|
||||
@media (min-width: 769px) {
|
||||
.mobile-toggle {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.mobile-menu,
|
||||
.mobile-menu-overlay {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Accessibility improvements */
|
||||
.action-btn:focus,
|
||||
.mobile-toggle:focus,
|
||||
.mobile-close:focus {
|
||||
outline: 2px solid #fcb1d8;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.mobile-link:focus {
|
||||
outline: 2px solid #fcb1d8;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
/* Smooth transitions */
|
||||
* {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
button {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
/* Fix for iOS Safari button styling */
|
||||
button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button:focus-visible {
|
||||
outline: 2px solid #fcb1d8;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
139
website/public/assets/css/page-overrides.css
Normal file
139
website/public/assets/css/page-overrides.css
Normal file
@@ -0,0 +1,139 @@
|
||||
/* Page-specific overrides for home, portfolio, blog, etc. */
|
||||
|
||||
/* Sticky Banner Wrapper */
|
||||
.sticky-banner-wrapper {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
background: #ffd0d0;
|
||||
}
|
||||
|
||||
.sticky-banner-wrapper .modern-navbar {
|
||||
position: relative;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* CRITICAL FIX: Force dropdowns below navbar */
|
||||
.modern-navbar {
|
||||
position: relative !important;
|
||||
overflow: visible !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
.modern-navbar .navbar-wrapper {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.modern-navbar .navbar-actions {
|
||||
overflow: visible !important;
|
||||
display: flex !important;
|
||||
gap: 8px !important;
|
||||
}
|
||||
|
||||
.modern-navbar .action-btn,
|
||||
.modern-navbar #wishlistToggle,
|
||||
.modern-navbar #cartToggle {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
width: 44px !important;
|
||||
height: 44px !important;
|
||||
}
|
||||
|
||||
.modern-navbar .action-item,
|
||||
.modern-navbar .wishlist-dropdown-wrapper,
|
||||
.modern-navbar .cart-dropdown-wrapper {
|
||||
position: relative !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.modern-navbar .action-dropdown,
|
||||
.modern-navbar #cartPanel,
|
||||
.modern-navbar #wishlistPanel {
|
||||
position: absolute !important;
|
||||
right: 0 !important;
|
||||
left: auto !important;
|
||||
z-index: 999999 !important;
|
||||
background: white !important;
|
||||
width: 400px !important;
|
||||
max-height: 500px !important;
|
||||
}
|
||||
|
||||
@media (max-width: 639px) {
|
||||
.modern-navbar .action-dropdown,
|
||||
.modern-navbar #cartPanel,
|
||||
.modern-navbar #wishlistPanel {
|
||||
position: fixed !important;
|
||||
top: 60px !important;
|
||||
right: 8px !important;
|
||||
left: 8px !important;
|
||||
width: auto !important;
|
||||
max-width: 400px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Product Title Link */
|
||||
.product-title-link {
|
||||
text-decoration: none !important;
|
||||
color: #202023 !important;
|
||||
display: block !important;
|
||||
cursor: pointer !important;
|
||||
transition: color 0.3s ease;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.product-title-link:hover {
|
||||
color: #fcb1d8 !important;
|
||||
}
|
||||
|
||||
.product-title-link h3 {
|
||||
color: inherit;
|
||||
transition: color 0.3s ease;
|
||||
margin: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.product-title-link:hover h3 {
|
||||
color: #fcb1d8 !important;
|
||||
}
|
||||
|
||||
/* Contact Page Mobile */
|
||||
@media (max-width: 768px) {
|
||||
#contactForm > div[style*="grid-template-columns"] {
|
||||
grid-template-columns: 1fr !important;
|
||||
}
|
||||
.contact-form-wrapper {
|
||||
padding: 24px !important;
|
||||
border-radius: 12px !important;
|
||||
}
|
||||
.contact-section {
|
||||
padding: 40px 0 !important;
|
||||
}
|
||||
section[style*="padding: 100px"] {
|
||||
padding: 60px 0 !important;
|
||||
}
|
||||
h1[style*="font-size: 2.5rem"] {
|
||||
font-size: 1.8rem !important;
|
||||
}
|
||||
h2[style*="font-size: 2rem"] {
|
||||
font-size: 1.5rem !important;
|
||||
}
|
||||
#contactInfoSection div[style*="grid-template-columns"] {
|
||||
grid-template-columns: 1fr !important;
|
||||
gap: 16px !important;
|
||||
}
|
||||
input, textarea, button {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.contact-form-wrapper {
|
||||
padding: 20px !important;
|
||||
}
|
||||
.container {
|
||||
padding-left: 16px !important;
|
||||
padding-right: 16px !important;
|
||||
}
|
||||
}
|
||||
@@ -232,18 +232,18 @@
|
||||
.mobile-menu {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
right: -100%;
|
||||
width: 280px;
|
||||
height: 100vh;
|
||||
background: white;
|
||||
z-index: 9999;
|
||||
transition: left 0.3s ease;
|
||||
transition: right 0.3s ease;
|
||||
overflow-y: auto;
|
||||
box-shadow: 2px 0 10px rgba(0,0,0,0.1);
|
||||
box-shadow: -2px 0 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.mobile-menu.active {
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.mobile-menu-overlay {
|
||||
|
||||
630
website/public/assets/css/responsive.css
Normal file
630
website/public/assets/css/responsive.css
Normal file
@@ -0,0 +1,630 @@
|
||||
/**
|
||||
* Responsive Layout Utilities
|
||||
* Mobile-first responsive design system
|
||||
*/
|
||||
|
||||
/* ========================================
|
||||
RESPONSIVE UTILITIES
|
||||
======================================== */
|
||||
|
||||
/* Loading States */
|
||||
.loading {
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.loading::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: -20px 0 0 -20px;
|
||||
border: 4px solid #f3f3f3;
|
||||
border-top: 4px solid #667eea;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Accessibility */
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0,0,0,0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.focus-visible:focus {
|
||||
outline: 2px solid #667eea;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* Responsive Images */
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Container Queries */
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
padding: 0 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.container {
|
||||
padding: 0 60px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Grid System */
|
||||
.grid {
|
||||
display: grid;
|
||||
gap: 20px;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.grid-2 {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.grid-3 {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.grid-4 {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Flex Utilities */
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex-col {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.flex-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.justify-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.justify-center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.gap-1 { gap: 0.25rem; }
|
||||
.gap-2 { gap: 0.5rem; }
|
||||
.gap-3 { gap: 0.75rem; }
|
||||
.gap-4 { gap: 1rem; }
|
||||
.gap-6 { gap: 1.5rem; }
|
||||
|
||||
/* Spacing */
|
||||
.m-0 { margin: 0; }
|
||||
.mt-1 { margin-top: 0.25rem; }
|
||||
.mt-2 { margin-top: 0.5rem; }
|
||||
.mt-4 { margin-top: 1rem; }
|
||||
.mt-6 { margin-top: 1.5rem; }
|
||||
.mb-2 { margin-bottom: 0.5rem; }
|
||||
.mb-4 { margin-bottom: 1rem; }
|
||||
.mb-6 { margin-bottom: 1.5rem; }
|
||||
|
||||
.p-0 { padding: 0; }
|
||||
.p-2 { padding: 0.5rem; }
|
||||
.p-4 { padding: 1rem; }
|
||||
.p-6 { padding: 1.5rem; }
|
||||
|
||||
/* Text Utilities */
|
||||
.text-center { text-align: center; }
|
||||
.text-left { text-align: left; }
|
||||
.text-right { text-align: right; }
|
||||
|
||||
.text-sm { font-size: 0.875rem; }
|
||||
.text-base { font-size: 1rem; }
|
||||
.text-lg { font-size: 1.125rem; }
|
||||
.text-xl { font-size: 1.25rem; }
|
||||
.text-2xl { font-size: 1.5rem; }
|
||||
.text-3xl { font-size: 1.875rem; }
|
||||
|
||||
.font-normal { font-weight: 400; }
|
||||
.font-medium { font-weight: 500; }
|
||||
.font-semibold { font-weight: 600; }
|
||||
.font-bold { font-weight: 700; }
|
||||
|
||||
/* Display Utilities */
|
||||
.hidden { display: none !important; }
|
||||
.block { display: block; }
|
||||
.inline-block { display: inline-block; }
|
||||
|
||||
@media (max-width: 639px) {
|
||||
.sm\\:hidden { display: none !important; }
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.sm\\:block { display: block; }
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.md\\:hidden { display: none !important; }
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.md\\:block { display: block; }
|
||||
.md\\:flex { display: flex; }
|
||||
}
|
||||
|
||||
@media (max-width: 1023px) {
|
||||
.lg\\:hidden { display: none !important; }
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.lg\\:block { display: block; }
|
||||
.lg\\:flex { display: flex; }
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
RESPONSIVE PRODUCT CARDS
|
||||
======================================== */
|
||||
|
||||
.products-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.products-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.products-grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.products-grid {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.product-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.product-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 8px 16px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.product-image-wrapper {
|
||||
position: relative;
|
||||
padding-top: 100%;
|
||||
overflow: hidden;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
/* .product-image styles moved to main.css - do not override */
|
||||
/* Commented out to prevent conflict with main.css product-image styles */
|
||||
/*
|
||||
.product-image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
*/
|
||||
|
||||
.product-info {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.product-title {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
margin: 0 0 8px 0;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.product-price {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
color: #667eea;
|
||||
margin: 0 0 12px 0;
|
||||
}
|
||||
|
||||
.product-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.product-actions {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
.wishlist-btn {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
color: #666;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.wishlist-btn:hover {
|
||||
background: #667eea;
|
||||
color: white;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.wishlist-btn.active {
|
||||
background: #dc3545;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
RESPONSIVE CART/WISHLIST DROPDOWNS
|
||||
======================================== */
|
||||
|
||||
.action-dropdown {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
width: 100vw;
|
||||
max-width: 400px;
|
||||
background: white;
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
|
||||
border-radius: 12px;
|
||||
margin-top: 8px;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateY(-10px);
|
||||
transition: all 0.3s ease;
|
||||
z-index: 1000;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 639px) {
|
||||
.action-dropdown {
|
||||
position: fixed;
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-width: 100%;
|
||||
border-radius: 12px 12px 0 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
}
|
||||
|
||||
.action-dropdown.active {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.dropdown-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px 20px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.dropdown-head h3 {
|
||||
margin: 0;
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.dropdown-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
color: #666;
|
||||
padding: 4px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.dropdown-body {
|
||||
padding: 16px;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.dropdown-foot {
|
||||
padding: 16px 20px;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
.cart-item,
|
||||
.wishlist-item {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.cart-item:last-child,
|
||||
.wishlist-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.cart-item-image,
|
||||
.wishlist-item-image {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
object-fit: cover;
|
||||
border-radius: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.cart-item-details,
|
||||
.wishlist-item-details {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.cart-item-title,
|
||||
.wishlist-item-title {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
margin: 0 0 4px 0;
|
||||
}
|
||||
|
||||
.cart-item-price,
|
||||
.wishlist-item-price {
|
||||
font-size: 0.875rem;
|
||||
color: #667eea;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cart-item-remove,
|
||||
.wishlist-item-remove {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
padding: 4px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.cart-item-remove:hover,
|
||||
.wishlist-item-remove:hover {
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
RESPONSIVE BUTTONS
|
||||
======================================== */
|
||||
|
||||
button,
|
||||
.btn,
|
||||
.btn-primary,
|
||||
.btn-secondary,
|
||||
.btn-outline {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 12px 24px;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.btn-primary,
|
||||
.btn-primary-full {
|
||||
background: #667eea;
|
||||
color: white;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: #5568d3;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(102,126,234,0.3);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: #28a745;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: #218838;
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
background: white;
|
||||
color: #667eea;
|
||||
border: 2px solid #667eea;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.btn-outline:hover {
|
||||
background: #667eea;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
background: none;
|
||||
color: #667eea;
|
||||
text-decoration: underline;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 639px) {
|
||||
button,
|
||||
.btn {
|
||||
font-size: 0.875rem;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
RESPONSIVE NAVIGATION
|
||||
======================================== */
|
||||
|
||||
/* Navbar styles removed - see navbar.css for all navbar styling */
|
||||
|
||||
.action-btn {
|
||||
position: relative;
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 24px;
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.action-badge {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background: #dc3545;
|
||||
color: white;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 9px;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
/* Mobile Menu */
|
||||
@media (max-width: 767px) {
|
||||
.mobile-menu-toggle {
|
||||
display: block;
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.mobile-menu {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: -100%;
|
||||
width: 80%;
|
||||
max-width: 300px;
|
||||
height: 100vh;
|
||||
background: white;
|
||||
box-shadow: -4px 0 12px rgba(0,0,0,0.1);
|
||||
transition: right 0.3s ease;
|
||||
z-index: 1001;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.mobile-menu.active {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.mobile-menu-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: rgba(0,0,0,0.5);
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all 0.3s ease;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.mobile-menu-overlay.active {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print Styles */
|
||||
@media print {
|
||||
.modern-navbar,
|
||||
.navbar-actions,
|
||||
.mobile-menu,
|
||||
.action-dropdown,
|
||||
button {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
299
website/public/assets/css/shopping.css
Normal file
299
website/public/assets/css/shopping.css
Normal file
@@ -0,0 +1,299 @@
|
||||
/* Cart and Wishlist Item Styles */
|
||||
|
||||
/* Cart Items */
|
||||
.cart-item {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
background: #fafafa;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 12px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.cart-item:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.cart-item-image {
|
||||
flex-shrink: 0;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.cart-item-image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.cart-item-details {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.cart-item-name {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.cart-item-price {
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: #6b46c1;
|
||||
}
|
||||
|
||||
.cart-item-quantity {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.qty-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: 1px solid #d1d5db;
|
||||
background: white;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.qty-btn:hover {
|
||||
border-color: #6b46c1;
|
||||
color: #6b46c1;
|
||||
background: #f3f0ff;
|
||||
}
|
||||
|
||||
.qty-value {
|
||||
min-width: 32px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
.cart-item-actions {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.cart-item-remove {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #9ca3af;
|
||||
font-size: 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.cart-item-remove:hover {
|
||||
background: #fee2e2;
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
.cart-item-total {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
/* Wishlist Items */
|
||||
.wishlist-item {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
background: #fafafa;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 12px;
|
||||
position: relative;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.wishlist-item:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.wishlist-item-image {
|
||||
flex-shrink: 0;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.wishlist-item-image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.wishlist-item-details {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.wishlist-item-name {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
line-height: 1.4;
|
||||
padding-right: 24px;
|
||||
}
|
||||
|
||||
.wishlist-item-price {
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: #6b46c1;
|
||||
}
|
||||
|
||||
.btn-move-to-cart {
|
||||
align-self: flex-start;
|
||||
padding: 6px 14px;
|
||||
border: 1px solid #6b46c1;
|
||||
background: transparent;
|
||||
color: #6b46c1;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.btn-move-to-cart:hover {
|
||||
background: #6b46c1;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.wishlist-item-remove {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #9ca3af;
|
||||
font-size: 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.wishlist-item-remove:hover {
|
||||
background: #fee2e2;
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
/* Notifications */
|
||||
.notification {
|
||||
position: fixed;
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
min-width: 280px;
|
||||
padding: 16px 20px;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
z-index: 10000;
|
||||
transform: translateY(100px);
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
|
||||
.notification.show {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.notification i {
|
||||
font-size: 20px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.notification-success {
|
||||
border-left: 4px solid #10b981;
|
||||
}
|
||||
|
||||
.notification-success i {
|
||||
color: #10b981;
|
||||
}
|
||||
|
||||
.notification-info {
|
||||
border-left: 4px solid #3b82f6;
|
||||
}
|
||||
|
||||
.notification-info i {
|
||||
color: #3b82f6;
|
||||
}
|
||||
|
||||
.notification span {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
/* Mobile Responsive */
|
||||
@media (max-width: 640px) {
|
||||
.cart-item,
|
||||
.wishlist-item {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.cart-item-image,
|
||||
.wishlist-item-image {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.cart-item-name,
|
||||
.wishlist-item-name {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.notification {
|
||||
right: 16px;
|
||||
left: 16px;
|
||||
min-width: auto;
|
||||
}
|
||||
}
|
||||
287
website/public/assets/js/accessibility-enhanced.js
Normal file
287
website/public/assets/js/accessibility-enhanced.js
Normal file
@@ -0,0 +1,287 @@
|
||||
/**
|
||||
* Accessibility Enhancements
|
||||
* WCAG 2.1 AA Compliant
|
||||
*/
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
const A11y = {
|
||||
init() {
|
||||
this.addSkipLink();
|
||||
this.enhanceFocusManagement();
|
||||
this.addARIALabels();
|
||||
this.improveKeyboardNav();
|
||||
this.addLiveRegions();
|
||||
this.enhanceFormAccessibility();
|
||||
console.log("[A11y] Accessibility enhancements loaded");
|
||||
},
|
||||
|
||||
// Add skip to main content link
|
||||
addSkipLink() {
|
||||
if (document.querySelector(".skip-link")) return;
|
||||
|
||||
const skipLink = document.createElement("a");
|
||||
skipLink.href = "#main-content";
|
||||
skipLink.className = "skip-link";
|
||||
skipLink.textContent = "Skip to main content";
|
||||
skipLink.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
const main = document.querySelector("#main-content, main");
|
||||
if (main) {
|
||||
main.setAttribute("tabindex", "-1");
|
||||
main.focus();
|
||||
}
|
||||
});
|
||||
|
||||
document.body.insertBefore(skipLink, document.body.firstChild);
|
||||
},
|
||||
|
||||
// Enhance focus management
|
||||
enhanceFocusManagement() {
|
||||
// Trap focus in modals
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key !== "Tab") return;
|
||||
|
||||
const modal = document.querySelector(
|
||||
'.modal.active, .dropdown[style*="display: flex"]'
|
||||
);
|
||||
if (!modal) return;
|
||||
|
||||
const focusable = modal.querySelectorAll(
|
||||
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
||||
);
|
||||
|
||||
if (focusable.length === 0) return;
|
||||
|
||||
const first = focusable[0];
|
||||
const last = focusable[focusable.length - 1];
|
||||
|
||||
if (e.shiftKey && document.activeElement === first) {
|
||||
e.preventDefault();
|
||||
last.focus();
|
||||
} else if (!e.shiftKey && document.activeElement === last) {
|
||||
e.preventDefault();
|
||||
first.focus();
|
||||
}
|
||||
});
|
||||
|
||||
// Focus visible styles
|
||||
const style = document.createElement("style");
|
||||
style.textContent = `
|
||||
*:focus-visible {
|
||||
outline: 3px solid #667eea !important;
|
||||
outline-offset: 2px !important;
|
||||
}
|
||||
|
||||
button:focus-visible,
|
||||
a:focus-visible,
|
||||
input:focus-visible,
|
||||
select:focus-visible,
|
||||
textarea:focus-visible {
|
||||
outline: 3px solid #667eea !important;
|
||||
outline-offset: 2px !important;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
},
|
||||
|
||||
// Add ARIA labels to interactive elements
|
||||
addARIALabels() {
|
||||
// Cart button
|
||||
const cartBtn = document.querySelector("#cart-btn");
|
||||
if (cartBtn && !cartBtn.hasAttribute("aria-label")) {
|
||||
cartBtn.setAttribute("aria-label", "Shopping cart");
|
||||
cartBtn.setAttribute("aria-haspopup", "true");
|
||||
}
|
||||
|
||||
// Wishlist button
|
||||
const wishlistBtn = document.querySelector("#wishlist-btn");
|
||||
if (wishlistBtn && !wishlistBtn.hasAttribute("aria-label")) {
|
||||
wishlistBtn.setAttribute("aria-label", "Wishlist");
|
||||
wishlistBtn.setAttribute("aria-haspopup", "true");
|
||||
}
|
||||
|
||||
// Mobile menu toggle
|
||||
const menuToggle = document.querySelector(".mobile-menu-toggle");
|
||||
if (menuToggle && !menuToggle.hasAttribute("aria-label")) {
|
||||
menuToggle.setAttribute("aria-label", "Open navigation menu");
|
||||
menuToggle.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
|
||||
// Add ARIA labels to product cards
|
||||
document.querySelectorAll(".product-card").forEach((card, index) => {
|
||||
if (!card.hasAttribute("role")) {
|
||||
card.setAttribute("role", "article");
|
||||
}
|
||||
|
||||
const title = card.querySelector("h3, .product-title");
|
||||
if (title && !title.id) {
|
||||
title.id = `product-title-${index}`;
|
||||
card.setAttribute("aria-labelledby", title.id);
|
||||
}
|
||||
});
|
||||
|
||||
// Add labels to icon-only buttons
|
||||
document.querySelectorAll("button:not([aria-label])").forEach((btn) => {
|
||||
const icon = btn.querySelector('i[class*="bi-"]');
|
||||
if (icon && !btn.textContent.trim()) {
|
||||
const iconClass = icon.className;
|
||||
let label = "Button";
|
||||
|
||||
if (iconClass.includes("cart")) label = "Add to cart";
|
||||
else if (iconClass.includes("heart")) label = "Add to wishlist";
|
||||
else if (iconClass.includes("trash")) label = "Remove";
|
||||
else if (iconClass.includes("plus")) label = "Increase";
|
||||
else if (iconClass.includes("minus") || iconClass.includes("dash"))
|
||||
label = "Decrease";
|
||||
else if (iconClass.includes("close") || iconClass.includes("x"))
|
||||
label = "Close";
|
||||
|
||||
btn.setAttribute("aria-label", label);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Improve keyboard navigation
|
||||
improveKeyboardNav() {
|
||||
// Dropdown keyboard support
|
||||
document.querySelectorAll("[data-dropdown-toggle]").forEach((toggle) => {
|
||||
toggle.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.preventDefault();
|
||||
toggle.click();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Product card keyboard navigation
|
||||
document.querySelectorAll(".product-card").forEach((card) => {
|
||||
const link = card.querySelector("a");
|
||||
if (link) {
|
||||
card.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Enter" && e.target === card) {
|
||||
link.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Quantity input keyboard support
|
||||
document.querySelectorAll(".quantity-input").forEach((input) => {
|
||||
input.addEventListener("keydown", (e) => {
|
||||
if (e.key === "ArrowUp") {
|
||||
e.preventDefault();
|
||||
const newValue = parseInt(input.value || 1) + 1;
|
||||
if (newValue <= 99) {
|
||||
input.value = newValue;
|
||||
input.dispatchEvent(new Event("change"));
|
||||
}
|
||||
} else if (e.key === "ArrowDown") {
|
||||
e.preventDefault();
|
||||
const newValue = parseInt(input.value || 1) - 1;
|
||||
if (newValue >= 1) {
|
||||
input.value = newValue;
|
||||
input.dispatchEvent(new Event("change"));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// Add live regions for dynamic content
|
||||
addLiveRegions() {
|
||||
// Create announcement region
|
||||
if (!document.querySelector("#a11y-announcements")) {
|
||||
const announcer = document.createElement("div");
|
||||
announcer.id = "a11y-announcements";
|
||||
announcer.setAttribute("role", "status");
|
||||
announcer.setAttribute("aria-live", "polite");
|
||||
announcer.setAttribute("aria-atomic", "true");
|
||||
announcer.className = "sr-only";
|
||||
document.body.appendChild(announcer);
|
||||
}
|
||||
|
||||
// Announce cart/wishlist updates
|
||||
window.addEventListener("cart-updated", (e) => {
|
||||
this.announce(`Cart updated. ${e.detail.length} items in cart.`);
|
||||
});
|
||||
|
||||
window.addEventListener("wishlist-updated", (e) => {
|
||||
this.announce(
|
||||
`Wishlist updated. ${e.detail.length} items in wishlist.`
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
announce(message) {
|
||||
const announcer = document.querySelector("#a11y-announcements");
|
||||
if (announcer) {
|
||||
announcer.textContent = "";
|
||||
setTimeout(() => {
|
||||
announcer.textContent = message;
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
|
||||
// Enhance form accessibility
|
||||
enhanceFormAccessibility() {
|
||||
// Add required indicators
|
||||
document
|
||||
.querySelectorAll(
|
||||
"input[required], select[required], textarea[required]"
|
||||
)
|
||||
.forEach((field) => {
|
||||
const label = document.querySelector(`label[for="${field.id}"]`);
|
||||
if (label && !label.querySelector(".required-indicator")) {
|
||||
const indicator = document.createElement("span");
|
||||
indicator.className = "required-indicator";
|
||||
indicator.textContent = " *";
|
||||
indicator.setAttribute("aria-label", "required");
|
||||
label.appendChild(indicator);
|
||||
}
|
||||
});
|
||||
|
||||
// Add error message associations
|
||||
document.querySelectorAll(".error-message").forEach((error, index) => {
|
||||
if (!error.id) {
|
||||
error.id = `error-${index}`;
|
||||
}
|
||||
|
||||
const field = error.previousElementSibling;
|
||||
if (
|
||||
field &&
|
||||
(field.tagName === "INPUT" ||
|
||||
field.tagName === "SELECT" ||
|
||||
field.tagName === "TEXTAREA")
|
||||
) {
|
||||
field.setAttribute("aria-describedby", error.id);
|
||||
field.setAttribute("aria-invalid", "true");
|
||||
}
|
||||
});
|
||||
|
||||
// Add autocomplete attributes
|
||||
document.querySelectorAll('input[type="email"]').forEach((field) => {
|
||||
if (!field.hasAttribute("autocomplete")) {
|
||||
field.setAttribute("autocomplete", "email");
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelectorAll('input[type="tel"]').forEach((field) => {
|
||||
if (!field.hasAttribute("autocomplete")) {
|
||||
field.setAttribute("autocomplete", "tel");
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// Initialize on DOM ready
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", () => A11y.init());
|
||||
} else {
|
||||
A11y.init();
|
||||
}
|
||||
|
||||
// Export for external use
|
||||
window.A11y = A11y;
|
||||
})();
|
||||
@@ -84,7 +84,8 @@
|
||||
closeId: "cartClose",
|
||||
wrapperClass: ".cart-dropdown-wrapper",
|
||||
eventName: "cart-updated",
|
||||
emptyMessage: '<p class="empty-state"><i class="bi bi-cart-x"></i><br>Your cart is empty</p>'
|
||||
emptyMessage:
|
||||
'<p class="empty-state"><i class="bi bi-cart-x"></i><br>Your cart is empty</p>',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -97,9 +98,10 @@
|
||||
}
|
||||
|
||||
const cart = window.AppState.cart;
|
||||
|
||||
|
||||
if (!Array.isArray(cart)) {
|
||||
this.content.innerHTML = '<p class="empty-state">Error loading cart</p>';
|
||||
this.content.innerHTML =
|
||||
'<p class="empty-state">Error loading cart</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -115,19 +117,24 @@
|
||||
this.updateFooter(null);
|
||||
return;
|
||||
}
|
||||
|
||||
this.content.innerHTML = validItems.map(item => this.renderCartItem(item)).join("");
|
||||
|
||||
this.content.innerHTML = validItems
|
||||
.map((item) => this.renderCartItem(item))
|
||||
.join("");
|
||||
this.setupCartItemListeners();
|
||||
|
||||
|
||||
const total = this._calculateTotal(validItems);
|
||||
this.updateFooter(total);
|
||||
} catch (error) {
|
||||
this.content.innerHTML = '<p class="empty-state">Error loading cart</p>';
|
||||
this.content.innerHTML =
|
||||
'<p class="empty-state">Error loading cart</p>';
|
||||
}
|
||||
}
|
||||
|
||||
_filterValidItems(items) {
|
||||
return items.filter(item => item && item.id && typeof item.price !== 'undefined');
|
||||
return items.filter(
|
||||
(item) => item && item.id && typeof item.price !== "undefined"
|
||||
);
|
||||
}
|
||||
|
||||
_calculateTotal(items) {
|
||||
@@ -137,7 +144,7 @@
|
||||
return items.reduce((sum, item) => {
|
||||
const price = parseFloat(item.price) || 0;
|
||||
const quantity = parseInt(item.quantity) || 0;
|
||||
return sum + (price * quantity);
|
||||
return sum + price * quantity;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
@@ -145,13 +152,13 @@
|
||||
try {
|
||||
// Validate item and Utils availability
|
||||
if (!item || !item.id) {
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
if (!window.Utils) {
|
||||
return '<p class="error-message">Error loading item</p>';
|
||||
}
|
||||
|
||||
|
||||
// Sanitize and validate item data with defensive checks
|
||||
const imageUrl =
|
||||
item.imageurl ||
|
||||
@@ -164,7 +171,7 @@
|
||||
const price = parseFloat(item.price) || 0;
|
||||
const quantity = Math.max(1, parseInt(item.quantity) || 1);
|
||||
const subtotal = price * quantity;
|
||||
|
||||
|
||||
const priceFormatted = window.Utils.formatCurrency(price);
|
||||
const subtotalFormatted = window.Utils.formatCurrency(subtotal);
|
||||
|
||||
@@ -191,7 +198,7 @@
|
||||
</div>
|
||||
`;
|
||||
} catch (error) {
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,19 +238,20 @@
|
||||
this._handleAction(e, () => {
|
||||
const id = e.currentTarget.dataset.id;
|
||||
if (!window.AppState?.cart) return;
|
||||
|
||||
|
||||
const item = window.AppState.cart.find(
|
||||
(item) => String(item.id) === String(id)
|
||||
);
|
||||
|
||||
|
||||
if (!item || !window.AppState.updateCartQuantity) return;
|
||||
|
||||
const newQuantity = delta > 0
|
||||
? Math.min(item.quantity + delta, 999)
|
||||
: Math.max(item.quantity + delta, 1);
|
||||
|
||||
|
||||
const newQuantity =
|
||||
delta > 0
|
||||
? Math.min(item.quantity + delta, 999)
|
||||
: Math.max(item.quantity + delta, 1);
|
||||
|
||||
if (delta < 0 && item.quantity <= 1) return;
|
||||
|
||||
|
||||
window.AppState.updateCartQuantity(id, newQuantity);
|
||||
this.render();
|
||||
});
|
||||
@@ -291,28 +299,10 @@
|
||||
closeId: "wishlistClose",
|
||||
wrapperClass: ".wishlist-dropdown-wrapper",
|
||||
eventName: "wishlist-updated",
|
||||
emptyMessage: '<p class="empty-state"><i class="bi bi-heart"></i><br>Your wishlist is empty</p>'
|
||||
emptyMessage:
|
||||
'<p class="empty-state"><i class="bi bi-heart"></i><br>Your wishlist is empty</p>',
|
||||
});
|
||||
}
|
||||
this.isOpen ? this.close() : this.open();
|
||||
}
|
||||
|
||||
open() {
|
||||
if (this.wishlistPanel) {
|
||||
this.wishlistPanel.classList.add("active");
|
||||
this.wishlistPanel.setAttribute("aria-hidden", "false");
|
||||
this.isOpen = true;
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.wishlistPanel) {
|
||||
this.wishlistPanel.classList.remove("active");
|
||||
this.wishlistPanel.setAttribute("aria-hidden", "true");
|
||||
this.isOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.content) return;
|
||||
|
||||
818
website/public/assets/js/main-enhanced.js
Normal file
818
website/public/assets/js/main-enhanced.js
Normal file
@@ -0,0 +1,818 @@
|
||||
/**
|
||||
* Enhanced Main Application JavaScript
|
||||
* Production-Ready with No Console Errors
|
||||
* Proper State Management & API Integration
|
||||
*/
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
// Production mode check
|
||||
const isDevelopment =
|
||||
window.location.hostname === "localhost" ||
|
||||
window.location.hostname === "127.0.0.1";
|
||||
|
||||
// Safe console wrapper
|
||||
const logger = {
|
||||
log: (...args) => isDevelopment && console.log(...args),
|
||||
error: (...args) => console.error(...args),
|
||||
warn: (...args) => isDevelopment && console.warn(...args),
|
||||
info: (...args) => isDevelopment && console.info(...args),
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// GLOBAL STATE MANAGEMENT
|
||||
// ========================================
|
||||
window.AppState = {
|
||||
cart: [],
|
||||
wishlist: [],
|
||||
products: [],
|
||||
settings: null,
|
||||
user: null,
|
||||
_saveCartTimeout: null,
|
||||
_saveWishlistTimeout: null,
|
||||
_initialized: false,
|
||||
|
||||
// Initialize state
|
||||
init() {
|
||||
if (this._initialized) {
|
||||
logger.warn("[AppState] Already initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("[AppState] Initializing...");
|
||||
this.loadCart();
|
||||
this.loadWishlist();
|
||||
this.updateUI();
|
||||
this._initialized = true;
|
||||
logger.info(
|
||||
"[AppState] Initialized - Cart:",
|
||||
this.cart.length,
|
||||
"items, Wishlist:",
|
||||
this.wishlist.length,
|
||||
"items"
|
||||
);
|
||||
|
||||
// Dispatch ready event
|
||||
window.dispatchEvent(new CustomEvent("appstate-ready"));
|
||||
},
|
||||
|
||||
// ========================================
|
||||
// CART MANAGEMENT
|
||||
// ========================================
|
||||
loadCart() {
|
||||
try {
|
||||
const saved = localStorage.getItem("cart");
|
||||
this.cart = saved ? JSON.parse(saved) : [];
|
||||
|
||||
// Validate cart items
|
||||
this.cart = this.cart.filter((item) => item && item.id && item.price);
|
||||
} catch (error) {
|
||||
logger.error("Error loading cart:", error);
|
||||
this.cart = [];
|
||||
}
|
||||
},
|
||||
|
||||
saveCart() {
|
||||
if (this._saveCartTimeout) {
|
||||
clearTimeout(this._saveCartTimeout);
|
||||
}
|
||||
|
||||
this._saveCartTimeout = setTimeout(() => {
|
||||
try {
|
||||
localStorage.setItem("cart", JSON.stringify(this.cart));
|
||||
this.updateUI();
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("cart-updated", { detail: this.cart })
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error("Error saving cart:", error);
|
||||
this.showNotification("Error saving cart", "error");
|
||||
}
|
||||
}, 100);
|
||||
},
|
||||
|
||||
addToCart(product, quantity = 1) {
|
||||
if (!product || !product.id) {
|
||||
logger.error("[AppState] Invalid product:", product);
|
||||
this.showNotification("Invalid product", "error");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const existing = this.cart.find((item) => item.id === product.id);
|
||||
if (existing) {
|
||||
existing.quantity = (existing.quantity || 1) + quantity;
|
||||
logger.info("[AppState] Updated cart quantity:", existing);
|
||||
} else {
|
||||
this.cart.push({
|
||||
...product,
|
||||
quantity,
|
||||
addedAt: new Date().toISOString(),
|
||||
});
|
||||
logger.info("[AppState] Added to cart:", product.name);
|
||||
}
|
||||
|
||||
this.saveCart();
|
||||
this.showNotification(
|
||||
`${product.name || "Item"} added to cart`,
|
||||
"success"
|
||||
);
|
||||
return true;
|
||||
} catch (error) {
|
||||
logger.error("[AppState] Error adding to cart:", error);
|
||||
this.showNotification("Error adding to cart", "error");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
removeFromCart(productId) {
|
||||
if (!productId) {
|
||||
logger.error("[AppState] Invalid productId");
|
||||
return false;
|
||||
}
|
||||
|
||||
const initialLength = this.cart.length;
|
||||
this.cart = this.cart.filter((item) => item.id !== productId);
|
||||
|
||||
if (this.cart.length < initialLength) {
|
||||
this.saveCart();
|
||||
this.showNotification("Removed from cart", "info");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
updateCartQuantity(productId, quantity) {
|
||||
const item = this.cart.find((item) => item.id === productId);
|
||||
if (item) {
|
||||
item.quantity = Math.max(1, parseInt(quantity) || 1);
|
||||
this.saveCart();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
clearCart() {
|
||||
this.cart = [];
|
||||
this.saveCart();
|
||||
this.showNotification("Cart cleared", "info");
|
||||
},
|
||||
|
||||
getCartTotal() {
|
||||
return this.cart.reduce((sum, item) => {
|
||||
const price = parseFloat(item.price) || 0;
|
||||
const quantity = parseInt(item.quantity) || 1;
|
||||
return sum + price * quantity;
|
||||
}, 0);
|
||||
},
|
||||
|
||||
getCartCount() {
|
||||
return this.cart.reduce(
|
||||
(sum, item) => sum + (parseInt(item.quantity) || 1),
|
||||
0
|
||||
);
|
||||
},
|
||||
|
||||
// ========================================
|
||||
// WISHLIST MANAGEMENT
|
||||
// ========================================
|
||||
loadWishlist() {
|
||||
try {
|
||||
const saved = localStorage.getItem("wishlist");
|
||||
this.wishlist = saved ? JSON.parse(saved) : [];
|
||||
|
||||
// Validate wishlist items
|
||||
this.wishlist = this.wishlist.filter((item) => item && item.id);
|
||||
} catch (error) {
|
||||
logger.error("Error loading wishlist:", error);
|
||||
this.wishlist = [];
|
||||
}
|
||||
},
|
||||
|
||||
saveWishlist() {
|
||||
if (this._saveWishlistTimeout) {
|
||||
clearTimeout(this._saveWishlistTimeout);
|
||||
}
|
||||
|
||||
this._saveWishlistTimeout = setTimeout(() => {
|
||||
try {
|
||||
localStorage.setItem("wishlist", JSON.stringify(this.wishlist));
|
||||
this.updateUI();
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("wishlist-updated", { detail: this.wishlist })
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error("Error saving wishlist:", error);
|
||||
}
|
||||
}, 100);
|
||||
},
|
||||
|
||||
addToWishlist(product) {
|
||||
if (!product || !product.id) {
|
||||
logger.error("[AppState] Invalid product:", product);
|
||||
this.showNotification("Invalid product", "error");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const exists = this.wishlist.some((item) => item.id === product.id);
|
||||
if (exists) {
|
||||
this.showNotification("Already in wishlist", "info");
|
||||
return false;
|
||||
}
|
||||
|
||||
this.wishlist.push({
|
||||
...product,
|
||||
addedAt: new Date().toISOString(),
|
||||
});
|
||||
this.saveWishlist();
|
||||
this.showNotification(
|
||||
`${product.name || "Item"} added to wishlist`,
|
||||
"success"
|
||||
);
|
||||
return true;
|
||||
} catch (error) {
|
||||
logger.error("[AppState] Error adding to wishlist:", error);
|
||||
this.showNotification("Error adding to wishlist", "error");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
removeFromWishlist(productId) {
|
||||
if (!productId) return false;
|
||||
|
||||
const initialLength = this.wishlist.length;
|
||||
this.wishlist = this.wishlist.filter((item) => item.id !== productId);
|
||||
|
||||
if (this.wishlist.length < initialLength) {
|
||||
this.saveWishlist();
|
||||
this.showNotification("Removed from wishlist", "info");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
isInWishlist(productId) {
|
||||
return this.wishlist.some((item) => item.id === productId);
|
||||
},
|
||||
|
||||
getWishlistCount() {
|
||||
return this.wishlist.length;
|
||||
},
|
||||
|
||||
// ========================================
|
||||
// UI UPDATES
|
||||
// ========================================
|
||||
updateUI() {
|
||||
this.updateCartBadge();
|
||||
this.updateWishlistBadge();
|
||||
this.updateCartDropdown();
|
||||
this.updateWishlistDropdown();
|
||||
},
|
||||
|
||||
updateCartBadge() {
|
||||
const badges = document.querySelectorAll(
|
||||
".cart-count, .cart-badge, #cartCount"
|
||||
);
|
||||
const count = this.getCartCount();
|
||||
|
||||
badges.forEach((badge) => {
|
||||
badge.textContent = count;
|
||||
if (count > 0) {
|
||||
badge.classList.add("show");
|
||||
} else {
|
||||
badge.classList.remove("show");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateWishlistBadge() {
|
||||
const badges = document.querySelectorAll(
|
||||
".wishlist-count, .wishlist-badge, #wishlistCount"
|
||||
);
|
||||
const count = this.getWishlistCount();
|
||||
|
||||
badges.forEach((badge) => {
|
||||
badge.textContent = count;
|
||||
if (count > 0) {
|
||||
badge.classList.add("show");
|
||||
} else {
|
||||
badge.classList.remove("show");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateCartDropdown() {
|
||||
const container = document.querySelector("#cart-items");
|
||||
if (!container) return;
|
||||
|
||||
if (this.cart.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<i class="bi bi-cart-x"></i>
|
||||
<p>Your cart is empty</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const totalEl = document.querySelector(".cart-total-value");
|
||||
if (totalEl) totalEl.textContent = "$0.00";
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = this.cart
|
||||
.map((item) => this.renderCartItem(item))
|
||||
.join("");
|
||||
|
||||
const totalEl = document.querySelector(".cart-total-value");
|
||||
if (totalEl) {
|
||||
totalEl.textContent = `$${this.getCartTotal().toFixed(2)}`;
|
||||
}
|
||||
|
||||
this.attachCartEventListeners();
|
||||
},
|
||||
|
||||
updateWishlistDropdown() {
|
||||
const container = document.querySelector("#wishlist-items");
|
||||
if (!container) return;
|
||||
|
||||
if (this.wishlist.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<i class="bi bi-heart"></i>
|
||||
<p>Your wishlist is empty</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = this.wishlist
|
||||
.map((item) => this.renderWishlistItem(item))
|
||||
.join("");
|
||||
this.attachWishlistEventListeners();
|
||||
},
|
||||
|
||||
renderCartItem(item) {
|
||||
const price = parseFloat(item.price) || 0;
|
||||
const quantity = parseInt(item.quantity) || 1;
|
||||
const imageUrl = this.getProductImage(item);
|
||||
const name = this.sanitizeHTML(item.name || "Product");
|
||||
|
||||
return `
|
||||
<div class="cart-item" data-product-id="${item.id}">
|
||||
<div class="cart-item-image">
|
||||
<img src="${imageUrl}" alt="${name}" loading="lazy" onerror="this.src='/assets/img/placeholder.jpg'">
|
||||
</div>
|
||||
<div class="cart-item-info">
|
||||
<div class="cart-item-title">${name}</div>
|
||||
<div class="cart-item-price">$${price.toFixed(2)}</div>
|
||||
<div class="cart-item-controls">
|
||||
<button class="btn-quantity" data-action="decrease" aria-label="Decrease quantity">
|
||||
<i class="bi bi-dash"></i>
|
||||
</button>
|
||||
<input type="number" class="quantity-input" value="${quantity}" min="1" max="99" aria-label="Quantity">
|
||||
<button class="btn-quantity" data-action="increase" aria-label="Increase quantity">
|
||||
<i class="bi bi-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn-remove" data-action="remove" aria-label="Remove from cart">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
|
||||
renderWishlistItem(item) {
|
||||
const price = parseFloat(item.price) || 0;
|
||||
const imageUrl = this.getProductImage(item);
|
||||
const name = this.sanitizeHTML(item.name || "Product");
|
||||
|
||||
return `
|
||||
<div class="wishlist-item" data-product-id="${item.id}">
|
||||
<div class="wishlist-item-image">
|
||||
<img src="${imageUrl}" alt="${name}" loading="lazy" onerror="this.src='/assets/img/placeholder.jpg'">
|
||||
</div>
|
||||
<div class="wishlist-item-info">
|
||||
<div class="wishlist-item-title">${name}</div>
|
||||
<div class="wishlist-item-price">$${price.toFixed(2)}</div>
|
||||
<button class="btn-add-to-cart" data-product-id="${item.id}">
|
||||
<i class="bi bi-cart-plus"></i> Add to Cart
|
||||
</button>
|
||||
</div>
|
||||
<button class="btn-remove" data-action="remove" aria-label="Remove from wishlist">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
|
||||
attachCartEventListeners() {
|
||||
document.querySelectorAll(".cart-item").forEach((item) => {
|
||||
const productId = item.dataset.productId;
|
||||
|
||||
// Quantity controls
|
||||
const decreaseBtn = item.querySelector('[data-action="decrease"]');
|
||||
const increaseBtn = item.querySelector('[data-action="increase"]');
|
||||
const quantityInput = item.querySelector(".quantity-input");
|
||||
|
||||
if (decreaseBtn) {
|
||||
decreaseBtn.addEventListener("click", () => {
|
||||
const currentQty = parseInt(quantityInput.value) || 1;
|
||||
if (currentQty > 1) {
|
||||
quantityInput.value = currentQty - 1;
|
||||
this.updateCartQuantity(productId, currentQty - 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (increaseBtn) {
|
||||
increaseBtn.addEventListener("click", () => {
|
||||
const currentQty = parseInt(quantityInput.value) || 1;
|
||||
if (currentQty < 99) {
|
||||
quantityInput.value = currentQty + 1;
|
||||
this.updateCartQuantity(productId, currentQty + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (quantityInput) {
|
||||
quantityInput.addEventListener("change", (e) => {
|
||||
const newQty = parseInt(e.target.value) || 1;
|
||||
this.updateCartQuantity(productId, newQty);
|
||||
});
|
||||
}
|
||||
|
||||
// Remove button
|
||||
const removeBtn = item.querySelector('[data-action="remove"]');
|
||||
if (removeBtn) {
|
||||
removeBtn.addEventListener("click", () => {
|
||||
this.removeFromCart(productId);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
attachWishlistEventListeners() {
|
||||
document.querySelectorAll(".wishlist-item").forEach((item) => {
|
||||
const productId = item.dataset.productId;
|
||||
|
||||
// Add to cart button
|
||||
const addBtn = item.querySelector(".btn-add-to-cart");
|
||||
if (addBtn) {
|
||||
addBtn.addEventListener("click", () => {
|
||||
const product = this.wishlist.find((p) => p.id === productId);
|
||||
if (product) {
|
||||
this.addToCart(product);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Remove button
|
||||
const removeBtn = item.querySelector('[data-action="remove"]');
|
||||
if (removeBtn) {
|
||||
removeBtn.addEventListener("click", () => {
|
||||
this.removeFromWishlist(productId);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// ========================================
|
||||
// NOTIFICATIONS
|
||||
// ========================================
|
||||
showNotification(message, type = "info") {
|
||||
if (!message) return;
|
||||
|
||||
let container = document.querySelector(".notification-container");
|
||||
|
||||
if (!container) {
|
||||
container = document.createElement("div");
|
||||
container.className = "notification-container";
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
|
||||
const notification = document.createElement("div");
|
||||
notification.className = `notification ${type}`;
|
||||
|
||||
const icon =
|
||||
type === "success"
|
||||
? "check-circle-fill"
|
||||
: type === "error"
|
||||
? "exclamation-circle-fill"
|
||||
: "info-circle-fill";
|
||||
|
||||
notification.innerHTML = `
|
||||
<i class="bi bi-${icon}"></i>
|
||||
<span class="notification-message">${this.sanitizeHTML(message)}</span>
|
||||
`;
|
||||
|
||||
container.appendChild(notification);
|
||||
|
||||
setTimeout(() => {
|
||||
notification.style.animation = "slideOut 0.3s ease forwards";
|
||||
setTimeout(() => notification.remove(), 300);
|
||||
}, 3000);
|
||||
},
|
||||
|
||||
// ========================================
|
||||
// API INTEGRATION
|
||||
// ========================================
|
||||
async fetchProducts() {
|
||||
try {
|
||||
const response = await fetch("/api/products");
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||
|
||||
const data = await response.json();
|
||||
if (data.success && Array.isArray(data.products)) {
|
||||
this.products = data.products;
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("products-loaded", { detail: this.products })
|
||||
);
|
||||
return this.products;
|
||||
}
|
||||
|
||||
throw new Error("Invalid API response");
|
||||
} catch (error) {
|
||||
logger.error("Error fetching products:", error);
|
||||
this.showNotification("Error loading products", "error");
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
async fetchSettings() {
|
||||
try {
|
||||
const response = await fetch("/api/settings");
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||
|
||||
const data = await response.json();
|
||||
if (data.success && data.settings) {
|
||||
this.settings = data.settings;
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("settings-loaded", { detail: this.settings })
|
||||
);
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
throw new Error("Invalid API response");
|
||||
} catch (error) {
|
||||
logger.error("Error fetching settings:", error);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
// ========================================
|
||||
// UTILITY METHODS
|
||||
// ========================================
|
||||
getProductImage(product) {
|
||||
if (!product) return "/assets/img/placeholder.jpg";
|
||||
|
||||
// Check various image properties
|
||||
if (product.image_url) return product.image_url;
|
||||
if (product.imageUrl) return product.imageUrl;
|
||||
if (
|
||||
product.images &&
|
||||
Array.isArray(product.images) &&
|
||||
product.images.length > 0
|
||||
) {
|
||||
return (
|
||||
product.images[0].image_url ||
|
||||
product.images[0].url ||
|
||||
"/assets/img/placeholder.jpg"
|
||||
);
|
||||
}
|
||||
if (product.thumbnail) return product.thumbnail;
|
||||
|
||||
return "/assets/img/placeholder.jpg";
|
||||
},
|
||||
|
||||
sanitizeHTML(str) {
|
||||
if (!str) return "";
|
||||
const div = document.createElement("div");
|
||||
div.textContent = str;
|
||||
return div.innerHTML;
|
||||
},
|
||||
|
||||
formatPrice(price) {
|
||||
const num = parseFloat(price) || 0;
|
||||
return `$${num.toFixed(2)}`;
|
||||
},
|
||||
|
||||
debounce(func, wait) {
|
||||
let timeout;
|
||||
return function executedFunction(...args) {
|
||||
const later = () => {
|
||||
clearTimeout(timeout);
|
||||
func(...args);
|
||||
};
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// DROPDOWN MANAGEMENT
|
||||
// ========================================
|
||||
window.DropdownManager = {
|
||||
activeDropdown: null,
|
||||
|
||||
init() {
|
||||
this.attachEventListeners();
|
||||
logger.info("[DropdownManager] Initialized");
|
||||
},
|
||||
|
||||
attachEventListeners() {
|
||||
// Cart toggle
|
||||
const cartBtn = document.querySelector("#cart-btn");
|
||||
if (cartBtn) {
|
||||
cartBtn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
this.toggle("cart");
|
||||
});
|
||||
}
|
||||
|
||||
// Wishlist toggle
|
||||
const wishlistBtn = document.querySelector("#wishlist-btn");
|
||||
if (wishlistBtn) {
|
||||
wishlistBtn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
this.toggle("wishlist");
|
||||
});
|
||||
}
|
||||
|
||||
// Close on outside click
|
||||
document.addEventListener("click", (e) => {
|
||||
if (!e.target.closest(".dropdown") && !e.target.closest(".icon-btn")) {
|
||||
this.closeAll();
|
||||
}
|
||||
});
|
||||
|
||||
// Close on escape key
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape") {
|
||||
this.closeAll();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
toggle(type) {
|
||||
const dropdown = document.querySelector(`#${type}-dropdown`);
|
||||
if (!dropdown) return;
|
||||
|
||||
if (this.activeDropdown === dropdown) {
|
||||
this.close(dropdown);
|
||||
} else {
|
||||
this.closeAll();
|
||||
this.open(dropdown, type);
|
||||
}
|
||||
},
|
||||
|
||||
open(dropdown, type) {
|
||||
dropdown.style.display = "flex";
|
||||
this.activeDropdown = dropdown;
|
||||
|
||||
// Update content
|
||||
if (type === "cart") {
|
||||
window.AppState.updateCartDropdown();
|
||||
} else if (type === "wishlist") {
|
||||
window.AppState.updateWishlistDropdown();
|
||||
}
|
||||
},
|
||||
|
||||
close(dropdown) {
|
||||
if (dropdown) {
|
||||
dropdown.style.display = "none";
|
||||
}
|
||||
this.activeDropdown = null;
|
||||
},
|
||||
|
||||
closeAll() {
|
||||
document.querySelectorAll(".dropdown").forEach((dropdown) => {
|
||||
dropdown.style.display = "none";
|
||||
});
|
||||
this.activeDropdown = null;
|
||||
},
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// MOBILE MENU
|
||||
// ========================================
|
||||
window.MobileMenu = {
|
||||
menu: null,
|
||||
overlay: null,
|
||||
isOpen: false,
|
||||
|
||||
init() {
|
||||
this.menu = document.querySelector(".mobile-menu");
|
||||
this.overlay = document.querySelector(".mobile-menu-overlay");
|
||||
|
||||
if (!this.menu || !this.overlay) {
|
||||
logger.warn("[MobileMenu] Elements not found");
|
||||
return;
|
||||
}
|
||||
|
||||
this.attachEventListeners();
|
||||
logger.info("[MobileMenu] Initialized");
|
||||
},
|
||||
|
||||
attachEventListeners() {
|
||||
// Toggle button
|
||||
const toggleBtn = document.querySelector(".mobile-menu-toggle");
|
||||
if (toggleBtn) {
|
||||
toggleBtn.addEventListener("click", () => this.toggle());
|
||||
}
|
||||
|
||||
// Close button
|
||||
const closeBtn = document.querySelector(".mobile-menu-close");
|
||||
if (closeBtn) {
|
||||
closeBtn.addEventListener("click", () => this.close());
|
||||
}
|
||||
|
||||
// Overlay click
|
||||
if (this.overlay) {
|
||||
this.overlay.addEventListener("click", () => this.close());
|
||||
}
|
||||
|
||||
// Menu links
|
||||
this.menu.querySelectorAll("a").forEach((link) => {
|
||||
link.addEventListener("click", () => {
|
||||
setTimeout(() => this.close(), 100);
|
||||
});
|
||||
});
|
||||
|
||||
// Escape key
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape" && this.isOpen) {
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
toggle() {
|
||||
this.isOpen ? this.close() : this.open();
|
||||
},
|
||||
|
||||
open() {
|
||||
this.menu.classList.add("active");
|
||||
this.overlay.classList.add("active");
|
||||
this.isOpen = true;
|
||||
document.body.style.overflow = "hidden";
|
||||
},
|
||||
|
||||
close() {
|
||||
this.menu.classList.remove("active");
|
||||
this.overlay.classList.remove("active");
|
||||
this.isOpen = false;
|
||||
document.body.style.overflow = "";
|
||||
},
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// INITIALIZATION
|
||||
// ========================================
|
||||
function initialize() {
|
||||
logger.info("[App] Initializing...");
|
||||
|
||||
// Initialize state
|
||||
if (window.AppState) {
|
||||
window.AppState.init();
|
||||
}
|
||||
|
||||
// Initialize dropdown manager
|
||||
if (window.DropdownManager) {
|
||||
window.DropdownManager.init();
|
||||
}
|
||||
|
||||
// Initialize mobile menu
|
||||
if (window.MobileMenu) {
|
||||
window.MobileMenu.init();
|
||||
}
|
||||
|
||||
// Fetch initial data
|
||||
if (window.AppState.fetchSettings) {
|
||||
window.AppState.fetchSettings();
|
||||
}
|
||||
|
||||
logger.info("[App] Initialization complete");
|
||||
}
|
||||
|
||||
// Run on DOM ready
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", initialize);
|
||||
} else {
|
||||
initialize();
|
||||
}
|
||||
|
||||
// Export for debugging in development
|
||||
if (isDevelopment) {
|
||||
window.DEBUG = {
|
||||
AppState: window.AppState,
|
||||
DropdownManager: window.DropdownManager,
|
||||
MobileMenu: window.MobileMenu,
|
||||
logger,
|
||||
};
|
||||
}
|
||||
})();
|
||||
@@ -6,7 +6,7 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
console.log('[main.js] Loading...');
|
||||
console.log("[main.js] Loading...");
|
||||
|
||||
// Global state management
|
||||
window.AppState = {
|
||||
@@ -20,12 +20,18 @@
|
||||
|
||||
// Initialize state from localStorage
|
||||
init() {
|
||||
console.log('[AppState] Initializing...');
|
||||
console.log('[AppState] window.AppState exists:', !!window.AppState);
|
||||
console.log("[AppState] Initializing...");
|
||||
console.log("[AppState] window.AppState exists:", !!window.AppState);
|
||||
this.loadCart();
|
||||
this.loadWishlist();
|
||||
this.updateUI();
|
||||
console.log('[AppState] Initialized - Cart:', this.cart.length, 'items, Wishlist:', this.wishlist.length, 'items');
|
||||
console.log(
|
||||
"[AppState] Initialized - Cart:",
|
||||
this.cart.length,
|
||||
"items, Wishlist:",
|
||||
this.wishlist.length,
|
||||
"items"
|
||||
);
|
||||
},
|
||||
|
||||
// Cart management
|
||||
@@ -55,18 +61,26 @@
|
||||
},
|
||||
|
||||
addToCart(product, quantity = 1) {
|
||||
console.log('[AppState] addToCart called:', product, 'quantity:', quantity);
|
||||
console.log(
|
||||
"[AppState] addToCart called:",
|
||||
product,
|
||||
"quantity:",
|
||||
quantity
|
||||
);
|
||||
const existing = this.cart.find((item) => item.id === product.id);
|
||||
if (existing) {
|
||||
console.log('[AppState] Product exists in cart, updating quantity');
|
||||
console.log("[AppState] Product exists in cart, updating quantity");
|
||||
existing.quantity += quantity;
|
||||
} else {
|
||||
console.log('[AppState] Adding new product to cart');
|
||||
console.log("[AppState] Adding new product to cart");
|
||||
this.cart.push({ ...product, quantity });
|
||||
}
|
||||
console.log('[AppState] Cart after add:', this.cart);
|
||||
console.log("[AppState] Cart after add:", this.cart);
|
||||
this.saveCart();
|
||||
this.showNotification(`${product.name || product.title || 'Item'} added to cart`, "success");
|
||||
this.showNotification(
|
||||
`${product.name || product.title || "Item"} added to cart`,
|
||||
"success"
|
||||
);
|
||||
},
|
||||
|
||||
removeFromCart(productId) {
|
||||
@@ -77,9 +91,11 @@
|
||||
|
||||
updateCartQuantity(productId, quantity) {
|
||||
const item = this.cart.find((item) => item.id === productId);
|
||||
|
||||
// Dispatch custom event for cart dropdown
|
||||
window.dispatchEvent(new CustomEvent('cart-updated', { detail: this.cart }));
|
||||
|
||||
// Dispatch custom event for cart dropdown
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("cart-updated", { detail: this.cart })
|
||||
);
|
||||
if (item) {
|
||||
item.quantity = Math.max(1, quantity);
|
||||
this.saveCart();
|
||||
@@ -118,18 +134,20 @@
|
||||
},
|
||||
|
||||
addToWishlist(product) {
|
||||
if (!this.wishlist.find(`${product.name || product.title || 'Item'} added to wishlist`, "success");
|
||||
|
||||
// Dispatch custom event for wishlist dropdown
|
||||
window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: this.wishlist }));
|
||||
} else {
|
||||
this.showNotification("Already in wishlist", "info.id)) {
|
||||
if (!this.wishlist.find((item) => item.id === product.id)) {
|
||||
this.wishlist.push(product);
|
||||
this.saveWishlist();
|
||||
|
||||
// Dispatch custom event for wishlist dropdown
|
||||
window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: this.wishlist }));
|
||||
this.showNotification("Added to wishlist", "success");
|
||||
this.showNotification(
|
||||
`${product.name || product.title || "Item"} added to wishlist`,
|
||||
"success"
|
||||
);
|
||||
|
||||
// Dispatch custom event for wishlist dropdown
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("wishlist-updated", { detail: this.wishlist })
|
||||
);
|
||||
} else {
|
||||
this.showNotification("Already in wishlist", "info");
|
||||
}
|
||||
},
|
||||
|
||||
@@ -151,32 +169,44 @@
|
||||
|
||||
updateCartUI() {
|
||||
const count = this.getCartCount();
|
||||
console.log('[AppState] Updating cart UI, count:', count);
|
||||
console.log("[AppState] Updating cart UI, count:", count);
|
||||
const badge = document.getElementById("cartCount");
|
||||
if (badge) {
|
||||
badge.textContent = count;
|
||||
badge.style.display = count > 0 ? "flex" : "none";
|
||||
console.log('[AppState] Cart badge updated');
|
||||
if (count > 0) {
|
||||
badge.classList.add("show");
|
||||
} else {
|
||||
badge.classList.remove("show");
|
||||
}
|
||||
console.log("[AppState] Cart badge updated");
|
||||
} else {
|
||||
console.warn('[AppState] Cart badge element not found');
|
||||
console.warn("[AppState] Cart badge element not found");
|
||||
}
|
||||
// Also trigger cart dropdown update
|
||||
window.dispatchEvent(new CustomEvent('cart-updated', { detail: this.cart }));
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("cart-updated", { detail: this.cart })
|
||||
);
|
||||
},
|
||||
|
||||
updateWishlistUI() {
|
||||
const count = this.wishlist.length;
|
||||
console.log('[AppState] Updating wishlist UI, count:', count);
|
||||
console.log("[AppState] Updating wishlist UI, count:", count);
|
||||
const badge = document.getElementById("wishlistCount");
|
||||
if (badge) {
|
||||
badge.textContent = count;
|
||||
badge.style.display = count > 0 ? "flex" : "none";
|
||||
console.log('[AppState] Wishlist badge updated');
|
||||
if (count > 0) {
|
||||
badge.classList.add("show");
|
||||
} else {
|
||||
badge.classList.remove("show");
|
||||
}
|
||||
console.log("[AppState] Wishlist badge updated");
|
||||
} else {
|
||||
console.warn('[AppState] Wishlist badge element not found');
|
||||
console.warn("[AppState] Wishlist badge element not found");
|
||||
}
|
||||
// Also trigger wishlist dropdown update
|
||||
window.dispatchEvent(new CustomEvent('wishlist-updated', { detail: this.wishlist }));
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("wishlist-updated", { detail: this.wishlist })
|
||||
);
|
||||
},
|
||||
|
||||
// Notifications
|
||||
@@ -341,14 +371,17 @@
|
||||
};
|
||||
|
||||
// Initialize on DOM ready
|
||||
console.log('[main.js] Script loaded, document.readyState:', document.readyState);
|
||||
console.log(
|
||||
"[main.js] Script loaded, document.readyState:",
|
||||
document.readyState
|
||||
);
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
console.log('[main.js] DOMContentLoaded fired');
|
||||
console.log("[main.js] DOMContentLoaded fired");
|
||||
window.AppState.init();
|
||||
});
|
||||
} else {
|
||||
console.log('[main.js] DOM already loaded, initializing immediately');
|
||||
console.log("[main.js] DOM already loaded, initializing immediately");
|
||||
window.AppState.init();
|
||||
}
|
||||
|
||||
|
||||
@@ -359,7 +359,11 @@
|
||||
if (cartBadge) {
|
||||
const count = this.getCartCount();
|
||||
cartBadge.textContent = count;
|
||||
cartBadge.style.display = count > 0 ? "flex" : "none";
|
||||
if (count > 0) {
|
||||
cartBadge.classList.add("show");
|
||||
} else {
|
||||
cartBadge.classList.remove("show");
|
||||
}
|
||||
}
|
||||
|
||||
// Update wishlist badge
|
||||
@@ -367,7 +371,11 @@
|
||||
if (wishlistBadge) {
|
||||
const count = this.wishlist.length;
|
||||
wishlistBadge.textContent = count;
|
||||
wishlistBadge.style.display = count > 0 ? "flex" : "none";
|
||||
if (count > 0) {
|
||||
wishlistBadge.classList.add("show");
|
||||
} else {
|
||||
wishlistBadge.classList.remove("show");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,14 +471,14 @@
|
||||
const footer = document.querySelector("#cartPanel .dropdown-foot");
|
||||
if (!footer) return;
|
||||
|
||||
if (total === 0) {
|
||||
if (total === 0 || total === null) {
|
||||
footer.innerHTML =
|
||||
'<a href="/shop" class="btn-outline">Continue Shopping</a>';
|
||||
} else {
|
||||
footer.innerHTML = `
|
||||
<div class="cart-total">
|
||||
<span>Total:</span>
|
||||
<strong>$${total.toFixed(2)}</strong>
|
||||
<strong>${window.Utils.formatCurrency(total)}</strong>
|
||||
</div>
|
||||
<a href="/shop" class="btn-text">Continue Shopping</a>
|
||||
<button class="btn-primary-full" onclick="alert('Checkout coming soon!')">
|
||||
|
||||
@@ -226,21 +226,33 @@
|
||||
|
||||
// Update badges on state changes
|
||||
window.StateManager.on("cartUpdated", () => {
|
||||
const badge = document.querySelector(".cart-badge");
|
||||
if (badge) {
|
||||
const count = window.StateManager.getCartCount();
|
||||
badge.textContent = count;
|
||||
badge.style.display = count > 0 ? "flex" : "none";
|
||||
}
|
||||
const badges = document.querySelectorAll(".cart-badge, #cartCount");
|
||||
const count = window.StateManager.getCartCount();
|
||||
badges.forEach((badge) => {
|
||||
if (badge) {
|
||||
badge.textContent = count;
|
||||
if (count > 0) {
|
||||
badge.classList.add("show");
|
||||
} else {
|
||||
badge.classList.remove("show");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
window.StateManager.on("wishlistUpdated", () => {
|
||||
const badge = document.querySelector(".wishlist-badge");
|
||||
if (badge) {
|
||||
const count = window.StateManager.getWishlist().length;
|
||||
badge.textContent = count;
|
||||
badge.style.display = count > 0 ? "flex" : "none";
|
||||
}
|
||||
const badges = document.querySelectorAll(".wishlist-badge, #wishlistCount");
|
||||
const count = window.StateManager.getWishlist().length;
|
||||
badges.forEach((badge) => {
|
||||
if (badge) {
|
||||
badge.textContent = count;
|
||||
if (count > 0) {
|
||||
badge.classList.add("show");
|
||||
} else {
|
||||
badge.classList.remove("show");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize badges
|
||||
|
||||
@@ -8,17 +8,20 @@
|
||||
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=1735692100" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css?v=1735692200" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css?v=1767233028" />
|
||||
<link rel="stylesheet" href="/assets/css/page-overrides.css?v=1736790001" />
|
||||
<link rel="stylesheet" href="/assets/css/cart-wishlist.css" />
|
||||
<link rel="stylesheet" href="/assets/css/shopping.css" />
|
||||
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
|
||||
<link rel="stylesheet" href="/assets/css/responsive.css" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar-mobile-fix.css?v=1736790000" />
|
||||
</head>
|
||||
<body>
|
||||
<script>window.__bodyReady=true</script>
|
||||
<div class="sticky-banner-wrapper">
|
||||
<!-- Modern Navigation -->
|
||||
<nav class="modern-navbar">
|
||||
<div class="navbar-wrapper">
|
||||
@@ -99,17 +102,10 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown-body" id="cartContent">
|
||||
<p class="empty-state">Your cart is empty</p>
|
||||
<p class="empty-state"><i class="bi bi-cart-x"></i><br>Your cart is empty</p>
|
||||
</div>
|
||||
<div class="dropdown-foot">
|
||||
<div class="cart-summary">
|
||||
<span class="summary-label">Subtotal:</span>
|
||||
<span class="summary-value" id="cartSubtotal">$0.00</span>
|
||||
</div>
|
||||
<a href="/checkout" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop" class="btn-text">Continue Shopping</a>
|
||||
<a href="/shop" class="btn-outline">Continue Shopping</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -138,23 +134,44 @@
|
||||
<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="
|
||||
@@ -163,7 +180,6 @@
|
||||
gap: 30px;
|
||||
"
|
||||
></div>
|
||||
<div
|
||||
id="noPosts"
|
||||
style="display: none; text-align: center; padding: 40px; color: #666"
|
||||
>
|
||||
@@ -172,12 +188,7 @@
|
||||
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>
|
||||
@@ -190,12 +201,7 @@
|
||||
><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>
|
||||
@@ -203,39 +209,25 @@
|
||||
<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>© 2025 Sky Art Shop. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<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/main.js"></script>
|
||||
<script src="/assets/js/navigation.js"></script>
|
||||
<script src="/assets/js/cart.js"></script>
|
||||
<script src="/assets/js/shop-system.js"></script>
|
||||
<script src="/assets/js/shopping.js"></script>
|
||||
<script>
|
||||
// Load blog posts from API
|
||||
async function loadBlog() {
|
||||
try {
|
||||
@@ -243,14 +235,11 @@
|
||||
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(
|
||||
@@ -275,7 +264,6 @@
|
||||
<span><i class="bi bi-calendar"></i> ${new Date(
|
||||
post.createdat
|
||||
).toLocaleDateString()}</span>
|
||||
</div>
|
||||
<h2 style="font-size: 22px; font-weight: 600; margin-bottom: 12px; color: #333; line-height: 1.3;">${
|
||||
post.title
|
||||
}</h2>
|
||||
@@ -289,24 +277,19 @@
|
||||
}" 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>
|
||||
</div>
|
||||
</article>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
} else {
|
||||
document.getElementById("loadingMessage").style.display = "none";
|
||||
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>
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
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=1735692100" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css?v=1767233028" />
|
||||
<link rel="stylesheet" href="/assets/css/page-overrides.css?v=1736790001" />
|
||||
<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/navbar-mobile-fix.css?v=1736790000"
|
||||
/>
|
||||
<style>
|
||||
@media (max-width: 768px) {
|
||||
#contactForm > div[style*="grid-template-columns"] {
|
||||
@@ -27,126 +33,135 @@
|
||||
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.__bodyReady = true;
|
||||
</script>
|
||||
<!-- 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 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">
|
||||
<div class="cart-summary">
|
||||
<span class="summary-label">Subtotal:</span>
|
||||
<span class="summary-value" id="cartSubtotal">$0.00</span>
|
||||
</div>
|
||||
<a href="/checkout" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop" class="btn-text">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="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>
|
||||
<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="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">
|
||||
<div class="cart-summary">
|
||||
<span class="summary-label">Subtotal:</span>
|
||||
<span class="summary-value" id="cartSubtotal">$0.00</span>
|
||||
</div>
|
||||
<a href="/checkout" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop" class="btn-text">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>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<!-- Contact Hero -->
|
||||
<section
|
||||
@@ -650,5 +665,6 @@
|
||||
loadContactInfo();
|
||||
}
|
||||
</script>
|
||||
<script src="/assets/js/shop-system.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -13,332 +13,4 @@
|
||||
<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" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css" />
|
||||
<link rel="stylesheet" href="/assets/css/cart-wishlist.css" />
|
||||
<link rel="stylesheet" href="/assets/css/shopping.css" />
|
||||
<style>
|
||||
.privacy-hero {
|
||||
background: linear-gradient(135deg, #f6ccde 0%, #fcb1d8 100%);
|
||||
padding: 40px 0 30px;
|
||||
color: #202023;
|
||||
text-align: center;
|
||||
}
|
||||
.privacy-hero h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 16px;
|
||||
font-weight: 700;
|
||||
color: #202023;
|
||||
}
|
||||
.privacy-hero p {
|
||||
font-size: 1.1rem;
|
||||
color: #202023;
|
||||
opacity: 0.9;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.privacy-content {
|
||||
padding: 60px 0;
|
||||
background: #ffebeb;
|
||||
}
|
||||
.privacy-text {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
padding: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(252, 177, 216, 0.2);
|
||||
line-height: 1.8;
|
||||
border: 1px solid #ffd0d0;
|
||||
}
|
||||
.privacy-text h2 {
|
||||
color: #202023;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.privacy-text h3 {
|
||||
color: #202023;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.privacy-text p {
|
||||
color: #202023;
|
||||
opacity: 0.8;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.privacy-text ul {
|
||||
margin-bottom: 20px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
.privacy-text li {
|
||||
margin-bottom: 8px;
|
||||
color: #202023;
|
||||
opacity: 0.8;
|
||||
}
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<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.html" 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.html" class="nav-link">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/shop.html" class="nav-link">Shop</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/portfolio.html" class="nav-link">Portfolio</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/about.html" class="nav-link">About</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/blog.html" class="nav-link">Blog</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/contact.html" 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.html" 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">
|
||||
<div class="cart-summary">
|
||||
<span class="summary-label">Subtotal:</span>
|
||||
<span class="summary-value" id="cartSubtotal">$0.00</span>
|
||||
</div>
|
||||
<a href="/checkout.html" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop.html" class="btn-text">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.html" class="mobile-link">Home</a></li>
|
||||
<li><a href="/shop.html" class="mobile-link">Shop</a></li>
|
||||
<li><a href="/portfolio.html" class="mobile-link">Portfolio</a></li>
|
||||
<li><a href="/about.html" class="mobile-link">About</a></li>
|
||||
<li><a href="/blog.html" class="mobile-link">Blog</a></li>
|
||||
<li><a href="/contact.html" class="mobile-link">Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<section class="privacy-hero">
|
||||
<div class="container">
|
||||
<h1>Privacy Policy</h1>
|
||||
<p>Your privacy is important to us</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="privacy-content">
|
||||
<div class="container">
|
||||
<div class="privacy-text" id="privacyContent">
|
||||
<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 privacy policy...</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.html">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.html">Our Story</a></li>
|
||||
<li><a href="/portfolio.html">Portfolio</a></li>
|
||||
<li><a href="/blog.html">Blog</a></li>
|
||||
<li><a href="/contact.html">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>© 2025 Sky Art Shop. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="/assets/js/page-transitions.js"></script>
|
||||
<script src="/assets/js/main.js"></script>
|
||||
<script src="/assets/js/navigation.js"></script>
|
||||
<script src="/assets/js/cart.js"></script>
|
||||
<script src="/assets/js/shopping.js"></script>
|
||||
<script>
|
||||
// Load privacy policy content from API
|
||||
async function loadFaqContent() {
|
||||
try {
|
||||
const response = await fetch("/api/pages/faq");
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.page) {
|
||||
const contentDiv = document.getElementById("privacyContent");
|
||||
contentDiv.innerHTML =
|
||||
data.page.content || "<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("privacyContent").innerHTML =
|
||||
"<p>Unable to load content.</p>";
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading privacy content:", error);
|
||||
document.getElementById("privacyContent").innerHTML =
|
||||
"<p>Error loading content.</p>";
|
||||
}
|
||||
}
|
||||
|
||||
// Load content when page loads
|
||||
document.addEventListener("DOMContentLoaded", loadFaqContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -18,43 +18,21 @@
|
||||
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=1735692100" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css?v=1735692200" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css?v=1767233028" />
|
||||
<link rel="stylesheet" href="/assets/css/page-overrides.css?v=1736790001" />
|
||||
<link rel="stylesheet" href="/assets/css/cart-wishlist.css" />
|
||||
<link rel="stylesheet" href="/assets/css/shopping.css" />
|
||||
<link rel="stylesheet" href="/assets/css/responsive-enhanced.css" />
|
||||
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
|
||||
<style>
|
||||
/* Product Title Link - Make entire title clickable */
|
||||
.product-title-link {
|
||||
text-decoration: none !important;
|
||||
color: #202023 !important;
|
||||
display: block !important;
|
||||
cursor: pointer !important;
|
||||
transition: color 0.3s ease;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.product-title-link:hover {
|
||||
color: #fcb1d8 !important;
|
||||
}
|
||||
|
||||
.product-title-link h3 {
|
||||
color: inherit;
|
||||
transition: color 0.3s ease;
|
||||
margin: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.product-title-link:hover h3 {
|
||||
color: #fcb1d8 !important;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/assets/css/responsive.css" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar-mobile-fix.css?v=1736790000" />
|
||||
</head>
|
||||
<body>
|
||||
<!-- Modern Navigation -->
|
||||
<nav class="modern-navbar">
|
||||
<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">
|
||||
@@ -133,17 +111,10 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown-body" id="cartContent">
|
||||
<p class="empty-state">Your cart is empty</p>
|
||||
<p class="empty-state"><i class="bi bi-cart-x"></i><br>Your cart is empty</p>
|
||||
</div>
|
||||
<div class="dropdown-foot">
|
||||
<div class="cart-summary">
|
||||
<span class="summary-label">Subtotal:</span>
|
||||
<span class="summary-value" id="cartSubtotal">$0.00</span>
|
||||
</div>
|
||||
<a href="/checkout" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop" class="btn-text">Continue Shopping</a>
|
||||
<a href="/shop" class="btn-outline">Continue Shopping</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -172,8 +143,42 @@
|
||||
<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">
|
||||
@@ -310,8 +315,8 @@
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="/assets/js/main.js"></script>
|
||||
<script src="/assets/js/shop-system.js"></script>
|
||||
<script src="/assets/js/cart.js"></script>
|
||||
<script src="/assets/js/page-transitions.js?v=1766709739"></script>
|
||||
<script src="/assets/js/back-button-control.js?v=1766723554"></script>
|
||||
<script>
|
||||
|
||||
@@ -11,314 +11,6 @@
|
||||
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" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css" />
|
||||
<style>
|
||||
.page-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
.page-header {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 2px solid #e0e0e0;
|
||||
}
|
||||
.page-header h1 {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.page-content {
|
||||
background: white;
|
||||
padding: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
line-height: 1.8;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
.page-content h1,
|
||||
.page-content h2,
|
||||
.page-content h3,
|
||||
.page-content h4,
|
||||
.page-content h5,
|
||||
.page-content h6 {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0.5em;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
.page-content h1 {
|
||||
font-size: 2rem;
|
||||
border-bottom: 2px solid #e0e0e0;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.page-content h2 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
.page-content h3 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
.page-content p {
|
||||
margin-bottom: 1.2em;
|
||||
color: #555;
|
||||
}
|
||||
.page-content ul,
|
||||
.page-content ol {
|
||||
margin-bottom: 1.5em;
|
||||
padding-left: 30px;
|
||||
}
|
||||
.page-content li {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
.page-content img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: 8px;
|
||||
margin: 20px 0;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.page-content blockquote {
|
||||
border-left: 4px solid #667eea;
|
||||
padding-left: 20px;
|
||||
margin: 20px 0;
|
||||
font-style: italic;
|
||||
color: #666;
|
||||
background: #f8f9fa;
|
||||
padding: 15px 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.page-content a {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
.page-content a:hover {
|
||||
color: #5568d3;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.page-content code {
|
||||
background: #f4f4f4;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
font-family: monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.page-content pre {
|
||||
background: #2d2d2d;
|
||||
color: #f8f8f2;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
overflow-x: auto;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.page-content pre code {
|
||||
background: none;
|
||||
padding: 0;
|
||||
color: inherit;
|
||||
}
|
||||
.loading-container {
|
||||
text-align: center;
|
||||
padding: 100px 20px;
|
||||
}
|
||||
.loading-spinner {
|
||||
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;
|
||||
}
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.error-container {
|
||||
text-align: center;
|
||||
padding: 100px 20px;
|
||||
}
|
||||
.error-container i {
|
||||
font-size: 4rem;
|
||||
color: #e74c3c;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.error-container h2 {
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.error-container p {
|
||||
color: #666;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.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="/contact" class="nav-link">Contact</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="navbar-actions">
|
||||
<a href="/shop" class="btn-cart">
|
||||
<i class="bi bi-cart3"></i>
|
||||
<span class="cart-count">0</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="page-container" id="pageContainer">
|
||||
<div class="loading-container">
|
||||
<div class="loading-spinner"></div>
|
||||
<p>Loading page...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="site-footer">
|
||||
<div class="footer-content">
|
||||
<div class="footer-section">
|
||||
<h4>Sky Art Shop</h4>
|
||||
<p>
|
||||
Quality scrapbooking, journaling, and crafting supplies for creative
|
||||
minds.
|
||||
</p>
|
||||
</div>
|
||||
<div class="footer-section">
|
||||
<h4>Quick Links</h4>
|
||||
<ul>
|
||||
<li><a href="/home">Home</a></li>
|
||||
<li><a href="/shop">Shop</a></li>
|
||||
<li><a href="/portfolio">Portfolio</a></li>
|
||||
<li><a href="/about">About</a></li>
|
||||
<li><a href="/contact">Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer-section">
|
||||
<h4>Follow Us</h4>
|
||||
<div class="social-links">
|
||||
<a href="#"><i class="bi bi-facebook"></i></a>
|
||||
<a href="#"><i class="bi bi-instagram"></i></a>
|
||||
<a href="#"><i class="bi bi-pinterest"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<p>© 2025 Sky Art Shop. All rights reserved.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
// Get slug from URL parameter
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const pageSlug = urlParams.get("slug");
|
||||
|
||||
if (!pageSlug) {
|
||||
showError("No page specified");
|
||||
} else {
|
||||
loadPage(pageSlug);
|
||||
}
|
||||
|
||||
async function loadPage(slug) {
|
||||
try {
|
||||
const response = await fetch(`/api/pages/${slug}`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.page) {
|
||||
displayPage(data.page);
|
||||
} else {
|
||||
showError("Page not found");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to load page:", error);
|
||||
showError("Failed to load page");
|
||||
}
|
||||
}
|
||||
|
||||
function displayPage(page) {
|
||||
// Update page title and meta
|
||||
document.getElementById("pageTitle").textContent =
|
||||
page.metatitle || page.title + " - Sky Art Shop";
|
||||
document.getElementById("pageDescription").content =
|
||||
page.metadescription || page.title;
|
||||
|
||||
// Display page content
|
||||
const container = document.getElementById("pageContainer");
|
||||
container.innerHTML = `
|
||||
<div class="page-header">
|
||||
<h1>${escapeHtml(page.title)}</h1>
|
||||
</div>
|
||||
<div class="page-content">
|
||||
${page.content || "<p>No content available.</p>"}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function showError(message) {
|
||||
const container = document.getElementById("pageContainer");
|
||||
container.innerHTML = `
|
||||
<div class="error-container">
|
||||
<i class="bi bi-exclamation-triangle"></i>
|
||||
<h2>Oops! Something went wrong</h2>
|
||||
<p>${escapeHtml(message)}</p>
|
||||
<a href="/home" class="btn btn-primary">
|
||||
<i class="bi bi-house"></i> Back to Home
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
const map = {
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
'"': """,
|
||||
"'": "'",
|
||||
};
|
||||
return text.replace(/[&<>"']/g, (m) => map[m]);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -8,17 +8,20 @@
|
||||
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=1735692100" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css?v=1735692200" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css?v=1767233028" />
|
||||
<link rel="stylesheet" href="/assets/css/page-overrides.css?v=1736790001" />
|
||||
<link rel="stylesheet" href="/assets/css/cart-wishlist.css" />
|
||||
<link rel="stylesheet" href="/assets/css/shopping.css" />
|
||||
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
|
||||
<link rel="stylesheet" href="/assets/css/responsive.css" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar-mobile-fix.css?v=1736790000" />
|
||||
</head>
|
||||
<body>
|
||||
<script>window.__bodyReady=true</script>
|
||||
<div class="sticky-banner-wrapper">
|
||||
<!-- Modern Navigation -->
|
||||
<nav class="modern-navbar">
|
||||
<div class="navbar-wrapper">
|
||||
@@ -99,17 +102,10 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown-body" id="cartContent">
|
||||
<p class="empty-state">Your cart is empty</p>
|
||||
<p class="empty-state"><i class="bi bi-cart-x"></i><br>Your cart is empty</p>
|
||||
</div>
|
||||
<div class="dropdown-foot">
|
||||
<div class="cart-summary">
|
||||
<span class="summary-label">Subtotal:</span>
|
||||
<span class="summary-value" id="cartSubtotal">$0.00</span>
|
||||
</div>
|
||||
<a href="/checkout" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop" class="btn-text">Continue Shopping</a>
|
||||
<a href="/shop" class="btn-outline">Continue Shopping</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -138,28 +134,56 @@
|
||||
<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>
|
||||
</div>
|
||||
</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"
|
||||
@@ -169,7 +193,6 @@
|
||||
gap: 30px;
|
||||
"
|
||||
></div>
|
||||
<div
|
||||
id="noProjects"
|
||||
style="display: none; text-align: center; padding: 40px; color: #666"
|
||||
>
|
||||
@@ -178,12 +201,7 @@
|
||||
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>
|
||||
@@ -196,12 +214,7 @@
|
||||
><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>
|
||||
@@ -209,32 +222,19 @@
|
||||
<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>© 2025 Sky Art Shop. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Project Modal -->
|
||||
<div
|
||||
id="projectModal"
|
||||
@@ -250,7 +250,6 @@
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
"
|
||||
>
|
||||
<div
|
||||
style="
|
||||
position: absolute;
|
||||
@@ -270,7 +269,6 @@
|
||||
>
|
||||
<button
|
||||
onclick="closeProjectModal()"
|
||||
style="
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
@@ -287,42 +285,43 @@
|
||||
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"
|
||||
style="
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
flex: 1;
|
||||
scroll-behavior: smooth;
|
||||
"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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/main.js"></script>
|
||||
<script src="/assets/js/navigation.js"></script>
|
||||
<script src="/assets/js/cart.js"></script>
|
||||
<script src="/assets/js/shop-system.js"></script>
|
||||
<script src="/assets/js/shopping.js"></script>
|
||||
<script>
|
||||
let portfolioProjects = [];
|
||||
|
||||
// Open project modal
|
||||
function openProjectModal(projectId) {
|
||||
const project = portfolioProjects.find((p) => p.id === projectId);
|
||||
if (!project) return;
|
||||
|
||||
const modal = document.getElementById("projectModal");
|
||||
const modalContent = document.getElementById("modalContent");
|
||||
|
||||
modalContent.innerHTML = `
|
||||
try {
|
||||
const project = portfolioProjects.find((p) => p.id === projectId);
|
||||
if (!project) {
|
||||
console.error('[Portfolio] Project not found:', projectId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate project data
|
||||
if (!project.title) {
|
||||
console.error('[Portfolio] Invalid project data - missing title:', project);
|
||||
return;
|
||||
}
|
||||
|
||||
const modal = document.getElementById("projectModal");
|
||||
const modalContent = document.getElementById("modalContent");
|
||||
|
||||
// Safe template with validated data
|
||||
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.imageurl || "/assets/images/placeholder.svg"}"
|
||||
alt="${project.title}"
|
||||
@@ -352,33 +351,33 @@
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
modal.style.display = "block";
|
||||
modalContent.scrollTop = 0;
|
||||
document.body.style.overflow = "hidden";
|
||||
} catch (error) {
|
||||
console.error('[Portfolio] Error opening modal:', error);
|
||||
alert('Unable to open project details. Please try again.');
|
||||
}
|
||||
|
||||
}
|
||||
// Close project modal
|
||||
function closeProjectModal() {
|
||||
document.getElementById("projectModal").style.display = "none";
|
||||
document.body.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 {
|
||||
@@ -386,16 +385,28 @@
|
||||
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 = portfolioProjects
|
||||
grid.innerHTML = validProjects
|
||||
.map(
|
||||
(project) => `
|
||||
<div class="product-card" onclick="openProjectModal('${
|
||||
@@ -426,18 +437,13 @@
|
||||
)
|
||||
.join("");
|
||||
} else {
|
||||
document.getElementById("loadingMessage").style.display = "none";
|
||||
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>
|
||||
|
||||
@@ -11,330 +11,6 @@
|
||||
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" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css" />
|
||||
<link rel="stylesheet" href="/assets/css/shopping.css" />
|
||||
<style>
|
||||
.privacy-hero {
|
||||
background: linear-gradient(135deg, #f6ccde 0%, #fcb1d8 100%);
|
||||
padding: 40px 0 30px;
|
||||
color: #202023;
|
||||
text-align: center;
|
||||
}
|
||||
.privacy-hero h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 16px;
|
||||
font-weight: 700;
|
||||
color: #202023;
|
||||
}
|
||||
.privacy-hero p {
|
||||
font-size: 1.1rem;
|
||||
color: #202023;
|
||||
opacity: 0.9;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.privacy-content {
|
||||
padding: 60px 0;
|
||||
background: #ffebeb;
|
||||
}
|
||||
.privacy-text {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
padding: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(252, 177, 216, 0.2);
|
||||
line-height: 1.8;
|
||||
border: 1px solid #ffd0d0;
|
||||
}
|
||||
.privacy-text h2 {
|
||||
color: #202023;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.privacy-text h3 {
|
||||
color: #202023;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.privacy-text p {
|
||||
color: #202023;
|
||||
opacity: 0.8;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.privacy-text ul {
|
||||
margin-bottom: 20px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
.privacy-text li {
|
||||
margin-bottom: 8px;
|
||||
color: #202023;
|
||||
opacity: 0.8;
|
||||
}
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"
|
||||
</head>
|
||||
<body>
|
||||
<!-- Modern Navigation -->
|
||||
<nav class="modern-navbar">
|
||||
<div class="navbar-wrapper">
|
||||
<div class="navbar-brand">
|
||||
<a href="/home.html" 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.html" class="nav-link">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/shop.html" class="nav-link">Shop</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/portfolio.html" class="nav-link">Portfolio</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/about.html" class="nav-link">About</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/blog.html" class="nav-link">Blog</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/contact.html" 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.html" 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">
|
||||
<div class="cart-summary">
|
||||
<span class="summary-label">Subtotal:</span>
|
||||
<span class="summary-value" id="cartSubtotal">$0.00</span>
|
||||
</div>
|
||||
<a href="/checkout.html" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop.html" class="btn-text">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.html" class="mobile-link">Home</a></li>
|
||||
<li><a href="/shop.html" class="mobile-link">Shop</a></li>
|
||||
<li><a href="/portfolio.html" class="mobile-link">Portfolio</a></li>
|
||||
<li><a href="/about.html" class="mobile-link">About</a></li>
|
||||
<li><a href="/blog.html" class="mobile-link">Blog</a></li>
|
||||
<li><a href="/contact.html" class="mobile-link">Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<section class="privacy-hero">
|
||||
<div class="container">
|
||||
<h1>Privacy Policy</h1>
|
||||
<p>Your privacy is important to us</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="privacy-content">
|
||||
<div class="container">
|
||||
<div class="privacy-text" id="privacyContent">
|
||||
<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 privacy policy...</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.html">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.html">Our Story</a></li>
|
||||
<li><a href="/portfolio.html">Portfolio</a></li>
|
||||
<li><a href="/blog.html">Blog</a></li>
|
||||
<li><a href="/contact.html">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>© 2025 Sky Art Shop. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="/assets/js/page-transitions.js"></script>
|
||||
<script src="/assets/js/main.js"></script>
|
||||
<script src="/assets/js/navigation.js"></script>
|
||||
<script src="/assets/js/cart.js"></script>
|
||||
<script src="/assets/js/shopping.js"></script>
|
||||
<script>
|
||||
// Load privacy policy content from API
|
||||
async function loadPrivacyContent() {
|
||||
try {
|
||||
const response = await fetch("/api/pages/privacy");
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.page) {
|
||||
const contentDiv = document.getElementById("privacyContent");
|
||||
contentDiv.innerHTML =
|
||||
data.page.content || "<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("privacyContent").innerHTML =
|
||||
"<p>Unable to load content.</p>";
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading privacy content:", error);
|
||||
document.getElementById("privacyContent").innerHTML =
|
||||
"<p>Error loading content.</p>";
|
||||
}
|
||||
}
|
||||
|
||||
// Load content when page loads
|
||||
document.addEventListener("DOMContentLoaded", loadPrivacyContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,887 +10,6 @@
|
||||
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=1735692100" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css?v=1735692200" />
|
||||
<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>
|
||||
/* Custom Scrollbar for Description Box */
|
||||
div[style*="overflow-y: auto"] {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #6b46c1 #f3f4f6;
|
||||
}
|
||||
|
||||
div[style*="overflow-y: auto"]::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
div[style*="overflow-y: auto"]::-webkit-scrollbar-track {
|
||||
background: #f3f4f6;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
div[style*="overflow-y: auto"]::-webkit-scrollbar-thumb {
|
||||
background: #6b46c1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
div[style*="overflow-y: auto"]::-webkit-scrollbar-thumb:hover {
|
||||
background: #5936a3;
|
||||
}
|
||||
|
||||
/* Smooth image transitions */
|
||||
#primaryImage {
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
/* Thumbnail hover effect */
|
||||
.thumbnail-item:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Color variant animation */
|
||||
.color-variant-circle {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.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">
|
||||
<div class="cart-summary">
|
||||
<span class="summary-label">Subtotal:</span>
|
||||
<span class="summary-value" id="cartSubtotal">$0.00</span>
|
||||
</div>
|
||||
<a href="/checkout" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop" class="btn-text">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>
|
||||
|
||||
<script src="/assets/js/shop-system.js"></script>
|
||||
<script src="/assets/js/cart.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 src="/assets/js/api-client.js"></script>
|
||||
<script src="/assets/js/notifications.js"></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 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 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">© 2025 Sky Art Shop. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -11,330 +11,6 @@
|
||||
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" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css" />
|
||||
<link rel="stylesheet" href="/assets/css/shopping.css" />
|
||||
<style>
|
||||
.privacy-hero {
|
||||
background: linear-gradient(135deg, #f6ccde 0%, #fcb1d8 100%);
|
||||
padding: 40px 0 30px;
|
||||
color: #202023;
|
||||
text-align: center;
|
||||
}
|
||||
.privacy-hero h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 16px;
|
||||
font-weight: 700;
|
||||
color: #202023;
|
||||
}
|
||||
.privacy-hero p {
|
||||
font-size: 1.1rem;
|
||||
color: #202023;
|
||||
opacity: 0.9;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.privacy-content {
|
||||
padding: 60px 0;
|
||||
background: #ffebeb;
|
||||
}
|
||||
.privacy-text {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
padding: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(252, 177, 216, 0.2);
|
||||
line-height: 1.8;
|
||||
border: 1px solid #ffd0d0;
|
||||
}
|
||||
.privacy-text h2 {
|
||||
color: #202023;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.privacy-text h3 {
|
||||
color: #202023;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.privacy-text p {
|
||||
color: #202023;
|
||||
opacity: 0.8;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.privacy-text ul {
|
||||
margin-bottom: 20px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
.privacy-text li {
|
||||
margin-bottom: 8px;
|
||||
color: #202023;
|
||||
opacity: 0.8;
|
||||
}
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/assets/css/theme-colors.css" />
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"
|
||||
</head>
|
||||
<body>
|
||||
<!-- Modern Navigation -->
|
||||
<nav class="modern-navbar">
|
||||
<div class="navbar-wrapper">
|
||||
<div class="navbar-brand">
|
||||
<a href="/home.html" 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.html" class="nav-link">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/shop.html" class="nav-link">Shop</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/portfolio.html" class="nav-link">Portfolio</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/about.html" class="nav-link">About</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/blog.html" class="nav-link">Blog</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/contact.html" 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.html" 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">
|
||||
<div class="cart-summary">
|
||||
<span class="summary-label">Subtotal:</span>
|
||||
<span class="summary-value" id="cartSubtotal">$0.00</span>
|
||||
</div>
|
||||
<a href="/checkout.html" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop.html" class="btn-text">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.html" class="mobile-link">Home</a></li>
|
||||
<li><a href="/shop.html" class="mobile-link">Shop</a></li>
|
||||
<li><a href="/portfolio.html" class="mobile-link">Portfolio</a></li>
|
||||
<li><a href="/about.html" class="mobile-link">About</a></li>
|
||||
<li><a href="/blog.html" class="mobile-link">Blog</a></li>
|
||||
<li><a href="/contact.html" class="mobile-link">Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<section class="privacy-hero">
|
||||
<div class="container">
|
||||
<h1>Privacy Policy</h1>
|
||||
<p>Your privacy is important to us</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="privacy-content">
|
||||
<div class="container">
|
||||
<div class="privacy-text" id="privacyContent">
|
||||
<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 privacy policy...</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.html">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.html">Our Story</a></li>
|
||||
<li><a href="/portfolio.html">Portfolio</a></li>
|
||||
<li><a href="/blog.html">Blog</a></li>
|
||||
<li><a href="/contact.html">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>© 2025 Sky Art Shop. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="/assets/js/page-transitions.js"></script>
|
||||
<script src="/assets/js/main.js"></script>
|
||||
<script src="/assets/js/navigation.js"></script>
|
||||
<script src="/assets/js/cart.js"></script>
|
||||
<script src="/assets/js/shopping.js"></script>
|
||||
<script>
|
||||
// Load privacy policy content from API
|
||||
async function loadReturnsContent() {
|
||||
try {
|
||||
const response = await fetch("/api/pages/returns");
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.page) {
|
||||
const contentDiv = document.getElementById("privacyContent");
|
||||
contentDiv.innerHTML =
|
||||
data.page.content || "<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("privacyContent").innerHTML =
|
||||
"<p>Unable to load content.</p>";
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading privacy content:", error);
|
||||
document.getElementById("privacyContent").innerHTML =
|
||||
"<p>Error loading content.</p>";
|
||||
}
|
||||
}
|
||||
|
||||
// Load content when page loads
|
||||
document.addEventListener("DOMContentLoaded", loadReturnsContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -13,331 +13,4 @@
|
||||
<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" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css" />
|
||||
<link rel="stylesheet" href="/assets/css/shopping.css" />
|
||||
<style>
|
||||
.privacy-hero {
|
||||
background: linear-gradient(135deg, #f6ccde 0%, #fcb1d8 100%);
|
||||
padding: 40px 0 30px;
|
||||
color: #202023;
|
||||
text-align: center;
|
||||
}
|
||||
.privacy-hero h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 16px;
|
||||
font-weight: 700;
|
||||
color: #202023;
|
||||
}
|
||||
.privacy-hero p {
|
||||
font-size: 1.1rem;
|
||||
color: #202023;
|
||||
opacity: 0.9;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.privacy-content {
|
||||
padding: 60px 0;
|
||||
background: #ffebeb;
|
||||
}
|
||||
.privacy-text {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
padding: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(252, 177, 216, 0.2);
|
||||
line-height: 1.8;
|
||||
border: 1px solid #ffd0d0;
|
||||
}
|
||||
.privacy-text h2 {
|
||||
color: #202023;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.privacy-text h3 {
|
||||
color: #202023;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.privacy-text p {
|
||||
color: #202023;
|
||||
opacity: 0.8;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.privacy-text ul {
|
||||
margin-bottom: 20px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
.privacy-text li {
|
||||
margin-bottom: 8px;
|
||||
color: #202023;
|
||||
opacity: 0.8;
|
||||
}
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<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.html" 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.html" class="nav-link">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/shop.html" class="nav-link">Shop</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/portfolio.html" class="nav-link">Portfolio</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/about.html" class="nav-link">About</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/blog.html" class="nav-link">Blog</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/contact.html" 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.html" 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">
|
||||
<div class="cart-summary">
|
||||
<span class="summary-label">Subtotal:</span>
|
||||
<span class="summary-value" id="cartSubtotal">$0.00</span>
|
||||
</div>
|
||||
<a href="/checkout.html" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop.html" class="btn-text">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.html" class="mobile-link">Home</a></li>
|
||||
<li><a href="/shop.html" class="mobile-link">Shop</a></li>
|
||||
<li><a href="/portfolio.html" class="mobile-link">Portfolio</a></li>
|
||||
<li><a href="/about.html" class="mobile-link">About</a></li>
|
||||
<li><a href="/blog.html" class="mobile-link">Blog</a></li>
|
||||
<li><a href="/contact.html" class="mobile-link">Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<section class="privacy-hero">
|
||||
<div class="container">
|
||||
<h1>Privacy Policy</h1>
|
||||
<p>Your privacy is important to us</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="privacy-content">
|
||||
<div class="container">
|
||||
<div class="privacy-text" id="privacyContent">
|
||||
<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 privacy policy...</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.html">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.html">Our Story</a></li>
|
||||
<li><a href="/portfolio.html">Portfolio</a></li>
|
||||
<li><a href="/blog.html">Blog</a></li>
|
||||
<li><a href="/contact.html">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>© 2025 Sky Art Shop. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="/assets/js/page-transitions.js"></script>
|
||||
<script src="/assets/js/main.js"></script>
|
||||
<script src="/assets/js/navigation.js"></script>
|
||||
<script src="/assets/js/cart.js"></script>
|
||||
<script src="/assets/js/shopping.js"></script>
|
||||
<script>
|
||||
// Load privacy policy content from API
|
||||
async function loadShippingContent() {
|
||||
try {
|
||||
const response = await fetch("/api/pages/shipping-info");
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.page) {
|
||||
const contentDiv = document.getElementById("privacyContent");
|
||||
contentDiv.innerHTML =
|
||||
data.page.content || "<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("privacyContent").innerHTML =
|
||||
"<p>Unable to load content.</p>";
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading privacy content:", error);
|
||||
document.getElementById("privacyContent").innerHTML =
|
||||
"<p>Error loading content.</p>";
|
||||
}
|
||||
}
|
||||
|
||||
// Load content when page loads
|
||||
document.addEventListener("DOMContentLoaded", loadShippingContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -15,12 +15,17 @@
|
||||
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=1735692100" />
|
||||
<link rel="stylesheet" href="/assets/css/navbar.css?v=1767233028" />
|
||||
<link rel="stylesheet" href="/assets/css/page-overrides.css?v=1736790001" />
|
||||
<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" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="/assets/css/navbar-mobile-fix.css?v=1736790000"
|
||||
/>
|
||||
<style>
|
||||
/* Body Reset */
|
||||
body {
|
||||
|
||||
Reference in New Issue
Block a user