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:
@@ -263,53 +263,236 @@ class ExamCubit extends Cubit<ExamState> {
|
||||
id: examId,
|
||||
uuid: 'exam-default-$examId',
|
||||
courseId: 1,
|
||||
title: title ?? 'اختبار الفهم والتشخيص السقراطي — المستوى المتقدم',
|
||||
description: 'اختبار تشخيصي تكيفي يقيس الفهم العميق والقدرة على تطبيق القوانين الوزارية.',
|
||||
title: title ?? 'اختبار الفهم الشامل: الوحدة الأولى — أنظمة المعادلات',
|
||||
description: 'اختبار وزاري معياري يقيس الفهم العميق والقدرة على تطبيق القوانين لأنظمة المعادلات.',
|
||||
scope: 'unit_exam',
|
||||
passingPercentage: 70.0,
|
||||
durationMinutes: 15,
|
||||
questionsCount: 3,
|
||||
durationMinutes: 45,
|
||||
questionsCount: 15,
|
||||
questions: const [
|
||||
// 1. حل معادلات خاصة (إخراج العامل المشترك)
|
||||
QuestionModel(
|
||||
id: 101,
|
||||
questionText: 'ما هو المعنى الهندسي المباشر للمشتقة الأولى f\'(x) عند نقطة التماس؟',
|
||||
id: 1,
|
||||
questionText: 'ما هي مجموعة حل المعادلة الحقيقية: x³ - 4x = 0؟',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'المعنى الهندسي للاشتقاق',
|
||||
explanationText: 'المشتقة الأولى تمثل رياضياً وهندسياً ميل خط المماس لمنحنى الاقتران عند نقطة التماس.',
|
||||
topicTag: 'حل المعادلات بإخراج العامل المشترك الأكبر',
|
||||
explanationText: 'بإخراج x كعامل مشترك: x(x² - 4) = 0 ومنها x(x - 2)(x + 2) = 0، فيكون الحل x = 0, 2, -2.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 1, optionText: 'ميل خط المماس للمنحنى عند تلك النقطة', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 2, optionText: 'معادلة المستقيم القاطع المار بنقطتين', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 3, optionText: 'المساحة المحصورة تحت المنحنى ومحور السينات', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 4, optionText: 'طول المماس الأفقي عند النقطة الحرجة', isCorrect: false, sequenceOrder: 4),
|
||||
QuestionOptionModel(id: 1, optionText: '{ -2, 0, 2 }', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 2, optionText: '{ 0, 4 }', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 3, optionText: '{ -2, 2 }', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 4, optionText: '{ 0, 2 }', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 2. الصورة التربيعية
|
||||
QuestionModel(
|
||||
id: 102,
|
||||
questionText: 'إذا كان f(x) = sin(4x)، فما هي قيمة مشتقته الأولى f\'(x) وفق قاعدة السلسلة؟',
|
||||
id: 2,
|
||||
questionText: 'حل المعادلة x⁴ - 5x² + 4 = 0 في مجموعة الأعداد الحقيقية هو:',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'مشتقات الاقترانات الدائرية وقاعدة السلسلة',
|
||||
explanationText: 'مشتقة sin(ax) هي a * cos(ax)؛ أي مشتقة الزاوية ضرب مشتقة الاقتران الخارجي.',
|
||||
topicTag: 'المعادلات في الصورة التربيعية',
|
||||
explanationText: 'بالتحليل كمعادلة تربيعية: (x² - 4)(x² - 1) = 0، ومنها x² = 4 أو x² = 1، فالجذور هي ±2 و ±1.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 5, optionText: '4 cos(4x)', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 6, optionText: 'cos(4x)', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 7, optionText: '-4 cos(4x)', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 8, optionText: '4 sin(4x)', isCorrect: false, sequenceOrder: 4),
|
||||
QuestionOptionModel(id: 5, optionText: '{ -2, -1, 1, 2 }', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 6, optionText: '{ 1, 4 }', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 7, optionText: '{ -1, 1 }', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 8, optionText: '{ -4, 4 }', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 3. مجموع المكعبين والحلول الحقيقية
|
||||
QuestionModel(
|
||||
id: 103,
|
||||
questionText: 'ما هو الشرط الرياضي اللازم والكافي ليكون المماس أفقياً عند نقطة واقعة على المنحنى؟',
|
||||
id: 3,
|
||||
questionText: 'كم حلاً حقيقياً يحقق المعادلة: x³ + 8 = 0؟',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'المماسات الأفقية والنقاط الحرجة',
|
||||
explanationText: 'يكون المماس أفقياً وموازياً لمحور السينات عندما يكون ميله مساوياً للصفر، أي f\'(x) = 0.',
|
||||
topicTag: 'تحليل مجموع المكعبين والحلول الحقيقية',
|
||||
explanationText: 'بتحليل مجموع مكعبين: (x + 2)(x² - 2x + 4) = 0. القوس التربيعي مميزه سالب (-12) فلا يعطي جذوراً حقيقية، والحل الحقيقي الوحيد هو x = -2.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 9, optionText: 'أن تكون المشتقة الأولى مساوية للصفر f\'(x) = 0', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 10, optionText: 'أن تكون قيمة الاقتران مساوية للصفر f(x) = 0', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 11, optionText: 'أن تكون المشتقة غير معرّفة أو قيمة مطلقة', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 12, optionText: 'أن يتقاطع المماس مع نقطة الأصل دائماً', isCorrect: false, sequenceOrder: 4),
|
||||
QuestionOptionModel(id: 9, optionText: 'حل حقيقي واحد فقط وهو x = -2', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 10, optionText: 'ثلاثة حلول حقيقية', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 11, optionText: 'حلّان حقيقيان', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 12, optionText: 'لا يوجد أي حل حقيقي', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 4. أقصى عدد حلول لنظام خطي وتربيعي
|
||||
QuestionModel(
|
||||
id: 4,
|
||||
questionText: 'ما هو أقصى عدد ممكن لنقاط التقاطع بين مستقيم وقطع مكافئ في المستوى الإحداثي؟',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'التمثيل الهندسي لنظام خطي وتربيعي',
|
||||
explanationText: 'المستقيم يقطع القطع المكافئ في نقطتين كحد أقصى (حلان)، أو يمسه في نقطة (حل واحد)، أو لا يقطعه (لا يوجد حل حقيقي).',
|
||||
options: [
|
||||
QuestionOptionModel(id: 13, optionText: 'نقطتان كحد أقصى (حلّان حقيقيان)', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 14, optionText: 'ثلاث نقاط تقاطع', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 15, optionText: 'أربع نقاط تقاطع', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 16, optionText: 'نقطة واحدة فقط دائماً', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 5. حل نظام خطي وتربيعي بالتعويض
|
||||
QuestionModel(
|
||||
id: 5,
|
||||
questionText: 'إذا كان لدينا النظام: y = x + 1 و y = x² + 1، فما هي نقاط تقاطع المنحنيين؟',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'حل نظام خطي وتربيعي بطريقة التعويض',
|
||||
explanationText: 'بالمساواة: x² + 1 = x + 1 ومنها x² - x = 0 أي x(x - 1) = 0، فيكون x = 0 أو x = 1. بالتعويض نجد y = 1 أو y = 2.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 17, optionText: '(0, 1) و (1, 2)', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 18, optionText: '(0, 0) و (1, 1)', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 19, optionText: '(1, 2) فقط', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 20, optionText: '(-1, 0) و (1, 2)', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 6. المميز وسالبية الحلول
|
||||
QuestionModel(
|
||||
id: 6,
|
||||
questionText: 'متى لا يوجد أي حل حقيقي لنظام مكوّن من معادلة خطية وأخرى تربيعية؟',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'استخدام المميز لتحديد عدد حلول النظام',
|
||||
explanationText: 'إذا كان مميز المعادلة التربيعية الناتجة عن التعويض سالباً (Δ = b² - 4ac < 0)، فإن المستقيم لا يتقاطع مع المنحنى.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 21, optionText: 'عندما يكون مميز المعادلة التربيعية الناتجة سالباً (Δ < 0)', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 22, optionText: 'عندما يكون المميز مساوياً لصفر', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 23, optionText: 'عندما يكون المميز موجباً تماماً', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 24, optionText: 'إذا كان ميل المستقيم يساوي صفراً', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 7. حالة المماس
|
||||
QuestionModel(
|
||||
id: 7,
|
||||
questionText: 'إذا كان لنظام مكوّن من مستقيم وقطع مكافئ حل حقيقي وحيد فقط، فإن المستقيم يعتبر:',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'المستقيم المماس لمنحنى تربيعي',
|
||||
explanationText: 'وجود حل حقيقي وحيد لنظام خطي-تربيعي يعني هندسياً أن المستقيم يمس المنحنى عند نقطة واحدة فقط.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 25, optionText: 'مماساً لمنحنى القطع المكافئ عند نقطة التماس', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 26, optionText: 'قاطعاً للمنحنى في نقطتين', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 27, optionText: 'خط تقارب رأسي للمنحنى', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 28, optionText: 'محور تماثل للقطع المكافئ', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 8. حل نظام تربيعي بالحذف
|
||||
QuestionModel(
|
||||
id: 8,
|
||||
questionText: 'في النظام: x² + y² = 25 و x² - y² = 7، ما هي قيمة x²؟',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'حل نظام تربيعي بطريقة الحذف',
|
||||
explanationText: 'بجمع المعادلتين طرفاً لطرف: 2x² = 32 ومنها x² = 16.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 29, optionText: 'x² = 16', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 30, optionText: 'x² = 9', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 31, optionText: 'x² = 32', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 32, optionText: 'x² = 18', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 9. أقصى عدد حلول بين دائرة وقطع مكافئ
|
||||
QuestionModel(
|
||||
id: 9,
|
||||
questionText: 'ما هو أقصى عدد ممكن من نقاط التقاطع بين دائرة وقطع مكافئ في المستوى الإحداثي؟',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'التقاطع الهندسي بين منحنيين تربيعيين',
|
||||
explanationText: 'يمكن لدائرة وقطع مكافئ أن يتقاطعا في 0، أو 1، أو 2، أو 3، أو 4 نقاط كحد أقصى.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 33, optionText: '4 نقاط تقاطع (أربعة حلول)', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 34, optionText: 'حلان فقط', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 35, optionText: '6 نقاط تقاطع', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 36, optionText: 'حل وحيد فقط دائماً', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 10. التعويض بين معادلتين تربيعيتين
|
||||
QuestionModel(
|
||||
id: 10,
|
||||
questionText: 'النظام: x² + y² = 13 و y = x² + 1 يتقاطع في النقطتين:',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'التعويض بين معادلتين تربيعيتين',
|
||||
explanationText: 'بتعويض x² = y - 1 في الأولى: y - 1 + y² = 13 أي y² + y - 14 = 0 أو نجد بالنظام y=3 و x=±2.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 37, optionText: '(-2, 3) و (2, 3)', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 38, optionText: '(3, -2) و (3, 2)', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 39, optionText: '(0, 1) فقط', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 40, optionText: '(2, 5) و (-2, 5)', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 11. التناظر في أنظمة المعادلات
|
||||
QuestionModel(
|
||||
id: 11,
|
||||
questionText: 'إذا كانت النقطة (a, b) حلاً لنظام يتكون من دائرة مركزها نقطة الأصل ومعادلة متماثلة حول المحور الصادي، فإن:',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'خصائص التناظر في أنظمة المعادلات',
|
||||
explanationText: 'التماثل حول محور الصادات يعني أن استبدال x بـ (-x) يعطي نفس النتيجة، فالنقطة (-a, b) تكون أيضاً حلاً للنظام.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 41, optionText: '(-a, b) تكون أيضاً حلاً للنظام', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 42, optionText: '(a, -b) هو الحل الوحيد دائماً', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 43, optionText: 'لا يوجد أي تناظر هندسي', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 44, optionText: 'الحل سالب دائماً', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 12. برمجية جيوجبرا وأداة التقاطع
|
||||
QuestionModel(
|
||||
id: 12,
|
||||
questionText: 'في برمجية جيوجبرا (GeoGebra)، ما هي الأداة المخصصة لإيجاد حل نظام المعادلات بيانياً؟',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'برمجية جيوجبرا وحل الأنظمة بيانياً',
|
||||
explanationText: 'أداة التقاطع (Intersect Tool) في جيوجبرا تُحدد إحداثيات نقاط تقاطع المنحنيات التي تمثل حلول النظام مباشرة.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 45, optionText: 'أداة التقاطع (Intersect Tool)', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 46, optionText: 'أداة القياس (Measure)', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 47, optionText: 'أداة الانعكاس (Reflect)', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 48, optionText: 'أداة المماس (Tangent)', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 13. قراءة الإحداثيات في جيوجبرا
|
||||
QuestionModel(
|
||||
id: 13,
|
||||
questionText: 'عند تمثيل معادلتين في جيوجبرا وظهور نقطة التقاطع A = (3, -2)، فهذا يعني هندسياً وجبرياً أن:',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'تفسير مخرجات برمجية جيوجبرا',
|
||||
explanationText: 'إحداثيات نقطة التقاطع (x, y) تعني أن الزوج المرتب يحقق كلتا المعادلتين معاً في آن واحد، وهو حل النظام.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 49, optionText: 'x = 3 و y = -2 هو حل يحقق كلتا المعادلتين معاً', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 50, optionText: 'x = -2 و y = 3 هو الحل', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 51, optionText: 'المنحنيان متباعدان ولا حل لهما', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 52, optionText: 'النظام له حلول غير منتهية', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 14. النماذج الحياتية والأرصاد
|
||||
QuestionModel(
|
||||
id: 14,
|
||||
questionText: 'لماذا يستخدم خبراء الأرصاد الجوية أنظمة معادلات غير خطية في التنبؤ بالطقس كما ورد في كتاب الطالب؟',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'التطبيقات الحياتية لأنظمة المعادلات',
|
||||
explanationText: 'لأن أي تغير في أحد العوامل (كالضغط ودرجة الحرارة وسرعة الرياح) يؤدي إلى تغير غير خطي في العوامل الأخرى.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 53, optionText: 'لأن أي تغير في أحد العوامل يؤدي إلى تغير غير خطي في العوامل الأخرى', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 54, optionText: 'لأن درجة الحرارة ثابتة دائماً على مدار السنة', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 55, optionText: 'للتخلص من قياس الضغط الجوي', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 56, optionText: 'لأن سرعة الرياح لا ترتبط بحركة الغلاف الجوي', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
// 15. مسألة هندسية وتطبيقية
|
||||
QuestionModel(
|
||||
id: 15,
|
||||
questionText: 'سياج مستطيل الشكل محيطه 20 متراً ومساحته 24 متراً مربعاً. ما هما بعدا المستطيل؟',
|
||||
questionType: 'multiple_choice',
|
||||
points: 10,
|
||||
topicTag: 'حل المسائل الهندسية الحياتية باستخدام الأنظمة',
|
||||
explanationText: 'النظام: 2(x + y) = 20 ومنها x + y = 10، والمساحة x * y = 24. العددان اللذان مجموعهما 10 وحاصل ضربهما 24 هما 6 و 4.',
|
||||
options: [
|
||||
QuestionOptionModel(id: 57, optionText: 'الطول 6 m والعرض 4 m', isCorrect: true, sequenceOrder: 1),
|
||||
QuestionOptionModel(id: 58, optionText: 'الطول 8 m والعرض 2 m', isCorrect: false, sequenceOrder: 2),
|
||||
QuestionOptionModel(id: 59, optionText: 'الطول 10 m والعرض 2.4 m', isCorrect: false, sequenceOrder: 3),
|
||||
QuestionOptionModel(id: 60, optionText: 'الطول 5 m والعرض 5 m', isCorrect: false, sequenceOrder: 4),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
+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