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>
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>
- 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>
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>
- Create tt_StaffRoles lookup table (Staff, Manager, Admin)
- Add RoleID column to Employees table (default: Staff)
- Wire portal role dropdown to addTeamMember API
- Return RoleName in team list and RoleID to Android
- Skip worker payout ledger and cash_debit for Manager/Admin roles
on cash task completion (they collect on behalf of the restaurant)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New api/tabs/ directory with 13 endpoints: open, close, cancel, get, getActive,
addOrder, increaseAuth, addMember, removeMember, getPresence, approveOrder,
rejectOrder, pendingOrders
- New api/presence/heartbeat.cfm for beacon-based user presence tracking
- New cron/expireTabs.cfm for idle tab expiry and presence cleanup
- Modified submit.cfm for tab-aware order submission (skip payment, update running total)
- Modified getOrCreateCart.cfm to auto-detect active tab and set TabID on new carts
- Modified webhook.cfm to handle tab capture events (metadata type=tab_close)
- Modified businesses/get.cfm and updateTabs.cfm with new tab config columns
- Updated portal tab settings UI with auth amounts, max members, approval toggle
- Added tab and presence endpoints to Application.cfm public allowlist
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
b.Minor is 0 for the first beacon which is falsy in JS.
Changed to null check so Minor: 0 displays correctly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The refresh button in the top bar had no click handler attached.
Now it reloads the current page data when clicked.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The API returns ServicePointID but portal.js was using sp.ID which was undefined.
Changed all sp.ID references to sp.ServicePointID.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix menu builder dropdown showing empty names (return MenuName instead of Name)
- Add default menu selection (setDefault action, DefaultMenuID in getForBuilder)
- Fix createPaymentIntent column names for dev schema (ID, StripeAccountID, etc.)
- Fix menu-builder favicon and remove redundant business label
- Comment out Tabs/Running Checks feature for launch (HTML + JS)
- Comment out Service Point Marketing/Grants feature for launch (HTML + JS)
- Add testMarkPaid.cfm for testing orders without Stripe webhooks
- Task API updates for worker payout ledger integration
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Menu builder UI improvements
- Portal CSS and JS updates
- Station assignment updates
- Add business tabs update endpoint
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Converts 200+ endpoint files to use queryTimed() wrapper which tracks
DB query count and execution time. Restores perf dashboard files that
were accidentally moved to _scripts/. Includes portal UI updates.
Grant-based system allowing businesses to share service points with
other businesses. Includes grant CRUD API, time/eligibility/economics
policies, enforcement at cart creation and order submit, Stripe payment
routing for owner fees, and portal UI for managing grants.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Save FirstName to localStorage on login (both OTP and password paths).
Portal reads it back and displays the first letter in the user avatar.
Falls back to 'U' if no name is stored. Cleared on logout.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Brand color: add # prefix when loading from DB (stored without #,
CSS needs it for backgroundColor)
- Header upload: delete destination file before rename to prevent
collision when re-uploading same extension
- Header preview: prepend BASE_PATH to image URL for local dev
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The user icon in the top-right header now opens a dropdown
with Settings and Logout links, making both accessible on mobile
where the sidebar is hidden.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Lucee serializeJSON casing varies by server config (preserveCaseForStructKey).
Normalize all biz object keys to uppercase on the JS side so lookups
work regardless of server config.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Hide wrapper div instead of img (avoids mobile empty-src issues)
- Use img onload handler to show wrapper after image loads
- Use backgroundColor instead of background shorthand for swatch
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Header preview: max-width 1200px, white background, no border-radius on img
- Brand color swatch: change span to div with min-width/min-height and
flex-shrink:0 to prevent collapse on mobile flex layouts
- Remove headerPreviewWrapper brand color tinting (wrapper stays white)
- Fix swatch border from white-alpha to black-alpha for visibility on white cards
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CSS background-image with padding-bottom trick for aspect ratio was not
rendering on mobile. Using an actual <img> element with width:100% is
universally reliable across all browsers and devices.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace fixed 120px height with aspect-ratio padding (33.3%) so image
scales properly on narrow mobile screens
- Use background-size: cover instead of contain for better fill
- Add wrapper div that shows brand color behind the header image
- Update saveBrandColor to also update the header wrapper background
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
settingName -> settingBusinessName, settingLine1 -> settingAddressLine1
to match actual HTML element IDs. The mismatch caused null reference
errors that broke the entire settings page load.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- saveBrandColor.cfm: BrandColor -> BusinessBrandColor (normalized column name)
- portal.js: Accept hex colors with or without # prefix in validation
- portal.js: Auto-prepend # when typing bare hex in color input
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- myBusinesses.cfm: Use BusinessID/BusinessName/BusinessUserID instead of
ID/Name/UserID (post-normalization column names)
- login.html: Fix biz.BusinessName -> biz.Name to match API response key
- login.html: Add friendly error messages for bad_credentials
- portal.js: Fix b.ID -> b.BusinessID in access check
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update all SQL queries, query result references, and ColdFusion code to match
the renamed database schema. Tables use plural CamelCase, PKs are all `ID`,
column prefixes stripped (e.g. BusinessName→Name, UserFirstName→FirstName).
Key changes:
- Strip table-name prefixes from all column references (Businesses, Users,
Addresses, Hours, Menus, Categories, Items, Stations, Orders,
OrderLineItems, Tasks, TaskCategories, TaskRatings, QuickTaskTemplates,
ScheduledTaskDefinitions, ChatMessages, Beacons, ServicePoints, Employees,
VisitorTrackings, ApiPerfLogs, tt_States, tt_Days, tt_AddressTypes,
tt_OrderTypes, tt_TaskTypes)
- Rename PK references from {TableName}ID to ID in all queries
- Rewrite 7 admin beacon files to use ServicePoints.BeaconID instead of
dropped lt_Beacon_Businesses_ServicePoints link table
- Rewrite beacon assignment files (list, save, delete) for new schema
- Fix FK references incorrectly changed to ID (OrderLineItems.OrderID,
Categories.MenuID, Tasks.CategoryID, ServicePoints.BeaconID)
- Update Addresses: AddressLat→Latitude, AddressLng→Longitude
- Update Users: UserPassword→Password, UserIsEmailVerified→IsEmailVerified,
UserIsActive→IsActive, UserBalance→Balance, etc.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move menu manager button to toolbar next to Save Menu for visibility
- Implement server-side photo upload for menu items
- Strip base64 data URLs from save payload to reduce size
- Add scheduled tasks, quick tasks, ratings, and task categories APIs
- Add vertical support and brand color features
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Skip business selection for users with only one business
- Add Switch Business and Add New Business links in portal sidebar
- Handle returning users switching businesses (token + no business)
- HUD reads businessId from localStorage instead of ?b= param
- Portal opens HUD/quick-tasks without URL params
- Business select auto-proceeds on selection (no button needed)
- Quick tasks reads from payfrit_portal_business localStorage
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Lucee's serializeJSON converts all struct keys to UPPERCASE.
Updated loadBusinessInfo to check for uppercase key variants.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added portal sidebar navigation to menu builder
- Updated color scheme to use portal CSS variables (gray-* instead of custom vars)
- Fixed header image preview to use HeaderImageURL from API response
- Fixed upload handler to use correct extension from response
- Added sidebar toggle and logout functionality
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- HUD now displays "Payfrit Tasks - <BusinessName>" by fetching from getBusiness API
- Fixed portal Task HUD button to link to /hud/index.html instead of /hud/
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add uploadHeader.cfm API for 1200px header images
- Add saveBrandColor.cfm API for hex color storage
- Add Branding section to menu builder sidebar
- Fix header upload path and permissions
- Various beacon and service point API improvements
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Display Pending/Invited/Active/Suspended from EmployeeStatusID
- Add CSS for pending and suspended status badges
- Update getStatusClass to handle employee status codes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace Role column with Phone column in team table
- Add formatPhone() helper to format phone numbers nicely
- Add cleanupDuplicateEmployees.cfm admin script to remove duplicates
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add setHiring.cfm API endpoint to update BusinessIsHiring
- Add endpoint to Application.cfm allowlist
- Update portal.js to load and sync hiring toggle state
- Wire toggle to call API and show feedback toasts
- Bump portal.js version for cache busting
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>