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
This commit is contained in:
@@ -89,9 +89,23 @@ export function ResultsTab({
|
||||
const fdm = result?.solvers?.fdm ?? primary ?? null;
|
||||
const [overlayMode, setOverlayMode] = useState<OverlayMode>("depth");
|
||||
const [selectedSegment, setSelectedSegment] = useState<number | null>(null);
|
||||
const [traceabilityQuery, setTraceabilityQuery] = useState("");
|
||||
const dlsUnitLabel = caseState.unitsSelection === 1 ? "deg/100 m" : "deg/100 ft";
|
||||
const trajectorySegments = useMemo(() => buildTrajectorySegments(caseState.survey), [caseState.survey]);
|
||||
const sideLoadProfile = primary?.profiles?.sideLoadProfile ?? null;
|
||||
const pumpDiag = useMemo(() => computePumpPlacement(caseState), [caseState]);
|
||||
const filteredTraceability = useMemo(() => {
|
||||
const fields = result?.fieldTraceability?.fields ?? [];
|
||||
const q = traceabilityQuery.trim().toLowerCase();
|
||||
if (!q) return fields;
|
||||
return fields.filter((row) => {
|
||||
return (
|
||||
row.xmlKey.toLowerCase().includes(q) ||
|
||||
row.category.toLowerCase().includes(q) ||
|
||||
row.notes.toLowerCase().includes(q)
|
||||
);
|
||||
});
|
||||
}, [result?.fieldTraceability?.fields, traceabilityQuery]);
|
||||
|
||||
const dynacardData = useMemo<AlignedData | null>(() => {
|
||||
const fdmSeries = toSeries(fdm ?? undefined);
|
||||
@@ -240,8 +254,7 @@ export function ResultsTab({
|
||||
</Fieldset>
|
||||
<Fieldset legend="Trajectory Analytics">
|
||||
<p className="panel-note" style={{ marginBottom: 8 }}>
|
||||
Click a row or 3D segment to cross-highlight. DLS is shown numerically only (deg per
|
||||
100 ft MD).
|
||||
Click a row or 3D segment to cross-highlight. DLS is shown numerically only ({dlsUnitLabel}).
|
||||
</p>
|
||||
<div className="table-scroll" style={{ maxHeight: 250 }}>
|
||||
<table className="data-table">
|
||||
@@ -251,7 +264,7 @@ export function ResultsTab({
|
||||
<th>MD start</th>
|
||||
<th>MD end</th>
|
||||
<th>ΔMD</th>
|
||||
<th>DLS (deg/100)</th>
|
||||
<th>DLS ({dlsUnitLabel})</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -449,6 +462,18 @@ export function ResultsTab({
|
||||
Categories mirror <code>docs/engineering/field-traceability.md</code> (
|
||||
physics, metadata, parseCalibration, payloadInactive, parsedUnused).
|
||||
</p>
|
||||
<div className="button-row" style={{ gap: 8, alignItems: "center" }}>
|
||||
<input
|
||||
className="panel-input"
|
||||
value={traceabilityQuery}
|
||||
placeholder="Filter by XML key/category/notes"
|
||||
aria-label="Filter traceability rows"
|
||||
onChange={(e) => setTraceabilityQuery(e.target.value)}
|
||||
/>
|
||||
<span className="panel-note">
|
||||
Showing {filteredTraceability.length} / {result.fieldTraceability.fields.length}
|
||||
</span>
|
||||
</div>
|
||||
<div className="table-scroll" style={{ maxHeight: 280 }}>
|
||||
<table className="data-table">
|
||||
<thead>
|
||||
@@ -456,14 +481,16 @@ export function ResultsTab({
|
||||
<th>XML field</th>
|
||||
<th>Category</th>
|
||||
<th>In file</th>
|
||||
<th>Notes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{result.fieldTraceability.fields.map((row) => (
|
||||
{filteredTraceability.map((row) => (
|
||||
<tr key={row.xmlKey} title={row.notes || undefined}>
|
||||
<td className="mono">{row.xmlKey}</td>
|
||||
<td>{row.category}</td>
|
||||
<td>{row.presentInXml ? "yes" : "—"}</td>
|
||||
<td>{row.notes}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
||||
Reference in New Issue
Block a user