Use getElementById for progressDiv/spinnerDiv inside an addMessage bubble
so completed lines persist as each menu finishes extracting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously each extraction step cleared the conversation and only showed
the latest result. Now completed menus accumulate as checkmarked lines
while the spinner updates in place for the current extraction.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PHP returns prices as strings (e.g. "0.000000000"). Wrap in parseFloat()
before calling .toFixed(2) to prevent render crash.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New users without an existing menu to import can now click "Start from Scratch"
to enter their business info and get redirected to the Menu Builder.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Pass platform URLs from discovery to extraction phase
- Call platform_images mode with stealth Playwright
- Fuzzy match platform images to extracted items by name
- Show progress during image fetching
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- showItemsStep rendered per-category index as data-item-id
- confirmItems filtered by global index, causing massive mismatch
- Now assigns unique 'item_N' IDs to all items before rendering
- Also preserves menuName in category confirmation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add console.log to showFinalStep for menus debugging
- Preserve menuName property when rebuilding categories in confirmCategories
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Store schedule per menu from Claude extraction
- Show schedule in progress messages
- Compute combined business hours from all menu schedules
- Display schedule summary in final result
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Store businessInfo from discovery phase
- Pre-populate from JSON-LD/meta before sub-page extraction
- Only fill gaps from sub-page Claude responses
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Phase 1: Quick scan shows detected menu pages with checkboxes
- User confirms which pages are actual menus
- Phase 2: Each page extracted individually through Claude
- Shows progress for each page being processed
- Falls back to single-page extract if no sub-pages found
- Optional extra URL field for manual addition
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Handles "United States/USA" at end of address string that
was blocking ZIP and state regex extraction.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the import detects multiple menus (Brunch, Lunch, Dinner, etc.),
shows checkboxes for each menu instead of a single menu name input.
Passes selectedMenus array to saveWizard for separate menu creation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PHP API is now deployed on both dev and biz servers with PHP-FPM.
Admin endpoints (quickTasks, scheduledTasks) remain .cfm as they
haven't been ported yet.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Another tab doing the PHP migration renamed all API endpoint references
from .cfm to .php, but the PHP endpoints aren't deployed yet. Reverted
all references back to .cfm so the wizard and portal work again.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Combined HTML from multiple sub-pages was too large. Now strips all HTML
tags and keeps only text content for Claude extraction. Also strips
nav/header/footer from sub-pages to remove duplication. Bumped Claude
API timeout from 120s to 300s. Updated wizard message to say 1-3 minutes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
parseHoursString expected a string but Claude AI sometimes returns
structured hours data as an object. Now normalizes to string first.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Strip common suffixes like "Order pickup and delivery" and embedded
street addresses from business names. Clean city field when it contains
state/zip/country (e.g. "Santa Monica, CA 90405, USA" → "Santa Monica").
Fixes applied in both CFML parser and JS frontend as safety net.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Feature cancelled — modifier wording handles the use case instead.
Removes IsInvertedGroup from SELECTs, JSON responses, RemovedDefaults
computation, and KDS/portal display logic. DB column left in place.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The JSON-LD fast path only got items/categories/prices but no modifiers.
Removing it lets Uber Eats pages fall through to Claude AI extraction
which handles modifiers like every other platform.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Warning to disable ad blockers before saving pages for import
- Listed supported platforms with what each extracts (Toast, Grubhub,
DoorDash, Uber Eats, and fallback AI extraction)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Removed IsInvertedGroup toggle and badge from menu builder UI
- Fixed saveFromBuilder.cfm not updating Name for template modifiers
(only selection rules were saved, name changes were silently lost)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Application.cfm requires request.BusinessID from session or header.
The fetch was only sending it in the POST body which the auth layer
doesn't read.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- showToast → toast (correct method name) across all settings methods
- Clear onchange before setting .checked to prevent save during load
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire onchange listener via JS instead of inline attribute,
matching the hiring toggle pattern. The zero-sized hidden
checkbox wasn't firing inline onchange reliably.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Uses the native EyeDropper API (Chrome/Edge) to pick colors from
anywhere on screen. Button only shows in supported browsers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When enabled on a modifier group, KDS and cart only show removed
defaults (e.g., "NO Mustard") instead of listing all selected items.
Useful for groups where all options are checked by default.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Parse JSON-LD structured menu data from saved Uber Eats pages
(categories, items, prices, descriptions, business info)
- Show save-and-upload instructions when user pastes Uber Eats URL
- Always show header image upload step (was skipped for URL imports)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- getOrCreateCart: only require ServicePointID for dine-in (OrderTypeID=1)
- get.cfm + items.cfm: return OrderTypes from Businesses table
- saveOrderTypes.cfm: new endpoint to save business order type config
- KDS: add PICKUP/DELIVERY badges on order cards
- Portal: add Order Types toggle card in settings (Dine-In always on, Takeaway toggle)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Changed from cover/fixed-height to contain/aspect-ratio 3:1 so the
full 1200x400 header image is visible without cropping.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- items.cfm: return BrandColorLight in menu response
- saveWizard.cfm: save BrandColorLight during business creation
- setup-wizard.html: second color picker for light brand color
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Updated the portal settings brand color picker to show both dark
and light colors. Light swatch shown alongside dark swatch.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New BrandColorLight column on Businesses table. Menu builder cards
(categories, subcategories, items) get a very subtle tint from the
light brand color. White when no color is set. Brand color picker
now has both dark and light fields.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Station assignment was a standalone page with no sidebar. Added the
same portal sidebar so users can navigate between pages. Also added
Stations link to menu-builder sidebar.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds button in the outline modal to toggle modifier group display
under each item. Each group shows a + to expand into full options
with prices. Useful for debugging modifier assignments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the conditional out of the nested template literal to avoid
parsing issues with arrow functions inside backtick strings. Also
skip empty mod-groups divs on items without modifiers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Outline button reveals modifier groups under each item with a +
expand button to drill into individual options and prices. Helps
debug imported menus before saving.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
For URL imports (Toast, Grubhub, etc.) there's no header image
to show, so skip straight from business info to categories
instead of showing an empty "Choose Image / Skip" prompt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
API returns Name, Price, ParentItemID, CategoryID, StationID but JS
was referencing ItemName, ItemPrice, ItemParentItemID, etc. causing
all items to be filtered out and not displayed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New endpoints: save.cfm (combined add/update) and delete.cfm
(soft-delete with item unassignment). Registered in Application.cfm.
Portal station-assignment page now uses real API calls for add,
edit, and delete instead of client-side-only prompt(). Fixed key
naming mismatch (StationName/StationColor → Name/Color) so the
page works with real API data. Removed hardcoded demo fallbacks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Constrain main-content to 100vh and builder-wrapper to flex: 1
so the height chain propagates correctly and the properties panel
scrolls within the viewport instead of extending off screen.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Properties panel was extending off screen due to missing min-height: 0
on flex containers. Made Properties header sticky so it floats as you
scroll through long modifier lists.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Subcategories shared expandedCategoryId with parent categories,
so clicking a subcategory collapsed the parent. Added separate
expandedSubCategoryId state so subcategories expand independently.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>