Files
intaleq_admin/lib/views/admin/admin_home_page.dart
2026-01-20 23:39:59 +03:00

684 lines
25 KiB
Dart

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:get/get.dart';
import 'package:sefer_admin1/constant/colors.dart';
import 'package:sefer_admin1/controller/admin/dashboard_controller.dart';
import 'package:sefer_admin1/controller/admin/static_controller.dart';
import 'package:sefer_admin1/controller/notification_controller.dart';
import 'package:sefer_admin1/main.dart';
import 'package:sefer_admin1/views/admin/drivers/driver_tracker_screen.dart';
import 'package:sefer_admin1/views/admin/error/error/error_page.dart';
import 'package:sefer_admin1/views/widgets/mycircular.dart';
// تأكد من صحة المسارات
import '../../constant/box_name.dart';
import '../../controller/functions/crud.dart';
import '../invoice/invoice_list_page.dart';
import '../widgets/my_textField.dart';
import 'captain/captain.dart';
import 'captain/syrian_driver_not_active.dart';
import 'drivers/driver_gift_check_page.dart';
import 'drivers/driver_the_best.dart';
import 'drivers/monitor_ride.dart';
import 'employee/employee_page.dart';
import 'packages.dart';
import 'passenger/passenger.dart';
import 'rides/ride_lookup_page.dart';
import 'static/static.dart';
import 'wallet/wallet.dart';
class AdminHomePage extends StatelessWidget {
AdminHomePage({super.key});
final TextEditingController _messageController = TextEditingController();
// حساب عدد الأعمدة
int _calculateCrossAxisCount(BuildContext context, {bool isSmall = false}) {
double screenWidth = MediaQuery.of(context).size.width;
if (screenWidth > 1200) return isSmall ? 6 : 5;
if (screenWidth > 900) return isSmall ? 5 : 4;
if (screenWidth > 600) return isSmall ? 4 : 3;
return isSmall ? 3 : 2;
}
String _formatCurrency(dynamic value) {
if (value == null) return '0.00';
final number = double.tryParse(value.toString());
if (number != null) return number.toStringAsFixed(2);
return '0.00';
}
@override
Widget build(BuildContext context) {
final DashboardController dashboardController =
Get.put(DashboardController());
// 1. تحديد هوية المستخدم الحالي
String myPhone = box.read(BoxName.adminPhone).toString();
// 2. تحديد من هو "السوبر أدمن" الذي يرى كل شيء
// يمكنك إضافة المزيد من الأرقام هنا باستخدام || أو قائمة
bool isSuperAdmin = myPhone == '963942542053' || myPhone == '963992952235';
// 3. بناء القائمة باستخدام (Collection If)
final List<Map<String, dynamic>> actionItems = [
// --- عناصر يراها الجميع ---
{
'title': 'الركاب',
'icon': Icons.people_alt_rounded,
'color': Colors.blueAccent,
'onPressed': () =>
Get.to(() => Passengrs(), transition: Transition.fadeIn)
},
{
'title': 'الكباتن',
'icon': Icons.sports_motorsports_rounded,
'color': Colors.orangeAccent,
'onPressed': () =>
Get.to(() => CaptainsPage(), transition: Transition.fadeIn)
},
{
'title': 'الرحلات',
'icon': Icons.directions_car_filled_rounded,
'color': Colors.indigoAccent,
'onPressed': () =>
Get.to(() => RidesDashboardScreen(), transition: Transition.fadeIn)
// Get.to(() => RideLookupPage(), transition: Transition.fadeIn)
},
{
'title': ' الكباتن النشطين',
'icon': Icons.directions_car_filled_rounded,
'color': Colors.indigoAccent,
'onPressed': () =>
Get.to(() => IntaleqTrackerScreen(), transition: Transition.fadeIn)
},
// --- عناصر خاصة بالسوبر أدمن فقط (Using Collection If) ---
if (isSuperAdmin)
{
'title': 'مراقبة الرحلات'.tr,
'icon': Icons.route, // أيقونة مناسبة لمراقبة الرحلات
'color': Colors.purpleAccent,
'onPressed': () =>
Get.to(() => RideMonitorScreen(), transition: Transition.fadeIn),
},
if (isSuperAdmin)
{
'title': 'المحفظة', // الأمور المالية حساسة
'icon': Icons.account_balance_wallet_rounded,
'color': Colors.purpleAccent,
'onPressed': () =>
Get.to(() => Wallet(), transition: Transition.fadeIn)
},
if (isSuperAdmin)
{
'title': 'دفع هدية 300'.tr,
'icon': Icons.card_giftcard, // أيقونة الهدية
'color': Colors.purpleAccent,
'onPressed': () => Get.to(() => DriverGiftCheckPage(),
transition: Transition.fadeIn),
},
// if (isSuperAdmin)
{
'title': 'الإحصائيات',
'icon': Icons.bar_chart_rounded,
'color': Colors.teal,
'onPressed': () async {
await Get.put(StaticController()).getAll();
Get.to(() => const StaticDash());
}
},
// هذا هو الجزء الذي طلبته تحديداً
if (isSuperAdmin)
{
'title': 'واتساب سائقين',
'icon': Icons.message_rounded,
'color': Colors.green,
'onPressed': () => _showWhatsAppDialog(context)
},
// --- عودة للعناصر العامة (أو يمكنك تقييدها أيضاً) ---
if (isSuperAdmin)
{
'title': 'إشعار للسائقين',
'icon': Icons.notifications_active_rounded,
'color': Colors.deepOrange,
'onPressed': () async =>
await Get.put(NotificationController()).sendNotificationDrivers()
},
if (isSuperAdmin)
{
'title': 'إشعار للركاب',
'icon': Icons.notification_important_rounded,
'color': Colors.pinkAccent,
'onPressed': () async => await Get.put(NotificationController())
.sendNotificationPassengers()
},
if (isSuperAdmin)
{
'title': 'تسجيل كابتن',
'icon': Icons.person_add_alt_1_rounded,
'color': Colors.cyan,
'onPressed': () => Get.to(() => DriversPendingPage())
},
if (isSuperAdmin) // تحديث الباقات للمدير فقط
{
'title': 'تحديث الباقات',
'icon': Icons.inventory_2_rounded,
'color': Colors.brown,
'onPressed': () => Get.to(() => PackageUpdateScreen())
},
if (isSuperAdmin) // الموظفون للمدير فقط
{
'title': 'الموظفون',
'icon': Icons.badge_rounded,
'color': Colors.blueGrey,
'onPressed': () => Get.to(() => EmployeePage())
},
if (isSuperAdmin)
{
'title': 'أفضل السائقين',
'icon': Icons.star_rounded,
'color': Colors.amber,
'onPressed': () => Get.to(() => DriverTheBestRedesigned())
},
if (isSuperAdmin) // الفواتير للمدير فقط
{
'title': 'الفواتير',
'icon': Icons.receipt_long_rounded,
'color': Colors.green.shade800,
'onPressed': () => Get.to(() => InvoiceListPage())
},
if (isSuperAdmin)
{
'title': 'سجل الأخطاء',
'icon': Icons.error_outline_rounded,
'color': Colors.redAccent,
'onPressed': () => Get.to(() => ErrorListPage())
},
];
return Scaffold(
backgroundColor: const Color(0xFFF5F7FA),
body: RefreshIndicator(
onRefresh: () async {
await dashboardController.getDashBoard();
},
child: GetBuilder<DashboardController>(builder: (controller) {
if (controller.dashbord.isEmpty) {
return const Center(child: MyCircularProgressIndicator());
}
final data = controller.dashbord[0];
// إحصائيات لوحة التحكم
final List<Map<String, dynamic>> statCards = [
// يمكنك تطبيق نفس المنطق هنا لإخفاء الأرباح عن الموظفين العاديين
if (isSuperAdmin)
{
'title': 'رصيد الرسائل',
'value': controller.creditSMS.toString(),
'icon': Icons.sms_outlined,
'color': Colors.lightBlue
},
{
'title': 'الركاب',
'value': data['countPassengers'].toString(),
'icon': Icons.people_alt_outlined,
'color': Colors.teal
},
{
'title': 'السائقون',
'value': data['countDriver'].toString(),
'icon': Icons.sports_motorsports_outlined,
'color': Colors.orange
},
{
'title': 'رحلات الشهر',
'value': data['countRideThisMonth'].toString(),
'icon': Icons.calendar_month_outlined,
'color': Colors.purple
},
if (isSuperAdmin) // إخفاء الأمور المالية
{
'title': 'متوسط التكلفة',
'value': _formatCurrency(data['avg_passenger_price']),
'icon': Icons.monetization_on_outlined,
'color': Colors.green
},
{
'title': 'الرحلات المكتملة',
'value': data['completed_rides'].toString(),
'icon': Icons.check_circle_outline,
'color': AppColor.greenColor
},
{
'title': 'الرحلات الملغاة',
'value': data['cancelled_rides'].toString(),
'icon': Icons.cancel_outlined,
'color': AppColor.redColor
},
// if (isSuperAdmin) // إخفاء المدفوعات
{
'title': 'مدفوعات السائقين',
'value': _formatCurrency(data['payments']),
'icon': Icons.payments_outlined,
'color': Colors.indigo
},
// if (isSuperAdmin)
{
'title': 'محفظة انطلق',
'value': _formatCurrency(data['seferWallet']),
'icon': Icons.account_balance_wallet_outlined,
'color': Colors.deepOrange
},
{
'title': 'عدد التحويلات',
'value': data['transfer_from_count'].toString(),
'icon': Icons.swap_horiz_outlined,
'color': Colors.brown
},
// ... بقية العناصر التي لا تحتاج إخفاء
{
'title': 'رحلات الصباح',
'value': data['morning_ride_count'].toString(),
'icon': Icons.wb_sunny_outlined,
'color': Colors.amber.shade700
},
{
'title': 'رحلات المساء',
'value': data['evening_ride_count'].toString(),
'icon': Icons.brightness_4_outlined,
'color': Colors.blueGrey
},
{
'title': 'رحلات الليل',
'value': data['night_ride_count'].toString(),
'icon': Icons.nightlight_round_outlined,
'color': Colors.black87
},
{
'title': 'كومفورت',
'value': data['comfort'].toString(),
'icon': Icons.event_seat_outlined,
'color': Colors.cyan
},
{
'title': 'سبيد',
'value': data['speed'].toString(),
'icon': Icons.speed_outlined,
'color': Colors.red.shade700
},
{
'title': 'ليدي',
'value': data['lady'].toString(),
'icon': Icons.woman_2_outlined,
'color': Colors.pink
},
];
return CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: [
SliverAppBar(
expandedHeight: 120.0,
floating: true,
pinned: true,
backgroundColor: AppColor.primaryColor,
elevation: 0,
flexibleSpace: FlexibleSpaceBar(
titlePadding:
const EdgeInsets.only(left: 16, right: 16, bottom: 16),
title: const Text(
'لوحة التحكم',
style: TextStyle(
fontWeight: FontWeight.bold, color: Colors.white),
),
background: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
AppColor.primaryColor,
AppColor.primaryColor.withOpacity(0.8),
],
),
),
child: Stack(
children: [
Positioned(
left: -20,
top: -20,
child: Icon(Icons.dashboard,
size: 150, color: Colors.white.withOpacity(0.1)),
),
],
),
),
),
actions: [
IconButton(
onPressed: () async =>
await dashboardController.getDashBoard(),
icon: const Icon(Icons.refresh, color: Colors.white),
),
],
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 20, 16, 10),
child: Text(
"نظرة عامة",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.grey[800]),
),
),
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 16),
sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: _calculateCrossAxisCount(context),
mainAxisSpacing: 12.0,
crossAxisSpacing: 12.0,
childAspectRatio: 1.6,
),
delegate: SliverChildBuilderDelegate(
(context, index) {
final card = statCards[index];
return AnimationConfiguration.staggeredGrid(
position: index,
duration: const Duration(milliseconds: 375),
columnCount: _calculateCrossAxisCount(context),
child: ScaleAnimation(
child: FadeInAnimation(
child: _buildModernStatCard(
title: card['title'],
value: card['value'],
icon: card['icon'],
color: card['color'],
),
),
),
);
},
childCount: statCards.length,
),
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 24, 16, 10),
child: Text(
"إدارة النظام",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.grey[800]),
),
),
),
SliverPadding(
padding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount:
_calculateCrossAxisCount(context, isSmall: true),
mainAxisSpacing: 12.0,
crossAxisSpacing: 12.0,
childAspectRatio: 1.0,
),
delegate: SliverChildBuilderDelegate(
(context, index) {
final item = actionItems[index];
return AnimationConfiguration.staggeredGrid(
position: index,
duration: const Duration(milliseconds: 375),
columnCount:
_calculateCrossAxisCount(context, isSmall: true),
child: SlideAnimation(
verticalOffset: 50.0,
child: FadeInAnimation(
child: _buildActionCard(
context,
title: item['title'],
icon: item['icon'],
color: item['color'],
onTap: item['onPressed'],
),
),
),
);
},
childCount: actionItems.length,
),
),
),
const SliverToBoxAdapter(child: SizedBox(height: 40)),
],
);
}),
),
);
}
// --- بقية الدوال (buildModernStatCard, buildActionCard, showWhatsAppDialog) تبقى كما هي ---
Widget _buildModernStatCard({
required String title,
required String value,
required IconData icon,
required Color color,
}) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.04),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: Icon(icon, color: color, size: 20),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
value,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.grey[900],
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 4),
Text(
title,
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
fontWeight: FontWeight.w500,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
],
),
),
);
}
Widget _buildActionCard(
BuildContext context, {
required String title,
required IconData icon,
required Color color,
required VoidCallback onTap,
}) {
return Material(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
elevation: 0,
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(16),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
border: Border.all(color: Colors.grey.shade200),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
colors: [color.withOpacity(0.2), color.withOpacity(0.05)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: Icon(icon, size: 28, color: color),
),
const SizedBox(height: 12),
Text(
title,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
],
),
),
),
);
}
void _showWhatsAppDialog(BuildContext context) {
Get.dialog(
AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
title: const Text('إرسال رسالة جماعية',
style: TextStyle(fontWeight: FontWeight.bold)),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.green.withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: const Icon(Icons.send, size: 40, color: Colors.green),
),
const SizedBox(height: 15),
MyTextForm(
controller: _messageController,
label: 'الرسالة',
hint: 'اكتب الرسالة هنا...',
type: TextInputType.text,
),
],
),
actionsPadding: const EdgeInsets.all(15),
actions: [
TextButton(
onPressed: () {
_messageController.clear();
Get.back();
},
child: const Text('إلغاء', style: TextStyle(color: Colors.grey)),
),
ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
),
icon: const Icon(Icons.send, size: 18, color: Colors.white),
label: const Text('إرسال', style: TextStyle(color: Colors.white)),
onPressed: () async {
if (_messageController.text.isNotEmpty) {
Get.back();
var driverPhones =
box.read(BoxName.tokensDrivers)['message'] as List?;
if (driverPhones == null || driverPhones.isEmpty) {
Get.snackbar('تنبيه', 'لا توجد بيانات اتصال للسائقين',
backgroundColor: Colors.amber.withOpacity(0.5));
return;
}
Get.snackbar('جاري الإرسال', 'بدأت عملية الإرسال في الخلفية...',
backgroundColor: Colors.blue.withOpacity(0.3));
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();
Get.snackbar('نجاح', 'تمت العملية بنجاح',
backgroundColor: Colors.green.withOpacity(0.5));
}
},
),
],
),
);
}
}