Files
triqura-ecd/docs/swift/implementation-e5-s3-error-states.md
colinislit 14a9d34337 feat(swift): voeg chat orchestration toe (E5)
Epic 5 compleet: Chat orchestration voor Swift Agenda Planning.
Alle agenda intents worden nu correct gerouteerd naar AgendaBlock
met user-friendly error handling en fallback opties.

E5.S1 - Action Routing (2 SP)
- routeIntentToArtifact() functie in action-parser
- Maps agenda intents naar juiste AgendaBlock mode
- Confidence threshold enforcement (< 0.7 → fallback)
- Required entity validation (patient voor create, identifier voor reschedule)
- Command-input gebruikt nieuwe routing ipv legacy openBlock
- Migratie naar modern artifact systeem (openArtifact)

E5.S2 - Chat Prompt Update (2 SP)
- 4 agenda intents toegevoegd aan Swift chat system prompt
- agenda_query: afspraken opvragen op datumrange
- create_appointment: nieuwe afspraak maken (required: patient, datetime)
- cancel_appointment: afspraak annuleren (disambiguation support)
- reschedule_appointment: afspraak verzetten (required: identifier)
- Entity extraction rules gedocumenteerd (dateRange, datetime, identifier)
- 4 complete voorbeelden met JSON action format
- Clarification questions voor incomplete data
- Prompt size: ~325 → ~525 regels (+60%)

E5.S3 - Error States (2 SP)
- AgendaErrorState component voor full-page errors
- AgendaErrorAlert component voor inline form errors
- getUserFriendlyMessage() vertaalt technical → user-friendly Dutch
- Auto-redirect bij auth errors (401 → /login)
- Fallback link naar /epd/agenda in alle error states
- Context-aware messaging (query/create/cancel/reschedule)
- Retry functionaliteit voor recoverable errors
- Dev-only technical details collapsible

Error message mapping:
- 401 → "Je sessie is verlopen. Log opnieuw in." + auto-redirect
- 403 → "Je hebt geen toegang tot deze afspraak."
- 404 → "De gevraagde afspraak kon niet worden gevonden."
- 500 → "Er ging iets mis op de server. Probeer het opnieuw."
- Network → "Geen internetverbinding. Controleer je netwerkverbinding."
- Timeout → "De aanvraag duurde te lang. Probeer het opnieuw."

Components updated:
- command-input: gebruikt routeIntentToArtifact + openArtifact
- agenda-create-form: gebruikt AgendaErrorAlert met fallback link
- chat/route: uitgebreide system prompt met agenda sectie

Nieuwe files:
- lib/swift/action-parser.ts: routeIntentToArtifact() functie
- components/swift/artifacts/blocks/agenda-error-state.tsx (225 regels)
- docs/swift/implementation-e5-s1-action-routing.md
- docs/swift/implementation-e5-s2-chat-prompt.md
- docs/swift/implementation-e5-s3-error-states.md

Documentatie:
- Bouwplan bijgewerkt: Epic 5 → Done
- 3 implementation docs met API specs en testing scenarios
- Error handling best practices gedocumenteerd

Progress: 48 SP / 51 SP (94%) - Epic 6 (QA) remaining

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 22:44:18 +01:00

