Add clickable bid counters in the header that navigate to the sent/received tabs + small fix.

This commit is contained in:
gerlofvanek
2025-05-08 22:31:39 +02:00
parent ece9d7fb4b
commit b3c0ad7e9c
4 changed files with 248 additions and 59 deletions

View File

@@ -1925,3 +1925,74 @@ if (document.readyState === 'loading') {
} else { } else {
initialize(); initialize();
} }
(function() {
function handleBidsTabFromHash() {
if (window.location.pathname !== '/bids') {
return;
}
const hash = window.location.hash;
if (hash) {
const tabName = hash.substring(1);
let tabId;
switch (tabName.toLowerCase()) {
case 'sent':
tabId = '#sent';
break;
case 'received':
tabId = '#received';
break;
default:
tabId = '#sent';
}
switchTab(tabId);
} else {
switchTab('#sent');
}
}
function switchTab(tabId) {
const targetTabBtn = document.querySelector(`[data-tabs-target="${tabId}"]`);
if (targetTabBtn) {
targetTabBtn.click();
}
}
function setupBidsTabNavigation() {
handleBidsTabFromHash();
window.addEventListener('hashchange', handleBidsTabFromHash);
const originalSwitchTab = window.switchTab || null;
window.switchTab = function(tabId) {
const newTabName = tabId.replace('#', '');
if (window.location.hash !== `#${newTabName}`) {
history.replaceState(null, null, `#${newTabName}`);
}
if (originalSwitchTab && typeof originalSwitchTab === 'function') {
originalSwitchTab(tabId);
} else {
const targetTabBtn = document.querySelector(`[data-tabs-target="${tabId}"]`);
if (targetTabBtn) {
targetTabBtn.click();
}
}
};
const tabButtons = document.querySelectorAll('[data-tabs-target]');
tabButtons.forEach(btn => {
btn.addEventListener('click', function() {
const tabId = this.getAttribute('data-tabs-target');
const tabName = tabId.replace('#', '');
history.replaceState(null, null, `#${tabName}`);
});
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', setupBidsTabNavigation);
} else {
setupBidsTabNavigation();
}
})();

View File

@@ -1518,7 +1518,7 @@ refreshAllData: async function() {
} }
}, 1000); }, 1000);
} }
console.log(`Price refresh completed at ${new Date().toLocaleTimeString()}. Updated ${window.config.coins.length - failedCoins.length}/${window.config.coins.length} coins.`); //console.log(`Price refresh completed at ${new Date().toLocaleTimeString()}. Updated ${window.config.coins.length - failedCoins.length}/${window.config.coins.length} coins.`);
} catch (error) { } catch (error) {
console.error('Critical error during refresh:', error); console.error('Critical error during refresh:', error);

View File

@@ -0,0 +1,127 @@
(function() {
'use strict';
document.addEventListener('DOMContentLoaded', initBidsTabNavigation);
window.addEventListener('load', handleHashChange);
window.addEventListener('hashchange', preventScrollOnHashChange);
function initBidsTabNavigation() {
const sentTabButton = document.getElementById('sent-tab');
const receivedTabButton = document.getElementById('received-tab');
if (!sentTabButton || !receivedTabButton) {
return;
}
document.querySelectorAll('.bids-tab-link').forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
const targetTabId = this.getAttribute('data-tab-target');
if (targetTabId) {
if (window.location.pathname === '/bids') {
const oldScrollPosition = window.scrollY;
activateTab(targetTabId);
setTimeout(function() {
window.scrollTo(0, oldScrollPosition);
history.replaceState(null, null, '#' + targetTabId.replace('#', ''));
}, 0);
} else {
localStorage.setItem('bidsTabToActivate', targetTabId.replace('#', ''));
window.location.href = '/bids';
}
}
});
});
const tabToActivate = localStorage.getItem('bidsTabToActivate');
if (tabToActivate) {
localStorage.removeItem('bidsTabToActivate');
activateTab('#' + tabToActivate);
} else if (window.location.pathname === '/bids' && !window.location.hash) {
activateTab('#sent');
}
}
function preventScrollOnHashChange(e) {
if (window.location.pathname !== '/bids') {
return;
}
e.preventDefault();
const oldScrollPosition = window.scrollY;
const hash = window.location.hash;
if (hash) {
const tabId = `#${hash.replace('#', '')}`;
activateTab(tabId);
} else {
activateTab('#sent');
}
setTimeout(function() {
window.scrollTo(0, oldScrollPosition);
}, 0);
}
function handleHashChange() {
if (window.location.pathname !== '/bids') {
return;
}
const oldScrollPosition = window.scrollY;
const hash = window.location.hash;
if (hash) {
const tabId = `#${hash.replace('#', '')}`;
activateTab(tabId);
} else {
activateTab('#sent');
}
setTimeout(function() {
window.scrollTo(0, oldScrollPosition);
}, 0);
}
function activateTab(tabId) {
if (tabId !== '#sent' && tabId !== '#received') {
tabId = '#sent';
}
const tabButtonId = tabId === '#sent' ? 'sent-tab' : 'received-tab';
const tabButton = document.getElementById(tabButtonId);
if (tabButton) {
const oldScrollPosition = window.scrollY;
tabButton.click();
setTimeout(function() {
window.scrollTo(0, oldScrollPosition);
}, 0);
}
}
window.navigateToBidsTab = function(tabId) {
if (window.location.pathname === '/bids') {
const oldScrollPosition = window.scrollY;
activateTab('#' + (tabId === 'sent' || tabId === 'received' ? tabId : 'sent'));
setTimeout(function() {
window.scrollTo(0, oldScrollPosition);
history.replaceState(null, null, '#' + tabId);
}, 0);
} else {
localStorage.setItem('bidsTabToActivate', tabId);
window.location.href = '/bids';
}
};
})();

