Scrum4Me/docs/specs/dialogs/answer-modal.md
Madhura68 4b0ab8e4b2 feat(answer-modal): conform aan dialog-pattern + entity-profile
Story 7 van PBI "Alle dialogen conform docs/patterns/dialog.md".

- lib/schemas/question-answer.ts — gedeeld zod-schema +
  ANSWER_MAX_CHARS constant
- actions/questions.ts gebruikt het gedeelde schema
- AnswerModal: entityDialog* layout-classes, useDirtyCloseGuard,
  useDialogSubmitShortcut, DemoTooltip rond submit + multiple-choice
  knoppen
- docs/specs/dialogs/answer-modal.md — entity-profile

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 07:34:56 +02:00

2.8 KiB

title status audience language last_updated
AnswerModal Profiel active
ai-agent
contributor
nl 2026-05-04

AnswerModal Profiel

Volgt docs/patterns/dialog.md. Beschrijft alleen de Q&A-specifieke afwijkingen.

Doel

Een Claude-agent vraagt tijdens een lopende job een verduidelijking aan de gebruiker. De vraag verschijnt als notification (bell + SSE event). Klik op de notification opent deze dialog waarin de gebruiker antwoordt — vrij tekst (max ANSWER_MAX_CHARS) of een keuze uit options als die meegegeven is.

Velden

Veld Type Mode Validatie
answer string both min 1, max ANSWER_MAX_CHARS (4000), trim

questionId komt uit de prop question.id, niet uit het formulier.

Schema

lib/schemas/question-answer.ts:

  • answerQuestionSchema — gedeeld door form + answerQuestion action
  • ANSWER_MAX_CHARS constant — gebruikt door textarea + char-counter

URL- of state-pattern

  • Gekozen: state-basedquestion: NotificationQuestion | null-prop uit notifications-sheet.

Server action

  • answerQuestion(questionId, answer) in actions/questions.ts
  • Result-shape: { ok: true } | { ok: false; error: string }
  • Demo-policy: session.isDemo-check in actie blokkeert demo-writes (laag 2). Laag 3 wordt verzorgd door <DemoTooltip> rond submit-knop en disabled-state op de textarea.
  • Atomic transition met updateMany voorkomt double-submit races.

Layout

Gebruikt entityDialogContentClasses (§4 spec). Body bevat naast de textarea ook de gestelde vraag (read-only block) en een link naar de bijbehorende sprint. Geen klassieke form-tag — de Textarea is een controlled component.

Speciale gedragingen

Multiple-choice mode

Als question.options niet leeg is, wordt de textarea vervangen door een lijst van knoppen. Klikken op een knop submit direct met die waarde. De submit-knop in de footer wordt dan verborgen (alleen Annuleren blijft).

Optimistic remove

Na succesvolle submit wordt de vraag direct uit useNotificationsStore verwijderd. De SSE-event komt later met dezelfde verwijdering — voorkomt extra render.

Dirty-tracking

Single-field form: dirty = answer.trim().length > 0. Esc/backdrop/Cancel met dirty-state opent de standaard guard.

Foutcodes

Action geeft alleen { ok, error: string } terug — geen 422-fieldErrors omdat het een single-field form is. Errors worden via toast getoond. Validatie (min 1, max 4000) wordt UI-side voorkomen via maxLength + submit-disable.

Bewust NIET in v1

  • Markdown rendering — antwoord wordt als plain text doorgegeven; Claude leest 'm direct als context.
  • Cmd/Ctrl+Enter shortcut — werkt wél voor de textarea-mode (via useDialogSubmitShortcut); voor multiple-choice mode is er geen submit om te triggeren.
  • Bulk-answer — één vraag tegelijk per dialog.