User account page with firebase

The account page, dubbed Hearth, is the prime residency of the logged in user. It has buttons to view your wish list (desires) and liked images (collections). There is a button to edit your squarespace account and a button to edit your profile (the dossier). There is a button to enter peers chat, and a button to chat with the warden AI, which is my customer service chat bot with a strong personality. There is finally, also a button to log. This page will be extended as I make polivantage a more anchored experience. For now the bulk of user customization takes place in the dossier.

HTML:

JAVASCRIPT:

<script type="module">
// Initialize Firebase
import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.12.5/firebase-app.js';
import { getAuth, signOut, onAuthStateChanged, updatePassword, reauthenticateWithCredential, EmailAuthProvider } from 'https://www.gstatic.com/firebasejs/10.12.5/firebase-auth.js';
import { getFirestore, collection, setDoc, writeBatch, deleteDoc, getDocs, query, serverTimestamp, where, doc, getDoc } from 'https://www.gstatic.com/firebasejs/10.12.5/firebase-firestore.js';
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
//main stuff
document.addEventListener('DOMContentLoaded', function() {
const subString = 'useraccount';
const getURL = window.location.href;
const baseURL = "https://www.polivantage.com/";
//show and hide popover
let hideTimeout;
var popover = document.getElementById('custom-popover');
var popoverMessage = document.getElementById('popover-message');
function showPopover(message) {
popoverMessage.textContent = message;
popover.classList.add('show');
popover.style.pointerEvents = 'auto';
clearTimeout(hideTimeout);
hideTimeout = setTimeout(function() {
popover.classList.remove('show');
popover.style.pointerEvents = 'none';
}, 3000);
}
if (getURL.includes(subString)) {
onAuthStateChanged(auth, async (user) => {
if (user) {
const imagesLikedTextBlock = document.getElementById('block-yui_3_17_2_1_1723629178851_25945');
const imagesLikedText = imagesLikedTextBlock.querySelector('p'); 
const statusTextBlock = document.getElementById('block-yui_3_17_2_1_1723629178851_17416');
const statusText = statusTextBlock.querySelector('p');
const SignOutButton = document.getElementById('block-ed832b202fab80c68286');
const desiresButton = document.getElementById('block-77b36cfb140b770fa15e');
const desiresTextBlock = document.getElementById('block-2faf595f9b3381a46ed6');
const desiresText = desiresTextBlock.querySelector('p');    
const userAccountBadge = document.querySelector('.user-accounts-link'); 
const userAccountLink = userAccountBadge.querySelector('a'); 
const userAccountButton = document.getElementById('block-6456a0bb547b865b3236');
//squarespace user accounts link to button
userAccountButton.addEventListener('click', function(event) {
event.preventDefault();
userAccountLink.click();
});     
//Sign out logic
SignOutButton.addEventListener('click', async (event) => {
event.preventDefault();
try {
const user = auth.currentUser;
if (user) {
const userId = user.uid;
await setDoc(doc(db, 'users', userId), {
status: 'offline',
lastStatusChange: serverTimestamp()
}, { merge: true });
await signOut(auth);
window.location.href = '/login';
}
} catch (error) {
statusText.textContent = '- Stay here traitor!'; // Sign out failed status
console.error('Sign out error', error);
}
});
function checkSelectOptions(productItem) {
var selects = productItem.querySelectorAll('select');
for (var i = 0; i < selects.length; i++) {
if (selects[i].selectedIndex === 0) {
return 'Please Select ' + selects[i].options[0].textContent;
	}
}
return null;
}
//display greeting
const userDocRef = doc(db, 'users', user.uid);
try {
const userDocSnap = await getDoc(userDocRef);
if (userDocSnap.exists()) {
const userData = userDocSnap.data();
const userCodename = userData.codename || 'secret'; // Default
statusText.textContent = userCodename === 'secret' ? 'Welcome Stranger.' : `Welcome ${userCodename}.`; // Use actual codename 
} else {
statusText.textContent = `Welcome Stranger.`; // Default greeting
}
} catch (error) {
console.error('Error fetching user data:', error);
$('#popoverMessage').off('click');
popoverMessage.style.color = "#ea4b1a";
showPopover('Error fetching your data.');
statusText.textContent = `Welcome Stranger.`; // Default greeting on error
}
//check if mobile view
let isTouch = false;
const headerActions = document.querySelector('.header-actions');
function checkHeader() {
const styles = window.getComputedStyle(headerActions);
isTouch = styles.getPropertyValue('display') !== 'flex';
}
checkHeader();
//sync wishlist from local and display number of desires and link to wishlist
desiresButton.addEventListener('click', function(event) {
event.preventDefault();
window.location.href = '/shop?view=wishlist';
});
const wishlistRef = collection(db, 'users', user.uid, 'wishlist');
try {
const wishlistSnapshot = await getDocs(wishlistRef);
let firestoreWishlist = wishlistSnapshot.docs.map(doc => doc.id);
let localWishlist = JSON.parse(localStorage.getItem('wishlist') || '[]');
if (localWishlist){
const combinedWishlist = Array.from(new Set([...localWishlist, ...firestoreWishlist]));
const batch = writeBatch(db);
combinedWishlist.forEach(itemId => {
const itemDocRef = doc(wishlistRef, itemId);
batch.set(itemDocRef, { itemId: itemId });
});
await batch.commit(); 
localStorage.removeItem('wishlist');
}
const desireCount = wishlistSnapshot.size; 
const desireWord = desireCount === 1 ? 'desire' : 'desires';
desiresText.textContent = `You have ${desireCount} ${desireWord}.`;
} catch (error) {
console.error('Error fetching liked images:', error);
$('#popoverMessage').off('click');
popoverMessage.style.color = "#ea4b1a";
showPopover('Error fetching desires');
}    
//Display number of liked images
const likedImagesRef = collection(db, 'users', user.uid, 'likedImages');
try {
const likedImagesSnapshot = await getDocs(likedImagesRef);
const itemCount = likedImagesSnapshot.size;
const itemWord = itemCount === 1 ? 'sigil' : 'sigils';
imagesLikedText.textContent = `You are considering ${itemCount} ${itemWord}.`;
} catch (error) {
console.error('Error fetching liked images:', error);
$('#popoverMessage').off('click');
popoverMessage.style.color = "#ea4b1a";
showPopover('Error fetching liked images');
}  
//exit strategy
} else {
window.location.href = '/login'; //if not logged in redirect
}
});
}
});
</script>
CSS:

This page had more code to change password and code name, this functionality has been moved to the dossier page.

Previous
Previous

Snappy Lightbox for gallery

Next
Next

SHOPPING WISH LISTS WITH FIREBASE (PART 2 - Redundant)