feat(cortex): no-show casus — intent flow, brief-rescript en document artifact
Cortex handelt een no-show af vanuit één chatcommando: afspraak annuleren (declarabiliteits-nudge), en de openstaande concept- huisartsbrief wordt via LLM herschreven en ter review aangeboden in een document artifact (human-in-the-loop, PATCH dispatch zet status op verzendklaar). - API-routes: context, rescript, cancel, dispatch - NoShowDocumentBlock: review/edit UI met origineel-vergelijk - Mock-data voor concept huisartsbrief - PRD, FO, bouwplan en epics in docs/intent/noshow-case/ Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
51
app/api/cortex/noshow/cancel/route.ts
Normal file
51
app/api/cortex/noshow/cancel/route.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { z } from 'zod';
|
||||
import { createClient } from '@/lib/auth/server';
|
||||
import { isMockAppointment } from '@/lib/cortex/mock-data/noshow';
|
||||
|
||||
const CancelNoShowSchema = z.object({
|
||||
appointmentId: z.string().min(1, 'appointmentId is verplicht'),
|
||||
patientId: z.string().min(1, 'patientId is verplicht'),
|
||||
});
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const supabase = await createClient();
|
||||
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
||||
if (authError || !user) {
|
||||
return NextResponse.json({ error: 'Niet geautoriseerd' }, { status: 401 });
|
||||
}
|
||||
|
||||
let body: z.infer<typeof CancelNoShowSchema>;
|
||||
try {
|
||||
body = CancelNoShowSchema.parse(await request.json());
|
||||
} catch {
|
||||
return NextResponse.json({ error: 'Ongeldige invoer' }, { status: 400 });
|
||||
}
|
||||
|
||||
const { appointmentId, patientId } = body;
|
||||
|
||||
// Mock path — demo flow
|
||||
if (isMockAppointment(appointmentId)) {
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
appointmentId,
|
||||
newStatus: 'cancelled_no_show',
|
||||
message: 'Afspraak geregistreerd als no show (demo)',
|
||||
});
|
||||
}
|
||||
|
||||
// Productie path — 'cancelled' is de dichtstbijzijnde geldige DB status
|
||||
// In productie zou je een aparte no_show kolom of notitieveld gebruiken
|
||||
const { error } = await supabase
|
||||
.from('encounters')
|
||||
.update({ status: 'cancelled' as 'cancelled' })
|
||||
.eq('id', appointmentId)
|
||||
.eq('patient_id', patientId);
|
||||
|
||||
if (error) {
|
||||
console.error('[noshow/cancel] DB error:', error);
|
||||
return NextResponse.json({ error: 'Annuleren mislukt' }, { status: 500 });
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true, appointmentId, newStatus: 'cancelled_no_show' });
|
||||
}
|
||||
Reference in New Issue
Block a user