# 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
```
### 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
fetchAppointments()}
showFallbackLink={true}
context="query"
/>
```
### 6. Dev-Only Technical Details
In development mode, shows collapsible technical details:
```tsx
{process.env.NODE_ENV === 'development' && (
Technische details (dev only)
{error.stack}
)}
```
---
## π 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
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 && (
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
// β Good - Context-specific error
```
### 3. Offer Retry When Possible
```typescript
// β Bad - No recovery path
// β Good - User can retry
refetchAppointments()}
/>
```
### 4. Use Inline Alerts for Forms
```typescript
// β Bad - Full-page error for form validation
// β Good - Inline alert in form
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)