Update Saqel Platform: 2026-09-05 23:24:49

This commit is contained in:
Hamza-Ayed
2026-09-05 23:24:49 +03:00
parent 0e5be7adbb
commit 0f424062fe
20 changed files with 2132 additions and 324 deletions
@@ -2,18 +2,20 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../core/theme/teacher_theme.dart';
import '../../../core/utils/saqel_toast.dart';
import '../../../data/models/teacher_models.dart';
import '../../../logic/cubits/teacher_qna_cubit.dart';
/**
* ==============================================================================
* SAQEL TEACHER STUDIO - TAB 4: ASSIGNMENTS & Q&A (VOICE REPLIES)
* SAQEL TEACHER STUDIO - TAB 4: REAL CHAT, SOCRATIC VOICE & WEBSOCKET BROADCAST
* ==============================================================================
*
* إدارة الواجبات المدرسية الموجهة وغرفة الشكوك والاستفسارات:
* - إسناد أوراق عمل مؤتمتة التصحيح بنقرة واحدة
* - تسجيل الردود الصوتية السقراطية (Socratic Voice Replies 🎙️)
* - مؤشرات تسليم الطلاب ومعدلات الشعب المدرسية.
* غرفة استفسارات الطلبة الفعلية والبث الصوتي المباشر:
* - استفسارات وأسئلة الطلبة الميدانية (طالبات الصف العاشر مثل سما حمزة)
* - تسجيل الردود الصوتية السقراطية (Socratic Voice Notes 🎙️)
* - بث مقاطع صوتية توجيهية لكافة طلبة الشعبة عبر الويب سوكت (0ms Broadcast)
* - إسناد ومتابعة أوراق العمل المؤتمتة.
*/
class TeacherAssignmentsQnATab extends StatefulWidget {
const TeacherAssignmentsQnATab({super.key});
@@ -23,12 +25,25 @@ class TeacherAssignmentsQnATab extends StatefulWidget {
}
class _TeacherAssignmentsQnATabState extends State<TeacherAssignmentsQnATab> {
final TextEditingController _broadcastTitleCtrl = TextEditingController(text: 'توضيح بيداغوجي: مسار الشحنة في الوعاء المغناطيسي');
final TextEditingController _broadcastMessageCtrl = TextEditingController(
text: 'أعزائي طلبة الصف العاشر: انتبهوا إلى أن قوة لورنتز تكون دائماً عمودية على كل من متجه السرعة ومتجه المجال، لذلك لا تبذل شغلاً ولا تغيّر الطاقة الحركية، بل تُوجّه الجسيم في مسار حلزوني محصور داخل الوعاء.',
);
String _selectedBroadcastGrade = 'الصف العاشر الأساسي';
@override
void initState() {
super.initState();
context.read<TeacherQnACubit>().loadQnA();
}
@override
void dispose() {
_broadcastTitleCtrl.dispose();
_broadcastMessageCtrl.dispose();
super.dispose();
}
void _dispatchNewHomework() {
showCupertinoDialog(
context: context,
@@ -49,16 +64,11 @@ class _TeacherAssignmentsQnATabState extends State<TeacherAssignmentsQnATab> {
onPressed: () {
Navigator.of(ctx).pop();
context.read<TeacherQnACubit>().dispatchNewHomework(
title: 'ورقة عمل: الشغل والطاقة الميكانيكية',
className: 'الأول ثانوي العلمي (شعبة أ وب)',
dueDate: 'الخميس القادم',
title: 'ورقة عمل: ضرب المتجهات وتطبيقات عزم القوة',
className: 'الصف العاشر الأساسي (شعبة أ وب)',
dueDate: 'الخميس القادم الساعة 08:00 م',
);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('تم إسناد ورقة العمل وإشعار الطلبة بنجاح 🚀'),
backgroundColor: TeacherTheme.emeraldPrimary,
),
);
SaqelToast.showSuccess(context, 'تم إسناد ورقة العمل وإشعار الطلبة بنجاح 🚀');
},
child: const Text('إسناد للطلبة الآن'),
),
@@ -68,7 +78,163 @@ class _TeacherAssignmentsQnATabState extends State<TeacherAssignmentsQnATab> {
);
}
void _recordVoiceReply(String doubtId) {
void _openBroadcastDialog() {
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (ctx) => Directionality(
textDirection: TextDirection.rtl,
child: Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(ctx).viewInsets.bottom + 20,
top: 24,
left: 20,
right: 20,
),
decoration: const BoxDecoration(
color: TeacherTheme.surfaceDark,
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
border: Border(top: BorderSide(color: TeacherTheme.emeraldPrimary, width: 2)),
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
children: [
Container(
width: 44,
height: 44,
decoration: BoxDecoration(
color: TeacherTheme.emeraldPrimary.withOpacity(0.15),
borderRadius: BorderRadius.circular(12),
),
child: const Icon(CupertinoIcons.waveform_path_badge_plus, color: TeacherTheme.emeraldPrimary, size: 24),
),
const SizedBox(width: 12),
const Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'بث مقطع صوتي وإشعار فوري للشعبة 🎙️',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.w900, fontSize: 15),
),
SizedBox(height: 2),
Text(
'يصل التسجيل الصوتي عبر خادم الويب سوكت (0ms) لكافة الطلبة المشتركين',
style: TextStyle(color: Color(0xFF94A3B8), fontSize: 11),
),
],
),
),
],
),
const SizedBox(height: 18),
const Text('عنوان التوجيه الصوتي:', style: TextStyle(color: Colors.white70, fontSize: 12, fontWeight: FontWeight.bold)),
const SizedBox(height: 6),
_buildInputContainer(
child: TextField(
controller: _broadcastTitleCtrl,
style: const TextStyle(color: Colors.white, fontSize: 13),
decoration: const InputDecoration(border: InputBorder.none, hintText: 'عنوان التوجيه الصوتي'),
),
),
const SizedBox(height: 12),
const Text('الشعبة المستهدفة:', style: TextStyle(color: Colors.white70, fontSize: 12, fontWeight: FontWeight.bold)),
const SizedBox(height: 6),
_buildInputContainer(
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: _selectedBroadcastGrade,
isExpanded: true,
dropdownColor: TeacherTheme.surfaceDark,
icon: const Icon(CupertinoIcons.chevron_down, color: TeacherTheme.emeraldPrimary, size: 16),
items: const [
DropdownMenuItem(value: 'الصف العاشر الأساسي', child: Text('الصف العاشر الأساسي (فيزياء)', style: TextStyle(color: Colors.white, fontSize: 12.5))),
DropdownMenuItem(value: 'الأول ثانوي العلمي', child: Text('الأول ثانوي العلمي (ميكانيكا)', style: TextStyle(color: Colors.white, fontSize: 12.5))),
DropdownMenuItem(value: 'الثاني ثانوي (التوجيهي)', child: Text('الثاني ثانوي التوجيهي (مكثف)', style: TextStyle(color: Colors.white, fontSize: 12.5))),
],
onChanged: (val) {
if (val != null) setState(() => _selectedBroadcastGrade = val);
},
),
),
),
const SizedBox(height: 12),
const Text('نص الشرح أو ملخص المقطع الصوتي:', style: TextStyle(color: Colors.white70, fontSize: 12, fontWeight: FontWeight.bold)),
const SizedBox(height: 6),
_buildInputContainer(
child: TextField(
controller: _broadcastMessageCtrl,
maxLines: 4,
style: const TextStyle(color: Colors.white, fontSize: 12.5, height: 1.4),
decoration: const InputDecoration(border: InputBorder.none, hintText: 'اكتب التوجيه المفاهيمي للشعبة...'),
),
),
const SizedBox(height: 16),
// Voice Recording Strip Simulation
Container(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
decoration: BoxDecoration(
color: const Color(0xFF0C241D),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: TeacherTheme.emeraldPrimary.withOpacity(0.5)),
),
child: const Row(
children: [
Icon(CupertinoIcons.mic_fill, color: TeacherTheme.emeraldPrimary, size: 18),
SizedBox(width: 10),
Expanded(
child: Text(
'مقطع صوتي مسجل بنقاء عالي: 01:14 دقيقة (ترميز AAC - 128kbps)',
style: TextStyle(color: TeacherTheme.emeraldLight, fontSize: 11.5, fontWeight: FontWeight.w600),
),
),
Icon(CupertinoIcons.play_circle_fill, color: TeacherTheme.emeraldPrimary, size: 22),
],
),
),
const SizedBox(height: 20),
ElevatedButton.icon(
onPressed: () async {
Navigator.of(ctx).pop();
final success = await context.read<TeacherQnACubit>().broadcastAudioAnnouncement(
title: _broadcastTitleCtrl.text.trim(),
explanationText: _broadcastMessageCtrl.text.trim(),
gradeLevel: _selectedBroadcastGrade,
);
if (success) {
SaqelToast.showSuccess(
context,
'تم إرسال البث الصوتي بنجاح عبر شبكة الويب سوكت الحية لكافة طلبة $_selectedBroadcastGrade 📡',
title: 'بث ويب سوكت فوري 🎙️',
);
}
},
icon: const Icon(CupertinoIcons.paperplane_fill, size: 16),
label: const Text('بث المقطع الصوتي للشعبة الآن 🚀', style: TextStyle(fontSize: 13, fontWeight: FontWeight.bold)),
style: ElevatedButton.styleFrom(
backgroundColor: TeacherTheme.emeraldPrimary,
foregroundColor: Colors.black,
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
),
),
],
),
),
),
);
}
void _recordVoiceReply(String doubtId, String studentName) {
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
@@ -86,30 +252,32 @@ class _TeacherAssignmentsQnATabState extends State<TeacherAssignmentsQnATab> {
children: [
const Icon(CupertinoIcons.mic_circle_fill, size: 56, color: TeacherTheme.emeraldPrimary),
const SizedBox(height: 12),
const Text(
'تسجيل رد صوتي سقراطي للطالب 🎙️',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w800, color: Colors.white),
Text(
'تسجيل رد صوتي سقراطي للطالبة ($studentName) 🎙️',
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w800, color: Colors.white),
),
const SizedBox(height: 6),
const Text(
'سيصل التسجيل الصوتي بجودة عالية داخل تطبيق الطالب مع التوجيه المفاهيمي.',
'سيصل التسجيل الصوتي بجودة عالية داخل تطبيق الطالب مع التوجيه المفاهيمي وتنبيه فوري.',
style: TextStyle(fontSize: 12, color: Color(0xFF94A3B8)),
textAlign: TextAlign.center,
),
const SizedBox(height: 20),
ElevatedButton.icon(
onPressed: () {
context.read<TeacherQnACubit>().recordVoiceReply(doubtId);
context.read<TeacherQnACubit>().sendVoiceReply(
doubtId,
voiceText: 'رد الأستاذ صوتياً على استفسار الطالبة $studentName حول الوعاء المغناطيسي وحصر البلازما.',
);
Navigator.of(ctx).pop();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('تم إرسال الرد الصوتي للطالب بنجاح 🎧'),
backgroundColor: TeacherTheme.emeraldPrimary,
),
SaqelToast.showSuccess(
context,
'تم إرسال الرد الصوتي إلى الطالبة $studentName بنجاح 🎧',
title: 'رد سقراطي مسجل ✨',
);
},
icon: const Icon(CupertinoIcons.paperplane_fill, size: 16),
label: const Text('إنهاء وإرسال التسجيل الصوتي (00:42)'),
label: const Text('إنهاء وإرسال التسجيل الصوتي (00:38 د)'),
style: ElevatedButton.styleFrom(
backgroundColor: TeacherTheme.emeraldPrimary,
foregroundColor: Colors.black,
@@ -137,69 +305,116 @@ class _TeacherAssignmentsQnATabState extends State<TeacherAssignmentsQnATab> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Top Action Card
// WebSocket Voice Broadcast Banner
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF064E3B), Color(0xFF0F172A)],
colors: [Color(0xFF064E3B), Color(0xFF0F261E)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: TeacherTheme.emeraldPrimary.withOpacity(0.4)),
borderRadius: BorderRadius.circular(18),
border: Border.all(color: TeacherTheme.emeraldPrimary, width: 1.2),
boxShadow: const [
BoxShadow(
color: Color(0x3310B981),
blurRadius: 18,
offset: Offset(0, 6),
),
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'أوراق العمل والواجبات الوزارية 📝',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w800, color: Colors.white),
),
SizedBox(height: 3),
Text(
'تصحيح مؤتمت بنسبة 100% مرتبط ببنك الأسئلة',
style: TextStyle(fontSize: 11.5, color: Color(0xFF94A3B8)),
),
],
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: TeacherTheme.emeraldPrimary.withOpacity(0.2),
shape: BoxShape.circle,
border: Border.all(color: TeacherTheme.emeraldPrimary),
),
child: const Icon(CupertinoIcons.waveform_path_ecg, color: TeacherTheme.emeraldPrimary, size: 24),
),
ElevatedButton.icon(
onPressed: _dispatchNewHomework,
icon: const Icon(CupertinoIcons.plus_circle_fill, size: 16),
label: const Text('إسناد واجب جديد', style: TextStyle(fontSize: 12, fontWeight: FontWeight.w800)),
const SizedBox(width: 14),
const Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'بث صوتي وتوجيهي عبر الويب سوكت',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.w900, fontSize: 13.5),
),
SizedBox(width: 6),
Icon(CupertinoIcons.antenna_radiowaves_left_right, color: TeacherTheme.emeraldPrimary, size: 14),
],
),
SizedBox(height: 4),
Text(
'بث مقطع صوتي حي وشرح مباشر لجميع طلبة الشعبة المشتركين (0ms)',
style: TextStyle(color: Color(0xFF94A3B8), fontSize: 11),
),
],
),
),
ElevatedButton(
onPressed: _openBroadcastDialog,
style: ElevatedButton.styleFrom(
backgroundColor: TeacherTheme.emeraldPrimary,
foregroundColor: Colors.black,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
),
child: const Text('بدء البث 🎙️', style: TextStyle(fontSize: 12, fontWeight: FontWeight.w800)),
),
],
),
),
const SizedBox(height: 16),
// Homeworks List
...state.homeworks.map((hw) => _buildHomeworkCard(hw)),
const SizedBox(height: 18),
// Student Doubts Section
// Homeworks Header & Add Button
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Row(
children: [
Icon(CupertinoIcons.doc_text_fill, color: TeacherTheme.emeraldPrimary, size: 16),
SizedBox(width: 6),
Text(
'أوراق العمل والواجبات الوزارية 📝',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w800, color: Colors.white),
),
],
),
TextButton.icon(
onPressed: _dispatchNewHomework,
icon: const Icon(CupertinoIcons.plus_circle_fill, size: 15, color: TeacherTheme.emeraldPrimary),
label: const Text('إسناد واجب جديد', style: TextStyle(color: TeacherTheme.emeraldPrimary, fontSize: 12, fontWeight: FontWeight.bold)),
),
],
),
const SizedBox(height: 6),
// Homework Cards
...state.homeworks.map((hw) => _buildHomeworkCard(hw)),
const SizedBox(height: 20),
// Student Inquiries / Real Chat Header
const Row(
children: [
Icon(CupertinoIcons.bubble_left_bubble_right_fill, color: TeacherTheme.cyberCyan, size: 18),
Icon(CupertinoIcons.chat_bubble_2_fill, color: TeacherTheme.cyberCyan, size: 18),
SizedBox(width: 8),
Text(
'استفسارات وأسئلة الطلبة الميدانية (غرفة الشكوك) 💬',
'استفسارات الطلبة والمحادثات المباشرة (غرفة الشكوك) 💬',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w800, color: Colors.white),
),
],
),
const SizedBox(height: 10),
// Doubts List
// Student Inquiries Cards
...state.doubts.map((doubt) => _buildDoubtCard(doubt)),
],
),
@@ -208,44 +423,64 @@ class _TeacherAssignmentsQnATabState extends State<TeacherAssignmentsQnATab> {
);
}
Widget _buildHomeworkCard(TeacherHomeworkModel hw) {
Widget _buildInputContainer({required Widget child}) {
return Container(
margin: const EdgeInsets.only(bottom: 10),
padding: const EdgeInsets.all(14),
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 4),
decoration: BoxDecoration(
color: TeacherTheme.surfaceCard,
borderRadius: BorderRadius.circular(14),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: TeacherTheme.surfaceBorder),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
child: child,
);
}
Widget _buildHomeworkCard(TeacherHomeworkModel hw) {
final isCompleted = hw.status == 'completed';
return Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: TeacherTheme.surfaceDark,
borderRadius: BorderRadius.circular(14),
border: Border.all(color: isCompleted ? TeacherTheme.surfaceBorder : TeacherTheme.emeraldPrimary.withOpacity(0.3)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(hw.title, style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w800, color: Colors.white)),
const SizedBox(height: 4),
Text('${hw.className} · ${hw.dueDate}', style: const TextStyle(fontSize: 11, color: Color(0xFF94A3B8))),
],
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
hw.title,
style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w800, color: Colors.white),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
decoration: BoxDecoration(
color: TeacherTheme.emeraldPrimary.withOpacity(0.15),
color: isCompleted ? const Color(0xFF1E293B) : TeacherTheme.emeraldPrimary.withOpacity(0.15),
borderRadius: BorderRadius.circular(6),
),
child: Text(
hw.submitted,
style: const TextStyle(fontSize: 11, fontWeight: FontWeight.w700, color: TeacherTheme.emeraldLight),
isCompleted ? 'مكتمل التسليم' : 'نشط حالياً',
style: TextStyle(
fontSize: 10.5,
fontWeight: FontWeight.w800,
color: isCompleted ? const Color(0xFF94A3B8) : TeacherTheme.emeraldPrimary,
),
),
),
const SizedBox(height: 4),
Text('معدل الشعبة: ${hw.averageScore}', style: const TextStyle(fontSize: 10.5, color: Color(0xFF64748B))),
],
),
const SizedBox(height: 6),
Row(
children: [
Text(hw.className, style: const TextStyle(fontSize: 11, color: Color(0xFF94A3B8))),
const Spacer(),
Text('المعدل: ${hw.averageScore}', style: const TextStyle(fontSize: 11, fontWeight: FontWeight.bold, color: TeacherTheme.royalGold)),
],
),
],
@@ -253,15 +488,15 @@ class _TeacherAssignmentsQnATabState extends State<TeacherAssignmentsQnATab> {
);
}
Widget _buildDoubtCard(StudentDoubtModel d) {
Widget _buildDoubtCard(StudentDoubtModel doubt) {
return Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: TeacherTheme.surfaceCard,
color: TeacherTheme.surfaceDark,
borderRadius: BorderRadius.circular(14),
border: Border.all(
color: d.replied ? TeacherTheme.emeraldPrimary.withOpacity(0.3) : TeacherTheme.cyberCyan.withOpacity(0.4),
color: doubt.replied ? TeacherTheme.surfaceBorder : TeacherTheme.cyberCyan.withOpacity(0.5),
),
),
child: Column(
@@ -270,53 +505,76 @@ class _TeacherAssignmentsQnATabState extends State<TeacherAssignmentsQnATab> {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${d.studentName} · ${d.className}',
style: const TextStyle(fontSize: 12.5, fontWeight: FontWeight.w800, color: TeacherTheme.cyberCyan),
Row(
children: [
Container(
width: 32,
height: 32,
decoration: BoxDecoration(
color: TeacherTheme.cyberCyan.withOpacity(0.2),
shape: BoxShape.circle,
),
child: Center(
child: Text(
doubt.studentName.characters.first,
style: const TextStyle(color: TeacherTheme.cyberCyan, fontWeight: FontWeight.bold, fontSize: 13),
),
),
),
const SizedBox(width: 8),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(doubt.studentName, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 12.5)),
Text(doubt.className, style: const TextStyle(color: Color(0xFF94A3B8), fontSize: 10.5)),
],
),
],
),
Text(d.time, style: const TextStyle(fontSize: 11, color: Color(0xFF64748B))),
Text(doubt.time, style: const TextStyle(color: Color(0xFF64748B), fontSize: 10.5)),
],
),
const SizedBox(height: 8),
Text(
d.question,
style: const TextStyle(fontSize: 13, color: Colors.white, height: 1.4),
const SizedBox(height: 10),
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: TeacherTheme.surfaceCard,
borderRadius: BorderRadius.circular(10),
),
child: Text(
doubt.question,
style: const TextStyle(color: Colors.white70, fontSize: 12, height: 1.4),
),
),
const SizedBox(height: 12),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (d.replied)
const Row(
children: [
Icon(CupertinoIcons.checkmark_seal_fill, color: TeacherTheme.emeraldLight, size: 15),
SizedBox(width: 6),
Text(
'تم إرسال الرد الصوتي للطالب 🎧',
style: TextStyle(fontSize: 11.5, color: Color(0xFF6EE7B7), fontWeight: FontWeight.w700),
),
],
if (doubt.replied)
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: TeacherTheme.emeraldPrimary.withOpacity(0.15),
borderRadius: BorderRadius.circular(6),
),
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(CupertinoIcons.checkmark_alt_circle_fill, color: TeacherTheme.emeraldPrimary, size: 14),
SizedBox(width: 4),
Text('تم الرد بصوت مسجل 🎧', style: TextStyle(color: TeacherTheme.emeraldPrimary, fontSize: 11, fontWeight: FontWeight.bold)),
],
),
)
else
const Row(
children: [
Icon(CupertinoIcons.clock_fill, color: TeacherTheme.royalGold, size: 14),
SizedBox(width: 6),
Text(
'بانتظار إجابة المعلم',
style: TextStyle(fontSize: 11.5, color: TeacherTheme.royalGold),
),
],
),
if (!d.replied)
ElevatedButton.icon(
onPressed: () => _recordVoiceReply(d.id),
onPressed: () => _recordVoiceReply(doubt.id, doubt.studentName),
icon: const Icon(CupertinoIcons.mic_fill, size: 14),
label: const Text('تسجيل رد صوتي 🎙️', style: TextStyle(fontSize: 11, fontWeight: FontWeight.w700)),
label: const Text('تسجيل رد صوتي سقراطي 🎙️', style: TextStyle(fontSize: 11.5, fontWeight: FontWeight.w800)),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF0284C7),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
backgroundColor: TeacherTheme.emeraldPrimary,
foregroundColor: Colors.black,
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
),
@@ -1,6 +1,8 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../core/theme/teacher_theme.dart';
import '../../../logic/cubits/teacher_auth_cubit.dart';
/**
* ==============================================================================
@@ -17,6 +19,9 @@ class TeacherReputationScorecardTab extends StatelessWidget {
@override
Widget build(BuildContext context) {
final authState = context.watch<TeacherAuthCubit>().state;
final teacherName = (authState is TeacherAuthenticated) ? authState.profile.name : 'المهندس حمزة الغويريين';
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
@@ -42,9 +47,9 @@ class TeacherReputationScorecardTab extends StatelessWidget {
child: Icon(CupertinoIcons.rosette, size: 36, color: Colors.white),
),
const SizedBox(height: 12),
const Text(
'أ. أحمد المجالي',
style: TextStyle(
Text(
teacherName,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w900,
color: Colors.white,