diff --git a/portal/setup-wizard.html b/portal/setup-wizard.html index 4172843..7108f13 100644 --- a/portal/setup-wizard.html +++ b/portal/setup-wizard.html @@ -1401,6 +1401,200 @@ // Hide upload section, show conversation document.getElementById('uploadSection').style.display = 'none'; + addMessage('ai', ` +
This takes about 30 seconds while I crawl the site and look for menu sub-pages.
+ `); + + try { + // Phase 1: Discovery — quick Playwright crawl to find menu pages + const discoverResp = await fetch(`${config.apiBaseUrl}/setup/analyzeMenuUrl.php`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ mode: 'discover', url }) + }); + const discoverResult = await discoverResp.json(); + + if (!discoverResult.OK) { + throw new Error(discoverResult.MESSAGE || 'Failed to scan website'); + } + + console.log('=== DISCOVERY RESULT ===', discoverResult); + document.getElementById('conversation').innerHTML = ''; + + const menuPages = discoverResult.menuPages || []; + const siteName = discoverResult.siteName || ''; + + if (menuPages.length > 1) { + // Multiple menus found — show confirmation step + const pageListHtml = menuPages.map((p, i) => ` + + `).join(''); + + addMessage('ai', ` +I found ${menuPages.length} menu pages${siteName ? ' for ' + siteName + '' : ''}:
+Uncheck any that aren't actual menus. Each checked page will be analyzed separately.
+Sorry, I encountered an error importing from that URL:
+${error.message}
+ + `); + } + } + + // Phase 2: Extract each confirmed menu page individually + async function extractConfirmedMenuPages(mainUrl) { + const checkboxes = document.querySelectorAll('#discoveredMenuPages input[type="checkbox"]:checked'); + const pages = Array.from(checkboxes).map(cb => ({ + url: cb.dataset.menuUrl, + name: cb.dataset.menuName + })); + + // Add extra URL if provided + const extraUrl = (document.getElementById('extraMenuUrl')?.value || '').trim(); + if (extraUrl) { + const slug = extraUrl.replace(/.*\//, '').replace(/[-_]/g, ' '); + pages.push({ url: extraUrl, name: slug ? slug.charAt(0).toUpperCase() + slug.slice(1) : 'Extra' }); + } + + if (pages.length === 0) { + alert('Please select at least one menu page.'); + return; + } + + document.getElementById('conversation').innerHTML = ''; + + // Combined results + const allItems = []; + const allCategories = []; + const allMenus = []; + let businessInfo = {}; + let totalProcessed = 0; + + for (const page of pages) { + addMessage('ai', ` +Extracted ${page.name}: ${data.items?.length || 0} items in ${data.categories?.length || 0} categories
+ `); + } else { + document.getElementById('conversation').innerHTML = ''; + addMessage('ai', `Could not extract items from ${page.name} page.
`); + totalProcessed++; + } + } catch (err) { + console.error(`Error extracting ${page.name}:`, err); + document.getElementById('conversation').innerHTML = ''; + addMessage('ai', `Error extracting ${page.name}: ${err.message}
`); + totalProcessed++; + } + } + + // Build final combined data + document.getElementById('conversation').innerHTML = ''; + config.extractedData = { + business: businessInfo, + categories: allCategories, + items: allItems, + modifiers: [], + menus: allMenus.length > 1 ? allMenus : [], + imageMappings: [], + imageUrls: [], + headerCandidateIndices: [], + }; + config.sourceUrl = mainUrl; + config.imageMappings = []; + + const totalItems = allItems.length; + const totalCats = allCategories.length; + addMessage('ai', ` +Done! Found ${totalItems} items across ${totalCats} categories in ${allMenus.length} menus.
+ `); + + console.log('=== MULTI-PAGE EXTRACT RESULT ===', config.extractedData); + + // Brief pause then continue to business info + await new Promise(r => setTimeout(r, 1500)); + document.getElementById('conversation').innerHTML = ''; + if (config.businessId && config.menuId) { + showCategoriesStep(); + } else { + showBusinessInfoStep(); + } + } + + // Fallback: extract entire site as single page (original behavior) + async function skipDiscoveryExtractAll(url) { + document.getElementById('conversation').innerHTML = ''; + await extractSingleUrl(url); + } + + async function extractSingleUrl(url) { addMessage('ai', `