- Standardize script loading on faq, privacy, returns, shipping-info pages - Archive 14 unused JS files (cart-functions, shopping, cart.js, enhanced versions, etc.) - Archive 2 unused CSS files (responsive-enhanced, responsive-fixes) - All pages now use consistent script loading order - Eliminated shopping.js dependency (not needed after standardization)
819 lines
23 KiB
JavaScript
819 lines
23 KiB
JavaScript
/**
|
|
* 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,
|
|
};
|
|
}
|
|
})();
|