Files
SportstimeAPI/.planning/ROADMAP.md
Trey t 23788a44d2 docs(04): create phase 4 drag interaction plans
Phase 04: Drag Interaction
- 2 plans in 2 waves
- Plan 01: Migrate to modern drag-drop delegates, lift animation, haptics
- Plan 02: Themed insertion line, invalid zone feedback, snap-back animation

Ready for execution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 16:39:06 -06:00

5.2 KiB

Roadmap: Itinerary Editor

Overview

Build a drag-and-drop itinerary editor for SportsTime using UITableView bridged into SwiftUI. The core insight is that semantic positions (day, sortOrder) are truth while row indices are ephemeral display concerns. Four phases establish the data model, constraints, flattening, and interaction layer - each building on the previous.

Phases

Phase 1: Semantic Position Model

Goal: All movable items have a persistent semantic position that survives data reloads.

Dependencies: None (foundation phase)

Plans: 2 plans

Plans:

  • 01-01-PLAN.md - Create SortOrderProvider utility and Trip day derivation methods
  • 01-02-PLAN.md - Create tests verifying semantic position persistence

Requirements:

  • DATA-01: All movable items have semantic position (day: Int, sortOrder: Double)
  • DATA-02: Travel segments are positioned items with their own sortOrder
  • DATA-03: Games are immovable anchors ordered by game time within each day
  • DATA-04: Custom items can be placed anywhere within any day
  • DATA-05: Items always belong to exactly one day
  • PERS-01: Semantic position survives data reloads from SwiftUI/SwiftData
  • PERS-02: No visual-only state; all positions are persisted semantically
  • PERS-03: Midpoint insertion for sortOrder enables unlimited insertions

Success Criteria:

  1. User can persist an item's position, reload the app, and find it in the same location
  2. Moving travel segment to different day updates its day property (verifiable in debugger/logs)
  3. Inserting between two items gets sortOrder between their values (e.g., 1.0 and 2.0 -> 1.5)
  4. Games remain fixed at their schedule-determined positions regardless of other changes

Phase 2: Constraint Validation

Goal: The system prevents invalid positions and enforces item-specific rules.

Dependencies: Phase 1 (semantic position model)

Plans: 2 plans

Plans:

  • 02-01-PLAN.md - Migrate XCTest constraint tests to Swift Testing
  • 02-02-PLAN.md - Add edge case tests and document constraint API

Requirements:

  • CONS-01: Games cannot be moved (fixed by schedule)
  • CONS-02: Travel segments constrained to valid day range
  • CONS-03: Travel segments must be after from-city games, before to-city games on same day
  • CONS-04: Custom items have no constraints (any position within any day)

Success Criteria:

  1. Attempting to drag a game row shows no drag interaction (game is not draggable)
  2. Travel segment between Chicago and Boston cannot be placed on Day 1 if Chicago games extend through Day 2
  3. Custom note item can be placed before, between, or after games on any day
  4. Invalid position attempt returns rejection (constraint checker returns false)

Phase 3: Visual Flattening

Goal: Semantic items flatten to display rows deterministically, sorted by sortOrder.

Dependencies: Phase 2 (constraints inform what items exist per day)

Plans: 2 plans

Plans:

  • 03-01-PLAN.md - Create ItineraryFlattener utility and refactor reloadData()
  • 03-02-PLAN.md - Add determinism tests for flattening behavior

Requirements:

  • FLAT-01: Visual flattening sorts by sortOrder within each day
  • FLAT-02: Flattening is deterministic and stateless
  • FLAT-03: sortOrder < 0 for "before games", sortOrder >= 0 for "after/between games"

Success Criteria:

  1. Item with sortOrder -1.0 appears before all games in that day's section
  2. Same semantic state always produces identical row order (test with snapshot comparison)
  3. Reordering items and re-flattening preserves the new order (no reversion to "default")

Phase 4: Drag Interaction

Goal: User can drag items with proper feedback, animation, and constraint enforcement.

Dependencies: Phase 3 (flattening provides row-to-semantic translation)

Plans: 2 plans

Plans:

  • 04-01-PLAN.md - Migrate to modern drag-drop delegates with lift animation and haptics
  • 04-02-PLAN.md - Add themed insertion line, invalid zone feedback, and snap-back animation

Requirements:

  • DRAG-01: Lift animation on grab (shadow + slight scale)
  • DRAG-02: Insertion line appears between items showing drop target
  • DRAG-03: Items shuffle out of the way during drag (100ms animation)
  • DRAG-04: Magnetic snap on drop
  • DRAG-05: Invalid drops rejected with snap-back animation
  • DRAG-06: Haptic feedback on grab (light) and drop (medium)
  • DRAG-07: Auto-scroll when dragging to viewport edge
  • DRAG-08: Slight tilt during drag (2-3 degrees)

Success Criteria:

  1. User sees clear insertion line indicating where item will land during drag
  2. Dropping on invalid target snaps item back to original position with haptic feedback
  3. Dragging to bottom of visible area auto-scrolls to reveal more content
  4. Complete drag-drop cycle feels responsive with visible lift, shuffle, and settle animations
  5. Haptic pulses on both grab and drop (verifiable on physical device)

Progress

Phase Status Requirements Completed
1 - Semantic Position Model Complete 8 8
2 - Constraint Validation Complete 4 4
3 - Visual Flattening Complete 3 3
4 - Drag Interaction Planned 8 0

Total: 15/23 requirements completed


Roadmap created: 2026-01-18 Depth: quick (4 phases)