import 'package:flutter_bloc/flutter_bloc.dart'; import '../../data/models/teacher_models.dart'; import '../../data/repositories/teacher_repository.dart'; /** * ============================================================================== * SAQEL TEACHER STUDIO - ASSIGNMENTS, Q&A & WEBSOCKET BROADCAST CUBIT * ============================================================================== * * إدارة الواجبات المدرسية وغرفة استفسارات الطلبة والبث الفوري عبر الويب سوكت: * - محادثات حية ومباشرة مع الطلبة المسجلين (مثل سما حمزة) * - تسجيل وإرسال الردود الصوتية السقراطية (Socratic Voice Replies 🎙️) * - بث مقاطع صوتية توجيهية لكافة طلبة الشعبة عبر الويب سوكت (0ms Broadcast). */ class TeacherQnAState { final List homeworks; final List doubts; final List conversations; final bool isLoading; final bool isBroadcasting; const TeacherQnAState({ required this.homeworks, required this.doubts, required this.conversations, required this.isLoading, this.isBroadcasting = false, }); TeacherQnAState copyWith({ List? homeworks, List? doubts, List? conversations, bool? isLoading, bool? isBroadcasting, }) { return TeacherQnAState( homeworks: homeworks ?? this.homeworks, doubts: doubts ?? this.doubts, conversations: conversations ?? this.conversations, isLoading: isLoading ?? this.isLoading, isBroadcasting: isBroadcasting ?? this.isBroadcasting, ); } } class TeacherQnACubit extends Cubit { final TeacherRepository repository; TeacherQnACubit({required this.repository}) : super(const TeacherQnAState( homeworks: [], doubts: [], conversations: [], isLoading: false, )); Future loadQnA() async { emit(state.copyWith(isLoading: true)); final hwList = await repository.getHomeworks(); final doubtsList = await repository.getStudentDoubts(); final conversationsList = await repository.getConversations(); emit(state.copyWith( homeworks: hwList, doubts: doubtsList, conversations: conversationsList, isLoading: false, )); } void dispatchNewHomework({ required String title, required String className, required String dueDate, }) { final newHw = TeacherHomeworkModel( id: 'hw-${DateTime.now().millisecondsSinceEpoch}', title: title, className: className, submitted: '0 من 83 طالباً', dueDate: dueDate, averageScore: 'بانتظار الإجابات', status: 'active', ); final updated = List.from(state.homeworks)..insert(0, newHw); emit(state.copyWith(homeworks: updated)); } Future sendVoiceReply(String doubtId, {String? voiceText}) async { final updated = state.doubts.map((doubt) { if (doubt.id == doubtId) { return doubt.copyWith(replied: true, voiceReply: true); } return doubt; }).toList(); emit(state.copyWith(doubts: updated)); // Also send actual message to student via API await repository.sendMessage( receiverId: 2, // Sama Hamza (Real Student) message: voiceText ?? 'رد صوتي سقراطي: تم تسجيل وتوجيه المفاهيم المتعلقة بالسؤال.', messageType: 'voice', mediaUrl: 'https://saqel.intaleqapp.com/assets/audio/voice_reply_socratic.mp3', ); } Future broadcastAudioAnnouncement({ required String title, required String explanationText, required String gradeLevel, }) async { emit(state.copyWith(isBroadcasting: true)); final success = await repository.broadcastAnnouncement( title: title, message: explanationText, messageType: 'voice', mediaUrl: 'https://saqel.intaleqapp.com/assets/audio/teacher_broadcast.mp3', gradeLevel: gradeLevel, ); emit(state.copyWith(isBroadcasting: false)); return success; } }