feat(swift): Epic 5 Progress - Error Handling & Keyboard Shortcuts (E5.S2-S3)
Epic 5 deels compleet: Error handling en keyboard shortcuts geïmplementeerd. Voortgang: 62 SP / 72 SP (86%) - Nog 1 story voor MVP compleet! E5.S2 - Error Handling (2 SP) - Gecentraliseerde error handler utility (lib/swift/error-handler.ts) - isOffline(), isNetworkError(), getErrorInfo() functies - safeFetch() wrapper met 30s timeout en retry logic - retryFetch() met exponential backoff (max 3 retries) - User-friendly Nederlandse error messages voor alle HTTP status codes - OfflineBanner component met online/offline detection - Alle blocks en CommandInput gebruiken nieuwe error handler - Context bar margin adjustment voor offline banner - parseErrorResponse() voor HTML error detection E5.S3 - Keyboard Shortcuts (2 SP) - ⌘Enter / Ctrl+Enter quick submit in CommandInput - ⌘Enter / Ctrl+Enter quick save in DagnotatieBlock - Visual hints (⌘↵) op submit button in DagnotatieBlock - Geverifieerd: ⌘K focus, Escape close, 1-3 FallbackPicker - Cross-platform support (macOS + Windows/Linux) - preventDefault() voor browser conflict preventie Components Updated: - DagnotatieBlock: safeFetch, getErrorInfo, retryFetch, ⌘Enter save - OverdrachtBlock: safeFetch, retryFetch voor AI generation - ZoekenBlock: safeFetch, getErrorInfo voor patient search - CommandInput: safeFetch, getErrorInfo, ⌘Enter submit - CommandCenter: OfflineBanner integration - ContextBar: useOffline hook voor margin adjustment Nieuwe Files: - lib/swift/error-handler.ts (301 regels) - Error handling utilities - components/swift/command-center/offline-banner.tsx (72 regels) - docs/swift/keyboard-shortcuts-reference.md (200+ regels) - docs/swift/test-plan-e5-s2-error-handling.md (350+ regels) - docs/swift/test-plan-e5-s3-keyboard-shortcuts.md (350+ regels) - docs/swift/PROJECT-STATUS-2024-12-27.md (500+ regels) - Status report Documentatie: - Bouwplan bijgewerkt naar v2.5 - Epic completion details toegevoegd met progress bars - Manual test checklist bijgewerkt (17/20 scenarios) - Risico's sectie bijgewerkt (alle major risks gemitigeerd) - Sprint planning status: E5 75% compleet (6/8 SP) Technische verbeteringen: - Offline detection met visual feedback - Network error retry met exponential backoff - HTTP 401/404/500/503 error messages in Nederlands - Timeout protection (30s) op alle API calls - Keyboard shortcuts met visual hints - Cross-platform shortcut support Testing: - Error handling test plan met 8 categorieën - Keyboard shortcuts test plan met 6 categorieën - 40+ test scenarios gedocumenteerd - Quick smoke test checklists Voortgang: 62 SP / 72 SP (86%) - E5.S2 en E5.S3 compleet 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@ import { format } from 'date-fns';
|
||||
import { nl } from 'date-fns/locale/nl';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { safeFetch, getErrorInfo, retryFetch } from '@/lib/swift/error-handler';
|
||||
|
||||
interface OverdrachtBlockProps {
|
||||
prefill?: BlockPrefillData;
|
||||
@@ -64,10 +65,11 @@ export function OverdrachtBlock({ prefill }: OverdrachtBlockProps) {
|
||||
const fetchPatients = async () => {
|
||||
setIsLoadingPatients(true);
|
||||
try {
|
||||
const response = await fetch('/api/overdracht/patients');
|
||||
if (!response.ok) {
|
||||
throw new Error('Kon patiëntenlijst niet laden');
|
||||
}
|
||||
const response = await safeFetch(
|
||||
'/api/overdracht/patients',
|
||||
undefined,
|
||||
{ operation: 'Patiëntenlijst laden' }
|
||||
);
|
||||
const data = await response.json();
|
||||
setPatients(data.patients || []);
|
||||
|
||||
@@ -84,10 +86,15 @@ export function OverdrachtBlock({ prefill }: OverdrachtBlockProps) {
|
||||
setPatientSummaries(summaries);
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch patients:', error);
|
||||
const statusCode = (error as any)?.statusCode;
|
||||
const errorInfo = getErrorInfo(error, {
|
||||
operation: 'Patiëntenlijst laden',
|
||||
statusCode,
|
||||
});
|
||||
toast({
|
||||
variant: 'destructive',
|
||||
title: 'Laden mislukt',
|
||||
description: error instanceof Error ? error.message : 'Kon patiëntenlijst niet laden',
|
||||
title: errorInfo.title,
|
||||
description: errorInfo.description,
|
||||
});
|
||||
} finally {
|
||||
setIsLoadingPatients(false);
|
||||
@@ -125,16 +132,20 @@ export function OverdrachtBlock({ prefill }: OverdrachtBlockProps) {
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/overdracht/generate', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ patientId, period }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({ error: 'Genereren mislukt' }));
|
||||
throw new Error(errorData.error || 'Genereren mislukt');
|
||||
}
|
||||
const response = await retryFetch(
|
||||
() =>
|
||||
safeFetch(
|
||||
'/api/overdracht/generate',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ patientId, period }),
|
||||
},
|
||||
{ operation: 'Overdracht genereren' }
|
||||
),
|
||||
3,
|
||||
1000
|
||||
);
|
||||
|
||||
const summary: AISamenvatting = await response.json();
|
||||
|
||||
@@ -153,6 +164,11 @@ export function OverdrachtBlock({ prefill }: OverdrachtBlockProps) {
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to generate summary:', error);
|
||||
const statusCode = (error as any)?.statusCode;
|
||||
const errorInfo = getErrorInfo(error, {
|
||||
operation: 'Overdracht genereren',
|
||||
statusCode,
|
||||
});
|
||||
setPatientSummaries((prev) => {
|
||||
const updated = new Map(prev);
|
||||
const existing = updated.get(patientId);
|
||||
@@ -160,7 +176,7 @@ export function OverdrachtBlock({ prefill }: OverdrachtBlockProps) {
|
||||
updated.set(patientId, {
|
||||
...existing,
|
||||
loading: false,
|
||||
error: error instanceof Error ? error.message : 'Onbekende fout',
|
||||
error: errorInfo.description,
|
||||
});
|
||||
}
|
||||
return updated;
|
||||
|
||||
Reference in New Issue
Block a user