Fix sandblast-only toggle overflow and $0 AI quote pricing
Overflow: replaced Bootstrap form-check with an explicit flex row so the two-line label (title + subtitle) never bleeds outside the card boundary. $0 pricing: when sandblast-only was toggled on an AI item, manualUnitPrice was cleared and isAiItem set to false. The pricing engine then returned $0 because no prep services with minutes were configured. Fix: preserve the AI price when toggling sandblast-only, and keep isAiItem=true so the server routes through the AI-price path (manualUnitPrice) rather than trying to recalculate from prep labor. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1461,10 +1461,12 @@ function aiShowError(message) {
|
|||||||
function renderStep3Html() {
|
function renderStep3Html() {
|
||||||
const isSandblastOnly = !!wz.data.sandblastOnly;
|
const isSandblastOnly = !!wz.data.sandblastOnly;
|
||||||
return `
|
return `
|
||||||
<div class="form-check form-switch border rounded py-2 px-3 mb-3 bg-light">
|
<div class="d-flex align-items-center border rounded py-2 px-3 mb-3 bg-light gap-2">
|
||||||
<input class="form-check-input" type="checkbox" id="sandblastOnlyToggle"
|
<div class="form-check form-switch mb-0 flex-shrink-0">
|
||||||
${isSandblastOnly ? 'checked' : ''} onchange="onSandblastOnlyToggle()">
|
<input class="form-check-input" type="checkbox" id="sandblastOnlyToggle"
|
||||||
<label class="form-check-label" for="sandblastOnlyToggle" style="line-height:1.3">
|
${isSandblastOnly ? 'checked' : ''} onchange="onSandblastOnlyToggle()" style="cursor:pointer">
|
||||||
|
</div>
|
||||||
|
<label for="sandblastOnlyToggle" class="mb-0" style="line-height:1.3; cursor:pointer;">
|
||||||
<strong>Sandblast / Prep Only</strong>
|
<strong>Sandblast / Prep Only</strong>
|
||||||
<span class="d-block text-muted fw-normal small">No powder coating — no oven or powder costs</span>
|
<span class="d-block text-muted fw-normal small">No powder coating — no oven or powder costs</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -1491,10 +1493,8 @@ function onSandblastOnlyToggle() {
|
|||||||
wz.data.sandblastOnly = checked;
|
wz.data.sandblastOnly = checked;
|
||||||
if (checked) {
|
if (checked) {
|
||||||
wz.data.coats = [];
|
wz.data.coats = [];
|
||||||
// AI price was estimated with coating in mind — clear it so pricing recalculates from prep labor
|
// Keep manualUnitPrice — if the AI returned a price, preserve it as the sandblast price.
|
||||||
if (wz.itemType === 'ai') {
|
// The user can adjust it; clearing it causes a $0 quote when prep services aren't configured.
|
||||||
wz.data.manualUnitPrice = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
renderStep(3);
|
renderStep(3);
|
||||||
}
|
}
|
||||||
@@ -2309,9 +2309,10 @@ function preFillStep2() {
|
|||||||
function buildItemFromWizard() {
|
function buildItemFromWizard() {
|
||||||
const d = wz.data;
|
const d = wz.data;
|
||||||
const isSandblastOnly = !!d.sandblastOnly;
|
const isSandblastOnly = !!d.sandblastOnly;
|
||||||
// Sandblast-only AI items lose the AI pricing flag — the AI price included coating costs
|
// AI flag is preserved even for sandblast-only so the server uses the AI price (manualUnitPrice).
|
||||||
// that no longer apply, so the server prices from prep labor instead.
|
// Without this, sandblast-only AI items fall through to the pricing engine and return $0 when
|
||||||
const isAi = wz.itemType === 'ai' && !isSandblastOnly;
|
// no prep services with minutes are configured.
|
||||||
|
const isAi = wz.itemType === 'ai';
|
||||||
return {
|
return {
|
||||||
description: d.description || null,
|
description: d.description || null,
|
||||||
quantity: d.quantity || 1,
|
quantity: d.quantity || 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user