Fix image matching to use Toast item ID from filename, not alt text

This commit is contained in:
John Mizerek 2026-02-12 20:51:37 -08:00
parent 4471ddc92b
commit 04f65e3495

View file

@ -1449,8 +1449,12 @@
// Remove loading message and start conversation flow
document.getElementById('conversation').innerHTML = '';
// In add-menu mode, skip business info and header
if (config.businessId && config.menuId) {
// Check if any items have imageUrl - if so, offer image upload matching
const itemsWithImages = (config.extractedData.items || []).filter(item => item.imageUrl).length;
if (itemsWithImages > 0) {
showImageMatchingStep();
} else if (config.businessId && config.menuId) {
// In add-menu mode, skip business info and header
showCategoriesStep();
} else {
showBusinessInfoStep();
@ -1489,12 +1493,12 @@
// Show step to upload images from saved webpage subfolder and match to items
function showImageMatchingStep() {
const itemCount = config.extractedData.items ? config.extractedData.items.length : 0;
const mappingCount = config.imageMappings.length;
const itemsWithImages = (config.extractedData.items || []).filter(item => item.imageUrl).length;
addMessage('ai', `
<p>I found <strong>${itemCount} menu items</strong> and detected <strong>${mappingCount} image references</strong> in the HTML.</p>
<p>To add images to your menu items, upload the images from the saved webpage folder (usually named something like <code>pagename_files</code>).</p>
<p style="font-size:13px;color:var(--gray-500);">I'll automatically match images to items based on filenames.</p>
<p>I found <strong>${itemCount} menu items</strong> with <strong>${itemsWithImages} image references</strong>.</p>
<p>Upload the images from your saved webpage folder to add them to menu items.</p>
<p style="font-size:13px;color:var(--gray-500);">I'll match by Toast item ID in the filename.</p>
<div style="margin-top:16px;">
<input type="file" id="matchImagesInput" accept="image/*" multiple style="display:none;" onchange="handleImageMatching(event)">
<button class="btn btn-primary" onclick="document.getElementById('matchImagesInput').click()">
@ -1517,38 +1521,56 @@
let matchedCount = 0;
const matchResults = [];
const items = config.extractedData.items || [];
// Extract Toast-style item ID from filename (e.g., "item-600000000167924464_1636677556.jpg")
function extractToastId(str) {
// Match the long numeric ID pattern from Toast filenames
const match = str.match(/item-(\d{15,})/i);
return match ? match[1] : null;
}
// Skip duplicate sizes (_002, _003, _004 suffixes)
function isBaseSizeImage(filename) {
return !/_00[234]\.[^.]+$/i.test(filename);
}
Array.from(files).forEach(file => {
const filename = file.name.toLowerCase();
const filename = file.name;
// Try to find a matching mapping
for (const mapping of config.imageMappings) {
const mappingFilename = mapping.filename.toLowerCase();
// Skip smaller size variants - only use base image
if (!isBaseSizeImage(filename)) {
return;
}
// Check for exact filename match or close match
if (filename === mappingFilename ||
filename.includes(mappingFilename.replace(/\.[^.]+$/, '')) ||
mappingFilename.includes(filename.replace(/\.[^.]+$/, ''))) {
// Extract Toast item ID from uploaded filename
const uploadedToastId = extractToastId(filename);
// Find matching item by alt text or name
const altText = (mapping.alt || '').toLowerCase();
const matchedItem = config.extractedData.items.find(item => {
const itemName = (item.name || '').toLowerCase();
const itemAlt = (item.imageAlt || '').toLowerCase();
return itemName === altText ||
itemAlt === altText ||
itemName.includes(altText) ||
altText.includes(itemName) ||
(itemAlt && (itemAlt.includes(altText) || altText.includes(itemAlt)));
});
// Try to match to an item
let matchedItem = null;
if (matchedItem) {
config.itemImages[matchedItem.id] = file;
matchedCount++;
matchResults.push({ item: matchedItem.name, file: file.name });
break;
}
}
if (uploadedToastId) {
// Match by Toast ID in imageUrl
matchedItem = items.find(item => {
if (!item.imageUrl) return false;
const itemToastId = extractToastId(item.imageUrl);
return itemToastId === uploadedToastId;
});
}
// Fallback: match by filename contained in imageUrl
if (!matchedItem) {
const filenameBase = filename.replace(/\.[^.]+$/, '').toLowerCase();
matchedItem = items.find(item => {
if (!item.imageUrl) return false;
return item.imageUrl.toLowerCase().includes(filenameBase);
});
}
if (matchedItem && !config.itemImages[matchedItem.id]) {
config.itemImages[matchedItem.id] = file;
matchedCount++;
matchResults.push({ item: matchedItem.name, file: file.name });
}
});