Update Saqel Platform: 2026-09-05 22:17:15

This commit is contained in:
Hamza-Ayed
2026-09-05 22:17:15 +03:00
parent 68265a5bc6
commit 0e5be7adbb
6 changed files with 3322 additions and 885 deletions
@@ -0,0 +1,934 @@
import 'dart:math' as math;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../../../core/theme/app_colors.dart';
import '../../widgets/luxury_widgets.dart';
/// ==============================================================================
/// SAQEL ENTERPRISE (EDTECH 2.0) - VOCATIONAL TRAINING CORPORATION (VTC) HUB
/// ==============================================================================
///
/// بوابة منظومة مؤسسة التدريب المهني (VTC) والتعليم التقني والتدريب المهني:
/// 1. دليل الـ 140 مهنة وحرفة موزعة على 8 قطاعات إنتاجية وصناعية وطنية.
/// 2. تخصص صيانة وتشخيص المركبات الكهربائية والهجينة (EV & Hybrid Specialist).
/// 3. محاكي فحص بطاريات الجهد العالي ونظام العزل (HVIL & BMS 120 FPS Lab).
/// 4. نظام الكفايات المهنية (CBT) ومعايير السلامة المهنية للمركبات الكهربائية (NFPA 70E).
class VocationalTrainingScreen extends StatefulWidget {
const VocationalTrainingScreen({super.key});
@override
State<VocationalTrainingScreen> createState() => _VocationalTrainingScreenState();
}
class _VocationalTrainingScreenState extends State<VocationalTrainingScreen>
with SingleTickerProviderStateMixin {
int _selectedSectorIndex = 0;
int _activeTabIndex = 0; // 0 = 140 Trades Directory, 1 = EV Diagnostic Lab, 2 = CBT Modules
// EV Lab Parameters
double _batterySoc = 82.0; // State of Charge %
double _packVoltage = 384.0; // Volts DC
double _isolationResistance = 5.2; // Mega-Ohms (Threshold > 0.5 MΩ)
bool _hvilInterlockClosed = true; // High Voltage Interlock Loop
bool _contactorPrechargeActive = true;
String _activeDtcCode = 'P0000: No Faults Detected (Normal Operation)';
bool _simulationRunning = true;
late final AnimationController _pulseController;
final List<Map<String, dynamic>> _sectors = [
{
'title': 'المركبات والطاقة المتجددة',
'icon': CupertinoIcons.bolt_car,
'color': Color(0xFF10B981),
'tradesCount': 18,
'featured': 'ميكانيك وتشخيص المركبات الكهربائية والهجينة (EV)',
'description': 'فحص أنظمة الجهد العالي، بطاريات الليثيوم، ومحولات التيار (Inverters).',
'trades': [
'تشخيص وصيانة المركبات الكهربائية والهجينة',
'كهرباء وإلكترونيات السيارات الحديثة',
'ميكانيك محركات الديزل والبنزين المتقدم',
'تركيب وصيانة أنظمة الطاقة الشمسية الكهروضوئية',
'صيانة طواحين الرياح وأنظمة التوليد الهجينة',
'فحص بطاريات الجهد العالي وإعادة تدوير الخلايا',
],
},
{
'title': 'التكنولوجيا والتحول الرقمي',
'icon': CupertinoIcons.device_laptop,
'color': Color(0xFF00F5D4),
'tradesCount': 22,
'featured': 'أمن الشبكات والدعم الفني السحابي',
'description': 'هندسة الشبكات المحلية، الألياف الضوئية، وصيانة الخوادم والأنظمة الذكية.',
'trades': [
'فني صيانة شبكات الحاسوب والألياف الضوئية',
'الدعم الفني لأنظمة الحوسبة السحابية',
'فني صيانة الهواتف الذكية والأجهزة اللوحية',
'تشغيل وبرمجة أنظمة التحكم الرقمي (CNC)',
'فني تركيب كاميرات المراقبة وأنظمة الأمان الذكية',
],
},
{
'title': 'الصناعات الهندسية والميكانيكية',
'icon': CupertinoIcons.wrench_fill,
'color': Color(0xFFF59E0B),
'tradesCount': 28,
'featured': 'اللحام وتشكيل المعادن المتقدم (TIG/MIG)',
'description': 'الخراطة، تشكيل المعادن، واللحام بالأرغون وخطوط الإنتاج المؤتمتة.',
'trades': [
'لحام الأنابيب الصناعية وضغط الغاز (TIG/MIG)',
'الخراطة والتفريز وتشكيل المعادن المبرمج',
'صيانة خطوط الإنتاج والآلات الصناعية',
'التمديدات الكهروميكانيكية للمصانع',
'تشكيل وهيكلة الألمنيوم والواجهات المعمارية',
],
},
{
'title': 'الضيافة والسياحة والفندقة',
'icon': CupertinoIcons.building_2_fill,
'color': Color(0xFFEC4899),
'tradesCount': 16,
'featured': 'فنون الطهي وإنتاج الأغذية الفندقية',
'description': 'إدارة المكاتب الأمامية، فنون الطهي الدولي، وخدمة الغرف والضيافة.',
'trades': [
'إنتاج الأغذية والطهي الشرقي والغربي',
'فنون الحلويات والمخبوزات الفرنسية',
'إدارة المطاعم وخدمة الضيوف الراقية',
'الإشراف الداخلي وإدارة الغرف الفندقية',
],
},
{
'title': 'الزراعة الحديثة والري الذكي',
'icon': CupertinoIcons.leaf_arrow_circlepath,
'color': Color(0xFF22C55E),
'tradesCount': 14,
'featured': 'الزراعة المائية والبيوت البلاستيكية الذكية',
'description': 'أنظمة الزراعة بدون تربة (Hydroponics)، الري المحوسب، وتنسيق الحدائق.',
'trades': [
'تقنيات الزراعة المائية والعمودية المغلقة',
'إدارة وصيانة شبكات الري بالتنقيط المؤتمتة',
'إنتاج النباتات الطبية والعطرية العضوية',
'تنسيق وتصميم الحدائق والمتنزهات الخضراء',
],
},
{
'title': 'الصناعات الدوائية والكيميائية',
'icon': CupertinoIcons.lab_flask_solid,
'color': Color(0xFF8B5CF6),
'tradesCount': 12,
'featured': 'تشغيل خطوط التعبئة والتغليف الدوائي',
'description': 'تطبيق معايير ممارسات التصنيع الجيد (GMP) ومراقبة جودة الإنتاج الكيميائي.',
'trades': [
'فني تشغيل آلات التصنيع الدوائي المعقم',
'مساعد مراقبة الجودة والتحاليل الكيميائية',
'صيانة المضخات والمفاعلات الكيميائية',
],
},
{
'title': 'الحلاقة والتجميل والعناية',
'icon': CupertinoIcons.scissors,
'color': Color(0xFFF43F5E),
'tradesCount': 15,
'featured': 'تصفيف الشعر والتجميل الاحترافي',
'description': 'تقنيات العناية بالبشرة، التصميم المسرحي، وإدارة الصالونات الحديثة.',
'trades': [
'الحلاقة وتصفيف الشعر الرجالي المتقدم',
'التجميل وتصفيف الشعر النسائي',
'العناية بالبشرة والمساج العلاجي',
],
},
{
'title': 'الحرف التقليدية والمشغولات اليدوية',
'icon': CupertinoIcons.cube_box_fill,
'color': Color(0xFFD97706),
'tradesCount': 15,
'featured': 'صياغة الذهب والمجوهرات والفسيفساء',
'description': 'إحياء التراث الحرفي الأردني، فن الفسيفساء المادبي، وحفر الخشب التراثي.',
'trades': [
'صياغة الحلي والمجوهرات وتركيب الأحجار الكريمة',
'فن الفسيفساء والترميم الأثري الحرفي',
'النجارة التراثية والحفر على الخشب والزخرفة',
'الخزف والفخار الفني والتشكيل اليدوي',
],
},
];
@override
void initState() {
super.initState();
_pulseController = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
)..repeat(reverse: true);
}
@override
void dispose() {
_pulseController.dispose();
super.dispose();
}
void _triggerFault(String faultCode, String description, double rIso, bool hvilState) {
setState(() {
_activeDtcCode = '$faultCode: $description';
_isolationResistance = rIso;
_hvilInterlockClosed = hvilState;
if (!hvilState || rIso < 0.5) {
_contactorPrechargeActive = false;
}
});
}
void _clearFaults() {
setState(() {
_activeDtcCode = 'P0000: No Faults Detected (Normal Operation)';
_isolationResistance = 5.2;
_hvilInterlockClosed = true;
_contactorPrechargeActive = true;
});
}
@override
Widget build(BuildContext context) {
final activeSector = _sectors[_selectedSectorIndex];
return Scaffold(
backgroundColor: AppColors.darkBackground,
appBar: AppBar(
backgroundColor: const Color(0xFF091620),
elevation: 0,
title: Row(
children: [
Container(
padding: const EdgeInsets.all(6),
decoration: BoxDecoration(
color: const Color(0xFF10B981).withAlpha(30),
borderRadius: BorderRadius.circular(10),
border: Border.all(color: const Color(0xFF10B981).withAlpha(100)),
),
child: const Icon(CupertinoIcons.wrench_fill, color: Color(0xFF10B981), size: 18),
),
const SizedBox(width: 10),
const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'مؤسسة التدريب المهني (VTC Hub)',
style: TextStyle(color: Colors.white, fontSize: 15, fontWeight: FontWeight.w800),
),
Text(
'140 مهنة وحرفة معتمدة • الشراكة الاستراتيجية للتحول المهني',
style: TextStyle(color: AppColors.textSecondaryDark, fontSize: 11),
),
],
),
],
),
),
body: Directionality(
textDirection: TextDirection.rtl,
child: Column(
children: [
// Top Executive Stats Strip
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: const BoxDecoration(
color: Color(0xFF0A1E1D),
border: Border(bottom: BorderSide(color: Color(0xFF10B981), width: 0.8)),
),
child: Row(
children: [
_buildExecutiveStat('140 مهنة', 'دليل المهن الوزاري', CupertinoIcons.square_grid_2x2_fill),
_buildVerticalDivider(),
_buildExecutiveStat('8 قطاعات', 'سلاسل القيمة الصناعية', CupertinoIcons.layers_fill),
_buildVerticalDivider(),
_buildExecutiveStat('EV 384V', 'مختبر فحص الهايبرد والكهرباء', CupertinoIcons.bolt_car_fill),
_buildVerticalDivider(),
_buildExecutiveStat('CBT Level 3', 'الكفايات والسلامة الدولية', CupertinoIcons.checkmark_seal_fill),
],
),
),
// Navigation Tabs (Directory / EV Lab / CBT)
Container(
color: AppColors.darkSurface,
child: Row(
children: [
_buildTopTabItem(0, 'دليل الـ 140 مهنة (8 قطاعات) 📋', CupertinoIcons.list_bullet),
_buildTopTabItem(1, 'مختبر فحص المركبات الكهربائية ⚡', CupertinoIcons.bolt_fill),
_buildTopTabItem(2, 'شهادات الكفايات المهنية (CBT) 🎓', CupertinoIcons.rosette),
],
),
),
// Tab View Body
Expanded(
child: IndexedStack(
index: _activeTabIndex,
children: [
_buildTradesDirectoryTab(activeSector),
_buildEvDiagnosticLabTab(),
_buildCbtCompetenciesTab(),
],
),
),
],
),
),
);
}
Widget _buildTopTabItem(int index, String label, IconData icon) {
final isSelected = _activeTabIndex == index;
return Expanded(
child: GestureDetector(
onTap: () => setState(() => _activeTabIndex = index),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 12),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: isSelected ? const Color(0xFF10B981) : Colors.transparent,
width: 3,
),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, size: 16, color: isSelected ? const Color(0xFF10B981) : AppColors.textSecondaryDark),
const SizedBox(height: 4),
Text(
label,
style: TextStyle(
color: isSelected ? Colors.white : AppColors.textSecondaryDark,
fontSize: 11.5,
fontWeight: isSelected ? FontWeight.w800 : FontWeight.w500,
),
textAlign: TextAlign.center,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
),
),
);
}
Widget _buildExecutiveStat(String title, String subtitle, IconData icon) {
return Expanded(
child: Row(
children: [
Icon(icon, color: const Color(0xFF10B981), size: 18),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(title, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 12.5)),
Text(subtitle, style: const TextStyle(color: AppColors.textSecondaryDark, fontSize: 9.5), maxLines: 1, overflow: TextOverflow.ellipsis),
],
),
),
],
),
);
}
Widget _buildVerticalDivider() {
return Container(
width: 1,
height: 24,
margin: const EdgeInsets.symmetric(horizontal: 8),
color: Colors.white12,
);
}
// ===========================================================================
// TAB 1: 140 VOCATIONAL TRADES DIRECTORY & 8 SECTORS
// ===========================================================================
Widget _buildTradesDirectoryTab(Map<String, dynamic> activeSector) {
return ListView(
padding: const EdgeInsets.all(16),
children: [
// Sector Pill Chips Row
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: _sectors.asMap().entries.map((entry) {
final idx = entry.key;
final sec = entry.value;
final isSelected = _selectedSectorIndex == idx;
final secColor = sec['color'] as Color;
return GestureDetector(
onTap: () => setState(() => _selectedSectorIndex = idx),
child: Container(
margin: const EdgeInsets.only(left: 8),
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
decoration: BoxDecoration(
color: isSelected ? secColor.withAlpha(40) : AppColors.darkSurface,
borderRadius: BorderRadius.circular(14),
border: Border.all(
color: isSelected ? secColor : AppColors.darkCardBorder,
width: 1.5,
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(sec['icon'] as IconData, size: 15, color: isSelected ? secColor : Colors.white70),
const SizedBox(width: 6),
Text(
sec['title'] as String,
style: TextStyle(
color: isSelected ? Colors.white : Colors.white70,
fontWeight: isSelected ? FontWeight.w800 : FontWeight.w500,
fontSize: 12,
),
),
const SizedBox(width: 6),
Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(
color: secColor.withAlpha(60),
borderRadius: BorderRadius.circular(8),
),
child: Text(
'${sec['tradesCount']}',
style: TextStyle(color: secColor, fontSize: 10, fontWeight: FontWeight.w900),
),
),
],
),
),
);
}).toList(),
),
),
const SizedBox(height: 16),
// Featured Specialization Spotlight Card
Container(
padding: const EdgeInsets.all(18),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
(activeSector['color'] as Color).withAlpha(40),
const Color(0xFF0F1A28),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(20),
border: Border.all(color: (activeSector['color'] as Color).withAlpha(120), width: 1.5),
boxShadow: const [
BoxShadow(color: Colors.black45, blurRadius: 16, offset: Offset(0, 6)),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: (activeSector['color'] as Color).withAlpha(40),
borderRadius: BorderRadius.circular(12),
),
child: Icon(activeSector['icon'] as IconData, color: activeSector['color'] as Color, size: 22),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
activeSector['title'] as String,
style: const TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w800),
),
const SizedBox(height: 2),
Text(
'التخصص الاستراتيجي: ${activeSector['featured']}',
style: TextStyle(color: activeSector['color'] as Color, fontSize: 12, fontWeight: FontWeight.w700),
),
],
),
),
],
),
const SizedBox(height: 12),
Text(
activeSector['description'] as String,
style: const TextStyle(color: Colors.white70, fontSize: 12.5, height: 1.5),
),
],
),
),
const SizedBox(height: 16),
// Trades List
const Text(
'المهن والحرف المعتمدة في هذا القطاع:',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 13.5),
),
const SizedBox(height: 10),
...((activeSector['trades'] as List<String>).asMap().entries.map((tEntry) {
final idx = tEntry.key + 1;
final tradeTitle = tEntry.value;
return Container(
margin: const EdgeInsets.only(bottom: 8),
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
decoration: BoxDecoration(
color: AppColors.darkSurface,
borderRadius: BorderRadius.circular(14),
border: Border.all(color: AppColors.darkCardBorder),
),
child: Row(
children: [
Container(
width: 28,
height: 28,
decoration: BoxDecoration(
color: Colors.white.withAlpha(10),
shape: BoxShape.circle,
),
alignment: Alignment.center,
child: Text(
'$idx',
style: const TextStyle(color: AppColors.saqelCyan, fontSize: 12, fontWeight: FontWeight.bold),
),
),
const SizedBox(width: 12),
Expanded(
child: Text(
tradeTitle,
style: const TextStyle(color: Colors.white, fontSize: 13, fontWeight: FontWeight.w600),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
decoration: BoxDecoration(
color: const Color(0xFF10B981).withAlpha(20),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: const Color(0xFF10B981).withAlpha(80)),
),
child: const Text('دبلوم مهني VTC', style: TextStyle(color: Color(0xFF10B981), fontSize: 10, fontWeight: FontWeight.bold)),
),
],
),
);
}).toList()),
],
);
}
// ===========================================================================
// TAB 2: INTERACTIVE EV & HYBRID DIAGNOSTIC VIRTUAL LAB (120 FPS)
// ===========================================================================
Widget _buildEvDiagnosticLabTab() {
return ListView(
padding: const EdgeInsets.all(16),
children: [
// Live Diagnostics Canvas (Battery Pack & Inverter)
Container(
height: 280,
decoration: BoxDecoration(
color: const Color(0xFF070E14),
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: _activeDtcCode.startsWith('P0000') ? const Color(0xFF10B981).withAlpha(80) : const Color(0xFFFF2D55),
width: 1.5,
),
boxShadow: const [
BoxShadow(color: Colors.black54, blurRadius: 16, offset: Offset(0, 6)),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(19),
child: CustomPaint(
painter: _EvDiagnosticsPainter(
batterySoc: _batterySoc,
packVoltage: _packVoltage,
isolationResistance: _isolationResistance,
hvilClosed: _hvilInterlockClosed,
isFaulted: !_activeDtcCode.startsWith('P0000'),
),
),
),
),
const SizedBox(height: 14),
// Live Diagnostic Telemetry Grid
Row(
children: [
_buildTelemetryCard(
'حالة الشحن (SoC)',
'${_batterySoc.toInt()}%',
const Color(0xFF10B981),
CupertinoIcons.battery_75_percent,
),
const SizedBox(width: 8),
_buildTelemetryCard(
'جهد البطارية (Pack V)',
'${_packVoltage.toInt()} V',
AppColors.saqelCyan,
CupertinoIcons.bolt_fill,
),
const SizedBox(width: 8),
_buildTelemetryCard(
'مقاومة العزل (R_iso)',
'${_isolationResistance.toStringAsFixed(1)} MΩ',
_isolationResistance >= 0.5 ? const Color(0xFF10B981) : const Color(0xFFFF2D55),
CupertinoIcons.shield_lefthalf_fill,
),
const SizedBox(width: 8),
_buildTelemetryCard(
'حلقة القفل (HVIL)',
_hvilInterlockClosed ? 'مغلقة (آمن)' : 'مفتوحة (خطر)',
_hvilInterlockClosed ? const Color(0xFF10B981) : const Color(0xFFFF2D55),
CupertinoIcons.lock_shield_fill,
),
],
),
const SizedBox(height: 14),
// Active DTC Code Box
Container(
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: _activeDtcCode.startsWith('P0000') ? const Color(0xFF0F261E) : const Color(0xFF330E14),
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: _activeDtcCode.startsWith('P0000') ? const Color(0xFF10B981) : const Color(0xFFFF2D55),
),
),
child: Row(
children: [
Icon(
_activeDtcCode.startsWith('P0000') ? CupertinoIcons.check_mark_circled_solid : CupertinoIcons.exclamationmark_triangle_fill,
color: _activeDtcCode.startsWith('P0000') ? const Color(0xFF10B981) : const Color(0xFFFF2D55),
size: 22,
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('كود التشخيص والأعطال (OBD-II DTC Readout):', style: TextStyle(color: Colors.white70, fontSize: 11)),
const SizedBox(height: 2),
Text(
_activeDtcCode,
style: TextStyle(
color: _activeDtcCode.startsWith('P0000') ? const Color(0xFF10B981) : const Color(0xFFFF2D55),
fontWeight: FontWeight.w800,
fontSize: 13,
),
),
],
),
),
],
),
),
const SizedBox(height: 14),
// Simulated Fault Injection Controls
LuxuryCard(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('حقن الأعطال المخبرية (Fault Injection Simulation):', style: TextStyle(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 13)),
const SizedBox(height: 4),
const Text('اختر عطلاً كهربائياً لاختبار استجابة نظام إدارة البطارية (BMS) وفصل قواطع الجهد العالي:', style: TextStyle(color: AppColors.textSecondaryDark, fontSize: 11)),
const SizedBox(height: 12),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
OutlinedButton.icon(
icon: const Icon(CupertinoIcons.shield_slash, color: Color(0xFFFF2D55), size: 16),
label: const Text('عطل تسريب العزل (P0AA6 - Loss of Isolation)', style: TextStyle(color: Colors.white, fontSize: 11.5)),
style: OutlinedButton.styleFrom(side: const BorderSide(color: Color(0xFFFF2D55))),
onPressed: () => _triggerFault('P0AA6', 'Hybrid Battery Voltage Isolation Fault (Leakage < 0.5 MΩ)', 0.1, true),
),
OutlinedButton.icon(
icon: const Icon(CupertinoIcons.lock_slash_fill, color: Color(0xFFF59E0B), size: 16),
label: const Text('قطع حلقة الأمان (P0A0D - HVIL Open Circuit)', style: TextStyle(color: Colors.white, fontSize: 11.5)),
style: OutlinedButton.styleFrom(side: const BorderSide(color: Color(0xFFF59E0B))),
onPressed: () => _triggerFault('P0A0D', 'High Voltage System Interlock Circuit Open (HVIL Broken)', 5.2, false),
),
ElevatedButton.icon(
icon: const Icon(CupertinoIcons.arrow_counterclockwise, size: 16),
label: const Text('إعادة ضبط وتشغيل النظام السليم (Clear DTC)', style: TextStyle(fontSize: 11.5, fontWeight: FontWeight.bold)),
style: ElevatedButton.styleFrom(backgroundColor: const Color(0xFF10B981), foregroundColor: Colors.black),
onPressed: _clearFaults,
),
],
),
],
),
),
],
);
}
Widget _buildTelemetryCard(String label, String value, Color color, IconData icon) {
return Expanded(
child: Container(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 8),
decoration: BoxDecoration(
color: AppColors.darkSurface,
borderRadius: BorderRadius.circular(14),
border: Border.all(color: AppColors.darkCardBorder),
),
child: Column(
children: [
Icon(icon, color: color, size: 18),
const SizedBox(height: 4),
Text(value, style: TextStyle(color: color, fontWeight: FontWeight.w800, fontSize: 13.5)),
const SizedBox(height: 2),
Text(label, style: const TextStyle(color: AppColors.textSecondaryDark, fontSize: 9.5), textAlign: TextAlign.center, maxLines: 1, overflow: TextOverflow.ellipsis),
],
),
),
);
}
// ===========================================================================
// TAB 3: CBT COMPETENCIES & CERTIFICATION STANDARDS
// ===========================================================================
Widget _buildCbtCompetenciesTab() {
return ListView(
padding: const EdgeInsets.all(16),
children: [
// Level 3 Certification Banner
Container(
padding: const EdgeInsets.all(18),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF132A1C), Color(0xFF0F1A28)],
),
borderRadius: BorderRadius.circular(20),
border: Border.all(color: const Color(0xFF10B981), width: 1.5),
),
child: const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(CupertinoIcons.rosette, color: Color(0xFF10B981), size: 24),
SizedBox(width: 10),
Text(
'نظام التدريب المبني على الكفايات (CBT Level 3)',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 15),
),
],
),
SizedBox(height: 8),
Text(
'برنامج معتمد دولياً لتأهيل فنيي المركبات الكهربائية والهجينة وفق معايير السلامة المهنية العالمية (NFPA 70E و ISO 26262 و ECE-R100). يشترط إتقان 5 كفايات إلزامية لنيل رخصة الفحص الميداني.',
style: TextStyle(color: Colors.white70, fontSize: 12.5, height: 1.5),
),
],
),
),
const SizedBox(height: 16),
_buildCbtModuleCard(
'الكفاية 1: إجراءات السلامة وفصل الجهد العالي (HV De-energization)',
'التحقق من خلو الجهد الكهربائي (Zero Voltage Verification) واستخدام قفازات الفئة Class 0 (1000V).',
'95% إتقان مطلوب',
CupertinoIcons.shield_fill,
const Color(0xFF10B981),
),
_buildCbtModuleCard(
'الكفاية 2: تشخيص خلايا بطارية الجهد العالي (BMS Cell Balancing)',
'قراءة قيم الجهد لكل خلية (3.2V - 4.2V) وفحص مقاومة العزل وتوازن درجات الحرارة.',
'معتمد دولياً',
CupertinoIcons.battery_full,
AppColors.saqelCyan,
),
_buildCbtModuleCard(
'الكفاية 3: فحص محول التيار والمحرك الكهربائي (Inverter & Motor)',
'فحص إشارات التردد العالي (PWM Gate Signals) وقياس مقاومة أطوار المحرك الثلاثية (U-V-W).',
'مستوى متقدم',
CupertinoIcons.bolt_horizontal_fill,
const Color(0xFFF59E0B),
),
_buildCbtModuleCard(
'الكفاية 4: بروتوكول حلقة الأمان وقفل الفحص (HVIL Loop Diagnostics)',
'كشف انقطاع أسلاك التوصيل السريع وإشارات تأكيد إغلاق غطاء مقبس الخدمة (Service Plug).',
'إلزامي للفحص',
CupertinoIcons.lock_shield,
const Color(0xFF8B5CF6),
),
],
);
}
Widget _buildCbtModuleCard(String title, String desc, String badge, IconData icon, Color color) {
return Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColors.darkSurface,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColors.darkCardBorder),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: color.withAlpha(30),
borderRadius: BorderRadius.circular(12),
),
child: Icon(icon, color: color, size: 20),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
title,
style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w700, fontSize: 13),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
decoration: BoxDecoration(
color: color.withAlpha(20),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: color.withAlpha(80)),
),
child: Text(badge, style: TextStyle(color: color, fontSize: 10.5, fontWeight: FontWeight.bold)),
),
],
),
const SizedBox(height: 6),
Text(desc, style: const TextStyle(color: AppColors.textSecondaryDark, fontSize: 12, height: 1.4)),
],
),
),
],
),
);
}
}
// =============================================================================
// EV DIAGNOSTICS CUSTOM PAINTER (120 FPS HIGH-VOLTAGE ARCHITECTURE)
// =============================================================================
class _EvDiagnosticsPainter extends CustomPainter {
final double batterySoc;
final double packVoltage;
final double isolationResistance;
final bool hvilClosed;
final bool isFaulted;
_EvDiagnosticsPainter({
required this.batterySoc,
required this.packVoltage,
required this.isolationResistance,
required this.hvilClosed,
required this.isFaulted,
});
@override
void paint(Canvas canvas, Size size) {
final w = size.width;
final h = size.height;
final cy = h / 2;
// Watermark
const watermarkSpan = TextSpan(
text: 'منصة صَقِل • مختبر فحص المركبات الكهربائية VTC EV Lab',
style: TextStyle(color: Color(0x3300F5D4), fontSize: 11, fontWeight: FontWeight.bold),
);
final watermarkPainter = TextPainter(text: watermarkSpan, textDirection: TextDirection.rtl)..layout();
watermarkPainter.paint(canvas, const Offset(12, 12));
// 1. High Voltage Battery Pack Silhouette
final bRect = RRect.fromRectAndRadius(
Rect.fromLTWH(24, cy - 65, w * 0.40, 130),
const Radius.circular(16),
);
canvas.drawRRect(bRect, Paint()..color = const Color(0xFF0F1E29));
canvas.drawRRect(bRect, Paint()..color = const Color(0xFF10B981)..style = PaintingStyle.stroke..strokeWidth = 2);
// Battery Pack label
const bSpan = TextSpan(
text: 'بطارية الجهد العالي (384V DC)\nLi-Ion NMC Battery Pack',
style: TextStyle(color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold),
);
final btp = TextPainter(text: bSpan, textDirection: TextDirection.rtl)..layout();
btp.paint(canvas, Offset(36, cy - 45));
// SoC Bar inside pack
final socW = (w * 0.40 - 24) * (batterySoc / 100.0);
canvas.drawRRect(
RRect.fromRectAndRadius(Rect.fromLTWH(36, cy + 20, socW, 16), const Radius.circular(6)),
Paint()..color = const Color(0xFF10B981),
);
// 2. Inverter & Motor Unit
final invRect = RRect.fromRectAndRadius(
Rect.fromLTWH(w * 0.60, cy - 65, w * 0.34, 130),
const Radius.circular(16),
);
canvas.drawRRect(invRect, Paint()..color = const Color(0xFF1E1A2E));
canvas.drawRRect(
invRect,
Paint()
..color = isFaulted ? const Color(0xFFFF2D55) : const Color(0xFF8B5CF6)
..style = PaintingStyle.stroke
..strokeWidth = 2,
);
final invSpan = TextSpan(
text: 'محول القدرة والمحرك (Inverter)\nAC 3-Phase Permanent Magnet',
style: TextStyle(color: isFaulted ? const Color(0xFFFF2D55) : Colors.white, fontSize: 11, fontWeight: FontWeight.bold),
);
final itp = TextPainter(text: invSpan, textDirection: TextDirection.rtl)..layout();
itp.paint(canvas, Offset(w * 0.60 + 12, cy - 45));
// 3. High-Voltage Bus Cables (Orange Cables +HV and -HV)
final hvCableColor = isFaulted ? const Color(0xFFFF2D55) : const Color(0xFFFF7A00); // Standard Orange EV Cable
final cablePaint = Paint()..color = hvCableColor..strokeWidth = 4..strokeCap = StrokeCap.round;
// +HV Cable (Top)
canvas.drawLine(Offset(24 + w * 0.40, cy - 20), Offset(w * 0.60, cy - 20), cablePaint);
// -HV Cable (Bottom)
canvas.drawLine(Offset(24 + w * 0.40, cy + 20), Offset(w * 0.60, cy + 20), cablePaint);
// Cable Voltage Badge
final voltSpan = TextSpan(
text: isFaulted ? '⚠️ جهد معزول تلقائياً' : '+384V DC Bus',
style: TextStyle(color: hvCableColor, fontSize: 10, fontWeight: FontWeight.w800),
);
final vtp = TextPainter(text: voltSpan, textDirection: TextDirection.ltr)..layout();
vtp.paint(canvas, Offset(w * 0.46, cy - 36));
// 4. HVIL Interlock Loop Indicator
final hvilColor = hvilClosed ? const Color(0xFF10B981) : const Color(0xFFFF2D55);
final hvilPaint = Paint()..color = hvilColor..strokeWidth = 2..style = PaintingStyle.stroke;
canvas.drawCircle(Offset(w * 0.50, cy + 45), 8, hvilPaint);
canvas.drawCircle(Offset(w * 0.50, cy + 45), 4, Paint()..color = hvilColor);
}
@override
bool shouldRepaint(covariant _EvDiagnosticsPainter oldDelegate) => true;
}