From dd636bbe03c11cb06d4963c0f0a0e68e56c96f34 Mon Sep 17 00:00:00 2001 From: tajniak81 <13187254+tajniak81@users.noreply.github.com> Date: Thu, 3 Sep 2026 21:13:42 +0200 Subject: [PATCH] A time box that reads on the clock the user chose MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The schedule windows met this account with "12:00 AM", clipped to "12:00 A!" by a box too narrow for it, while the card above them printed 00:00. Both halves of that are the native control: renders in the browser's locale, and its am/pm did not fit. Nothing on the page moves it. lang= was measured rather than assumed — five inputs set to en-US, en-GB, da-DK, pl-PL and nothing came out identically wide, because the control follows navigator.languages and not the document. That is the wall DateField hit for dates, so the answer has its shape: the typing half is ours, the value stays 24-hour "HH:MM", and what the box shows follows the setting. Four digits, the colon inserted as they are typed, the meridiem its own control rather than something to spell. No picker button: a calendar earns one, four digits do not, and the browser's popup would have brought the 12-hour reading back in with it. A half-typed or impossible time emits nothing rather than the part of it that parses, so a block's Apply leaves that field out instead of writing a time nobody meant. format.js exports which clock is in force now, so what prints a time and what accepts one cannot disagree about it. The box is 80px because 12:30 measures 66 with its padding and the first attempt at 64 clipped — which was the complaint. Co-Authored-By: Claude Opus 5 --- Web App/web/src/components/TimeField.vue | 147 +++++++++++++++++++++++ Web App/web/src/lib/format.js | 18 ++- Web App/web/src/views/Charging.vue | 10 +- 3 files changed, 165 insertions(+), 10 deletions(-) create mode 100644 Web App/web/src/components/TimeField.vue diff --git a/Web App/web/src/components/TimeField.vue b/Web App/web/src/components/TimeField.vue new file mode 100644 index 0000000..3a70f69 --- /dev/null +++ b/Web App/web/src/components/TimeField.vue @@ -0,0 +1,147 @@ + + + diff --git a/Web App/web/src/lib/format.js b/Web App/web/src/lib/format.js index 4fafc0b..3a38a78 100644 --- a/Web App/web/src/lib/format.js +++ b/Web App/web/src/lib/format.js @@ -109,13 +109,25 @@ export function formatTime(value) { const pad = (n) => String(n).padStart(2, "0"); const mm = pad(d.getMinutes()); - const mode = prefs.timeFormat; - const twelve = mode === "12" || (mode !== "24" && regionReadsTwelveHour()); - if (!twelve) return `${pad(h)}:${mm}`; + if (!clockIsTwelveHour()) return `${pad(h)}:${mm}`; // 12 for both noon and midnight, and midnight is the am one. return `${pad(h % 12 || 12)}:${mm} ${h < 12 ? "am" : "pm"}`; } +// Whether times are written on a 12-hour clock right now: what the setting says +// outright, or what the region says when it is left on auto. +// +// Exported because printing a time is not the only thing that has to know. A +// control that lets somebody *enter* one has to offer the same clock, and a box +// that reads 13:45 beside a picker that says 01:45 PM is the disagreement this +// setting exists to end (see components/TimeField.vue). +export function clockIsTwelveHour() { + const mode = prefs.timeFormat; + if (mode === "12") return true; + if (mode === "24") return false; + return regionReadsTwelveHour(); +} + // Whether the chosen region tells the time on a 12-hour clock — the one question // "auto" asks it. Cached because this is asked once per timestamp on a page that // can hold a great many, and the answer only changes when the region does. diff --git a/Web App/web/src/views/Charging.vue b/Web App/web/src/views/Charging.vue index 46d7e5f..fe4baeb 100644 --- a/Web App/web/src/views/Charging.vue +++ b/Web App/web/src/views/Charging.vue @@ -5,6 +5,7 @@ import { prefs } from "../prefs"; import { askConfirm } from "../lib/confirm.js"; import { api } from "../api"; import { formatDateTime } from "../lib/format.js"; +import TimeField from "../components/TimeField.vue"; import { CHARGING_TABS, defaultTabFor } from "../lib/tabs.js"; import ChargerImportModal from "../components/ChargerImportModal.vue"; @@ -2592,18 +2593,13 @@ onMounted(async () => { - -