UNPKG

ultimate-jekyll-manager

Version:
272 lines (226 loc) 10.9 kB
// UI update functions for checkout import { state } from './state.js'; import { calculatePrices } from './pricing.js'; // Unified UI update function - handles all state changes export function updateAllUI() { console.log('updateAllUI called, product:', state.product); // Update product info document.getElementById('product-name').textContent = state.product.name; document.getElementById('product-description').textContent = state.product.description; // Update selected plan name in billing cycle section const $selectedPlanName = document.getElementById('selected-plan-name'); if ($selectedPlanName) { console.log('Updating selected-plan-name to:', state.product.name); $selectedPlanName.textContent = state.product.name; } else { console.log('selected-plan-name element not found'); } if (state.isSubscription) { // Show subscription toggle document.getElementById('subscription-toggle').classList.remove('d-none'); // Update prices in toggle buttons - annual shows monthly rate const annualMonthlyRate = (state.product.price_annually / 12).toFixed(2); document.getElementById('monthly-price-lg').textContent = `$${state.product.price_monthly.toFixed(2)}`; document.getElementById('annually-price-lg').textContent = `$${annualMonthlyRate}`; // Update payment text based on selected billing cycle const $paymentText = document.getElementById('billing-cycle-payment-text'); if ($paymentText) { if (state.billingCycle === 'monthly') { $paymentText.textContent = `$${state.product.price_monthly.toFixed(2)} monthly`; } else { $paymentText.textContent = `$${state.product.price_annually.toFixed(2)} annually`; } } // Calculate and update savings percentage const monthlyAnnual = state.product.price_monthly * 12; const annuallyPrice = state.product.price_annually; const savingsPercent = Math.round(((monthlyAnnual - annuallyPrice) / monthlyAnnual) * 100); // Update savings badge text const $savingsBadge = document.getElementById('savings-badge'); if ($savingsBadge) { $savingsBadge.textContent = `Save ${savingsPercent}%`; } // Get current pricing const basePrice = state.billingCycle === 'monthly' ? state.product.price_monthly : state.product.price_annually; // Calculate discounted price const discountAmount = (basePrice * state.discountPercent) / 100; const discountedPrice = basePrice - discountAmount; const period = state.billingCycle === 'monthly' ? '/mo' : '/yr'; const periodText = state.billingCycle === 'monthly' ? 'monthly' : 'annually'; // Update product price display (show discounted price) document.getElementById('product-price').textContent = `$${discountedPrice.toFixed(2)}${period}`; // Update recurring amount display (show discounted price) document.getElementById('recurring-amount').innerHTML = `$${discountedPrice.toFixed(2)} <span id="recurring-period">${periodText}</span>`; // Update button visual states updateBillingCycleButtons(); // Update trial badge based on current state updateTrialBadge(); // Helper function to update button text for specific payment method const updateButtonText = (paymentMethod, textContent) => { const buttons = document.querySelectorAll(`.payment-button[data-payment-method="${paymentMethod}"] span.fw-semibold`); buttons.forEach(span => { span.textContent = textContent; }); }; // Update payment button text based on trial if (state.hasFreeTrial) { // Update all payment buttons for free trial (keeping logic for future customization) updateButtonText('card', 'Credit/Debit Card'); // PayPal uses logo - no text to update updateButtonText('apple-pay', 'Apple Pay'); updateButtonText('google-pay', 'Google Pay'); updateButtonText('crypto', 'Crypto'); } else { // Reset to normal payment text updateButtonText('card', 'Credit/Debit Card'); // PayPal uses logo - no text to update updateButtonText('apple-pay', 'Apple Pay'); updateButtonText('google-pay', 'Google Pay'); updateButtonText('crypto', 'Crypto'); } // Update subscription terms updateSubscriptionTerms(); // Calculate and update all pricing calculatePrices(); } else { // One-time purchase document.getElementById('product-price').textContent = `$${state.product.price.toFixed(2)}`; calculatePrices(); } } // Update billing cycle button visual states function updateBillingCycleButtons() { const $monthlyLabel = document.querySelector('label[for="monthly"]'); const $annuallyLabel = document.querySelector('label[for="annually"]'); const $monthlyCheckmark = $monthlyLabel?.querySelector('span.rounded-circle'); const $annuallyCheckmark = $annuallyLabel?.querySelector('span.rounded-circle'); if ($monthlyLabel && $annuallyLabel && $monthlyCheckmark && $annuallyCheckmark) { // Remove any existing selected state $monthlyLabel.classList.remove('billing-selected'); $annuallyLabel.classList.remove('billing-selected'); if (state.billingCycle === 'monthly') { // Monthly is selected document.getElementById('monthly').checked = true; $monthlyLabel.classList.add('billing-selected'); $monthlyCheckmark.className = 'bg-primary text-light rounded-circle d-inline-flex align-items-center justify-content-center'; $annuallyCheckmark.className = 'bg-secondary bg-opacity-25 text-secondary rounded-circle d-inline-flex align-items-center justify-content-center'; } else { // Annually is selected document.getElementById('annually').checked = true; $annuallyLabel.classList.add('billing-selected'); $annuallyCheckmark.className = 'bg-primary text-light rounded-circle d-inline-flex align-items-center justify-content-center'; $monthlyCheckmark.className = 'bg-secondary bg-opacity-25 text-secondary rounded-circle d-inline-flex align-items-center justify-content-center'; } } } // Update trial badge function updateTrialBadge() { const $trialBadge = document.getElementById('trial-badge'); const $trialMessage = document.getElementById('trial-message'); if (state.hasFreeTrial) { $trialBadge.classList.remove('d-none'); $trialMessage.textContent = `Start with a ${state.product.free_trial_days}-day free trial`; } else { $trialBadge.classList.add('d-none'); } } // Update subscription terms text export function updateSubscriptionTerms() { const $termsDiv = document.getElementById('subscription-terms'); const $termsText = document.getElementById('terms-text'); if (!state.isSubscription) { $termsDiv.classList.add('d-none'); return; } if (state.hasFreeTrial) { // Calculate trial end date const trialEndDate = new Date(); trialEndDate.setDate(trialEndDate.getDate() + state.product.free_trial_days); const formattedDate = trialEndDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }); const basePrice = state.billingCycle === 'monthly' ? state.product.price_monthly : state.product.price_annually; // Apply discount to the recurring price (always calculate, even if 0%) const discountAmount = (basePrice * state.discountPercent) / 100; const discountedPrice = basePrice - discountAmount; const periodText = state.billingCycle === 'monthly' ? 'monthly' : 'annually'; $termsText.textContent = `You won't be charged for your free trial. On ${formattedDate}, your ${periodText} subscription will start and you'll be charged $${discountedPrice.toFixed(2)} plus applicable tax. Cancel anytime before then.`; $termsDiv.classList.remove('d-none'); } else { // No trial - show regular subscription terms with renewal date const periodText = state.billingCycle === 'monthly' ? 'monthly' : 'annually'; const basePrice = state.billingCycle === 'monthly' ? state.product.price_monthly : state.product.price_annually; // Apply discount to the recurring price (always calculate, even if 0%) const discountAmount = (basePrice * state.discountPercent) / 100; const discountedPrice = basePrice - discountAmount; // Calculate next renewal date (30 days for monthly, 365 days for annual) const renewalDate = new Date(); const daysToAdd = state.billingCycle === 'monthly' ? 30 : 365; renewalDate.setDate(renewalDate.getDate() + daysToAdd); const formattedRenewalDate = renewalDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }); $termsText.textContent = `Your ${periodText} subscription will start today and renew on ${formattedRenewalDate} for $${discountedPrice.toFixed(2)} plus applicable tax. Cancel anytime.`; $termsDiv.classList.remove('d-none'); } } // Centralized billing cycle change handler export function handleBillingCycleChange(newCycle = null) { // Update state if a specific cycle is provided if (newCycle && newCycle !== state.billingCycle) { state.billingCycle = newCycle; } // Update all UI elements updateAllUI(); } // Show error message export function showError(message) { const $errorContainer = document.getElementById('checkout-error-container'); const $errorMessage = document.getElementById('checkout-error-message'); const $checkoutContent = document.getElementById('checkout-content'); if ($errorContainer && $errorMessage && $checkoutContent) { $errorMessage.textContent = message; $errorContainer.classList.remove('d-none'); $checkoutContent.classList.add('d-none'); } } // Hide preloader with animation export function hidePreloader() { const $preloader = document.getElementById('checkout-preloader'); if ($preloader) { $preloader.style.opacity = '0'; $preloader.style.transition = 'opacity 0.3s ease-out'; setTimeout(() => { $preloader.remove(); }, 300); } } // Update payment button visibility based on processor availability export function updatePaymentButtonVisibility(paymentManager) { // Get all payment buttons const paymentButtons = document.querySelectorAll('.payment-button'); // Update each button's visibility based on its payment method paymentButtons.forEach(button => { const paymentMethod = button.getAttribute('data-payment-method'); const isAvailable = paymentManager.isPaymentMethodAvailable(paymentMethod); if (isAvailable) { button.classList.remove('d-none'); } else { button.classList.add('d-none'); } }); // Log which payment methods are available const availableMethods = paymentManager.getAvailablePaymentMethods(); console.log('Payment buttons updated. Available methods:', availableMethods.map(m => m.id)); }