diff --git a/basicswap/static/js/offerstable.js b/basicswap/static/js/offerstable.js index ecfc1bc..f861b7a 100644 --- a/basicswap/static/js/offerstable.js +++ b/basicswap/static/js/offerstable.js @@ -485,7 +485,8 @@ function fetchOffers(manualRefresh = false) { created_at: Number(offer.created_at || 0), expire_at: Number(offer.expire_at || 0), is_own_offer: Boolean(offer.is_own_offer), - amount_negotiable: Boolean(offer.amount_negotiable) + amount_negotiable: Boolean(offer.amount_negotiable), + unique_id: `${offer.offer_id}_${offer.created_at}_${offer.coin_from}_${offer.coin_to}` })); if (!isSentOffers) { @@ -610,7 +611,7 @@ function filterAndSortData() { const formData = new FormData(filterForm); const filters = Object.fromEntries(formData); - console.log('Raw filters:', filters); + console.log('Processed filters:', filters); if (filters.coin_to !== 'any') { filters.coin_to = coinIdToName[filters.coin_to] || filters.coin_to; @@ -623,41 +624,49 @@ function filterAndSortData() { const currentTime = Math.floor(Date.now() / 1000); - let filteredData = originalJsonData.filter(offer => { + const uniqueOffersMap = new Map(); + + originalJsonData.forEach(offer => { const coinFrom = (offer.coin_from || '').toLowerCase(); const coinTo = (offer.coin_to || '').toLowerCase(); const isExpired = offer.expire_at <= currentTime; if (!isSentOffers && isExpired) { - return false; + return; } + let passesFilter = true; + if (isSentOffers) { if (filters.coin_to !== 'any' && coinFrom.toLowerCase() !== filters.coin_to.toLowerCase()) { - return false; + passesFilter = false; } if (filters.coin_from !== 'any' && coinTo.toLowerCase() !== filters.coin_from.toLowerCase()) { - return false; + passesFilter = false; } } else { if (filters.coin_to !== 'any' && coinTo.toLowerCase() !== filters.coin_to.toLowerCase()) { - return false; + passesFilter = false; } if (filters.coin_from !== 'any' && coinFrom.toLowerCase() !== filters.coin_from.toLowerCase()) { - return false; + passesFilter = false; } } if (isSentOffers && filters.active && filters.active !== 'any') { const offerState = isExpired ? 'expired' : 'active'; if (filters.active !== offerState) { - return false; + passesFilter = false; } } - return true; + if (passesFilter) { + uniqueOffersMap.set(offer.unique_id, offer); + } }); + let filteredData = Array.from(uniqueOffersMap.values()); + console.log('Filtered data length:', filteredData.length); const sortBy = filters.sort_by || 'created_at'; @@ -822,6 +831,7 @@ function prepareOfferData(offer, isSentOffers) { }; } +// to-do revoked function getButtonProperties(isActuallyExpired, isSentOffers, isTreatedAsSentOffer, isRevoked) { if (isRevoked) { return { @@ -865,8 +875,7 @@ function updateProfitLoss(row, fromCoin, toCoin, fromAmount, toAmount) { const colorClass = getProfitColorClass(profitLossPercentage); profitLossElement.textContent = `${profitLossPercentage > 0 ? '+' : ''}${profitLossPercentage}%`; profitLossElement.className = `profit-loss text-lg font-bold ${colorClass}`; - - // Update the tooltip content + const tooltipId = `percentage-tooltip-${row.getAttribute('data-offer-id')}`; const tooltipElement = document.getElementById(tooltipId); if (tooltipElement) { @@ -955,6 +964,7 @@ function getMarketRate(fromCoin, toCoin) { }); } +// todo function getTimerColor(offer) { const now = Math.floor(Date.now() / 1000); const offerAge = now - offer.created_at; @@ -1015,21 +1025,19 @@ function createDetailsColumn(offer) { `; } -function createTakerAmountColumn(offer, coinFrom, coinTo) { - const fromAmount = parseFloat(offer.amount_from); +function createOrderbookColumn(offer, coinFrom, coinTo) { + const toAmount = parseFloat(offer.amount_to); const fromSymbol = getCoinSymbol(coinFrom); - const fromPriceUSD = latestPrices[coinNameToSymbol[coinFrom]]?.usd || 0; - const fromValueUSD = fromAmount * fromPriceUSD; - return ` - - -
- ${fromAmount.toFixed(4)} -
${coinFrom}
-
USD: (${fromValueUSD.toFixed(2)})
-
-
+ +
+ +
+
${toAmount.toFixed(4)}
+
${coinFrom}
+
+
+
`; } @@ -1053,19 +1061,16 @@ function createSwapColumn(offer, coinFrom, coinTo) { `; } -function createOrderbookColumn(offer, coinTo, coinFrom) { - const toAmount = parseFloat(offer.amount_to); +function createTakerAmountColumn(offer, coinTo, coinFrom) { + const fromAmount = parseFloat(offer.amount_from); const toSymbol = getCoinSymbol(coinTo); - const toPriceUSD = latestPrices[coinNameToSymbol[coinTo]]?.usd || 0; - const toValueUSD = toAmount * toPriceUSD; return ` -
- -
-
${toAmount.toFixed(4)}
+
@@ -1083,11 +1088,9 @@ function createRateColumn(offer, coinFrom, coinTo) { const fromSymbol = getCoinSymbol(coinFrom); const toSymbol = getCoinSymbol(coinTo); - // Get USD prices const fromPriceUSD = latestPrices[coinNameToSymbol[coinFrom]]?.usd || 0; const toPriceUSD = latestPrices[coinNameToSymbol[coinTo]]?.usd || 0; - // Calculate USD equivalent of the rate const rateInUSD = rate * toPriceUSD; console.log(`Rate calculation for ${fromSymbol} to ${toSymbol}:`); @@ -1101,15 +1104,15 @@ function createRateColumn(offer, coinFrom, coinTo) {
- + + $${rateInUSD.toFixed(2)}/${fromSymbol} + + ${rate.toFixed(6)} ${toSymbol}/${fromSymbol} - + ${inverseRate.toFixed(6)} ${fromSymbol}/${toSymbol} - - ($${rateInUSD.toFixed(2)}) -
@@ -1152,10 +1155,8 @@ function createTooltips(offer, isSentOffers, coinFrom, coinTo, postedTime, expir const toPriceUSD = latestPrices[toSymbol]?.usd || 0; const rateInUSD = rate * toPriceUSD; - const combinedRateTooltip = createCombinedRateTooltip(offer, coinFrom, coinTo); - const fromAmount = parseFloat(offer.amount_from); const toAmount = parseFloat(offer.amount_to); const percentageTooltipContent = createTooltipContent(isSentOffers, coinFrom, coinTo, fromAmount, toAmount); @@ -1177,7 +1178,7 @@ function createTooltips(offer, isSentOffers, coinFrom, coinTo, postedTime, expir
@@ -1187,7 +1188,7 @@ function createTooltips(offer, isSentOffers, coinFrom, coinTo, postedTime, expir
@@ -1260,6 +1261,7 @@ function createTooltipContent(isSentOffers, coinFrom, coinTo, fromAmount, toAmou "As a buyer, a positive percentage indicates potential
savings compared to current market rates."}

`; } + function createCombinedRateTooltip(offer, coinFrom, coinTo) { const rate = parseFloat(offer.rate); const inverseRate = 1 / rate; diff --git a/basicswap/static/js/pricechart.js b/basicswap/static/js/pricechart.js index 985207b..50a91a2 100644 --- a/basicswap/static/js/pricechart.js +++ b/basicswap/static/js/pricechart.js @@ -866,69 +866,75 @@ const app = { }, init: () => { - window.addEventListener('load', app.onLoad); - app.loadLastRefreshedTime(); - }, - - onLoad: async () => { - ui.showLoader(); - try { - volumeToggle.init(); - await app.updateBTCPrice(); - const chartContainer = document.getElementById('coin-chart'); - if (chartContainer) { - chartModule.initChart(); - chartModule.showChartLoader(); - } else { - console.warn('Chart container not found, skipping chart initialization'); - } - for (const coin of config.coins) { - await app.loadCoinData(coin); - } - if (chartModule.chart) { - config.currentResolution = 'month'; - await chartModule.updateChart('BTC'); - app.updateResolutionButtons('BTC'); - } - ui.setActiveContainer('btc-container'); - config.coins.forEach(coin => { - const container = document.getElementById(`${coin.symbol.toLowerCase()}-container`); - if (container) { - container.addEventListener('click', () => { - ui.setActiveContainer(`${coin.symbol.toLowerCase()}-container`); - if (chartModule.chart) { - if (coin.symbol === 'WOW') { - config.currentResolution = 'day'; - } - chartModule.updateChart(coin.symbol); - app.updateResolutionButtons(coin.symbol); - } - }); + window.addEventListener('load', async () => { + ui.showLoader(); + try { + volumeToggle.init(); + await app.updateBTCPrice(); + + chartModule.initChart(); + chartModule.showChartLoader(); + } else { + console.warn('Chart container not found, skipping chart initialization'); + } + + const coinDataPromises = config.coins.map(coin => app.loadCoinData(coin)); + await Promise.all(coinDataPromises); + + if (chartModule.chart) { + config.currentResolution = 'month'; + await chartModule.updateChart('BTC'); + app.updateResolutionButtons('BTC'); + } + + ui.setActiveContainer('btc-container'); + + // Set up event listeners for coin containers + config.coins.forEach(coin => { + const container = document.getElementById(`${coin.symbol.toLowerCase()}-container`); + if (container) { + container.addEventListener('click', () => { + ui.setActiveContainer(`${coin.symbol.toLowerCase()}-container`); + if (chartModule.chart) { + if (coin.symbol === 'WOW') { + config.currentResolution = 'day'; + } + chartModule.updateChart(coin.symbol); + app.updateResolutionButtons(coin.symbol); + } + }); + } + }); + + app.initializeSelectImages(); + app.initAutoRefresh(); + + const refreshAllButton = document.getElementById('refresh-all'); + if (refreshAllButton) { + refreshAllButton.addEventListener('click', app.refreshAllData); + } + + const headers = document.querySelectorAll('th'); + headers.forEach((header, index) => { + header.addEventListener('click', () => app.sortTable(index, header.classList.contains('disabled'))); + }); + + const closeErrorButton = document.getElementById('close-error'); + if (closeErrorButton) { + closeErrorButton.addEventListener('click', ui.hideErrorMessage); + } + + } catch (error) { + console.error('Error during initialization:', error); + ui.displayErrorMessage('Failed to initialize the dashboard. Please try refreshing the page.'); + } finally { + ui.hideLoader(); + if (chartModule.chart) { + chartModule.hideChartLoader(); } - }); - const refreshAllButton = document.getElementById('refresh-all'); - if (refreshAllButton) { - refreshAllButton.addEventListener('click', app.refreshAllData); } - app.initializeSelectImages(); - const headers = document.querySelectorAll('th'); - headers.forEach((header, index) => { - header.addEventListener('click', () => app.sortTable(index, header.classList.contains('disabled'))); - }); - const closeErrorButton = document.getElementById('close-error'); - if (closeErrorButton) { - closeErrorButton.addEventListener('click', ui.hideErrorMessage); - } - app.initAutoRefresh(); - } catch (error) { - console.error('Error during initialization:', error); - ui.displayErrorMessage('Failed to initialize the dashboard. Please try refreshing the page.'); - } finally { - ui.hideLoader(); - if (chartModule.chart) { - chartModule.hideChartLoader(); - } - } + }); + app.loadLastRefreshedTime(); }, loadCoinData: async (coin) => { diff --git a/basicswap/templates/offers.html b/basicswap/templates/offers.html index 6681e08..5ee178a 100644 --- a/basicswap/templates/offers.html +++ b/basicswap/templates/offers.html @@ -195,7 +195,6 @@ function getAPIKeys() { {% endif %} -
@@ -208,34 +207,69 @@ function getAPIKeys() {
- - -
- {{ input_arrow_down_svg | safe }} - -
-
-
-

{{ arrow_right_svg | safe }}

+ {% if sent_offers %} + + +
+ {{ input_arrow_down_svg | safe }} +
-
- - -
- {{ input_arrow_down_svg | safe }} - -
-
+ +
+
+

{{ arrow_right_svg | safe }}

+
+
+ + +
+ {{ input_arrow_down_svg | safe }} + +
+
+ {% else %} +
+
+ + +
+ {{ input_arrow_down_svg | safe }} + +
+
+
+

{{ arrow_right_svg | safe }}

+
+
+ + +
+ {{ input_arrow_down_svg | safe }} + +
+
+ {% endif %}
@@ -287,7 +321,7 @@ function getAPIKeys() { - +
@@ -334,7 +368,9 @@ function getAPIKeys() {
- + + +