Files
saqel/apps/student_app/lib/data/models/lesson_model.dart
T

149 lines
6.2 KiB
Dart

/// Real Lesson Model from /api/student/lessons
class LessonModel {
final int id;
final int courseId;
final String title;
final int sequenceOrder;
final String storageType;
final String? videoUuid;
final String? hlsUrl;
final String? thumbnailUrl;
final String? aiVideoUrl;
final int durationSeconds;
final bool isFreePreview;
final String courseTitle;
final bool isAiVersion;
final int? checkpointCount;
LessonModel({
required this.id,
required this.courseId,
required this.title,
required this.sequenceOrder,
required this.storageType,
this.videoUuid,
this.hlsUrl,
this.thumbnailUrl,
this.aiVideoUrl,
required this.durationSeconds,
required this.isFreePreview,
required this.courseTitle,
required this.isAiVersion,
this.checkpointCount,
});
factory LessonModel.fromJson(Map<String, dynamic> json) {
return LessonModel(
id: json['id'] is int ? json['id'] : int.tryParse(json['id']?.toString() ?? '0') ?? 0,
courseId: json['course_id'] is int ? json['course_id'] : int.tryParse(json['course_id']?.toString() ?? '0') ?? 0,
title: json['title']?.toString() ?? 'درس تفاعلي',
sequenceOrder: json['sequence_order'] is int ? json['sequence_order'] : int.tryParse(json['sequence_order']?.toString() ?? '1') ?? 1,
storageType: json['storage_type']?.toString() ?? 'local',
videoUuid: json['video_uuid']?.toString(),
hlsUrl: json['hls_url']?.toString(),
thumbnailUrl: json['thumbnail_url']?.toString(),
aiVideoUrl: json['ai_video_url']?.toString(),
durationSeconds: json['duration_seconds'] is int ? json['duration_seconds'] : int.tryParse(json['duration_seconds']?.toString() ?? '0') ?? 0,
isFreePreview: json['is_free_preview'] == 1 || json['is_free_preview'] == true,
courseTitle: json['course_title']?.toString() ?? 'المنهاج المعتمد',
isAiVersion: json['is_ai_version'] == 1 || json['is_ai_version'] == true,
checkpointCount: json['checkpoint_count'] is int ? json['checkpoint_count'] : int.tryParse(json['checkpoint_count']?.toString() ?? '0'),
);
}
String get formattedDuration {
if (durationSeconds <= 0) return 'درس تفاعلي';
final minutes = durationSeconds ~/ 60;
final seconds = durationSeconds % 60;
return '$minutes دقيقة ${seconds > 0 ? '$seconds ثانية' : ''}';
}
}
/// Real Child Profile & Academic Progress Model for Guardian
class GuardianChildModel {
final int id;
final String uuid;
final String name;
final String? nationalId;
final String? gradeLevel;
final String? stream;
final String? schoolName;
final double readinessScore;
final int examsPassed;
final int examsTotal;
final int errorTotalCount;
final int errorMasteredCount;
final int errorPendingCount;
final double errorMasteryRate;
GuardianChildModel({
required this.id,
required this.uuid,
required this.name,
this.nationalId,
this.gradeLevel,
this.stream,
this.schoolName,
this.readinessScore = 0.0,
this.examsPassed = 0,
this.examsTotal = 0,
this.errorTotalCount = 0,
this.errorMasteredCount = 0,
this.errorPendingCount = 0,
this.errorMasteryRate = 100.0,
});
factory GuardianChildModel.fromJson(Map<String, dynamic> json) {
final student = json['student'] is Map
? Map<String, dynamic>.from(json['student'])
: <String, dynamic>{};
final metrics = json['metrics'] is Map
? Map<String, dynamic>.from(json['metrics'])
: <String, dynamic>{};
final source = <String, dynamic>{...student, ...metrics, ...json};
final errorNotebook = metrics['error_notebook'] is Map
? Map<String, dynamic>.from(metrics['error_notebook'])
: <String, dynamic>{};
final errTotal = errorNotebook['total_errors'] is int
? errorNotebook['total_errors'] as int
: (source['errors_total'] is int
? source['errors_total'] as int
: int.tryParse(errorNotebook['total_errors']?.toString() ?? source['errors_total']?.toString() ?? '0') ?? 0);
final errMastered = errorNotebook['mastered_count'] is int
? errorNotebook['mastered_count'] as int
: (source['errors_mastered'] is int
? source['errors_mastered'] as int
: int.tryParse(errorNotebook['mastered_count']?.toString() ?? source['errors_mastered']?.toString() ?? '0') ?? 0);
final errPending = errorNotebook['pending_count'] is int
? errorNotebook['pending_count'] as int
: (source['errors_pending'] is int
? source['errors_pending'] as int
: int.tryParse(errorNotebook['pending_count']?.toString() ?? source['errors_pending']?.toString() ?? '0') ?? 0);
final errRate = errorNotebook['mastery_percentage'] != null
? double.tryParse(errorNotebook['mastery_percentage'].toString()) ?? 100.0
: (source['errors_mastery_rate'] != null
? double.tryParse(source['errors_mastery_rate'].toString()) ?? 100.0
: (errTotal > 0 ? (errMastered / errTotal) * 100 : 100.0));
return GuardianChildModel(
id: source['id'] is int ? source['id'] : int.tryParse(source['id']?.toString() ?? '0') ?? 0,
uuid: source['uuid']?.toString() ?? '',
name: source['full_name']?.toString() ?? source['name']?.toString() ?? 'الطالب',
nationalId: source['national_id']?.toString(),
gradeLevel: source['grade_level']?.toString(),
stream: source['stream']?.toString(),
schoolName: source['school_name']?.toString() ?? 'مدرسة معتمدة',
readinessScore: source['readiness_score'] != null
? double.tryParse(source['readiness_score'].toString()) ?? 0.0
: (source['tawjihi_readiness_score'] != null ? double.tryParse(source['tawjihi_readiness_score'].toString()) ?? 0.0 : 0.0),
examsPassed: source['exams_passed_count'] is int ? source['exams_passed_count'] : int.tryParse(source['exams_passed_count']?.toString() ?? '0') ?? 0,
examsTotal: source['exams_total_count'] is int ? source['exams_total_count'] : int.tryParse(source['exams_total_count']?.toString() ?? '0') ?? 0,
errorTotalCount: errTotal,
errorMasteredCount: errMastered,
errorPendingCount: errPending,
errorMasteryRate: errRate,
);
}
}