From 39a340fc395bdc81b67eb3bdac7e604926a40503 Mon Sep 17 00:00:00 2001 From: Horacio Date: Thu, 27 Aug 2026 19:57:21 -0300 Subject: [PATCH] fix: allow negative latitude and longitude in position config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fixed-position latitude/longitude fields rejected negative coordinates, breaking configuration for users in the southern and western hemispheres. Two separate defects were involved. fieldLength.max is a character count, not a value bound. With max: 10, an 11-character value like -34.1147648 was discarded outright while its 10-character positive counterpart was accepted. Raised to 12, the length of -180.0000000 — the longest value the field's own "max 7 decimal precision" contract allows. GenericInput rendered String(controllerField.value) into an , which yields the literal string "undefined" for an optional field with no value yet. The DOM sanitises that to "" while React's value tracker still holds "undefined", and the resulting desync swallowed the first keystroke — the minus sign. Using controllerField.value ?? "" keeps the two in sync. Fixes #1308 --- .../src/components/Form/FormInput.test.tsx | 94 +++++++++++++++++++ apps/web/src/components/Form/FormInput.tsx | 6 +- .../PageComponents/Settings/Position.tsx | 4 +- 3 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 apps/web/src/components/Form/FormInput.test.tsx diff --git a/apps/web/src/components/Form/FormInput.test.tsx b/apps/web/src/components/Form/FormInput.test.tsx new file mode 100644 index 000000000..0ea2f5ede --- /dev/null +++ b/apps/web/src/components/Form/FormInput.test.tsx @@ -0,0 +1,94 @@ +import { PositionValidationSchema } from "@app/validation/config/position.ts"; +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { useForm } from "react-hook-form"; +import { describe, expect, it } from "vitest"; +import { GenericInput, type InputFieldProps } from "./FormInput.tsx"; + +type LatitudeForm = { latitude: number | undefined }; + +/** + * Mirrors how Position.tsx uses the latitude field: an optional numeric value + * that starts out `undefined` when the node has no fixed position. The stored + * form value is echoed into a test-only node, since the bug in #1308 was about + * what the field committed, not only what it displayed. + */ +function Harness({ + properties, +}: { + properties: InputFieldProps["properties"]; +}) { + const { control, watch } = useForm({ + defaultValues: { latitude: undefined }, + }); + + return ( + <> + + control={control} + field={{ + type: "number", + name: "latitude", + label: "Latitude", + properties, + }} + /> + {String(watch("latitude"))} + + ); +} + +// Matches the real latitude/longitude field config in Position.tsx. +const latitudeProperties = { step: 0.0000001, fieldLength: { max: 12 } }; + +/** GenericInput renders no