const CONFIG = { API_URL: 'https://open.er-api.com/v6/latest/', MAX_HISTORY: 5 }; const state = { resultsCount: 0, history: [], isDark: false, lastResult: null }; // UI Elements const el = { amount: document.getElementById('amount'), from: document.getElementById('from-currency'), to: document.getElementById('to-currency'), convertBtn: document.getElementById('convert-btn'), resetBtn: document.getElementById('reset-btn'), resultArea: document.getElementById('result-area'), skeleton: document.getElementById('result-skeleton'), resultText: document.getElementById('result-text'), resultCount: document.getElementById('result-count'), feedbackRow: document.getElementById('feedback-row'), donateContainer: document.getElementById('donate-container'), themeToggle: document.getElementById('theme-toggle'), pasteBtn: document.getElementById('paste-btn'), h1: document.getElementById('main-h1'), metaTitle: document.getElementById('meta-title'), metaDesc: document.getElementById('meta-desc'), qrContainer: document.getElementById('qr-container'), historyChips: document.getElementById('history-chips') }; // SVG Assets const SVGS = { thumbsUp: ``, thumbsDown: ``, star: `` }; const init = () => { attachListeners(); resetFeedbackRow(); checkUrlParams(); }; const attachListeners = () => { [el.amount, el.from, el.to].forEach(input => { input.addEventListener('input', validate); }); el.convertBtn.onclick = handleConvert; el.resetBtn.onclick = handleReset; el.themeToggle.onclick = toggleTheme; el.pasteBtn.onclick = handlePaste; document.getElementById('print-btn').onclick = () => window.print(); document.getElementById('copy-btn').onclick = handleCopy; document.getElementById('csv-btn').onclick = handleCSV; document.getElementById('qr-btn').onclick = toggleQR; }; const validate = () => { const isValid = el.amount.value > 0 && el.from.value && el.to.value; el.convertBtn.disabled = !isValid; }; const handlePaste = async () => { const text = await navigator.clipboard.readText(); const num = parseFloat(text); if (!isNaN(num)) { el.amount.value = num; validate(); } }; const handleConvert = async () => { const amt = el.amount.value; const from = el.from.value; const to = el.to.value; el.skeleton.classList.remove('hidden'); el.resultArea.classList.add('hidden'); try { const res = await fetch(`${CONFIG.API_URL}${from}`); const data = await res.json(); if (data.result === 'success') { const rate = data.rates[to]; const result = (amt * rate).toFixed(2); displayResult(amt, from, to, result); } } catch (e) { console.error("API Error", e); } finally { el.skeleton.classList.add('hidden'); } }; const displayResult = (amt, from, to, res) => { const text = `${amt} ${from} = ${res} ${to}`; el.resultText.textContent = text; state.lastResult = { amt, from, to, res, date: new Date().toISOString() }; state.resultsCount++; el.resultCount.textContent = `${state.resultsCount} results so far`; // SEO & History updateMetadata(text, amt, from, to); addHistory(text); // UI Logic el.resultArea.classList.remove('hidden'); el.donateContainer.classList.remove('hidden'); el.qrContainer.classList.add('hidden'); }; const updateMetadata = (text, amt, from, to) => { el.h1.textContent = text; el.metaTitle.textContent = `${text} - Converter`; el.metaDesc.content = `Real-time conversion: ${text}. Live exchange rates provided by Rivlosys.`; history.replaceState(null, '', `?amount=${amt}&from=${from}&to=${to}`); }; const addHistory = (item) => { state.history.unshift(item); if (state.history.length > CONFIG.MAX_HISTORY) state.history.pop(); el.historyChips.innerHTML = state.history.map(h => `${h}`).join(''); }; const handleReset = () => { // Clear Inputs el.amount.value = ''; el.from.selectedIndex = 0; el.to.selectedIndex = 0; validate(); // Reset Branding/SEO el.h1.textContent = 'Currency Converter'; el.metaTitle.textContent = 'Live Currency Converter - Real-Time Exchange Rates'; el.metaDesc.content = 'Convert 160+ currencies with real-time exchange rates. Free, fast, and mobile-friendly currency conversion tool.'; history.replaceState(null, '', '/'); // Reset Result Areas el.resultArea.classList.add('hidden'); el.qrContainer.innerHTML = ''; el.qrContainer.classList.add('hidden'); resetFeedbackRow(); }; const resetFeedbackRow = () => { el.feedbackRow.innerHTML = ` ${SVGS.star} Did this help?