fix(cortex): update date handling in API and UI components

- Adjusted date handling in the agenda API to ensure optional parameters for start, end, and label are correctly processed.
- Enhanced chat input and action parser to support optional date labels for relative dates.
- Updated agenda components to handle date ranges and loading states more effectively.
- Improved error handling and loading indicators in the agenda block for better user experience.

This commit ensures consistency in date handling across the application, aligning with the new requirements for relative date inputs.
This commit is contained in:
colinislit
2026-01-02 09:21:37 +01:00
parent 011815072b
commit 52e07aaf80
20 changed files with 2092 additions and 65 deletions

View File

@@ -31,15 +31,16 @@ const ActionSchema = z.object({
query: z.string().optional(), // For zoeken intent
dateRange: z
.object({
start: z.string(),
end: z.string(),
start: z.string().optional(),
end: z.string().optional(),
label: z.string(),
})
.optional(),
datetime: z
.object({
date: z.string(),
time: z.string(),
date: z.string().optional(),
time: z.string().optional(),
label: z.string().optional(), // Voor relatieve datums: vandaag, morgen, etc.
})
.optional(),
appointmentType: z.string().optional(),
@@ -61,6 +62,7 @@ const ActionSchema = z.object({
.object({
date: z.string().optional(),
time: z.string().optional(),
label: z.string().optional(), // Voor relatieve datums
})
.optional(),
}),
@@ -197,6 +199,56 @@ export function getConfidenceLabel(confidence: number): string {
return 'Zeer onzeker';
}
/**
* Generate a default confirmation message for an intent when AI response has no text
*/
export function getDefaultConfirmationMessage(intent: CortexIntent, entities: Record<string, any>): string {
const dateLabel = entities?.dateRange?.label || entities?.datetime?.label;
const patientName = entities?.patientName;
switch (intent) {
case 'agenda_query':
if (dateLabel) {
return `Ik toon je de afspraken voor ${dateLabel}.`;
}
return 'Ik toon je de agenda.';
case 'create_appointment':
if (patientName && dateLabel) {
return `Ik open het afspraakformulier voor ${patientName} op ${dateLabel}.`;
}
if (patientName) {
return `Ik open het afspraakformulier voor ${patientName}.`;
}
return 'Ik open het afspraakformulier.';
case 'cancel_appointment':
return 'Ik help je met het annuleren van een afspraak.';
case 'reschedule_appointment':
return 'Ik help je met het verzetten van een afspraak.';
case 'dagnotitie':
if (patientName) {
return `Ik open de dagnotitie voor ${patientName}.`;
}
return 'Ik open het dagnotitie formulier.';
case 'zoeken':
const query = entities?.query || entities?.patientName;
if (query) {
return `Ik zoek naar "${query}".`;
}
return 'Ik open de zoekfunctie.';
case 'overdracht':
return 'Ik bereid de overdracht voor.';
default:
return 'Ik help je verder.';
}
}
/**
* Validate that artifact type matches intent
*/

109
lib/cortex/suggestions.ts Normal file
View File

@@ -0,0 +1,109 @@
/**
* Cortex Suggestion Data
*
* Defines categories and example sentences for the Intent Helper UI.
* Based on implemented intents in lib/cortex/types.ts
*/
import type { CortexIntent } from './types';
export interface SuggestionCategory {
id: string;
label: string;
icon: string;
description: string;
examples: SuggestionExample[];
}
export interface SuggestionExample {
text: string;
intent: CortexIntent;
/** Placeholder marker for patient name */
hasPatientPlaceholder?: boolean;
}
/**
* Suggestion categories with examples
* Based on the 7 implemented intents:
* - dagnotitie
* - zoeken
* - overdracht
* - agenda_query
* - create_appointment
* - cancel_appointment
* - reschedule_appointment
*/
export const SUGGESTION_CATEGORIES: SuggestionCategory[] = [
{
id: 'notities',
label: 'Notities',
icon: '📝',
description: 'Dagnotities en rapportages maken',
examples: [
{ text: 'Notitie [naam] medicatie gegeven', intent: 'dagnotitie', hasPatientPlaceholder: true },
{ text: '[naam] is rustig vandaag', intent: 'dagnotitie', hasPatientPlaceholder: true },
{ text: 'Incident: patient gevallen', intent: 'dagnotitie' },
{ text: 'ADL: hulp bij douchen gegeven', intent: 'dagnotitie' },
],
},
{
id: 'agenda',
label: 'Agenda',
icon: '📅',
description: 'Afspraken bekijken en beheren',
examples: [
{ text: 'Agenda vandaag', intent: 'agenda_query' },
{ text: 'Plan intake [naam] morgen', intent: 'create_appointment', hasPatientPlaceholder: true },
{ text: 'Annuleer afspraak [naam]', intent: 'cancel_appointment', hasPatientPlaceholder: true },
{ text: 'Verzet afspraak naar volgende week', intent: 'reschedule_appointment' },
],
},
{
id: 'zoeken',
label: 'Zoeken',
icon: '🔍',
description: 'Patiënten en dossiers zoeken',
examples: [
{ text: 'Zoek [naam]', intent: 'zoeken', hasPatientPlaceholder: true },
{ text: 'Wie is mevrouw de Vries?', intent: 'zoeken' },
{ text: 'Dossier Jan Pietersen', intent: 'zoeken' },
{ text: 'Patiënt kamer 12', intent: 'zoeken' },
],
},
{
id: 'overdracht',
label: 'Overdracht',
icon: '📋',
description: 'Dienstoverdrachten en samenvattingen',
examples: [
{ text: 'Overdracht', intent: 'overdracht' },
{ text: 'Wat is er gebeurd vandaag?', intent: 'overdracht' },
{ text: 'Samenvatting voor collega', intent: 'overdracht' },
{ text: 'Aandachtspunten voor de nacht', intent: 'overdracht' },
],
},
];
/**
* Get a flat list of all examples for quick access
*/
export function getAllExamples(): SuggestionExample[] {
return SUGGESTION_CATEGORIES.flatMap((category) => category.examples);
}
/**
* Get examples for a specific category
*/
export function getExamplesByCategory(categoryId: string): SuggestionExample[] {
const category = SUGGESTION_CATEGORIES.find((c) => c.id === categoryId);
return category?.examples ?? [];
}
/**
* Replace placeholder [naam] with actual patient name
*/
export function replacePlaceholder(text: string, patientName?: string): string {
if (!patientName) return text;
return text.replace(/\[naam\]/g, patientName);
}