Commit Graph

26 Commits

Author SHA1 Message Date
Falkan
4c2fe9b3ad fix: replace $effect with onMount for initial data load
$effect re-runs on any reactive state change — loadData/loadConfig both
write state, creating an infinite loop that hung the page under load.
2026-03-18 20:18:30 -04:00
Falkan
b020b74c31 feat: yoloVisibility config, alwaysShowLabel on groups, site settings panel
- AppConfig gains yoloVisibility: 'auto' | 'never' (default: auto)
- Group gains alwaysShowLabel?: boolean
- YOLO toggle only renders when showYoloToggle is true (auto + >1 group)
- Group divider shows when >1 group OR alwaysShowLabel is set
- New /admin/api/config GET+PUT endpoint for yolo settings
- Admin: alwaysShowLabel checkbox in group form
- Admin: ⚙ Settings panel with YOLO label, description, and visibility controls
2026-03-18 20:15:45 -04:00
Falkan
1204ede140 feat: Enter to save, Escape to discard, auto-save on unit/group selection
- selectUnit/selectGroup now async; call autoSaveCurrentForm before switching
- Enter in any form field (except textarea) triggers save
- Escape restores form to snapshot (discards unsaved changes)
- discardUnitForm/discardGroupForm helpers for snapshot restore
2026-03-18 19:42:56 -04:00
Falkan
b1a5586c25 fix: checkbox alignment, wording, and Dan Mode drag handle contrast 2026-03-18 19:13:48 -04:00
Falkan
998cda0bb3 feat: hidden flag, description placeholders, drag handle contrast fix
- Unit and Group get hidden?: boolean — filtered server-side before render
- Hidden group also suppresses all its units from the converter
- New resolveDescription() utility in src/lib/description.ts
  supports {id}, {id:label}, {id:plural}, {id:symbol} placeholders
- ConverterCard pre-resolves descriptions and passes result to ConversionResult
- ConversionResult accepts description prop instead of reading unit.description
- Admin forms: Hidden checkbox added for both units and groups
- drag-handle color overridden to --pico-primary-inverse on selected/drag-over rows
  (white in light/dark themes, black on Dan Mode yellow)
2026-03-18 16:53:34 -04:00
Falkan
9d56d2ed46 Revert "fix: replace braille glyph drag handle with SVG grip icon"
This reverts commit 21f1f6baaa.
2026-03-18 16:34:48 -04:00
Falkan
21f1f6baaa fix: replace braille glyph drag handle with SVG grip icon 2026-03-18 16:26:39 -04:00
Falkan
5ed392a2d4 fix: template literal quotes in fetch calls; a11y roles on drag elements 2026-03-17 20:52:44 -04:00
Falkan
3598a2dd25 fix: all admin client-side fetches and redirects use configured adminPath 2026-03-17 20:49:38 -04:00
Falkan
51f047df3e revert: undo adminPath routing attempts — clean slate for restart 2026-03-17 20:39:51 -04:00
Falkan
3a256ccef5 fix: adminPath reroute — move to hooks.ts universal hook, read config.json directly 2026-03-17 20:36:12 -04:00
Falkan
b2adcf05ca feat: bulk delete action with confirmation in admin panel 2026-03-17 20:02:48 -04:00
Falkan
192e852a8c feat: add text-decoration underline to bulk-clear button hover 2026-03-17 20:01:18 -04:00
Falkan
a5d0e988f8 feat: auto-ID generation from label with kebab conversion 2026-03-17 20:00:53 -04:00
Falkan
1317f5e8fb feat: per-group sort order (defined/alpha) in group form and converter 2026-03-17 19:59:02 -04:00
Falkan
6d72242aaa feat: drag-to-reorder groups and units with PUT /admin/api/order 2026-03-17 19:58:17 -04:00
Falkan
c1279c3757 feat: auto-save dirty form guard with field-error highlighting 2026-03-17 19:56:39 -04:00
Falkan
15b763e062 feat: unit descriptions with tooltip action and admin textarea 2026-03-17 19:55:09 -04:00
Falkan
f43f415cfa fix: translate __orphan__ sentinel to null in bulk move; ungrouped units now fully bulk-operable 2026-03-17 18:32:03 -04:00
Falkan
6e992bbfae fix: bulk-clear hover — override Pico CSS vars not just color property 2026-03-17 18:00:52 -04:00
Falkan
670833ffa2 fix: bulk-clear hover invisible in light/Dan mode (Pico [role=button] override) 2026-03-17 17:57:14 -04:00
Falkan
7cdb84a4f3 refactor: bulk bar — stable layout, disabled not hidden, stacked group row 2026-03-17 16:22:45 -04:00
Falkan
10d94d676b refactor: bulk bar — two-row layout, better contrast, controls only when active 2026-03-17 16:14:37 -04:00
Falkan
ac6af9e90d refactor: admin left panel — wider, less cluttered, persistent bulk action bar
- Left panel widened to 340px (was 280px)
- Removed redundant edit pencil icons from unit rows — clicking the row selects it
- Group names truncate with ellipsis instead of wrapping
- Added select-all/none checkbox per group header (with indeterminate state)
- Bulk action bar is now persistent at top of left panel, always visible
- Bulk actions use two-dropdown pattern: Action (Move to group) → Target group
- 'Add unit' text shortened to '+ Add unit', no more wrapping
- Delete-group orphan label clarified: 'Delete group only — keep units as Ungrouped'
2026-03-17 15:45:11 -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