1036 lines
39 KiB
Dart
1036 lines
39 KiB
Dart
import 'dart:convert';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:http/http.dart' as http;
|
|
|
|
void main() {
|
|
runApp(const SaqelTeacherApp());
|
|
}
|
|
|
|
/// ==============================================================================
|
|
/// SAQEL ENTERPRISE (EDTECH 2.0) - TEACHER STUDIO & MONETIZATION APP
|
|
/// ==============================================================================
|
|
class SaqelTeacherApp extends StatelessWidget {
|
|
const SaqelTeacherApp({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MaterialApp(
|
|
title: 'صَقِل — استوديو المعلم المعتمد',
|
|
debugShowCheckedModeBanner: false,
|
|
theme: ThemeData(
|
|
brightness: Brightness.dark,
|
|
scaffoldBackgroundColor: const Color(0xFF070B12),
|
|
fontFamily: '-apple-system',
|
|
fontFamilyFallback: const [
|
|
'SF Pro Display',
|
|
'SF Pro Text',
|
|
'SF Arabic',
|
|
'Cairo',
|
|
'system-ui',
|
|
],
|
|
colorScheme: const ColorScheme.dark(
|
|
primary: Color(0xFF10B981),
|
|
surface: Color(0xFF0F172A),
|
|
background: Color(0xFF070B12),
|
|
),
|
|
),
|
|
home: const TeacherMainShell(),
|
|
);
|
|
}
|
|
}
|
|
|
|
class TeacherMainShell extends StatefulWidget {
|
|
const TeacherMainShell({super.key});
|
|
|
|
@override
|
|
State<TeacherMainShell> createState() => _TeacherMainShellState();
|
|
}
|
|
|
|
class _TeacherMainShellState extends State<TeacherMainShell> {
|
|
int _currentTabIndex = 0;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Directionality(
|
|
textDirection: TextDirection.rtl,
|
|
child: Scaffold(
|
|
backgroundColor: const Color(0xFF070B12),
|
|
appBar: AppBar(
|
|
backgroundColor: const Color(0xFF0E1626),
|
|
elevation: 0,
|
|
title: Row(
|
|
children: [
|
|
Container(
|
|
width: 36,
|
|
height: 36,
|
|
decoration: BoxDecoration(
|
|
gradient: const LinearGradient(
|
|
colors: [Color(0xFF10B981), Color(0xFF059669)],
|
|
),
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
child: const Center(
|
|
child: Text(
|
|
'م',
|
|
style: TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.w900,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(width: 10),
|
|
const Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Text(
|
|
'استوديو المعلم المعتمد',
|
|
style: TextStyle(
|
|
fontSize: 15,
|
|
fontWeight: FontWeight.w800,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
SizedBox(width: 6),
|
|
Icon(CupertinoIcons.checkmark_seal_fill,
|
|
color: Color(0xFF10B981), size: 16),
|
|
],
|
|
),
|
|
Text(
|
|
'أ. أحمد المجالي · فيزياء التوجيهي (الثقافة العسكرية)',
|
|
style: TextStyle(fontSize: 11, color: Color(0xFF94A3B8)),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
actions: [
|
|
Container(
|
|
margin: const EdgeInsets.symmetric(vertical: 12, horizontal: 12),
|
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFF10B981).withOpacity(0.15),
|
|
borderRadius: BorderRadius.circular(8),
|
|
border: Border.all(color: const Color(0xFF10B981).withOpacity(0.4)),
|
|
),
|
|
child: const Row(
|
|
children: [
|
|
Icon(CupertinoIcons.star_fill,
|
|
color: Color(0xFFFBBF24), size: 14),
|
|
SizedBox(width: 4),
|
|
Text(
|
|
'معتمد 94%',
|
|
style: TextStyle(
|
|
fontSize: 11.5,
|
|
fontWeight: FontWeight.w800,
|
|
color: Color(0xFF34D399),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
body: IndexedStack(
|
|
index: _currentTabIndex,
|
|
children: const [
|
|
TeacherStudioUploadView(),
|
|
TeacherMonetizationView(),
|
|
TeacherReputationScorecardView(),
|
|
],
|
|
),
|
|
bottomNavigationBar: Container(
|
|
decoration: const BoxDecoration(
|
|
color: Color(0xFF0E1626),
|
|
border: Border(top: BorderSide(color: Color(0xFF1E293B))),
|
|
),
|
|
child: BottomNavigationBar(
|
|
currentIndex: _currentTabIndex,
|
|
onTap: (idx) => setState(() => _currentTabIndex = idx),
|
|
backgroundColor: Colors.transparent,
|
|
selectedItemColor: const Color(0xFF10B981),
|
|
unselectedItemColor: const Color(0xFF64748B),
|
|
selectedLabelStyle:
|
|
const TextStyle(fontWeight: FontWeight.w800, fontSize: 12),
|
|
unselectedLabelStyle: const TextStyle(fontSize: 11),
|
|
type: BottomNavigationBarType.fixed,
|
|
elevation: 0,
|
|
items: const [
|
|
BottomNavigationBarItem(
|
|
icon: Icon(CupertinoIcons.videocam_circle_fill),
|
|
label: 'استوديو الحصص',
|
|
),
|
|
BottomNavigationBarItem(
|
|
icon: Icon(CupertinoIcons.money_dollar_circle_fill),
|
|
label: 'محفظة التسييل (55%)',
|
|
),
|
|
BottomNavigationBarItem(
|
|
icon: Icon(CupertinoIcons.chart_bar_circle_fill),
|
|
label: 'بطاقة الأداء والرادار',
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// ==============================================================================
|
|
/// TAB 1: STUDIO LESSON UPLOAD & QUALITY GATE (20-25 MIN COGNITIVE LIMIT)
|
|
/// ==============================================================================
|
|
class TeacherStudioUploadView extends StatefulWidget {
|
|
const TeacherStudioUploadView({super.key});
|
|
|
|
@override
|
|
State<TeacherStudioUploadView> createState() =>
|
|
_TeacherStudioUploadViewState();
|
|
}
|
|
|
|
class _TeacherStudioUploadViewState extends State<TeacherStudioUploadView> {
|
|
final TextEditingController _titleController = TextEditingController(
|
|
text: 'شرح قاعدة لنتز والحث الكهرومغناطيسي — فيزياء 2008');
|
|
double _durationMinutes = 22.5;
|
|
bool _isAuditing = false;
|
|
Map<String, dynamic>? _auditResult;
|
|
|
|
void _runQualityGate() async {
|
|
setState(() => _isAuditing = true);
|
|
|
|
try {
|
|
final response = await http.post(
|
|
Uri.parse('http://127.0.0.1:8000/api/teacher/audit-studio-video'),
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
},
|
|
body: json.encode({
|
|
'lesson_title': _titleController.text,
|
|
'duration_minutes': _durationMinutes,
|
|
'subject': 'الفيزياء',
|
|
}),
|
|
).timeout(const Duration(seconds: 4));
|
|
|
|
if (response.statusCode == 200) {
|
|
final decoded = json.decode(response.body);
|
|
if (decoded['status'] == 'success') {
|
|
setState(() {
|
|
_auditResult = decoded['data'];
|
|
_isAuditing = false;
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
} catch (_) {
|
|
// Fallback local simulation
|
|
}
|
|
|
|
await Future.delayed(const Duration(milliseconds: 600));
|
|
if (mounted) {
|
|
setState(() {
|
|
_isAuditing = false;
|
|
final isValid = _durationMinutes >= 15.0 && _durationMinutes <= 25.0;
|
|
_auditResult = {
|
|
'lesson_title': _titleController.text,
|
|
'subject': 'الفيزياء',
|
|
'duration_minutes': _durationMinutes,
|
|
'duration_gate_passed': isValid,
|
|
'duration_warning': _durationMinutes > 25.0
|
|
? 'تنبيه إدراكي: مدة الحصة تتجاوز 25 دقيقة. أثبتت أبحاث معهد ماساتشوستس أن التركيز الذهني يهبط بعد الدقيقة 18. يُوصى بتقسيم الحصة إلى جزأين.'
|
|
: null,
|
|
'quality_score': 92,
|
|
'approval_status': 'approved_for_broadcast',
|
|
'curriculum_alignment': '96% تطابق مع مخرجات المنهاج الوزاري',
|
|
'audio_clarity': '95% نقاء صوتي ممتاز',
|
|
'socratic_stops_count': 3,
|
|
'decision':
|
|
'الحصة معتمدة ومؤهلة للبث المشفر والعرض للبيع خارج الثقافة العسكرية 🚀',
|
|
};
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final isDurationGood =
|
|
_durationMinutes >= 15.0 && _durationMinutes <= 25.0;
|
|
|
|
return SingleChildScrollView(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
// Banner
|
|
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: const Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Icon(CupertinoIcons.sparkles,
|
|
color: Color(0xFF34D399), size: 20),
|
|
SizedBox(width: 8),
|
|
Text(
|
|
'بوابة جودة حصص الأستوديو الرقمية (صَقِل 2.0)',
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w800,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 6),
|
|
Text(
|
|
'تخضع كل حصة رقمية لمعايير التركيز الإدراكي (20-25 دقيقة كحد أقصى) وفحص الذكاء الاصطناعي بنسبة قبول لا تقل عن 85% قبل نشرها وتسييلها.',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Color(0xFF94A3B8),
|
|
height: 1.4,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// Upload Details Card
|
|
Container(
|
|
padding: const EdgeInsets.all(18),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFF0F172A),
|
|
borderRadius: BorderRadius.circular(16),
|
|
border: Border.all(color: const Color(0xFF1E293B)),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text(
|
|
'عنوان الحصة الصفية الرقمية:',
|
|
style: TextStyle(
|
|
fontSize: 13,
|
|
fontWeight: FontWeight.w700,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
TextField(
|
|
controller: _titleController,
|
|
style: const TextStyle(color: Colors.white, fontSize: 13.5),
|
|
decoration: InputDecoration(
|
|
filled: true,
|
|
fillColor: const Color(0xFF161F30),
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(10),
|
|
borderSide: const BorderSide(color: Color(0xFF334155)),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// Duration Slider
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
const Text(
|
|
'مدة الشرح الرقمي:',
|
|
style: TextStyle(
|
|
fontSize: 13,
|
|
fontWeight: FontWeight.w700,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 10, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
color: isDurationGood
|
|
? const Color(0xFF10B981).withOpacity(0.2)
|
|
: const Color(0xFFEF4444).withOpacity(0.2),
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
child: Text(
|
|
'${_durationMinutes.toStringAsFixed(1)} دقيقة',
|
|
style: TextStyle(
|
|
fontSize: 13,
|
|
fontWeight: FontWeight.w900,
|
|
color: isDurationGood
|
|
? const Color(0xFF34D399)
|
|
: const Color(0xFFEF4444),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
Slider(
|
|
value: _durationMinutes,
|
|
min: 5.0,
|
|
max: 45.0,
|
|
divisions: 40,
|
|
activeColor: isDurationGood
|
|
? const Color(0xFF10B981)
|
|
: const Color(0xFFEF4444),
|
|
inactiveColor: const Color(0xFF1E293B),
|
|
onChanged: (val) => setState(() {
|
|
_durationMinutes = val;
|
|
_auditResult = null;
|
|
}),
|
|
),
|
|
|
|
// Cognitive Indicator Message
|
|
Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: isDurationGood
|
|
? const Color(0xFF064E3B).withOpacity(0.2)
|
|
: const Color(0xFF7F1D1D).withOpacity(0.2),
|
|
borderRadius: BorderRadius.circular(10),
|
|
border: Border.all(
|
|
color: isDurationGood
|
|
? const Color(0xFF10B981).withOpacity(0.4)
|
|
: const Color(0xFFEF4444).withOpacity(0.4),
|
|
),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Icon(
|
|
isDurationGood
|
|
? CupertinoIcons.check_mark_circled_solid
|
|
: CupertinoIcons.exclamationmark_triangle_fill,
|
|
size: 18,
|
|
color: isDurationGood
|
|
? const Color(0xFF34D399)
|
|
: const Color(0xFFEF4444),
|
|
),
|
|
const SizedBox(width: 8),
|
|
Expanded(
|
|
child: Text(
|
|
isDurationGood
|
|
? 'مثالي: الشرح ضمن المدى الإدراكي القياسي (20 إلى 25 دقيقة) لمعادلة تركيز الحصة الصفية.'
|
|
: 'تحذير إدراكي: الشرح يتجاوز 25 دقيقة! ينخفض الاستيعاب بعد الدقيقة 18، يرجى اختصار المقطع أو تقسيمه.',
|
|
style: TextStyle(
|
|
fontSize: 11.5,
|
|
color: isDurationGood
|
|
? const Color(0xFF6EE7B7)
|
|
: const Color(0xFFFCA5A5),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 18),
|
|
|
|
// Run Audit Button
|
|
ElevatedButton.icon(
|
|
onPressed: _isAuditing ? null : _runQualityGate,
|
|
icon: _isAuditing
|
|
? const SizedBox(
|
|
width: 16,
|
|
height: 16,
|
|
child: CircularProgressIndicator(
|
|
strokeWidth: 2, color: Colors.black),
|
|
)
|
|
: const Icon(CupertinoIcons.checkmark_shield_fill, size: 18),
|
|
label: Text(
|
|
_isAuditing
|
|
? 'جاري التدقيق التربوي عبر محرك صَقِل...'
|
|
: 'فحص الحصة عبر بوابة الجودة الذكية (عتبة 85%) ⚡',
|
|
style: const TextStyle(
|
|
fontSize: 13.5, fontWeight: FontWeight.w800),
|
|
),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: const Color(0xFF10B981),
|
|
foregroundColor: Colors.black,
|
|
minimumSize: const Size(double.infinity, 44),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
// Quality Audit Result Card
|
|
if (_auditResult != null) _buildAuditResultCard(_auditResult!),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildAuditResultCard(Map<String, dynamic> res) {
|
|
final score = res['quality_score'] as int? ?? 0;
|
|
final isApproved = score >= 85;
|
|
|
|
return Container(
|
|
padding: const EdgeInsets.all(18),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFF0F172A),
|
|
borderRadius: BorderRadius.circular(16),
|
|
border: Border.all(
|
|
color: isApproved
|
|
? const Color(0xFF10B981)
|
|
: const Color(0xFFEF4444),
|
|
width: 1.5,
|
|
),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Icon(
|
|
isApproved
|
|
? CupertinoIcons.check_mark_seal_fill
|
|
: CupertinoIcons.xmark_seal_fill,
|
|
color: isApproved
|
|
? const Color(0xFF10B981)
|
|
: const Color(0xFFEF4444),
|
|
size: 22,
|
|
),
|
|
const SizedBox(width: 8),
|
|
Text(
|
|
isApproved ? 'حصة معتمدة للبث والتسييل 🏅' : 'تجميد الحصة للمراجعة ⚠️',
|
|
style: TextStyle(
|
|
fontSize: 15,
|
|
fontWeight: FontWeight.w900,
|
|
color: isApproved
|
|
? const Color(0xFF10B981)
|
|
: const Color(0xFFEF4444),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
color: isApproved
|
|
? const Color(0xFF10B981).withOpacity(0.2)
|
|
: const Color(0xFFEF4444).withOpacity(0.2),
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: Text(
|
|
'درجة التقييم: $score%',
|
|
style: TextStyle(
|
|
fontSize: 13,
|
|
fontWeight: FontWeight.w900,
|
|
color: isApproved
|
|
? const Color(0xFF34D399)
|
|
: const Color(0xFFEF4444),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 12),
|
|
|
|
Text(
|
|
res['decision'] ?? '',
|
|
style: const TextStyle(
|
|
fontSize: 13,
|
|
fontWeight: FontWeight.w700,
|
|
color: Colors.white,
|
|
height: 1.4,
|
|
),
|
|
),
|
|
const Divider(color: Color(0xFF1E293B), height: 20),
|
|
|
|
// Breakdown
|
|
_rowMetric('التطابق مع نتاجات المنهاج:', res['curriculum_alignment']),
|
|
const SizedBox(height: 6),
|
|
_rowMetric('نقاء الصوت ومخارج الحروف:', res['audio_clarity']),
|
|
const SizedBox(height: 6),
|
|
_rowMetric('الفواصل السقراطية التفاعلية:',
|
|
'${res['socratic_stops_count']} محطات تفكيرية إلزامية'),
|
|
const SizedBox(height: 14),
|
|
|
|
if (isApproved)
|
|
ElevatedButton.icon(
|
|
onPressed: () {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text(
|
|
'تم ترحيل الحصة لتقطيع البث المشفر ونشرها في سوق صَقِل! 🚀'),
|
|
backgroundColor: Color(0xFF10B981),
|
|
),
|
|
);
|
|
},
|
|
icon: const Icon(CupertinoIcons.cloud_upload_fill, size: 16),
|
|
label: const Text('نشر الحصة في سوق التسييل التجاري 💰'),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: const Color(0xFF059669),
|
|
foregroundColor: Colors.white,
|
|
minimumSize: const Size(double.infinity, 42),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(10)),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _rowMetric(String label, dynamic value) {
|
|
return Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(label,
|
|
style: const TextStyle(fontSize: 12, color: Color(0xFF94A3B8))),
|
|
Text('$value',
|
|
style: const TextStyle(
|
|
fontSize: 12.5,
|
|
fontWeight: FontWeight.w700,
|
|
color: Color(0xFFCBD5E1))),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
/// ==============================================================================
|
|
/// TAB 2: MONETIZATION & REVENUE SHARE DASHBOARD (55% / 15% / 30%)
|
|
/// ==============================================================================
|
|
class TeacherMonetizationView extends StatefulWidget {
|
|
const TeacherMonetizationView({super.key});
|
|
|
|
@override
|
|
State<TeacherMonetizationView> createState() =>
|
|
_TeacherMonetizationViewState();
|
|
}
|
|
|
|
class _TeacherMonetizationViewState extends State<TeacherMonetizationView> {
|
|
double _studentSubscribers = 380;
|
|
final double _pricePerCourse = 20.0;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final grossRevenue = _studentSubscribers * _pricePerCourse;
|
|
final teacherShare = grossRevenue * 0.55;
|
|
final directorateShare = grossRevenue * 0.15;
|
|
final platformShare = grossRevenue * 0.30;
|
|
|
|
return SingleChildScrollView(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
// Wallet Card
|
|
Container(
|
|
padding: const EdgeInsets.all(20),
|
|
decoration: BoxDecoration(
|
|
gradient: const LinearGradient(
|
|
colors: [Color(0xFF064E3B), Color(0xFF062E25)],
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
),
|
|
borderRadius: BorderRadius.circular(20),
|
|
border: Border.all(color: const Color(0xFF10B981).withOpacity(0.4)),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: const Color(0xFF10B981).withOpacity(0.15),
|
|
blurRadius: 20,
|
|
offset: const Offset(0, 8),
|
|
)
|
|
],
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
const Text(
|
|
'الرصيد المتاح للسحب (حصة المعلم 55%):',
|
|
style: TextStyle(
|
|
fontSize: 12.5,
|
|
fontWeight: FontWeight.w700,
|
|
color: Color(0xFF6EE7B7),
|
|
),
|
|
),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 8, vertical: 3),
|
|
decoration: BoxDecoration(
|
|
color: Colors.black.withOpacity(0.3),
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
child: const Text(
|
|
'IBAN معتمد',
|
|
style: TextStyle(
|
|
fontSize: 11,
|
|
color: Color(0xFF34D399),
|
|
fontWeight: FontWeight.w700),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
'${teacherShare.toStringAsFixed(0)} دينار أردني',
|
|
style: const TextStyle(
|
|
fontSize: 30,
|
|
fontWeight: FontWeight.w900,
|
|
color: Colors.white,
|
|
letterSpacing: 0.5,
|
|
),
|
|
),
|
|
const SizedBox(height: 12),
|
|
ElevatedButton.icon(
|
|
onPressed: () {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text(
|
|
'تم تقديم طلب التحويل لحسابك البنكي المعتمد بنجاح.'),
|
|
backgroundColor: Color(0xFF10B981),
|
|
),
|
|
);
|
|
},
|
|
icon: const Icon(CupertinoIcons.money_dollar, size: 18),
|
|
label: const Text('طلب تحويل الرصيد للحساب البنكي'),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: const Color(0xFF10B981),
|
|
foregroundColor: Colors.black,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(10)),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 18),
|
|
|
|
// Interactive Revenue Share Formula
|
|
Container(
|
|
padding: const EdgeInsets.all(18),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFF0F172A),
|
|
borderRadius: BorderRadius.circular(18),
|
|
border: Border.all(color: const Color(0xFF1E293B)),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text(
|
|
'نموذج تقاسم العوائد الثلاثي المعتمد (الفصل السابع):',
|
|
style: TextStyle(
|
|
fontSize: 13.5,
|
|
fontWeight: FontWeight.w800,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
const SizedBox(height: 14),
|
|
|
|
// Split Bars
|
|
_splitRow('حصة المعلم المباشرة (55%):',
|
|
'${teacherShare.toStringAsFixed(0)} د.أ', const Color(0xFF10B981)),
|
|
const SizedBox(height: 8),
|
|
_splitRow('حصة مديرية الثقافة العسكرية (15%):',
|
|
'${directorateShare.toStringAsFixed(0)} د.أ', const Color(0xFFF59E0B)),
|
|
const SizedBox(height: 8),
|
|
_splitRow('حصة منصة صَقِل للبنية والسيرفرات (30%):',
|
|
'${platformShare.toStringAsFixed(0)} د.أ', const Color(0xFF38BDF8)),
|
|
|
|
const Divider(color: Color(0xFF1E293B), height: 24),
|
|
|
|
// Subscribers Slider
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
const Text('محاكي المشتركين خارج الثقافة:',
|
|
style: TextStyle(fontSize: 12, color: Color(0xFF94A3B8))),
|
|
Text('${_studentSubscribers.toInt()} طالب مشترك',
|
|
style: const TextStyle(
|
|
fontSize: 13.5,
|
|
fontWeight: FontWeight.w800,
|
|
color: Color(0xFF34D399))),
|
|
],
|
|
),
|
|
Slider(
|
|
value: _studentSubscribers,
|
|
min: 50,
|
|
max: 2000,
|
|
divisions: 39,
|
|
activeColor: const Color(0xFF10B981),
|
|
inactiveColor: const Color(0xFF1E293B),
|
|
onChanged: (val) => setState(() => _studentSubscribers = val),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 18),
|
|
|
|
// Active Courses Selling
|
|
const Text(
|
|
'الدورات المنشورة في سوق صَقِل الخارجي:',
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w800,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
const SizedBox(height: 10),
|
|
|
|
_courseEarningCard(
|
|
title: 'الفيزياء للتوجيهي العلمي (الفصل الأول)',
|
|
students: 240,
|
|
revenue: '2,640 د.أ',
|
|
),
|
|
const SizedBox(height: 8),
|
|
_courseEarningCard(
|
|
title: 'المكثف الشامل لقوانين نيوتن وحفظ الطاقة',
|
|
students: 140,
|
|
revenue: '1,540 د.أ',
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _splitRow(String label, String amount, Color color) {
|
|
return Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Container(width: 8, height: 8, decoration: BoxDecoration(color: color, shape: BoxShape.circle)),
|
|
const SizedBox(width: 8),
|
|
Text(label, style: const TextStyle(fontSize: 12.5, color: Colors.white)),
|
|
],
|
|
),
|
|
Text(amount, style: TextStyle(fontSize: 13.5, fontWeight: FontWeight.w900, color: color)),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _courseEarningCard({
|
|
required String title,
|
|
required int students,
|
|
required String revenue,
|
|
}) {
|
|
return Container(
|
|
padding: const EdgeInsets.all(14),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFF0F172A),
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(color: const Color(0xFF1E293B)),
|
|
),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(title, style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w800, color: Colors.white)),
|
|
const SizedBox(height: 3),
|
|
Text('$students طالب مشترك · رسوم 20 د.أ', style: const TextStyle(fontSize: 11, color: Color(0xFF94A3B8))),
|
|
],
|
|
),
|
|
),
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
Text(revenue, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w900, color: Color(0xFF10B981))),
|
|
const Text('صافي أرباحك', style: TextStyle(fontSize: 10, color: Color(0xFF64748B))),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// ==============================================================================
|
|
/// TAB 3: TEACHER REPUTATION & CERTIFICATION SCORECARD
|
|
/// ==============================================================================
|
|
class TeacherReputationScorecardView extends StatelessWidget {
|
|
const TeacherReputationScorecardView({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return SingleChildScrollView(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
// Top Merit Card
|
|
Container(
|
|
padding: const EdgeInsets.all(20),
|
|
decoration: BoxDecoration(
|
|
gradient: const LinearGradient(
|
|
colors: [Color(0xFF1E1B4B), Color(0xFF0F172A)],
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
),
|
|
borderRadius: BorderRadius.circular(20),
|
|
border: Border.all(color: const Color(0xFF8B5CF6).withOpacity(0.5)),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
const CircleAvatar(
|
|
radius: 32,
|
|
backgroundColor: Color(0xFF8B5CF6),
|
|
child: Icon(CupertinoIcons.rosette, size: 36, color: Colors.white),
|
|
),
|
|
const SizedBox(height: 12),
|
|
const Text(
|
|
'أ. أحمد المجالي',
|
|
style: TextStyle(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.w900,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
const SizedBox(height: 4),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFF10B981).withOpacity(0.2),
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
child: const Text(
|
|
'🏅 معلم معتمد رسمياً من منصة صَقِل (فوق 90%)',
|
|
style: TextStyle(
|
|
fontSize: 11.5,
|
|
fontWeight: FontWeight.w800,
|
|
color: Color(0xFF34D399),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
const Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
children: [
|
|
_ScoreStat(label: 'التقييم العام', value: '4.92 / 5.0'),
|
|
_ScoreStat(label: 'الطلاب المخدومون', value: '1,240 طالب'),
|
|
_ScoreStat(label: 'نسبة النجاح', value: '98.2%'),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 18),
|
|
|
|
// Pedagogical Metrics Breakdown
|
|
Container(
|
|
padding: const EdgeInsets.all(18),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFF0F172A),
|
|
borderRadius: BorderRadius.circular(18),
|
|
border: Border.all(color: const Color(0xFF1E293B)),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text(
|
|
'رادار الجودة التربوية المعتمد:',
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w800,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
const SizedBox(height: 14),
|
|
|
|
_metricProgress('الالتزام بالمنهاج والنتاجات الوزارية', 0.96, const Color(0xFF10B981)),
|
|
const SizedBox(height: 12),
|
|
_metricProgress('التفاعل السقراطي وإثارة التفكير', 0.89, const Color(0xFF38BDF8)),
|
|
const SizedBox(height: 12),
|
|
_metricProgress('الوضوح الصوتي وسلامة اللغة', 0.94, const Color(0xFFF59E0B)),
|
|
const SizedBox(height: 12),
|
|
_metricProgress('إدارة الوقت والتركيز الإدراكي (20-25 دقيقة)', 0.92, const Color(0xFF8B5CF6)),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 18),
|
|
|
|
// AI Growth Insights Box
|
|
Container(
|
|
padding: const EdgeInsets.all(14),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFF1E293B),
|
|
borderRadius: BorderRadius.circular(14),
|
|
border: Border.all(color: const Color(0xFF334155)),
|
|
),
|
|
child: const Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Icon(CupertinoIcons.lightbulb_fill, color: Color(0xFFFBBF24), size: 20),
|
|
SizedBox(width: 10),
|
|
Expanded(
|
|
child: Text(
|
|
'توجيه الذكاء الاصطناعي الأسبوعي: نسبة الالتزام الوزاري ممتازة (96%). يُوصى بإضافة وقفة سقراطية استنتاجية في الدقيقة 14 من الدرس القادم لتعزيز تفاعل الطلبة.',
|
|
style: TextStyle(fontSize: 12, color: Color(0xFFCBD5E1), height: 1.4),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _metricProgress(String title, double value, Color color) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(title, style: const TextStyle(fontSize: 12, color: Colors.white)),
|
|
Text('${(value * 100).toInt()}%',
|
|
style: TextStyle(fontSize: 12.5, fontWeight: FontWeight.w800, color: color)),
|
|
],
|
|
),
|
|
const SizedBox(height: 6),
|
|
ClipRRect(
|
|
borderRadius: BorderRadius.circular(4),
|
|
child: LinearProgressIndicator(
|
|
value: value,
|
|
minHeight: 6,
|
|
backgroundColor: const Color(0xFF1E293B),
|
|
valueColor: AlwaysStoppedAnimation<Color>(color),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ScoreStat extends StatelessWidget {
|
|
final String label;
|
|
final String value;
|
|
|
|
const _ScoreStat({required this.label, required this.value});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Column(
|
|
children: [
|
|
Text(value, style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w900, color: Colors.white)),
|
|
const SizedBox(height: 2),
|
|
Text(label, style: const TextStyle(fontSize: 11, color: Color(0xFF94A3B8))),
|
|
],
|
|
);
|
|
}
|
|
}
|