# πŸš€ 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 { data: T | null; isLoading: boolean; error: string | null; refetch: () => Promise; } // 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 |