docs: add architecture and intake intent documentation

- Add architecture overview, implementation plan, and intent overview
- Add intake intent process specs (gap analyse, bouwplan, testplan)
- Add swift architecture specs and visualization prompts
- Remove obsolete aispeedrun-manifesto template

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
colinislit
2026-02-04 19:26:14 +01:00
parent 91b61d215b
commit af88ac9446
18 changed files with 6905 additions and 756 deletions

View File

@@ -0,0 +1,894 @@
# Cortex Block Template & Patterns
**Datum:** 03-02-2026
**Status:** Ontwerp
**Doel:** Herbruikbaar patroon voor alle intake-gerelateerde Cortex blocks
---
## 1. Anatomie van een Cortex Block
```
┌─────────────────────────────────────────────────────────────┐
│ [Icon] Titel [Close] │ ← Header (via BlockContainer)
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Loading State │ │ ← State: Loading
│ │ [Spinner] Data laden... │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Error State │ │ ← State: Error
│ │ [!] Foutmelding + [Retry] │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Empty State │ │ ← State: Empty
│ │ [Icon] Geen data + [Actie] │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Data State │ │ ← State: Data
│ │ │ │
│ │ Section 1: [Icon] Label │ │
│ │ ├── Item 1 │ │
│ │ └── Item 2 │ │
│ │ │ │
│ │ Section 2: [Icon] Label │ │
│ │ └── Content │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ───────────────────────────────────────────────────────── │
│ [Secondary Action] [Primary Action] │ ← Footer Actions
│ │
└─────────────────────────────────────────────────────────────┘
```
---
## 2. Block Types
### 2.1 Query Block (Read-only)
**Doel:** Data tonen, navigeren naar EPD voor bewerken
```typescript
// Voorbeeld: RisicoQueryBlock
// Input: "Wat zijn de risico's?"
// Output: Lijst risico's met levels
interface QueryBlockPattern {
// Data ophalen
fetch: () => Promise<Data>;
// Tonen
render: (data: Data) => JSX.Element;
// Navigatie
onViewInEPD: () => void; // "Bekijk in dossier"
}
```
### 2.2 Action Block (Create/Update)
**Doel:** Snelle invoer, bevestiging, opslaan
```typescript
// Voorbeeld: RisicoToevoegenBlock
// Input: "Risico suïcidaliteit matig"
// Output: Prefilled form, confirm, save
interface ActionBlockPattern {
// Prefill van intent entities
prefill: ExtractedEntities;
// Form state
form: FormState;
// Opslaan
onSubmit: () => Promise<void>;
// Bevestiging
confirmationRequired: boolean;
}
```
### 2.3 Status Block (Progress/Checklist)
**Doel:** Voortgang tonen, navigeren naar onvolledige items
```typescript
// Voorbeeld: IntakeStatusBlock
// Input: "Wat moet ik nog doen?"
// Output: Checklist met links
interface StatusBlockPattern {
// Status per onderdeel
status: Record<string, boolean>;
// Navigatie naar onderdeel
onNavigate: (section: string) => void;
}
```
### 2.4 Navigation Block (Route)
**Doel:** Direct navigeren naar EPD pagina
```typescript
// Voorbeeld: IntakeNavigatieBlock
// Input: "Ga naar diagnose"
// Output: Router.push() of openArtifact()
interface NavigationBlockPattern {
// Doel bepalen
destination: string;
// Navigeren
onNavigate: () => void;
}
```
---
## 3. Shared Components
### 3.1 Block States
```typescript
// components/cortex/shared/block-states.tsx
interface BlockLoadingProps {
message?: string;
}
export function BlockLoading({ message = 'Laden...' }: BlockLoadingProps) {
return (
<div className="flex items-center justify-center py-12">
<Loader2 className="h-6 w-6 animate-spin text-slate-400 mr-2" />
<span className="text-sm text-slate-500">{message}</span>
</div>
);
}
interface BlockErrorProps {
message: string;
onRetry?: () => void;
}
export function BlockError({ message, onRetry }: BlockErrorProps) {
return (
<div className="text-center py-8">
<AlertCircle className="h-8 w-8 text-red-500 mx-auto mb-2" />
<p className="text-sm text-red-700 mb-3">{message}</p>
{onRetry && (
<Button variant="outline" size="sm" onClick={onRetry}>
<RefreshCw className="h-4 w-4 mr-1.5" />
Opnieuw proberen
</Button>
)}
</div>
);
}
interface BlockEmptyProps {
icon: LucideIcon;
message: string;
action?: {
label: string;
onClick: () => void;
};
}
export function BlockEmpty({ icon: Icon, message, action }: BlockEmptyProps) {
return (
<div className="text-center py-8 text-slate-400">
<Icon className="h-8 w-8 mx-auto mb-2 opacity-50" />
<p className="text-sm">{message}</p>
{action && (
<Button variant="outline" size="sm" onClick={action.onClick} className="mt-3">
{action.label}
</Button>
)}
</div>
);
}
```
### 3.2 Block Section
```typescript
// components/cortex/shared/block-section.tsx
interface BlockSectionProps {
icon: LucideIcon;
iconColor?: string;
title: string;
count?: number;
children: ReactNode;
}
export function BlockSection({
icon: Icon,
iconColor = 'text-slate-600',
title,
count,
children
}: BlockSectionProps) {
return (
<section className="bg-white rounded-lg border border-slate-200 p-4">
<div className="flex items-center gap-2 mb-3">
<Icon className={cn('h-4 w-4', iconColor)} />
<h3 className="text-sm font-medium text-slate-700">{title}</h3>
{count !== undefined && (
<span className="text-xs text-slate-500">({count})</span>
)}
</div>
{children}
</section>
);
}
```
### 3.3 Block Item (List Row)
```typescript
// components/cortex/shared/block-item.tsx
interface BlockItemProps {
title: string;
subtitle?: string;
badge?: {
label: string;
variant: 'default' | 'success' | 'warning' | 'danger';
};
onClick?: () => void;
}
const BADGE_STYLES = {
default: 'bg-slate-100 text-slate-700',
success: 'bg-green-50 text-green-700',
warning: 'bg-amber-50 text-amber-700',
danger: 'bg-red-50 text-red-700',
};
export function BlockItem({ title, subtitle, badge, onClick }: BlockItemProps) {
const Wrapper = onClick ? 'button' : 'div';
return (
<Wrapper
onClick={onClick}
className={cn(
'flex items-center justify-between p-3 rounded-lg bg-slate-50 border border-slate-200 w-full text-left',
onClick && 'hover:bg-slate-100 cursor-pointer transition-colors'
)}
>
<div>
<p className="text-sm font-medium text-slate-900">{title}</p>
{subtitle && (
<p className="text-xs text-slate-500 mt-0.5">{subtitle}</p>
)}
</div>
{badge && (
<span className={cn(
'px-2 py-0.5 rounded-full text-xs font-medium',
BADGE_STYLES[badge.variant]
)}>
{badge.label}
</span>
)}
</Wrapper>
);
}
```
### 3.4 Block Footer
```typescript
// components/cortex/shared/block-footer.tsx
interface BlockFooterProps {
secondaryAction?: {
label: string;
icon?: LucideIcon;
onClick: () => void;
};
primaryAction?: {
label: string;
icon?: LucideIcon;
onClick: () => void;
loading?: boolean;
};
}
export function BlockFooter({ secondaryAction, primaryAction }: BlockFooterProps) {
return (
<div className="flex items-center justify-between pt-4 border-t border-slate-200 mt-4">
{secondaryAction ? (
<Button variant="ghost" size="sm" onClick={secondaryAction.onClick}>
{secondaryAction.icon && <secondaryAction.icon className="h-4 w-4 mr-1.5" />}
{secondaryAction.label}
</Button>
) : <div />}
{primaryAction && (
<Button
size="sm"
onClick={primaryAction.onClick}
disabled={primaryAction.loading}
>
{primaryAction.loading ? (
<Loader2 className="h-4 w-4 mr-1.5 animate-spin" />
) : primaryAction.icon ? (
<primaryAction.icon className="h-4 w-4 mr-1.5" />
) : null}
{primaryAction.label}
</Button>
)}
</div>
);
}
```
---
## 4. Custom Hook Pattern
### 4.1 useBlockData (Generic Data Fetching)
```typescript
// lib/cortex/hooks/use-block-data.ts
interface UseBlockDataOptions<T> {
endpoint: string;
params?: Record<string, string>;
enabled?: boolean;
onError?: (error: Error) => void;
}
interface UseBlockDataResult<T> {
data: T | null;
isLoading: boolean;
error: string | null;
refetch: () => Promise<void>;
}
export function useBlockData<T>({
endpoint,
params,
enabled = true,
onError,
}: UseBlockDataOptions<T>): UseBlockDataResult<T> {
const [data, setData] = useState<T | null>(null);
const [isLoading, setIsLoading] = useState(enabled);
const [error, setError] = useState<string | null>(null);
const { toast } = useToast();
const fetchData = useCallback(async () => {
setIsLoading(true);
setError(null);
try {
const url = new URL(endpoint, window.location.origin);
if (params) {
Object.entries(params).forEach(([key, value]) => {
url.searchParams.set(key, value);
});
}
const response = await safeFetch(url.toString());
const result = await response.json();
setData(result);
} catch (err) {
const errorInfo = getErrorInfo(err);
setError(errorInfo.description);
onError?.(err as Error);
toast({
variant: 'destructive',
title: errorInfo.title,
description: errorInfo.description,
});
} finally {
setIsLoading(false);
}
}, [endpoint, params, onError, toast]);
useEffect(() => {
if (enabled) {
fetchData();
}
}, [enabled, fetchData]);
return { data, isLoading, error, refetch: fetchData };
}
```
### 4.2 useIntakeContext (Intake-specific)
```typescript
// lib/cortex/hooks/use-intake-context.ts
interface UseIntakeContextResult {
patientId: string | null;
intakeId: string | null;
patientName: string | null;
hasContext: boolean;
}
export function useIntakeContext(prefill?: BlockPrefillData): UseIntakeContextResult {
const { activePatient } = useCortexStore();
// TODO: Add activeIntake to cortex-store
// For now, we need intakeId from prefill or URL
const patientId = prefill?.patientId || activePatient?.id || null;
const patientName = prefill?.patientName ||
(activePatient ? formatPatientName(activePatient) : null);
const intakeId = prefill?.intakeId || null;
return {
patientId,
intakeId,
patientName,
hasContext: Boolean(patientId),
};
}
```
---
## 5. Template: Query Block
```typescript
// components/cortex/blocks/[name]-query-block.tsx
'use client';
/**
* [Name] Query Block
*
* Block voor het tonen van [beschrijving].
* Intent: [intent_name]
*/
import { useEffect } from 'react';
import { useCortexStore } from '@/stores/cortex-store';
import { useToast } from '@/hooks/use-toast';
import { BlockContainer } from './block-container';
import { BlockLoading, BlockError, BlockEmpty } from '../shared/block-states';
import { BlockSection } from '../shared/block-section';
import { BlockItem } from '../shared/block-item';
import { BlockFooter } from '../shared/block-footer';
import { useBlockData } from '@/lib/cortex/hooks/use-block-data';
import { useIntakeContext } from '@/lib/cortex/hooks/use-intake-context';
import type { BlockPrefillData } from '@/stores/cortex-store';
import { BLOCK_CONFIGS } from '@/lib/cortex/types';
import { [Icon], ExternalLink } from 'lucide-react';
// ============================================================================
// Types
// ============================================================================
interface [Name]QueryBlockProps {
prefill?: BlockPrefillData;
}
interface [Name]Data {
items: Array<{
id: string;
// ... fields
}>;
}
// ============================================================================
// Component
// ============================================================================
export function [Name]QueryBlock({ prefill }: [Name]QueryBlockProps) {
const config = BLOCK_CONFIGS['[block-type]'];
const { closeBlock } = useCortexStore();
const { patientId, intakeId, patientName, hasContext } = useIntakeContext(prefill);
// Fetch data
const { data, isLoading, error, refetch } = useBlockData<[Name]Data>({
endpoint: `/api/cortex/intake/${intakeId}/[endpoint]`,
enabled: Boolean(intakeId),
});
// Handle no context
if (!hasContext) {
return (
<BlockContainer title={config.title} size={config.size}>
<BlockEmpty
icon={[Icon]}
message="Selecteer eerst een patiënt"
/>
</BlockContainer>
);
}
// Handle loading
if (isLoading) {
return (
<BlockContainer title={config.title} size={config.size}>
<BlockLoading message="[Name] laden..." />
</BlockContainer>
);
}
// Handle error
if (error) {
return (
<BlockContainer title={config.title} size={config.size}>
<BlockError message={error} onRetry={refetch} />
</BlockContainer>
);
}
// Handle empty
if (!data?.items?.length) {
return (
<BlockContainer title={config.title} size={config.size}>
<BlockEmpty
icon={[Icon]}
message="Geen [items] gevonden"
action={{
label: 'Toevoegen in dossier',
onClick: () => {
// Navigate to EPD
window.location.href = `/epd/patients/${patientId}/intakes/${intakeId}/[tab]`;
},
}}
/>
</BlockContainer>
);
}
// Render data
return (
<BlockContainer title={config.title} size={config.size}>
<div className="space-y-4">
<BlockSection icon={[Icon]} iconColor="text-[color]-600" title="[Section Title]" count={data.items.length}>
<div className="space-y-2">
{data.items.map((item) => (
<BlockItem
key={item.id}
title={item.title}
subtitle={item.subtitle}
badge={{
label: item.status,
variant: getBadgeVariant(item.status),
}}
/>
))}
</div>
</BlockSection>
<BlockFooter
secondaryAction={{
label: 'Bekijk in dossier',
icon: ExternalLink,
onClick: () => {
window.location.href = `/epd/patients/${patientId}/intakes/${intakeId}/[tab]`;
},
}}
primaryAction={{
label: 'Toevoegen',
onClick: () => {
// Open action block or navigate
},
}}
/>
</div>
</BlockContainer>
);
}
// ============================================================================
// Helpers
// ============================================================================
function getBadgeVariant(status: string): 'default' | 'success' | 'warning' | 'danger' {
switch (status) {
case 'laag': return 'success';
case 'gemiddeld': return 'warning';
case 'hoog':
case 'zeer_hoog': return 'danger';
default: return 'default';
}
}
```
---
## 6. Template: Status Block
```typescript
// components/cortex/blocks/intake-status-block.tsx
'use client';
/**
* Intake Status Block
*
* Block voor het tonen van intake voortgang/checklist.
* Intent: intake_status
*/
import { useCortexStore } from '@/stores/cortex-store';
import { BlockContainer } from './block-container';
import { BlockLoading, BlockError, BlockEmpty } from '../shared/block-states';
import { useBlockData } from '@/lib/cortex/hooks/use-block-data';
import { useIntakeContext } from '@/lib/cortex/hooks/use-intake-context';
import type { BlockPrefillData } from '@/stores/cortex-store';
import { BLOCK_CONFIGS } from '@/lib/cortex/types';
import {
CheckCircle2,
Circle,
ClipboardList,
ChevronRight,
} from 'lucide-react';
import { cn } from '@/lib/utils';
// ============================================================================
// Types
// ============================================================================
interface IntakeStatusBlockProps {
prefill?: BlockPrefillData;
}
interface IntakeStatusData {
intakeId: string;
intakeTitle: string;
completedCount: number;
totalCount: number;
sections: Array<{
key: string;
label: string;
completed: boolean;
required: boolean;
path: string;
}>;
}
// ============================================================================
// Constants
// ============================================================================
const SECTION_ORDER = [
{ key: 'algemeen', label: 'Algemeen', required: true },
{ key: 'contactmomenten', label: 'Contactmomenten', required: false },
{ key: 'kindcheck', label: 'Kindcheck', required: true },
{ key: 'risicotaxatie', label: 'Risicotaxatie', required: true },
{ key: 'anamnese', label: 'Anamnese', required: true },
{ key: 'onderzoeken', label: 'Onderzoeken', required: false },
{ key: 'rom', label: 'ROM', required: false },
{ key: 'diagnose', label: 'Diagnose', required: true },
{ key: 'behandeladvies', label: 'Behandeladvies', required: true },
];
// ============================================================================
// Component
// ============================================================================
export function IntakeStatusBlock({ prefill }: IntakeStatusBlockProps) {
const config = BLOCK_CONFIGS['intake-status']; // Need to add this
const { patientId, intakeId, hasContext } = useIntakeContext(prefill);
const { data, isLoading, error, refetch } = useBlockData<IntakeStatusData>({
endpoint: `/api/cortex/intake/${intakeId}/status`,
enabled: Boolean(intakeId),
});
if (!hasContext) {
return (
<BlockContainer title="Intake Status" size="md">
<BlockEmpty
icon={ClipboardList}
message="Selecteer eerst een patiënt met een actieve intake"
/>
</BlockContainer>
);
}
if (isLoading) {
return (
<BlockContainer title="Intake Status" size="md">
<BlockLoading message="Status laden..." />
</BlockContainer>
);
}
if (error) {
return (
<BlockContainer title="Intake Status" size="md">
<BlockError message={error} onRetry={refetch} />
</BlockContainer>
);
}
if (!data) {
return (
<BlockContainer title="Intake Status" size="md">
<BlockEmpty
icon={ClipboardList}
message="Geen actieve intake gevonden"
/>
</BlockContainer>
);
}
const progress = Math.round((data.completedCount / data.totalCount) * 100);
const incompleteSections = data.sections.filter(s => !s.completed && s.required);
return (
<BlockContainer title={`Intake Status - ${data.intakeTitle}`} size="md">
<div className="space-y-4">
{/* Progress Bar */}
<div className="space-y-2">
<div className="flex items-center justify-between text-sm">
<span className="text-slate-600">Voortgang</span>
<span className="font-medium text-slate-900">
{data.completedCount}/{data.totalCount} ({progress}%)
</span>
</div>
<div className="h-2 bg-slate-100 rounded-full overflow-hidden">
<div
className={cn(
'h-full rounded-full transition-all',
progress === 100 ? 'bg-green-500' : 'bg-teal-500'
)}
style={{ width: `${progress}%` }}
/>
</div>
</div>
{/* Incomplete Items (priority) */}
{incompleteSections.length > 0 && (
<div className="p-3 bg-amber-50 border border-amber-200 rounded-lg">
<p className="text-sm font-medium text-amber-800 mb-2">
Nog te voltooien ({incompleteSections.length})
</p>
<div className="space-y-1">
{incompleteSections.map((section) => (
<button
key={section.key}
onClick={() => {
window.location.href = `/epd/patients/${patientId}/intakes/${intakeId}/${section.path}`;
}}
className="flex items-center justify-between w-full p-2 rounded hover:bg-amber-100 transition-colors text-left"
>
<span className="text-sm text-amber-900">{section.label}</span>
<ChevronRight className="h-4 w-4 text-amber-600" />
</button>
))}
</div>
</div>
)}
{/* All Sections */}
<div className="space-y-1">
{data.sections.map((section) => (
<button
key={section.key}
onClick={() => {
window.location.href = `/epd/patients/${patientId}/intakes/${intakeId}/${section.path}`;
}}
className={cn(
'flex items-center justify-between w-full p-3 rounded-lg border transition-colors text-left',
section.completed
? 'bg-green-50 border-green-200 hover:bg-green-100'
: 'bg-slate-50 border-slate-200 hover:bg-slate-100'
)}
>
<div className="flex items-center gap-3">
{section.completed ? (
<CheckCircle2 className="h-5 w-5 text-green-600" />
) : (
<Circle className="h-5 w-5 text-slate-400" />
)}
<span className={cn(
'text-sm',
section.completed ? 'text-green-900' : 'text-slate-700'
)}>
{section.label}
</span>
{section.required && !section.completed && (
<span className="text-xs px-1.5 py-0.5 bg-red-100 text-red-700 rounded">
Verplicht
</span>
)}
</div>
<ChevronRight className={cn(
'h-4 w-4',
section.completed ? 'text-green-600' : 'text-slate-400'
)} />
</button>
))}
</div>
{/* Complete Message */}
{progress === 100 && (
<div className="p-3 bg-green-50 border border-green-200 rounded-lg text-center">
<CheckCircle2 className="h-6 w-6 text-green-600 mx-auto mb-2" />
<p className="text-sm font-medium text-green-800">
Intake is compleet!
</p>
<p className="text-xs text-green-600 mt-1">
Je kunt de intake nu afsluiten
</p>
</div>
)}
</div>
</BlockContainer>
);
}
```
---
## 7. Checklist voor nieuwe Block
Bij het bouwen van een nieuwe block:
- [ ] **Types definiëren** - Props interface, Data interface
- [ ] **Intent toevoegen** aan `lib/cortex/types.ts`
- [ ] **Patterns toevoegen** aan `lib/cortex/reflex-classifier.ts`
- [ ] **Block config toevoegen** aan `BLOCK_CONFIGS`
- [ ] **API route maken** (indien nodig) in `app/api/cortex/`
- [ ] **Block component bouwen** met shared components
- [ ] **Canvas-area updaten** om block te renderen
- [ ] **Testen** met voice input en prefill
---
## 8. Bestandsstructuur
```
components/cortex/
├── blocks/
│ ├── block-container.tsx # Wrapper (bestaat)
│ ├── dagnotitie-block.tsx # Bestaat
│ ├── zoeken-block.tsx # Bestaat
│ ├── overdracht-block.tsx # Bestaat
│ ├── patient-dashboard-block.tsx # Bestaat
│ │
│ ├── # NIEUW - Intake Blocks
│ ├── intake-status-block.tsx # Checklist
│ ├── risico-query-block.tsx # Risico's tonen
│ ├── diagnose-query-block.tsx # Diagnoses tonen
│ ├── kindcheck-query-block.tsx # Kindcheck status
│ └── screening-query-block.tsx # Screening overzicht
├── shared/
│ ├── patient-list-item.tsx # Bestaat
│ ├── linked-evidence.tsx # Bestaat
│ │
│ ├── # NIEUW - Shared Block Components
│ ├── block-states.tsx # Loading/Error/Empty
│ ├── block-section.tsx # Section wrapper
│ ├── block-item.tsx # List item
│ └── block-footer.tsx # Footer actions
lib/cortex/
├── hooks/
│ ├── use-patient-search.ts # Bestaat
│ ├── use-patient-selection.ts # Bestaat
│ │
│ ├── # NIEUW
│ ├── use-block-data.ts # Generic data fetching
│ └── use-intake-context.ts # Intake context
```
---
## 9. Volgende Stappen
1. **Shared components bouwen** (`block-states.tsx`, etc.)
2. **Hooks bouwen** (`use-block-data.ts`, `use-intake-context.ts`)
3. **Eerste block:** `IntakeStatusBlock` (meest waardevolle quick win)
4. **API route:** `/api/cortex/intake/[id]/status`
5. **Intent + patterns** toevoegen voor `intake_status`

