Story 5 van PBI "Alle dialogen conform docs/patterns/dialog.md". - lib/schemas/sprint.ts — gedeelde zod-schemas (create/dates/goal) - actions/sprints.ts — code+fieldErrors voor 422; code: 403 voor auth/demo errors - StartSprintButton dialog: useDirtyCloseGuard, useDialogSubmitShortcut, entityDialog* layout-classes; DemoTooltip op trigger; veld-niveau errors via fieldErrors - SprintHeader's date- en complete-dialogen: zelfde behandeling; date- dialog krijgt dirty-guard, complete-dialog krijgt DemoTooltip op bevestigen - docs/specs/dialogs/sprint.md — entity-profile dat alle drie de modes documenteert; consolidatie naar één SprintDialog component bewust uitgesteld - Sprint-dates tests aangepast aan nieuwe action-shape Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
72 lines
3.2 KiB
Markdown
72 lines
3.2 KiB
Markdown
---
|
|
title: "Sprint Dialogs Profiel"
|
|
status: active
|
|
audience: [ai-agent, contributor]
|
|
language: nl
|
|
last_updated: 2026-05-04
|
|
---
|
|
|
|
# Sprint Dialogs Profiel
|
|
|
|
> Volgt `docs/patterns/dialog.md`. Dit document beschrijft alleen de Sprint-specifieke afwijkingen en keuzes.
|
|
|
|
Sprint heeft drie dialog-flows verspreid over twee componenten:
|
|
|
|
| Flow | Locatie | Mode |
|
|
|---|---|---|
|
|
| Sprint starten | `components/sprint/start-sprint-button.tsx` | create |
|
|
| Datums bewerken | `components/sprint/sprint-header.tsx` (inline) | edit |
|
|
| Sprint afronden | `components/sprint/sprint-header.tsx` (inline) | actie-bevestiging |
|
|
|
|
Daarnaast bestaat een **inline edit-form** voor de Sprint Goal in `sprint-header.tsx` — dat is geen dialog (geen modale overlay) maar een toggleable form-row.
|
|
|
|
## Velden
|
|
|
|
### Create / Edit dates
|
|
|
|
| Veld | Type | Validatie |
|
|
|---|---|---|
|
|
| `sprint_goal` | string (alleen create) | min 1, max 500 |
|
|
| `start_date` | date \| null | optioneel; `end_date >= start_date` |
|
|
| `end_date` | date \| null | optioneel; `end_date >= start_date` |
|
|
|
|
### Complete sprint
|
|
|
|
Geen form-velden. Per story-rij in de sprint kiest de gebruiker `'DONE'` of `'OPEN'` (default `'OPEN'`). De decisions-map wordt direct aan `completeSprintAction` doorgegeven.
|
|
|
|
## URL- of state-pattern
|
|
|
|
- Gekozen: **state-based** (§11.2)
|
|
- Reden: alle dialogen zijn local-state in hun parent-component (button of header). Sprint heeft geen deep-link-bare detail-pagina voor zijn dialogen.
|
|
|
|
## Server actions
|
|
|
|
- `createSprintAction(_prev, fd)` — `actions/sprints.ts` — revalidate `/products/${productId}`
|
|
- `updateSprintDatesAction(_prev, fd)` — idem — revalidate `/products/${productId}/sprint`
|
|
- `updateSprintGoalAction(_prev, fd)` — idem — revalidate `/products/${productId}/sprint`
|
|
- `completeSprintAction(sprintId, decisions)` — niet form-based; directe argumenten
|
|
- Alle hebben `session.userId`-check, `session.isDemo`-check (laag 2 demo-policy) en `productAccessFilter`/`getAccessibleProduct` voor scope
|
|
- Resultaat-shape: `{ success: true, ... }` of `{ error: string, code?: 422|403, fieldErrors?: Record<string, string[]> }`
|
|
|
|
## Foutcodes
|
|
|
|
| Code | Wanneer | UI |
|
|
|---|---|---|
|
|
| 422 | zod-validatie of date-order constraint | `fieldErrors` onder de velden, geen toast |
|
|
| 403 | niet ingelogd, demo-modus, of geen toegang | toast met message |
|
|
|
|
## Schema
|
|
|
|
`lib/schemas/sprint.ts` exporteert:
|
|
- `createSprintSchema` — productId, sprint_goal, start_date, end_date
|
|
- `updateSprintDatesSchema` — id, start_date, end_date
|
|
- `updateSprintGoalSchema` — id, sprint_goal
|
|
- `validateDateOrder` — refinement gebruikt door beide date-schemas
|
|
|
|
Alle drie de actions importeren hier; geen inline schemas meer.
|
|
|
|
## Bewust NIET in v1
|
|
|
|
- ❌ **Eén consolideerde `SprintDialog`-component** met `mode: 'create' | 'edit-dates' | 'complete'` — overwogen tijdens story 5 maar niet uitgevoerd; de dialogen leven natuurlijker in hun parent-component (button / header) en worden niet hergebruikt elders. Indien een vierde sprint-dialog ontstaat, hernieuw deze afweging.
|
|
- ❌ Bewerken van de Sprint Goal vanuit deze dialogen — gebeurt via een inline-form in `sprint-header.tsx` (toggleable, geen modal)
|
|
- ❌ Sprint-templates / kopiëren van vorige sprint
|