Only Call Staff, Chat With Staff, and Pay With Cash should appear
on the customer service bell. New column distinguishes service bell
items from internal task types.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Got reverted during earlier merge conflict resolution. Without cd,
node can't find modules. Without stderr redirect, log lines corrupt
the JSON output causing json_decode to fail.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- analyzeMenuUrl.php: Extract og:image and JSON-LD image during discovery, return as headerImageUrl
- downloadImages.php: Add User-Agent header, detect image format from content-type/magic bytes, update HeaderImageExtension in DB
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
order.online embeds displayPrice alongside images — now extracted and
returned so items missing prices from image-based menus get filled in.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
downloadItemImage() saved files to disk but never updated the DB column,
so items appeared to have no images despite files existing on disk.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Moved directory on both dev and biz servers
- Updated nginx configs on both servers
- Added appRoot() helper, uploadsRoot() uses it
- No more hardcoded /opt/payfrit-api paths in codebase
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Moved uploads from Lucee webroot to /opt/payfrit-api/uploads/
- Updated nginx on both dev and biz to alias /uploads/ to new path
- Replaced luceeWebroot() with uploadsRoot() helper
- Temp files now use /opt/payfrit-api/temp/
- No more /opt/lucee or /var/www/biz.payfrit.com references
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Detect contact/about/location/hours links on main page
- Fetch contact page and extract phone, address, hours
- Phone: regex for US phone formats + tel: links
- Address: US street address pattern (number + street type)
- Hours: day + time range patterns from plain text
- Overrides bad JSON-LD data with actual contact page info
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Prefer title tag for name over JSON-LD (sites often put address in LD name)
- Parse full address string into components (addressLine1, city, state, zip)
- Handle newlines in addresses (Squarespace puts newlines in JSON-LD)
- Convert 24h hours to 12h format
- Strip country suffix from addresses
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Claude prompt now asks for menuSchedule (days/times this menu is served)
- Separates menu schedule from overall business hours
- Returns menuSchedule in response for frontend to use
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Parse JSON-LD structured data (Restaurant, FoodEstablishment, etc.)
- Extract phone from tel: links, address from og: meta tags
- Return businessInfo in discovery response so sub-pages don't need it
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Discovery mode: quick Playwright crawl returns detected menu sub-pages
- Extract_page mode: processes single menu page through Claude individually
- More aggressive HTML stripping: removes SVG, nav, footer, form, attributes
- Increased truncation limit from 100KB to 200KB for generic fallback path
- Enables interactive wizard flow: discover → confirm → extract each page
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude returns address as one string with country suffix.
Now strips "United States/USA", extracts ZIP, state, splits
address line and city server-side before sending to wizard.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Updated Claude prompt to detect separate menus vs categories
- Added platformImageMap and subPagesVisited parsing from Playwright
- Bumped Playwright wait from 5s to 10s for sub-page crawling
- saveWizard.php creates separate Menus rows and assigns categories/items
to the correct menu based on each item's "menu" field
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Complete port of all 163 API endpoints from Lucee/CFML to PHP 8.3.
Shared helpers in api/helpers.php (DB, auth, request/response, security).
PDO prepared statements throughout. Same JSON response shapes as CFML.