How to handle favoriting errors? Answered

Post author
Stefan Lakovic

Hey! I made the save favorites functionality. Works perfectly. I am trying to build a save list that only shows the saved items. It shows the exact number but does not show the info. I am loading it in a collection list. Thanks

Comments

7 comments

  • Comment author
    Julian Galluzzo

    Pozdrav 😄

    Is this what you're trying to do?

    https://webflow.com/made-in-webflow/website/filter-saved-cms-items

    0
  • Comment author
    Ben Tossell

    Can these saves be shown on a dedicated page? Or only on the page they are saved on? https://www.memberstack.com/scripts/like-unlike-cms-items

    0
  • Comment author
    Stefan Lakovic

    Hey, I asked yesterday the same. Put the collection list on any page and follow this
    https://webflow.com/made-in-webflow/website/filter-saved-cms-items

    0
  • Comment author
    Ben Tossell

    Thanks

    0
  • Comment author
    Bartosz Chlebowicz

    Hi everyone,
    I’m using the following script in Webflow to allow users to favorite and unfavorite collection items. It works flawlessly for logged-in users, but I’m encountering an issue with non-logged-in users experiencing errors.
    Here’s the error message:

    Memberstack loaded
    (index):230 Is logged in: true
    frame_ant.js:2 GET https://memberstack-client.myurl/member/json 401 (Unauthorized)
    (anonymous) @ frame_ant.js:2
    ...
    (index):239 Error retrieving member data: Unauthorized
    

    It seems that the script is trying to access getMemberJSON() for users who are not logged in, which results in a 401 Unauthorized error. Ideally, the script should only load the favorite/unfavorite functionality for logged-in users and not attempt to load for non-logged-in users.
    I’ve tried several approaches but haven’t found a solution that works. Is there an efficient way to identify if a user is logged in to Memberstack before attempting to run the script? Any help or suggestions would be greatly appreciated!
    Thanks in advance!Script:

    <style>
    /* Hide the "saved" state parent by default */
    .save_unsave {
      display: none;
    }
    
    /* Show the "not-saved" state parent by default */
    .save_save {
      display: block; /* or inline-block, depending on your design */
    }
    </style>
    <script>
    window.onload = function() {
      let memberstack;
      let isLoggedIn = false;
      let savedItems = [];
    
      // Function to wait until Memberstack is fully loaded
      function waitForMemberstack(callback) {
        if (typeof window.$memberstackDom !== 'undefined') {
          callback(); // If Memberstack is already loaded, run the callback
        } else {
          const checkInterval = setInterval(function() {
            if (typeof window.$memberstackDom !== 'undefined') {
              clearInterval(checkInterval); // Stop checking once it's loaded
              callback();
            }
          }, 100); // Check every 100ms
        }
      }
    
      // Initialize the script when Memberstack is ready
      waitForMemberstack(async function() {
        memberstack = window.$memberstackDom;
    
        // Check if the member is logged in
        async function checkMemberLogin() {
          try {
            const member = await memberstack.getCurrentMember();
            return !!member; // Returns true if the member is logged in, false otherwise
          } catch (error) {
            console.error("Error checking member login: ", error);
            return false;
          }
        }
    
        function getSavedItems(memberData) {
          return memberData.savedItems || [];
        }
    
        // Update visibility of save/unsave buttons
        function updateButtonVisibility() {
          const saveButtons = document.querySelectorAll('[ms-code-save]');
          const unsaveButtons = document.querySelectorAll('[ms-code-unsave]');
    
          saveButtons.forEach(button => {
            const itemId = button.getAttribute('ms-code-save');
            const isSaved = savedItems.includes(itemId);
            button.style.display = isSaved ? 'none' : 'block';
          });
    
          unsaveButtons.forEach(button => {
            const itemId = button.getAttribute('ms-code-unsave');
            const isSaved = savedItems.includes(itemId);
            button.style.display = isSaved ? 'block' : 'none';
          });
        }
    
        // Update visibility of items in save lists
        function updateItemVisibility() {
          const saveLists = document.querySelectorAll('[ms-code-save-list]');
    
          saveLists.forEach(list => {
            const filter = list.getAttribute('ms-code-save-list');
            const items = list.querySelectorAll('[ms-code-save-item]');
    
            items.forEach(item => {
              const saveButton = item.querySelector('[ms-code-save]');
              if (!saveButton) {
                item.style.display = 'block';
                return;
              }
              const itemId = saveButton.getAttribute('ms-code-save');
    
              if (!isLoggedIn || filter === 'all') {
                item.style.display = 'block';
              } else if (filter === 'saved' && savedItems.includes(itemId)) {
                item.style.display = 'block';
              } else if (filter === 'unsaved' && !savedItems.includes(itemId)) {
                item.style.display = 'block';
              } else {
                item.style.display = 'none';
              }
            });
          });
        }
    
        // Handle button click for save/unsave
        async function handleButtonClick(event) {
          if (!isLoggedIn) return; // Skip if not logged in
    
          const button = event.currentTarget;
          const action = button.getAttribute('ms-code-save') ? 'save' : 'unsave';
          const itemId = button.getAttribute(action === 'save' ? 'ms-code-save' : 'ms-code-unsave');
    
          // Debug log for action and item ID
          console.log("Action: ", action, "Item ID: ", itemId);
    
          if (action === 'save' && !savedItems.includes(itemId)) {
            savedItems.push(itemId);
            console.log("Saved items after saving: ", savedItems); // Debug log for saved items
          } else if (action === 'unsave') {
            savedItems = savedItems.filter(id => id !== itemId);
            console.log("Saved items after unsaving: ", savedItems); // Debug log for saved items
          }
    
          try {
            await memberstack.updateMemberJSON({ json: { savedItems } });
            console.log("Updated Memberstack successfully");  // Log success
          } catch (error) {
            console.error("Error updating Memberstack: ", error);  // Log error
          }
    
          updateButtonVisibility();
          updateItemVisibility();
        }
    
        // Add event listeners to save/unsave buttons
        function addClickListeners() {
          const saveButtons = document.querySelectorAll('[ms-code-save]');
          const unsaveButtons = document.querySelectorAll('[ms-code-unsave]');
    
          saveButtons.forEach(button => button.addEventListener('click', handleButtonClick));
          unsaveButtons.forEach(button => button.addEventListener('click', handleButtonClick));
        }
    
        // Initialize the script when the page is ready
        async function initializeScript() {
          isLoggedIn = await checkMemberLogin();
          console.log("Is logged in: ", isLoggedIn);  // Debug log for login status
    
          if (isLoggedIn) {
            try {
              const result = await memberstack.getMemberJSON();
              const memberData = result.data || {};
              savedItems = getSavedItems(memberData);
              console.log("Initial saved items: ", savedItems);  // Debug log for initial saved items
            } catch (error) {
              console.error("Error retrieving member data: ", error);  // Log error
            }
          }
    
          updateButtonVisibility();
          updateItemVisibility();
          addClickListeners();
    
          // Set up a MutationObserver to watch for changes in the DOM
          const observer = new MutationObserver((mutations) => {
            let shouldUpdate = false;
            mutations.forEach((mutation) => {
              if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                shouldUpdate = true;
              }
            });
            if (shouldUpdate) {
              console.log("DOM changed, reapplying listeners");  // Debug log for DOM changes
              updateButtonVisibility();
              updateItemVisibility();
              addClickListeners();
            }
          });
    
          // Start observing the document with the configured parameters
          observer.observe(document.body, { childList: true, subtree: true });
        }
    
        // Run the initialize script once Memberstack is ready
        initializeScript();
      });
    };
    </script>
    
    0
  • Comment author
    A J

    He Bartosz Chlebowicz, could you share your site where I can test this as a logged out user?

    The memberscript should have taken care of this by default, as if you check the project demo, logged out users can only see the CMS without the feature of saving / unsaving.

    So having a look at your site might help in troubleshooting the issue faster.

    I was testing the script you shared in personal dummy site and I made a slight change to the code via which now logged out members can't see any error in the console which you shared.

    Just replace this line of code in checkMemberLogin() function:

    const member = await memberstack.getCurrentMember();
    

    to the following line:

    const member = (await memberstack.getCurrentMember()).data; 
    

    I have tested this in my site and logged in users can save / unsave items as usual, additionally logged out-users do not have any error in the console regarding this feature. Hope this helps.

    0
  • Comment author
    Bartosz Chlebowicz

    Hi, I managed to fix it! Thank you.

    0

Please sign in to leave a comment.