// Helper function to sanitize religion names for IDs function sanitizeReligionName(name) { return name.replace(/\s+/g, '-'); } // ==================== FIREBASE AUTHENTICATION ==================== // Google Sign-In with Firebase async function signInWithGoogle() { if (!window.firebaseEnabled || !window.firebaseAuth) { const resultDiv = document.getElementById('result'); if (resultDiv) { resultDiv.innerHTML = '
⚠️ Firebase not configured
'; } return; } const provider = new firebase.auth.GoogleAuthProvider(); // Configure provider for better popup behavior provider.setCustomParameters({ prompt: 'select_account' // Always show account selection }); try { // Show loading state const resultDiv = document.getElementById('result'); if (resultDiv) { resultDiv.innerHTML = 'Opening sign-in window...
'; } const result = await window.firebaseAuth.signInWithPopup(provider); const user = result.user; if (resultDiv) { resultDiv.innerHTML = 'Signing in...
'; } // Get ID token to send to backend const idToken = await user.getIdToken(); // Send to backend for session creation const endpoint = window.location.pathname === '/signup' ? '/signup' : '/login'; const response = await fetch(endpoint, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({idToken}), credentials: 'same-origin' }); const data = await response.json(); if (data.success) { window.location.href = '/assessment'; } else { const resultDiv = document.getElementById('result'); if (resultDiv) { resultDiv.innerHTML = `${data.message || 'Authentication failed'}
`; } } } catch (error) { console.error('Google Sign-In Error:', error); console.error('Error code:', error.code); console.error('Error details:', error); const resultDiv = document.getElementById('result'); let errorMsg = ''; // Handle specific error cases if (error.code === 'auth/popup-closed-by-user') { errorMsg = '❌ Sign-in window was closed. Please try again and complete the sign-in process.'; } else if (error.code === 'auth/popup-blocked') { errorMsg = '❌ Pop-up was blocked by your browser. Please allow pop-ups for this site and try again.'; } else if (error.code === 'auth/cancelled-popup-request') { errorMsg = '❌ Another sign-in is in progress. Please wait a moment and try again.'; } else if (error.code === 'auth/unauthorized-domain') { errorMsg = '❌ This domain is not authorized for Google Sign-In. Please contact the administrator.'; } else if (error.code === 'auth/operation-not-allowed') { errorMsg = '❌ Google Sign-In is not enabled. Please contact the administrator.'; } else if (error.code === 'auth/network-request-failed') { errorMsg = '❌ Network error. Please check your internet connection and try again.'; } else { errorMsg = `❌ ${error.message || 'Google Sign-In failed. Please try again.'}`; } if (resultDiv) { resultDiv.innerHTML = `${errorMsg}
`; } } } // Firebase Email/Password Authentication async function authenticateWithFirebase(email, password, isSignup) { if (!window.firebaseEnabled || !window.firebaseAuth) { return null; // Fall back to legacy auth } try { let userCredential; if (isSignup) { // Create new user with Firebase userCredential = await window.firebaseAuth.createUserWithEmailAndPassword(email, password); // Send email verification await userCredential.user.sendEmailVerification(); } else { // Sign in existing user userCredential = await window.firebaseAuth.signInWithEmailAndPassword(email, password); // Check if email is verified if (!userCredential.user.emailVerified) { document.getElementById('result').innerHTML = '⚠️ Please verify your email first. Check your inbox.
'; await window.firebaseAuth.signOut(); return null; } } // Get ID token const idToken = await userCredential.user.getIdToken(); return idToken; } catch (error) { console.error('Firebase Auth Error:', error); throw error; } } // ==================== AUTHENTICATION ==================== async function authenticate() { const email = document.getElementById('authEmail').value.trim(); const username = document.getElementById('authUsername') ? document.getElementById('authUsername').value.trim() : ''; const password = document.getElementById('authPassword').value; if (!email || !password) { document.getElementById('result').innerHTML = '⚠️ Please fill in all fields
'; return; } const isSignup = window.location.pathname === '/signup'; const endpoint = isSignup ? '/signup' : '/login'; // Try Firebase authentication first if available if (window.firebaseEnabled) { try { const idToken = await authenticateWithFirebase(email, password, isSignup); if (!idToken) { return; // Error already displayed } // Send token to backend const response = await fetch(endpoint, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({idToken}), credentials: 'same-origin' }); const data = await response.json(); if (data.success) { if (isSignup) { document.getElementById('result').innerHTML = '✅ Account created! Please check your email to verify.
'; } else { window.location.href = '/assessment'; } } else { document.getElementById('result').innerHTML = `${data.message || 'Authentication failed'}
`; } return; } catch (error) { console.error('Firebase auth error:', error); document.getElementById('result').innerHTML = `${error.message || 'Authentication failed'}
`; return; } } // Legacy authentication fallback (if Firebase is disabled) const body = isSignup ? {username, password, email} : {username, password}; fetch(endpoint, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(body), credentials: 'same-origin' }) .then(response => { if (!response.ok) { return response.json().then(err => Promise.reject(err)); } return response.json(); }) .then(data => { if (data.success) { if (data.verification_sent) { document.getElementById('result').innerHTML = '✅ ' + (data.message || 'Account created! Please check your email to verify.') + '
'; } else { window.location.href = '/assessment'; } } else { document.getElementById('result').innerHTML = `${data.message || 'Authentication failed'}
`; } }) .catch(error => { document.getElementById('result').innerHTML = `${error.message || 'Network error. Please try again.'}
`; }); } function switchAuth() { const newPath = window.location.pathname === '/signup' ? '/login' : '/signup'; window.location.href = newPath; } function resetPassword() { const email = document.getElementById('resetEmail').value.trim(); if (!email) { document.getElementById('result').innerHTML = '⚠️ Please enter your email
'; return; } fetch('/forgot-password', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({email}), credentials: 'same-origin' }) .then(response => { if (!response.ok) { return response.json().then(err => Promise.reject(err)); } return response.json(); }) .then(data => { if (data.success) { document.getElementById('result').innerHTML = '✅ Password reset link sent! Check your email (or server console in dev mode).
'; } else { document.getElementById('result').innerHTML = `${data.message || 'Failed to send reset link'}
`; } }) .catch(error => { document.getElementById('result').innerHTML = `${error.message || 'Network error. Please try again.'}
`; }); } function submitPasswordReset() { const token = document.getElementById('resetToken').value; const password = document.getElementById('resetPassword').value; if (!password) { document.getElementById('result').innerHTML = '⚠️ Please enter a new password
'; return; } fetch('/reset-password-submit', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({token, password}), credentials: 'same-origin' }) .then(response => { if (!response.ok) { return response.json().then(err => Promise.reject(err)); } return response.json(); }) .then(data => { if (data.success) { document.getElementById('result').innerHTML = '✅ Password reset successfully! Redirecting to login...
'; setTimeout(() => window.location.href = '/login', 1500); } else { document.getElementById('result').innerHTML = `${data.message || 'Failed to reset password'}
`; } }) .catch(error => { document.getElementById('result').innerHTML = `${error.message || 'Network error. Please try again.'}
`; }); } // ==================== ASSESSMENT ==================== var currentQuestion = 1; var maxQuestionReached = 1; var assessmentDataEl = document.getElementById('assessmentData'); var totalQuestions = assessmentDataEl ? parseInt(assessmentDataEl.getAttribute('data-total')) : 0; var questionIds = assessmentDataEl ? JSON.parse(assessmentDataEl.getAttribute('data-ids')) : []; // Show first question on load window.addEventListener('DOMContentLoaded', function() { if (assessmentDataEl) { showQuestion(1); } // Add Enter key listener for password field if it exists const passwordField = document.getElementById('authPassword'); if (passwordField) { passwordField.addEventListener('keypress', function(e) { if (e.key === 'Enter') authenticate(); }); } }); function showQuestion(questionIndex) { if (questionIndex > maxQuestionReached + 1) return; if (questionIndex > maxQuestionReached) maxQuestionReached = questionIndex; document.querySelectorAll('.question-block').forEach(function(block) { block.classList.remove('active'); var blockIndex = parseInt(block.getAttribute('data-question-index')); if (blockIndex === questionIndex) block.classList.add('active'); }); currentQuestion = questionIndex; document.getElementById('questionCounter').textContent = 'Question ' + questionIndex + ' of ' + totalQuestions; document.getElementById('progressBar').style.width = ((questionIndex - 1) / (totalQuestions - 1)) * 100 + '%'; updateNavigationButtons(); } function updateNavigationButtons() { // Check if we're on the last question and it's answered var currentQuestionId = questionIds[currentQuestion - 1]; var radioName = 'q' + currentQuestionId; var isAnswered = document.querySelector('input[name="' + radioName + '"]:checked') !== null; if (currentQuestion === totalQuestions && isAnswered) { document.getElementById('submitBtn').style.display = 'block'; } } function handleAnswer(radioElement) { var questionIndex = parseInt(radioElement.getAttribute('data-question-index')); // Only process if this is the current question if (questionIndex !== currentQuestion) { return; } // Auto-advance to next question after selection setTimeout(function() { if (questionIndex < totalQuestions) { showQuestion(questionIndex + 1); } else { // Last question - show submit button document.getElementById('submitBtn').style.display = 'block'; } }, 400); } function goToNext() { if (currentQuestion < totalQuestions) { showQuestion(currentQuestion + 1); } } function goToPrev() { if (currentQuestion > 1) { showQuestion(currentQuestion - 1); } } function submitAssessment() { var form = document.getElementById('assessmentForm'); var answers = []; questionIds.forEach(function(qId) { var radioName = 'q' + qId; var selectedRadio = form.querySelector('input[name="' + radioName + '"]:checked'); if (selectedRadio) { answers.push({ question_id: qId, answer: selectedRadio.value }); } }); if (answers.length !== totalQuestions) { document.getElementById('errorMsg').innerHTML = '⚠️ Please answer all questions
'; return; } document.getElementById('submitBtn').disabled = true; document.getElementById('submitBtn').textContent = '✨ Calculating...'; fetch('/submit_assessment', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({answers: answers}) }) .then(function(response) { return response.json(); }) .then(function(data) { if (data.success) { window.location.reload(); } else { document.getElementById('errorMsg').innerHTML = '' + data.message + '
'; document.getElementById('submitBtn').disabled = false; document.getElementById('submitBtn').textContent = '✨ Discover Your Path'; } }); } function resetAssessment() { if (!confirm('Are you sure you want to retake the assessment? Your current results will be cleared.')) { return; } fetch('/reset_assessment', { method: 'POST', headers: {'Content-Type': 'application/json'} }) .then(function(response) { return response.json(); }) .then(function(data) { if (data.success) { window.location.reload(); } }); } // ==================== SHARE RESULTS ==================== function shareResults() { const results = getResultsSummary(); const text = `My Spiritual Path Results:\n\n${results}\n\nTake the assessment: ${window.location.origin}`; if (navigator.share) { navigator.share({ title: 'Spiritual Path Results', text: text }); } else { navigator.clipboard.writeText(text); alert('Results copied to clipboard!'); } } function getResultsSummary() { const cards = document.querySelectorAll('.result-card'); return Array.from(cards).map((card, i) => { const title = card.querySelector('h3').textContent; const percentage = card.querySelector('.result-percentage').textContent; return `${i+1}. ${title} (${percentage})`; }).join('\n'); } // ==================== CHAT FUNCTIONALITY ==================== var chatHistories = {}; function formatBotResponse(text) { var div = document.createElement('div'); div.textContent = text; var escaped = div.innerHTML; // Check for bullet points if (escaped.match(/\*\s+/g) || escaped.match(/•\s+/g) || escaped.match(/^\s*-\s+/gm)) { var lines = escaped.split(/(?:\*|•|\n-)\s+/); if (lines.length > 1) { var formatted = lines[0].trim() ? lines[0].trim() + '