View File

@@ -0,0 +1,365 @@
# 🚀 Mission Control — Bouwplan Cortex Shared Components
**Projectnaam:** Cortex Intake Intent System - Shared Components
**Versie:** v1.0
**Datum:** 03-02-2026
**Auteur:** Colin Lit
---
## 1. Doel en Context
🎯 **Doel:**
Bouwen van herbruikbare shared components en hooks voor alle Cortex Intake Blocks. Deze componenten vormen de foundation voor de intake-gerelateerde intents.
📘 **Context:**
De Cortex Command Center heeft momenteel 7 werkende intents, maar geen van de 26 intake-gerelateerde intents is geïmplementeerd. De shared components zijn de eerste stap om dit te realiseren. Ze worden hergebruikt door alle nieuwe intake blocks.
**Relatie met andere documenten:**
| Document | Relatie |
|----------|---------|
| `fo-to-cortex-shared-components.md` | Functionele en technische specificaties |
| `intake-process-intents.md` | Intent definities die deze components gebruiken |
| `gap-analyse-intake-cortex.md` | Identificeert de behoefte aan deze components |
---
## 2. Uitgangspunten
### 2.1 Technische Stack
| Component | Technologie | Reden |
|-----------|-------------|-------|
| **Framework** | Next.js 14 (App Router) | Bestaande stack |
| **UI Library** | React 18 + TypeScript | Type safety, DX |
| **Styling** | Tailwind CSS | Utility-first, consistent met project |
| **Icons** | Lucide React | Bestaande icon library |
| **Components** | shadcn/ui | Button, etc. al in gebruik |
| **State** | Zustand (cortex-store) | Bestaande state management |
| **Animations** | Framer Motion | Optioneel, al in project |
### 2.2 Projectkaders
| Kader | Waarde |
|-------|--------|
| **Tijd** | 1 dag bouwtijd |
| **Scope** | 4 components + 2 hooks |
| **Team** | 1 developer |
| **Data** | Geen nieuwe data, alleen UI |
| **Doel** | Foundation voor intake blocks |
### 2.3 Programmeer Uitgangspunten
**Code Quality Principles:**
- **DRY** - Herbruikbare components en utility functions
- **KISS** - Eenvoudige oplossingen, geen premature optimization
- **SOC** - UI gescheiden van business logic, hooks voor data
- **YAGNI** - Alleen bouwen wat nu nodig is
**Development Practices:**
- TypeScript strict mode
- Props interfaces geëxporteerd voor hergebruik
- Consistente naamgeving (`Block*` prefix)
- JSDoc comments voor public API
- Tree-shakeable exports via index.ts
---
## 3. Epics & Stories Overzicht
| Epic ID | Titel | Doel | Status | Stories | Geschat |
|---------|-------|------|--------|---------|---------|
| E0 | Block States | Loading/Error/Empty states | ⏳ To Do | 3 | 2 uur |
| E1 | Block Layout | Section/Item/Footer components | ⏳ To Do | 3 | 2 uur |
| E2 | Custom Hooks | Data fetching en context hooks | ⏳ To Do | 2 | 2 uur |
| E3 | Integration | Exports en documentatie | ⏳ To Do | 2 | 1 uur |
**Totaal geschat:** ~7 uur (1 werkdag)
---
## 4. Epics & Stories (Uitwerking)
### Epic 0 — Block States
**Epic Doel:** Consistente states voor alle blocks (loading, error, empty).
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | SP |
|----------|--------------|---------------------|--------|------------------|----|
| E0.S1 | `BlockLoading` component | Spinner + message, centered, animatie | ⏳ | — | 1 |
| E0.S2 | `BlockError` component | Error icon + message + retry button | ⏳ | — | 1 |
| E0.S3 | `BlockEmpty` component | Custom icon + message + action button | ⏳ | — | 1 |
**Technical Notes:**
```typescript
// Verwachte exports
export { BlockLoading } from './block-states';
export { BlockError } from './block-states';
export { BlockEmpty } from './block-states';
```
**Acceptatiecriteria E0:**
- [ ] Alle 3 states renderen correct
- [ ] Props zijn fully typed met interfaces
- [ ] Responsive op alle block sizes (sm/md/lg)
- [ ] Consistent met bestaande design (slate colors, tailwind)
---
### Epic 1 — Block Layout
**Epic Doel:** Herbruikbare layout components voor block content.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | SP |
|----------|--------------|---------------------|--------|------------------|----|
| E1.S1 | `BlockSection` component | Icon + title + count + children wrapper | ⏳ | — | 1 |
| E1.S2 | `BlockItem` component | Title + subtitle + badge, clickable optie | ⏳ | — | 2 |
| E1.S3 | `BlockFooter` component | Secondary + primary action buttons | ⏳ | E1.S2 | 1 |
**Technical Notes:**
```typescript
// Badge variants voor BlockItem
type BadgeVariant = 'default' | 'success' | 'warning' | 'danger';
// Helper functie
export function getRiskBadgeVariant(level: string): BadgeVariant;
```
**Acceptatiecriteria E1:**
- [ ] Section toont icon met configureerbare kleur
- [ ] Item is klikbaar wanneer onClick meegegeven
- [ ] Item hover state alleen bij klikbaar
- [ ] Footer acties correct aligned (left/right)
- [ ] Footer toont loading spinner op primary action
---
### Epic 2 — Custom Hooks
**Epic Doel:** Hooks voor data fetching en context management.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | SP |
|----------|--------------|---------------------|--------|------------------|----|
| E2.S1 | `useBlockData` hook | Generic fetch met loading/error states, refetch | ⏳ | error-handler.ts | 3 |
| E2.S2 | `useIntakeContext` hook | Patient + Intake context van store/prefill | ⏳ | cortex-store | 2 |
**Technical Notes:**
```typescript
// useBlockData interface
interface UseBlockDataResult<T> {
data: T | null;
isLoading: boolean;
error: string | null;
refetch: () => Promise<void>;
}
// useIntakeContext interface
interface UseIntakeContextResult {
patientId: string | null;
intakeId: string | null;
patientName: string | null;
hasPatientContext: boolean;
hasIntakeContext: boolean;
}
```
**Acceptatiecriteria E2:**
- [ ] useBlockData handelt errors via bestaande error-handler
- [ ] useBlockData toont toast bij error
- [ ] useBlockData supported enabled flag voor conditional fetching
- [ ] useIntakeContext valt terug op activePatient uit store
- [ ] useIntakeContext is memoized om re-renders te voorkomen
---
### Epic 3 — Integration
**Epic Doel:** Exports, documentatie en integratie met bestaande code.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | SP |
|----------|--------------|---------------------|--------|------------------|----|
| E3.S1 | Index exports | Barrel file met alle exports | ⏳ | E0, E1, E2 | 1 |
| E3.S2 | Update bestaande blocks | Refactor ZoekenBlock naar shared components | ⏳ | E3.S1 | 2 |
**Technical Notes:**
```typescript
// components/cortex/shared/index.ts
// Block States
export { BlockLoading, BlockError, BlockEmpty } from './block-states';
// Block Layout
export { BlockSection } from './block-section';
export { BlockItem, getRiskBadgeVariant, type BadgeVariant } from './block-item';
export { BlockFooter } from './block-footer';
// Existing (unchanged)
export { PatientListItem, PatientListEmpty, PatientListLoading } from './patient-list-item';
export { LinkedEvidence } from './linked-evidence';
```
**Acceptatiecriteria E3:**
- [ ] Alle components importeerbaar via `@/components/cortex/shared`
- [ ] Hooks importeerbaar via `@/lib/cortex/hooks`
- [ ] Geen breaking changes voor bestaande code
- [ ] ZoekenBlock werkt nog na refactor (smoke test)
---
## 5. Implementatie Volgorde
```
E0.S1 BlockLoading ──┐
E0.S2 BlockError ──┼──▶ E0 Complete
E0.S3 BlockEmpty ──┘
E1.S1 BlockSection ──┐ │
E1.S2 BlockItem ──┼──▶ E1 Complete
E1.S3 BlockFooter ──┘ │
E2.S1 useBlockData ──┬──▶ E2 Complete
E2.S2 useIntakeContext ──┘ │
E3.S1 Index exports ──┬──▶ E3 Complete ──▶ ✅ DONE
E3.S2 Refactor test ──┘
```
---
## 6. Bestandsstructuur (Deliverables)
```
components/cortex/shared/
├── block-states.tsx 🆕 E0.S1-S3
├── block-section.tsx 🆕 E1.S1
├── block-item.tsx 🆕 E1.S2
├── block-footer.tsx 🆕 E1.S3
├── index.ts 🆕 E3.S1 (update)
├── patient-list-item.tsx ✅ Bestaat
└── linked-evidence.tsx ✅ Bestaat
lib/cortex/hooks/
├── use-block-data.ts 🆕 E2.S1
├── use-intake-context.ts 🆕 E2.S2
├── use-patient-search.ts ✅ Bestaat
└── use-patient-selection.ts ✅ Bestaat
```
---
## 7. Kwaliteit & Testplan
### Test Types
| Test Type | Scope | Hoe | Status |
|-----------|-------|-----|--------|
| Type Check | Alle files | `pnpm types:check` | ⏳ |
| Lint | Alle files | `pnpm lint` | ⏳ |
| Visual | Components | Browser inspection | ⏳ |
| Integration | ZoekenBlock | Manual smoke test | ⏳ |
### Manual Test Checklist
**Block States:**
- [ ] BlockLoading toont spinner + tekst
- [ ] BlockError toont error + retry knop werkt
- [ ] BlockEmpty toont icon + message + action werkt
**Block Layout:**
- [ ] BlockSection toont icon in juiste kleur
- [ ] BlockSection toont count badge
- [ ] BlockItem is klikbaar met hover state
- [ ] BlockItem toont badge in juiste kleur
- [ ] BlockFooter toont beide acties
- [ ] BlockFooter primary loading state werkt
**Hooks:**
- [ ] useBlockData fetcht data correct
- [ ] useBlockData toont loading state
- [ ] useBlockData toont error bij failure
- [ ] useBlockData refetch werkt
- [ ] useIntakeContext leest activePatient
- [ ] useIntakeContext leest prefill data
**Integration:**
- [ ] Alle exports werken via index.ts
- [ ] ZoekenBlock werkt nog na changes
- [ ] Geen TypeScript errors
- [ ] Geen console errors
---
## 8. Definition of Done
Een story is **DONE** wanneer:
- [ ] Code is geschreven volgens FO/TO spec
- [ ] TypeScript compileert zonder errors
- [ ] ESLint toont geen errors
- [ ] Component/hook werkt in browser
- [ ] Props zijn gedocumenteerd met JSDoc
- [ ] Export is toegevoegd aan index.ts
Het **project** is **DONE** wanneer:
- [ ] Alle 10 stories zijn DONE
- [ ] Manual test checklist is 100% ✅
- [ ] ZoekenBlock smoke test passed
- [ ] `pnpm build` slaagt
---
## 9. Risico's & Mitigatie
| Risico | Kans | Impact | Mitigatie |
|--------|------|--------|-----------|
| Breaking changes bestaande blocks | Middel | Hoog | Backward compatible exports, smoke test |
| Performance issues hooks | Laag | Middel | useMemo, useCallback waar nodig |
| Inconsistente styling | Laag | Laag | Tailwind design tokens hergebruiken |
| Scope creep (extra features) | Middel | Middel | Strict aan FO/TO houden, YAGNI |
---
## 10. Dependencies Check
**Bestaande dependencies (geen installatie nodig):**
-`lucide-react` - Icons
-`@/components/ui/button` - shadcn Button
-`@/lib/utils` - cn() helper
-`@/lib/cortex/error-handler` - safeFetch, getErrorInfo
-`@/stores/cortex-store` - useCortexStore
-`@/hooks/use-toast` - Toast notifications
**Geen nieuwe dependencies nodig**
---
## 11. Referenties
**Project Documents:**
- `docs/intent/intake-intent-proces/fo-to-cortex-shared-components.md` - FO/TO
- `docs/intent/intake-intent-proces/intake-process-intents.md` - Intents
- `docs/intent/intake-intent-proces/gap-analyse-intake-cortex.md` - Gap analyse
- `docs/intent/intake-intent-proces/block-template-pattern.md` - Patterns
**Bestaande Code (referentie):**
- `components/cortex/shared/patient-list-item.tsx` - Pattern voorbeeld
- `components/cortex/blocks/zoeken-block.tsx` - Block voorbeeld
- `lib/cortex/hooks/use-patient-search.ts` - Hook voorbeeld
---
## 12. Glossary
| Term | Betekenis |
|------|-----------|
| Block | UI component in Cortex canvas-area |
| Shared Component | Herbruikbare UI component voor blocks |
| Hook | React custom hook voor logic/state |
| Prefill | Data meegegeven aan block bij openen |
| Intent | Gebruikers intentie (spraak/tekst) |
---
**Versiehistorie:**
| Versie | Datum | Auteur | Wijziging |
|--------|-------|--------|-----------|
| v1.0 | 03-02-2026 | Colin Lit | Initiële versie |

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,379 @@
# Gap Analyse: Intake Proces × Cortex
**Datum:** 03-02-2026
**Status:** Analyse
**Bron:** `docs/intent/intake-process-intents.md`
---
## 1. Executive Summary
| Laag | Status | Conclusie |
|------|--------|-----------|
| **EPD Backend** | ✅ 90% compleet | Server actions, database, API's zijn uitgebreid aanwezig |
| **EPD UI** | ✅ 95% compleet | Alle 9 intake tabs + screening hebben werkende componenten |
| **Cortex Intents** | ❌ 0% | Geen van de 26 intake intents bestaat |
| **Cortex Blocks** | ❌ 0% | Geen intake-specifieke blocks |
| **Cortex API** | ❌ 0% | Geen /api/cortex/intake/* routes |
**Conclusie:** De EPD-functionaliteit is robuust gebouwd. De koppeling met Cortex ontbreekt volledig.
---
## 2. Wat Bestaat (✅)
### 2.1 Cortex Core (7 intents)
```typescript
// lib/cortex/types.ts
type CortexIntent =
| 'dagnotitie' // ✅ Block + patterns
| 'zoeken' // ✅ Block + patterns
| 'overdracht' // ✅ Block + patterns
| 'agenda_query' // ✅ Patterns (geen dedicated block)
| 'create_appointment' // ✅ Patterns
| 'cancel_appointment' // ✅ Patterns
| 'reschedule_appointment'// ✅ Patterns
| 'unknown';
```
### 2.2 Cortex Blocks (6 stuks)
| Block | Pad | Functie |
|-------|-----|---------|
| `dagnotitie-block.tsx` | `components/cortex/blocks/` | Notitie invoer |
| `zoeken-block.tsx` | `components/cortex/blocks/` | Patiënt zoeken |
| `overdracht-block.tsx` | `components/cortex/blocks/` | Overdracht samenvatting |
| `patient-dashboard-block.tsx` | `components/cortex/blocks/` | Patiënt overzicht |
| `patient-context-card.tsx` | `components/cortex/blocks/` | Context weergave |
| `fallback-picker.tsx` | `components/cortex/blocks/` | Unknown intent handler |
### 2.3 Cortex API Routes
| Route | Methode | Functie |
|-------|---------|---------|
| `/api/cortex/classify` | POST | Intent classificatie |
| `/api/cortex/chat` | POST | Streaming chat |
| `/api/cortex/context` | GET | Context ophalen |
| `/api/cortex/agenda` | GET | Agenda query |
| `/api/cortex/agenda/create` | POST | Afspraak maken |
| `/api/cortex/agenda/cancel` | POST | Afspraak annuleren |
| `/api/cortex/agenda/reschedule` | POST | Afspraak verzetten |
| `/api/cortex/patients/search` | GET | Patiënt zoeken |
### 2.4 EPD Screening (Volledig)
**UI Componenten:**
| Component | Status | Functie |
|-----------|--------|---------|
| `HelpRequestCard` | ✅ | Hulpvraag invoer (textarea) |
| `DecisionCard` | ✅ | Besluit: geschikt/niet_geschikt |
| `DocumentCard` | ✅ | Document upload |
| `ActivityLog` | ✅ | Activiteiten timeline |
**Server Actions:**
| Action | Status | Functie |
|--------|--------|---------|
| `getScreeningSummary()` | ✅ | Screening data ophalen |
| `saveHelpRequest()` | ✅ | Hulpvraag opslaan |
| `saveScreeningDecision()` | ✅ | Besluit opslaan |
| `addScreeningActivity()` | ✅ | Activiteit toevoegen |
### 2.5 EPD Intake (Volledig)
**9 Tabs met UI + Actions:**
| Tab | UI Component | GET Action | CREATE Action |
|-----|--------------|------------|---------------|
| Algemeen | `IntakePage` | `getIntakeById()` | `createIntake()` |
| Contactmomenten | `ContactManager` | `getContactMoments()` | `createContactMoment()` |
| Kindcheck | `KindcheckForm` | `getKindcheck()` | `saveKindcheck()` |
| Risicotaxatie | `RiskManager` | `getRiskAssessments()` | `createRiskAssessment()` |
| Anamnese | `AnamneseManager` | `getAnamneses()` | `createAnamnese()` |
| Onderzoeken | `ExaminationManager` | `getExaminations()` | `createExamination()` |
| ROM | `ExaminationManager` | `getExaminations()` | `createExamination()` |
| Diagnose | `DiagnosisManager` | `getDiagnoses()` | `createDiagnosis()` |
| Behandeladvies | `TreatmentAdviceForm` | `getTreatmentAdvice()` | `saveTreatmentAdvice()` |
---
## 3. Wat Ontbreekt (❌)
### 3.1 Intents (26 ontbreken)
Geen van de intake-gerelateerde intents uit `intake-process-intents.md` bestaat:
#### Screening Intents (4)
| Intent | Type | Patterns nodig |
|--------|------|----------------|
| `screening_query` | Query | `^(toon\s+)?screening`, `wat is de hulpvraag` |
| `hulpvraag_invoer` | Actie | `hulpvraag:`, `noteer hulpvraag` |
| `screening_besluit` | Actie | `geschikt voor behandeling`, `niet geschikt` |
| `screening_activiteit` | Actie | `gebeld met`, `verwijsbrief ontvangen` |
#### Intake Start Intents (2)
| Intent | Type | Patterns nodig |
|--------|------|----------------|
| `intake_starten` | Actie | `start intake`, `nieuwe intake` |
| `intake_lijst` | Query | `toon intakes`, `welke intakes` |
#### Intake Navigatie (3)
| Intent | Type | Patterns nodig |
|--------|------|----------------|
| `intake_navigeer` | Navigatie | `ga naar risico`, `open kindcheck` |
| `intake_volgende` | Navigatie | `volgende stap`, `ga verder` |
| `intake_vorige` | Navigatie | `vorige`, `terug` |
#### Intake Tab Intents (14)
| Intent | Type | Tab |
|--------|------|-----|
| `contact_toevoegen` | Actie | Contactmomenten |
| `contacten_query` | Query | Contactmomenten |
| `kindcheck_invullen` | Actie | Kindcheck |
| `kindcheck_query` | Query | Kindcheck |
| `risico_toevoegen` | Actie | Risicotaxatie |
| `risico_query` | Query | Risicotaxatie |
| `anamnese_toevoegen` | Actie | Anamnese |
| `anamnese_query` | Query | Anamnese |
| `onderzoek_toevoegen` | Actie | Onderzoeken |
| `onderzoeken_query` | Query | Onderzoeken |
| `rom_toevoegen` | Actie | ROM |
| `rom_query` | Query | ROM |
| `diagnose_toevoegen` | Actie | Diagnose |
| `diagnose_query` | Query | Diagnose |
| `behandeladvies_invoer` | Actie | Behandeladvies |
| `behandeladvies_query` | Query | Behandeladvies |
#### Intake Afsluiten (3)
| Intent | Type | Patterns nodig |
|--------|------|----------------|
| `intake_afsluiten` | Actie | `sluit intake af`, `intake afronden` |
| `intake_samenvatting` | Query | `samenvatting intake` |
| `intake_checklist` | Query | `wat moet ik nog doen`, `is intake compleet` |
### 3.2 Cortex Blocks (9 ontbreken)
| Block | Doel | Data bron |
|-------|------|-----------|
| `ScreeningBlock` | Screening overzicht | `getScreeningSummary()` |
| `IntakeListBlock` | Lijst intakes van patiënt | `getIntakesByPatientId()` |
| `IntakeStatusBlock` | Voortgang/checklist | Nieuwe functie nodig |
| `KindcheckBlock` | Kindcheck samenvatting | `getKindcheck()` |
| `RisicoBlock` | Risico's met levels | `getRiskAssessments()` |
| `AnamneseBlock` | Anamnese samenvatting | `getAnamneses()` |
| `DiagnoseBlock` | Diagnoses lijst | `getDiagnoses()` |
| `BehandeladviesBlock` | Behandeladvies tonen | `getTreatmentAdvice()` |
| `IntakeSamenvattingBlock` | AI samenvatting | Nieuwe AI functie nodig |
### 3.3 Cortex API Routes (ontbreken)
| Route | Methode | Functie |
|-------|---------|---------|
| `/api/cortex/screening` | GET | Screening data voor Cortex |
| `/api/cortex/intake` | GET | Intake lijst |
| `/api/cortex/intake/[id]` | GET | Intake details |
| `/api/cortex/intake/[id]/status` | GET | Intake voortgang/checklist |
| `/api/cortex/intake/[id]/risks` | GET | Risico's van intake |
| `/api/cortex/intake/[id]/diagnoses` | GET | Diagnoses van intake |
| `/api/cortex/intake/[id]/summary` | GET | AI samenvatting |
### 3.4 Reflex Patterns (ontbreken)
In `lib/cortex/reflex-classifier.ts` moeten patterns worden toegevoegd voor alle 26 intents.
---
## 4. Architectuur Gap
```
┌─────────────────────────────────────────────────────────────────────────┐
│ HUIDIGE SITUATIE │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ CORTEX EPD │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 7 Intents │ │ Screening UI │ │
│ │ 6 Blocks │ ❌ │ Intake UI (9) │ │
│ │ 8 API routes │ ─ ─ ─ ─ ─ ─ │ Server Actions │ │
│ └─────────────────┘ GEEN LINK └─────────────────┘ │
│ │
├─────────────────────────────────────────────────────────────────────────┤
│ GEWENSTE SITUATIE │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ CORTEX EPD │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 7 + 26 Intents │ │ Screening UI │ │
│ │ 6 + 9 Blocks │ ✅ │ Intake UI (9) │ │
│ │ 8 + 7 API routes│ ◀──────────▶ │ Server Actions │ │
│ └─────────────────┘ GEKOPPELD └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
---
## 5. Implementatie Roadmap
### Fase 1: Foundation (Query Intents)
**Doel:** Informatie opvragen via spraak
| # | Taak | Effort | Prioriteit |
|---|------|--------|------------|
| 1.1 | Intent types toevoegen aan `types.ts` | S | 🔴 |
| 1.2 | Patterns toevoegen aan `reflex-classifier.ts` | M | 🔴 |
| 1.3 | `IntakeStatusBlock` bouwen | M | 🔴 |
| 1.4 | `RisicoBlock` bouwen | S | 🔴 |
| 1.5 | `DiagnoseBlock` bouwen | S | 🟡 |
| 1.6 | `/api/cortex/intake/*` routes | M | 🔴 |
**Resultaat:** "Wat zijn de risico's?", "Is de intake compleet?" werken
### Fase 2: Navigation (Navigatie Intents)
**Doel:** Navigeren via spraak
| # | Taak | Effort | Prioriteit |
|---|------|--------|------------|
| 2.1 | `intake_navigeer` patterns | S | 🔴 |
| 2.2 | Navigation handler in orchestrator | M | 🔴 |
| 2.3 | Router integratie | M | 🟡 |
**Resultaat:** "Ga naar diagnose", "Open kindcheck" werken
### Fase 3: Actions (Actie Intents)
**Doel:** Data invoeren via spraak
| # | Taak | Effort | Prioriteit |
|---|------|--------|------------|
| 3.1 | `intake_starten` intent + handler | M | 🟡 |
| 3.2 | `risico_toevoegen` intent + handler | L | 🟡 |
| 3.3 | `diagnose_toevoegen` intent + handler | L | 🟡 |
| 3.4 | Confirmatie dialogen | M | 🟡 |
**Resultaat:** "Start intake", "Risico suïcidaliteit matig" werken
### Fase 4: Intelligence (AI Features)
**Doel:** Slimme AI functionaliteit
| # | Taak | Effort | Prioriteit |
|---|------|--------|------------|
| 4.1 | `IntakeSamenvattingBlock` met AI | L | 🔵 |
| 4.2 | Intake-gerelateerde nudges | M | 🔵 |
| 4.3 | Context-aware suggestions | L | 🔵 |
**Resultaat:** "Samenvatting intake", proactieve suggesties werken
---
## 6. Effort Schatting
| Fase | Items | Effort |
|------|-------|--------|
| Fase 1: Foundation | 6 taken | ~3-4 dagen |
| Fase 2: Navigation | 3 taken | ~1-2 dagen |
| Fase 3: Actions | 4 taken | ~3-4 dagen |
| Fase 4: Intelligence | 3 taken | ~2-3 dagen |
| **Totaal** | **16 taken** | **~10-13 dagen** |
---
## 7. Quick Wins
Snel te implementeren met hoge waarde:
### 7.1 `intake_status` Query (1 dag)
```typescript
// Input: "Wat moet ik nog doen?" / "Is de intake compleet?"
// Output: Checklist met voltooide/openstaande tabs
// Nieuwe functie nodig:
async function getIntakeCompletionStatus(intakeId: string) {
const intake = await getIntakeById(intakeId);
const kindcheck = await getKindcheck(intakeId);
const risks = await getRiskAssessments(intakeId);
const diagnoses = await getDiagnoses(intakeId);
// etc...
return {
algemeen: !!intake,
kindcheck: !!kindcheck.hasChildren !== undefined,
risicotaxatie: risks.length > 0,
diagnose: diagnoses.length > 0,
// ...
};
}
```
### 7.2 `risico_query` (0.5 dag)
```typescript
// Input: "Wat zijn de risico's?"
// Output: RisicoBlock met bestaande getRiskAssessments()
// Block template:
<RisicoBlock
risks={[
{ type: 'suicidaliteit', level: 'matig', rationale: '...' },
{ type: 'agressie', level: 'laag', rationale: '...' }
]}
/>
```
### 7.3 `intake_navigeer` (0.5 dag)
```typescript
// Input: "Ga naar diagnose"
// Output: router.push() naar juiste tab
// Pattern matching:
{ pattern: /^ga\s+naar\s+(risico|diagnose|kindcheck|anamnese)/i, weight: 1.0 }
```
---
## 8. Dependencies
```
types.ts (intent definitions)
reflex-classifier.ts (patterns)
/api/cortex/intake/* (data routes)
blocks/*.tsx (UI components)
canvas-area.tsx (block rendering)
```
---
## 9. Risico's
| Risico | Impact | Mitigatie |
|--------|--------|-----------|
| Intake context niet beschikbaar | Hoog | ActiveIntake store toevoegen |
| Meerdere intakes per patiënt | Middel | Intent clarification bij ambiguïteit |
| Performance bij grote datasets | Laag | Pagination in queries |
| Pattern overlap met bestaande intents | Middel | Goede escalation logic |
---
## 10. Aanbeveling
**Start met Fase 1 (Query Intents)** omdat:
1. Hergebruikt bestaande server actions
2. Geen destructieve acties (veilig)
3. Direct waarde voor gebruiker
4. Legt foundation voor actie intents
**Eerste implementatie:**
1. `intake_status` - "Wat moet ik nog doen?"
2. `risico_query` - "Wat zijn de risico's?"
3. `intake_navigeer` - "Ga naar diagnose"
Deze 3 intents dekken de belangrijkste use case: snel navigeren en informatie opvragen tijdens een intake sessie.

View File

@@ -0,0 +1,234 @@
# Text-to-Image Prompts: Intake Proces Visualisatie
**Doel:** Prompts voor het genereren van visualisaties van het Cortex intake proces
---
## 1. Overzichtsprompt (Hero Image)
### Voor: Midjourney / DALL-E 3
```
A clean, modern healthcare software interface showing an AI-powered patient intake workflow.
The image displays a split view:
- Left side: A vertical process flow with connected nodes showing stages: "Screening" → "Intake Start" → "Assessment" → "Diagnosis" → "Treatment Plan", each node glowing softly in teal/cyan
- Right side: A sleek dashboard interface with a voice input bar at the top showing a waveform, and card-based UI components below displaying patient information
The design aesthetic is minimal, professional healthcare software with a white background, subtle shadows, and accent colors in teal (#0d9488) and slate gray. Small microphone icon indicates voice control.
Style: Clean UI mockup, flat design, healthcare technology, professional, minimalist
Aspect ratio: 16:9
```
---
## 2. Process Flow Diagram
### Voor: Midjourney / Ideogram
```
A horizontal workflow diagram for a medical intake process, infographic style.
Four connected phases flowing left to right:
1. "SCREENING" - icon of clipboard with checkmark, showing "Hulpvraag" and "Besluit"
2. "INTAKE" - icon of folder opening, showing 9 small tab icons stacked
3. "ASSESSMENT" - icon of stethoscope and brain, showing "Risico", "Diagnose", "Anamnese"
4. "BEHANDELPLAN" - icon of document with heart, showing "Doelen" and "Interventies"
Arrows connect each phase. Below each phase, small cards show the key data points.
Color scheme: Teal (#0d9488) for primary, soft grays for backgrounds, white cards with subtle shadows. Modern healthcare aesthetic, clean lines, professional.
Style: Process infographic, flat icons, medical software, flowchart
Aspect ratio: 21:9 (ultrawide)
```
---
## 3. Voice Intent Interactie
### Voor: DALL-E 3 / Midjourney
```
A modern healthcare software interface demonstrating voice-controlled AI assistant interaction.
Center focus: A floating command bar with a glowing microphone icon and the Dutch text "Wat zijn de risico's van Jan?" displayed as voice input with a subtle sound waveform.
Below the command bar: Three response cards appearing in a staggered layout:
- Card 1: "Suïcidaliteit - Matig" with orange indicator
- Card 2: "Agressie - Laag" with green indicator
- Card 3: "Zelfverwaarlozing - Laag" with green indicator
The interface has a soft blur effect on the background showing a patient dashboard. A small AI assistant avatar or brain icon indicates the system is processing.
Style: Voice UI, conversational interface, healthcare app, glassmorphism, modern
Aspect ratio: 4:3
```
---
## 4. Intake Tabs UI
### Voor: Midjourney / Stable Diffusion
```
A detailed healthcare software interface showing a patient intake workflow with 9 horizontal tabs.
The tab bar displays: "Algemeen | Contacten | Kindcheck | Risico | Anamnese | Onderzoek | ROM | Diagnose | Behandeladvies"
The "Risico" tab is highlighted/active in teal. Below shows a risk assessment form with:
- Risk type dropdown showing "Suïcidaliteit"
- Severity scale: Laag / Matig / Hoog / Zeer hoog (Matig selected)
- Notes textarea
- Action items checklist
Left sidebar shows patient info card with name, age, photo placeholder.
Clean, professional medical software aesthetic. White background, teal accents, clear typography, organized layout.
Style: Healthcare EHR interface, medical software UI, dashboard design, professional
Aspect ratio: 16:10
```
---
## 5. Cortex Command Center
### Voor: DALL-E 3
```
A futuristic but professional healthcare AI command center interface called "Cortex".
Top section: A prominent voice/text input bar with placeholder "Vraag iets of geef een opdracht..." and a microphone button, subtle glow effect.
Main area shows three "action blocks" in a grid:
1. "Intake Status" card - circular progress indicator showing 6/9 complete, checklist of remaining items
2. "Risicotaxatie" card - risk assessment summary with colored severity badges
3. "Volgende Actie" card - AI suggestion "Kindcheck invullen?" with accept/dismiss buttons
Bottom: Recent actions timeline showing "Diagnose toegevoegd", "Risico bijgewerkt" with timestamps.
Right sidebar: Active patient context showing "Jan de Vries" with key info.
Color palette: Teal primary (#0d9488), white backgrounds, slate text, subtle gradients. Modern healthcare technology feel.
Style: AI dashboard, healthcare technology, command center UI, modern minimal
Aspect ratio: 16:9
```
---
## 6. Intent Classification Diagram
### Voor: Ideogram / Midjourney
```
A technical diagram showing AI intent classification for healthcare voice commands.
Center: A brain/neural network icon labeled "Cortex AI"
Three incoming arrows from the left showing voice inputs:
- "Start intake voor Jan"
- "Wat zijn de risico's?"
- "Ga naar diagnose"
Three outgoing arrows to the right showing classified intents with icons:
- "intake_starten" → folder icon → "Actie"
- "risico_query" → search icon → "Query"
- "intake_navigeer" → arrow icon → "Navigatie"
Below: A confidence meter showing "Reflex: 0.9" and "AI Fallback" path for low confidence.
Style: Technical flowchart, AI/ML diagram, clean infographic, developer documentation
Aspect ratio: 16:9
```
---
## 7. Mobile Voice Assistant
### Voor: DALL-E 3 / Midjourney
```
A healthcare professional's hand holding a tablet device showing a voice-activated patient intake assistant.
The tablet screen displays:
- Top: Patient header "Marie Jansen - Intake #2024-0042"
- Center: Large circular voice activation button with pulsing animation rings
- Below: Recent voice command "Kindcheck: geen kinderen" with checkmark
- Bottom: Suggested next actions as pill-shaped buttons: "Risicotaxatie", "Anamnese", "Diagnose"
Background: Soft-focus hospital/clinic environment with warm lighting.
The overall feel is modern healthcare technology that's approachable and easy to use.
Style: Healthcare technology, tablet UI, medical app, professional photography composite
Aspect ratio: 3:4 (portrait)
```
---
## 8. Before/After Comparison
### Voor: Midjourney
```
A split-screen comparison image showing healthcare workflow transformation.
LEFT SIDE labeled "Traditioneel":
- Cluttered desktop with multiple windows open
- Paper forms scattered
- Mouse clicking through endless menus
- Stressed healthcare worker
- Gray, busy, overwhelming
RIGHT SIDE labeled "Met Cortex":
- Clean single interface
- Voice waveform indicating speech input
- Organized card-based results
- Calm, focused healthcare worker
- Bright, organized, efficient
A diagonal dividing line separates the two sides. The contrast emphasizes simplicity vs complexity.
Style: Comparison infographic, before/after, healthcare technology marketing
Aspect ratio: 2:1
```
---
## Prompt Tips
### Stijl Keywords
- Healthcare software / Medical EHR / Clinical interface
- Clean UI / Minimal design / Professional
- Voice interface / AI assistant / Conversational UI
- Dashboard / Card-based layout / Modern web app
### Kleurenpalet
- Primary: Teal `#0d9488`
- Background: White `#ffffff`, Slate `#f1f5f9`
- Text: Slate `#1e293b`
- Accents: Amber (warning), Red (high risk), Green (success)
### Vermijden
- Geen stockfoto-achtige healthcare beelden (stethoscopen, witte jassen)
- Geen te futuristische sci-fi elementen
- Geen drukke, overladen interfaces
- Geen generieke "AI brain" clichés
---
## Aanbevolen Model per Prompt
| Prompt | Best Model | Reden |
|--------|------------|-------|
| 1. Hero Image | DALL-E 3 | Beste voor UI mockups |
| 2. Process Flow | Ideogram | Sterk in diagrammen |
| 3. Voice Intent | DALL-E 3 | Goed met tekst in beeld |
| 4. Tabs UI | Midjourney | Gedetailleerde interfaces |
| 5. Command Center | DALL-E 3 | Complexe UI compositie |
| 6. Intent Diagram | Ideogram | Technische diagrammen |
| 7. Mobile | Midjourney | Realistische composities |
| 8. Before/After | Midjourney | Conceptuele vergelijkingen |

View File

@@ -0,0 +1,330 @@
# Intake Proces: Flow, Intents & UI
**Datum:** 03-02-2026
**Status:** Ontwerp
**Doel:** Documentatie van het intake proces met bijbehorende Cortex intents en UI componenten
---
## 1. Procesoverzicht
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ INTAKE PROCES │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │
│ │ SCREENING │ ──▶ │ INTAKE START │ ──▶ │ INTAKE UITVOERING │ │
│ │ │ │ │ │ │ │
│ │ • Hulpvraag │ │ • Titel │ │ ┌────────────────────┐ │ │
│ │ • Documenten │ │ • Afdeling │ │ │ 1. Algemeen │ │ │
│ │ • Activiteit │ │ • Startdatum │ │ │ 2. Contactmomenten │ │ │
│ │ • Besluit │ │ │ │ │ 3. Kindcheck │ │ │
│ └──────────────┘ └──────────────┘ │ │ 4. Risicotaxatie │ │ │
│ │ │ │ │ 5. Anamnese │ │ │
│ ▼ │ │ │ 6. Onderzoeken │ │ │
│ geschikt? ───▶ NEE ───▶ STOP │ │ 7. ROM │ │ │
│ │ │ │ 8. Diagnose │ │ │
│ JA │ │ 9. Behandeladvies │ │ │
│ └────────────────────┘ │ └────────────────────┘ │ │
│ │ │ │ │
│ └─────────────┼────────────┘ │
│ ▼ │
│ ┌──────────────────────────┐ │
│ │ INTAKE AFSLUITEN │ │
│ │ │ │
│ │ • Status: afgerond │ │
│ │ • Einddatum │ │
│ │ → Start Behandelplan │ │
│ └──────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
---
## 2. Fase 1: Screening
### 2.1 Procesbeschrijving
De screening is de eerste beoordeling of een patiënt geschikt is voor behandeling. Hier wordt de hulpvraag vastgelegd, documenten verzameld (verwijsbrief), en een besluit genomen.
### 2.2 UI Componenten
| Component | Pad | Beschrijving |
|-----------|-----|--------------|
| `ScreeningPage` | `app/epd/patients/[id]/screening/page.tsx` | Container pagina |
| `HelpRequestCard` | `screening/components/help-request-card.tsx` | Hulpvraag invoer (textarea) |
| `DecisionCard` | `screening/components/decision-card.tsx` | Besluit: geschikt/niet_geschikt + afdeling |
| `DocumentCard` | `screening/components/document-card.tsx` | Upload verwijsbrief en documenten |
| `ActivityLog` | `screening/components/activity-log.tsx` | Chronologisch activiteitenlog |
### 2.3 Intents & Queries
| Intent | Type | Input Voorbeelden | Output/Actie |
|--------|------|-------------------|--------------|
| `screening_query` | Query | "Toon screening van Jan"<br>"Wat is de hulpvraag?" | `ScreeningBlock` - overzicht hulpvraag, besluit, status |
| `hulpvraag_invoer` | Actie | "Hulpvraag: angstklachten en slaapproblemen"<br>"Noteer hulpvraag: depressieve klachten" | Vult `HelpRequestCard` in |
| `screening_besluit` | Actie | "Jan is geschikt voor behandeling"<br>"Niet geschikt, doorverwijzen" | Vult `DecisionCard` in |
| `screening_activiteit` | Actie | "Gebeld met huisarts over verwijzing"<br>"Verwijsbrief ontvangen" | Voegt toe aan `ActivityLog` |
### 2.4 Nudges
| Trigger | Nudge | Priority |
|---------|-------|----------|
| Hulpvraag ingevuld, geen verwijsbrief | "Verwijsbrief uploaden?" | medium |
| Verwijsbrief + hulpvraag compleet | "Screeningsbesluit nemen?" | medium |
| Besluit = geschikt | "Intake starten voor deze patiënt?" | low |
---
## 3. Fase 2: Intake Starten
### 3.1 Procesbeschrijving
Na een positief screeningsbesluit wordt een nieuwe intake aangemaakt met basisgegevens.
### 3.2 UI Componenten
| Component | Pad | Beschrijving |
|-----------|-----|--------------|
| `NewIntakePage` | `intakes/new/page.tsx` | Formulier voor nieuwe intake |
| `NewIntakeForm` | `intakes/components/new-intake-form.tsx` | Titel, afdeling, startdatum |
| `IntakeList` | `intakes/components/intake-list.tsx` | Overzicht alle intakes van patiënt |
### 3.3 Intents & Queries
| Intent | Type | Input Voorbeelden | Output/Actie |
|--------|------|-------------------|--------------|
| `intake_starten` | Actie | "Start intake voor Jan"<br>"Nieuwe intake afdeling Volwassenen" | Opent `NewIntakeForm` met prefill |
| `intake_lijst` | Query | "Toon intakes van Jan"<br>"Welke intakes heeft Marie?" | `IntakeListBlock` - lijst met status |
---
## 4. Fase 3: Intake Uitvoering
### 4.1 Overzicht Tabs
| # | Tab | Verplicht | Component | Beschrijving |
|---|-----|-----------|-----------|--------------|
| 1 | Algemeen | ✅ | `IntakePage` | Basisgegevens intake |
| 2 | Contactmomenten | ❌ | `ContactManager` | Gesprekken, telefoontjes |
| 3 | Kindcheck | ⚠️* | `KindcheckForm` | Kinderen in beeld, zorgen, acties |
| 4 | Risicotaxatie | ✅ | `RiskManager` | Suïcidaliteit, agressie, etc. |
| 5 | Anamnese | ✅ | `AnamneseManager` | Psychiatrisch, sociaal, somatisch |
| 6 | Onderzoeken | ❌ | `ExaminationManager` | Lichamelijk, psychologisch onderzoek |
| 7 | ROM | ❌ | `ExaminationManager` (isRom) | Vragenlijsten (OQ-45, etc.) |
| 8 | Diagnose | ✅ | `DiagnosisManager` | ICD-10 classificaties |
| 9 | Behandeladvies | ✅ | `TreatmentAdviceForm` | Advies, programma, behandelaar |
*Kindcheck is wettelijk verplicht bij patiënten met kinderen
### 4.2 Tab-specifieke Intents
#### 4.2.1 Algemeen
| Intent | Type | Input | Output |
|--------|------|-------|--------|
| `intake_algemeen` | Query | "Toon intake gegevens"<br>"Wanneer is de intake gestart?" | Toont algemene info |
| `intake_status` | Query | "Wat is de status van de intake?"<br>"Is de intake compleet?" | Status + checklist onvolledige secties |
#### 4.2.2 Contactmomenten
| Intent | Type | Input | Output |
|--------|------|-------|--------|
| `contact_toevoegen` | Actie | "Intakegesprek gehad met Jan"<br>"Telefonisch contact: besproken wachttijd" | Voegt contactmoment toe |
| `contacten_query` | Query | "Welke contactmomenten zijn er geweest?" | Lijst contactmomenten |
#### 4.2.3 Kindcheck
| Intent | Type | Input | Output |
|--------|------|-------|--------|
| `kindcheck_invullen` | Actie | "Kindcheck: 2 kinderen, geen zorgen"<br>"Geen kinderen in beeld" | Vult kindcheck formulier |
| `kindcheck_query` | Query | "Is de kindcheck gedaan?"<br>"Hoeveel kinderen heeft Jan?" | Status + samenvatting |
#### 4.2.4 Risicotaxatie
| Intent | Type | Input | Output |
|--------|------|-------|--------|
| `risico_toevoegen` | Actie | "Risico suïcidaliteit: matig"<br>"Agressierisico laag" | Voegt risico toe aan `RiskManager` |
| `risico_query` | Query | "Wat zijn de risico's van Jan?"<br>"Toon risicotaxatie" | Risico overzicht met levels |
#### 4.2.5 Anamnese
| Intent | Type | Input | Output |
|--------|------|-------|--------|
| `anamnese_toevoegen` | Actie | "Psychiatrische anamnese: eerste depressie 2019"<br>"Sociale anamnese: woont alleen" | Voegt anamnese sectie toe |
| `anamnese_query` | Query | "Wat is de voorgeschiedenis?"<br>"Toon anamnese" | Anamnese overzicht |
#### 4.2.6 Onderzoeken
| Intent | Type | Input | Output |
|--------|------|-------|--------|
| `onderzoek_toevoegen` | Actie | "Psychologisch onderzoek aangevraagd"<br>"Lab: bloedonderzoek normaal" | Voegt onderzoek toe |
| `onderzoeken_query` | Query | "Welke onderzoeken zijn gedaan?" | Lijst onderzoeken + resultaten |
#### 4.2.7 ROM
| Intent | Type | Input | Output |
|--------|------|-------|--------|
| `rom_toevoegen` | Actie | "ROM: OQ-45 score 82"<br>"PHQ-9 afgenomen, score 14" | Voegt ROM-meting toe |
| `rom_query` | Query | "Wat zijn de ROM scores?"<br>"Toon vragenlijsten" | ROM overzicht met scores |
#### 4.2.8 Diagnose
| Intent | Type | Input | Output |
|--------|------|-------|--------|
| `diagnose_toevoegen` | Actie | "Diagnose: depressieve stoornis"<br>"Hoofddiagnose F32.1" | Opent ICD-10 zoeken + voegt toe |
| `diagnose_query` | Query | "Wat zijn de diagnoses?"<br>"Welke diagnose heeft Jan?" | Diagnose overzicht |
#### 4.2.9 Behandeladvies
| Intent | Type | Input | Output |
|--------|------|-------|--------|
| `behandeladvies_invoer` | Actie | "Behandeladvies: CGT bij angst"<br>"Advies: EMDR voor trauma" | Vult behandeladvies formulier |
| `behandeladvies_query` | Query | "Wat is het behandeladvies?"<br>"Toon advies" | Behandeladvies overzicht |
### 4.3 Navigatie Intents
| Intent | Type | Input | Output |
|--------|------|-------|--------|
| `intake_navigeer` | Navigatie | "Ga naar risicotaxatie"<br>"Open kindcheck"<br>"Naar diagnose" | Navigeert naar specifieke tab |
| `intake_volgende` | Navigatie | "Volgende stap"<br>"Ga verder" | Navigeert naar volgende tab |
| `intake_vorige` | Navigatie | "Vorige"<br>"Terug" | Navigeert naar vorige tab |
---
## 5. Fase 4: Intake Afsluiten
### 5.1 Procesbeschrijving
Wanneer alle verplichte secties zijn ingevuld, kan de intake worden afgesloten.
### 5.2 Intents
| Intent | Type | Input | Output |
|--------|------|-------|--------|
| `intake_afsluiten` | Actie | "Sluit intake af"<br>"Intake afronden" | Zet status op 'afgerond' + einddatum |
| `intake_samenvatting` | Query | "Samenvatting intake"<br>"Geef overzicht van de intake" | AI-gegenereerde samenvatting |
| `intake_checklist` | Query | "Wat moet ik nog doen?"<br>"Is de intake compleet?" | Checklist onvolledige secties |
### 5.3 Nudges
| Trigger | Nudge | Priority |
|---------|-------|----------|
| Alle verplichte secties ingevuld | "Intake afsluiten?" | medium |
| Intake afgesloten | "Behandelplan opstellen?" | low |
| Intake > 4 weken open | "Intake nog actueel? Afsluiten of voortzetten?" | low |
---
## 6. Intent Matrix (Totaaloverzicht)
### 6.1 Alle Intents
| # | Intent ID | Type | Fase | Priority |
|---|-----------|------|------|----------|
| 1 | `screening_query` | Query | Screening | 🔴 Hoog |
| 2 | `hulpvraag_invoer` | Actie | Screening | 🟡 Middel |
| 3 | `screening_besluit` | Actie | Screening | 🟡 Middel |
| 4 | `screening_activiteit` | Actie | Screening | 🔵 Laag |
| 5 | `intake_starten` | Actie | Start | 🔴 Hoog |
| 6 | `intake_lijst` | Query | Start | 🟡 Middel |
| 7 | `intake_navigeer` | Navigatie | Uitvoering | 🔴 Hoog |
| 8 | `intake_status` | Query | Uitvoering | 🔴 Hoog |
| 9 | `contact_toevoegen` | Actie | Uitvoering | 🟡 Middel |
| 10 | `kindcheck_invullen` | Actie | Uitvoering | 🟡 Middel |
| 11 | `kindcheck_query` | Query | Uitvoering | 🟡 Middel |
| 12 | `risico_toevoegen` | Actie | Uitvoering | 🔴 Hoog |
| 13 | `risico_query` | Query | Uitvoering | 🔴 Hoog |
| 14 | `anamnese_toevoegen` | Actie | Uitvoering | 🟡 Middel |
| 15 | `anamnese_query` | Query | Uitvoering | 🟡 Middel |
| 16 | `onderzoek_toevoegen` | Actie | Uitvoering | 🔵 Laag |
| 17 | `onderzoeken_query` | Query | Uitvoering | 🔵 Laag |
| 18 | `rom_toevoegen` | Actie | Uitvoering | 🟡 Middel |
| 19 | `rom_query` | Query | Uitvoering | 🟡 Middel |
| 20 | `diagnose_toevoegen` | Actie | Uitvoering | 🔴 Hoog |
| 21 | `diagnose_query` | Query | Uitvoering | 🔴 Hoog |
| 22 | `behandeladvies_invoer` | Actie | Uitvoering | 🔴 Hoog |
| 23 | `behandeladvies_query` | Query | Uitvoering | 🔴 Hoog |
| 24 | `intake_afsluiten` | Actie | Afsluiten | 🟡 Middel |
| 25 | `intake_samenvatting` | Query | Afsluiten | 🟡 Middel |
| 26 | `intake_checklist` | Query | Afsluiten | 🟡 Middel |
### 6.2 Verdeling
| Type | Aantal |
|------|--------|
| Query | 13 |
| Actie | 11 |
| Navigatie | 2 |
| **Totaal** | **26** |
| Priority | Aantal |
|----------|--------|
| 🔴 Hoog | 10 |
| 🟡 Middel | 13 |
| 🔵 Laag | 3 |
---
## 7. UI Blocks (Nieuw te bouwen)
Voor Cortex moeten we nieuwe blocks bouwen die de intent resultaten tonen:
| Block | Toont | Bron Data |
|-------|-------|-----------|
| `ScreeningBlock` | Hulpvraag, besluit, status | `getScreeningSummary()` |
| `IntakeStatusBlock` | Checklist tabs, voortgang | Nieuwe functie nodig |
| `IntakeListBlock` | Lijst intakes van patiënt | `getIntakesByPatient()` |
| `KindcheckBlock` | Samenvatting kindcheck | `getKindcheck()` |
| `RisicoBlock` | Risico's met levels | `getRiskAssessments()` |
| `AnamneseBlock` | Anamnese samenvatting | `getAnamneses()` |
| `DiagnoseBlock` | Diagnoses lijst | `getDiagnoses()` |
| `BehandeladviesBlock` | Behandeladvies | `getTreatmentAdvice()` |
| `IntakeSamenvattingBlock` | AI-samenvatting hele intake | Nieuwe AI functie nodig |
---
## 8. Implementatie Prioriteit
### 8.1 MVP (Fase 1)
Focus op de meest waardevolle intents:
1. **`intake_status`** - "Wat moet ik nog doen?" → Checklist
2. **`intake_navigeer`** - "Ga naar risicotaxatie" → Direct navigeren
3. **`risico_query`** - "Wat zijn de risico's?" → Risico overzicht
4. **`diagnose_query`** - "Welke diagnoses?" → Diagnose overzicht
5. **`intake_samenvatting`** - "Samenvatting intake" → AI samenvatting
### 8.2 Fase 2
6. **`screening_query`** - Screening overzicht
7. **`kindcheck_query`** - Kindcheck status
8. **`behandeladvies_query`** - Behandeladvies tonen
9. **`intake_starten`** - Nieuwe intake via spraak
### 8.3 Fase 3 (Actie intents)
10. **`risico_toevoegen`** - Risico toevoegen via spraak
11. **`diagnose_toevoegen`** - Diagnose toevoegen
12. **`kindcheck_invullen`** - Kindcheck invullen
13. Overige actie intents...
---
## 9. Open Vragen
1. **Contextbeheer**: Hoe weet Cortex welke intake actief is als een patiënt meerdere intakes heeft?
2. **Navigatie vs Blocks**: Navigeren we naar bestaande pagina's of tonen we data in Cortex blocks?
3. **Actie confirmatie**: Welke acties vereisen bevestiging voordat ze uitgevoerd worden?
4. **Integratie behandelplan**: Hoe koppelen we intake-afsluiting aan behandelplan-start?
---
## Versiehistorie
| Versie | Datum | Auteur | Wijziging |
|--------|-------|--------|-----------|
| v0.1 | 03-02-2026 | Colin Lit | Initieel ontwerp |

View File

@@ -0,0 +1,221 @@
# Text-to-Image Prompt: Intake Procesflow met Intents
**Doel:** Visualisatie van het complete intake proces met spraak-intents en EPD schermen
---
## Prompt (DALL-E 3 / Ideogram)
```
A detailed horizontal process flow diagram for a Dutch healthcare EPD (Electronic Patient Dossier) system showing voice intents triggering UI screens.
The diagram flows LEFT to RIGHT through 4 main phases, each in a distinct colored zone:
PHASE 1 - "SCREENING" (light blue zone):
┌─────────────────────────────────────────┐
│ Voice intents (speech bubbles): │
│ • "Wat is de hulpvraag?" │
│ • "Jan is geschikt voor behandeling" │
│ ↓ │
│ EPD Screens (UI cards): │
│ [HelpRequestCard] [DecisionCard] │
│ [DocumentCard] [ActivityLog] │
└─────────────────────────────────────────┘
Arrow → to next phase
PHASE 2 - "INTAKE START" (light green zone):
┌─────────────────────────────────────────┐
│ Voice intents: │
│ • "Start intake voor Jan" │
│ • "Nieuwe intake Volwassenen" │
│ ↓ │
│ EPD Screens: │
│ [NewIntakeForm] │
│ - Titel │
│ - Afdeling │
│ - Startdatum │
└─────────────────────────────────────────┘
Arrow → to next phase
PHASE 3 - "INTAKE UITVOERING" (light teal zone, largest section):
┌─────────────────────────────────────────────────────────────┐
│ 9 TABS displayed as a horizontal tab bar: │
│ [Algemeen|Contact|Kindcheck|Risico|Anamnese|Onderzoek|ROM|Diagnose|Advies] │
│ │
│ Below: 3 columns of intent→screen mappings: │
│ │
│ Column 1: Column 2: Column 3: │
│ "Ga naar risico" "Wat zijn de risico's?" "Diagnose: depressie" │
│ ↓ ↓ ↓ │
│ [RiskManager] [RisicoBlock] [DiagnosisManager] │
│ │
│ "Kindcheck: geen kinderen" "Is intake compleet?" "Behandeladvies CGT" │
│ ↓ ↓ ↓ │
│ [KindcheckForm] [IntakeStatusBlock] [TreatmentAdviceForm] │
└─────────────────────────────────────────────────────────────┘
Arrow → to next phase
PHASE 4 - "AFSLUITEN" (light purple zone):
┌─────────────────────────────────────────┐
│ Voice intents: │
│ • "Sluit intake af" │
│ • "Samenvatting intake" │
│ ↓ │
│ EPD Screens: │
│ [IntakeSummaryBlock] │
│ [Status: Afgerond ✓] │
│ ↓ │
│ "Start behandelplan" → │
└─────────────────────────────────────────┘
LEGEND at bottom:
🎤 = Voice Intent (input)
📱 = EPD Screen/Component (output)
→ = Process flow
↓ = Intent triggers screen
Design style: Clean technical flowchart, software architecture diagram, white background with subtle colored zones for each phase. Speech bubbles for intents, rounded rectangles for UI components. Arrows showing relationships. Professional documentation style.
Typography: Sans-serif, clear hierarchy, Dutch language labels.
Colors: Screening=#e0f2fe, Start=#dcfce7, Uitvoering=#ccfbf1, Afsluiten=#f3e8ff, Arrows=#0d9488
Aspect ratio: 21:9 (ultrawide) or 3:1
```
---
## Alternatief: Verticale Flow (voor A4/portrait)
```
A vertical process flow diagram for a Dutch healthcare intake system showing voice commands and their corresponding EPD screens.
TOP TO BOTTOM layout with 4 stacked sections:
SECTION 1 - SCREENING
├── Intent bubble: "Wat is de hulpvraag van Jan?"
├── Arrow down
└── Screen cards: [HelpRequestCard] [DecisionCard]
SECTION 2 - INTAKE START
├── Intent bubble: "Start intake voor Jan"
├── Arrow down
└── Screen card: [NewIntakeForm]
SECTION 3 - INTAKE TABS (expanded section)
├── Tab bar showing 9 tabs
├── Three example flows side by side:
│ ├── "Ga naar risico" → [RiskManager]
│ ├── "Wat zijn diagnoses?" → [DiagnoseBlock]
│ └── "Kindcheck geen kinderen" → [KindcheckForm]
SECTION 4 - AFSLUITEN
├── Intent bubble: "Sluit intake af"
├── Arrow down
└── Screen cards: [IntakeSummaryBlock] → Behandelplan
Visual style: Technical documentation, swim lane diagram, clear sections with subtle background colors, speech bubbles for voice input, device frames for screens.
Aspect ratio: 9:16 or A4 portrait
```
---
## Simpele Versie (voor snelle generatie)
```
A software flowchart showing voice commands triggering healthcare screens.
Four colored columns left to right:
1. SCREENING (blue): "Hulpvraag?" → HelpRequestCard
2. INTAKE START (green): "Start intake" → NewIntakeForm
3. UITVOERING (teal): "Risico's?" → RiskManager, "Diagnose?" → DiagnosisManager
4. AFSLUITEN (purple): "Samenvatting" → IntakeSummaryBlock
Speech bubbles connect to UI component boxes with arrows.
Clean, minimal, technical diagram style.
White background, colored section headers.
Aspect ratio: 16:9
```
---
## Mermaid Diagram (voor technische docs)
Als je liever een exacte diagram wilt die je zelf kunt renderen:
```mermaid
flowchart LR
subgraph SCREENING["🔵 SCREENING"]
I1["🎤 Wat is de hulpvraag?"]
I2["🎤 Jan is geschikt"]
S1["📱 HelpRequestCard"]
S2["📱 DecisionCard"]
I1 --> S1
I2 --> S2
end
subgraph START["🟢 INTAKE START"]
I3["🎤 Start intake voor Jan"]
S3["📱 NewIntakeForm"]
I3 --> S3
end
subgraph UITVOERING["🔷 INTAKE UITVOERING"]
direction TB
TABS["9 Tabs: Algemeen | Contact | Kindcheck | Risico | Anamnese | Onderzoek | ROM | Diagnose | Advies"]
I4["🎤 Ga naar risico"]
I5["🎤 Wat zijn de risico's?"]
I6["🎤 Diagnose: depressie"]
I7["🎤 Kindcheck: geen kinderen"]
S4["📱 RiskManager"]
S5["📱 RisicoBlock"]
S6["📱 DiagnosisManager"]
S7["📱 KindcheckForm"]
I4 --> S4
I5 --> S5
I6 --> S6
I7 --> S7
end
subgraph AFSLUITEN["🟣 AFSLUITEN"]
I8["🎤 Sluit intake af"]
I9["🎤 Samenvatting intake"]
S8["📱 IntakeSummaryBlock"]
S9["📱 Status: Afgerond ✓"]
I8 --> S9
I9 --> S8
end
SCREENING --> START
START --> UITVOERING
UITVOERING --> AFSLUITEN
AFSLUITEN -->|"Start behandelplan"| BP["📱 BehandelplanView"]
```
---
## Prompt Parameters
| Parameter | Waarde |
|-----------|--------|
| **Model** | DALL-E 3, Ideogram, of Midjourney |
| **Style** | Technical diagram / Software flowchart |
| **Aspect** | 21:9 (ultrawide) voor horizontaal, 9:16 voor verticaal |
| **Kleuren** | Fase-gebonden: blauw→groen→teal→paars |
| **Taal** | Nederlands (intent teksten) |
---
## Tips voor beste resultaat
1. **DALL-E 3**: Beste voor tekst in afbeeldingen, maar kan moeite hebben met complexe diagrammen
2. **Ideogram**: Zeer sterk in diagrammen en flowcharts met tekst
3. **Midjourney**: Mooi visueel maar minder nauwkeurig met tekst
**Aanbeveling**: Gebruik Ideogram voor dit type technische procesflow, of maak het diagram in Figma/Miro en gebruik AI alleen voor styling.