/* 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;