diff --git a/gerbil-manager-web/e2e/mock-data.ts b/gerbil-manager-web/e2e/mock-data.ts index 477dce6..6258a40 100644 --- a/gerbil-manager-web/e2e/mock-data.ts +++ b/gerbil-manager-web/e2e/mock-data.ts @@ -480,6 +480,29 @@ export function seedDb(): MockDb { { role: 'breeder', text: 'Im Juni.', at: '2026-06-13T18:00:00Z' }, ], }, + { + // Beantwortetes Ticket (Answered): die KI hat noch NICHT reagiert. Der Erst-Text ist + // jetzt gesperrt (kein „Bearbeiten"), nur die neueste Antwort ist noch änderbar. + id: 'feedback-answered', + message: 'Bei Karlsson stimmt der Farbschlag nicht.', + context: 'gerbil-detail', + gerbilId: 'karlsson', + litterId: null, + contactId: null, + entityName: 'Karlsson', + url: 'http://localhost:5173/rennmaeuse/karlsson', + clientTimestamp: '2026-06-16T09:00:00Z', + userAgent: null, + createdAt: '2026-06-16T09:00:00Z', + status: 'Answered', + resolvedAt: null, + question: 'Welcher Farbschlag ist korrekt?', + answer: 'Karlsson ist Blau, nicht Schwarz.', + answeredAt: '2026-06-16T18:00:00Z', + fixNote: null, + agentContext: null, + thread: [], + }, { id: 'feedback-open', message: 'Das Gewicht wird auf der Verlaufskurve falsch gerundet.', diff --git a/gerbil-manager-web/e2e/tickets.spec.ts b/gerbil-manager-web/e2e/tickets.spec.ts index 7585084..b166a1f 100644 --- a/gerbil-manager-web/e2e/tickets.spec.ts +++ b/gerbil-manager-web/e2e/tickets.spec.ts @@ -38,7 +38,8 @@ test.describe('Meine Tickets', () => { const open = page.locator('.tickets-filter').filter({ hasText: tt.filters.open }) const closed = page.locator('.tickets-filter').filter({ hasText: tt.filters.closed }) await expect(dialog.locator('.tickets-filter__count')).toHaveText('1') - await expect(open.locator('.tickets-filter__count')).toHaveText('1') + // „Offen" = Open + Answered → das offene + das beantwortete Ticket = 2. + await expect(open.locator('.tickets-filter__count')).toHaveText('2') await expect(closed.locator('.tickets-filter__count')).toHaveText('1') // „Offen": nur das offene Ticket. @@ -131,6 +132,20 @@ test.describe('Meine Tickets', () => { await expect(page.getByText('Korrigierte Beschreibung des Fehlers.')).toBeVisible() }) + test('beantwortetes Ticket: Erst-Text gesperrt, nur die neueste Antwort ist änderbar', async ({ + page, + }) => { + await page.goto('/hilfe/tickets') + // „Offen"-Ansicht (Default) zeigt auch beantwortete Tickets (Answered). + const card = page.locator('.ticket-card').filter({ hasText: 'Karlsson ist Blau' }) + await expect(card).toBeVisible() + + // Erst-Text ist gesperrt: kein „Bearbeiten"-Button mehr, sobald es eine Antwort gibt. + await expect(card.getByRole('button', { name: tt.edit })).toHaveCount(0) + // Die neueste Antwort ist dagegen noch änderbar (KI hat noch nicht reagiert → Answered). + await expect(card.getByRole('button', { name: tt.amendAnswer })).toBeVisible() + }) + test('Rückfrage beantworten: Züchterin sieht Frage, antwortet, Badge wird „Beantwortet"', async ({ page, }) => { diff --git a/gerbil-manager-web/src/pages/TicketsPage.tsx b/gerbil-manager-web/src/pages/TicketsPage.tsx index c526a36..9959791 100644 --- a/gerbil-manager-web/src/pages/TicketsPage.tsx +++ b/gerbil-manager-web/src/pages/TicketsPage.tsx @@ -535,9 +535,11 @@ function TicketCard({ ticket, onToggleStatus, onSaveMessage, onAnswer, onDelete const canAmend = !!ticket.answer && ticket.status === 'Answered' // Antwort-Formular zeigen: neue Antwort, aktives Ändern, oder ein gepufferter Änderungs-Entwurf. const showAnswerForm = canAnswerNew || answerEditing || (canAmend && !!answerDraft) - // Bearbeiten (Beschreibung) ist gesperrt, solange eine Rückfrage offen ist (NeedsInfo): - // dann soll die Züchterin ANTWORTEN, nicht den Text ändern. - const canEditMessage = ticket.status !== 'NeedsInfo' + // Der ursprüngliche Ticket-Text ist nur bearbeitbar, SOLANGE es noch keine Antwort gibt + // UND keine Rückfrage offen ist (NeedsInfo). Sobald die Züchterin geantwortet hat (oder die + // KI nachgefragt hat), bleibt der Erst-Text fix — editierbar ist dann nur noch die neueste + // Antwort (und auch die nur, bis die KI darauf reagiert hat, s. canAmend). + const canEditMessage = !ticket.answer && ticket.status !== 'NeedsInfo' function startAmend() { if (!answerDraft) setAnswerDraft(ticket.answer ?? '')