Files
brainwave/frontend/src/types.ts
T
LaurensBartelds 4eeacc38c5
Release Pipeline / build-and-release (push) Successful in 5m24s
feat: replace screen state machine with React Router v7 URL routing
- Install react-router-dom
- Add slugify utility with full TDD test suite (7 tests)
- Wrap app in BrowserRouter in main.tsx
- Add optional onNavigate prop to ExamRunner.goTo
- Create ExamRoute component (deep-link restore + back/forward sync)
- Migrate App.tsx: replace screen useState with <Routes>, all setScreen()
  calls replaced with navigate(), add activateExam for deep-link activation,
  use useLocation for verify/reset-password special layouts
- Remove unused AppScreen type from types.ts
2026-04-24 23:55:52 +02:00

125 lines
2.4 KiB
TypeScript

// src/types.ts
export type QuestionType =
| "multiple-choice"
| "multiple-select"
| "short-answer"
| "translation"
| "math-input"
| "essay"
| "match"
| "order";
export interface Choice {
id: string;
text: string;
}
export interface MatchItem {
id: string;
text: string;
}
export interface QuestionImage {
src: string;
alt?: string;
caption?: string;
}
export interface QuestionAudio {
src: string;
}
export interface QuestionCode {
language: string;
content: string;
}
export interface QuestionTable {
headers: string[];
rows: string[][];
}
export interface Question {
id: string;
type: QuestionType;
category?: string;
points?: number;
prompt: string;
explanation?: string;
image?: QuestionImage;
audio?: QuestionAudio;
code?: QuestionCode;
table?: QuestionTable;
svg?: string;
answer?: string | string[] | Record<string, string>;
acceptedForms?: string[];
caseSensitive?: boolean;
ignorePunctuation?: boolean;
ignoreAccents?: boolean;
sourceLanguage?: string;
targetLanguage?: string;
choices?: Choice[];
minWords?: number;
rubric?: string[];
left?: MatchItem[];
right?: MatchItem[];
items?: MatchItem[];
}
export interface Exam {
title: string;
subtitle?: string;
author?: string;
timeLimitMinutes?: number | null;
feedbackMode?: "end" | "immediate";
passingScore?: number;
categories?: string[];
questions: Question[];
}
export type FeedbackMode = "immediate" | "end";
export interface ExamState {
currentIdx: number;
answers: Record<string, unknown>;
flags: Record<string, boolean>;
notes: string;
revealed?: Record<string, boolean>;
startedAt: number;
completedAt?: number;
feedbackMode: FeedbackMode;
}
export interface HistoryEntry {
id: string;
title: string;
completedAt: number;
elapsedMs: number;
gradedCount: number;
correctCount: number;
totalPoints: number;
scorePoints: number;
passingScore: number;
exam: Exam;
state: ExamState;
}
export type GradeStatus = "correct" | "wrong" | "ungraded" | "unanswered";
export interface GradeResult {
status: GradeStatus;
correct: boolean;
points: number;
}
export type ThemeMode = "light" | "dark";
export type FontSize = "small" | "medium" | "large";
export type FeedbackTweak = "auto" | "immediate" | "end";
export interface Tweaks {
theme: ThemeMode;
fontSize: FontSize;
feedbackMode: FeedbackTweak;
}