fix(admin-ui): top-5 critical review bugs (auth + AJV + TZ + idempotency + storage)
This commit is contained in:
@@ -65,3 +65,35 @@ export const nowIsoLocal = (): string => {
|
||||
const pad = (n: number) => String(n).padStart(2, '0')
|
||||
return `${formatIsoDate(d)}T${pad(d.getHours())}:${pad(d.getMinutes())}:00${localTzOffset(d)}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Форматирует ISO datetime в формат для `<input type="datetime-local">`:
|
||||
* "YYYY-MM-DDTHH:mm" в local TZ (без offset).
|
||||
*
|
||||
* <p>Use case: time-travel picker. Раньше использовался
|
||||
* {@code new Date(s).toISOString().slice(0,16)} что отдаёт UTC — у пользователя в
|
||||
* +03:00 picker показывал значение на 3 часа раньше выбранного, а на onChange
|
||||
* value трактовался как local → time drift на каждое редактирование.
|
||||
*/
|
||||
export const toDateTimeLocalInput = (s: string | undefined): string => {
|
||||
if (!s) return ''
|
||||
const d = new Date(s)
|
||||
if (Number.isNaN(d.getTime())) return ''
|
||||
const pad = (n: number) => String(n).padStart(2, '0')
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Парсит value из `<input type="datetime-local">` ("YYYY-MM-DDTHH:mm") в local-TZ
|
||||
* ISO datetime со смещением: "2026-05-08T14:30:00+03:00".
|
||||
*
|
||||
* <p>Pair с {@link toDateTimeLocalInput} — round-trip preserves wall clock time.
|
||||
*/
|
||||
export const fromDateTimeLocalInput = (v: string): string => {
|
||||
if (!v) return ''
|
||||
const m = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/.exec(v)
|
||||
if (!m) return ''
|
||||
const [, y, mo, day, hh, mm] = m
|
||||
const d = new Date(Number(y), Number(mo) - 1, Number(day), Number(hh), Number(mm), 0)
|
||||
return `${formatIsoDate(d)}T${hh}:${mm}:00${localTzOffset(d)}`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user