feat(record-inputs): tap-to-adjust steppers + inputmode keypad hint
Adds [-] / [+] buttons around every numeric input in the Record Inputs dialog (single-value, dual-entry, and pass_fail+range branches). Tap to increment / decrement by the recipe-author-derived step size (stepFor() already computes this from target_min/target_max precision, falling back to input-type defaults). - Decrement clamps at 0 (typical qty/time/temp on a plating floor doesn't go negative; if needed, operator can still tap the input and type a negative value) - Increment uses _stepRound() to avoid floating-point fuzz on decimals - Center-aligned monospace-ish input between the buttons for clarity - inputmode='decimal' (or 'numeric' for time fields) hint so when the operator does tap the input, the iPad shows a number keypad instead of the full keyboard Touches single-value, dual-entry (min/max), and pass_fail+range. Other multi-field widgets (multi-point thickness, bath chemistry panel) still use plain inputs — separate request if they need steppers too. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -236,6 +236,52 @@ export class FpRecordInputsDialog extends Component {
|
||||
return "any";
|
||||
}
|
||||
|
||||
// Stepper helpers — give the operator a tap-to-increment / -decrement
|
||||
// pair next to each numeric input so they don't have to open the
|
||||
// keyboard for small adjustments. Field is one of: value_number,
|
||||
// value_min, value_max. Increment uses stepFor() so taps move in the
|
||||
// same decimal magnitude the recipe spec was written in. Clamps at 0
|
||||
// (typical qty/time/temp on a plating shop floor doesn't go negative;
|
||||
// if a recipe needs negatives, the operator can still type the value
|
||||
// by tapping the input).
|
||||
_stepDelta(row) {
|
||||
const s = this.stepFor(row);
|
||||
if (s === "any") return 1;
|
||||
const n = parseFloat(s);
|
||||
return isNaN(n) || n <= 0 ? 1 : n;
|
||||
}
|
||||
|
||||
_stepRound(n, delta) {
|
||||
// Avoid floating-point fuzz (0.1+0.2=0.30000004). Round to the
|
||||
// delta's decimal precision.
|
||||
const decimals = (String(delta).split(".")[1] || "").length;
|
||||
if (!decimals) return Math.round(n);
|
||||
const factor = Math.pow(10, decimals);
|
||||
return Math.round(n * factor) / factor;
|
||||
}
|
||||
|
||||
onIncrement(row, field) {
|
||||
const cur = parseFloat(row[field]) || 0;
|
||||
const delta = this._stepDelta(row);
|
||||
row[field] = this._stepRound(cur + delta, delta);
|
||||
}
|
||||
|
||||
onDecrement(row, field) {
|
||||
const cur = parseFloat(row[field]) || 0;
|
||||
const delta = this._stepDelta(row);
|
||||
row[field] = Math.max(0, this._stepRound(cur - delta, delta));
|
||||
}
|
||||
|
||||
inputModeFor(row) {
|
||||
// Tablet keyboard hint — show numeric keypad instead of full
|
||||
// keyboard when the operator does tap the input. 'decimal' is
|
||||
// safer than 'numeric' because it includes the decimal point
|
||||
// (needed for pH, thickness, temperature).
|
||||
const t = row.input_type || "";
|
||||
if (t === "time_seconds" || t === "time_hms") return "numeric";
|
||||
return "decimal";
|
||||
}
|
||||
|
||||
_fpCountDecimals(n) {
|
||||
if (n === null || n === undefined || n === "" || n === 0) return 0;
|
||||
const s = String(n);
|
||||
|
||||
Reference in New Issue
Block a user