Global E-commerce Customs & Tax Widget Builder

QR Code

`; generatedCode.textContent = widgetCode.trim(); const qrData = encodeURIComponent(`data:text/html,${widgetCode.trim()}`); // Embed code directly into data URL for small widgets qrCodeImage.src = `https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=${qrData}`; outputArea.classList.add('active'); updateUsageDisplay(); }, 1000); // Simulate network delay } async function requestWhatsApp() { const texts = i18n[getCurrentLanguage()]; const productCategory = inputs.productCategory.value.trim(); const originCountryCode = inputs.originCountry.value; const originCountryName = countries[originCountryCode] || originCountryCode; const destinationCountriesCodes = Array.from(inputs.destinationCountries.selectedOptions).map(option => option.value); const destinationCountriesNames = destinationCountriesCodes.map(code => countries[code] || code).join(', '); const productValue = parseFloat(inputs.productValue.value); const shippingCost = parseFloat(inputs.shippingCost.value); const hsCode = inputs.hsCode.value.trim(); const vatRate = inputs.vatRate.value.trim(); const dutyRate = inputs.dutyRate.value.trim(); const currency = inputs.currency.value; let message = texts.appTitle + " - " + texts.requestWhatsAppButton + "\n\n"; message += texts.labelProductCategory + ": " + productCategory + "\n"; message += texts.labelOriginCountry + ": " + originCountryName + "\n"; message += texts.labelDestinationCountries + ": " + destinationCountriesNames + "\n"; message += texts.labelProductValue + ": " + productValue + "\n"; message += texts.labelShippingCost + ": " + shippingCost + "\n"; if (isUnlocked) { message += texts.labelHsCode + ": " + hsCode + "\n"; message += texts.labelVatRate + ": " + vatRate + "%\n"; message += texts.labelDutyRate + ": " + dutyRate + "%\n"; message += texts.labelCurrency + ": " + currency + "\n"; } message += "\n" + texts.unlockedMessage + " (Full version status: " + isUnlocked + ")"; const whatsappUrl = `https://wa.me/${WHATSAPP_NUMBER}?text=${encodeURIComponent(message)}`; window.open(whatsappUrl, '_blank'); } // --- Event Listeners --- languageSwitcher.addEventListener('change', (e) => { updateUI(e.target.value); }); generateWidgetButton.addEventListener('click', generateWidgetCode); requestWhatsAppButton.addEventListener('click', requestWhatsApp); copyCodeButton.addEventListener('click', () => { navigator.clipboard.writeText(generatedCode.textContent) .then(() => { copyCodeButton.textContent = i18n[getCurrentLanguage()].copiedSuccess; setTimeout(() => { copyCodeButton.textContent = i18n[getCurrentLanguage()].copyCodeButton; }, 2000); }) .catch(err => { console.error('Failed to copy text: ', err); }); }); copyCryptoAddress.addEventListener('click', () => { navigator.clipboard.writeText(cryptoAddress.textContent) .then(() => { copyCryptoAddress.textContent = i18n[getCurrentLanguage()].copiedSuccess; setTimeout(() => { copyCryptoAddress.textContent = i18n[getCurrentLanguage()].copyCodeButton; // Re-using copy code button text }, 2000); }) .catch(err => { console.error('Failed to copy text: ', err); }); }); // Payment Overlay Event Listeners closePaymentModal.addEventListener('click', hidePaymentOverlay); authSignInButton.addEventListener('click', handleAuthAction); authRegisterButton.addEventListener('click', handleAuthAction); signInWithGoogleButton.addEventListener('click', signInWithGoogle); toggleAuthMode.addEventListener('click', toggleAuthUI); subscribeHubButton.addEventListener('click', () => createStripeSession(WIDGET_SLUG, null, null, true)); buyLifetimeButton.addEventListener('click', () => createStripeSession(WIDGET_SLUG, 199, i18n[getCurrentLanguage()].appTitle, false)); payCryptoButton.addEventListener('click', () => requestCryptoPayment(WIDGET_SLUG, 199, i18n[getCurrentLanguage()].appTitle)); cancelCryptoPaymentButton.addEventListener('click', () => { hidePaymentOverlay(); // This also stops polling showMessage(errorMessage, "Crypto payment cancelled.", 'error'); // Or some other message }); inputs.destinationCountries.addEventListener('change', () => { if (!isUnlocked) { let selectedOptions = Array.from(inputs.destinationCountries.selectedOptions); if (selectedOptions.length > 2) { // Deselect the last selected option if limit is exceeded selectedOptions[selectedOptions.length - 1].selected = false; showMessage(errorMessage, i18n[getCurrentLanguage()].errorMaxDestinations.replace('{max}', 2), 'error'); } else { errorMessage.style.display = 'none'; } } }); // --- Initialize on Load --- document.addEventListener('DOMContentLoaded', async () => { populateCountrySelects(); updateUI(getCurrentLanguage()); updateUsageDisplay(); // Check URL for payment status const urlParams = new URLSearchParams(window.location.search); const status = urlParams.get('status'); const sessionId = urlParams.get('session_id'); const subscriptionStatus = urlParams.get('subscription_status'); if (status === 'success' && sessionId) { showLoader(); try { const response = await fetch(`${API_BASE_URL}/verify-session?session_id=${sessionId}`); if (response.ok) { const data = await response.json(); if (data.verified) { await handleSuccessfulPayment(false); // One-time payment } else { showMessage(errorMessage, 'Payment verification failed.', 'error'); } } else { showMessage(errorMessage, 'Payment verification failed on server.', 'error'); } } catch (error) { console.error('Error verifying session:', error); showMessage(errorMessage, i18n[getCurrentLanguage()].errorMessageGeneral, 'error'); } finally { hideLoader(); } } else if (subscriptionStatus === 'success' && sessionId) { // For subscription, the auth.onAuthStateChanged will handle the unlock. if (!currentUser) { // If user is not yet loaded or not logged in, prompt them showPaymentOverlay('authPrompt'); showMessage(paymentSuccessMessage, "Subscription initiated! Please sign in to activate your unlimited access.", 'success', 10000); } else { // User is logged in, auth.onAuthStateChanged will re-check and unlock. await handleSuccessfulPayment(true); // Hub subscription } } else if (!isUnlocked && usageCount >= FREE_USES_LIMIT) { // If the user has exhausted free uses and hasn't unlocked, show overlay // Delay showing it slightly to allow initial UI render setTimeout(() => showPaymentOverlay('limitReached'), 500); } // Initially update auth modal UI state updateAuthModeUI(); });