1// Currency Calculator functionality 2document.addEventListener('alpine:init', () => { 3 Alpine.data('currencyCalculatorV2', () => { 4 return { 5 allCurrencies: [ 6 { code: 'AZN', name: 'AzÉrbaycan Manatı', flag: 'https://flagcdn.com/az.svg', rate: 1, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 7 { code: 'USD', name: 'ABÅ Dolları', flag: 'https://flagcdn.com/us.svg', rate: 0.5882, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 8 { code: 'EUR', name: 'Avro', flag: 'https://flagcdn.com/eu.svg', rate: 0.5044, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 9 { code: 'TRY', name: 'Türk LirÉsi', flag: 'https://flagcdn.com/tr.svg', rate: 23.8095, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 10 { code: 'AED', name: 'BÆÆ DirhÉmi', flag: 'https://flagcdn.com/ae.svg', rate: 2.16, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 11 { code: 'GBP', name: 'İngilis Funtu', flag: 'https://flagcdn.com/gb.svg', rate: 0.433, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 12 { code: 'RUB', name: 'Rus Rublu', flag: 'https://flagcdn.com/ru.svg', rate: 47.619, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 13 { code: 'GEL', name: 'Gürcüstan Larisi', flag: 'https://flagcdn.com/ge.svg', rate: 1.6, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 14 { code: 'JPY', name: 'Yapon Yeni', flag: 'https://flagcdn.com/jp.svg', rate: 86.21, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 15 { code: 'CNY', name: 'Ãin Yuanı', flag: 'https://flagcdn.com/cn.svg', rate: 0.237, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 16 { code: 'CHF', name: 'İsveçrÉ Frankı', flag: 'https://flagcdn.com/ch.svg', rate: 2.11, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 17 { code: 'CAD', name: 'Kanada Dolları', flag: 'https://flagcdn.com/ca.svg', rate: 1.235, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 18 ], 19 cards: [ 20 { id: 1, code: 'AZN', name: 'AzÉrbaycan Manatı', flag: 'https://flagcdn.com/az.svg', amount: 100, rate: 1, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 21 { id: 2, code: 'USD', name: 'ABÅ Dolları', flag: 'https://flagcdn.com/us.svg', amount: 58.82, rate: 0.5882, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 22 { id: 3, code: 'EUR', name: 'Avro', flag: 'https://flagcdn.com/eu.svg', amount: 50.44, rate: 0.5044, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 23 { id: 4, code: 'TRY', name: 'Türk LirÉsi', flag: 'https://flagcdn.com/tr.svg', amount: 1, rate: 23.8095, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 24 { id: 5, code: 'RUB', name: 'Rus Rublu', flag: 'https://flagcdn.com/ru.svg', amount: 4761.90, rate: 47.619, date: new Date().toLocaleDateString('az-AZ', { day: '2-digit', month: '2-digit', year: 'numeric' }) }, 25 ], 26 27 isLoading: false, 28 lastUpdate: null, 29 error: null, 30 31 init() { 32 this.loadFromLocalStorage(); 33 this.checkAndFetchRates(); 34 // Auto-refresh rates every hour (60 minutes) 35 setInterval(() => { 36 this.checkAndFetchRates(); 37 }, 60 * 60 * 1000); 38 }, 39 40 // Load data from localStorage 41 loadFromLocalStorage() { 42 try { 43 const storedData = localStorage.getItem('currencyRates'); 44 if (storedData) { 45 const data = JSON.parse(storedData); 46 47 // Check if data is not older than 1 hour 48 const now = new Date().getTime(); 49 const storedTime = data.timestamp || 0; 50 const oneHour = 60 * 60 * 1000; // 1 hour in milliseconds 51 52 if (now - storedTime < oneHour) { 53 // Update allCurrencies with stored rates 54 if (data.allCurrencies) { 55 this.allCurrencies = data.allCurrencies; 56 } 57 58 // Update cards with stored rates 59 if (data.cards) { 60 this.cards = data.cards; 61 } 62 63 // Update last update time 64 if (data.lastUpdate) { 65 this.lastUpdate = data.lastUpdate; 66 } 67 68 console.log('Currency rates loaded from localStorage'); 69 return true; 70 } else { 71 console.log('Stored currency rates are outdated, will fetch new data'); 72 } 73 } 74 } catch (error) { 75 console.error('Error loading currency rates from localStorage:', error); 76 } 77 return false;
78 }, 79 80 // Save data to localStorage 81 saveToLocalStorage() { 82 try { 83 const dataToStore = { 84 allCurrencies: this.allCurrencies, 85 cards: this.cards, 86 lastUpdate: this.lastUpdate, 87 timestamp: new Date().getTime() 88 }; 89 localStorage.setItem('currencyRates', JSON.stringify(dataToStore)); 90 console.log('Currency rates saved to localStorage'); 91 } catch (error) { 92 console.error('Error saving currency rates to localStorage:', error); 93 } 94 }, 95 96 // Check if we need to fetch new rates 97 checkAndFetchRates() { 98 const storedData = localStorage.getItem('currencyRates'); 99 if (storedData) { 100 try { 101 const data = JSON.parse(storedData); 102 const now = new Date().getTime(); 103 const storedTime = data.timestamp || 0; 104 const oneHour = 60 * 60 * 1000; // 1 hour in milliseconds 105 106 if (now - storedTime >= oneHour) { 107 this.fetchCurrencyRates(); 108 } 109 } catch (error) { 110 console.error('Error checking stored data timestamp:', error); 111 this.fetchCurrencyRates(); 112 } 113 } else { 114 this.fetchCurrencyRates(); 115 } 116 }, 117 118 async fetchCurrencyRates() { 119 this.isLoading = true; 120 this.error = null; 121 122 try { 123 const response = await fetch('https://api.exchangerate-api.com/v4/latest/AZN'); 124 125 if (!response.ok) { 126 throw new Error(`HTTP error! status: ${response.status}`); 127 } 128 129 const data = await response.json(); 130 131 if (data.rates && Object.keys(data.rates).length > 0) { 132 // Format current date properly 133 const currentDate = new Date().toLocaleDateString('az-AZ', { 134 day: '2-digit', 135 month: '2-digit', 136 year: 'numeric' 137 }); 138 139 // Update rates from Exchange Rate API 140 Object.entries(data.rates).forEach(([currency, rate]) => { 141 // The API returns: 1 AZN = X currency 142 // We need: 1 AZN = X currency (use the rate directly) 143 const aznRate = parseFloat(rate); 144 145 if (!isNaN(aznRate) && aznRate > 0) { 146 // Update allCurrencies array 147 const currencyIndex = this.allCurrencies.findIndex(c => c.code === currency); 148 if (currencyIndex !== -1) { 149 this.allCurrencies[currencyIndex].rate = aznRate; 150 this.allCurrencies[currencyIndex].date = currentDate; 151 } 152 153 // Update cards array 154 const cardIndex = this.cards.findIndex(c => c.code === currency); 155 if (cardIndex !== -1) { 156 this.cards[cardIndex].rate = aznRate; 157 this.cards[cardIndex].date = currentDate; 158 } 159 } 160 }); 161 162 // Recalculate amounts after updating rates 163 this.updateAll(0); 164 165 // Update last update time 166 this.lastUpdate = new Date().toLocaleTimeString('az-AZ', { 167 hour: '2-digit', 168 minute: '2-digit', 169 second: '2-digit' 170 }); 171 172 // Save to localStorage 173 this.saveToLocalStorage(); 174 175 } else { 176 console.warn('No valid rates found in API response'); 177 } 178 179 } catch (error) { 180 console.error('Error fetching currency rates from Exchange Rate API:', error); 181 this.error = 'Valyuta mÉzÉnnÉlÉri yüklÉnÉrkÉn xÉta baÅ verdi. ZÉhmÉt olmasa yenidÉn cÉhd edin.'; 182 // Keep using default values if API fails 183 } finally { 184 this.isLoading = false;
185 } 186 }, 187 188 updateAll(changedIdx) { 189 if (changedIdx === 0) { 190 const baseAmount = parseFloat(this.cards[0].amount) || 0; 191 192 this.cards.forEach((card, idx) => { 193 if (idx !== 0) { 194 // Convert from AZN to other currency: amount = baseAmount * rate 195 const newAmount = baseAmount * parseFloat(card.rate); 196 card.amount = newAmount.toFixed(2); 197 } 198 }); 199 } else { 200 const changedAmount = parseFloat(this.cards[changedIdx].amount) || 0; 201 const changedRate = parseFloat(this.cards[changedIdx].rate) || 1; 202 203 // Convert from other currency to AZN: baseAmount = changedAmount / rate 204 const baseAmount = changedAmount / changedRate; 205 this.cards[0].amount = baseAmount.toFixed(2); 206 207 this.cards.forEach((card, idx) => { 208 if (idx !== 0 && idx !== changedIdx) { 209 // Convert from AZN to other currency: amount = baseAmount * rate 210 const newAmount = baseAmount * parseFloat(card.rate); 211 card.amount = newAmount.toFixed(2); 212 } 213 }); 214 } 215 }, 216 217 // Add new method to manually refresh rates 218 refreshRates() { 219 this.fetchCurrencyRates(); 220 }, 221 222 // Add method to get loading status 223 getLoadingStatus() { 224 return this.isLoading ? 'YüklÉnir...' : 'YüklÉndi'; 225 }, 226 227 // Add method to get last update time 228 getLastUpdate() { 229 return this.lastUpdate ? `Son yenilÉmÉ: ${this.lastUpdate}` : 'YenilÉnmÉdi'; 230 }, 231 232 // Add method to clear localStorage (for testing) 233 clearLocalStorage() { 234 localStorage.removeItem('currencyRates'); 235 console.log('LocalStorage cleared'); 236 } 237 }; 238 }); 239});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.