Commit graph

8 commits

Author SHA1 Message Date
2b01d0e837 feat(plan): bar-math helpers + open reschedule to anyone signed in
Pure helpers for the Gantt's drag/double-click math:

- fractionToDate(fraction, range): what ISO date a fractional
  position in the chart represents, snapped to whole UTC days.
- shiftDatesByFraction: move a bar's start and target by the
  same delta, clamped to the visible range, with start dropped
  when clamping would invert or collapse the span.
- resizeEndToFraction: what the new target date becomes when
  the user drags a right edge.
- moveCardByFraction: alias that produces the action's input
  shape.

11 unit tests cover the corners (no dates set, point bar,
clamping past the right edge, inversion guard).

rescheduleCardAction also drops its owner-only gate. Any
signed-in user — owner or client manager — can move dates
now. PocketBase's existing row-level rules govern which cards
a given user can write (a client manager still only writes
their own client's cards); the activity-log row is unchanged
and attributes the move to the actual user either way.

Adds setSubtaskDatesAction so the same drag/double-click
gestures work on subtask rows. No audit log on subtasks —
matches the existing pattern (subtask toggles don't log).
2026-09-22 05:16:04 +02:00
92c2501726 feat(plan): loadPlan loader with pure buildPlanSections helper
New loader returns the sectioned shape the Gantt view needs:

- buildPlanSections (pure): groups cards by project, sorts by
  start_date asc / title, splits subtasks into dated vs undated.
  Five unit tests cover the grouping and sorting rules.
- loadPlan (server-only): one PocketBase trip per collection,
  delegates to buildPlanSections.

471/471 unit tests pass (was 466, +5 new).
2026-09-21 16:13:47 +02:00
cab3b98372 chore(plan): pick up Plan Puzzle v1 in-progress work and Forgejo repo-url helper
The branch plan-puzzle-v1-tests had accumulated changes from a
sibling thread (Plan Puzzle v1 backend + frontend) that hadn't
been committed yet, plus a new src/lib/git/repo-url helper used by
the Forgejo ingest path. Pick them all up so the working tree is
clean and the branch reflects everything since its fork.

Files (Plan Puzzle):
  src/app/actions/client-proposal.ts
  src/app/actions/owner-plan.ts
  src/app/actions/reschedule.ts
  src/app/actions/reschedule-helpers.ts (+ test)
  src/components/admin/project-form.tsx
  src/components/roadmap/roadmap-builder.tsx
  src/components/roadmap/timeline-view.tsx
  src/lib/cards/write-with-audit.ts (+ test)
  src/lib/roadmap/timeline.ts (+ test)

New helper:
  src/lib/git/repo-url.ts (+ test)

Verified: npm run build clean, 466/466 unit tests pass.
2026-09-21 14:40:04 +02:00
Pixel
b2f332436a feat(plan): Puzzle v1 frontend — tray + 3 month slots, keyboard listbox, proposals, toast
The Plan page replaces the read-only Bands tab with a drag-and-drop
puzzle surface. Both roles drag; owners write target_date directly via
the existing rescheduleCardAction, clients write proposed_target_date
via proposePlanMoveAction. Done-column cards are excluded; they live
on the Timeline tab with a new 'Return to scheduled' button.

UI:
- Tray (unscheduled) + 3 slot columns: This Month / Next / Month After.
  Slot headers carry count + '+N more' chip beyond 12 cards. Tray
  virtualises via scroll-window math at 50+ cards.
- HTML5 drag-and-drop matching the existing PendingTray pattern; the
  PuzzleView keeps the optimistic-state pattern from the kanban Board
  (no router.refresh until the server confirms).
- Keyboard parity: Tab focuses a card, Space opens a listbox (3 slot
  options), 1/2/3 picks a slot, Escape closes, ArrowUp/Down reorders
  within the slot (optimistic local display; no v1 server action for
  in-slot position). aria-live='polite' announces each successful move.
- prefers-reduced-motion via Tailwind motion-safe: variants — the 180ms
  settle animation is dropped for users who request it.

Proposal overlay:
- RoadmapCard shows a left-edge accent stripe + Accept/Dismiss chip
  when proposedTargetDate is set and the viewer is the owner.
- The existing RoadmapCard primitive is reused — no new card component.

Return-to-scheduled button:
- New component on Done-card rows in TimelineView. Replaces the
  drag-sideways motion that the new Done-column server guard blocks.
- Owner-only, calls returnToScheduledAction.

Toast system:
- New ui/toast.tsx: useToast() hook + top-right aria-live region, 4s
  auto-dismiss. AppShell mounts the provider so any page can call it.
- roadmap-builder.tsx no longer console.errors on a failed drag.

Server action stubs:
- client-proposal.ts and owner-plan.ts: temporary no-op stubs that
  return a non-ok response. Deleted when Lin's branch lands; the
  dynamic imports in the UI call them lazily so a missing module
  surfaces through the toast rather than crashing.

Type widening:
- src/lib/roadmap/load.ts: adds optional proposedTargetDate,
  proposedBy, proposedAt, isDone fields to the RoadmapCard interface
  so the Puzzle compiles against pre-migration data. Lin's branch
  populates and tightens these.

Files (15 changed):
- New: slot-date.ts + tests (slot↔date mapping)
- New: puzzle-keyboard.ts + tests (pure listbox state machine)
- New: toast.tsx, proposal-overlay.tsx, return-to-scheduled-button.tsx
- Rewritten: band-view.tsx now exports PuzzleView (per task brief)
- Updated: roadmap-tabs, roadmap-card, roadmap-builder, timeline-view,
  plan/page, app-shell, load.ts

Tests (38 new):
- 18 unit tests for slot-date.ts (month boundaries, year rollover,
  past/future, mid-month symmetry)
- 20 unit tests for the keyboard listbox state machine
  (nextListboxState + isCardShortcut)

UX decisions worth flagging:
- ArrowUp/Down reorders are optimistic only — the order resets to
  canonical (priority desc, title asc) on the next page load. No v1
  server action exists for in-slot position; v2 should add one.
- Done cards are excluded from the Puzzle (per spec §6.1); the
  Return-to-scheduled button lives on the Timeline tab (per task brief).
- A drop on the tray itself is a no-op in v1 — there is no
  'unschedule' action, and the spec lists only 1/2/3 for the keyboard
  listbox.
2026-09-19 18:29:32 +02:00
6e231374e2 feat(roadmap): loader scoped by the caller's own read rules 2026-09-17 07:17:18 +02:00
b164f3273c feat(roadmap): checklist-derived completion percentage 2026-09-17 07:16:57 +02:00
1c24687dae feat(roadmap): time axis, month ticks and greedy row packing 2026-09-17 07:16:47 +02:00
0454abb853 feat(roadmap): Now/Next/Later derived from board order and dates 2026-09-17 07:16:24 +02:00