Files
rods/gui-ts/src/ui/tabs/PumpTab.tsx
Conner Majic 64d4492c60 feat: polish rod and trajectory UX interactions
Improve Majic Rod Solver usability with denser table controls, clearer unit-aware guidance, and stronger accessibility affordances for keyboard/screen-reader workflows.

Made-with: Cursor
2026-04-17 08:16:11 -06:00

108 lines
3.4 KiB
TypeScript

import { useMemo } from "react";
import type { CaseStore } from "../../state/useCaseStore";
import { Fieldset } from "../common/Fieldset";
import { Row } from "../common/Row";
import { NumberField } from "../common/NumberField";
import { SelectField } from "../common/SelectField";
import {
PUMP_PLUNGER_INCH_OPTIONS,
formatPumpDiameterDual,
pumpDiameterMmFromInches
} from "../../state/unitsDisplay";
type Props = { store: CaseStore };
export function PumpTab({ store }: Props) {
const { state, update } = store;
const isMetric = state.unitsSelection === 1;
const pumpOptions = useMemo(() => {
const mmVals = PUMP_PLUNGER_INCH_OPTIONS.map((inchVal) => pumpDiameterMmFromInches(inchVal));
const opts = PUMP_PLUNGER_INCH_OPTIONS.map((inchVal, i) => ({
value: mmVals[i],
label: formatPumpDiameterDual(mmVals[i], state.unitsSelection)
}));
const known = opts.some((o) => Math.abs(o.value - state.pumpDiameter) < 0.001);
if (!known && state.pumpDiameter > 0) {
opts.unshift({
value: state.pumpDiameter,
label: formatPumpDiameterDual(state.pumpDiameter, state.unitsSelection)
});
}
return opts;
}, [state.pumpDiameter, state.unitsSelection]);
return (
<div className="tab-grid two">
<Fieldset legend="Pump Geometry">
<Row
label="Plunger diameter"
htmlFor="plungerDiam"
hint={
isMetric
? "Metric-first display with imperial equivalent in each option."
: "Imperial-first display with metric equivalent in each option."
}
>
<SelectField
id="plungerDiam"
value={state.pumpDiameter}
options={pumpOptions}
onChange={(v) => update("pumpDiameter", v)}
ariaLabel="Pump plunger diameter"
/>
</Row>
<Row
label="Pump Friction"
htmlFor="pumpFric"
hint={isMetric ? "N (SI case)" : "lbf (imperial oilfield case)"}
>
<NumberField
id="pumpFric"
value={state.pumpFriction}
step={10}
onChange={(v) => update("pumpFriction", v)}
/>
</Row>
<Row
label="Pump Intake Pressure"
htmlFor="pumpIntake"
hint={isMetric ? "Pa (SI case)" : "psi (imperial oilfield case)"}
>
<NumberField
id="pumpIntake"
value={state.pumpIntakePressure}
step={1}
onChange={(v) => update("pumpIntakePressure", v)}
/>
</Row>
</Fieldset>
<Fieldset legend="Fillage">
<Row label="Pump Fillage Option" htmlFor="fillageOpt">
<SelectField
id="fillageOpt"
value={state.pumpFillageOption}
onChange={(v) => update("pumpFillageOption", v)}
options={[
{ value: 0, label: "0 — auto" },
{ value: 1, label: "1 — specified" },
{ value: 2, label: "2 — incomplete fillage" }
]}
/>
</Row>
<Row label="Percent Pump Fillage (%)" htmlFor="pctFill">
<NumberField
id="pctFill"
value={state.percentPumpFillage}
step={1}
min={0}
max={100}
onChange={(v) => update("percentPumpFillage", v)}
/>
</Row>
</Fieldset>
</div>
);
}