Add modal-based photo upload for better mobile support
- Show a modal with file input and preview - Uses alert() instead of toast for error messages (more visible on mobile) - Preview shows selected image before upload - Submit button with loading state - Keeps old uploadPhoto function for compatibility Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
cab561a20e
commit
946c2ebdf0
1 changed files with 100 additions and 2 deletions
|
|
@ -1753,7 +1753,7 @@
|
|||
`<span>No photo yet</span>`}
|
||||
</div>
|
||||
<div class="photo-actions">
|
||||
<button class="btn btn-secondary" onclick="MenuBuilder.uploadPhoto('${item.id}')">
|
||||
<button class="btn btn-secondary" onclick="MenuBuilder.showUploadModal('${item.id}', '${item.dbId || ''}')">
|
||||
Upload
|
||||
</button>
|
||||
<button class="btn btn-secondary" onclick="MenuBuilder.createPhotoTask('${item.id}')">
|
||||
|
|
@ -2804,10 +2804,108 @@
|
|||
}
|
||||
},
|
||||
|
||||
// Show upload modal - works better on mobile
|
||||
showUploadModal(itemId, dbId) {
|
||||
if (!dbId) {
|
||||
alert('Please save the menu first before uploading photos.');
|
||||
return;
|
||||
}
|
||||
|
||||
document.getElementById('modalTitle').textContent = 'Upload Item Photo';
|
||||
document.getElementById('modalBody').innerHTML = `
|
||||
<form id="photoUploadForm" enctype="multipart/form-data" style="text-align: center;">
|
||||
<input type="hidden" name="ItemID" value="${dbId}">
|
||||
<input type="hidden" id="uploadItemId" value="${itemId}">
|
||||
<p style="color: var(--gray-600); margin-bottom: 16px;">
|
||||
Select or take a photo for this item
|
||||
</p>
|
||||
<div style="margin-bottom: 16px;">
|
||||
<input type="file" name="photo" id="modalPhotoInput" accept="image/*"
|
||||
style="font-size: 16px; padding: 12px; border: 2px dashed var(--gray-300);
|
||||
border-radius: 8px; width: 100%; cursor: pointer;">
|
||||
</div>
|
||||
<div id="uploadPreview" style="margin-bottom: 16px; display: none;">
|
||||
<img id="previewImg" style="max-width: 100%; max-height: 200px; border-radius: 8px;">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" id="uploadSubmitBtn" disabled
|
||||
style="width: 100%; padding: 12px;">
|
||||
Upload Photo
|
||||
</button>
|
||||
</form>
|
||||
`;
|
||||
this.showModal();
|
||||
|
||||
const fileInput = document.getElementById('modalPhotoInput');
|
||||
const submitBtn = document.getElementById('uploadSubmitBtn');
|
||||
const preview = document.getElementById('uploadPreview');
|
||||
const previewImg = document.getElementById('previewImg');
|
||||
const form = document.getElementById('photoUploadForm');
|
||||
|
||||
fileInput.addEventListener('change', (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (file) {
|
||||
submitBtn.disabled = false;
|
||||
// Show preview
|
||||
const reader = new FileReader();
|
||||
reader.onload = (ev) => {
|
||||
previewImg.src = ev.target.result;
|
||||
preview.style.display = 'block';
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
});
|
||||
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
const file = fileInput.files[0];
|
||||
if (!file) return;
|
||||
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = 'Uploading...';
|
||||
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('photo', file);
|
||||
formData.append('ItemID', dbId);
|
||||
|
||||
const response = await fetch(`${this.config.apiBaseUrl}/menu/uploadItemPhoto.cfm`, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (data.OK) {
|
||||
// Update the item
|
||||
const itemIdVal = document.getElementById('uploadItemId').value;
|
||||
for (const cat of this.menu.categories) {
|
||||
const item = cat.items.find(i => i.id === itemIdVal);
|
||||
if (item) {
|
||||
item.imageUrl = data.IMAGEURL + '?t=' + Date.now();
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.closeModal();
|
||||
this.render();
|
||||
this.toast('Photo uploaded!', 'success');
|
||||
} else {
|
||||
alert('Upload failed: ' + (data.MESSAGE || data.ERROR || 'Unknown error'));
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = 'Upload Photo';
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Upload error:', err);
|
||||
alert('Upload failed: ' + err.message);
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = 'Upload Photo';
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Pending photo upload info (for mobile camera flow)
|
||||
_pendingPhotoUpload: null,
|
||||
|
||||
// Upload photo - mobile-friendly version
|
||||
// Upload photo - legacy version (kept for compatibility)
|
||||
uploadPhoto(itemId) {
|
||||
// Find the item and check it has a database ID
|
||||
let targetItem = null;
|
||||
|
|
|
|||
Reference in a new issue