fix(ui): submit raw number input value for auth key expiry (#609)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jade
2026-08-19 10:40:53 +09:00
committed by GitHub
parent e1f9db4c4e
commit 0feab692bd
4 changed files with 115 additions and 5 deletions
+6 -4
View File
@@ -21,8 +21,13 @@ export default function NumberInput(props: NumberInputProps) {
const { label, name, description } = props;
return (
// `name` belongs on the Root, not the Input. The Input is a text field that
// holds the locale-formatted value ("365,000", "365 000", "365.000"), while
// the Root renders a hidden number input carrying the raw value. Naming the
// Input would submit the formatted string and break server-side parsing.
<NumberField.Root
className="flex flex-col gap-1"
name={name}
defaultValue={props.defaultValue}
value={props.value}
onValueChange={props.onValueChange}
@@ -49,10 +54,7 @@ export default function NumberInput(props: NumberInputProps) {
"border border-mist-200 dark:border-mist-800",
)}
>
<NumberField.Input
name={name}
className="w-full rounded-l-md bg-transparent py-2 pl-3 text-sm focus:outline-hidden"
/>
<NumberField.Input className="w-full rounded-l-md bg-transparent py-2 pl-3 text-sm focus:outline-hidden" />
<NumberField.Decrement aria-label="Decrement" className="h-7.5 w-7.5 rounded-lg p-1">
<Minus className="h-4 w-4" />
</NumberField.Decrement>
+12 -1
View File
@@ -88,10 +88,21 @@ export async function authKeysAction({ request, context }: Route.ActionArgs) {
});
}
const day = Number(expiry.toString().split(" ")[0]);
// The form submits the raw, unformatted value of the number input, so
// anything that is not a plain integer (grouping separators from
// `Intl.NumberFormat`, unit suffixes, ...) is malformed input. Parsing it
// leniently either produces an Invalid Date (500) or, for dot-grouping
// locales, a silently truncated expiry.
const day = /^\d+$/.test(expiry.trim()) ? Number(expiry.trim()) : Number.NaN;
const date = new Date();
date.setDate(date.getDate() + day);
if (day < 1 || Number.isNaN(date.getTime())) {
return data("`expiry` must be a whole number of days.", {
status: 400,
});
}
const key = await api.preAuthKeys.create({
user,
ephemeral: ephemeral === "on",