SHOPPING WISH LISTS WITH FIREBASE (PART 2 - Redundant)

I have implemented wish list functionality into my store. Wish list functionality allows users to save and manage a list of desired items or products they may want to purchase in the future. By clicking the heart icon in the category view you can add, or remove products in the wish list individually, and by clicking the button on the cart page, all items in cart are added to the wish list. I use Firebase for this, which I discussed in the previous post. Below you will find a lot of code that handles displaying wished for items on a separate page, however, I just made this code redundant by using a live, or instant approach which filters the shop grid instead. I am keeping the code below for archival purposes only, as it may have a few functions which could be of use later.

HTML:

JAVASCRIPT:

<!--WISHLIST DIRECTORY BUTTON IN SHOP-->
<div id="wishlistPageButton" class="wishlistPageButton"></div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const subString = 'shop';
const subStringTwo = 'shop/p/';
let getURL = window.location.href;  
const wishlistPageButton = document.querySelector('.wishlistPageButton');
if (getURL.includes(subString) && !getURL.includes(subStringTwo)) {
let isTouch = false;
const headerActions = document.querySelector('.header-actions');
function checkHeader() {
const styles = window.getComputedStyle(headerActions);
isTouch = styles.getPropertyValue('display') !== 'flex';
}
checkHeader();
//place the button
var nestedCategories = document.querySelector('.nested-category-tree-wrapper');
var categoryList = nestedCategories.querySelector('ul');
categoryList.insertAdjacentElement('afterend', wishlistPageButton);
isTouch ? wishlistPageButton.classList.add('mobile') : wishlistPageButton.classList.remove('mobile');
//handle pushing the button
wishlistPageButton.addEventListener('click', function(event) {
window.location.href = '/wishlist';
});
} else {
wishlistPageButton.remove();
}
}); 
</script>

<!--WISHLIST PAGE-->
<script type="module">
// init firebase
import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.12.5/firebase-app.js';
import { getAuth, onAuthStateChanged } from 'https://www.gstatic.com/firebasejs/10.12.5/firebase-auth.js';
import { getFirestore, collection, getDocs, doc, deleteDoc } from 'https://www.gstatic.com/firebasejs/10.12.5/firebase-firestore.js';
const firebaseConfig = {apiKey: "AIzaSyBZSF7gaLoqI5ni_ntvvhujH1kL5h5OaEs",
authDomain: "-----------",
projectId: "--------",
storageBucket: "--------------",
messagingSenderId: "-------",
appId: "-----------------",
measurementId: "--------"};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
// The usual page checks
document.addEventListener('DOMContentLoaded', () => {
const subString = 'wishlist';
const getURL = window.location.href;
if (getURL.includes(subString)) {
onAuthStateChanged(auth, async (user) => {
if (user) {
console.log('User authenticated');
// Function to fetch the wishlist item IDs
async function fetchWishlistItemIds() {
try {
const wishlistRef = collection(db, 'users', user.uid, 'wishlist');
const querySnapshot = await getDocs(wishlistRef);
const itemIds = querySnapshot.docs.map(doc => doc.id); // Get item IDs
return itemIds;
} catch (error) {
console.error('Error fetching wishlist items:', error);
return []; // Return an empty array in case of an error
}
}
// Function to remove an item from the wishlist
async function removeItemFromWishlist(itemId, itemElement) {
try {
const itemRef = doc(db, 'users', user.uid, 'wishlist', itemId);
await deleteDoc(itemRef);
console.log(`Item ${itemId} removed from wishlist`);
// Hide the specific item element instead of reloading
itemElement.style.display = 'none';
// Check if all items are removed and display a message if needed
const remainingItems = document.querySelectorAll('#product-grid .product-item');
if (remainingItems.length === 0) {
const productContent = document.querySelector('.content-wrapper');
if (productContent) {
productContent.innerHTML = `<p>None, how despondent!</p>`;
productContent.style.display = 'flex';

}
}
} catch (error) {
console.error('Error removing item from wishlist:', error);
}
}
// Function to fetch and display products
async function fetchAndDisplayProducts(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
// Access the products from the 'items' key
const products = data.items;
// Get wishlist item IDs
const wishlistItemIds = await fetchWishlistItemIds();
// Create a grid container element
const gridContainer = document.createElement('div');
gridContainer.id = 'product-grid';
gridContainer.className = 'product-grid';
// Flag to check if any products were added
let hasProducts = false;
// Generate HTML for each product
products.forEach((product) => {
if (wishlistItemIds.includes(product.id)) { // Check if product is in wishlist
hasProducts = true;
let assetUrl = product.assetUrl;
if (!assetUrl.includes('images.squarespace')) {
if (product.items && product.items.length > 0) {
assetUrl = product.items[0].assetUrl;
}
}
const productElement = document.createElement('div');
productElement.className = 'product-item';
productElement.innerHTML = `
<a href="${product.fullUrl}">
<img src="${assetUrl}" alt="${product.name}" class="wishlistItemImage" style="opacity: 1; width: 400px; height: 400px; border: solid 2px black; transition: all 0.3s ease !important;">
<h4 class="wishlistItemTitle" style="cursor: pointer">${product.title}</h4>
</a>
<button class="remove-from-wishlist sqs-block-button-element--medium sqs-button-element--primary sqs-block-button-element sqs-block-button-container" style="text-align: right" data-product-id="${product.id}">Discard</button>
`;
// Append the product element to the grid container
gridContainer.appendChild(productElement);
}
});
const productSection = document.querySelector('[data-section-id="66bbf4f37d8e3666c9d71b7b"]');
const productContent = productSection.querySelector('.content-wrapper');
if (productContent) {
productContent.innerHTML = ''; // Clear any existing content
if (hasProducts) {
productContent.appendChild(gridContainer);
} else {
productContent.innerHTML = `<p>None, how despondent!</p>`;
productContent.style.display = 'flex';
}
// Add event listeners to remove buttons
document.querySelectorAll('.remove-from-wishlist').forEach(button => {
button.addEventListener('click', (event) => {
event.preventDefault(); // Prevent default action if inside a link
const itemId = button.getAttribute('data-product-id');
const itemElement = button.closest('.product-item'); // Get the product item element
removeItemFromWishlist(itemId, itemElement);
});
});
}
} catch (error) {
console.error('Error fetching the products:', error);
const productSection = document.querySelector('[data-section-id="66bbf4f37d8e3666c9d71b7b"]');
const productContent = productSection.querySelector('.content-wrapper');
if (productContent) {
productContent.innerHTML = `<p>None, how despondent!</p>`;
productContent.style.display = 'flex';
}
}
}
const productsUrl = 'https://www.polivantage.com/shop?format=json-pretty';
fetchAndDisplayProducts(productsUrl);
} else {
console.error('User not authenticated');
window.location.href = '/login';
}
});
}
});
</script>
CSS:

section[data-section-id="66bbf4f37d8e3666c9d71b7b"] .content-wrapper .content {
  width: 0 !important;
}
.product-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 25px; 
}
@media only screen and (max-width:790px) {
.product-grid {
  grid-template-columns: repeat(1, 1fr);
  }
}
.product-item {
  margin-bottom: 40px;
  transition: all 0.3s ease; 
}
.product-item:hover .wishlistItemImage {
  transform: scale(1.05);
}
.wishlistItemTitle {
  margin: 0;
  margin-bottom: 20px;
  margin-top: 10px;
  text-align: center;
  word-wrap: break-word;
  overflow-wrap: break-word;
  max-width: 100%;
}
.wishlistItemImage {
  margin: 0;
  transition: all 0.3s ease; 
}
.remove-from-wishlist {
  width: 100%;
  text-align: right;
}
//wishlist category button
#wishlistPageButton {
  background-image: url('https://images.squarespace-cdn.com/content/v1/6654b2fee26f292de13f1a9d/d88a683e-1625-4ab8-87f8-69467233fa6b/heartGrabbedicon.png');
  width: 60px !important;
  height: 60px !important;
  margin-top: -15px;
  pointer-events: auto;
  cursor: pointer;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  transition: all 0.6s ease;
  scale: 1;
}
#wishlistPageButton.mobile {
  margin-left: 160px;
  margin-bottom: 20px;
}
#wishlistPageButton:hover {
   transition: all 0.3s ease;
  scale: 1.15;
}
Previous
Previous

User account page with firebase

Next
Next

SHOPPING WISH LISTS WITH FIREBASE (PART 1)