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 780347d..5583f7d 100644 --- a/basicswap/static/js/pricechart.js +++ b/basicswap/static/js/pricechart.js @@ -1061,27 +1061,37 @@ const app = { }, updateAutoRefreshButton: () => { - const button = document.getElementById('toggle-auto-refresh'); - if (button) { - if (app.isAutoRefreshEnabled) { - button.classList.remove('text-gray-600', 'dark:text-gray-400'); - button.classList.add('text-green-500', 'dark:text-green-400'); - } else { - button.classList.remove('text-green-500', 'dark:text-green-400'); - button.classList.add('text-gray-600', 'dark:text-gray-400'); - } - button.title = app.isAutoRefreshEnabled ? 'Disable Auto-Refresh' : 'Enable Auto-Refresh'; - - const svg = button.querySelector('svg'); - if (svg) { - if (app.isAutoRefreshEnabled) { - svg.classList.add('animate-spin'); - } else { - svg.classList.remove('animate-spin'); - } - } + const button = document.getElementById('toggle-auto-refresh'); + if (button) { + if (app.isAutoRefreshEnabled) { + button.classList.remove('text-gray-600', 'dark:text-gray-400'); + button.classList.add('text-green-500', 'dark:text-green-400'); + app.startSpinAnimation(); + } else { + button.classList.remove('text-green-500', 'dark:text-green-400'); + button.classList.add('text-gray-600', 'dark:text-gray-400'); + app.stopSpinAnimation(); } - }, + button.title = app.isAutoRefreshEnabled ? 'Disable Auto-Refresh' : 'Enable Auto-Refresh'; + } +}, + +startSpinAnimation: () => { + const svg = document.querySelector('#toggle-auto-refresh svg'); + if (svg) { + svg.classList.add('animate-spin'); + setTimeout(() => { + svg.classList.remove('animate-spin'); + }, 2000); // Remove the animation after 2 seconds + } +}, + +stopSpinAnimation: () => { + const svg = document.querySelector('#toggle-auto-refresh svg'); + if (svg) { + svg.classList.remove('animate-spin'); + } +}, refreshAllData: async () => { ui.showLoader(); 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() {
- + + +