/** * ============================================================================== * SAQEL TEACHER STUDIO - DATA MODELS * ============================================================================== * * نماذج البيانات الخاصة باستوديو المعلم: * - نتائج فحص الجودة الإدراكي والأكاديمي (Quality Gate & MIT 20-25 Min Limit) * - بيانات التسييل المالي وحسابات الحصص (55% المعلم / 15% المديرية / 30% المنصة) * - أوراق العمل والواجبات المدرسية المصححة آلياً * - استفسارات وأسئلة الطلبة الميدانية (غرفة الشكوك) والردود السقراطية المسجلة. */ class TeacherLessonAuditModel { final String lessonTitle; final String subject; final double durationMinutes; final bool durationGatePassed; final String? durationWarning; final int qualityScore; final String approvalStatus; final String curriculumAlignment; final String audioClarity; final int socraticStopsCount; final String decision; const TeacherLessonAuditModel({ required this.lessonTitle, required this.subject, required this.durationMinutes, required this.durationGatePassed, this.durationWarning, required this.qualityScore, required this.approvalStatus, required this.curriculumAlignment, required this.audioClarity, required this.socraticStopsCount, required this.decision, }); factory TeacherLessonAuditModel.fromJson(Map json) { final durationSeconds = (json['duration_seconds'] as num?)?.toDouble() ?? 0; final readiness = (json['pedagogical_readiness_score'] as num?)?.toInt(); final visual = (json['visual_clarity_score'] as num?)?.toInt(); final decisionValue = json['decision']?.toString() ?? 'pending'; final ai = json['ai_analysis'] is Map ? Map.from(json['ai_analysis'] as Map) : null; final estimatedCp = (durationSeconds / 600).clamp(1, 4).toInt(); final cpCount = (ai?['checkpoints_count'] as num?)?.toInt() ?? (json['socratic_stops_count'] as num?)?.toInt() ?? (durationSeconds > 0 ? estimatedCp : 0); final alignScore = (qa?['alignment_score'] as num?)?.toInt() ?? readiness; return TeacherLessonAuditModel( lessonTitle: json['lesson_title'] ?? '', subject: json['subject'] ?? '', durationMinutes: (json['duration_minutes'] as num?)?.toDouble() ?? durationSeconds / 60, durationGatePassed: json['duration_gate_passed'] ?? (durationSeconds > 0 && durationSeconds <= 1500), durationWarning: json['duration_warning'], qualityScore: (qa?['clarity_score'] as num?)?.toInt() ?? (json['quality_score'] as num?)?.toInt() ?? readiness ?? 0, approvalStatus: qa?['status']?.toString() ?? json['approval_status'] ?? decisionValue, curriculumAlignment: alignScore != null ? 'تطابق معتمد بنسبة $alignScore% مع المنهاج الرسمي' : (json['curriculum_alignment'] ?? 'بانتظار تحليل الملف الفعلي'), audioClarity: json['audio_clarity'] ?? (visual == null ? 'تم التحقق من وجود مسار صوت فعلي' : 'وضوح الصورة $visual%، وتم التحقق من وجود الصوت'), socraticStopsCount: cpCount, decision: json['report'] ?? json['reason'] ?? decisionValue, ); } } class TeacherHomeworkModel { final String id; final String title; final String className; final String submitted; final String dueDate; final String averageScore; final String status; // 'active', 'completed' const TeacherHomeworkModel({ required this.id, required this.title, required this.className, required this.submitted, required this.dueDate, required this.averageScore, required this.status, }); } class StudentDoubtModel { final String id; final int studentId; final String studentName; final String className; final String question; final String time; final bool replied; final bool voiceReply; const StudentDoubtModel({ required this.id, required this.studentId, required this.studentName, required this.className, required this.question, required this.time, required this.replied, required this.voiceReply, }); StudentDoubtModel copyWith({ bool? replied, bool? voiceReply, }) { return StudentDoubtModel( id: id, studentId: studentId, studentName: studentName, className: className, question: question, time: time, replied: replied ?? this.replied, voiceReply: voiceReply ?? this.voiceReply, ); } } class TeacherCourseModel { final String id; final String title; final String grade; final int totalLessons; final int militaryStudents; final int externalSubscribers; final double priceJod; final double netRevenueJod; const TeacherCourseModel({ required this.id, required this.title, required this.grade, required this.totalLessons, required this.militaryStudents, required this.externalSubscribers, required this.priceJod, required this.netRevenueJod, }); } class TeacherPayoutRequestModel { final String cliqAlias; final double amountJod; final String requestedAt; final String status; // 'queued', 'approved', 'completed' const TeacherPayoutRequestModel({ required this.cliqAlias, required this.amountJod, required this.requestedAt, required this.status, }); } class TeacherProfileModel { final int id; final String uuid; final String name; final String specialization; final String schoolName; final List gradesTaught; final String bio; final double rating; final int studentsCount; final int lessonsCount; const TeacherProfileModel({ required this.id, required this.uuid, required this.name, required this.specialization, required this.schoolName, required this.gradesTaught, required this.bio, this.rating = 4.9, this.studentsCount = 42, this.lessonsCount = 28, }); factory TeacherProfileModel.fromJson(Map json) { final user = json['user'] as Map? ?? {}; final profile = json['profile'] as Map? ?? {}; List grades = []; if (profile['grades_taught'] is List) { grades = (profile['grades_taught'] as List).map((e) => e.toString()).toList(); } else if (profile['grades_taught'] is String) { grades = [profile['grades_taught'].toString()]; } if (grades.isEmpty) { grades = []; } return TeacherProfileModel( id: user['id'] is int ? user['id'] : 1, uuid: user['uuid']?.toString() ?? '', name: user['full_name']?.toString() ?? 'حساب معلم غير مكتمل', specialization: profile['specialization']?.toString() ?? 'بانتظار استكمال التخصص', schoolName: profile['school_name']?.toString() ?? '', gradesTaught: grades, bio: profile['bio']?.toString() ?? '', rating: 0, studentsCount: 0, lessonsCount: 0, ); } TeacherProfileModel copyWith({ String? name, String? specialization, String? schoolName, List? gradesTaught, String? bio, }) { return TeacherProfileModel( id: id, uuid: uuid, name: name ?? this.name, specialization: specialization ?? this.specialization, schoolName: schoolName ?? this.schoolName, gradesTaught: gradesTaught ?? this.gradesTaught, bio: bio ?? this.bio, rating: rating, studentsCount: studentsCount, lessonsCount: lessonsCount, ); } } class ChatConversationModel { final int userId; final String userUuid; final String fullName; final String role; final String? specialization; final String lastMessage; final String lastMessageType; final String? lastMessageAt; final int unreadCount; const ChatConversationModel({ required this.userId, required this.userUuid, required this.fullName, required this.role, this.specialization, required this.lastMessage, required this.lastMessageType, this.lastMessageAt, this.unreadCount = 0, }); factory ChatConversationModel.fromJson(Map json) { return ChatConversationModel( userId: json['user_id'] is int ? json['user_id'] : int.tryParse(json['user_id']?.toString() ?? '0') ?? 0, userUuid: json['user_uuid']?.toString() ?? '', fullName: json['full_name']?.toString() ?? 'طالب صَقِل', role: json['role']?.toString() ?? 'student', specialization: json['specialization']?.toString(), lastMessage: json['last_message']?.toString() ?? '', lastMessageType: json['last_message_type']?.toString() ?? 'text', lastMessageAt: json['last_message_at']?.toString(), unreadCount: json['unread_count'] is int ? json['unread_count'] : 0, ); } } class ChatMessageModel { final int id; final String uuid; final bool isMine; final int senderId; final int receiverId; final String message; final String messageType; // 'text', 'voice', 'image', 'file' final String? mediaUrl; final bool isRead; final String createdAt; const ChatMessageModel({ required this.id, required this.uuid, required this.isMine, required this.senderId, required this.receiverId, required this.message, required this.messageType, this.mediaUrl, required this.isRead, required this.createdAt, }); factory ChatMessageModel.fromJson(Map json) { return ChatMessageModel( id: json['id'] is int ? json['id'] : int.tryParse(json['id']?.toString() ?? '0') ?? 0, uuid: json['uuid']?.toString() ?? '', isMine: json['is_mine'] ?? false, senderId: json['sender_id'] is int ? json['sender_id'] : int.tryParse(json['sender_id']?.toString() ?? '0') ?? 0, receiverId: json['receiver_id'] is int ? json['receiver_id'] : int.tryParse(json['receiver_id']?.toString() ?? '0') ?? 0, message: json['message']?.toString() ?? '', messageType: json['message_type']?.toString() ?? 'text', mediaUrl: json['media_url']?.toString(), isRead: json['is_read'] ?? false, createdAt: json['created_at']?.toString() ?? '', ); } }