Add "Start from Scratch" option to setup wizard for new businesses
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>
This commit is contained in:
parent
2d1618dc1c
commit
6d157b44f7
1 changed files with 153 additions and 21 deletions
|
|
@ -813,7 +813,7 @@
|
|||
<!-- Wizard Header -->
|
||||
<div class="wizard-header">
|
||||
<h1>Let's Setup Your Menu</h1>
|
||||
<p>Import your menu from a website URL or upload images/PDFs</p>
|
||||
<p>Import from an existing source, or start from scratch</p>
|
||||
</div>
|
||||
|
||||
<!-- Upload Section -->
|
||||
|
|
@ -832,6 +832,12 @@
|
|||
</svg>
|
||||
Upload Files
|
||||
</button>
|
||||
<button class="import-tab" id="tabScratch" onclick="switchImportTab('scratch')" style="flex:1;padding:12px 16px;border:none;background:var(--gray-100);color:var(--gray-700);font-weight:500;cursor:pointer;transition:all 0.2s;">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align:middle;margin-right:6px;">
|
||||
<path d="M12 5v14M5 12h14"/>
|
||||
</svg>
|
||||
Start from Scratch
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- URL Import Panel -->
|
||||
|
|
@ -905,6 +911,23 @@
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Start from Scratch Panel (hidden by default) -->
|
||||
<div id="scratchPanel" style="display:none;">
|
||||
<div style="background:var(--gray-50);border:2px dashed var(--gray-300);border-radius:12px;padding:40px;text-align:center;">
|
||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="var(--gray-400)" stroke-width="1.5" style="margin-bottom:16px;">
|
||||
<path d="M12 5v14M5 12h14"/>
|
||||
</svg>
|
||||
<h3 style="margin:0 0 8px;color:var(--gray-700);">Build Your Menu from Scratch</h3>
|
||||
<p style="margin:0 0 24px;color:var(--gray-500);font-size:14px;">Enter your business information and then use the Visual Menu Builder to add categories, items, and modifiers.</p>
|
||||
<button class="btn btn-primary" onclick="startFromScratch()" style="min-width:200px;">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right:6px;">
|
||||
<path d="M12 5v14M5 12h14"/>
|
||||
</svg>
|
||||
Get Started
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Conversation Section -->
|
||||
|
|
@ -1341,25 +1364,126 @@
|
|||
|
||||
// Switch between URL and file upload tabs
|
||||
function switchImportTab(tab) {
|
||||
const tabUrl = document.getElementById('tabUrl');
|
||||
const tabUpload = document.getElementById('tabUpload');
|
||||
const urlPanel = document.getElementById('urlImportPanel');
|
||||
const filePanel = document.getElementById('fileUploadPanel');
|
||||
const tabs = {
|
||||
url: document.getElementById('tabUrl'),
|
||||
upload: document.getElementById('tabUpload'),
|
||||
scratch: document.getElementById('tabScratch')
|
||||
};
|
||||
const panels = {
|
||||
url: document.getElementById('urlImportPanel'),
|
||||
upload: document.getElementById('fileUploadPanel'),
|
||||
scratch: document.getElementById('scratchPanel')
|
||||
};
|
||||
|
||||
if (tab === 'url') {
|
||||
tabUrl.style.background = 'var(--primary)';
|
||||
tabUrl.style.color = 'white';
|
||||
tabUpload.style.background = 'var(--gray-100)';
|
||||
tabUpload.style.color = 'var(--gray-700)';
|
||||
urlPanel.style.display = 'block';
|
||||
filePanel.style.display = 'none';
|
||||
} else {
|
||||
tabUpload.style.background = 'var(--primary)';
|
||||
tabUpload.style.color = 'white';
|
||||
tabUrl.style.background = 'var(--gray-100)';
|
||||
tabUrl.style.color = 'var(--gray-700)';
|
||||
urlPanel.style.display = 'none';
|
||||
filePanel.style.display = 'block';
|
||||
Object.keys(tabs).forEach(key => {
|
||||
if (key === tab) {
|
||||
tabs[key].style.background = 'var(--primary)';
|
||||
tabs[key].style.color = 'white';
|
||||
panels[key].style.display = 'block';
|
||||
} else {
|
||||
tabs[key].style.background = 'var(--gray-100)';
|
||||
tabs[key].style.color = 'var(--gray-700)';
|
||||
panels[key].style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Start from scratch — skip import, go straight to business info
|
||||
function startFromScratch() {
|
||||
config.scratchMode = true;
|
||||
config.extractedData = {
|
||||
business: {},
|
||||
categories: [],
|
||||
modifiers: [],
|
||||
items: []
|
||||
};
|
||||
|
||||
// Hide upload section, show conversation
|
||||
document.getElementById('uploadSection').style.display = 'none';
|
||||
|
||||
showBusinessInfoStep();
|
||||
}
|
||||
|
||||
// Save business only (scratch mode) then redirect to Menu Builder
|
||||
async function saveScratchBusiness() {
|
||||
// Add a default menu name and community meal type
|
||||
config.extractedData.menuName = 'Main Menu';
|
||||
config.extractedData.communityMealType = 1;
|
||||
|
||||
addMessage('ai', `
|
||||
<p>Saving your business information...</p>
|
||||
<div class="loading-spinner" style="width:24px;height:24px;border-width:3px;margin:16px auto;"></div>
|
||||
`);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${config.apiBaseUrl}/setup/saveWizard.php`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
businessId: config.businessId || 0,
|
||||
menuId: 0,
|
||||
userId: config.userId,
|
||||
data: config.extractedData,
|
||||
tempFolder: null
|
||||
})
|
||||
});
|
||||
|
||||
const responseText = await response.text();
|
||||
let result;
|
||||
try {
|
||||
result = JSON.parse(responseText);
|
||||
} catch (e) {
|
||||
throw new Error('Invalid response from server');
|
||||
}
|
||||
|
||||
if (!result.OK) {
|
||||
const errorMsg = result.errors && result.errors.length > 0
|
||||
? result.errors.join('; ')
|
||||
: (result.MESSAGE || 'Save failed');
|
||||
throw new Error(errorMsg);
|
||||
}
|
||||
|
||||
const summary = result.summary || result.SUMMARY || {};
|
||||
const finalBusinessId = summary.businessId || summary.BUSINESSID || summary.businessid || config.businessId;
|
||||
|
||||
localStorage.setItem('payfrit_portal_business', finalBusinessId);
|
||||
|
||||
// Upload header image if one was selected
|
||||
if (config.headerImageFile && finalBusinessId) {
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('BusinessID', finalBusinessId);
|
||||
formData.append('header', config.headerImageFile);
|
||||
|
||||
const headerResp = await fetch(`${config.apiBaseUrl}/menu/uploadHeader.php`, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
const headerResult = await headerResp.json();
|
||||
if (!headerResult.OK) {
|
||||
console.error('Header upload failed:', headerResult.MESSAGE);
|
||||
}
|
||||
} catch (headerErr) {
|
||||
console.error('Header upload error:', headerErr);
|
||||
}
|
||||
}
|
||||
|
||||
showToast('Business created! Redirecting to Menu Builder...', 'success');
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = '/portal/menu-builder.html';
|
||||
}, 1500);
|
||||
|
||||
} catch (err) {
|
||||
console.error('Save error:', err);
|
||||
showToast('Error: ' + err.message, 'error');
|
||||
// Remove the loading message and show retry
|
||||
addMessage('ai', `
|
||||
<p style="color:var(--error);">Something went wrong: ${err.message}</p>
|
||||
<div class="action-buttons">
|
||||
<button class="btn btn-primary" onclick="saveScratchBusiness()">Try Again</button>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2657,12 +2781,20 @@
|
|||
}
|
||||
|
||||
function confirmHeaderImage() {
|
||||
showCategoriesStep();
|
||||
if (config.scratchMode) {
|
||||
saveScratchBusiness();
|
||||
} else {
|
||||
showCategoriesStep();
|
||||
}
|
||||
}
|
||||
|
||||
function skipHeaderImage() {
|
||||
config.headerImageFile = null;
|
||||
showCategoriesStep();
|
||||
if (config.scratchMode) {
|
||||
saveScratchBusiness();
|
||||
} else {
|
||||
showCategoriesStep();
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Categories
|
||||
|
|
|
|||
Reference in a new issue