400 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Epic 5.S3 Implementation: Error States
**Story**: E5.S3 - Error states
**Date**: 2025-12-27
**Status**: ✅ Complete
**Story Points**: 2 SP
---
## 🎯 Objective
Add user-friendly error states to agenda functionality with fallback links to `/epd/agenda` and proper error messaging in Dutch.
---
## 📝 Implementation Summary
### New Component Created
**`components/swift/artifacts/blocks/agenda-error-state.tsx`**
Created two reusable error components for consistent error handling across all agenda views:
1. **AgendaErrorState** - Full-page error state with retry button
2. **AgendaErrorAlert** - Inline error alert for forms
### Updated Components
**`components/swift/artifacts/blocks/agenda-create-form.tsx`**
- Replaced basic error display with `AgendaErrorAlert`
- Added fallback link to full agenda
- Added dismiss functionality
---
## 🔑 Key Features
### 1. User-Friendly Error Messages
The `getUserFriendlyMessage()` function maps technical errors to Dutch user-facing messages:
| Error Type | Technical | User Message |
|------------|-----------|--------------|
| **Auth (401)** | "401 Unauthorized" | "Je sessie is verlopen. Log opnieuw in." |
| **Not Found (404)** | "404 Not Found" | "De gevraagde afspraak kon niet worden gevonden." |
| **Forbidden (403)** | "403 Forbidden" | "Je hebt geen toegang tot deze afspraak." |
| **Server (500)** | "500 Internal Server Error" | "Er ging iets mis op de server. Probeer het opnieuw." |
| **Network** | "Failed to fetch" | "Geen internetverbinding. Controleer je netwerkverbinding." |
| **Timeout** | "Request timeout" | "De aanvraag duurde te lang. Probeer het opnieuw." |
### 2. Context-Aware Messages
Different default messages based on operation context:
```typescript
context: 'query' "Er ging iets mis bij het ophalen van je afspraken."
context: 'create' "Er ging iets mis bij het aanmaken van de afspraak."
context: 'cancel' "Er ging iets mis bij het annuleren van de afspraak."
context: 'reschedule' "Er ging iets mis bij het verzetten van de afspraak."
```
### 3. Fallback Link to Full Agenda
All error states include a prominent link to `/epd/agenda`:
```tsx
<Button onClick={() => window.location.href = '/epd/agenda'}>
<ExternalLink className="h-4 w-4" />
Open volledige agenda
</Button>
```
### 4. Automatic Auth Redirect
Auth errors (401) automatically redirect to `/login`:
```typescript
if (isAuthError) {
window.location.href = '/login';
return null;
}
```
### 5. Retry Functionality
Optional retry button for recoverable errors:
```tsx
<AgendaErrorState
error={error}
onRetry={() => fetchAppointments()}
showFallbackLink={true}
context="query"
/>
```
### 6. Dev-Only Technical Details
In development mode, shows collapsible technical details:
```tsx
{process.env.NODE_ENV === 'development' && (
<details>
<summary>Technische details (dev only)</summary>
<pre>{error.stack}</pre>
</details>
)}
```
---
## 📐 Component API
### AgendaErrorState (Full-Page Error)
```typescript
interface AgendaErrorStateProps {
error: string | Error; // Error to display
onRetry?: () => void; // Optional retry function
showFallbackLink?: boolean; // Show link to /epd/agenda (default: true)
context?: 'query' | 'create' | 'cancel' | 'reschedule';
}
```
**Usage Example**:
```tsx
<AgendaErrorState
error="Failed to fetch appointments"
onRetry={() => refetch()}
context="query"
/>
```
### AgendaErrorAlert (Inline Alert)
```typescript
interface AgendaErrorAlertProps {
error: string | Error; // Error to display
onDismiss?: () => void; // Optional dismiss function
showFallbackLink?: boolean; // Show link to /epd/agenda (default: false)
}
```
**Usage Example**:
```tsx
{error && (
<AgendaErrorAlert
error={error}
onDismiss={() => setError(null)}
showFallbackLink={true}
/>
)}
```
---
## ✅ Acceptance Criteria
| Criterion | Status | Implementation |
|-----------|--------|----------------|
| User-friendly error messages | ✅ | `getUserFriendlyMessage()` function |
| Dutch language errors | ✅ | All messages in Dutch |
| Fallback link to /epd/agenda | ✅ | "Open volledige agenda" button |
| Auth error redirect | ✅ | Automatic redirect to /login |
| Retry functionality | ✅ | Optional `onRetry` prop |
| Context-aware messages | ✅ | Different messages per operation type |
| Network error handling | ✅ | "Geen internetverbinding" message |
| Server error handling | ✅ | "Er ging iets mis op de server" message |
| TypeScript type safety | ✅ | Full type definitions |
| Consistent styling | ✅ | Matches existing UI patterns |
---
## 🎨 UI Design
### Full-Page Error State
```
┌─────────────────────────────────────┐
│ │
│ 🔴 (AlertCircle Icon) │
│ │
│ Er ging iets mis │
│ │
│ Er ging iets mis bij het │
│ ophalen van je afspraken. │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ 🔄 Probeer │ │ 🔗 Open │ │
│ │ opnieuw │ │ volledige │ │
│ └──────────────┘ │ agenda │ │
│ └──────────────┘ │
│ │
└─────────────────────────────────────┘
```
### Inline Error Alert
```
┌─────────────────────────────────────┐
│ ⚠️ Er ging iets mis bij het │
│ aanmaken van de afspraak. │
│ Open volledige agenda → [×] │
└─────────────────────────────────────┘
```
---
## 🧪 Testing Scenarios
### Scenario 1: Network Error
**Trigger**: Disconnect internet, try to create appointment
**Expected**:
- Message: "Geen internetverbinding. Controleer je netwerkverbinding."
- Retry button enabled
- Fallback link visible
### Scenario 2: Auth Error (401)
**Trigger**: Expired session token
**Expected**:
- Automatic redirect to `/login`
- No error component shown
### Scenario 3: Server Error (500)
**Trigger**: Backend returns 500
**Expected**:
- Message: "Er ging iets mis op de server. Probeer het opnieuw."
- Retry button enabled
- Fallback link visible
### Scenario 4: Not Found (404)
**Trigger**: Try to cancel non-existent appointment
**Expected**:
- Message: "De gevraagde afspraak kon niet worden gevonden."
- Fallback link visible
### Scenario 5: Validation Error
**Trigger**: Submit form with invalid data
**Expected**:
- Inline alert with specific validation message
- Fallback link visible
- Dismiss button works
### Scenario 6: Retry Success
**Trigger**: Network error → reconnect → click retry
**Expected**:
- Retry function called
- Error cleared on success
- Content loads normally
---
## 💡 Design Decisions
### Why Two Components?
1. **AgendaErrorState**: For full-page failures (query, list loading)
2. **AgendaErrorAlert**: For form-level errors (create, cancel, reschedule)
Different UI patterns for different contexts.
### Why Auto-Redirect for Auth Errors?
Auth errors (401) are not user-recoverable in the UI. User must log in again, so immediate redirect provides better UX than showing an error message.
### Why Show Fallback Link?
If Swift fails, users can always fall back to the classic agenda UI at `/epd/agenda`. This provides a safety net and reduces frustration.
### Why Context Parameter?
Different operations have different error messages. Context makes messages more specific and actionable:
- Query failure → "bij het ophalen"
- Create failure → "bij het aanmaken"
- etc.
### Why Dev-Only Technical Details?
Technical stack traces are only useful for developers debugging issues. Production users should see user-friendly messages only.
---
## 🚀 Error Handling Best Practices
### 1. Always Use getUserFriendlyMessage()
```typescript
// ❌ Bad - Technical error exposed to user
setError(error.message);
// ✅ Good - User-friendly Dutch message
const friendlyMessage = getUserFriendlyMessage(error, 'create');
setError(friendlyMessage);
```
### 2. Provide Context
```typescript
// ❌ Bad - Generic error
<AgendaErrorState error={error} />
// ✅ Good - Context-specific error
<AgendaErrorState error={error} context="query" />
```
### 3. Offer Retry When Possible
```typescript
// ❌ Bad - No recovery path
<AgendaErrorState error={error} />
// ✅ Good - User can retry
<AgendaErrorState
error={error}
onRetry={() => refetchAppointments()}
/>
```
### 4. Use Inline Alerts for Forms
```typescript
// ❌ Bad - Full-page error for form validation
<AgendaErrorState error="Patient required" />
// ✅ Good - Inline alert in form
<AgendaErrorAlert
error="Selecteer a.u.b. een patiënt."
onDismiss={() => setError(null)}
/>
```
---
## 📊 Error Message Coverage
Covered error types:
- ✅ Authentication (401)
- ✅ Authorization (403)
- ✅ Not Found (404)
- ✅ Server Error (500)
- ✅ Network/Offline
- ✅ Timeout
- ✅ Validation
- ✅ Generic/Unknown
All with Dutch user-friendly messages.
---
## 📁 Files Modified/Created
```
✅ components/swift/artifacts/blocks/agenda-error-state.tsx (NEW - 225 lines)
├── AgendaErrorState component
├── AgendaErrorAlert component
└── getUserFriendlyMessage() utility
✅ components/swift/artifacts/blocks/agenda-create-form.tsx (UPDATED)
└── Replaced basic error with AgendaErrorAlert
✅ docs/swift/bouwplan-swift-agenda-planning.md (UPDATED)
└── E5.S3 → Done, Epic 5 → Done
✅ docs/swift/implementation-e5-s3-error-states.md (NEW)
└── This documentation
```
---
## 🎯 Impact
### Before E5.S3
- ❌ Technical error messages exposed to users
- ❌ No fallback when errors occur
- ❌ No retry functionality
- ❌ Inconsistent error handling
### After E5.S3
- ✅ User-friendly Dutch error messages
- ✅ Always provide fallback link to full agenda
- ✅ Retry button for recoverable errors
- ✅ Consistent error handling across all views
- ✅ Auto-redirect for auth errors
- ✅ Context-aware messaging
---
## 🚀 Next Steps
**Epic 6 - QA & Docs**
- E6.S1: Manual test checklist (20 scenarios from build plan)
- E6.S2: Docs update (bouwplan + release note)
- E6.S3: Regression checks (Swift + klassieke agenda)
---
**Implementation Status**: ✅ Complete
**Epic 5 Status**: ✅ Complete (All 3 stories done)
**Ready for**: Epic 6 (QA & Documentation)