feat(swift): implementeer AI-filtering psychiater voor overdracht (E5.S1)
E5.S1 compleet: AI filtert op behandelrelevantie voor psychiaters. Voortgang: 56 SP / 72 SP (78%) - Epic 5 in progress! Implementatie: - Twee-staps filtering: Server (include_in_handover=true) → AI (psychiater: behandelrelevant) - Role toggle UI: Verpleegkundige/Psychiater knoppen in OverdrachtBlock - buildSystemPrompt(role) functie met psychiater-specifieke filtering regels - filterForRole parameter toegevoegd aan GenerateOverdrachtSchema - API route verwerkt role parameter en stuurt door naar Claude AI Psychiater filtering regels: ✅ WEL RELEVANT: - Medicatie-issues: weigering, bijwerkingen, dosisaanpassingen - Stemming/gedrag: veranderingen, afwijkend gedrag, agitatie - Risico-signalen: suïcidaliteit, automutilatie, agressie - Psychotische symptomen: wanen, hallucinaties - Crisis/dwang: separatie, fixatie, dwangmedicatie - Afwijkende vitals: HH, LL met behandelimpact ❌ FILTER UIT: - Routine medicatie ("volgens schema", "zonder problemen") - ADL activiteiten (douchen, eten) tenzij significant afwijkend - Sociale activiteiten ("groepstherapie", "gesprek gehad") - Standaard observaties ("rustige dag", "geen bijzonderheden") - Routine vitals (normaal bereik, N interpretatie) - Dagstructuur ("dagprogramma gevolgd") UI/UX verbeteringen: - Role toggle met 2 knoppen (verpleegkundige/psychiater) - Visual hints: "Alle gemarkeerde items" vs "Behandelrelevante items" - Dynamic description tekst onder toggle - filterRole state + useCallback dependency update Files Changed: - lib/types/overdracht.ts: +1 line (filterForRole in schema) - lib/ai/overdracht-prompt.ts: +52 lines (buildSystemPrompt functie) - app/api/overdracht/generate/route.ts: +8/-8 lines (role parameter) - components/swift/blocks/overdracht-block.tsx: +43 lines (UI + logic) Technische details: - filterForRole default: 'verpleegkundige' - Psychiater max: 3 aandachtspunten, 2 actiepunten - Verpleegkundige max: 5 aandachtspunten, 3 actiepunten - Role parameter propageert van UI → API → Claude prompt Testing: - Build succesvol (pnpm build) - Geen nieuwe type errors - UI toggle functioneel Voortgang: 56 SP / 72 SP (78%) - E5.S1 compleet (5 SP) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -56,6 +56,7 @@ export function OverdrachtBlock({ prefill }: OverdrachtBlockProps) {
|
||||
const { toast } = useToast();
|
||||
|
||||
const [period, setPeriod] = useState<PeriodValue>('1d');
|
||||
const [filterRole, setFilterRole] = useState<'verpleegkundige' | 'psychiater'>('verpleegkundige');
|
||||
const [patients, setPatients] = useState<PatientOverzicht[]>([]);
|
||||
const [isLoadingPatients, setIsLoadingPatients] = useState(true);
|
||||
const [patientSummaries, setPatientSummaries] = useState<Map<string, PatientSummary>>(new Map());
|
||||
@@ -139,7 +140,7 @@ export function OverdrachtBlock({ prefill }: OverdrachtBlockProps) {
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ patientId, period }),
|
||||
body: JSON.stringify({ patientId, period, filterForRole: filterRole }),
|
||||
},
|
||||
{ operation: 'Overdracht genereren' }
|
||||
),
|
||||
@@ -182,7 +183,7 @@ export function OverdrachtBlock({ prefill }: OverdrachtBlockProps) {
|
||||
return updated;
|
||||
});
|
||||
}
|
||||
}, [period]);
|
||||
}, [period, filterRole]);
|
||||
|
||||
// Filter patients: if activePatient is set, only show that one
|
||||
const displayPatients = activePatient
|
||||
@@ -230,6 +231,44 @@ export function OverdrachtBlock({ prefill }: OverdrachtBlockProps) {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Role Filter Toggle */}
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-slate-700">Doelgroep</label>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setFilterRole('verpleegkundige')}
|
||||
className={cn(
|
||||
'px-3 py-2.5 rounded-lg text-sm font-medium transition-colors text-left',
|
||||
filterRole === 'verpleegkundige'
|
||||
? 'bg-slate-900 text-white border-2 border-slate-700'
|
||||
: 'bg-slate-50 text-slate-600 border border-slate-200 hover:bg-slate-100 hover:text-slate-900'
|
||||
)}
|
||||
>
|
||||
<div className="font-semibold">Verpleegkundige</div>
|
||||
<div className="text-xs opacity-80 mt-0.5">Alle gemarkeerde items</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setFilterRole('psychiater')}
|
||||
className={cn(
|
||||
'px-3 py-2.5 rounded-lg text-sm font-medium transition-colors text-left',
|
||||
filterRole === 'psychiater'
|
||||
? 'bg-slate-900 text-white border-2 border-slate-700'
|
||||
: 'bg-slate-50 text-slate-600 border border-slate-200 hover:bg-slate-100 hover:text-slate-900'
|
||||
)}
|
||||
>
|
||||
<div className="font-semibold">Psychiater</div>
|
||||
<div className="text-xs opacity-80 mt-0.5">Behandelrelevante items</div>
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-xs text-slate-500">
|
||||
{filterRole === 'psychiater'
|
||||
? 'AI filtert op behandelrelevantie voor psychiater'
|
||||
: 'Toont alle door verpleegkundige gemarkeerde items'}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Patients List */}
|
||||
{isLoadingPatients ? (
|
||||
<div className="flex items-center justify-center py-12">
|
||||
|
||||
Reference in New Issue
Block a user