Commit graph

5 commits

Author SHA1 Message Date
d7d11124e3 feat(PBI-79): sprint-switch auto-select PBI/story + user-settings persist
Bij sprint-switch wordt de sprint-content server-side opgevraagd. Wanneer
de sprint precies één PBI (en die PBI exact één story binnen de sprint)
heeft, worden PBI en story automatisch geselecteerd. Alle drie keuzes
(sprint, pbi, story) worden atomair in user-settings opgeslagen zodat ze
cross-device blijven hangen.

- lib/user-settings.ts: layout krijgt nullable activePbis +
  activeStories per product.
- lib/active-sprint.ts: setActiveSelectionInSettings schrijft de drie
  keys atomair + notify pg_notify.
- actions/active-sprint.ts: switchActiveSprintAction(productId, sprintId)
  doet de server-side auto-select-resolutie (single PBI → single story)
  en returnt { sprintId, pbiId, storyId }.
- components/shared/sprint-switcher.tsx: handleSwitchSprint roept de
  nieuwe action aan en synchroniseert de workspace-store gelijk zodat
  de UI geen flash krijgt voor de SSR-refresh.
- components/backlog/active-selection-hydrator.tsx (nieuw): client-side
  effect dat user-settings.activePbis/activeStories naar workspace-store
  spiegelt; wint van de localStorage hint-restore.
- app/(app)/products/[id]/page.tsx: ActiveSelectionHydrator gemount
  binnen BacklogHydrationWrapper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 18:13:20 +02:00
2af6f24598 feat(PBI-79/ST-1333): active-sprint null-contract + clearActiveSprintAction
- lib/user-settings.ts: activeSprints values nullable in Zod-schema.
  Key-aanwezigheid heeft nu betekenis (key+null = bewust geen sprint;
  key ontbreekt = fallback-cascade).
- lib/active-sprint.ts: nieuwe readStoredActiveSprintState helper +
  resolveActiveSprint respecteert expliciet 'cleared' state zonder fallback.
  clearActiveSprintInSettings schrijft null i.p.v. de key te verwijderen.
- actions/active-sprint.ts: nieuwe clearActiveSprintAction met auth +
  membership-check.
- components/shared/sprint-switcher.tsx: '— Geen actieve sprint —'-optie
  in dropdown, disabled wanneer er geen actieve sprint is.
- Tests: nieuwe active-sprint.test.ts (resolver-paden + clear),
  active-sprint-action.test.ts (action-laag), uitbreiding user-settings.test.ts.

