Fix powder catalog lookup: exact match auto-fills, partials show picker modal
- CatalogLookup now returns all partial color name matches ranked by specificity (exact vendor+color first, same-vendor partial, cross-vendor) with isExact flag so JS can decide to auto-fill vs show modal - Removed cross-vendor fallback that was silently overwriting manufacturer field with wrong brand when vendor-scoped search found nothing - Picker modal now includes "Not listed — search online" option that triggers AI lookup as an escape hatch from the catalog results Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -62,23 +62,25 @@
|
||||
const items = await resp.json();
|
||||
|
||||
if (items.length === 0) {
|
||||
// No catalog match — fall back to AI if available
|
||||
hideStatus();
|
||||
if (typeof window._runInventoryAiLookup === 'function') {
|
||||
showStatus('info', '<span class="spinner-border spinner-border-sm me-1"></span>Not in catalog — searching with AI…');
|
||||
await window._runInventoryAiLookup();
|
||||
} else {
|
||||
showStatus('warning', 'No match found in the catalog. Enter details manually or enable AI Lookup.');
|
||||
}
|
||||
// Nothing in catalog — go straight to AI
|
||||
await runAiOrWarn();
|
||||
return;
|
||||
}
|
||||
|
||||
if (items.length === 1) {
|
||||
// Single exact match (vendor + color name both match precisely) — auto-fill
|
||||
if (items.length === 1 && items[0].isExact) {
|
||||
await fillFields(items[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Multiple matches — let the user pick via modal
|
||||
// Exact match exists but so do other results — auto-fill the exact one
|
||||
const exactMatches = items.filter(i => i.isExact);
|
||||
if (exactMatches.length === 1) {
|
||||
await fillFields(exactMatches[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
// No exact match (or ambiguous) — show picker modal with "Not Listed" escape hatch
|
||||
hideStatus();
|
||||
showPickerModal(items);
|
||||
|
||||
@@ -89,6 +91,18 @@
|
||||
}
|
||||
});
|
||||
|
||||
// ── AI fallback helper ───────────────────────────────────────────────────
|
||||
|
||||
async function runAiOrWarn() {
|
||||
hideStatus();
|
||||
if (typeof window._runInventoryAiLookup === 'function') {
|
||||
showStatus('info', '<span class="spinner-border spinner-border-sm me-1"></span>Not in catalog — searching online with AI…');
|
||||
await window._runInventoryAiLookup();
|
||||
} else {
|
||||
showStatus('warning', 'No match found in the catalog. Enter details manually or enable AI Lookup.');
|
||||
}
|
||||
}
|
||||
|
||||
// ── Fill fields from a catalog result ────────────────────────────────────
|
||||
|
||||
async function fillFields(item) {
|
||||
@@ -368,6 +382,12 @@
|
||||
<div class="modal-body p-0">
|
||||
<div class="list-group list-group-flush">${rows}</div>
|
||||
</div>
|
||||
<div class="modal-footer py-2 justify-content-start">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" id="catalogPickerNotListed">
|
||||
<i class="bi bi-search me-1"></i>Not listed — search online
|
||||
</button>
|
||||
<span class="text-muted small ms-2">Uses AI to look up the exact product</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
@@ -383,6 +403,11 @@
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('catalogPickerNotListed').addEventListener('click', function () {
|
||||
bsModal.hide();
|
||||
runAiOrWarn();
|
||||
});
|
||||
|
||||
bsModal.show();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user