Files
siftlode/frontend/src/lib/parseId.ts
T
peter 482dd28006 fix(e4): address code-review findings (a11y sweep + dedup guards)
Resolves the 5 /code-review high findings on this branch:
- a11y sweep: extend aria-label to the remaining icon-only Plex card buttons the
  first pass missed — PlexPosterCard Info, SeasonCard watched-toggle + add-season
  (EpisodeCard already had them). "Fix a principle everywhere, in one sweep."
- new shared lib/parseId.ts `parsePositiveIntId`, used by BOTH readSelectedId
  (now guarding the stored ?pl fallback the same as the URL — was unguarded) and
  plexSubUrl's ?v=playlist decode; removes the hand-duplicated guard.
- PAGE_KEY exported from navigationInit and imported by NavigationProvider (was
  defined in both).
- hoist a `watchedLabel` const per card so title + aria-label can't drift.

+8 tests (parseId unit + guarded-stored ?pl); full FE gate green (tsc/eslint/
prettier/knip, 317 vitest).
2026-08-20 05:40:59 +02:00

10 lines
609 B
TypeScript

/** Parse a raw value to a positive-integer id, or null if it isn't one. A bare "" gives
* Number("")===0 (finite but not positive), "1.5" is fractional, "-1"/"abc" invalid — all rejected.
* The single guard behind the ?pl / ?v=playlist id params AND the stored playlist selection, so a bad
* value (a malformed link, a legacy/corrupted storage entry) never selects a non-existent playlist. */
export function parsePositiveIntId(raw: string | null | undefined): number | null {
if (raw == null || raw === "") return null;
const n = Number(raw);
return Number.isInteger(n) && n > 0 ? n : null;
}