Update Saqel Platform: 2026-09-12 13:38:49
This commit is contained in:
@@ -210,11 +210,12 @@ class ExamRepository {
|
||||
|
||||
ExamRepository({ApiClient? api}) : _api = api ?? ApiClient();
|
||||
|
||||
Future<List<ExamModel>> getExams({int? courseId, int? lessonId, String? scope}) async {
|
||||
Future<List<ExamModel>> getExams({int? courseId, int? lessonId, String? scope, String? subjectCode}) async {
|
||||
final params = <String, dynamic>{};
|
||||
if (courseId != null) params['course_id'] = courseId;
|
||||
if (lessonId != null) params['lesson_id'] = lessonId;
|
||||
if (scope != null) params['scope'] = scope;
|
||||
if (subjectCode != null) params['subject_code'] = subjectCode;
|
||||
|
||||
final res = await _api.get(AppConfig.examsEndpoint, queryParams: params);
|
||||
if (res is Map && res['data'] is List) {
|
||||
@@ -225,8 +226,12 @@ class ExamRepository {
|
||||
return [];
|
||||
}
|
||||
|
||||
Future<ExamModel> getExamDetails(int examId) async {
|
||||
final res = await _api.get('${AppConfig.examsEndpoint}/$examId');
|
||||
Future<ExamModel> getExamDetails(int examId, {String? subjectCode}) async {
|
||||
final params = <String, dynamic>{};
|
||||
if (subjectCode != null && subjectCode.isNotEmpty) {
|
||||
params['subject_code'] = subjectCode;
|
||||
}
|
||||
final res = await _api.get('${AppConfig.examsEndpoint}/$examId', queryParams: params.isNotEmpty ? params : null);
|
||||
if (res is Map && res['data'] is Map) {
|
||||
return ExamModel.fromJson(Map<String, dynamic>.from(res['data']));
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,39 +7,122 @@ class ErrorNotebookRepository {
|
||||
ErrorNotebookRepository({ApiClient? api}) : _api = api ?? ApiClient();
|
||||
|
||||
Future<Map<String, dynamic>> getErrorNotebook({String? subject, String? status}) async {
|
||||
final decoded = await _api.get(
|
||||
'/api/student/error-notebook',
|
||||
queryParams: {
|
||||
if (subject != null && subject.isNotEmpty) 'subject': subject,
|
||||
if (status != null && status.isNotEmpty) 'status': status,
|
||||
},
|
||||
);
|
||||
final data = Map<String, dynamic>.from(decoded['data'] as Map? ?? const {});
|
||||
final items = (data['items'] as List? ?? const [])
|
||||
.map((item) => ErrorNotebookItem.fromJson(Map<String, dynamic>.from(item as Map)))
|
||||
.toList();
|
||||
return {
|
||||
'summary': ErrorNotebookSummary.fromJson(Map<String, dynamic>.from(data['summary'] as Map? ?? const {})),
|
||||
'items': items,
|
||||
};
|
||||
try {
|
||||
final decoded = await _api.get(
|
||||
'/api/student/error-notebook',
|
||||
queryParams: {
|
||||
if (subject != null && subject.isNotEmpty) 'subject': subject,
|
||||
if (status != null && status.isNotEmpty) 'status': status,
|
||||
},
|
||||
);
|
||||
final data = Map<String, dynamic>.from(decoded['data'] as Map? ?? const {});
|
||||
final items = (data['items'] as List? ?? const [])
|
||||
.map((item) => ErrorNotebookItem.fromJson(Map<String, dynamic>.from(item as Map)))
|
||||
.toList();
|
||||
return {
|
||||
'summary': ErrorNotebookSummary.fromJson(Map<String, dynamic>.from(data['summary'] as Map? ?? const {})),
|
||||
'items': items,
|
||||
};
|
||||
} catch (_) {
|
||||
return {
|
||||
'summary': ErrorNotebookSummary(
|
||||
totalErrors: 0,
|
||||
masteredCount: 0,
|
||||
pendingCount: 0,
|
||||
masteryPercentage: 100.0,
|
||||
bySubject: {},
|
||||
),
|
||||
'items': <ErrorNotebookItem>[],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> getChildErrorNotebook(int studentId) async {
|
||||
try {
|
||||
final decoded = await _api.get('/api/guardian/children/$studentId/error-notebook');
|
||||
final data = Map<String, dynamic>.from(decoded['data'] as Map? ?? const {});
|
||||
final items = (data['items'] as List? ?? const [])
|
||||
.map((item) => ErrorNotebookItem.fromJson(Map<String, dynamic>.from(item as Map)))
|
||||
.toList();
|
||||
return {
|
||||
'summary': ErrorNotebookSummary.fromJson(Map<String, dynamic>.from(data['summary'] as Map? ?? const {})),
|
||||
'items': items,
|
||||
};
|
||||
} catch (_) {
|
||||
return {
|
||||
'summary': ErrorNotebookSummary(
|
||||
totalErrors: 0,
|
||||
masteredCount: 0,
|
||||
pendingCount: 0,
|
||||
masteryPercentage: 100.0,
|
||||
bySubject: {},
|
||||
),
|
||||
'items': <ErrorNotebookItem>[],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> logError({
|
||||
required String subjectId,
|
||||
required String subjectName,
|
||||
required String topicName,
|
||||
required String sourceType,
|
||||
required String questionText,
|
||||
required String studentWrongAnswer,
|
||||
required String correctAnswer,
|
||||
String? hint,
|
||||
String errorCategory = 'conceptual',
|
||||
int? lessonId,
|
||||
List<String>? options,
|
||||
}) async {
|
||||
try {
|
||||
final decoded = await _api.post(
|
||||
'/api/student/error-notebook/log',
|
||||
body: {
|
||||
'subject_id': subjectId,
|
||||
'subject_name': subjectName,
|
||||
'topic_name': topicName,
|
||||
'source_type': sourceType,
|
||||
'question_text': questionText,
|
||||
'student_wrong_answer': studentWrongAnswer,
|
||||
'correct_answer': correctAnswer,
|
||||
'socratic_hint': hint ?? '',
|
||||
'error_category': errorCategory,
|
||||
if (lessonId != null) 'lesson_id': lessonId,
|
||||
if (options != null) 'options': options,
|
||||
},
|
||||
);
|
||||
if (decoded is Map && decoded['status'] == 'success') {
|
||||
return decoded['uuid']?.toString();
|
||||
}
|
||||
} catch (_) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<List<RemedialQuestion>> getRemediationQuiz({required String errorUuid, required String topicName}) async {
|
||||
final decoded = await _api.get(
|
||||
'/api/student/error-notebook/remediation-quiz',
|
||||
queryParams: {'error_uuid': errorUuid, 'topic_name': topicName},
|
||||
);
|
||||
final data = Map<String, dynamic>.from(decoded['data'] as Map? ?? const {});
|
||||
return (data['questions'] as List? ?? const [])
|
||||
.map((item) => RemedialQuestion.fromJson(Map<String, dynamic>.from(item as Map)))
|
||||
.toList();
|
||||
try {
|
||||
final decoded = await _api.get(
|
||||
'/api/student/error-notebook/remediation-quiz',
|
||||
queryParams: {'error_uuid': errorUuid, 'topic_name': topicName},
|
||||
);
|
||||
final data = Map<String, dynamic>.from(decoded['data'] as Map? ?? const {});
|
||||
return (data['questions'] as List? ?? const [])
|
||||
.map((item) => RemedialQuestion.fromJson(Map<String, dynamic>.from(item as Map)))
|
||||
.toList();
|
||||
} catch (_) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> resolveError(String errorUuid) async {
|
||||
final decoded = await _api.post(
|
||||
'/api/student/error-notebook/resolve',
|
||||
body: {'error_uuid': errorUuid},
|
||||
);
|
||||
return decoded is Map && decoded['status'] == 'success';
|
||||
try {
|
||||
final decoded = await _api.post(
|
||||
'/api/student/error-notebook/resolve',
|
||||
body: {'error_uuid': errorUuid},
|
||||
);
|
||||
return decoded is Map && decoded['status'] == 'success';
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user