/** * Exam-marker types — mirror the FastAPI /api/exam contract (see api routers/exam/schemas.py). * Supabase is source of truth for this operational data; the graph (cc.public.exams) joins by * the shared UUIDs (template/question/region ids, exam_code). */ export type ExamTemplateStatus = 'draft' | 'ready' | 'archived'; export interface ExamTemplate { id: string; title: string; subject: string | null; exam_id: string | null; exam_code: string | null; source_file_id: string | null; page_count: number | null; institute_id: string; teacher_id: string; status: ExamTemplateStatus; created_at: string; updated_at: string; } export interface CreateTemplatePayload { title: string; subject?: string; exam_id?: string; exam_code?: string; source_file_id?: string; page_count?: number; institute_id?: string; } export type MarkSchemeType = 'points' | 'levels' | 'parts' | 'checklist' | 'free'; export interface MarkSchemePoint { mark: number; text: string; } export interface MarkSchemeLevel { level: string; min: number; max: number; descriptor: string; } export interface MarkSchemePart { label: string; marks: number; guidance: string; } export interface MarkSchemeChecklistItem { text: string; marks: number; } export interface MarkScheme { type?: MarkSchemeType; points?: MarkSchemePoint[]; levels?: MarkSchemeLevel[]; parts?: MarkSchemePart[]; checklist?: MarkSchemeChecklistItem[]; text?: string; notes?: string; [key: string]: unknown; } /** Canvas children (used from S4-9 onward; defined here so the seam is complete). */ export interface ExamQuestion { id: string; template_id: string; parent_id: string | null; label: string; order: number; max_marks: number; answer_type: string | null; mcq_options: unknown | null; mark_scheme: MarkScheme; is_container: boolean; spec_ref: string | null; bounds?: Record | null; page?: number | null; } export interface ExamResponseArea { id: string; question_id: string; template_id: string; page: number; bounds: Record; kind: 'response' | 'context' | 'question_number' | 'mark_area' | 'reference' | 'furniture'; response_form: string | null; context_type?: string | null; source: 'manual' | 'ai'; confirmed: boolean; confidence: number | null; } export interface ExamBoundary { id: string; template_id: string; question_id: string | null; label: string | null; page_index: number; y: number; bounds: Record | null; source: 'manual' | 'ai'; confirmed: boolean; } export interface ExamTemplateDetail extends ExamTemplate { questions: ExamQuestion[]; response_areas: ExamResponseArea[]; boundaries: ExamBoundary[]; } export interface PatchQuestionPayload { label?: string; order?: number; max_marks?: number; answer_type?: 'written' | 'mcq' | 'short' | 'diagram' | null; mcq_options?: unknown; mark_scheme?: MarkScheme; is_container?: boolean; spec_ref?: string | null; } export interface SpecPoint { uid?: string; uuid_string?: string; ref: string; description: string; spec_code: string; exam_board_code?: string; } export interface Neo4jSyncResult { status: string; projection?: Record; }