Mission 4: Nächste Schritte vorbereiten
Planzeit: 5 Stunden. Achievement: A06 API Detektiv (125 XP) bei 4 von 4 Tests.
Ziel
Deine App spricht mit einer Schnittstelle und bleibt auch dann verständlich, wenn die Schnittstelle leer antwortet, abstürzt oder hängt. Das unterscheidet eine Arbeitsprobe von einem Prototyp.
Was du baust
src/components/FollowUpPanel.tsx: In der Detailansicht kann die Person Notizen zum
Gespräch eintippen und einen Follow-up-Entwurf anfordern. Die Anfrage geht an
api.createDraft(request, token). Die API ist ein Simulator (src/api/followUpApi.ts),
der je nach Modus Erfolg, eine leere Antwort, einen Serverfehler oder einen Timeout liefert.
Nichts wird an echte Kontakte gesendet.
Danach bindest du das Panel in LeadDetail oder App.tsx ein (api und token kommen aus App).
Der Vertrag mit den Tests
| Element | data-testid |
|---|---|
| Textfeld für Notizen | followup-notes |
| Button "Entwurf anfordern" | request-draft |
| Ladeanzeige während der Anfrage | draft-loading |
| Entwurfsvorschau bei Erfolg | draft-preview |
| Hinweis bei leerer Antwort | api-hint |
| Fehlermeldung bei Serverfehler oder Timeout | api-error |
| Button für neuen Versuch | retry-button |
| Meldung bei abgelehntem Token (Mission 5) | api-unauthorized |
| Kriterium | Was geprüft wird |
|---|---|
| C02-M4-01 | Erfolg: Nach Klick erscheint draft-preview mit dem Vornamen des Kontakts und den eingetippten Notizen. |
| C02-M4-02 | Leere Antwort (draft: ""): api-hint mit einem verständlichen Satz, keine draft-preview. |
| C02-M4-03 | Serverfehler: api-error erscheint und das Textfeld enthält weiterhin die Notizen. |
| C02-M4-04 | Timeout: api-error und retry-button; ein Klick auf retry-button ruft die API ein zweites Mal auf. |
Schritte
- Lies
src/api/followUpApi.tsmit deinem Agenten. Fragen: Was ist einPromise? Was bedeutetthrow new ApiError(...)? Welche vier Modi gibt es? - Zeichne auf Papier die Zustände des Panels: Ruhe, Laden, Entwurf da, leer, Fehler, nicht erlaubt. Jeder Zustand ist ein Bildschirm.
- Modelliere die Zustände als ein
state-Objekt mit einemkind-Feld statt mit fünf einzelnen booleans. Dein Agent kann dir zeigen, wie ein solcher "discriminated union"-Typ aussieht. - Baue zuerst den Erfolgsfall mit
try, danncatchfür die Fehler. Unterscheideerror.kind("server", "timeout", "unauthorized"). - Wichtig: Die Notizen leben in einem eigenen
useStateund werden im Fehlerfall nicht zurückgesetzt. - Probiere alle Modi im Browser aus: In
App.tsxkannst du vorübergehendcreateSimulatedApi("timeout", { latencyMs: 1500, timeoutMs: 2000 })einsetzen. Danach zurück auf"success". npm run bic -- check 4, Commit, KI-PROTOKOLL,npm run bic -- submit 4.
Typische Stolpersteine
awaitohnetry: Der Fehler landet in der Konsole, der Bildschirm friert im Ladezustand ein.- Die leere Antwort ist kein Fehler. Der Simulator liefert
{ draft: "" }ganz normal zurück. Du musst den Inhalt prüfen, nicht nur ob es geklappt hat. - Der Retry-Button ruft eine andere Funktion auf als der erste Button. Beide sollen dieselbe
requestDraft-Funktion verwenden.
Erklären
- Was ist der Unterschied zwischen "die Anfrage ist fehlgeschlagen" und "die Anfrage hat nichts geliefert"? Warum behandelt deine App beides verschieden?
- Warum darf eine App Eingaben nie verwerfen, nur weil ein Server einen Fehler hat?
Hinweise
missions/hints/04-1.md (Zustände modellieren), missions/hints/04-2.md (try und catch), missions/hints/04-3.md (Timeout und Retry).
Weiter mit missions/05-fehler-und-zugriff.md.