// Current selection state let currentBillingCycle = 'monthly'; let currentCurrency = 'USD'; let isProcessing = false; // Plan pricing configuration (matching pricing.html logic) const planPricing = { starter: { monthly: { USD: 7.5, GBP: 5, EUR: 7.5 }, yearly: { USD: 75, GBP: 50, EUR: 75 } }, professional: { monthly: { USD: 25, GBP: 20, EUR: 25 }, yearly: { USD: 250, GBP: 200, EUR: 250 } }, enterprise: { monthly: { USD: 75, GBP: 60, EUR: 75 }, yearly: { USD: 750, GBP: 600, EUR: 750 } } }; // Currency symbols const currencySymbols = { USD: '$', GBP: 'Β£', EUR: '€' }; // Helper to get auth headers from localStorage function getAuthHeaders() { try { const userStr = localStorage.getItem('wordpress_plugin_ai_user') || localStorage.getItem('shopify_ai_user'); if (userStr) { const user = JSON.parse(userStr); if (user && user.sessionToken) { return { 'Authorization': `Bearer ${user.sessionToken}` }; } } } catch (err) { console.warn('Failed to get auth headers from localStorage', err); } return {}; } // Initialize on page load document.addEventListener('DOMContentLoaded', function() { setupBillingCycleToggle(); setupCurrencyDropdown(); setupPlanSelection(); updatePlanPrices(); autoDetectCurrency(); // Check for pre-selected plan from URL query parameter const urlParams = new URLSearchParams(window.location.search); const preselectedPlan = urlParams.get('plan'); if (preselectedPlan) { preselectPlan(preselectedPlan); } }); function preselectPlan(plan) { const card = document.querySelector(`.plan-card[data-plan="${plan}"]`); if (card) { // Add visual selection state const allCards = document.querySelectorAll('.plan-card'); allCards.forEach(c => { c.classList.remove('ring-4', 'ring-green-700', 'ring-offset-2'); }); card.classList.add('ring-4', 'ring-green-700', 'ring-offset-2'); // Auto-trigger checkout for paid plans (hobby is free, no checkout needed) if (plan !== 'hobby') { // Small delay to ensure UI is ready setTimeout(() => { triggerPlanSelection(plan); }, 100); } } } // Separate function to trigger plan selection (can be called from click or auto-trigger) async function triggerPlanSelection(plan) { // Don't process if already in progress if (isProcessing) return; const card = document.querySelector(`.plan-card[data-plan="${plan}"]`); if (!card) return; console.log('Plan selected:', plan); isProcessing = true; // Update UI state const allCards = document.querySelectorAll('.plan-card'); allCards.forEach(c => { c.classList.remove('ring-4', 'ring-green-700', 'ring-offset-2'); }); card.classList.add('ring-4', 'ring-green-700', 'ring-offset-2'); // Disable all buttons during selection const allButtons = document.querySelectorAll('.plan-btn'); allButtons.forEach(btn => { btn.disabled = true; btn.textContent = 'Processing...'; btn.classList.add('opacity-50', 'cursor-not-allowed'); }); try { const authHeaders = getAuthHeaders(); let data; if (plan === 'hobby') { // Hobby plan is free, use original endpoint const response = await fetch('/api/select-plan', { method: 'POST', headers: { 'Content-Type': 'application/json', ...authHeaders }, body: JSON.stringify({ plan }), credentials: 'include', }); data = await response.json(); if (response.ok && data.ok) { window.location.href = '/apps'; } else { throw new Error(data.error || 'Failed to select plan'); } } else { // Paid plans use inline subscription checkout const response = await fetch('/api/subscription/checkout', { method: 'POST', headers: { 'Content-Type': 'application/json', ...authHeaders }, body: JSON.stringify({ plan: plan, billingCycle: currentBillingCycle, currency: currentCurrency.toLowerCase(), inline: true }), credentials: 'include', }); data = await response.json(); if (response.ok && data.sessionId) { // Use Dodo inline checkout - prefer inlineCheckoutUrl if available, otherwise use checkoutUrl const checkoutUrl = data.inlineCheckoutUrl || data.checkoutUrl; if (checkoutUrl) { await openInlineCheckout(checkoutUrl, data.sessionId); } else { throw new Error('No checkout URL provided'); } } else { throw new Error(data.error || 'Failed to start checkout'); } } } catch (error) { console.error('Error selecting plan:', error); alert(error.message || 'Failed to select plan. Please try again.'); // Re-enable buttons allButtons.forEach(btn => { btn.disabled = false; const planType = btn.getAttribute('data-plan'); if (planType === 'hobby') { btn.textContent = 'Start for Free'; } else if (planType === 'starter') { btn.textContent = 'Choose Starter'; } else if (planType === 'professional') { btn.textContent = 'Get Started'; } else if (planType === 'enterprise') { btn.textContent = 'Choose Enterprise'; } btn.classList.remove('opacity-50', 'cursor-not-allowed'); }); isProcessing = false; } } function setupBillingCycleToggle() { const monthlyBtn = document.getElementById('monthly-toggle'); const yearlyBtn = document.getElementById('yearly-toggle'); if (!monthlyBtn || !yearlyBtn) return; monthlyBtn.addEventListener('click', () => { currentBillingCycle = 'monthly'; monthlyBtn.className = 'px-6 py-2 rounded-full text-sm font-medium bg-green-700 text-white shadow-sm transition-all'; yearlyBtn.className = 'px-6 py-2 rounded-full text-sm font-medium text-gray-600 hover:text-gray-900 transition-all'; updatePlanPrices(); }); yearlyBtn.addEventListener('click', () => { currentBillingCycle = 'yearly'; yearlyBtn.className = 'px-6 py-2 rounded-full text-sm font-medium bg-green-700 text-white shadow-sm transition-all'; monthlyBtn.className = 'px-6 py-2 rounded-full text-sm font-medium text-gray-600 hover:text-gray-900 transition-all'; updatePlanPrices(); }); } function setupCurrencyDropdown() { const dropdown = document.getElementById('currency-dropdown'); const btn = document.getElementById('currency-btn'); const options = document.getElementById('currency-options'); const chevron = document.getElementById('currency-chevron'); if (!dropdown || !btn || !options) return; btn.addEventListener('click', (e) => { e.stopPropagation(); const isOpen = !dropdown.classList.contains('open'); if (isOpen) { dropdown.classList.add('open'); options.classList.remove('hidden'); if (chevron) chevron.style.transform = 'rotate(180deg)'; } else { dropdown.classList.remove('open'); options.classList.add('hidden'); if (chevron) chevron.style.transform = 'rotate(0deg)'; } }); // Handle currency selection document.querySelectorAll('.currency-option').forEach(option => { option.addEventListener('click', (e) => { e.preventDefault(); const currency = option.getAttribute('data-value'); currentCurrency = currency; // Update button display const flags = { USD: 'πŸ‡ΊπŸ‡Έ', GBP: 'πŸ‡¬πŸ‡§', EUR: 'πŸ‡ͺπŸ‡Ί' }; const flagEl = document.getElementById('currency-flag'); const codeEl = document.getElementById('currency-code'); if (flagEl) flagEl.textContent = flags[currency]; if (codeEl) codeEl.textContent = currency; // Close dropdown dropdown.classList.remove('open'); options.classList.add('hidden'); if (chevron) chevron.style.transform = 'rotate(0deg)'; updatePlanPrices(); }); }); // Close dropdown when clicking outside document.addEventListener('click', () => { dropdown.classList.remove('open'); options.classList.add('hidden'); if (chevron) chevron.style.transform = 'rotate(0deg)'; }); } function updatePlanPrices() { // Update Hobby plan price const hobbyPrice = document.getElementById('hobby-price'); const hobbyPeriod = document.getElementById('hobby-period'); if (hobbyPrice) hobbyPrice.textContent = currencySymbols[currentCurrency] + '0'; if (hobbyPeriod) hobbyPeriod.textContent = currentBillingCycle === 'monthly' ? '/mo' : '/yr'; // Update Starter plan price const starterPrice = document.getElementById('starter-price'); const starterPeriod = document.getElementById('starter-period'); const starterAmount = planPricing.starter[currentBillingCycle][currentCurrency]; if (starterPrice) starterPrice.textContent = currencySymbols[currentCurrency] + starterAmount.toFixed(starterAmount % 1 === 0 ? 0 : 2); if (starterPeriod) starterPeriod.textContent = currentBillingCycle === 'monthly' ? '/mo' : '/yr'; // Update Professional plan price const proPrice = document.getElementById('pro-price'); const proPeriod = document.getElementById('pro-period'); const proAmount = planPricing.professional[currentBillingCycle][currentCurrency]; if (proPrice) proPrice.textContent = currencySymbols[currentCurrency] + proAmount.toFixed(proAmount % 1 === 0 ? 0 : 2); if (proPeriod) proPeriod.textContent = currentBillingCycle === 'monthly' ? '/mo' : '/yr'; // Update Enterprise plan price const enterprisePrice = document.getElementById('enterprise-price'); const enterprisePeriod = document.getElementById('enterprise-period'); const enterpriseAmount = planPricing.enterprise[currentBillingCycle][currentCurrency]; if (enterprisePrice) enterprisePrice.textContent = currencySymbols[currentCurrency] + enterpriseAmount.toFixed(enterpriseAmount % 1 === 0 ? 0 : 2); if (enterprisePeriod) enterprisePeriod.textContent = currentBillingCycle === 'monthly' ? '/mo' : '/yr'; } function setupPlanSelection() { // Only handle card clicks to avoid double-triggering document.querySelectorAll('.plan-card').forEach(card => { card.addEventListener('click', async (e) => { // Let links within the card work normally if (e.target.closest('a')) return; e.preventDefault(); const plan = card.getAttribute('data-plan'); if (!plan) return; // Use the shared triggerPlanSelection function triggerPlanSelection(plan); }); }); // Prevent button clicks from bubbling to card (card listener handles everything) document.querySelectorAll('.plan-btn').forEach(btn => { btn.addEventListener('click', (e) => { // Just let it bubble to the card }); }); } // Detect Location and Set Currency async function autoDetectCurrency() { try { const response = await fetch('https://ipapi.co/json/'); const data = await response.json(); if (data.currency && currencySymbols[data.currency]) { currentCurrency = data.currency; // Update button display const flags = { USD: 'πŸ‡ΊπŸ‡Έ', GBP: 'πŸ‡¬πŸ‡§', EUR: 'πŸ‡ͺπŸ‡Ί' }; const flagEl = document.getElementById('currency-flag'); const codeEl = document.getElementById('currency-code'); if (flagEl) flagEl.textContent = flags[currentCurrency]; if (codeEl) codeEl.textContent = currentCurrency; updatePlanPrices(); } } catch (err) { console.log('Currency detection failed, defaulting to USD'); } } async function openInlineCheckout(checkoutUrl, sessionId) { const modal = document.getElementById('payment-modal'); const container = document.getElementById('payment-frame-container'); container.innerHTML = ``; modal.classList.add('active'); let pollCount = 0; const maxPolls = 180; const pollInterval = 1000; const checkPaymentStatus = async () => { try { pollCount++; const resp = await fetch(`/api/subscription/confirm?session_id=${encodeURIComponent(sessionId)}`, { credentials: 'include' }); if (resp.ok) { const data = await resp.json(); if (data.ok) { clearInterval(pollTimer); closeCheckoutModal(); window.location.href = '/subscription-success'; return; } } if (pollCount >= maxPolls) { clearInterval(pollTimer); closeCheckoutModal(); alert('Payment confirmation timeout. Please check your account status.'); reenableButtons(); isProcessing = false; } } catch (error) { console.error('Error checking payment status:', error); } }; const pollTimer = setInterval(checkPaymentStatus, pollInterval); function closeCheckoutModal() { clearInterval(pollTimer); modal.classList.remove('active'); container.innerHTML = ''; } function reenableButtons() { const allButtons = document.querySelectorAll('.plan-btn'); allButtons.forEach(btn => { btn.disabled = false; const planType = btn.getAttribute('data-plan'); if (planType === 'hobby') { btn.textContent = 'Start for Free'; } else if (planType === 'starter') { btn.textContent = 'Choose Starter'; } else if (planType === 'professional') { btn.textContent = 'Get Started'; } else if (planType === 'enterprise') { btn.textContent = 'Choose Enterprise'; } btn.classList.remove('opacity-50', 'cursor-not-allowed'); }); } document.getElementById('payment-modal-close').onclick = () => { closeCheckoutModal(); reenableButtons(); isProcessing = false; }; modal.onclick = (e) => { if (e.target === modal) { closeCheckoutModal(); reenableButtons(); isProcessing = false; } }; const handleEsc = (e) => { if (e.key === 'Escape') { closeCheckoutModal(); reenableButtons(); isProcessing = false; } }; document.addEventListener('keydown', handleEsc); } // Email Signup Form Handler const signupForm = document.getElementById('footer-signup-form'); const signupMessage = document.getElementById('signup-message'); if (signupForm) { signupForm.addEventListener('submit', async (e) => { e.preventDefault(); const email = signupForm.querySelector('input[name="email"]').value; const button = signupForm.querySelector('button'); button.disabled = true; button.textContent = 'Subscribing...'; try { const response = await fetch('https://emailmarketing.modelrailway3d.co.uk/api/webhooks/incoming/wh_0Z49zi_DGj4-lKJMOPO8-g', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email: email, source: 'plugin_compass_select_plan', timestamp: new Date().toISOString() }) }); if (response.ok) { signupMessage.textContent = 'Successfully subscribed!'; signupMessage.className = 'mt-2 text-xs text-green-600'; signupForm.reset(); } else { throw new Error('Failed to subscribe'); } } catch (error) { signupMessage.textContent = 'Failed to subscribe. Please try again.'; signupMessage.className = 'mt-2 text-xs text-red-600'; } finally { signupMessage.classList.remove('hidden'); button.disabled = false; button.textContent = 'Subscribe'; setTimeout(() => { signupMessage.classList.add('hidden'); }, 5000); } }); } }