Cart section needs to reload

Hello I’m using shrine pro (not the most recent one) and when I add to cart I need to reload to see the product added (also I use it as a drawer and that’s how I want it to be), I would like that when I click add to cart it appears the drawer on the right side, also when I delete any product in my cart I need to reload to see the changes i’ve tried asking chat gpt but had no luck, I can share whatever info you like to know

Hey @Lucas_Miranda,

Shrine Pro is known for being not very developer friendly.
I tried to reverse engineer their uglified main.js a little and came up with this little controller to open/close/update the cart drawer.

cart-controller.js
/**
 * Cart Drawer Controller
 * 
 * This script provides a global interface to control the cart drawer
 * functionality from anywhere in your Shopify theme.
 */

// Create a global namespace for cart drawer controls
window.CartDrawerController = (function() {
  // Private variables
  let cartDrawer = null;
  let cartDrawerItems = null;
  
  // Initialize references to the cart drawer elements
  function init() {
    cartDrawer = document.querySelector('cart-drawer');
    cartDrawerItems = document.querySelector('cart-drawer-items');
    
    if (!cartDrawer) {
      console.error('Cart drawer element not found. Make sure your theme includes a cart-drawer custom element.');
      return false;
    }
    
    return true;
  }
  
  /**
   * Open the cart drawer
   * @return {Boolean} Success status
   */
  function openCartDrawer() {
    if (!init()) return false;
    
    cartDrawer.open();
    return true;
  }
  
  /**
   * Close the cart drawer
   * @return {Boolean} Success status
   */
  function closeCartDrawer() {
    if (!init()) return false;
    
    cartDrawer.close();
    return true;
  }
  
  /**
   * Update cart drawer contents by fetching the latest cart data
   * @return {Promise} A promise that resolves when the cart is updated
   */
  function updateCartContents() {
    if (!init()) return Promise.reject('Cart drawer not initialized');
    
    return fetch('/cart.js')
      .then(response => response.json())
      .then(cartData => {
        // If cart is empty, make sure we reflect that state
        if (cartData.item_count === 0) {
          cartDrawer.classList.add('is-empty');
        } else {
          cartDrawer.classList.remove('is-empty');
        }
        
        // Fetch sections to get the rendered HTML
        return fetch('/cart?sections=cart-drawer,cart-icon-bubble', {
          method: 'GET'
        });
      })
      .then(response => response.json())
      .then(sections => {
        // Check if we have the expected sections in the response
        if (!sections || (typeof sections !== 'object')) {
          throw new Error('Invalid response format from cart sections');
        }
        
        // Now we have the rendered HTML for the cart drawer
        // Make sure we match the structure expected by renderContents
        try {
          cartDrawer.renderContents({ 
            sections: sections
          });
        } catch (e) {
          console.error('Error in renderContents:', e);
          
          // Alternative approach - directly update the innerHTML
          if (sections['cart-drawer']) {
            const drawerInner = cartDrawer.querySelector('.drawer__inner');
            if (drawerInner) {
              const parser = new DOMParser();
              const parsedHtml = parser.parseFromString(sections['cart-drawer'], 'text/html');
              const drawerContent = parsedHtml.querySelector('.drawer__inner');
              
              if (drawerContent) {
                drawerInner.innerHTML = drawerContent.innerHTML;
              }
            }
          }
          
          // Update cart count bubble if available
          if (sections['cart-icon-bubble']) {
            const iconBubble = document.getElementById('cart-icon-bubble');
            if (iconBubble) {
              const parser = new DOMParser();
              const parsedHtml = parser.parseFromString(sections['cart-icon-bubble'], 'text/html');
              const newBubble = parsedHtml.getElementById('cart-icon-bubble');
              
              if (newBubble) {
                iconBubble.innerHTML = newBubble.innerHTML;
              }
            }
          }
        }
        
        return sections;
      })
      .catch(error => {
        console.error('Error updating cart drawer:', error);
        throw error;
      });
  }
  
  /**
   * Add an item to the cart and open the drawer
   * @param {Number} variantId - The variant ID to add
   * @param {Number} quantity - The quantity to add (default: 1)
   * @param {Object} properties - Line item properties (optional)
   * @return {Promise} A promise that resolves when the item is added
   */
  function addItemAndOpenDrawer(variantId, quantity = 1, properties = {}) {
    if (!init()) return Promise.reject('Cart drawer not initialized');
    
    // Ensure variantId is valid
    if (!variantId || isNaN(Number(variantId))) {
      return Promise.reject('Invalid variant ID');
    }
    
    // Ensure quantity is valid
    quantity = Math.max(1, parseInt(quantity) || 1);
    
    // Prepare the request payload
    const data = {
      items: [{
        id: variantId,
        quantity: quantity
      }]
    };
    
    // Add properties if they exist
    if (Object.keys(properties).length > 0) {
      data.items[0].properties = properties;
    }
    
    // Add the item to the cart
    return fetch('/cart/add.js', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
    })
    .then(response => {
      if (!response.ok) {
        // If the server responds with an error status
        return response.json().then(data => {
          throw new Error(data.description || 'Error adding item to cart');
        });
      }
      return response.json();
    })
    .then(addResult => {
      // Now update the cart drawer contents
      return updateCartContents();
    })
    .then(() => {
      // Open the cart drawer
      openCartDrawer();
      return true;
    })
    .catch(error => {
      console.error('Error adding item to cart:', error);
      throw error;
    });
  }
  
  /**
   * Update the quantity of an item in the cart
   * @param {Number} lineItem - The line item to update (1-based index)
   * @param {Number} quantity - The new quantity
   * @return {Promise} A promise that resolves when the cart is updated
   */
  function updateItemQuantity(lineItem, quantity) {
    if (!init() || !cartDrawerItems) return Promise.reject('Cart drawer not initialized');
    
    // Call the updateQuantity method on the cart-drawer-items element
    return new Promise((resolve, reject) => {
      try {
        cartDrawerItems.updateQuantity(lineItem, quantity);
        resolve(true);
      } catch (error) {
        reject(error);
      }
    });
  }
  
  /**
   * Clear the cart
   * @return {Promise} A promise that resolves when the cart is cleared
   */
  function clearCart() {
    if (!init() || !cartDrawerItems) return Promise.reject('Cart drawer not initialized');
    
    // Call the clearCart method on the cart-drawer-items element
    return new Promise((resolve, reject) => {
      try {
        cartDrawerItems.clearCart();
        resolve(true);
      } catch (error) {
        reject(error);
      }
    });
  }
  
  /**
   * Debugging utility to help troubleshoot cart drawer issues
   * @return {Object} Diagnostic information about the cart drawer
   */
  function debug() {
    const diagnostics = {
      cartDrawerFound: !!document.querySelector('cart-drawer'),
      cartItemsFound: !!document.querySelector('cart-drawer-items'),
      cartIconFound: !!document.getElementById('cart-icon-bubble'),
      drawerMethods: {}
    };
    
    // Check drawer methods
    if (cartDrawer) {
      diagnostics.drawerMethods = {
        open: typeof cartDrawer.open === 'function',
        close: typeof cartDrawer.close === 'function',
        renderContents: typeof cartDrawer.renderContents === 'function',
        getSectionsToRender: typeof cartDrawer.getSectionsToRender === 'function'
      };
      
      // Check if drawer has required properties
      diagnostics.drawerProperties = {
        classList: !!cartDrawer.classList,
        querySelector: typeof cartDrawer.querySelector === 'function',
        drawerInner: !!cartDrawer.querySelector('.drawer__inner')
      };
    }
    
    // Check cart items methods
    if (cartDrawerItems) {
      diagnostics.cartItemsMethods = {
        updateQuantity: typeof cartDrawerItems.updateQuantity === 'function',
        clearCart: typeof cartDrawerItems.clearCart === 'function'
      };
    }
    
    return diagnostics;
  }

  // Public API
  return {
    open: openCartDrawer,
    close: closeCartDrawer,
    update: updateCartContents,
    addItem: addItemAndOpenDrawer,
    updateQuantity: updateItemQuantity,
    clear: clearCart,
    debug: debug
  };
})();

You then are able to use this controller to open, close, update, …

// Open the cart drawer
CartDrawerController.open();

// Add an item with custom properties
CartDrawerController.addItem(variantId, quantity, {
  'Gift Wrap': 'Yes',
  'Engraving': 'Happy Birthday'
})
.then(() => console.log('Added with properties!'));

// Update the quantity of an item
CartDrawerController.updateQuantity(lineItemNumber, newQuantity);

// Clear the entire cart
CartDrawerController.clear();

// Manually update the cart drawer contents
CartDrawerController.update();

// Debug cart drawer issues
console.log(CartDrawerController.debug());

Hope this helps,

Kevin :hatching_chick:

1 Like