[object Object]

← back to NationalPaperHangers

Stop clobbering the customer's hand-entered square footage

515caa4ff873b0713db4d9ea12a09e80955cafd7 · 2026-05-18 17:34:01 -0700 · SteveStudio2

room-capture.js promised "customer can override" the square_feet field
but serialize() overwrote it with the measured-walls total on every box
drag, keystroke, or wallpaper change — so the override only held when
zero rooms were measured. A userEditedSqft flag now latches on the
field's first real 'input' event (a programmatic .value set never fires
one), and the auto-fill is skipped once it trips. e2e proves a typed
999 survives a later room re-measure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 515caa4ff873b0713db4d9ea12a09e80955cafd7
Author: SteveStudio2 <steve@designerwallcoverings.com>
Date:   Mon May 18 17:34:01 2026 -0700

    Stop clobbering the customer's hand-entered square footage
    
    room-capture.js promised "customer can override" the square_feet field
    but serialize() overwrote it with the measured-walls total on every box
    drag, keystroke, or wallpaper change — so the override only held when
    zero rooms were measured. A userEditedSqft flag now latches on the
    field's first real 'input' event (a programmatic .value set never fires
    one), and the auto-fill is skipped once it trips. e2e proves a typed
    999 survives a later room re-measure.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 public/js/room-capture.js | 11 ++++++++++-
 tests/e2e-room-capture.js | 10 ++++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/public/js/room-capture.js b/public/js/room-capture.js
index 3ed3f61..0033cee 100644
--- a/public/js/room-capture.js
+++ b/public/js/room-capture.js
@@ -23,6 +23,13 @@
   var csrf = (document.querySelector('meta[name="csrf-token"]') || {}).content || '';
 
   var rooms = [];
+  // Once the customer types their own square-feet figure, stop overwriting it
+  // with the measured-walls total — a programmatic .value set never fires
+  // 'input', so this flag only trips on a genuine keystroke.
+  var userEditedSqft = false;
+  if (sqftInput) {
+    sqftInput.addEventListener('input', function () { userEditedSqft = true; });
+  }
 
   function num(v) { var n = parseFloat(v); return isFinite(n) ? n : 0; }
   function round(n, step) { return Math.round(n / step) * step; }
@@ -70,7 +77,9 @@
       out.push(entry);
     });
     field.value = JSON.stringify(out);
-    if (sqftInput && totalSqFt > 0) sqftInput.value = Math.round(totalSqFt);
+    if (sqftInput && totalSqFt > 0 && !userEditedSqft) {
+      sqftInput.value = Math.round(totalSqFt);
+    }
   }
 
   function applyBox(r) {
diff --git a/tests/e2e-room-capture.js b/tests/e2e-room-capture.js
index 33551ff..fa1336f 100644
--- a/tests/e2e-room-capture.js
+++ b/tests/e2e-room-capture.js
@@ -122,6 +122,16 @@ function db() { if (!_db) _db = require('../lib/db'); return _db; }
        && captures[0].wallpaper.repeat_in === 18,
        'wallpaper width + repeat serialized');
 
+    // A square-feet figure the customer types by hand must survive a later
+    // room re-measure — the measured-walls total no longer clobbers it.
+    await page.locator('input[name="square_feet"]').fill('999');
+    await page.locator('input[name="square_feet"]').dispatchEvent('input');
+    await page.locator('.rc-room-label').fill('Dining room (updated)');
+    await page.locator('.rc-room-label').dispatchEvent('input');
+    await page.waitForTimeout(150);
+    ok(await page.locator('input[name="square_feet"]').inputValue() === '999',
+       'customer-entered square feet is not overwritten by measured total');
+
     await page.locator('[data-rc-add]').click();
     ok(await page.locator('.rc-room').count() === 2, 'add-room adds a second card');
 

← 3e66967 Validate booking-media uploads by magic bytes, not the spoof  ·  back to NationalPaperHangers  ·  Coerce garbage numeric booking fields to null instead of 500 3fa1e62 →