refactor: use localDateTimeToUtcIso in component and clean up tests
- Import and call localDateTimeToUtcIso in the add-game onSubmit handler instead of duplicating the conversion inline; also applies the null/ invalid-date safety from the utility to the component - Remove the redundant "incompatible with datetime-local" test case (its intent is better expressed as a code comment than a test assertion) - Move the datetime-local incompatibility explanation into a NOTE comment on the utility function's JSDoc https://claude.ai/code/session_0148fgZiXpyvGX8ZX3BFRGCs
This commit is contained in:
parent
1ef37fa8db
commit
4288f14a79
3 changed files with 9 additions and 15 deletions
|
|
@ -41,15 +41,4 @@ describe("localDateTimeToUtcIso", () => {
|
|||
expect(result).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/);
|
||||
});
|
||||
|
||||
it("the returned ISO string is incompatible with datetime-local input format", () => {
|
||||
// This documents WHY we need a hidden input instead of setting the
|
||||
// datetime-local input's value directly. datetime-local only accepts
|
||||
// "YYYY-MM-DDTHH:MM" — a 'Z' suffix makes the value invalid and the
|
||||
// browser silently clears the field.
|
||||
const result = localDateTimeToUtcIso("2026-03-11T10:00");
|
||||
expect(result).not.toBeNull();
|
||||
expect(result).toContain("Z");
|
||||
// The value does NOT match the datetime-local format (no Z allowed)
|
||||
expect(result).not.toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@
|
|||
* to hold the converted UTC value before form submission.
|
||||
*
|
||||
* Returns null when value is empty, nullish, or not a valid date.
|
||||
*
|
||||
* NOTE: The returned ISO string (e.g. "2026-03-11T17:00:00.000Z") is intentionally
|
||||
* incompatible with datetime-local inputs, which only accept "YYYY-MM-DDTHH:MM".
|
||||
* Setting a Z-suffixed string on a datetime-local input causes browsers to silently
|
||||
* clear the field. Always write the result to a separate hidden input, not back to
|
||||
* the datetime-local input itself.
|
||||
*/
|
||||
export function localDateTimeToUtcIso(value: string | null | undefined): string | null {
|
||||
if (!value) return null;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Form, Link } from "react-router";
|
||||
import { Fragment, useState, useEffect, useMemo } from "react";
|
||||
import { localDateTimeToUtcIso } from "~/lib/date-utils";
|
||||
import type { Route } from "./+types/admin.sports-seasons.$id.events.$eventId.bracket";
|
||||
|
||||
import { loader, action } from "./admin.sports-seasons.$id.events.$eventId.bracket.server";
|
||||
|
|
@ -732,10 +733,8 @@ export default function EventBracket({
|
|||
const scheduledAtLocal = form.elements.namedItem("scheduledAtLocal") as HTMLInputElement;
|
||||
// Write the UTC ISO string into the hidden input that IS submitted
|
||||
const scheduledAtHidden = form.elements.namedItem("scheduledAt") as HTMLInputElement;
|
||||
if (scheduledAtLocal?.value && scheduledAtHidden) {
|
||||
// datetime-local inputs reject ISO strings with a 'Z' suffix and silently
|
||||
// clear their value, so we use a separate hidden input for the UTC value.
|
||||
scheduledAtHidden.value = new Date(scheduledAtLocal.value).toISOString();
|
||||
if (scheduledAtHidden) {
|
||||
scheduledAtHidden.value = localDateTimeToUtcIso(scheduledAtLocal?.value) ?? "";
|
||||
}
|
||||
}}>
|
||||
<input type="hidden" name="intent" value="add-game" />
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue