Implement multi-teacher video selector, in-app curriculum document reader, 15-question Unit 1 exam bank, and interactive science simulation engine
This commit is contained in:
+308
@@ -0,0 +1,308 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../core/theme/app_colors.dart';
|
||||
import '../../../core/utils/saqel_toast.dart';
|
||||
import '../../widgets/luxury_widgets.dart';
|
||||
|
||||
class CurriculumDocumentViewerScreen extends StatefulWidget {
|
||||
final String title;
|
||||
final String documentType; // 'worksheet', 'summary', 'textbook'
|
||||
final String subjectTitle;
|
||||
final String? customContent;
|
||||
|
||||
const CurriculumDocumentViewerScreen({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.documentType,
|
||||
required this.subjectTitle,
|
||||
this.customContent,
|
||||
});
|
||||
|
||||
@override
|
||||
State<CurriculumDocumentViewerScreen> createState() => _CurriculumDocumentViewerScreenState();
|
||||
}
|
||||
|
||||
class _CurriculumDocumentViewerScreenState extends State<CurriculumDocumentViewerScreen> {
|
||||
double _fontSize = 14.5;
|
||||
bool _showAnswer = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.darkBackground,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.darkSurface,
|
||||
elevation: 0,
|
||||
title: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
widget.title,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w700),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
'${widget.subjectTitle} • تصفح وقراءة ذكية',
|
||||
style: const TextStyle(color: AppColors.saqelCyan, fontSize: 11, fontWeight: FontWeight.w600),
|
||||
),
|
||||
],
|
||||
),
|
||||
centerTitle: true,
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(CupertinoIcons.textformat_size, color: Colors.white70, size: 20),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_fontSize = _fontSize >= 18.0 ? 13.0 : _fontSize + 1.5;
|
||||
});
|
||||
SaqelToast.showInfo(context, 'تم ضبط حجم الخط (${_fontSize.toInt()}pt)', title: 'حجم الخط');
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(CupertinoIcons.share, color: Colors.white70, size: 20),
|
||||
onPressed: () {
|
||||
SaqelToast.showSuccess(context, 'تم نسخ رابط المستند لمشاركته مع الزملاء', title: 'مشاركة الوثيقة 🔗');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Directionality(
|
||||
textDirection: TextDirection.rtl,
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Document Status Banner
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
AppColors.saqelCyan.withAlpha(25),
|
||||
AppColors.appleBlue.withAlpha(20),
|
||||
],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
border: Border.all(color: AppColors.saqelCyan.withAlpha(40)),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(CupertinoIcons.doc_checkmark_fill, color: AppColors.saqelCyan, size: 22),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
widget.documentType == 'textbook' ? 'الكتاب المدرسي المعتمد — وزارة التربية والتعليم' : 'ورقة عمل ومذكرة مراجعة معيارية',
|
||||
style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w700, fontSize: 13),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
const Text(
|
||||
'تمت مراجعة المحتوى وفهرسته ومطابقته لنتاجات الفصل الدراسي الأول',
|
||||
style: TextStyle(color: AppColors.textSecondaryDark, fontSize: 11),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// Section 1: Objectives & Learning Outcomes
|
||||
_buildSectionCard(
|
||||
title: 'الأهداف والنتاجات المستهدفة 🎯',
|
||||
content: [
|
||||
'1. حل المعادلات الخاصة بتحليل المقادير الجبرية وإخراج العامل المشترك الأكبر.',
|
||||
'2. إيجاد نقاط التقاطع بين مستقيم وقطع مكافئ هندسياً وجبرياً بطريقة التعويض.',
|
||||
'3. استخدام المميز (Δ) لتحديد عدد الحلول الحقيقية للنظام (حلان، حل وحيد، أو لا يوجد حل).',
|
||||
'4. حل أنظمة المعادلات المكوّنة من معادلتيْن تربيعيتيْن بطريقة الحذف أو التعويض.',
|
||||
'5. توظيف برمجية جيوجبرا في تمثيل المنحنيات وإيجاد نقط التقاطع بدقة.',
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Section 2: Core Theorems and Golden Rules
|
||||
_buildSectionCard(
|
||||
title: 'القواعد الذهبية والقوانين الوزارية 💡',
|
||||
content: [
|
||||
'• قاعدة العامل الصفري: إذا كان A × B = 0 فإن A = 0 أو B = 0.',
|
||||
'• الصورة التربيعية: المعادلة ax⁴ + bx² + c = 0 تُحل بالتعويض u = x² لتصبح au² + bu + c = 0.',
|
||||
'• مميز المعادلة التربيعية: Δ = b² - 4ac:\n - إذا كان Δ > 0: للنظام حلّان حقيقيان مختلفان (يتقاطع المستقيم مع المنحنى في نقطتين).\n - إذا كان Δ = 0: للنظام حل حقيقي وحيد (المستقيم مماس للمنحنى).\n - إذا كان Δ < 0: لا يوجد أي حل حقيقي للنظام (المستقيم لا يتقاطع مع المنحنى).',
|
||||
'• تقاطع دائرة وقطع مكافئ: أقصى عدد ممكن لنقاط التقاطع الحقيقية هو 4 نقاط.',
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Section 3: Solved Examples Step-by-Step
|
||||
LuxuryCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'مثال نموذجي محلول خطوة بخطوة ✍️',
|
||||
style: TextStyle(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 15),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.emeraldGreen.withAlpha(30),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: const Text(
|
||||
'سؤال وزاري متوقع',
|
||||
style: TextStyle(color: AppColors.emeraldGreen, fontSize: 11, fontWeight: FontWeight.w700),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'المسألة: حُلّ نظام المعادلات التالي في مجموعة الأعداد الحقيقية:\n(1) y = x + 1\n(2) y = x² + 1',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: _fontSize,
|
||||
fontWeight: FontWeight.w600,
|
||||
height: 1.6,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black26,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: AppColors.darkCardBorder),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text(
|
||||
'خطوات الحل النموذجي:',
|
||||
style: TextStyle(color: AppColors.saqelCyan, fontWeight: FontWeight.w700, fontSize: 13),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'1. بمساواة المعادلتين بالتعويض عن قيمة y:\n x² + 1 = x + 1\n\n'
|
||||
'2. بطرح (x + 1) من الطرفين لجعل المعادلة صفرية:\n x² - x = 0\n\n'
|
||||
'3. بإخراج x كعامل مشترك أكبر:\n x(x - 1) = 0\n\n'
|
||||
'4. إما x = 0 أو x = 1.\n\n'
|
||||
'5. إيجاد قيمة y بالتعويض في المعادلة الخطية:\n'
|
||||
' - عندما x = 0 => y = 0 + 1 = 1 => نقطة التقاطع الأولى (0, 1)\n'
|
||||
' - عندما x = 1 => y = 1 + 1 = 2 => نقطة التقاطع الثانية (1, 2)\n\n'
|
||||
'مجموعة حل النظام هي: { (0, 1), (1, 2) }',
|
||||
style: TextStyle(
|
||||
color: AppColors.textSecondaryDark,
|
||||
fontSize: _fontSize - 0.5,
|
||||
height: 1.6,
|
||||
fontFamily: 'SF Pro Text',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Section 4: Self-Test Exercise with Reveal Answer
|
||||
LuxuryCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Row(
|
||||
children: [
|
||||
Icon(CupertinoIcons.pencil_ellipsis_rectangle, color: AppColors.guardianAmber, size: 20),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
'تمرين تدريبي للتقييم الذاتي 📝',
|
||||
style: TextStyle(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 15),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'حُلّ النظام التربيعي التالي بطريقة الحذف:\n(1) x² + y² = 25\n(2) x² - y² = 7',
|
||||
style: TextStyle(color: Colors.white, fontSize: _fontSize, height: 1.6),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Center(
|
||||
child: TextButton.icon(
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: AppColors.saqelCyan,
|
||||
backgroundColor: AppColors.saqelCyan.withAlpha(20),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() => _showAnswer = !_showAnswer);
|
||||
},
|
||||
icon: Icon(_showAnswer ? CupertinoIcons.eye_slash : CupertinoIcons.eye, size: 18),
|
||||
label: Text(_showAnswer ? 'إخفاء الحل النموذجي' : 'إظهار الحل النموذجي للتحقق 🔍'),
|
||||
),
|
||||
),
|
||||
if (_showAnswer) ...[
|
||||
const SizedBox(height: 12),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.emeraldGreen.withAlpha(15),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: AppColors.emeraldGreen.withAlpha(50)),
|
||||
),
|
||||
child: Text(
|
||||
'الحل:\nبجمع المعادلتين: 2x² = 32 => x² = 16 => x = ±4\n'
|
||||
'بالتعويض في الأولى: 16 + y² = 25 => y² = 9 => y = ±3\n'
|
||||
'حلول النظام الأربعة هي: (4, 3), (4, -3), (-4, 3), (-4, -3).',
|
||||
style: TextStyle(color: Colors.white, fontSize: _fontSize - 1, height: 1.5),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSectionCard({required String title, required List<String> content}) {
|
||||
return LuxuryCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 15),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
...content.map((line) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: Text(
|
||||
line,
|
||||
style: TextStyle(
|
||||
color: AppColors.textSecondaryDark,
|
||||
fontSize: _fontSize,
|
||||
height: 1.55,
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import '../../../data/models/subject_model.dart';
|
||||
import '../../widgets/luxury_widgets.dart';
|
||||
import '../player/socratic_video_player_screen.dart';
|
||||
import '../exams/adaptive_exam_screen.dart';
|
||||
import 'curriculum_document_viewer_screen.dart';
|
||||
|
||||
class SubjectHubScreen extends StatefulWidget {
|
||||
final SubjectModel subject;
|
||||
@@ -184,14 +185,7 @@ class _SubjectHubScreenState extends State<SubjectHubScreen> with SingleTickerPr
|
||||
),
|
||||
trailing: const Icon(CupertinoIcons.chevron_back, color: AppColors.textSecondaryDark, size: 16),
|
||||
onTap: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => SocraticVideoPlayerScreen(
|
||||
lesson: lesson,
|
||||
subject: widget.subject,
|
||||
),
|
||||
),
|
||||
);
|
||||
_showLessonVideoSelector(context, lesson);
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -265,9 +259,9 @@ class _SubjectHubScreenState extends State<SubjectHubScreen> with SingleTickerPr
|
||||
/// Tab 3: Question Bank & Adaptive Unit Exams
|
||||
Widget _buildExamsTab(BuildContext context) {
|
||||
final exams = [
|
||||
const SubjectExamModel(id: 'ex1', title: 'اختبار الفهم الشامل: الوحدة الأولى', questionsCount: 25, durationMinutes: 45, targetScore: 100),
|
||||
const SubjectExamModel(id: 'ex2', title: 'نماذج أسئلة الوزارة للسنوات السابقة', questionsCount: 30, durationMinutes: 60, targetScore: 100),
|
||||
const SubjectExamModel(id: 'ex3', title: 'اختبار تشخيص الثغرات التكيفي بالذكاء الاصطناعي', questionsCount: 15, durationMinutes: 25, targetScore: 100),
|
||||
const SubjectExamModel(id: 'ex1', title: 'اختبار الفهم الشامل: الوحدة الأولى (أنظمة المعادلات)', questionsCount: 15, durationMinutes: 45, targetScore: 100),
|
||||
const SubjectExamModel(id: 'ex2', title: 'نماذج أسئلة الوزارة للسنوات السابقة', questionsCount: 15, durationMinutes: 45, targetScore: 100),
|
||||
const SubjectExamModel(id: 'ex3', title: 'اختبار تشخيص الثغرات التكيفي بالذكاء الاصطناعي', questionsCount: 15, durationMinutes: 30, targetScore: 100),
|
||||
];
|
||||
|
||||
return ListView.builder(
|
||||
@@ -483,7 +477,15 @@ class _SubjectHubScreenState extends State<SubjectHubScreen> with SingleTickerPr
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.of(ctx).pop();
|
||||
SaqelToast.showInfo(context, 'جاري عرض محتوى $title بالكامل عبر عارض الكتب الذكي', title: 'فتح الوثيقة 📑');
|
||||
Navigator.of(context).push(
|
||||
CupertinoPageRoute(
|
||||
builder: (_) => CurriculumDocumentViewerScreen(
|
||||
title: title,
|
||||
documentType: title.contains('كتاب') ? 'textbook' : 'worksheet',
|
||||
subjectTitle: widget.subject.title,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(CupertinoIcons.book, size: 18),
|
||||
label: const Text('قراءة وتصفح', style: TextStyle(fontWeight: FontWeight.w800)),
|
||||
@@ -497,4 +499,210 @@ class _SubjectHubScreenState extends State<SubjectHubScreen> with SingleTickerPr
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Multi-Teacher and AI Video Selector Bottom Sheet
|
||||
void _showLessonVideoSelector(BuildContext context, CurriculumLessonItemModel lesson) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
backgroundColor: AppColors.darkSurface,
|
||||
isScrollControlled: true,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
||||
),
|
||||
builder: (ctx) => SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Center(
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white24,
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.saqelCyan.withAlpha(25),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: const Icon(CupertinoIcons.play_circle_fill, color: AppColors.saqelCyan, size: 24),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text(
|
||||
'اختر أسلوب الشرح المناسب لك 🎥',
|
||||
style: TextStyle(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 16),
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
Text(
|
||||
lesson.title,
|
||||
style: const TextStyle(color: AppColors.textSecondaryDark, fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 18),
|
||||
|
||||
// Option 1: Official Saqel AI Master Lesson
|
||||
_buildVideoOptionCard(
|
||||
title: 'شرح الذكاء الاصطناعي لمنصة صَقِل 🤖',
|
||||
subtitle: 'الشرح الرسمي المعتمد وتفكيك المفاهيم خطوة بخطوة',
|
||||
tag: 'المنهاج المعتمد + سقراطي',
|
||||
tagColor: AppColors.saqelCyan,
|
||||
icon: CupertinoIcons.sparkles,
|
||||
iconColor: AppColors.saqelCyan,
|
||||
onTap: () {
|
||||
Navigator.of(ctx).pop();
|
||||
Navigator.of(context).push(
|
||||
CupertinoPageRoute(
|
||||
builder: (_) => SocraticVideoPlayerScreen(
|
||||
lesson: lesson,
|
||||
subject: widget.subject,
|
||||
instructorName: 'منصة صَقِل الذكية 🤖',
|
||||
videoSourceLabel: 'شرح الذكاء الاصطناعي الرسمي',
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Option 2: Certified Teacher 1
|
||||
_buildVideoOptionCard(
|
||||
title: 'شرح الأستاذ رعد الخمايسة 👨🏫',
|
||||
subtitle: 'خبير التوجيهي — حل نماذج وأسئلة وزارية إضافية',
|
||||
tag: 'معلم معتمد 🌟 4.9',
|
||||
tagColor: AppColors.guardianAmber,
|
||||
icon: CupertinoIcons.person_crop_circle_badge_checkmark,
|
||||
iconColor: AppColors.guardianAmber,
|
||||
onTap: () {
|
||||
Navigator.of(ctx).pop();
|
||||
Navigator.of(context).push(
|
||||
CupertinoPageRoute(
|
||||
builder: (_) => SocraticVideoPlayerScreen(
|
||||
lesson: lesson,
|
||||
subject: widget.subject,
|
||||
instructorName: 'أ. رعد الخمايسة (معلم معتمد)',
|
||||
videoSourceLabel: 'شرح الأستاذ رعد الخمايسة',
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Option 3: Certified Teacher 2
|
||||
_buildVideoOptionCard(
|
||||
title: 'شرح الأستاذ إياد النجار 👨🏫',
|
||||
subtitle: 'كبير المعلمين — تبسيط المفاهيم المعقدة والتحليل البياني',
|
||||
tag: 'معلم معتمد 🌟 4.8',
|
||||
tagColor: AppColors.emeraldGreen,
|
||||
icon: CupertinoIcons.person_crop_circle_fill,
|
||||
iconColor: AppColors.emeraldGreen,
|
||||
onTap: () {
|
||||
Navigator.of(ctx).pop();
|
||||
Navigator.of(context).push(
|
||||
CupertinoPageRoute(
|
||||
builder: (_) => SocraticVideoPlayerScreen(
|
||||
lesson: lesson,
|
||||
subject: widget.subject,
|
||||
instructorName: 'أ. إياد النجار (كبير المعلمين)',
|
||||
videoSourceLabel: 'شرح الأستاذ إياد النجار',
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildVideoOptionCard({
|
||||
required String title,
|
||||
required String subtitle,
|
||||
required String tag,
|
||||
required Color tagColor,
|
||||
required IconData icon,
|
||||
required Color iconColor,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.darkCard,
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
border: Border.all(color: AppColors.darkCardBorder),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: iconColor.withAlpha(25),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Icon(icon, color: iconColor, size: 22),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w700, fontSize: 13.5),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: tagColor.withAlpha(25),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: Text(
|
||||
tag,
|
||||
style: TextStyle(color: tagColor, fontSize: 10, fontWeight: FontWeight.w700),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
subtitle,
|
||||
style: const TextStyle(color: AppColors.textSecondaryDark, fontSize: 11.5),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
const Icon(CupertinoIcons.chevron_back, color: AppColors.textSecondaryDark, size: 14),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,15 @@ import 'package:video_player/video_player.dart';
|
||||
class SocraticVideoPlayerScreen extends StatefulWidget {
|
||||
final CurriculumLessonItemModel lesson;
|
||||
final SubjectModel? subject;
|
||||
final String? instructorName;
|
||||
final String? videoSourceLabel;
|
||||
|
||||
const SocraticVideoPlayerScreen({
|
||||
super.key,
|
||||
required this.lesson,
|
||||
this.subject,
|
||||
this.instructorName,
|
||||
this.videoSourceLabel,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -593,6 +597,28 @@ class _SocraticVideoPlayerScreenState extends State<SocraticVideoPlayerScreen> w
|
||||
),
|
||||
],
|
||||
),
|
||||
if (widget.instructorName != null || widget.videoSourceLabel != null) ...[
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.saqelCyan.withAlpha(25),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: AppColors.saqelCyan.withAlpha(60)),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(CupertinoIcons.person_crop_circle_fill, color: AppColors.saqelCyan, size: 14),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
widget.instructorName ?? widget.videoSourceLabel ?? 'شرح منصة صَقِل الذكية 🤖',
|
||||
style: const TextStyle(color: AppColors.saqelCyan, fontSize: 11, fontWeight: FontWeight.w700),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 14),
|
||||
if (widget.lesson.outcomes.isNotEmpty)
|
||||
...widget.lesson.outcomes.map((out) {
|
||||
|
||||
Reference in New Issue
Block a user