Add menu wizard flow: redirect to setup wizard after creating a new menu
When a new menu is created in Manage Menus, the user is now redirected to the setup wizard with businessId and menuId params. The wizard skips business info/header steps and goes straight to photo upload + category extraction. Backend uses the provided menuId instead of creating a new menu. Also removes temp debug from menus.cfm. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
65cf855ade
commit
02a19f52be
4 changed files with 126 additions and 98 deletions
|
|
@ -242,7 +242,7 @@ try {
|
||||||
response["ERROR"] = "server_error";
|
response["ERROR"] = "server_error";
|
||||||
response["MESSAGE"] = e.message;
|
response["MESSAGE"] = e.message;
|
||||||
response["DETAIL"] = e.detail ?: "";
|
response["DETAIL"] = e.detail ?: "";
|
||||||
response["TAGCONTEXT"] = e.tagContext[1].template & ":" & e.tagContext[1].line;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writeOutput(serializeJSON(response));
|
writeOutput(serializeJSON(response));
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ try {
|
||||||
|
|
||||||
businessId = structKeyExists(data, "businessId") ? val(data.businessId) : 0;
|
businessId = structKeyExists(data, "businessId") ? val(data.businessId) : 0;
|
||||||
userId = structKeyExists(data, "userId") ? val(data.userId) : 0;
|
userId = structKeyExists(data, "userId") ? val(data.userId) : 0;
|
||||||
|
providedMenuId = structKeyExists(data, "menuId") ? val(data.menuId) : 0;
|
||||||
wizardData = structKeyExists(data, "data") ? data.data : {};
|
wizardData = structKeyExists(data, "data") ? data.data : {};
|
||||||
biz = structKeyExists(wizardData, "business") ? wizardData.business : {};
|
biz = structKeyExists(wizardData, "business") ? wizardData.business : {};
|
||||||
|
|
||||||
|
|
@ -290,6 +291,11 @@ try {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use provided menuId (add-menu mode) or create/find menu
|
||||||
|
if (providedMenuId > 0) {
|
||||||
|
menuID = providedMenuId;
|
||||||
|
response.steps.append("Using provided menu ID: " & menuID);
|
||||||
|
} else {
|
||||||
// Create a Menu record for this business (or get existing menu with same name)
|
// Create a Menu record for this business (or get existing menu with same name)
|
||||||
menuName = structKeyExists(wizardData, "menuName") && isSimpleValue(wizardData.menuName) && len(trim(wizardData.menuName))
|
menuName = structKeyExists(wizardData, "menuName") && isSimpleValue(wizardData.menuName) && len(trim(wizardData.menuName))
|
||||||
? trim(wizardData.menuName)
|
? trim(wizardData.menuName)
|
||||||
|
|
@ -366,6 +372,7 @@ try {
|
||||||
timeInfo = len(menuStartTime) && len(menuEndTime) ? " (" & menuStartTime & " - " & menuEndTime & ")" : " (all day)";
|
timeInfo = len(menuStartTime) && len(menuEndTime) ? " (" & menuStartTime & " - " & menuEndTime & ")" : " (all day)";
|
||||||
response.steps.append("Created menu: " & menuName & timeInfo & " (ID: " & menuID & ")");
|
response.steps.append("Created menu: " & menuName & timeInfo & " (ID: " & menuID & ")");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Build category map
|
// Build category map
|
||||||
categories = structKeyExists(wizardData, "categories") ? wizardData.categories : [];
|
categories = structKeyExists(wizardData, "categories") ? wizardData.categories : [];
|
||||||
|
|
|
||||||
|
|
@ -3503,6 +3503,11 @@
|
||||||
});
|
});
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.OK) {
|
if (data.OK) {
|
||||||
|
if (data.ACTION === 'created') {
|
||||||
|
// New menu — redirect to wizard to populate it
|
||||||
|
window.location.href = `${BASE_PATH}/portal/setup-wizard.html?businessId=${this.config.businessId}&menuId=${data.MENUID}`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.toast(`Menu ${data.ACTION}!`, 'success');
|
this.toast(`Menu ${data.ACTION}!`, 'success');
|
||||||
this.closeModal();
|
this.closeModal();
|
||||||
await this.loadMenu();
|
await this.loadMenu();
|
||||||
|
|
|
||||||
|
|
@ -1048,8 +1048,13 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
function initializeConfig() {
|
function initializeConfig() {
|
||||||
// Wizard is for creating NEW businesses - businessId starts as null
|
// Parse URL parameters for add-menu mode
|
||||||
config.businessId = null;
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const paramBusinessId = params.get('businessId');
|
||||||
|
const paramMenuId = params.get('menuId');
|
||||||
|
|
||||||
|
config.businessId = paramBusinessId ? parseInt(paramBusinessId) : null;
|
||||||
|
config.menuId = paramMenuId ? parseInt(paramMenuId) : null;
|
||||||
|
|
||||||
// Determine API base URL
|
// Determine API base URL
|
||||||
const basePath = window.location.pathname.includes('/biz.payfrit.com/')
|
const basePath = window.location.pathname.includes('/biz.payfrit.com/')
|
||||||
|
|
@ -1065,8 +1070,7 @@
|
||||||
}
|
}
|
||||||
config.userId = userId;
|
config.userId = userId;
|
||||||
|
|
||||||
// BusinessId is optional - will be created if not provided
|
console.log('Wizard initialized. BusinessId:', config.businessId, 'MenuId:', config.menuId, 'UserId:', config.userId);
|
||||||
console.log('Wizard initialized. BusinessId:', config.businessId, 'UserId:', config.userId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupUploadZone() {
|
function setupUploadZone() {
|
||||||
|
|
@ -1250,8 +1254,12 @@
|
||||||
// Remove loading message and start conversation flow
|
// Remove loading message and start conversation flow
|
||||||
document.getElementById('conversation').innerHTML = '';
|
document.getElementById('conversation').innerHTML = '';
|
||||||
|
|
||||||
// Start with business info
|
// In add-menu mode, skip business info and header — go straight to categories
|
||||||
|
if (config.businessId && config.menuId) {
|
||||||
|
showCategoriesStep();
|
||||||
|
} else {
|
||||||
showBusinessInfoStep();
|
showBusinessInfoStep();
|
||||||
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Analysis error:', error);
|
console.error('Analysis error:', error);
|
||||||
|
|
@ -2157,6 +2165,11 @@
|
||||||
document.getElementById('summaryModifiers').textContent = modifiers.length;
|
document.getElementById('summaryModifiers').textContent = modifiers.length;
|
||||||
document.getElementById('summaryItems').textContent = items.length;
|
document.getElementById('summaryItems').textContent = items.length;
|
||||||
|
|
||||||
|
// In add-menu mode, hide menu name/hours/community meal (already set during menu creation)
|
||||||
|
if (config.menuId) {
|
||||||
|
document.getElementById('menuNameInput').parentElement.style.display = 'none';
|
||||||
|
document.getElementById('menuStartTime').closest('.summary-stat').style.display = 'none';
|
||||||
|
} else {
|
||||||
// Set default menu hours based on business hours (earliest open, latest close)
|
// Set default menu hours based on business hours (earliest open, latest close)
|
||||||
const hoursSchedule = business.hoursSchedule || [];
|
const hoursSchedule = business.hoursSchedule || [];
|
||||||
if (hoursSchedule.length > 0) {
|
if (hoursSchedule.length > 0) {
|
||||||
|
|
@ -2169,10 +2182,11 @@
|
||||||
document.getElementById('menuStartTime').value = earliestOpen;
|
document.getElementById('menuStartTime').value = earliestOpen;
|
||||||
document.getElementById('menuEndTime').value = latestClose;
|
document.getElementById('menuEndTime').value = latestClose;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addMessage('ai', `
|
addMessage('ai', `
|
||||||
<p>Your menu is ready to save!</p>
|
<p>Your menu is ready to save!</p>
|
||||||
<p><strong>${business.name || 'Your Restaurant'}</strong></p>
|
${config.menuId ? '' : `<p><strong>${business.name || 'Your Restaurant'}</strong></p>`}
|
||||||
<ul style="margin: 12px 0; padding-left: 20px; color: var(--gray-600);">
|
<ul style="margin: 12px 0; padding-left: 20px; color: var(--gray-600);">
|
||||||
<li>${categories.length} categories</li>
|
<li>${categories.length} categories</li>
|
||||||
<li>${modifiers.length} modifier templates</li>
|
<li>${modifiers.length} modifier templates</li>
|
||||||
|
|
@ -2189,10 +2203,11 @@
|
||||||
console.log('=== SAVE MENU CALLED ===');
|
console.log('=== SAVE MENU CALLED ===');
|
||||||
console.log('Data to save:', config.extractedData);
|
console.log('Data to save:', config.extractedData);
|
||||||
|
|
||||||
// Get menu name and time range from inputs
|
// In add-menu mode, menu name/time were already set — skip these fields
|
||||||
const menuName = document.getElementById('menuNameInput').value.trim() || 'Main Menu';
|
const menuNameEl = document.getElementById('menuNameInput');
|
||||||
const menuStartTime = document.getElementById('menuStartTime').value || '';
|
const menuName = menuNameEl ? menuNameEl.value.trim() || 'Main Menu' : 'Main Menu';
|
||||||
const menuEndTime = document.getElementById('menuEndTime').value || '';
|
const menuStartTime = document.getElementById('menuStartTime')?.value || '';
|
||||||
|
const menuEndTime = document.getElementById('menuEndTime')?.value || '';
|
||||||
|
|
||||||
// Validate menu hours fall within business operating hours
|
// Validate menu hours fall within business operating hours
|
||||||
if (menuStartTime && menuEndTime) {
|
if (menuStartTime && menuEndTime) {
|
||||||
|
|
@ -2233,6 +2248,7 @@
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
businessId: config.businessId || 0,
|
businessId: config.businessId || 0,
|
||||||
|
menuId: config.menuId || 0,
|
||||||
userId: config.userId,
|
userId: config.userId,
|
||||||
data: config.extractedData
|
data: config.extractedData
|
||||||
})
|
})
|
||||||
|
|
@ -2302,9 +2318,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect to visual menu builder after a moment
|
// Redirect back after a moment
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.href = 'index.html#menu';
|
window.location.href = config.menuId ? 'menu-builder.html' : 'index.html#menu';
|
||||||
}, 1500);
|
}, 1500);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
Reference in a new issue