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:
@@ -42,10 +42,11 @@ export async function GET(request: NextRequest) {
|
||||
}
|
||||
|
||||
// Parse and validate query parameters
|
||||
// Note: searchParams.get() returns null if not present, but Zod expects undefined
|
||||
const searchParams = request.nextUrl.searchParams;
|
||||
const start = searchParams.get('start');
|
||||
const end = searchParams.get('end');
|
||||
const label = searchParams.get('label');
|
||||
const start = searchParams.get('start') ?? undefined;
|
||||
const end = searchParams.get('end') ?? undefined;
|
||||
const label = searchParams.get('label') ?? undefined;
|
||||
|
||||
const validation = QuerySchema.safeParse({ start, end, label });
|
||||
if (!validation.success) {
|
||||
|
||||
@@ -110,6 +110,27 @@ Je helpt zorgmedewerkers (verpleegkundigen, psychiaters, behandelaren) met docum
|
||||
- Kort en to-the-point (geen lange uitleg)
|
||||
- Empatisch voor werkdruk zorgmedewerkers
|
||||
|
||||
## BELANGRIJK: Datum/Tijd Handling
|
||||
|
||||
**Stuur ALLEEN labels, GEEN datums!** De client berekent de exacte datum zelf.
|
||||
|
||||
Toegestane labels:
|
||||
- "vandaag", "morgen", "overmorgen"
|
||||
- "deze week", "volgende week"
|
||||
- "maandag", "dinsdag", etc. (weekdagen)
|
||||
|
||||
Voorbeeld datetime entity:
|
||||
\`\`\`json
|
||||
{
|
||||
"datetime": {
|
||||
"label": "morgen",
|
||||
"time": "14:00"
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
**NOOIT** een "date" veld met een ISO-datum string sturen. De client bepaalt de datum op basis van het label.
|
||||
|
||||
## Wat je DOET
|
||||
|
||||
### 1. Intents herkennen
|
||||
@@ -138,12 +159,12 @@ Je herkent de volgende gebruikersintenties en voert acties uit:
|
||||
|
||||
- **agenda_query** — Afspraken opvragen
|
||||
- Triggers: "afspraken vandaag", "agenda morgen", "wat is mijn volgende afspraak", "afspraken deze week"
|
||||
- Entities: dateRange (vandaag/morgen/deze week/volgende week)
|
||||
- Entities: dateRange (alleen label: "vandaag"/"morgen"/"deze week"/"volgende week" — GEEN datums!)
|
||||
- Actie: Toon lijst van afspraken in AgendaBlock
|
||||
|
||||
- **create_appointment** — Nieuwe afspraak maken
|
||||
- Triggers: "maak afspraak [patient]", "plan intake [patient]", "afspraak maken met [patient] [datum] [tijd]"
|
||||
- Entities: patientName (naam), datetime (datum + tijd), appointmentType (intake/behandeling/follow-up/telefonisch/huisbezoek/online/crisis), location (praktijk/online/thuis)
|
||||
- Entities: patientName (naam), datetime (label + tijd), appointmentType (intake/behandeling/follow-up/telefonisch/huisbezoek/online/crisis), location (praktijk/online/thuis)
|
||||
- Required: patientName OF patientId, datetime
|
||||
- Optional: appointmentType (default: behandeling), location (default: praktijk)
|
||||
- Actie: Open create form met pre-fill
|
||||
@@ -346,8 +367,6 @@ Je hebt toegang tot de volgende context:
|
||||
"intent": "agenda_query",
|
||||
"entities": {
|
||||
"dateRange": {
|
||||
"start": "2025-12-27",
|
||||
"end": "2025-12-27",
|
||||
"label": "vandaag"
|
||||
}
|
||||
},
|
||||
@@ -356,8 +375,6 @@ Je hebt toegang tot de volgende context:
|
||||
"type": "agenda_query",
|
||||
"prefill": {
|
||||
"dateRange": {
|
||||
"start": "2025-12-27",
|
||||
"end": "2025-12-27",
|
||||
"label": "vandaag"
|
||||
}
|
||||
}
|
||||
@@ -380,7 +397,7 @@ Je hebt toegang tot de volgende context:
|
||||
"entities": {
|
||||
"patientName": "Jan",
|
||||
"datetime": {
|
||||
"date": "2025-12-28",
|
||||
"label": "morgen",
|
||||
"time": "14:00"
|
||||
},
|
||||
"appointmentType": "behandeling",
|
||||
@@ -392,7 +409,7 @@ Je hebt toegang tot de volgende context:
|
||||
"prefill": {
|
||||
"patientName": "Jan",
|
||||
"datetime": {
|
||||
"date": "2025-12-28",
|
||||
"label": "morgen",
|
||||
"time": "14:00"
|
||||
},
|
||||
"appointmentType": "behandeling",
|
||||
@@ -430,7 +447,6 @@ Je hebt toegang tot de volgende context:
|
||||
"time": "14:00"
|
||||
},
|
||||
"newDatetime": {
|
||||
"date": "2025-12-27",
|
||||
"time": "15:00"
|
||||
}
|
||||
},
|
||||
@@ -443,7 +459,6 @@ Je hebt toegang tot de volgende context:
|
||||
"time": "14:00"
|
||||
},
|
||||
"newDatetime": {
|
||||
"date": "2025-12-27",
|
||||
"time": "15:00"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,28 +107,47 @@ interface CreateEncounterParams {
|
||||
export async function createEncounter(params: CreateEncounterParams) {
|
||||
const supabase = await createClient();
|
||||
|
||||
console.log('[createEncounter] Starting with params:', {
|
||||
patientId: params.patientId,
|
||||
periodStart: params.periodStart,
|
||||
periodEnd: params.periodEnd,
|
||||
typeCode: params.typeCode,
|
||||
});
|
||||
|
||||
const insertData = {
|
||||
patient_id: params.patientId,
|
||||
practitioner_id: params.practitionerId || null,
|
||||
period_start: params.periodStart,
|
||||
period_end: params.periodEnd,
|
||||
type_code: params.typeCode,
|
||||
type_display: params.typeDisplay,
|
||||
class_code: params.classCode,
|
||||
class_display: params.classDisplay,
|
||||
notes: params.notes,
|
||||
status: 'planned',
|
||||
};
|
||||
|
||||
console.log('[createEncounter] Insert data:', insertData);
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from('encounters')
|
||||
.insert({
|
||||
patient_id: params.patientId,
|
||||
practitioner_id: params.practitionerId || null,
|
||||
period_start: params.periodStart,
|
||||
period_end: params.periodEnd,
|
||||
type_code: params.typeCode,
|
||||
type_display: params.typeDisplay,
|
||||
class_code: params.classCode,
|
||||
class_display: params.classDisplay,
|
||||
notes: params.notes,
|
||||
status: 'planned',
|
||||
})
|
||||
.insert(insertData)
|
||||
.select()
|
||||
.single();
|
||||
|
||||
console.log('[createEncounter] Result:', { data, error });
|
||||
|
||||
if (error) {
|
||||
console.error('Error creating encounter:', error);
|
||||
console.error('[createEncounter] Error:', error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
console.error('[createEncounter] No data returned after insert');
|
||||
return { success: false, error: 'Geen data teruggegeven na insert' };
|
||||
}
|
||||
|
||||
console.log('[createEncounter] Success! Created encounter:', data.id);
|
||||
revalidatePath('/epd/agenda');
|
||||
return { success: true, data };
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ interface AgendaCalendarProps {
|
||||
events: CalendarEvent[];
|
||||
initialView?: CalendarView;
|
||||
currentView?: CalendarView;
|
||||
currentDate?: Date;
|
||||
onEventClick?: (event: CalendarEvent) => void;
|
||||
onDateSelect?: (start: Date, end: Date) => void;
|
||||
onEventDrop?: (eventId: string, newStart: Date, newEnd: Date | null) => void;
|
||||
@@ -31,6 +32,7 @@ export function AgendaCalendar({
|
||||
events,
|
||||
initialView = 'timeGridWeek',
|
||||
currentView,
|
||||
currentDate,
|
||||
onEventClick,
|
||||
onDateSelect,
|
||||
onEventDrop,
|
||||
@@ -47,7 +49,6 @@ export function AgendaCalendar({
|
||||
if (api.view.type !== currentView) {
|
||||
isChangingViewRef.current = true;
|
||||
api.changeView(currentView);
|
||||
// Reset flag after a short delay to allow the view change to complete
|
||||
setTimeout(() => {
|
||||
isChangingViewRef.current = false;
|
||||
}, 100);
|
||||
@@ -55,6 +56,20 @@ export function AgendaCalendar({
|
||||
}
|
||||
}, [currentView]);
|
||||
|
||||
// Sync date when currentDate prop changes
|
||||
useEffect(() => {
|
||||
if (currentDate && internalRef.current) {
|
||||
const api = internalRef.current.getApi();
|
||||
if (api.getDate().toDateString() !== currentDate.toDateString()) {
|
||||
isChangingViewRef.current = true;
|
||||
api.gotoDate(currentDate);
|
||||
setTimeout(() => {
|
||||
isChangingViewRef.current = false;
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
}, [currentDate]);
|
||||
|
||||
const handleEventClick = useCallback((info: EventClickArg) => {
|
||||
if (onEventClick) {
|
||||
const event = info.event;
|
||||
|
||||
@@ -118,7 +118,9 @@ export function AgendaView({ initialEvents, initialDate, highlightEncounterId }:
|
||||
|
||||
// Handle date range change from calendar
|
||||
const handleDateChange = useCallback((start: Date, end: Date) => {
|
||||
setCurrentDate(start);
|
||||
setCurrentDate((prev) =>
|
||||
prev.toDateString() === start.toDateString() ? prev : start
|
||||
);
|
||||
fetchEvents(start, end);
|
||||
}, [fetchEvents]);
|
||||
|
||||
@@ -262,6 +264,7 @@ export function AgendaView({ initialEvents, initialDate, highlightEncounterId }:
|
||||
events={events}
|
||||
initialView={currentView}
|
||||
currentView={currentView}
|
||||
currentDate={currentDate}
|
||||
onEventClick={handleEventClick}
|
||||
onDateSelect={handleDateSelect}
|
||||
onEventDrop={handleEventDrop}
|
||||
|
||||
Reference in New Issue
Block a user