Update Saqel Platform: 2026-09-04 03:09:10

This commit is contained in:
Hamza-Ayed
2026-09-04 03:09:10 +03:00
parent 882541a56a
commit 1235abc0cb
9 changed files with 689 additions and 83 deletions
@@ -669,37 +669,81 @@ class _UnifiedHomeScreenState extends State<UnifiedHomeScreen> {
const Divider(color: AppColors.darkCardBorder),
const SizedBox(height: 10),
_buildGuardianStat('الامتحانات المنجزة بنجاح', '${selectedChild.examsPassed} من ${selectedChild.examsTotal}'),
_buildGuardianStat('الرقم الوطني', selectedChild.nationalId ?? 'مسجل بالهاتف'),
_buildGuardianStat('دفتر الأخطاء الذكي', '8 من أصل 10 فجوات تم شفاؤها وإتقانها 🏆'),
_buildGuardianStat('نسبة الحضور ومشاهدة الحصص', '96% (28 حصة مكتملة)'),
_buildGuardianStat('الفحوصات السقراطية التفاعلية', '18 فحصاً مجتازاً بنجاح ✨'),
_buildGuardianStat('الرقم الوطني المشفر', selectedChild.nationalId ?? 'مسجل بالهاتف'),
],
),
),
const SizedBox(height: 16),
// Real WhatsApp Reports Integration Banner
LuxuryCard(
backgroundColor: const Color(0xFF075E54).withAlpha(35),
borderColor: AppColors.whatsappGreen.withAlpha(80),
child: const Row(
children: [
Icon(CupertinoIcons.chat_bubble_fill, color: AppColors.whatsappGreen, size: 24),
SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'تقارير بوابة نبيه للواتساب',
style: TextStyle(fontSize: 13.5, fontWeight: FontWeight.w700, color: Colors.white),
),
SizedBox(height: 2),
Text(
'تصلك إشعارات الأداء والغياب آلياً عبر رقم الواتساب المسجل',
style: TextStyle(fontSize: 11, color: AppColors.textSecondaryDark),
InkWell(
onTap: () {
showCupertinoDialog(
context: context,
builder: (ctx) => Directionality(
textDirection: TextDirection.rtl,
child: CupertinoAlertDialog(
title: const Text('ومضة التقرير الشهري لولي الأمر 📲'),
content: Text(
'🇯🇴 تقرير التحصيل الأكاديمي لشهر آب/أيلول 2026\n'
'الطالب: ${selectedChild.name}\n'
'المدرسة: ${selectedChild.schoolName ?? "الثقافة العسكرية"}\n\n'
'• مؤشر الجاهزية للتوجيهي: ${selectedChild.readinessScore.toStringAsFixed(1)}%\n'
'• الحصص المكتملة: 28 حصة بنسبة التزام 96%\n'
'• دفتر الأخطاء: تم إتقان 8 فجوات بنجاح\n'
'• نتيجة الامتحان الموحد الأخير: 88%\n\n'
'تم إرسال هذا التقرير عبر بوابة نبيه للواتساب برقم هاتف ولي الأمر.',
textAlign: TextAlign.start,
),
actions: [
CupertinoDialogAction(
onPressed: () => Navigator.of(ctx).pop(),
child: const Text('إغلاق'),
),
],
),
),
],
);
},
borderRadius: BorderRadius.circular(16),
child: LuxuryCard(
backgroundColor: const Color(0xFF075E54).withAlpha(45),
borderColor: AppColors.whatsappGreen.withAlpha(90),
child: const Row(
children: [
Icon(CupertinoIcons.chat_bubble_2_fill, color: AppColors.whatsappGreen, size: 26),
SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'تقارير بوابة نبيه للواتساب 📲',
style: TextStyle(fontSize: 13.5, fontWeight: FontWeight.w800, color: Colors.white),
),
SizedBox(width: 6),
Text(
'· نشطة',
style: TextStyle(color: Color(0xFF34D399), fontWeight: FontWeight.w700, fontSize: 11),
),
],
),
SizedBox(height: 3),
Text(
'انقر لمعاينة ومضة الأداء الأكاديمي الشهرية المرسلة لولي الأمر',
style: TextStyle(fontSize: 11, color: AppColors.textSecondaryDark),
),
],
),
),
Icon(CupertinoIcons.chevron_back, color: AppColors.whatsappGreen, size: 16),
],
),
),
),
],
+343 -4
View File
@@ -141,6 +141,7 @@ class _TeacherMainShellState extends State<TeacherMainShell> {
TeacherStudioUploadView(),
TeacherMonetizationView(),
TeacherReputationScorecardView(),
TeacherAssignmentsAndQnAView(),
],
),
bottomNavigationBar: Container(
@@ -155,8 +156,8 @@ class _TeacherMainShellState extends State<TeacherMainShell> {
selectedItemColor: const Color(0xFF10B981),
unselectedItemColor: const Color(0xFF64748B),
selectedLabelStyle:
const TextStyle(fontWeight: FontWeight.w800, fontSize: 12),
unselectedLabelStyle: const TextStyle(fontSize: 11),
const TextStyle(fontWeight: FontWeight.w800, fontSize: 11),
unselectedLabelStyle: const TextStyle(fontSize: 10.5),
type: BottomNavigationBarType.fixed,
elevation: 0,
items: const [
@@ -166,11 +167,15 @@ class _TeacherMainShellState extends State<TeacherMainShell> {
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.money_dollar_circle_fill),
label: 'محفظة التسييل (55%)',
label: 'محفظة التسييل',
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.chart_bar_circle_fill),
label: 'بطاقة الأداء والرادار',
label: 'رادار الأداء',
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.chat_bubble_2_fill),
label: 'الواجبات والأسئلة',
),
],
),
@@ -1033,3 +1038,337 @@ class _ScoreStat extends StatelessWidget {
);
}
}
/// ==============================================================================
/// TAB 4: TEACHER ASSIGNMENTS & STUDENT DOUBT CLEARING (Q&A & VOICE REPLIES)
/// ==============================================================================
class TeacherAssignmentsAndQnAView extends StatefulWidget {
const TeacherAssignmentsAndQnAView({super.key});
@override
State<TeacherAssignmentsAndQnAView> createState() =>
_TeacherAssignmentsAndQnAViewState();
}
class _TeacherAssignmentsAndQnAViewState
extends State<TeacherAssignmentsAndQnAView> {
final List<Map<String, dynamic>> _homeworks = [
{
'title': 'ورقة عمل: قوانين نيوتن وتطبيقات المصاعد',
'class': 'الأول ثانوي العلمي (شعبة أ)',
'submitted': '38 من 42 طالباً',
'due_date': 'غداً الساعة 08:00 مساءً',
'average_score': '86%',
'status': 'active',
},
{
'title': 'واجب بيتي: مسائل تحليل المتجهات والضرب القياسي',
'class': 'الأول ثانوي العلمي (شعبة ب)',
'submitted': '41 من 41 طالباً',
'due_date': 'مكتمل التسليم والتصحيح الآلي',
'average_score': '92%',
'status': 'completed',
},
];
final List<Map<String, dynamic>> _studentDoubts = [
{
'student_name': 'محمد طارق الحنيطي',
'class': 'الأول ثانوي العلمي',
'question': 'أستاذ، لماذا ينعدم الوزن الظاهري في المصعد الساقط سقوطاً حراً؟ هل تفقد الأجسام كتلتها؟',
'time': 'منذ 25 دقيقة',
'replied': false,
'voice_reply': false,
},
{
'student_name': 'سيف الدين الرواشدة',
'class': 'الأول ثانوي العلمي',
'question': 'هل قوة الاحتكاك السكوني دائماً تساوي القوة المؤثرة حتى نصل للقيمة العظمى؟',
'time': 'منذ ساعتين',
'replied': true,
'voice_reply': true,
},
];
void _dispatchNewHomework() {
showCupertinoDialog(
context: context,
builder: (ctx) => Directionality(
textDirection: TextDirection.rtl,
child: CupertinoAlertDialog(
title: const Text('إسناد ورقة عمل تفاعلية جديدة 📝'),
content: const Text(
'سيقوم محرك صَقِل بتوليد ورقة عمل مكونة من 5 مسائل تدريبية متدرجة من بنك الأسئلة الوزاري وإرسالها فوراً لشعبتك مع التصحيح التلقائي.',
),
actions: [
CupertinoDialogAction(
onPressed: () => Navigator.of(ctx).pop(),
child: const Text('إلغاء'),
),
CupertinoDialogAction(
isDefaultAction: true,
onPressed: () {
Navigator.of(ctx).pop();
setState(() {
_homeworks.insert(0, {
'title': 'ورقة عمل: الشغل والطاقة الميكانيكية',
'class': 'الأول ثانوي العلمي (شعبة أ وب)',
'submitted': '0 من 83 طالباً',
'due_date': 'الخميس القادم',
'average_score': 'بانتظار الإجابات',
'status': 'active',
});
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('تم إسناد ورقة العمل وإشعار الطلبة بنجاح 🚀'),
backgroundColor: Color(0xFF10B981),
),
);
},
child: const Text('إسناد للطلبة الآن'),
),
],
),
),
);
}
void _recordVoiceReply(int doubtIndex) {
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
builder: (ctx) => Directionality(
textDirection: TextDirection.rtl,
child: Container(
decoration: const BoxDecoration(
color: Color(0xFF0F172A),
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
border: Border(top: BorderSide(color: Color(0xFF10B981), width: 2)),
),
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(CupertinoIcons.mic_circle_fill, size: 56, color: Color(0xFF10B981)),
const SizedBox(height: 12),
const Text(
'تسجيل رد صوتي سقراطي للطالب 🎙️',
style: TextStyle(fontSize: 16, 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: () {
Navigator.of(ctx).pop();
setState(() {
_studentDoubts[doubtIndex]['replied'] = true;
_studentDoubts[doubtIndex]['voice_reply'] = true;
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('تم إرسال الرد الصوتي للطالب بنجاح 🎧'),
backgroundColor: Color(0xFF10B981),
),
);
},
icon: const Icon(CupertinoIcons.paperplane_fill, size: 16),
label: const Text('إنهاء وإرسال التسجيل الصوتي (00:42)'),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF10B981),
foregroundColor: Colors.black,
minimumSize: const Size(double.infinity, 44),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
),
),
],
),
),
),
);
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Top Action Card
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF064E3B), Color(0xFF0F172A)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: const Color(0xFF10B981).withOpacity(0.4)),
),
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)),
),
],
),
ElevatedButton.icon(
onPressed: _dispatchNewHomework,
icon: const Icon(CupertinoIcons.plus_circle_fill, size: 16),
label: const Text('إسناد واجب جديد', style: TextStyle(fontSize: 12, fontWeight: FontWeight.w800)),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF10B981),
foregroundColor: Colors.black,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
),
],
),
),
const SizedBox(height: 16),
// Homeworks List
..._homeworks.map((hw) => Container(
margin: const EdgeInsets.only(bottom: 10),
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: const Color(0xFF0F172A),
borderRadius: BorderRadius.circular(14),
border: Border.all(color: const Color(0xFF1E293B)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
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['class']} · ${hw['due_date']}', style: const TextStyle(fontSize: 11, color: Color(0xFF94A3B8))),
],
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
decoration: BoxDecoration(
color: const Color(0xFF10B981).withOpacity(0.15),
borderRadius: BorderRadius.circular(6),
),
child: Text(hw['submitted'], style: const TextStyle(fontSize: 11, fontWeight: FontWeight.w700, color: Color(0xFF34D399))),
),
const SizedBox(height: 4),
Text('معدل الشعبة: ${hw['average_score']}', style: const TextStyle(fontSize: 10.5, color: Color(0xFF64748B))),
],
),
],
),
)),
const SizedBox(height: 18),
// Student Doubts Section
const Row(
children: [
Icon(CupertinoIcons.bubble_left_bubble_right_fill, color: Color(0xFF38BDF8), size: 18),
SizedBox(width: 8),
Text(
'استفسارات وأسئلة الطلبة الميدانية (غرفة الشكوك) 💬',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w800, color: Colors.white),
),
],
),
const SizedBox(height: 10),
..._studentDoubts.asMap().entries.map((entry) {
final idx = entry.key;
final d = entry.value;
final replied = d['replied'] as bool;
return Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: const Color(0xFF0F172A),
borderRadius: BorderRadius.circular(14),
border: Border.all(
color: replied ? const Color(0xFF10B981).withOpacity(0.3) : const Color(0xFF38BDF8).withOpacity(0.4),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('${d['student_name']} · ${d['class']}', style: const TextStyle(fontSize: 12.5, fontWeight: FontWeight.w800, color: Color(0xFF38BDF8))),
Text(d['time'], style: const TextStyle(fontSize: 11, color: Color(0xFF64748B))),
],
),
const SizedBox(height: 8),
Text(
d['question'],
style: const TextStyle(fontSize: 13, color: Colors.white, height: 1.4),
),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (replied)
const Row(
children: [
Icon(CupertinoIcons.checkmark_seal_fill, color: Color(0xFF34D399), size: 15),
SizedBox(width: 6),
Text('تم إرسال الرد الصوتي للطالب 🎧', style: TextStyle(fontSize: 11.5, color: Color(0xFF6EE7B7), fontWeight: FontWeight.w700)),
],
)
else
const Row(
children: [
Icon(CupertinoIcons.clock_fill, color: Color(0xFFFBBF24), size: 14),
SizedBox(width: 6),
Text('بانتظار إجابة المعلم', style: TextStyle(fontSize: 11.5, color: Color(0xFFFBBF24))),
],
),
if (!replied)
ElevatedButton.icon(
onPressed: () => _recordVoiceReply(idx),
icon: const Icon(CupertinoIcons.mic_fill, size: 14),
label: const Text('تسجيل رد صوتي 🎙️', style: TextStyle(fontSize: 11, fontWeight: FontWeight.w700)),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF0284C7),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
),
],
),
],
),
);
}),
],
),
);
}
}