* feat(user-settings): voeg IdeasListPrefs schema toe met filterStatuses Nieuw IdeasListPrefs-subschema met filterStatuses (array van IdeaStatusApi-waarden), ingehangen als views.ideasList in ViewsPrefs. Testdekking voor geldig, ongeldig en leeg filterStatuses. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: extraheer MultiFilterPills naar backlog-filter-popover Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ideas): voeg IdeasFilterPopover component toe Nieuwe client-component met multi-select statusfilter popover voor het Ideeënscherm; hergebruikt MultiFilterPills uit backlog-filter-popover. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ideas): vervang inline statuschips door IdeasFilterPopover met user-settings persistentie Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(ideas): voeg componenttests toe voor IdeasFilterPopover en persistentie Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ideas): voeg activeProductId-prop toe aan IdeaList IdeaListProps uitgebreid met activeProductId: string | null. Create-form initialiseert en reset naar het actieve product na aanmaken. Tests en page.tsx bijgewerkt (page.tsx krijgt echte waarde in volgende taak). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ideas): resolve active_product_id en geef door aan IdeaList Haalt active_product_id op via prisma.user.findUnique en resolveert het tegen de al opgehaalde toegankelijke productenlijst (AC4). Geeft het resultaat als prop door aan IdeaList in plaats van hardcoded null. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(ideas): stuur activeProductId mee bij snel idee aanmaken Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(ideas): voeg component-tests toe voor activeProductId-voorvulling AC1: "Nieuw idee"-select voorgevuld met activeProductId AC2: "Nieuw idee"-select leeg bij activeProductId=null AC3: "Snel idee" stuurt product_id=activeProductId mee bij createIdeaAction Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(notifications): toon textarea altijd in answer-modal naast opties Vervang opties-XOR-textarea door twee onafhankelijke blokken: opties alleen wanneer aanwezig, vrij tekstveld altijd zichtbaar. Bij opties een visuele scheiding (border-t) en label 'Of typ een eigen antwoord'. Verstuur-knop nu altijd in footer zichtbaar (was verborgen bij opties). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(notifications): gebruik question.options?.length als conditie Gebruik de kortere optional chaining variant consistent, conform plan. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(notifications): voeg component-tests toe voor AnswerModal Dekt: optieknoppen + textarea + Verstuur zichtbaar met opties, submit via optieknop, submit via vrij tekstveld, disabled Verstuur bij leeg veld, en demo-modus (textarea + Verstuur disabled). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs(notifications): werk answer-modal spec bij voor vrije tekstveld naast opties Beschrijft dat textarea + Verstuur altijd zichtbaar zijn in multiple-choice mode. Corrigeert de Cmd/Ctrl+Enter-bullet: shortcut werkt nu ook daar. Bijgewerkt naar 2026-05-15. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2.9 KiB
| title | status | audience | language | last_updated | ||
|---|---|---|---|---|---|---|
| AnswerModal Profiel | active |
|
nl | 2026-05-15 |
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 +answerQuestionactionANSWER_MAX_CHARSconstant — gebruikt door textarea + char-counter
URL- of state-pattern
- Gekozen: state-based —
question: NotificationQuestion | null-prop uitnotifications-sheet.
Server action
answerQuestion(questionId, answer)inactions/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
updateManyvoorkomt 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, worden de opties getoond als een lijst van knoppen. Klikken op een knop submit direct met die waarde. Het vrije tekstveld en de Verstuur-knop blijven altijd zichtbaar — ook in multiple-choice mode. Zo kan de gebruiker naast de vaste opties ook een eigen antwoord typen en versturen.
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 via
useDialogSubmitShortcutin zowel textarea-mode als multiple-choice mode (het vrije tekstveld is altijd aanwezig). - ❌ Bulk-answer — één vraag tegelijk per dialog.