Harden published curriculum and student flows

This commit is contained in:
Hamza-Ayed
2026-09-30 08:22:17 +03:00
parent e8163fe265
commit ce7b0fcf14
53 changed files with 4723 additions and 3317 deletions
@@ -55,6 +55,7 @@ class ErrorNotebookItem {
final String errorCategory; // 'conceptual', 'calculation', 'rushed', 'misinterpretation'
final String status; // 'pending_remediation', 'in_remediation', 'mastered'
final int remediationAttemptsCount;
final bool retentionIsDue;
final String? masteredAt;
final String createdAt;
@@ -72,6 +73,7 @@ class ErrorNotebookItem {
required this.errorCategory,
required this.status,
required this.remediationAttemptsCount,
this.retentionIsDue = false,
this.masteredAt,
required this.createdAt,
});
@@ -125,6 +127,7 @@ class ErrorNotebookItem {
errorCategory: json['error_category']?.toString() ?? 'conceptual',
status: json['status']?.toString() ?? 'pending_remediation',
remediationAttemptsCount: (json['remediation_attempts_count'] as num?)?.toInt() ?? 0,
retentionIsDue: json['retention_is_due'] == true || json['retention_is_due'] == 1 || json['retention_is_due'] == '1',
masteredAt: json['mastered_at']?.toString(),
createdAt: json['created_at']?.toString() ?? '',
);
@@ -149,6 +152,7 @@ class ErrorNotebookItem {
errorCategory: errorCategory,
status: status ?? this.status,
remediationAttemptsCount: remediationAttemptsCount ?? this.remediationAttemptsCount,
retentionIsDue: retentionIsDue,
masteredAt: masteredAt ?? this.masteredAt,
createdAt: createdAt,
);
@@ -158,16 +162,12 @@ class ErrorNotebookItem {
class RemedialQuestion {
final int id;
final String question;
final List<String> options;
final int correctIndex;
final String explanation;
final List<RemedialOption> options;
RemedialQuestion({
required this.id,
required this.question,
required this.options,
required this.correctIndex,
required this.explanation,
});
factory RemedialQuestion.fromJson(Map<String, dynamic> json) {
@@ -175,9 +175,17 @@ class RemedialQuestion {
return RemedialQuestion(
id: (json['id'] as num?)?.toInt() ?? 0,
question: json['question']?.toString() ?? '',
options: rawOptions.map((e) => e.toString()).toList(),
correctIndex: (json['correct_index'] as num?)?.toInt() ?? 0,
explanation: json['explanation']?.toString() ?? '',
options: rawOptions.map((e) => RemedialOption.fromJson(Map<String, dynamic>.from(e as Map))).toList(),
);
}
}
class RemedialOption {
final int id;
final String text;
RemedialOption({required this.id, required this.text});
factory RemedialOption.fromJson(Map<String, dynamic> json) => RemedialOption(
id: (json['id'] as num?)?.toInt() ?? 0,
text: json['text']?.toString() ?? '',
);
}
@@ -209,6 +209,8 @@ class CurriculumLessonItemModel {
final List<String> outcomes;
final String? markdownFilePath;
final String? curriculumLessonId;
final String? curriculumVersion;
final String? primaryLessonAssetId;
final int durationSeconds;
final int checkpointsCount;
final bool isCompleted;
@@ -220,6 +222,8 @@ class CurriculumLessonItemModel {
this.outcomes = const [],
this.markdownFilePath,
this.curriculumLessonId,
this.curriculumVersion,
this.primaryLessonAssetId,
this.durationSeconds = 0,
this.checkpointsCount = 0,
this.isCompleted = false,
@@ -254,6 +258,8 @@ class CurriculumLessonItemModel {
outcomes: outs,
markdownFilePath: filePath,
curriculumLessonId: json['curriculum_lesson_id']?.toString(),
curriculumVersion: json['curriculum_version']?.toString(),
primaryLessonAssetId: json['primary_lesson_asset_id']?.toString(),
durationSeconds: (json['duration_seconds'] as num?)?.toInt() ?? 0,
checkpointsCount: (json['checkpoints_count'] as num?)?.toInt() ?? 0,
isCompleted: (json['is_completed'] as bool?) ?? false,