import 'dart:math'; import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:get/get.dart'; import 'package:sefer_admin1/views/admin/drivers/driver_gift_check_page.dart'; import 'package:sefer_admin1/views/admin/drivers/driver_tracker_screen.dart'; import '../../constant/box_name.dart'; import '../../controller/admin/dashboard_controller.dart'; import '../../controller/admin/static_controller.dart'; import '../../controller/functions/crud.dart'; import '../../controller/notification_controller.dart'; import '../../main.dart'; import '../../print.dart'; import '../invoice/invoice_list_page.dart'; import 'captain/captain.dart'; import 'captain/syrian_driver_not_active.dart'; import 'drivers/monitor_ride.dart'; import 'employee/employee_page.dart'; import 'enceypt/driver_fingerprint_migration.dart'; import 'enceypt/encrypt.dart'; import 'enceypt/fingerprint_migration.dart'; import 'error/error/error_page.dart'; import 'packages.dart'; import 'passenger/passenger.dart'; import 'rides/ride_lookup_page.dart'; import 'server/monitor_server_page.dart'; import 'static/static.dart'; import 'wallet/wallet.dart'; import 'staff/add_staff_page.dart'; import 'staff/pending_admins_page.dart'; class AdminHomePage extends StatefulWidget { const AdminHomePage({super.key}); @override State createState() => _AdminHomePageState(); } class _AdminHomePageState extends State with SingleTickerProviderStateMixin { final TextEditingController _messageController = TextEditingController(); final TextEditingController _searchController = TextEditingController(); late AnimationController _pulseController; late bool isSuperAdmin; late DashboardController dashboardController; String _searchQuery = ''; // ══════════════════ DESIGN TOKENS ══════════════════ static const Color _bg = Color(0xFF0D1117); static const Color _surface = Color(0xFF161B22); static const Color _surfaceElevated = Color(0xFF1C2333); static const Color _accent = Color(0xFF00D4AA); // Emerald-teal static const Color _accentSoft = Color(0xFF00D4AA20); static const Color _accentBorder = Color(0xFF00D4AA40); static const Color _danger = Color(0xFFFF5370); static const Color _warning = Color(0xFFFFCB6B); static const Color _info = Color(0xFF82AAFF); static const Color _success = Color(0xFFC3E88D); static const Color _textPrimary = Color(0xFFE6EDF3); static const Color _textSecondary = Color(0xFF7D8590); static const Color _divider = Color(0xFF21262D); @override void initState() { super.initState(); _pulseController = AnimationController( vsync: this, duration: const Duration(seconds: 2), )..repeat(reverse: true); final String role = box.read('admin_role')?.toString() ?? 'admin'; final String myPhone = box.read(BoxName.adminPhone)?.toString() ?? ''; // التحقق من الصلاحيات: إما عن طريق الدور أو عن طريق قائمة أرقام السوبر أدمن التقليدية isSuperAdmin = (role == 'super_admin') || (myPhone == '201023248456' || myPhone == '963992952235' || myPhone == '963942542053'); Log.print('AdminHomePage: role=$role, isSuperAdmin=$isSuperAdmin'); dashboardController = Get.put(DashboardController()); } @override void dispose() { _pulseController.dispose(); _messageController.dispose(); _searchController.dispose(); super.dispose(); } // ══════════════════════════════════════════════════════════════ // BUILD // ══════════════════════════════════════════════════════════════ @override Widget build(BuildContext context) { return Scaffold( backgroundColor: _bg, body: RefreshIndicator( onRefresh: () async => await dashboardController.getDashBoard(), color: _accent, backgroundColor: _surface, child: GetBuilder( builder: (controller) { if (controller.dashbord.isEmpty) { return _buildLoadingState(); } final data = controller.dashbord[0]; final categories = _getFilteredCategories(); return CustomScrollView( physics: const BouncingScrollPhysics(), slivers: [ _buildSliverAppBar(controller), _buildSearchBar(), if (_searchQuery.isEmpty) _buildQuickStatsSection(data, controller), SliverPadding( padding: const EdgeInsets.only(bottom: 60), sliver: SliverList( delegate: SliverChildBuilderDelegate( (context, index) { final category = categories[index]; if (category.items.isEmpty) return const SizedBox.shrink(); return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 450), child: SlideAnimation( verticalOffset: 40.0, child: FadeInAnimation( child: _buildCategorySection(category), ), ), ); }, childCount: categories.length, ), ), ), ], ); }, ), ), ); } // ══════════════════════════════════════════════════════════════ // LOADING STATE // ══════════════════════════════════════════════════════════════ Widget _buildLoadingState() { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: 60, height: 60, decoration: BoxDecoration( shape: BoxShape.circle, gradient: RadialGradient( colors: [_accent.withOpacity(0.3), Colors.transparent], ), ), child: const Center( child: SizedBox( width: 28, height: 28, child: CircularProgressIndicator( color: _accent, strokeWidth: 2.5, ), ), ), ), const SizedBox(height: 16), Text('جاري التحميل...', style: TextStyle(color: _textSecondary, fontSize: 13)), ], ), ); } // ══════════════════════════════════════════════════════════════ // SLIVER APP BAR // ══════════════════════════════════════════════════════════════ Widget _buildSliverAppBar(DashboardController controller) { return SliverAppBar( expandedHeight: 130.0, floating: true, pinned: true, backgroundColor: _bg, elevation: 0, flexibleSpace: FlexibleSpaceBar( collapseMode: CollapseMode.pin, background: Stack( fit: StackFit.expand, children: [ // Aurora gradient background Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color(0xFF0D2137), Color(0xFF0D1117), Color(0xFF0F1F1A), ], ), ), ), // Subtle glow orbs Positioned( top: -30, left: -40, child: _GlowOrb(color: _accent, size: 150, opacity: 0.08), ), Positioned( top: -20, right: -20, child: _GlowOrb(color: _info, size: 120, opacity: 0.06), ), // Content Align( alignment: Alignment.bottomCenter, child: Padding( padding: const EdgeInsets.only(bottom: 18), child: Column( mainAxisSize: MainAxisSize.min, children: [ _buildLogo(), const SizedBox(height: 6), Text( isSuperAdmin ? 'Super Admin Panel' : 'Admin Panel', style: TextStyle( color: _textSecondary, fontSize: 11, letterSpacing: 1.5, ), ), ], ), ), ), ], ), ), actions: [ _buildHeaderAction( Icons.refresh_rounded, () => controller.getDashBoard()), const SizedBox(width: 8), ], ); } Widget _buildLogo() { return Row( mainAxisSize: MainAxisSize.min, children: [ AnimatedBuilder( animation: _pulseController, builder: (_, __) { return Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), gradient: LinearGradient( colors: [ _accent.withOpacity(0.3 + 0.1 * _pulseController.value), _accent.withOpacity(0.1), ], ), border: Border.all( color: _accent.withOpacity(0.4 + 0.2 * _pulseController.value), width: 1, ), ), child: const Icon( Icons.admin_panel_settings_rounded, color: _accent, size: 18, ), ); }, ), const SizedBox(width: 10), ShaderMask( shaderCallback: (bounds) => const LinearGradient( colors: [_accent, _info], ).createShader(bounds), child: const Text( 'Intaleq Admin', style: TextStyle( color: Colors.white, fontWeight: FontWeight.w700, fontSize: 20, letterSpacing: 0.5, ), ), ), ], ); } Widget _buildHeaderAction(IconData icon, VoidCallback onTap) { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: _surface, borderRadius: BorderRadius.circular(10), border: Border.all(color: _divider), ), child: Icon(icon, color: _textSecondary, size: 18), ), ); } // ══════════════════════════════════════════════════════════════ // SEARCH BAR // ══════════════════════════════════════════════════════════════ Widget _buildSearchBar() { return SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.fromLTRB(16, 12, 16, 4), child: Container( decoration: BoxDecoration( color: _surface, borderRadius: BorderRadius.circular(14), border: Border.all( color: _searchQuery.isNotEmpty ? _accentBorder : _divider, width: _searchQuery.isNotEmpty ? 1.5 : 1, ), ), child: TextField( controller: _searchController, onChanged: (val) => setState(() => _searchQuery = val), style: const TextStyle(color: _textPrimary, fontSize: 14), decoration: InputDecoration( hintText: 'ابحث عن خدمة أو ميزة...', hintStyle: const TextStyle(color: _textSecondary, fontSize: 13), prefixIcon: const Icon(Icons.search_rounded, color: _accent, size: 20), suffixIcon: _searchQuery.isNotEmpty ? IconButton( icon: Icon(Icons.close_rounded, color: _textSecondary, size: 18), onPressed: () { setState(() { _searchQuery = ''; _searchController.clear(); }); }, ) : null, border: InputBorder.none, contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), ), ), ), ), ); } // ══════════════════════════════════════════════════════════════ // QUICK STATS SECTION // ══════════════════════════════════════════════════════════════ Widget _buildQuickStatsSection(dynamic data, DashboardController controller) { final highlights = [ _HighlightData( 'إجمالي الركاب', data['countPassengers'], Icons.group_rounded, _info), _HighlightData('إجمالي السائقين', data['countDriver'], Icons.drive_eta_rounded, _warning), _HighlightData('رحلات الشهر', data['countRideThisMonth'], Icons.calendar_today_rounded, const Color(0xFFC792EA)), if (isSuperAdmin) _HighlightData('المحفظة', _formatCurrency(data['seferWallet']), Icons.account_balance_wallet_rounded, _accent), ]; final detailedStats = _getDetailedStats(data, controller); return SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only(top: 8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Section label Padding( padding: const EdgeInsets.fromLTRB(20, 8, 20, 10), child: Row( children: [ Container( width: 3, height: 14, decoration: BoxDecoration( color: _accent, borderRadius: BorderRadius.circular(2), ), ), const SizedBox(width: 8), const Text('نظرة عامة', style: TextStyle( color: _textSecondary, fontSize: 11, fontWeight: FontWeight.w600, letterSpacing: 1.2, )), ], ), ), // Highlight Cards SizedBox( height: 108, child: ListView.builder( padding: const EdgeInsets.symmetric(horizontal: 16), scrollDirection: Axis.horizontal, itemCount: highlights.length, itemBuilder: (ctx, i) => Padding( padding: EdgeInsets.only( right: i < highlights.length - 1 ? 10 : 0), child: _buildHighlightCard(highlights[i]), ), ), ), const SizedBox(height: 16), // Detailed stats strip Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Container( decoration: BoxDecoration( color: _surface, borderRadius: BorderRadius.circular(16), border: Border.all(color: _divider), ), child: ClipRRect( borderRadius: BorderRadius.circular(16), child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: List.generate(detailedStats.length, (i) { final stat = detailedStats[i]; return Row( mainAxisSize: MainAxisSize.min, children: [ _buildDetailStatItem(stat), if (i < detailedStats.length - 1) Container( width: 1, height: 36, color: _divider, ), ], ); }), ), ), ), ), ), const SizedBox(height: 8), ], ), ), ); } Widget _buildHighlightCard(_HighlightData h) { return Container( width: 148, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: _surface, borderRadius: BorderRadius.circular(16), border: Border.all(color: h.color.withOpacity(0.2)), boxShadow: [ BoxShadow( color: h.color.withOpacity(0.08), blurRadius: 16, offset: const Offset(0, 6), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( padding: const EdgeInsets.all(7), decoration: BoxDecoration( color: h.color.withOpacity(0.12), borderRadius: BorderRadius.circular(9), ), child: Icon(h.icon, color: h.color, size: 16), ), Container( width: 6, height: 6, decoration: BoxDecoration( shape: BoxShape.circle, color: h.color.withOpacity(0.6), ), ), ], ), const Spacer(), Text( h.value.toString(), style: const TextStyle( color: _textPrimary, fontSize: 20, fontWeight: FontWeight.w700, height: 1.1, ), overflow: TextOverflow.ellipsis, ), const SizedBox(height: 3), Text( h.label, style: const TextStyle( color: _textSecondary, fontSize: 10, fontWeight: FontWeight.w500, ), overflow: TextOverflow.ellipsis, ), ], ), ); } Widget _buildDetailStatItem(Map stat) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 14), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(stat['icon'] as IconData, color: stat['color'] as Color, size: 20), const SizedBox(height: 6), Text( stat['value'].toString(), style: const TextStyle( color: _textPrimary, fontSize: 14, fontWeight: FontWeight.bold, height: 1, ), ), const SizedBox(height: 3), Text( stat['title'] as String, style: const TextStyle( color: _textSecondary, fontSize: 9, fontWeight: FontWeight.w500, ), ), ], ), ); } // ══════════════════════════════════════════════════════════════ // CATEGORY SECTION // ══════════════════════════════════════════════════════════════ Widget _buildCategorySection(ActionCategory category) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.fromLTRB(20, 20, 20, 12), child: Row( children: [ Container( width: 3, height: 14, decoration: BoxDecoration( color: _accent, borderRadius: BorderRadius.circular(2), ), ), const SizedBox(width: 8), Text( category.title, style: const TextStyle( color: _textPrimary, fontSize: 15, fontWeight: FontWeight.w600, letterSpacing: 0.3, ), ), const SizedBox(width: 10), Expanded( child: Container(height: 1, color: _divider), ), const SizedBox(width: 8), Text( '${category.items.length}', style: const TextStyle( color: _textSecondary, fontSize: 11, fontWeight: FontWeight.w500, ), ), ], ), ), GridView.builder( padding: const EdgeInsets.symmetric(horizontal: 16), shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 120, childAspectRatio: 0.88, crossAxisSpacing: 10, mainAxisSpacing: 10, ), itemCount: category.items.length, itemBuilder: (context, index) => _buildActionItem(category.items[index]), ), const SizedBox(height: 8), ], ); } Widget _buildActionItem(ActionItem item) { return Material( color: Colors.transparent, child: InkWell( onTap: item.onPressed, borderRadius: BorderRadius.circular(16), splashColor: item.color.withOpacity(0.1), highlightColor: item.color.withOpacity(0.05), child: Container( decoration: BoxDecoration( color: _surface, borderRadius: BorderRadius.circular(16), border: Border.all(color: _divider), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: const EdgeInsets.all(11), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ item.color.withOpacity(0.20), item.color.withOpacity(0.08), ], ), borderRadius: BorderRadius.circular(12), border: Border.all(color: item.color.withOpacity(0.25)), boxShadow: [ BoxShadow( color: item.color.withOpacity(0.15), blurRadius: 10, offset: const Offset(0, 3), ), ], ), child: Icon(item.icon, color: item.color, size: 22), ), const SizedBox(height: 10), Padding( padding: const EdgeInsets.symmetric(horizontal: 6), child: Text( item.title, textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( color: _textPrimary, fontSize: 11, fontWeight: FontWeight.w500, height: 1.3, ), ), ), ], ), ), ), ); } // ══════════════════════════════════════════════════════════════ // DATA HELPERS // ══════════════════════════════════════════════════════════════ List _getFilteredCategories() { final all = _getAllActionCategories(); if (_searchQuery.isEmpty) return all; return all .map((cat) { final matched = cat.items .where((item) => item.title.toLowerCase().contains(_searchQuery.toLowerCase())) .toList(); return matched.isEmpty ? null : ActionCategory(title: cat.title, items: matched); }) .whereType() .toList(); } List _getAllActionCategories() { return [ ActionCategory( title: 'المستخدمين', items: [ ActionItem('الركاب', Icons.people_outline_rounded, _info, () => Get.to(() => Passengrs())), ActionItem('السائقون', Icons.drive_eta_rounded, _warning, () => Get.to(() => CaptainsPage())), ActionItem('المراقب', Icons.track_changes_rounded, _danger, () => Get.to(() => IntaleqTrackerScreen())), ], ), ActionCategory( title: 'العمليات', items: [ ActionItem('الرحلات', Icons.map_rounded, const Color(0xFF82AAFF), () => Get.to(() => RidesDashboardScreen())), if (isSuperAdmin) ActionItem( 'مراقبة الرحلات', Icons.remove_red_eye_rounded, const Color(0xFFC792EA), () => Get.to(() => RideMonitorScreen())), ActionItem('الإحصائيات', Icons.bar_chart_rounded, _accent, () async { await Get.put(StaticController()).getAll(); Get.to(() => const StaticDash()); }), ], ), if (isSuperAdmin) ActionCategory( title: 'المالية والإدارة', items: [ ActionItem('المحفظة', Icons.account_balance_wallet_rounded, _accent, () => Get.to(() => Wallet())), ActionItem('هدية 300', Icons.card_giftcard_rounded, _warning, () => Get.to(() => DriverGiftCheckPage())), ActionItem('الفواتير', Icons.receipt_long_rounded, const Color(0xFF80CBC4), () => Get.to(() => InvoiceListPage())), ActionItem('الموظفون', Icons.badge_rounded, const Color(0xFFB0BEC5), () => Get.to(() => EmployeePage())), ActionItem('موافقة المشرفين', Icons.how_to_reg_rounded, _accent, () => Get.to(() => const PendingAdminsPage())), ], ), if (isSuperAdmin) ActionCategory( title: 'النظام والتواصل', items: [ ActionItem('واتساب جماعي', Icons.message_rounded, const Color(0xFF4CAF50), () => _showWhatsAppDialog(context)), ActionItem( 'إشعار سائقين', Icons.notifications_active_rounded, const Color(0xFFFF7043), () => Get.put(NotificationController()) .sendNotificationDrivers()), ActionItem( 'إشعار ركاب', Icons.notification_important_rounded, const Color(0xFFF06292), () => Get.put(NotificationController()) .sendNotificationPassengers()), ActionItem('تسجيل سائق', Icons.person_add_rounded, _info, () => Get.to(() => DriversPendingPage())), ActionItem( 'تحديث التطبيق', Icons.system_update_rounded, const Color(0xFFA1887F), () => Get.to(() => PackageUpdateScreen())), ActionItem('مراقب السيرفر', Icons.dns_rounded, _accent, () => Get.to(() => ServerMonitorPage())), ActionItem('سجل الأخطاء', Icons.error_outline_rounded, _danger, () => Get.to(() => ErrorListPage())), ActionItem('encrypt fp', Icons.error_outline_rounded, _danger, () => Get.to(() => FingerprintMigrationTool())), ActionItem('encrypt fp drivers', Icons.error_outline_rounded, _danger, () => Get.to(() => DriverFingerprintMigrationTool())), ActionItem( 'أداة التشفير', Icons.lock_rounded, const Color(0xFF9575CD), () => Get.to(() => EncryptToolPage( adminToken: box.read(BoxName.adminPhone), ))), ], ), if (isSuperAdmin) ActionCategory( title: 'إدارة الكوادر', items: [ ActionItem( 'إضافة مدير', Icons.admin_panel_settings_rounded, _accent, () => Get.to(() => const AddStaffPage(role: 'admin')), ), ActionItem( 'إضافة خدمة عملاء', Icons.support_agent_rounded, _info, () => Get.to(() => const AddStaffPage(role: 'service')), ), ], ), ]; } List> _getDetailedStats( dynamic data, DashboardController controller) { return [ if (isSuperAdmin) { 'title': 'رصيد الرسائل', 'value': controller.creditSMS, 'icon': Icons.sms_rounded, 'color': _info, }, { 'title': 'مكتملة', 'value': data['completed_rides'], 'icon': Icons.check_circle_rounded, 'color': _success, }, { 'title': 'ملغاة', 'value': data['cancelled_rides'], 'icon': Icons.cancel_rounded, 'color': _danger, }, { 'title': 'مدفوعات', 'value': _formatCurrency(data['payments']), 'icon': Icons.attach_money_rounded, 'color': _warning, }, { 'title': 'Comfort', 'value': data['comfort'], 'icon': Icons.chair_rounded, 'color': const Color(0xFF80CBC4), }, { 'title': 'Speed', 'value': data['speed'], 'icon': Icons.flash_on_rounded, 'color': const Color(0xFFFFD54F), }, { 'title': 'Lady', 'value': data['lady'], 'icon': Icons.woman_rounded, 'color': const Color(0xFFF48FB1), }, ]; } // ══════════════════════════════════════════════════════════════ // WHATSAPP DIALOG // ══════════════════════════════════════════════════════════════ void _showWhatsAppDialog(BuildContext context) { Get.dialog( Dialog( backgroundColor: Colors.transparent, child: Container( decoration: BoxDecoration( color: _surfaceElevated, borderRadius: BorderRadius.circular(24), border: Border.all(color: _divider), boxShadow: const [ BoxShadow( color: Colors.black45, blurRadius: 30, offset: Offset(0, 12), ), ], ), padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: const Color(0xFF4CAF50).withOpacity(0.12), shape: BoxShape.circle, border: Border.all( color: const Color(0xFF4CAF50).withOpacity(0.25)), ), child: const Icon(Icons.message_rounded, color: Color(0xFF4CAF50), size: 28), ), const SizedBox(height: 16), const Text( 'إرسال واتساب جماعي', style: TextStyle( color: _textPrimary, fontSize: 17, fontWeight: FontWeight.w700, ), ), const SizedBox(height: 4), const Text( 'سيتم إرسال الرسالة لجميع السائقين', style: TextStyle(color: _textSecondary, fontSize: 11), ), const SizedBox(height: 20), Container( decoration: BoxDecoration( color: _bg, borderRadius: BorderRadius.circular(14), border: Border.all(color: _divider), ), child: TextField( controller: _messageController, maxLines: 4, style: const TextStyle(color: _textPrimary, fontSize: 13), decoration: const InputDecoration( hintText: 'اكتب رسالتك هنا...', hintStyle: TextStyle(color: _textSecondary, fontSize: 12), border: InputBorder.none, contentPadding: EdgeInsets.all(14), ), ), ), const SizedBox(height: 20), Row( children: [ Expanded( child: TextButton( onPressed: () => Get.back(), style: TextButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: const BorderSide(color: _divider), ), ), child: const Text( 'إلغاء', style: TextStyle(color: _textSecondary, fontSize: 13), ), ), ), const SizedBox(width: 12), Expanded( child: ElevatedButton.icon( icon: const Icon(Icons.send_rounded, size: 16), label: const Text('إرسال', style: TextStyle(fontSize: 13)), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF4CAF50), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), elevation: 0, ), onPressed: () async { if (_messageController.text.isNotEmpty) { Get.back(); var driverPhones = box .read(BoxName.tokensDrivers)['message'] as List?; if (driverPhones == null || driverPhones.isEmpty) return; Get.snackbar( 'بدأ الإرسال', 'سيتم الإرسال في الخلفية', backgroundColor: const Color(0xFF4CAF50).withOpacity(0.15), colorText: _textPrimary, borderRadius: 12, margin: const EdgeInsets.all(16), icon: const Icon(Icons.check_circle_rounded, color: Color(0xFF4CAF50)), ); for (var driverData in driverPhones) { if (driverData['phone'] != null) { await CRUD().sendWhatsAppAuth( driverData['phone'].toString(), _messageController.text); await Future.delayed( Duration(seconds: Random().nextInt(3) + 1)); } } _messageController.clear(); } }, ), ), ], ), ], ), ), ), ); } String _formatCurrency(dynamic value) { if (value == null) return '0.0'; return double.tryParse(value.toString())?.toStringAsFixed(1) ?? '0.0'; } } // ══════════════════════════════════════════════════════════════ // HELPER WIDGETS // ══════════════════════════════════════════════════════════════ class _GlowOrb extends StatelessWidget { final Color color; final double size; final double opacity; const _GlowOrb( {required this.color, required this.size, required this.opacity}); @override Widget build(BuildContext context) { return Container( width: size, height: size, decoration: BoxDecoration( shape: BoxShape.circle, gradient: RadialGradient( colors: [color.withOpacity(opacity), Colors.transparent], ), ), ); } } // ══════════════════════════════════════════════════════════════ // DATA CLASSES // ══════════════════════════════════════════════════════════════ class _HighlightData { final String label; final dynamic value; final IconData icon; final Color color; _HighlightData(this.label, this.value, this.icon, this.color); } class ActionItem { final String title; final IconData icon; final Color color; final VoidCallback onPressed; ActionItem(this.title, this.icon, this.color, this.onPressed); } class ActionCategory { final String title; final List items; ActionCategory({required this.title, required this.items}); }