|
|
|
@ -1069,7 +1069,7 @@ const chart = new Chart(ctx, { |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<script> |
|
|
|
|
const coinNameToSymbol = { |
|
|
|
|
const coinNameToSymbol = { |
|
|
|
|
'Bitcoin': 'BTC', |
|
|
|
|
'Particl': 'PART', |
|
|
|
|
'Particl Blind': 'PART', |
|
|
|
@ -1079,11 +1079,11 @@ const chart = new Chart(ctx, { |
|
|
|
|
'Firo': 'FIRO', |
|
|
|
|
'Dash': 'DASH', |
|
|
|
|
'PIVX': 'PIVX' |
|
|
|
|
}; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const exchangeRateCache = {}; |
|
|
|
|
const exchangeRateCache = {}; |
|
|
|
|
|
|
|
|
|
function updateUsdValue(cryptoCell, coinFullName, isRate = false) { |
|
|
|
|
function updateUsdValue(cryptoCell, coinFullName, isRate = false) { |
|
|
|
|
const coinSymbol = coinNameToSymbol[coinFullName]; |
|
|
|
|
if (!coinSymbol) { |
|
|
|
|
console.error(`Coin symbol not found for full name: ${coinFullName}`); |
|
|
|
@ -1092,11 +1092,29 @@ const chart = new Chart(ctx, { |
|
|
|
|
|
|
|
|
|
const cryptoValue = parseFloat(cryptoCell.textContent); |
|
|
|
|
const usdCell = cryptoCell.nextElementSibling; |
|
|
|
|
if (usdCell) { |
|
|
|
|
// Check if the exchange rate is in the cache and is not expired |
|
|
|
|
if (exchangeRateCache[coinSymbol] && !isCacheExpired(coinSymbol)) { |
|
|
|
|
console.log(`Using cached exchange rate for ${coinSymbol}`); |
|
|
|
|
const exchangeRate = exchangeRateCache[coinSymbol].rate; |
|
|
|
|
const cryptoValue = parseFloat(cryptoCell.textContent); |
|
|
|
|
const usdValue = cryptoValue * exchangeRate; |
|
|
|
|
usdCell.textContent = `${usdValue.toFixed(2)} USD`; |
|
|
|
|
|
|
|
|
|
updateProfitLoss(cryptoCell.closest('tr')); |
|
|
|
|
updateProfitValue(cryptoCell.closest('tr')); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (isRate) { |
|
|
|
|
const rateCell = usdCell.nextElementSibling; |
|
|
|
|
if (rateCell) { |
|
|
|
|
const usdValue = rateCell.previousElementSibling.textContent * cryptoValue; |
|
|
|
|
usdCell.textContent = `${usdValue.toFixed(2)} USD`; |
|
|
|
|
} else { |
|
|
|
|
console.error("Rate cell does not exist."); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
const apiUrl = `https://min-api.cryptocompare.com/data/price?fsym=${coinSymbol}&tsyms=USD`; |
|
|
|
|
|
|
|
|
@ -1134,17 +1152,15 @@ const chart = new Chart(ctx, { |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
.catch(error => { |
|
|
|
|
console.error('Error retrieving exchange rate:', error); |
|
|
|
|
usdCell.textContent = 'Error retrieving exchange rate'; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function isCacheExpired(coinSymbol) { |
|
|
|
|
function isCacheExpired(coinSymbol) { |
|
|
|
|
const cacheEntry = exchangeRateCache[coinSymbol]; |
|
|
|
|
return cacheEntry && (Date.now() - cacheEntry.timestamp > cacheEntry.ttl); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function updateProfitLoss(row) { |
|
|
|
|
const buyingUSD = parseFloat(row.querySelector('.usd-value').textContent); |
|
|
|
@ -1171,7 +1187,7 @@ function updateProfitLoss(row) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function updateProfitValue(row) { |
|
|
|
|
function updateProfitValue(row) { |
|
|
|
|
const sellingUSD = parseFloat(row.querySelector('.usd-value').textContent); |
|
|
|
|
const profitValueCell = row.querySelector('.profit-value'); |
|
|
|
|
|
|
|
|
@ -1180,24 +1196,17 @@ function updateProfitLoss(row) { |
|
|
|
|
} else { |
|
|
|
|
profitValueCell.textContent = 'Invalid USD value'; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => { |
|
|
|
|
document.addEventListener('DOMContentLoaded', () => { |
|
|
|
|
const coinNameValues = document.querySelectorAll('.coinname-value'); |
|
|
|
|
for (let i = 0; i < coinNameValues.length; i++) { |
|
|
|
|
const coinFullName = coinNameValues[i].getAttribute('data-coinname'); |
|
|
|
|
const isRate = coinNameValues[i].textContent.includes('rate'); |
|
|
|
|
updateUsdValue(coinNameValues[i], coinFullName, isRate); |
|
|
|
|
|
|
|
|
|
if (!isRate) { |
|
|
|
|
coinNameValues[i].addEventListener('input', () => { |
|
|
|
|
console.log(`Clearing cache for ${coinNameToSymbol[coinFullName]}`); |
|
|
|
|
exchangeRateCache[coinNameToSymbol[coinFullName]] = undefined; |
|
|
|
|
updateUsdValue(coinNameValues[i], coinFullName); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
coinNameValues.forEach(coinNameValue => { |
|
|
|
|
const coinFullName = coinNameValue.getAttribute('data-coinname'); |
|
|
|
|
const isRateElement = coinNameValue.parentElement.querySelector('.ratetype'); |
|
|
|
|
const isRate = isRateElement ? isRateElement.textContent.includes('rate') : false; |
|
|
|
|
updateUsdValue(coinNameValue, coinFullName, isRate); |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
</script> |
|
|
|
|
{% include 'footer.html' %} |
|
|
|
|
</body> |
|
|
|
|