Files
PowderCoatingLogix/wwwroot/js/catalog-price-check.js
T
spouliot 9943c11571 Add progress overlay to AI Catalog Price Check
Shows a modal overlay with animated progress bar and batch-aware status messages
while Claude is analyzing. Progress animates in two phases: ease-out to ~85%
over the estimated duration, then a slow crawl to 99% so it never falsely
"completes" before the server responds.

- Overlay driven by CSS (hidden until .active added by JS)
- Item count passed from controller as data-item-count on the run button
- Batch count derived from item count (batches of 25) to show accurate
  "Analyzing batch N of M…" messages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 19:27:08 -04:00

86 lines
3.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
(function () {
'use strict';
var form = document.getElementById('runForm');
var btn = document.getElementById('runBtn');
var overlay = document.getElementById('price-check-overlay');
var bar = document.getElementById('overlay-bar');
var pctLabel = document.getElementById('overlay-pct');
var statusMsg = document.getElementById('overlay-status');
if (!form || !btn || !overlay) return;
// Estimate total seconds based on item count (roughly 12s per batch of 25, min 15s).
function estimateDuration(itemCount) {
var batches = Math.max(1, Math.ceil(itemCount / 25));
return Math.max(15, batches * 12);
}
// Messages keyed to approximate progress milestones (0100).
function messageAt(pct, batchCount) {
if (pct < 10) return 'Loading catalog items…';
if (pct < 20) return 'Sending items to Claude…';
if (batchCount <= 1) {
if (pct < 75) return 'Analyzing your catalog with AI…';
if (pct < 92) return 'Reviewing pricing data…';
} else {
var batchDone = Math.floor((pct / 100) * batchCount);
if (batchDone < batchCount) {
return 'Analyzing batch ' + (batchDone + 1) + ' of ' + batchCount + '…';
}
}
if (pct < 97) return 'Compiling results…';
return 'Almost done…';
}
function setProgress(pct, batchCount) {
var clamped = Math.min(99, Math.max(0, pct));
bar.style.width = clamped + '%';
pctLabel.textContent = Math.round(clamped);
statusMsg.textContent = messageAt(clamped, batchCount);
}
form.addEventListener('submit', function () {
btn.disabled = true;
var itemCount = parseInt(btn.getAttribute('data-item-count') || '0', 10);
var batchCount = Math.max(1, Math.ceil(itemCount / 25));
var totalSecs = estimateDuration(itemCount);
overlay.classList.add('active');
setProgress(0, batchCount);
// Animate progress: fast to ~85%, then slow crawl toward 99%.
// Uses two easing phases so it never "finishes" before the server responds.
var start = Date.now();
var phase1End = totalSecs * 0.80 * 1000; // 80% of time → 85% progress
var raf;
function tick() {
var elapsed = Date.now() - start;
var pct;
if (elapsed < phase1End) {
// Phase 1: ease-out from 0 → 85
var t = elapsed / phase1End;
pct = 85 * (1 - Math.pow(1 - t, 2));
} else {
// Phase 2: slow crawl 85 → 99 (never quite reaches 99)
var t2 = (elapsed - phase1End) / (totalSecs * 1000);
pct = 85 + 14 * (1 - Math.exp(-t2 * 1.5));
}
setProgress(pct, batchCount);
raf = requestAnimationFrame(tick);
}
raf = requestAnimationFrame(tick);
// Safety: if the server takes much longer than estimated, keep the overlay up.
// The page navigation itself will tear it down.
window.addEventListener('pagehide', function () {
cancelAnimationFrame(raf);
});
});
}());