fix(admin-ui): top-5 critical review bugs (auth + AJV + TZ + idempotency + storage)

This commit is contained in:
Александр Зимин
2026-05-10 16:22:35 +00:00
parent f2614244bf
commit fc2fb35717
8 changed files with 292 additions and 72 deletions
+32
View File
@@ -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)}`
}