feat: add loading spinners on tab switch for data-driven tabs
Show a CSS spinner overlay when switching to Autonomous Stats (tab6), Memories (tab9), and DM Management (tab10). Spinner only shows on first visit when content is empty, removed after data loads.
This commit is contained in:
@@ -455,6 +455,28 @@
|
|||||||
.tab-content.active {
|
.tab-content.active {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Tab loading spinner */
|
||||||
|
.tab-loading-overlay {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 3rem 1rem;
|
||||||
|
color: #888;
|
||||||
|
font-size: 1rem;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
.tab-loading-overlay .spinner {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border: 3px solid #444;
|
||||||
|
border-top-color: #4CAF50;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 0.8s linear infinite;
|
||||||
|
}
|
||||||
|
@keyframes spin {
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
/* Chat Interface Styles */
|
/* Chat Interface Styles */
|
||||||
.chat-message {
|
.chat-message {
|
||||||
@@ -1852,16 +1874,43 @@ function switchTab(tabId) {
|
|||||||
loadStatus();
|
loadStatus();
|
||||||
loadLastPrompt();
|
loadLastPrompt();
|
||||||
}
|
}
|
||||||
|
if (tabId === 'tab6') {
|
||||||
|
showTabLoading('tab6');
|
||||||
|
loadAutonomousStats().finally(() => hideTabLoading('tab6'));
|
||||||
|
}
|
||||||
if (tabId === 'tab9') {
|
if (tabId === 'tab9') {
|
||||||
console.log('🧠 Refreshing memory stats for Memories tab');
|
console.log('🧠 Refreshing memory stats for Memories tab');
|
||||||
refreshMemoryStats();
|
showTabLoading('tab9');
|
||||||
|
refreshMemoryStats().finally(() => hideTabLoading('tab9'));
|
||||||
}
|
}
|
||||||
if (tabId === 'tab10') {
|
if (tabId === 'tab10') {
|
||||||
console.log('📱 Loading DM users for DM Management tab');
|
console.log('📱 Loading DM users for DM Management tab');
|
||||||
loadDMUsers();
|
showTabLoading('tab10');
|
||||||
|
loadDMUsers().finally(() => hideTabLoading('tab10'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showTabLoading(tabId) {
|
||||||
|
const tab = document.getElementById(tabId);
|
||||||
|
if (!tab) return;
|
||||||
|
// Only show if no data loaded yet (first visit)
|
||||||
|
if (tab.querySelector('.tab-loading-overlay')) return;
|
||||||
|
const sections = tab.querySelectorAll('.section');
|
||||||
|
const hasContent = Array.from(sections).some(s => s.querySelector('[id]')?.innerHTML?.trim());
|
||||||
|
if (hasContent) return; // Data already loaded, skip spinner
|
||||||
|
const overlay = document.createElement('div');
|
||||||
|
overlay.className = 'tab-loading-overlay';
|
||||||
|
overlay.innerHTML = '<div class="spinner"></div> Loading...';
|
||||||
|
tab.prepend(overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideTabLoading(tabId) {
|
||||||
|
const tab = document.getElementById(tabId);
|
||||||
|
if (!tab) return;
|
||||||
|
const overlay = tab.querySelector('.tab-loading-overlay');
|
||||||
|
if (overlay) overlay.remove();
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Initialization — all setup in one DOMContentLoaded
|
// Initialization — all setup in one DOMContentLoaded
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user