Commit Graph

12 Commits

Author SHA1 Message Date
Falkan
e2e53ca44a feat: YOLO toggle inline layout; yoloLabel/yoloDescription configurable via config.json 2026-03-17 19:50:59 -04:00
Falkan
aeeae1e7ce refactor: simplify admin code — extract shared helpers, fix quality issues
- Extract KEBAB_RE, SESSION_COOKIE, SESSION_MAX_AGE_MS, COOKIE_MAX_AGE,
  authRequest(), and sessionResponse() to auth.ts — eliminating 4 copies
  of the auth() wrapper and 3 copies of KEBAB_RE across admin API routes
- Remove timing side-channel: drop a.length !== b.length early-return
  before timingSafeEqual in verifySession (SHA-256 HMAC always 64 chars)
- Fix YOLO localStorage write-before-read race using initialization guard
- Fix admin layout /api/ bypass to return {} instead of {authenticated:true}
- Extract extractError() helper in admin page — removes 4 inline patterns
- Parallel Promise.all in admin loadData() — halves round-trip latency
- Parallel Promise.all in moveCheckedUnits() + surface per-request errors
- Hoist Big(inputValue) above .map() in converter — one alloc per recompute
- O(n) single-pass orderedResults using Map instead of O(n*groups) filters
- Fix expandedGroups.add() mutation — use Set assignment for consistency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 14:04:33 -04:00
Falkan
d1f51c141e feat: admin page with dynamic converter loading
Implements full admin interface for managing units and groups.
Migrates converter from static imports to server-side data loading.

- Switch adapter-static → adapter-node
- Add bcryptjs session auth with HMAC-signed cookies
- Add data/units.json and data/config.json data layer
- Add atomic file writes via temp-file rename
- Add public GET /api/units endpoint
- Add auth-gated admin CRUD API for units and groups
- Add two-panel admin UI with group tree and edit forms
- Add YOLO mode toggle for cross-group conversions
- Add visual group dividers in converter results grid
- Update ResultItem type for nullable convertedValue and isYolo flag
- Group deletion supports reassign/orphan with toBase recalculation

Rollback point: 067fd44

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 13:55:11 -04:00
Falkan
b05f421bcb highlight: remove symbol line, reduce height to 5rem 2026-03-17 10:49:45 -04:00
Falkan
7ca0fc4032 highlight: inline equation layout with responsive stacked fallback
- From and result now on one line: '1.00 Units = 0.09 OtherUnits'
- Same font size and color for both sides (pico-color, 600 weight)
- Container query switches to over-under at <420px with '= ' prefix on result line
- Separator '=' shown inline; muted color/normal weight to visually anchor the equation
- Removed old two-tier font sizing (small grey from, large blue result)
2026-03-17 10:47:27 -04:00
Falkan
ee162fc0f7 Improve: stable highlight height, equation display format, responsive font sizes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 22:26:02 -04:00
Falkan
66f77a6394 Simplify: promote inline Big import type, merge duplicate hover/highlighted CSS rules
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 22:22:48 -04:00
Falkan
af5f10a4ec Fix: shift+click preserves input value, Ctrl+click adopts value, stable highlight layout
- shift+click now only sets fromUnitId; inputValue is unchanged so all outputs
  recalculate correctly from the original user input
- Ctrl+click is a new gesture that sets both fromUnitId and inputValue to the
  tile's displayed converted value (the "pivot" action)
- highlighted-result block always renders with min-height:8rem so the page
  below it never jumps when a highlight is added or cleared
- hotkey hint updated to document all three click gestures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 22:21:22 -04:00
Falkan
d9489a5db2 Simplify: token-ify hardcoded colors, remove redundant Big ternary, guard no-op shift-click
- Replace 5 hardcoded #2C2C2C/#555550/#888880 literals with var(--pico-color),
  var(--color-label), var(--pico-muted-color); add --color-label token to :root
- Remove inline Big(inputValue) ternary in results derived — convert.ts already
  handles same-unit identity via its own from.id === to.id guard
- Drop now-unused Big import from +page.svelte
- Guard onshiftclick in ConversionResult: no-op when tile is already the from-unit

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 22:07:37 -04:00
Falkan
d22885b708 Fix: card text contrast, stable grid order, independent highlight/input states, highlight dismiss
- Explicit dark colors on .result-value, .result-label, .result-symbol, .highlighted-value, .highlighted-label
- Include from-unit in results grid (stable definition-order); from-unit tile shows Big(inputValue) and gets is-input-unit dashed-border class
- Shift+click no longer clears highlightedUnitId — fromUnitId and highlightedUnitId are now fully independent states
- Add × dismiss button (aria-label="Remove highlight") to .highlighted-result banner; .highlighted-result gains position:relative

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 22:03:01 -04:00
Falkan
8f835c35d2 Phase 2: core converter, live conversion, URL state, highlight interaction 2026-03-16 21:34:16 -04:00
Falkan
65f8bc1b9f Phase 1: scaffold, types, schema, layout shell
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 21:22:34 -04:00