Files
projectmycelium/src/static/js/cart-marketplace.js
2025-09-01 21:37:01 -04:00

325 lines
11 KiB
JavaScript

/**
* Cart functionality for marketplace pages
* Migrated from inline scripts to use apiJson and shared error handlers
*/
// Global variable to store product ID for removal
let productIdToRemove = null;
document.addEventListener('DOMContentLoaded', function() {
// Initialize cart functionality
console.log('Cart page loaded');
// Update My Orders visibility when cart page loads
if (typeof updateMyOrdersVisibility === 'function') {
updateMyOrdersVisibility();
}
// Initialize recommended products functionality
initializeRecommendedProducts();
// Add event listeners for quantity buttons
document.querySelectorAll('[data-action="increase"], [data-action="decrease"]').forEach(button => {
button.addEventListener('click', function() {
const productId = this.getAttribute('data-product-id');
const action = this.getAttribute('data-action');
const currentQuantity = parseInt(this.parentElement.querySelector('span').textContent);
if (action === 'increase') {
updateQuantity(productId, currentQuantity + 1);
} else if (action === 'decrease') {
updateQuantity(productId, currentQuantity - 1);
}
});
});
// Add event listeners for remove buttons
document.querySelectorAll('[data-action="remove"]').forEach(button => {
button.addEventListener('click', function() {
const productId = this.getAttribute('data-product-id');
showRemoveItemModal(productId);
});
});
// Add event listener for clear cart button
const clearCartBtn = document.getElementById('clearCartBtn');
if (clearCartBtn) {
clearCartBtn.addEventListener('click', showClearCartModal);
}
// Add event listener for confirm clear cart button in modal
const confirmClearCartBtn = document.getElementById('confirmClearCartBtn');
if (confirmClearCartBtn) {
confirmClearCartBtn.addEventListener('click', clearCart);
}
// Add event listener for confirm remove item button in modal
const confirmRemoveItemBtn = document.getElementById('confirmRemoveItemBtn');
if (confirmRemoveItemBtn) {
confirmRemoveItemBtn.addEventListener('click', confirmRemoveItem);
}
// Add event listener for currency selector
const currencySelector = document.getElementById('currencySelector');
if (currencySelector) {
currencySelector.addEventListener('change', changeCurrency);
}
// Post-reload success toast for cart clear (marketplace view)
try {
if (sessionStorage.getItem('cartCleared') === '1') {
sessionStorage.removeItem('cartCleared');
showSuccessToast('Cart cleared successfully');
}
} catch (_) { /* storage may be blocked */ }
});
// Helper: zero Order Summary values and disable checkout when empty
function setMarketplaceSummaryEmpty() {
try {
const summaryCardBody = document.querySelector('.col-lg-4 .card .card-body');
if (!summaryCardBody) return;
// Update Subtotal and Total values to $0.00
summaryCardBody.querySelectorAll('.d-flex.justify-content-between').forEach(row => {
const spans = row.querySelectorAll('span');
if (spans.length >= 2) {
const label = spans[0].textContent.trim();
if (label.startsWith('Subtotal')) spans[1].textContent = '$0.00';
if (label === 'Total') spans[1].textContent = '$0.00';
}
});
// Disable checkout if present
const checkoutBtn = summaryCardBody.querySelector('.btn.btn-primary.btn-lg');
if (checkoutBtn) {
if (checkoutBtn.tagName === 'BUTTON') {
checkoutBtn.disabled = true;
} else {
checkoutBtn.classList.add('disabled');
checkoutBtn.setAttribute('aria-disabled', 'true');
checkoutBtn.setAttribute('tabindex', '-1');
}
}
} catch (_) { /* noop */ }
}
// Update item quantity using apiJson
async function updateQuantity(productId, newQuantity) {
if (newQuantity < 1) {
removeFromCart(productId);
return;
}
showLoading();
try {
const data = await window.apiJson(`/api/cart/item/${productId}`, {
method: 'PUT',
body: JSON.stringify({
quantity: newQuantity
})
});
// Success - reload page to show updated cart
window.location.reload();
} catch (error) {
handleApiError(error, 'updating quantity');
} finally {
hideLoading();
}
}
// Show clear cart modal
function showClearCartModal() {
const modal = new bootstrap.Modal(document.getElementById('clearCartModal'));
modal.show();
}
// Show remove item modal
function showRemoveItemModal(productId) {
productIdToRemove = productId;
const modal = new bootstrap.Modal(document.getElementById('removeItemModal'));
modal.show();
}
// Confirm remove item (called from modal)
async function confirmRemoveItem() {
if (!productIdToRemove) return;
// Hide the modal first
const modal = bootstrap.Modal.getInstance(document.getElementById('removeItemModal'));
modal.hide();
await removeFromCart(productIdToRemove);
productIdToRemove = null;
}
// Remove item from cart using apiJson
async function removeFromCart(productId) {
showLoading();
try {
await window.apiJson(`/api/cart/item/${productId}`, {
method: 'DELETE'
});
showSuccessToast('Item removed from cart');
// Remove the item from DOM immediately
const cartItem = document.querySelector(`[data-product-id="${productId}"]`);
if (cartItem) {
cartItem.remove();
}
// Notify globally and update navbar cart count
if (typeof window.emitCartUpdated === 'function') { window.emitCartUpdated(); }
if (typeof window.updateCartCount === 'function') { window.updateCartCount(); }
// Update cart counts and check if cart is empty
await refreshCartContents();
} catch (error) {
handleApiError(error, 'removing item from cart');
} finally {
hideLoading();
}
}
// Clear entire cart using apiJson
async function clearCart() {
// Hide the modal first
const modal = bootstrap.Modal.getInstance(document.getElementById('clearCartModal'));
modal.hide();
showLoading();
try {
await window.apiJson('/api/cart', { method: 'DELETE' });
// Emit and update counts, then reload to ensure consistent empty state
if (typeof window.emitCartUpdated === 'function') { window.emitCartUpdated(0); }
if (typeof window.updateCartCount === 'function') { window.updateCartCount(); }
try { sessionStorage.setItem('cartCleared', '1'); } catch (_) { /* storage may be blocked */ }
setTimeout(() => { window.location.reload(); }, 50);
} catch (error) {
handleApiError(error, 'clearing cart');
} finally {
hideLoading();
}
}
// Change display currency using apiJson
async function changeCurrency() {
const currencySelector = document.getElementById('currencySelector');
const selectedCurrency = currencySelector.value;
showLoading();
try {
await window.apiJson('/api/user/currency', {
method: 'POST',
body: JSON.stringify({
currency: selectedCurrency
})
});
// Reload page to show prices in new currency
window.location.reload();
} catch (error) {
handleApiError(error, 'changing currency');
} finally {
hideLoading();
}
}
// Refresh cart contents using apiJson
async function refreshCartContents() {
try {
// Fetch fresh cart data from server
const data = await window.apiJson('/api/cart', {
method: 'GET',
cache: 'no-store'
});
// Check if cart is empty and update UI accordingly
const cartItems = data.items || [];
if (cartItems.length === 0) {
// Show empty cart state
const cartContainer = document.querySelector('.cart-items-container');
if (cartContainer) {
cartContainer.innerHTML = `
<div class="text-center py-5">
<i class="bi bi-cart-x display-1 text-muted"></i>
<h3 class="mt-3">Your cart is empty</h3>
<p class="text-muted">Add some items to get started!</p>
<a href="/marketplace" class="btn btn-primary">Browse Marketplace</a>
</div>
`;
}
setMarketplaceSummaryEmpty();
}
} catch (error) {
console.error('Error refreshing cart contents:', error);
// Don't show error toast for this background operation
}
}
// Add to cart functionality for product pages
async function addToCartFromPage(productId, quantity = 1, buttonElement = null) {
if (buttonElement) {
setButtonLoading(buttonElement, 'Adding...');
}
try {
await window.apiJson('/api/cart/add', {
method: 'POST',
body: JSON.stringify({
product_id: productId,
quantity: quantity
})
});
if (buttonElement) {
setButtonSuccess(buttonElement, 'Added!');
}
showSuccessToast('Item added to cart');
// Update cart count in navbar
if (typeof window.updateCartCount === 'function') {
window.updateCartCount();
}
} catch (error) {
handleApiError(error, 'adding to cart', buttonElement);
}
}
// Utility functions
function showLoading() {
const overlay = document.getElementById('loadingOverlay');
if (overlay) {
overlay.classList.remove('d-none');
}
}
function hideLoading() {
const overlay = document.getElementById('loadingOverlay');
if (overlay) {
overlay.classList.add('d-none');
}
}
// Initialize recommended products functionality
function initializeRecommendedProducts() {
// Add event listeners for recommended product add-to-cart buttons
document.querySelectorAll('.recommended-product .add-to-cart-btn').forEach(btn => {
btn.addEventListener('click', function() {
const productId = this.dataset.productId;
if (productId) {
addToCartFromPage(productId, 1, this);
}
});
});
}
// Make functions available globally for backward compatibility
window.addToCartFromPage = addToCartFromPage;
window.refreshCartContents = refreshCartContents;