View File

@@ -63,6 +63,7 @@
<script src="/static/js/libs/tippy.js"></script> <script src="/static/js/libs/tippy.js"></script>
<!-- UI Components --> <!-- UI Components -->
<script src="/static/js/ui/tabs.js"></script> <script src="/static/js/ui/tabs.js"></script>
<script src="/static/js/ui/bids-tab-navigation.js"></script>
<script src="/static/js/ui/dropdown.js"></script> <script src="/static/js/ui/dropdown.js"></script>
<!-- Core functionality --> <!-- Core functionality -->
<script src="/static/js/modules/coin-manager.js"></script> <script src="/static/js/modules/coin-manager.js"></script>
@@ -84,6 +85,7 @@
<script src="/static/js/modules/memory-manager.js"></script> <script src="/static/js/modules/memory-manager.js"></script>
<!-- Main application script --> <!-- Main application script -->
<script src="/static/js/global.js"></script> <script src="/static/js/global.js"></script>
</head> </head>
<body class="dark:bg-gray-700"> <body class="dark:bg-gray-700">
<div id="shutdownModal" tabindex="-1" class="hidden fixed inset-0 z-50 overflow-y-auto overflow-x-hidden"> <div id="shutdownModal" tabindex="-1" class="hidden fixed inset-0 z-50 overflow-y-auto overflow-x-hidden">
@@ -422,26 +424,17 @@
<!-- Bids --> <!-- Bids -->
<li> <li>
<a href="/bids" data-tooltip-target="tooltip-bids" class="flex items-center text-sm text-gray-400 <a href="/bids" data-tooltip-target="tooltip-bids" class="flex items-center text-sm text-gray-400 hover:text-gray-600 dark:text-gray-100 dark:hover:text-gray-100">
hover:text-gray-600 dark:text-gray-100 dark:hover:text-gray-100">
<span class="inline-block mr-2">{{ bids_sent_svg | safe }}</span> <span class="inline-block mr-2">{{ bids_sent_svg | safe }}</span>
<span>Bids</span> <span class="my-auto">Bids</span>
<span class="flex items-center ml-2"> <span class="flex items-center ml-2 my-auto">
<span id="sent-bids-counter" class="inline-flex items-center text-xs font-semibold px-2.5 py-1 text-white {% if summary.num_sent_active_bids > 0 %}bg-blue-500{% else %}bg-gray-400{% endif %} rounded-full bids-tab-link cursor-pointer" data-tab-target="#sent">
<!-- Outgoing bids counter arrow -->
<span id="sent-bids-counter" class="inline-flex items-center text-xs font-semibold px-2.5 py-1
text-white {% if summary.num_sent_active_bids > 0 %}bg-blue-500{% else %}bg-gray-400{% endif %}
rounded-full">
<svg class="w-3 h-3 mr-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg class="w-3 h-3 mr-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 19V5L19 12L5 19Z" fill="currentColor" transform="rotate(-90 12 12)"/> <path d="M5 19V5L19 12L5 19Z" fill="currentColor" transform="rotate(-90 12 12)"/>
</svg> </svg>
{{ summary.num_sent_active_bids }} {{ summary.num_sent_active_bids }}
</span> </span>
<span id="recv-bids-counter" class="inline-flex items-center text-xs font-semibold ml-2 px-2.5 py-1 text-white {% if summary.num_recv_active_bids > 0 %}bg-blue-500{% else %}bg-gray-400{% endif %} rounded-full bids-tab-link cursor-pointer" data-tab-target="#received">
<!-- Incoming bids counter arrow -->
<span id="recv-bids-counter" class="inline-flex items-center text-xs font-semibold ml-2 px-2.5
py-1 text-white {% if summary.num_recv_active_bids > 0 %}bg-blue-500{% else %}bg-gray-400
{% endif %} rounded-full">
<svg class="w-3 h-3 mr-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg class="w-3 h-3 mr-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 19V5L19 12L5 19Z" fill="currentColor" transform="rotate(90 12 12)"/> <path d="M5 19V5L19 12L5 19Z" fill="currentColor" transform="rotate(90 12 12)"/>
</svg> </svg>
@@ -449,14 +442,11 @@
</span> </span>
</span> </span>
</a> </a>
<div id="tooltip-bids" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm <div id="tooltip-bids" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300
tooltip">
<p><b>Sent bids:</b> {{ sent_bids_count }} ({{ summary.num_sent_active_bids }} active)</p> <p><b>Sent bids:</b> {{ sent_bids_count }} ({{ summary.num_sent_active_bids }} active)</p>
<p><b>Received bids:</b> {{ received_bids_count }} ({{ summary.num_recv_active_bids }} active)</p> <p><b>Received bids:</b> {{ received_bids_count }} ({{ summary.num_recv_active_bids }} active)</p>
</div> </div>
</li> </li>
<li> <li>
<span class="text-gray-300">|</span> <span class="text-gray-300">|</span>
</li> </li>
@@ -556,11 +546,12 @@
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/bids"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/bids">
{{ bids_received_svg | safe }} {{ bids_received_svg | safe }}
<span>Bids</span> <span class="my-auto">Bids</span>
<div class="flex ml-auto"> <div class="flex items-center ml-auto my-auto">
<span id="sent-bids-counter" class="inline-flex items-center text-xs font-semibold px-2.5 <span id="sent-bids-counter" class="inline-flex items-center text-xs font-semibold px-2.5
py-1 text-white {% if summary.num_sent_active_bids and summary.num_sent_active_bids > 0 %} py-1 text-white {% if summary.num_sent_active_bids and summary.num_sent_active_bids > 0 %}
bg-blue-500{% else %}bg-gray-400{% endif %} rounded-full mr-2"> bg-blue-500{% else %}bg-gray-400{% endif %} rounded-full mr-2 bids-tab-link cursor-pointer"
data-tab-target="#sent">
<svg class="w-3 h-3 mr-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg class="w-3 h-3 mr-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 19V5L19 12L5 19Z" fill="currentColor" transform="rotate(-90 12 12)"/> <path d="M5 19V5L19 12L5 19Z" fill="currentColor" transform="rotate(-90 12 12)"/>
</svg> </svg>
@@ -568,7 +559,8 @@
</span> </span>
<span id="recv-bids-counter" class="inline-flex items-center text-xs font-semibold px-2.5 <span id="recv-bids-counter" class="inline-flex items-center text-xs font-semibold px-2.5
py-1 text-white {% if summary.num_recv_active_bids and summary.num_recv_active_bids > 0 %} py-1 text-white {% if summary.num_recv_active_bids and summary.num_recv_active_bids > 0 %}
bg-blue-500{% else %}bg-gray-400{% endif %} rounded-full"> bg-blue-500{% else %}bg-gray-400{% endif %} rounded-full bids-tab-link cursor-pointer"
data-tab-target="#received">
<svg class="w-3 h-3 mr-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg class="w-3 h-3 mr-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 19V5L19 12L5 19Z" fill="currentColor" transform="rotate(90 12 12)"/> <path d="M5 19V5L19 12L5 19Z" fill="currentColor" transform="rotate(90 12 12)"/>
</svg> </svg>
@@ -576,7 +568,6 @@
</span> </span>
</div> </div>
</a> </a>
</li>
<li> <li>
<a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/active"> <a class="flex items-center pl-3 py-3 pr-4 text-gray-50 hover:bg-gray-900 rounded" href="/active">
<div id="swapContainer" class="inline-flex center-spin mr-2" <div id="swapContainer" class="inline-flex center-spin mr-2"