Files
dickloads/MEMORY/WORK/20260317-000000_humor-units-7-improvements/PRD.md

7.1 KiB

task, slug, effort, phase, progress, mode, started, updated
task slug effort phase progress mode started updated
Implement 7 humor-units admin improvements 20260317-000000_humor-units-7-improvements comprehensive execute 0/64 interactive 2026-03-17T00:00:00Z 2026-03-17T00:01:00Z

Context

Implementing 7 ordered features for the humor-units SvelteKit admin page. Files: src/lib/types.ts, src/routes/admin/+page.svelte, src/routes/+page.svelte, src/components/ConversionResult.svelte, new src/routes/admin/api/order/+server.ts. Each feature must pass npm run build before committing and proceeding.

Risks

  • TypeScript strict mode may reject certain Svelte 5 patterns (e.g., action typing)
  • Drag-and-drop with Svelte 5 runes requires careful state management
  • Form dirty-check needs accurate initial-value tracking
  • Auto-ID edge cases: user clears field, then types again
  • The description field must be passed through all API layers (POST/PUT) without breaking existing validation
  • CSS override of Pico hover must handle both light and dark mode correctly

Plan

  1. Feature 1: Add description?: string to Unit type; add textarea in admin unit form; add use:tooltip action in ConversionResult.svelte
  2. Feature 2: Track form initial values; dirty detection; auto-save on "+ Add" when dirty; highlight invalid fields with field-error class
  3. Feature 3: HTML5 DnD on group rows and unit rows; new PUT /admin/api/order endpoint
  4. Feature 4: Add sortOrder? to Group type; select in group form; sort logic in orderedResults derived
  5. Feature 5: Auto-ID from label (kebab) in create forms; ID field with manual-edit tracking
  6. Feature 6: Add text-decoration: underline to .bulk-clear:hover and ensure color override
  7. Feature 7: Add "delete" to bulkAction dropdown; confirmation UI; DELETE each checked unit

Criteria

Feature 1: Unit descriptions / tooltips

  • ISC-1: description?: string optional field added to Unit interface in types.ts
  • ISC-2: Unit form has textarea labeled "Description" below existing fields
  • ISC-3: Description value saved via POST /admin/api/units (new unit)
  • ISC-4: Description value saved via PUT /admin/api/units/:id (edit unit)
  • ISC-5: Description value loaded into form when unit is selected for editing
  • ISC-6: use:tooltip Svelte action defined in frontend converter page
  • ISC-7: Tooltip action sets title attribute after 500ms mouseenter delay
  • ISC-8: Tooltip action clears timeout and removes title on mouseleave
  • ISC-9: Tooltip applied to unit label/symbol span in ConversionResult
  • ISC-10: Tooltip NOT set when description is empty or undefined

Feature 2: Auto-save partial forms + error blocking

  • ISC-11: isDirty() function detects changes from initial form values
  • ISC-12: Initial form snapshot captured when form is opened (select/new)
  • ISC-13: Clicking "+ Add Unit" while dirty unit form open attempts auto-save
  • ISC-14: Clicking "+ Add Group" while dirty group form open attempts auto-save
  • ISC-15: Successful auto-save opens new form as intended
  • ISC-16: Failed auto-save displays error inline; does NOT open new form
  • ISC-17: field-error CSS class defined with invalid border-color var
  • ISC-18: First invalid/empty required field highlighted with field-error on save failure
  • ISC-19: Required unit fields validated: label, labelPlural, symbol, toBase>0, id (kebab)
  • ISC-20: Required group fields validated: label, id (kebab)
  • ISC-21: Form not dirty if user clicked "+ Add" but typed nothing yet

Feature 3: Drag-to-reorder groups and units

  • ISC-22: Group header rows have draggable="true" attribute
  • ISC-23: Group drag cursor is grab (CSS)
  • ISC-24: Drag handle icon added to unit rows (left side, cursor grab)
  • ISC-25: Groups can be reordered by drag-and-drop within the list
  • ISC-26: Units can be reordered within their group by drag-and-drop
  • ISC-27: Units cannot be dragged between groups via DnD
  • ISC-28: After drop, PUT /admin/api/order called with new order arrays
  • ISC-29: New endpoint src/routes/admin/api/order/+server.ts created
  • ISC-30: Order endpoint is auth-gated via authRequest
  • ISC-31: Order endpoint accepts groups?: string[] and reorders data.groups
  • ISC-32: Order endpoint accepts units?: Record<string, string[]> and reorders units within groups
  • ISC-33: Order endpoint saves data and returns { ok: true }

Feature 4: Per-group sort order setting

  • ISC-34: sortOrder?: 'defined' | 'alpha' added to Group interface in types.ts
  • ISC-35: Group edit form has select for "Display order" (Defined order / Alphabetical)
  • ISC-36: sortOrder value saved via PUT /admin/api/groups/:id
  • ISC-37: sortOrder value loaded into form when group is selected for editing
  • ISC-38: Frontend orderedResults sorts by label when group.sortOrder === 'alpha'
  • ISC-39: Frontend uses defined order when sortOrder is undefined or 'defined'

Feature 5: Auto-ID generation from label

  • ISC-40: toKebab(s) helper function defined
  • ISC-41: idWasManuallyEdited boolean state tracked for unit create form
  • ISC-42: idWasManuallyEdited boolean state tracked for group create form
  • ISC-43: Unit create form ID field live-updates from label while not manually edited
  • ISC-44: Group create form ID field live-updates from label while not manually edited
  • ISC-45: Typing in ID field sets idWasManuallyEdited = true, stops auto-update
  • ISC-46: Clearing ID field sets idWasManuallyEdited = false, resumes auto-generation
  • ISC-47: On form blur or save attempt: ID generated from label if ID empty and label non-empty

Feature 6: Clear button hover highlight

  • ISC-48: .bulk-clear:not(:disabled):hover CSS has text-decoration: underline
  • ISC-49: Hover color uses --pico-contrast for dark text in light/Dan mode
  • ISC-50: Background stays transparent on hover
  • ISC-51: Dark mode hover effect not broken (text lightens appropriately)
  • ISC-52: All three Pico vars overridden: --pico-color, --pico-background-color, --pico-border-color

Feature 7: Bulk delete action

  • ISC-53: "Delete" option added to bulkAction select (value: 'delete')
  • ISC-54: Group target row hidden when bulkAction is 'delete'
  • ISC-55: Confirmation section shown: "Delete N units? [Confirm] [Cancel]"
  • ISC-56: N in confirmation reflects current checkedUnitIds.size
  • ISC-57: Confirm calls DELETE /admin/api/units/:id for each checked unit
  • ISC-58: After all deletions, selection cleared and data reloaded
  • ISC-59: Failed deletions shown as formError with count of failures
  • ISC-60: "Cancel" resets bulkAction to '' and clears confirmation state
  • ISC-61: Apply button disabled when bulkAction is 'delete' (confirm/cancel separate UI)

Anti-criteria

  • ISC-A1: data/units.json and data/config.json not directly modified by feature code
  • ISC-A2: Auth system, session handling unchanged
  • ISC-A3: No global CSS added outside scoped style blocks
  • ISC-A4: No bare :root var overrides for Pico
  • ISC-A5: npm run build passes after each feature implementation

Decisions

Verification