Browser session recovery, price tracking, and dashboard improvements

- Add browser session validation and auto-restart for BestBuy/GameStop scrapers
- Add price change detection and notifications
- Remove PokemonCenter scraper (now uses Chrome Extension)
- Dashboard UI improvements

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-04-01 22:18:35 -04:00
parent 74c2a45d50
commit e5527628a5
11 changed files with 530 additions and 468 deletions
+29
View File
@@ -771,6 +771,9 @@ async function loadControlPanel() {
// Render scrapers grid
renderScrapersGrid(state.scrapers);
// Load Chrome Extension status
loadExtensionStatus();
// Setup event listeners for control panel buttons
setupControlPanelListeners();
@@ -783,10 +786,36 @@ async function loadControlPanel() {
updateMonitorStatus(newState);
renderScrapersGrid(newState.scrapers);
}
loadExtensionStatus();
}
}, 5000);
}
async function loadExtensionStatus() {
const badge = document.getElementById('extensionBadge');
const productCount = document.getElementById('extProductCount');
const skuCount = document.getElementById('extSkuCount');
const lastSync = document.getElementById('extLastSync');
const stats = await api('/extension/stats');
if (stats && stats.last_sync) {
// Extension has synced data
badge.textContent = 'Connected';
badge.className = 'extension-badge connected';
productCount.textContent = stats.total_products || 0;
skuCount.textContent = stats.total_skus || 0;
lastSync.textContent = formatTime(new Date(stats.last_sync));
} else {
// No sync yet
badge.textContent = 'No Data';
badge.className = 'extension-badge disconnected';
productCount.textContent = '-';
skuCount.textContent = '-';
lastSync.textContent = 'Never';
}
}
function updateMonitorStatus(state) {
const badge = document.getElementById('monitorBadge');
const statusText = document.getElementById('monitorStatusText');
+51
View File
@@ -1103,6 +1103,57 @@ h3 {
grid-column: span 2;
}
/* Chrome Extension Card */
.extension-card {
grid-column: span 2;
border-color: #ffcb05;
}
.extension-badge {
padding: 4px 12px;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
}
.extension-badge.connected {
background: rgba(0, 255, 0, 0.2);
color: #00ff00;
}
.extension-badge.disconnected {
background: rgba(255, 100, 100, 0.2);
color: #ff6464;
}
.extension-stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 15px;
margin-top: 10px;
}
.extension-stat {
background: var(--bg-primary);
padding: 12px;
border-radius: 8px;
text-align: center;
}
.extension-stat .stat-label {
display: block;
font-size: 12px;
color: var(--text-secondary);
margin-bottom: 5px;
}
.extension-stat .stat-value {
display: block;
font-size: 18px;
font-weight: 600;
color: var(--text-primary);
}
.scrapers-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));