Plan: docs/plans/PBI-79-backlog-sprint-workflow.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 13:35:32 +02:00
Janpeter Visser
bf7162a5fc
feat(PBI-76): migrate cookie-based prefs to user-settings (Phase 2) (#189)
* feat(PBI-76): extend UserSettings schema with layout

Adds layout.splitPanePositions and layout.activeSprints. These will
hold values currently kept in client-side and server-side cookies
(Phase 2). Two new tests cover the shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(PBI-76): migrate SplitPane positions to user-settings store

Outside of a drag the store is the source of truth (cross-tab
updates flow in for free). During a drag we keep splits in local
state so mousemove does not round-trip through the store. On
mouseup we persist the final splits via setPref. Removes
document.cookie reads/writes — cookieKey is reused as the
store-key for backwards compat.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(PBI-76): resolveActiveSprint reads from User.settings

lib/active-sprint:
- New helpers: getActiveSprintIdFromSettings, setActiveSprintInSettings,
  clearActiveSprintInSettings — all read/write user.settings.layout.activeSprints.
- resolveActiveSprint(productId, userId) — userId now required, falls back
  to first OPEN, then most recent CLOSED sprint.
- Cookie helpers (getActiveSprintIdFromCookie/setActiveSprintCookie/
  clearActiveSprintCookie) removed.

Callers updated to pass session.userId. The cookie-based fallback path
is gone — `actions/active-sprint.ts` and `actions/sprints.ts` will be
updated in the next commit (T-917).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(PBI-76): rewrite setActiveSprint callers to use settings

setActiveSprintAction, syncActiveSprintCookieAction, and the two
sprint-creation paths in actions/sprints.ts now write through
setActiveSprintInSettings (which also emits pg_notify for cross-tab
sync) instead of dropping a cookie. The action names keep the
'cookie' suffix in the user-visible API for now — clean rename can
come later.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(PBI-76): migration helper v2 — handle legacy cookies

Bumps marker version to 'v2'. buildMigrationPatch now also scans
document.cookie for `sp:*` (split-pane positions) and
`active_sprint_*` (active sprint per product) and lifts them into
layout.splitPanePositions / layout.activeSprints. clearLegacyStorage
replaces clearLegacyLocalStorage and clears both keys and cookies.
clearLegacyLocalStorage stays as a deprecated alias so the bridge
upgrade is a single rename.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(PBI-76): align tests with new SplitPane and active-sprint flow

- split-pane.test.tsx: seed positions via Zustand store instead of
  document.cookie; mock @/actions/user-settings so the prisma client
  is not transitively initialised in jsdom.
- backlog-split-pane.test.tsx: same action mock.
- sprint-dates.test.ts: add user.findUnique/update + $executeRaw
  mocks because createSprintAction now writes to user-settings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 21:20:29 +02:00
Janpeter Visser
3842c05ae9
feat: sprint-switcher overal + PBI auto-toevoeging + cleanups (#163)
* refactor: verplaats sprint-switcher van NavBar naar product-header

Sprint-pulldown zit nu in de bestaande balk op de product backlog
(naast Sprint starten / Instellingen) i.p.v. in het midden van de
NavBar. Alleen zichtbaar wanneer het product ook het actieve product
van de gebruiker is.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: sync package-lock.json version naar 1.2.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: centreer sprint-switcher en verwijder badges uit dropdown items

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: vervang sprint-status badge door subtle tekst

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: toon code + titel + status in sprint-switcher dropdown items

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: cookie-write uit Server Component (Next.js 16 verbiedt dit)

setActiveSprintCookie werd direct aangeroepen in app/(app)/products/[id]/sprint/[sprintId]/page.tsx,
wat in Next.js 16 een runtime-error oplevert ('Cookies can only be modified in a Server Action
or Route Handler'). Vervangen door een client-side bridge die syncActiveSprintCookieAction
aanroept na mount, zodat de active-sprint cookie nog steeds gesynced blijft met de URL.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: filter 'toon afgeronde sprints' in sprint-switcher dropdown

Default verbergt de switcher gesloten/gearchiveerde/mislukte sprints
(toont alleen open + de huidige actieve sprint). Toggle bovenaan de
lijst om alle sprints te tonen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: nieuwe sprint wordt direct geselecteerd zonder redirect

createSprintAction zet nu de active-sprint cookie naar de zojuist
aangemaakte sprint, en de StartSprintButton refresht de huidige
pagina i.p.v. te redirecten naar /sprint. Resultaat: gebruiker blijft
op de product backlog en ziet de nieuwe sprint direct geselecteerd
in de sprint-pulldown.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: verplaats Manual en Admin naar user-menu dropdown

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: voeg geselecteerde PBI automatisch toe aan nieuwe sprint

Bij sprint-aanmaak wordt de pbi_id uit de selection-store als hidden
form-field meegestuurd. Server-side worden alle stories van die PBI
(zonder sprint) en hun taken aan de nieuwe sprint gekoppeld; stories
krijgen status IN_SPRINT met incrementele sort_order.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: sprint-switcher op solo- en sprint-board pagina's

Sprint-switcher is nu beschikbaar op de drie hoofdpagina's: product
backlog, solo board en sprint board. Allen renderen 'm in een
gecentreerde balk net onder de NavBar. Sprint-data via gedeelde helper
getSprintSwitcherData.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 02:32:50 +02:00
Janpeter Visser
4a9db57e94
feat(PBI-63): meerdere sprints per product + EXCLUDED + sprint-switcher (#161)
- Sprint lifecycle: ACTIVE→OPEN, COMPLETED→CLOSED, +ARCHIVED (FAILED behouden)
- TaskStatus: +EXCLUDED (overgeslagen door agent-loop via bestaande TO_DO filter)
- Cookie-gebaseerde actieve sprint per product (lib/active-sprint.ts)
- Route splitsen: /products/[id]/sprint/[sprintId] + /sprint redirect-page
- NavBar: gestapelde product/sprint dropdowns + BUILDING-badge derivatie
- Backlog selectie-modus + nieuwe-sprint-dialog (createSprintWithPbisAction)
- Migratie 20260507210000_sprint_lifecycle: ALTER TYPE RENAME (geen data-rewrite)
- Version bump 1.0.0 → 1.2.0

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 00:15:04 +02:00