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:
62
app/api/cortex/noshow/context/route.ts
Normal file
62
app/api/cortex/noshow/context/route.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { createClient } from '@/lib/auth/server';
|
||||
import { isMockPatient, MOCK_CONCEPT_BRIEF } from '@/lib/cortex/mock-data/noshow';
|
||||
|
||||
export async function GET(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 });
|
||||
}
|
||||
|
||||
const { searchParams } = new URL(request.url);
|
||||
const patientId = searchParams.get('patientId');
|
||||
|
||||
if (!patientId) {
|
||||
return NextResponse.json({ error: 'patientId is verplicht' }, { status: 400 });
|
||||
}
|
||||
|
||||
// Mock path — demo flow
|
||||
if (isMockPatient(patientId)) {
|
||||
return NextResponse.json({
|
||||
hasConceptBrief: true,
|
||||
document: {
|
||||
id: MOCK_CONCEPT_BRIEF.id,
|
||||
title: MOCK_CONCEPT_BRIEF.title,
|
||||
content: MOCK_CONCEPT_BRIEF.content,
|
||||
type: MOCK_CONCEPT_BRIEF.type,
|
||||
createdAt: MOCK_CONCEPT_BRIEF.createdAt,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Productie path
|
||||
const { data, error } = await supabase
|
||||
.from('reports')
|
||||
.select('id, content, structured_data, type, created_at')
|
||||
.eq('patient_id', patientId)
|
||||
.eq('type', 'huisartsbrief')
|
||||
.is('deleted_at', null)
|
||||
.order('created_at', { ascending: false })
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
if (error || !data) {
|
||||
return NextResponse.json({ hasConceptBrief: false });
|
||||
}
|
||||
|
||||
const content = (data.structured_data as Record<string, unknown>)?.content as string
|
||||
?? data.content
|
||||
?? '';
|
||||
|
||||
return NextResponse.json({
|
||||
hasConceptBrief: true,
|
||||
document: {
|
||||
id: data.id,
|
||||
title: 'Huisartsbrief',
|
||||
content,
|
||||
type: data.type,
|
||||
createdAt: data.created_at,
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user