Diagnose Module: - Diagnose overzicht pagina met alle patiënt diagnoses - Diagnosis manager met ICD-10 combobox zoekfunctie - Diagnose kaarten met hoofddiagnose markering - Modal voor nieuwe/bewerkte diagnoses - ICD-10 GGZ codes dataset (lib/data/) - Zod schemas voor diagnose validatie - TypeScript types voor ICD-10 (lib/types/icd10.ts) - Complete documentatie (PRD, FO, TO, Bouwplan) Agenda Uitbreidingen: - Patient context card in afspraak modal - Rapportage composer direct in afspraak modal - Rapportage bewerken vanuit gekoppelde rapportages - Verbeterde focus styling voor inputs Behandelplan: - Flat componenten structuur (behandeldoel-card, form, planning) - Context header component - Uitgebreide types (lib/types/behandelplan.ts) - Actions voor behandelplan beheer UI Componenten: - Command component (shadcn/ui) voor combobox - Popover component (shadcn/ui) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
621 lines
18 KiB
TypeScript
621 lines
18 KiB
TypeScript
/**
|
|
* Behandelplan (Treatment Plan) Types
|
|
*
|
|
* Types voor AI-gegenereerde behandelplannen
|
|
* Gebaseerd op FHIR CarePlan met GGZ-specifieke uitbreidingen
|
|
*/
|
|
|
|
import { z } from 'zod';
|
|
import { type LifeDomain, type LifeDomainScore, LIFE_DOMAINS, PRIORITIES } from './leefgebieden';
|
|
|
|
// =============================================================================
|
|
// STATUS TYPES
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Status van een behandelplan
|
|
*/
|
|
export const PLAN_STATUSES = ['concept', 'actief', 'in_evaluatie', 'afgerond', 'gearchiveerd'] as const;
|
|
export type PlanStatus = typeof PLAN_STATUSES[number];
|
|
|
|
/**
|
|
* Status van een doel
|
|
*/
|
|
export const GOAL_STATUSES = ['niet_gestart', 'bezig', 'gehaald', 'bijgesteld'] as const;
|
|
export type GoalStatus = typeof GOAL_STATUSES[number];
|
|
|
|
/**
|
|
* Type evaluatiemoment
|
|
*/
|
|
export const EVALUATION_TYPES = ['tussentijds', 'eind', 'crisis'] as const;
|
|
export type EvaluationType = typeof EVALUATION_TYPES[number];
|
|
|
|
/**
|
|
* Status evaluatiemoment
|
|
*/
|
|
export const EVALUATION_STATUSES = ['gepland', 'afgerond', 'overgeslagen'] as const;
|
|
export type EvaluationStatus = typeof EVALUATION_STATUSES[number];
|
|
|
|
// =============================================================================
|
|
// CORE TYPES
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Behandelstructuur - algemene parameters van het plan
|
|
*/
|
|
export interface Behandelstructuur {
|
|
duur: string; // bijv. "8 weken"
|
|
frequentie: string; // bijv. "Wekelijks"
|
|
aantalSessies: number; // bijv. 8
|
|
vorm: string; // bijv. "Individueel"
|
|
}
|
|
|
|
/**
|
|
* SMART Doel
|
|
*/
|
|
export interface SmartGoal {
|
|
id: string;
|
|
title: string; // Korte beschrijving (1 zin)
|
|
description: string; // SMART-uitwerking (2-3 zinnen)
|
|
clientVersion: string; // B1-taal versie voor cliënt
|
|
lifeDomain: LifeDomain; // Gekoppeld leefgebied
|
|
priority: 'hoog' | 'middel' | 'laag';
|
|
measurability: string; // Hoe meten we vooruitgang?
|
|
timelineWeeks: number; // Binnen X weken
|
|
status: GoalStatus;
|
|
progress: number; // 0-100
|
|
}
|
|
|
|
/**
|
|
* Evidence-based Interventie
|
|
*/
|
|
export interface Intervention {
|
|
id: string;
|
|
name: string; // bijv. "CGT", "EMDR", "ACT"
|
|
description: string; // Uitleg van de interventie
|
|
rationale: string; // Waarom past dit bij deze cliënt?
|
|
linkedGoalIds: string[]; // Welke doelen worden hiermee benaderd?
|
|
}
|
|
|
|
/**
|
|
* Evaluatiemoment
|
|
*/
|
|
export interface Evaluatiemoment {
|
|
id: string;
|
|
type: EvaluationType;
|
|
weekNumber: number;
|
|
plannedDate: string; // ISO date string
|
|
actualDate?: string; // Ingevuld na uitvoering
|
|
status: EvaluationStatus;
|
|
outcome?: string; // Vrije tekst resultaat
|
|
lifeDomainUpdates?: LifeDomainScore[]; // Nieuwe scores
|
|
}
|
|
|
|
/**
|
|
* Veiligheidsplan (alleen bij severity "Hoog")
|
|
*/
|
|
export interface Veiligheidsplan {
|
|
waarschuwingssignalen: string[]; // 3-5 items
|
|
copingStrategieen: string[]; // 3-5 items
|
|
contacten: {
|
|
naam: string;
|
|
rol: string;
|
|
telefoon: string;
|
|
}[];
|
|
restricties?: string[]; // bijv. "Geen alcohol tijdens behandeling"
|
|
}
|
|
|
|
/**
|
|
* Sessie in de planning
|
|
*/
|
|
export interface Sessie {
|
|
id: string;
|
|
nummer: number;
|
|
focus: string;
|
|
datum?: string; // ISO date string
|
|
status: 'gepland' | 'afgerond' | 'no_show' | 'verzet' | 'geannuleerd';
|
|
gekoppeldeDoelIds: string[];
|
|
notities?: string;
|
|
}
|
|
|
|
// =============================================================================
|
|
// GENERATED PLAN (AI OUTPUT)
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Volledig door AI gegenereerd behandelplan
|
|
*/
|
|
export interface GeneratedPlan {
|
|
behandelstructuur: Behandelstructuur;
|
|
doelen: SmartGoal[];
|
|
interventies: Intervention[];
|
|
sessiePlanning: Sessie[];
|
|
evaluatiemomenten: Evaluatiemoment[];
|
|
veiligheidsplan?: Veiligheidsplan; // Alleen bij severity "Hoog"
|
|
}
|
|
|
|
// =============================================================================
|
|
// API INPUT/OUTPUT TYPES
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Input voor behandelplan generatie
|
|
*/
|
|
export interface GenerateBehandelplanInput {
|
|
patientId: string;
|
|
intakeId: string;
|
|
conditionId?: string; // Optioneel, haalt anders laatste op
|
|
extraInstructions?: string; // Optionele aanvullende instructies
|
|
}
|
|
|
|
/**
|
|
* Input voor micro-regeneratie
|
|
*/
|
|
export interface RegenerateSectionInput {
|
|
patientId: string;
|
|
carePlanId: string;
|
|
sectionType: 'goal' | 'intervention';
|
|
sectionId: string;
|
|
instruction?: string; // Extra instructie voor AI
|
|
currentPlan: GeneratedPlan; // Context van huidige plan
|
|
}
|
|
|
|
/**
|
|
* Output van micro-regeneratie
|
|
*/
|
|
export interface RegeneratedSection {
|
|
type: 'goal' | 'intervention';
|
|
original: SmartGoal | Intervention;
|
|
regenerated: SmartGoal | Intervention;
|
|
}
|
|
|
|
// =============================================================================
|
|
// ZOD SCHEMAS
|
|
// =============================================================================
|
|
|
|
export const BehandelstructuurSchema = z.object({
|
|
duur: z.string(),
|
|
frequentie: z.string(),
|
|
aantalSessies: z.number().min(1).max(52),
|
|
vorm: z.string(),
|
|
});
|
|
|
|
export const SmartGoalSchema = z.object({
|
|
id: z.string(),
|
|
title: z.string().min(5).max(200),
|
|
description: z.string().min(10).max(500),
|
|
clientVersion: z.string().min(5).max(300),
|
|
lifeDomain: z.enum(LIFE_DOMAINS),
|
|
priority: z.enum(PRIORITIES),
|
|
measurability: z.string().min(5).max(200),
|
|
timelineWeeks: z.number().min(1).max(52),
|
|
status: z.enum(GOAL_STATUSES),
|
|
progress: z.number().min(0).max(100),
|
|
});
|
|
|
|
export const InterventionSchema = z.object({
|
|
id: z.string(),
|
|
name: z.string().min(2).max(100),
|
|
description: z.string().min(10).max(500),
|
|
rationale: z.string().min(10).max(500),
|
|
linkedGoalIds: z.array(z.string()),
|
|
});
|
|
|
|
export const EvaluatiemomentSchema = z.object({
|
|
id: z.string(),
|
|
type: z.enum(EVALUATION_TYPES),
|
|
weekNumber: z.number().min(1).max(52),
|
|
plannedDate: z.string(),
|
|
actualDate: z.string().optional(),
|
|
status: z.enum(EVALUATION_STATUSES),
|
|
outcome: z.string().optional(),
|
|
lifeDomainUpdates: z.array(z.any()).optional(), // Simplified for now
|
|
});
|
|
|
|
export const VeiligheidsplanSchema = z.object({
|
|
waarschuwingssignalen: z.array(z.string()).min(1).max(10),
|
|
copingStrategieen: z.array(z.string()).min(1).max(10),
|
|
contacten: z.array(z.object({
|
|
naam: z.string(),
|
|
rol: z.string(),
|
|
telefoon: z.string(),
|
|
})),
|
|
restricties: z.array(z.string()).optional(),
|
|
});
|
|
|
|
export const SessieSchema = z.object({
|
|
id: z.string(),
|
|
nummer: z.number().min(1),
|
|
focus: z.string(),
|
|
datum: z.string().optional(),
|
|
status: z.enum(['gepland', 'afgerond', 'no_show', 'verzet', 'geannuleerd']),
|
|
gekoppeldeDoelIds: z.array(z.string()),
|
|
notities: z.string().optional(),
|
|
});
|
|
|
|
export const GeneratedPlanSchema = z.object({
|
|
behandelstructuur: BehandelstructuurSchema,
|
|
doelen: z.array(SmartGoalSchema).min(1).max(6),
|
|
interventies: z.array(InterventionSchema).min(1).max(5),
|
|
sessiePlanning: z.array(SessieSchema),
|
|
evaluatiemomenten: z.array(EvaluatiemomentSchema).min(1),
|
|
veiligheidsplan: VeiligheidsplanSchema.optional(),
|
|
});
|
|
|
|
export const GenerateBehandelplanInputSchema = z.object({
|
|
patientId: z.string().uuid(),
|
|
intakeId: z.string().uuid(),
|
|
conditionId: z.string().uuid().optional(),
|
|
extraInstructions: z.string().max(500).optional(),
|
|
});
|
|
|
|
export const RegenerateSectionInputSchema = z.object({
|
|
patientId: z.string().uuid(),
|
|
carePlanId: z.string().uuid(),
|
|
sectionType: z.enum(['goal', 'intervention']),
|
|
sectionId: z.string(),
|
|
instruction: z.string().max(200).optional(),
|
|
currentPlan: GeneratedPlanSchema,
|
|
});
|
|
|
|
// =============================================================================
|
|
// HELPER FUNCTIONS
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Genereer een nieuw UUID-achtig ID
|
|
*/
|
|
export function generateId(): string {
|
|
return crypto.randomUUID();
|
|
}
|
|
|
|
/**
|
|
* Maak een nieuw leeg SMART doel
|
|
*/
|
|
export function createEmptyGoal(lifeDomain: LifeDomain = 'dlv'): SmartGoal {
|
|
return {
|
|
id: generateId(),
|
|
title: '',
|
|
description: '',
|
|
clientVersion: '',
|
|
lifeDomain,
|
|
priority: 'middel',
|
|
measurability: '',
|
|
timelineWeeks: 8,
|
|
status: 'niet_gestart',
|
|
progress: 0,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Maak een nieuwe lege interventie
|
|
*/
|
|
export function createEmptyIntervention(): Intervention {
|
|
return {
|
|
id: generateId(),
|
|
name: '',
|
|
description: '',
|
|
rationale: '',
|
|
linkedGoalIds: [],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Bereken totale voortgang van alle doelen
|
|
*/
|
|
export function calculateTotalProgress(goals: SmartGoal[]): number {
|
|
if (goals.length === 0) return 0;
|
|
const sum = goals.reduce((acc, goal) => acc + goal.progress, 0);
|
|
return Math.round(sum / goals.length);
|
|
}
|
|
|
|
/**
|
|
* Krijg doelen per leefgebied
|
|
*/
|
|
export function getGoalsByDomain(goals: SmartGoal[]): Record<LifeDomain, SmartGoal[]> {
|
|
const result = {} as Record<LifeDomain, SmartGoal[]>;
|
|
for (const domain of LIFE_DOMAINS) {
|
|
result[domain] = goals.filter((g) => g.lifeDomain === domain);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check of plan klaar is voor publicatie
|
|
*/
|
|
export function canPublish(plan: GeneratedPlan): { valid: boolean; errors: string[] } {
|
|
const errors: string[] = [];
|
|
|
|
if (plan.doelen.length === 0) {
|
|
errors.push('Minimaal 1 doel is vereist');
|
|
}
|
|
|
|
if (plan.interventies.length === 0) {
|
|
errors.push('Minimaal 1 interventie is vereist');
|
|
}
|
|
|
|
if (!plan.behandelstructuur.duur || !plan.behandelstructuur.frequentie) {
|
|
errors.push('Behandelstructuur moet compleet zijn');
|
|
}
|
|
|
|
if (plan.evaluatiemomenten.length < 2) {
|
|
errors.push('Minimaal 2 evaluatiemomenten zijn vereist');
|
|
}
|
|
|
|
return {
|
|
valid: errors.length === 0,
|
|
errors,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Status label voor UI (oude Nederlandse keys - deprecated)
|
|
*/
|
|
export const PLAN_STATUS_LABELS: Record<PlanStatus, { label: string; color: string }> = {
|
|
concept: { label: 'Concept', color: '#60a5fa' }, // blauw
|
|
actief: { label: 'Actief', color: '#10b981' }, // groen
|
|
in_evaluatie: { label: 'In evaluatie', color: '#f59e0b' }, // oranje
|
|
afgerond: { label: 'Afgerond', color: '#6b7280' }, // grijs
|
|
gearchiveerd: { label: 'Gearchiveerd', color: '#9ca3af' }, // lichtgrijs
|
|
};
|
|
|
|
/**
|
|
* FHIR status naar Nederlandse UI labels
|
|
* Database gebruikt FHIR statussen, UI toont Nederlands
|
|
*/
|
|
export type FhirCarePlanStatus = 'draft' | 'active' | 'on-hold' | 'completed' | 'revoked' | 'entered-in-error' | 'unknown';
|
|
|
|
export const FHIR_STATUS_LABELS: Record<FhirCarePlanStatus, { label: string; color: string }> = {
|
|
draft: { label: 'Concept', color: '#60a5fa' }, // blauw
|
|
active: { label: 'Actueel', color: '#10b981' }, // groen
|
|
'on-hold': { label: 'Gepauzeerd', color: '#f59e0b' }, // oranje
|
|
completed: { label: 'Definitief', color: '#6b7280' }, // grijs
|
|
revoked: { label: 'Archief', color: '#9ca3af' }, // lichtgrijs
|
|
'entered-in-error': { label: 'Verwijderd', color: '#ef4444' }, // rood
|
|
unknown: { label: 'Onbekend', color: '#9ca3af' }, // lichtgrijs
|
|
};
|
|
|
|
/**
|
|
* Goal status label voor UI
|
|
*/
|
|
export const GOAL_STATUS_LABELS: Record<GoalStatus, { label: string; color: string }> = {
|
|
niet_gestart: { label: 'Niet gestart', color: '#9ca3af' },
|
|
bezig: { label: 'Bezig', color: '#3b82f6' },
|
|
gehaald: { label: 'Gehaald', color: '#10b981' },
|
|
bijgesteld: { label: 'Bijgesteld', color: '#f59e0b' },
|
|
};
|
|
|
|
// =============================================================================
|
|
// FLAT BEHANDELPLAN TYPES (Nieuwe platte structuur)
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Embedded interventie binnen een behandeldoel
|
|
* Simpelere versie zonder linkedGoalIds (want embedded in doel)
|
|
*/
|
|
export interface EmbeddedInterventie {
|
|
id: string;
|
|
name: string; // bijv. "CGT", "EMDR", "ACT"
|
|
description: string; // Korte beschrijving van de aanpak
|
|
}
|
|
|
|
/**
|
|
* Behandeldoel met embedded interventies
|
|
* Kerntype voor de "platte" behandelplan structuur
|
|
*/
|
|
export interface Behandeldoel {
|
|
id: string;
|
|
|
|
// Doel informatie
|
|
title: string; // Professionele formulering
|
|
clientVersion: string; // B1-taal versie voor cliënt
|
|
|
|
// Classificatie
|
|
lifeDomain: LifeDomain; // Gekoppeld leefgebied
|
|
|
|
// Embedded interventies (KERNVERANDERING - niet meer apart)
|
|
interventies: EmbeddedInterventie[];
|
|
|
|
// Timeline
|
|
startWeek: number; // Start week (1-52)
|
|
endWeek: number; // Eind week (1-52)
|
|
|
|
// Status & voortgang
|
|
status: GoalStatus;
|
|
progress: number; // 0-100
|
|
}
|
|
|
|
// =============================================================================
|
|
// FLAT BEHANDELPLAN ZOD SCHEMAS
|
|
// =============================================================================
|
|
|
|
export const EmbeddedInterventieSchema = z.object({
|
|
id: z.string(),
|
|
name: z.string().min(1).max(100),
|
|
description: z.string().max(500),
|
|
});
|
|
|
|
export const BehandeldoelSchema = z.object({
|
|
id: z.string(),
|
|
title: z.string().min(5).max(200),
|
|
clientVersion: z.string().min(5).max(300),
|
|
lifeDomain: z.enum(LIFE_DOMAINS),
|
|
interventies: z.array(EmbeddedInterventieSchema),
|
|
startWeek: z.number().min(1).max(52),
|
|
endWeek: z.number().min(1).max(52),
|
|
status: z.enum(GOAL_STATUSES),
|
|
progress: z.number().min(0).max(100),
|
|
});
|
|
|
|
/**
|
|
* Schema voor AI-gegenereerd flat behandelplan
|
|
*/
|
|
export const GeneratedPlanFlatSchema = z.object({
|
|
behandelstructuur: BehandelstructuurSchema,
|
|
behandeldoelen: z.array(BehandeldoelSchema).min(1).max(6),
|
|
evaluatiemomenten: z.array(EvaluatiemomentSchema).min(1),
|
|
veiligheidsplan: VeiligheidsplanSchema.optional(),
|
|
});
|
|
|
|
export type GeneratedPlanFlat = z.infer<typeof GeneratedPlanFlatSchema>;
|
|
|
|
// =============================================================================
|
|
// TRANSFORMATIE FUNCTIES (Oude <-> Nieuwe structuur)
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Transformeer oude structuur (goals + interventions apart) naar flat (behandeldoelen)
|
|
* Koppelt interventies aan doelen op basis van linkedGoalIds
|
|
*/
|
|
export function transformToFlat(
|
|
goals: SmartGoal[],
|
|
interventions: Intervention[]
|
|
): Behandeldoel[] {
|
|
return goals.map((goal) => {
|
|
// Vind interventies die aan dit doel gekoppeld zijn
|
|
const linkedInterventions = interventions
|
|
.filter((int) => int.linkedGoalIds.includes(goal.id))
|
|
.map((int) => ({
|
|
id: int.id,
|
|
name: int.name,
|
|
description: int.description,
|
|
}));
|
|
|
|
return {
|
|
id: goal.id,
|
|
title: goal.title,
|
|
clientVersion: goal.clientVersion,
|
|
lifeDomain: goal.lifeDomain,
|
|
interventies: linkedInterventions,
|
|
startWeek: 1, // Default, kan later uit goal.timelineWeeks berekend worden
|
|
endWeek: goal.timelineWeeks,
|
|
status: goal.status,
|
|
progress: goal.progress,
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Transformeer flat structuur terug naar oude structuur (voor backwards compatibility)
|
|
* Zet embedded interventies om naar aparte array met linkedGoalIds
|
|
*/
|
|
export function transformFromFlat(behandeldoelen: Behandeldoel[]): {
|
|
goals: SmartGoal[];
|
|
interventions: Intervention[];
|
|
} {
|
|
const goals: SmartGoal[] = [];
|
|
const interventionMap = new Map<string, Intervention>();
|
|
|
|
for (const doel of behandeldoelen) {
|
|
// Maak SmartGoal van Behandeldoel
|
|
goals.push({
|
|
id: doel.id,
|
|
title: doel.title,
|
|
description: '', // Niet meer gebruikt in flat structuur
|
|
clientVersion: doel.clientVersion,
|
|
lifeDomain: doel.lifeDomain,
|
|
priority: 'middel', // Default
|
|
measurability: '', // Niet meer gebruikt in flat structuur
|
|
timelineWeeks: doel.endWeek,
|
|
status: doel.status,
|
|
progress: doel.progress,
|
|
});
|
|
|
|
// Verzamel interventies en koppel aan doel
|
|
for (const int of doel.interventies) {
|
|
const existing = interventionMap.get(int.id);
|
|
if (existing) {
|
|
// Interventie bestaat al, voeg dit doel toe aan linkedGoalIds
|
|
existing.linkedGoalIds.push(doel.id);
|
|
} else {
|
|
// Nieuwe interventie
|
|
interventionMap.set(int.id, {
|
|
id: int.id,
|
|
name: int.name,
|
|
description: int.description,
|
|
rationale: '', // Niet meer gebruikt in flat structuur
|
|
linkedGoalIds: [doel.id],
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
goals,
|
|
interventions: Array.from(interventionMap.values()),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Maak een nieuw leeg behandeldoel
|
|
*/
|
|
export function createEmptyBehandeldoel(lifeDomain: LifeDomain = 'dlv'): Behandeldoel {
|
|
return {
|
|
id: generateId(),
|
|
title: '',
|
|
clientVersion: '',
|
|
lifeDomain,
|
|
interventies: [],
|
|
startWeek: 1,
|
|
endWeek: 8,
|
|
status: 'niet_gestart',
|
|
progress: 0,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Maak een nieuwe lege embedded interventie
|
|
*/
|
|
export function createEmptyEmbeddedInterventie(): EmbeddedInterventie {
|
|
return {
|
|
id: generateId(),
|
|
name: '',
|
|
description: '',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Bereken totale voortgang van behandeldoelen
|
|
*/
|
|
export function calculateBehandeldoelenProgress(doelen: Behandeldoel[]): number {
|
|
if (doelen.length === 0) return 0;
|
|
const sum = doelen.reduce((acc, doel) => acc + doel.progress, 0);
|
|
return Math.round(sum / doelen.length);
|
|
}
|
|
|
|
/**
|
|
* Check of flat plan klaar is voor publicatie
|
|
*/
|
|
export function canPublishFlat(
|
|
behandeldoelen: Behandeldoel[],
|
|
behandelstructuur: Behandelstructuur,
|
|
evaluatiemomenten: Evaluatiemoment[]
|
|
): { valid: boolean; errors: string[] } {
|
|
const errors: string[] = [];
|
|
|
|
if (behandeldoelen.length === 0) {
|
|
errors.push('Minimaal 1 behandeldoel is vereist');
|
|
}
|
|
|
|
// Check of elk doel minimaal 1 interventie heeft
|
|
const doelenZonderInterventie = behandeldoelen.filter(
|
|
(d) => d.interventies.length === 0
|
|
);
|
|
if (doelenZonderInterventie.length > 0) {
|
|
errors.push('Elk behandeldoel moet minimaal 1 interventie hebben');
|
|
}
|
|
|
|
if (!behandelstructuur.duur || !behandelstructuur.frequentie) {
|
|
errors.push('Behandelstructuur moet compleet zijn');
|
|
}
|
|
|
|
if (evaluatiemomenten.length < 2) {
|
|
errors.push('Minimaal 2 evaluatiemomenten zijn vereist');
|
|
}
|
|
|
|
return {
|
|
valid: errors.length === 0,
|
|
errors,
|
|
};
|
|
}
|