Add quote bridge and quote handoff flow
This commit is contained in:
@@ -10,6 +10,9 @@ let productData = [];
|
||||
let accessoryData = [];
|
||||
let bitwiseData = {};
|
||||
|
||||
// In-page order list for the current browser session
|
||||
let orderItems = [];
|
||||
|
||||
// Track accumulated bit value for URL state
|
||||
let accumulatedBitValue = 0;
|
||||
|
||||
@@ -625,6 +628,8 @@ function startOver() {
|
||||
}
|
||||
// Clear bit value
|
||||
accumulatedBitValue = 0;
|
||||
// Clear order list
|
||||
orderItems = [];
|
||||
// Clear URL
|
||||
window.history.replaceState({}, '', window.location.pathname);
|
||||
loadContent('start');
|
||||
@@ -916,6 +921,11 @@ function showProductDetail(product) {
|
||||
<div class="config-field" style="margin-top: 20px;">
|
||||
<button class="back-button" onclick="addToOrder('${prodCode}')" style="width: 100%; padding: 12px; font-size: 16px;">Add to Order</button>
|
||||
</div>
|
||||
<div class="config-field" style="margin-top: 12px;">
|
||||
<div style="font-weight: 600; margin-bottom: 8px;">Current Order</div>
|
||||
<div id="order-items-list" style="background: #f8f9fb; border: 1px solid #e3e5ea; border-radius: 8px; padding: 10px;"></div>
|
||||
<button class="back-button" onclick="submitQuoteOrder()" style="width: 100%; margin-top: 10px; padding: 12px; font-size: 16px;">Quote</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="result-details">
|
||||
@@ -964,6 +974,7 @@ function showProductDetail(product) {
|
||||
|
||||
contentDiv.innerHTML = html;
|
||||
updateBreadcrumb();
|
||||
renderOrderList();
|
||||
|
||||
// Initialize images based on type
|
||||
if (useCanvasAPI) {
|
||||
@@ -1328,6 +1339,143 @@ function handleSizeChange(productCode) {
|
||||
}
|
||||
}
|
||||
|
||||
function getSelectedSizeLabel() {
|
||||
const sizeSelect = document.getElementById('config-size');
|
||||
if (!sizeSelect) return '';
|
||||
|
||||
if (sizeSelect.value === 'custom') {
|
||||
const customWidth = document.getElementById('custom-width')?.value || '';
|
||||
const customHeight = document.getElementById('custom-height')?.value || '';
|
||||
if (customWidth && customHeight) {
|
||||
return `Custom ${customWidth}" x ${customHeight}"`;
|
||||
}
|
||||
return 'Custom Size';
|
||||
}
|
||||
|
||||
const selectedOption = sizeSelect.options[sizeSelect.selectedIndex];
|
||||
return selectedOption ? selectedOption.textContent.trim() : '';
|
||||
}
|
||||
|
||||
function buildOrderItemKey(item) {
|
||||
return [
|
||||
item.productCode,
|
||||
item.material,
|
||||
item.color,
|
||||
item.size,
|
||||
item.hingeLocation
|
||||
].join('|');
|
||||
}
|
||||
|
||||
function addToOrder(productCode) {
|
||||
const product = productData.find(p => p.productCode === productCode || p.id === productCode);
|
||||
if (!product) {
|
||||
showNotification('Unable to add item: product not found.');
|
||||
return;
|
||||
}
|
||||
|
||||
const material = document.getElementById('config-material')?.value || 'N/A';
|
||||
const color = document.getElementById('config-color')?.value || 'N/A';
|
||||
const hingeLocation = document.querySelector('[name="hinge-location"]:checked')?.value || 'left';
|
||||
const size = getSelectedSizeLabel() || 'N/A';
|
||||
|
||||
const item = {
|
||||
productCode,
|
||||
description: product.description || product.DESCRIPTION || product.title || productCode,
|
||||
material,
|
||||
color,
|
||||
size,
|
||||
hingeLocation,
|
||||
quantity: 1
|
||||
};
|
||||
|
||||
const itemKey = buildOrderItemKey(item);
|
||||
const existingIndex = orderItems.findIndex(existing => buildOrderItemKey(existing) === itemKey);
|
||||
|
||||
if (existingIndex >= 0) {
|
||||
orderItems[existingIndex].quantity += 1;
|
||||
} else {
|
||||
orderItems.push(item);
|
||||
}
|
||||
|
||||
renderOrderList();
|
||||
showNotification('Added to order.');
|
||||
}
|
||||
|
||||
async function submitQuoteOrder() {
|
||||
if (!Array.isArray(orderItems) || orderItems.length === 0) {
|
||||
showNotification('Add at least one item before submitting a quote.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/quiz/api/submit-quote', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
items: orderItems,
|
||||
bitValue: accumulatedBitValue,
|
||||
answers: userAnswers,
|
||||
route: window.location.pathname,
|
||||
url: window.location.href
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (!response.ok || data.status !== 'success') {
|
||||
showNotification(data.message || 'Quote submission failed.');
|
||||
return;
|
||||
}
|
||||
|
||||
const submissionId = data.submissionId || 'unknown';
|
||||
orderItems = [];
|
||||
renderOrderList();
|
||||
showNotification(`Quote submitted (${submissionId}).`);
|
||||
} catch (error) {
|
||||
showNotification('Quote submission failed.');
|
||||
}
|
||||
}
|
||||
|
||||
function removeOrderItem(index) {
|
||||
if (index < 0 || index >= orderItems.length) return;
|
||||
orderItems.splice(index, 1);
|
||||
renderOrderList();
|
||||
}
|
||||
|
||||
function renderOrderList() {
|
||||
const container = document.getElementById('order-items-list');
|
||||
if (!container) return;
|
||||
|
||||
if (orderItems.length === 0) {
|
||||
container.innerHTML = '<div style="color: #666; font-size: 0.95em;">No items added yet.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
const totalQuantity = orderItems.reduce((total, item) => total + item.quantity, 0);
|
||||
|
||||
container.innerHTML = `
|
||||
<div style="display: grid; gap: 8px;">
|
||||
${orderItems.map((item, index) => `
|
||||
<div style="background: #fff; border: 1px solid #dfe3ea; border-radius: 6px; padding: 8px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start; gap: 8px;">
|
||||
<div>
|
||||
<div style="font-weight: 600;">${item.productCode} (${item.quantity})</div>
|
||||
<div style="font-size: 0.9em; color: #444;">${item.description}</div>
|
||||
<div style="font-size: 0.85em; color: #666; margin-top: 4px;">
|
||||
Material: ${item.material} | Color: ${item.color}<br>
|
||||
Size: ${item.size} | Hinge: ${item.hingeLocation}
|
||||
</div>
|
||||
</div>
|
||||
<button class="back-button" onclick="removeOrderItem(${index})" style="padding: 6px 10px; font-size: 0.85em;">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('')}
|
||||
<div style="font-size: 0.9em; color: #333; font-weight: 600; padding-top: 4px;">
|
||||
Total Items: ${totalQuantity}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// Go back to results from product detail
|
||||
function goBackToResults() {
|
||||
// Find results in history or load it directly
|
||||
|
||||
Reference in New Issue
Block a user