/* Quick-mode inputs form */ const { useState: useFormState } = React; function NumberField({ id, label, hint, value, onChange, suffix, error, step, min, decimals = 2, wideSuffix = false }) { // Local string state for natural typing (allow intermediate states like "12." or empty) const [text, setText] = useFormState(() => { if (!Number.isFinite(value)) return ""; return formatForInput(value, decimals); }); // Resync if external value changes (e.g. reset, fuel change auto-fill) React.useEffect(() => { if (!Number.isFinite(value)) { setText(""); return; } // Only resync if the parsed text differs from the value const parsed = parseNum(text); if (parsed === null || Math.abs(parsed - value) > 1e-7) { setText(formatForInput(value, decimals)); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [value]); const onLocal = (raw) => { setText(raw); const n = parseNum(raw); if (n !== null) onChange(n); }; return (
onLocal(e.target.value)} onBlur={() => { // Snap display back to canonical const n = parseNum(text); if (n !== null) setText(formatForInput(n, decimals)); }} step={step} min={min} /> {suffix ? {suffix} : null}
{error ?
{error}
: null}
); } function formatForInput(n, decimals) { return n.toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: decimals, }); } function parseNum(raw) { if (raw === "" || raw == null) return null; // Accept '1,234.56' or '1234.56' or '1234,56' (last comma = decimal? no — strip thousands commas, period stays) const cleaned = String(raw).replace(/,/g, "").trim(); if (cleaned === "" || cleaned === "-" || cleaned === ".") return null; const n = parseFloat(cleaned); return Number.isFinite(n) ? n : null; } function InputsForm({ inputs, set, errors }) { return (
set({ purchasePriceUsd: v })} suffix="USD/t" error={errors.purchasePriceUsd} decimals={2} /> set({ fxRate: v })} suffix="AMD" error={errors.fxRate} decimals={2} /> set({ density: v })} suffix="kg/L" error={errors.density} decimals={3} /> set({ batchTons: v })} suffix="tons" error={errors.batchTons} decimals={2} /> set({ sellingPriceAmd: v })} suffix="AMD/L" error={errors.sellingPriceAmd} decimals={2} wideSuffix={true} />
); } window.InputsForm = InputsForm; window.parseNum = parseNum;