first commit

This commit is contained in:
Hamza-Ayed
2025-07-30 10:24:53 +03:00
parent 0945095398
commit 0b17f93aaa
244 changed files with 40043 additions and 0 deletions

View File

@@ -0,0 +1,475 @@
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/register_captain_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/captain/drivers_cant_registe.dart';
import 'package:sefer_admin1/views/widgets/mycircular.dart';
// Please make sure all these imports are correct for your project structure
import '../../constant/box_name.dart';
import '../../constant/links.dart';
import '../../constant/style.dart';
import '../../controller/functions/crud.dart';
import '../invoice/invoice_list_page.dart';
import '../widgets/my_scafold.dart';
import '../widgets/my_textField.dart';
import '../invoice/add_invoice_page.dart';
import 'captain/captain.dart';
import 'dashboard_widget.dart'; // Assuming DashboardStatCard is here
import 'drivers/driver_the_best.dart';
import 'employee/employee_page.dart';
import 'packages.dart';
import 'passenger/passenger.dart';
import 'rides/rides.dart';
import 'static/static.dart';
import 'wallet/wallet.dart';
class AdminHomePage extends StatelessWidget {
AdminHomePage({super.key});
// Responsive grid column calculation
int _calculateCrossAxisCount(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
if (screenWidth > 1200) return 5; // Large desktops
if (screenWidth > 900) return 4; // Desktops
if (screenWidth > 600) return 3; // Tablets
return 2; // Phones
}
// Helper to format currency
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';
}
final TextEditingController _messageController = TextEditingController();
@override
Widget build(BuildContext context) {
// Make sure DashboardController is initialized
final DashboardController dashboardController =
Get.put(DashboardController());
// Action items list with Arabic titles
final List<Map<String, dynamic>> actionItems = [
{
'title': 'الركاب',
'icon': Icons.people_alt_outlined,
'onPressed': () => Get.to(() => Passengrs(),
transition: Transition.rightToLeftWithFade)
},
{
'title': 'الكباتن',
'icon': Icons.sports_motorsports_outlined,
'onPressed': () =>
Get.to(() => Captain(), transition: Transition.rightToLeftWithFade)
},
{
'title': 'المحفظة',
'icon': Icons.account_balance_wallet_outlined,
'onPressed': () =>
Get.to(() => Wallet(), transition: Transition.rightToLeftWithFade)
},
{
'title': 'الرحلات',
'icon': Icons.directions_car_filled_outlined,
'onPressed': () =>
Get.to(() => Rides(), transition: Transition.rightToLeftWithFade)
},
{
'title': 'الإحصائيات',
'icon': Icons.bar_chart_outlined,
'onPressed': () async {
await Get.put(StaticController()).getAll();
Get.to(() => const StaticDash());
}
},
{
'title': 'إرسال واتساب للسائقين',
'icon': Icons.message_outlined,
'iconColor': Colors.green.shade600,
'onPressed': () => _showWhatsAppDialog(context)
},
{
'title': 'إرسال إشعار للسائقين',
'icon': Icons.notifications_active_outlined,
'onPressed': () async =>
await Get.put(NotificationController()).getTokensDrivers()
},
{
'title': 'إرسال إشعار للركاب',
'icon': Icons.notification_important_outlined,
'onPressed': () async =>
await Get.put(NotificationController()).getTokensPassengers()
},
{
'title': 'تسجيل كابتن جديد',
'icon': Icons.person_add_alt_1_outlined,
'onPressed': () async {
await Get.put(RegisterCaptainController())
.getDriverNotCompleteRegistration();
Get.to(() => const DriversCantRegister());
}
},
{
'title': 'تحديث الباقات',
'icon': Icons.inventory_2_outlined,
'onPressed': () => Get.to(() => PackageUpdateScreen())
},
{
'title': 'الموظفون',
'icon': Icons.badge_outlined,
'onPressed': () => Get.to(() => EmployeePage())
},
{
'title': 'أفضل السائقين',
'icon': Icons.star_border_purple500_outlined,
'onPressed': () => Get.to(() => DriverTheBest())
},
{
'title': 'إضافة فاتورة',
'icon': Icons.post_add_outlined,
// 'onPressed': () => Get.to(() => AddInvoicePage())
'onPressed': () => Get.to(() => InvoiceListPage())
},
{
'title': 'إضافة جهاز كمسؤول',
'icon': Icons.admin_panel_settings_outlined,
'onPressed': () async => await CRUD()
.post(link: AppLink.addAdminUser, payload: {'name': 'b'})
},
];
return MyScafolld(
title: 'لوحة التحكم الرئيسية',
action: IconButton(
onPressed: () async {
await dashboardController.getDashBoard();
},
icon: const Icon(Icons.refresh, color: AppColor.primaryColor, size: 28),
tooltip: 'تحديث',
),
body: [
GetBuilder<DashboardController>(builder: (controller) {
if (controller.dashbord.isEmpty) {
return const MyCircularProgressIndicator();
}
// Main data map for easier access
final data = controller.dashbord[0];
// Stat cards list with Arabic titles
final List<Map<String, dynamic>> statCards = [
{
'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
},
{
'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
},
{
'title': 'مدفوعات السائقين',
'value': _formatCurrency(data['payments']),
'icon': Icons.payments_outlined,
'color': Colors.indigo
},
{
'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 AnimationLimiter(
child: ListView(
padding:
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0),
children: [
// --- Statistics Grid Section ---
AnimationLimiter(
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: _calculateCrossAxisCount(context),
mainAxisSpacing: 12.0,
crossAxisSpacing: 12.0,
childAspectRatio: 1.8,
),
itemCount: statCards.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
final card = statCards[index];
return AnimationConfiguration.staggeredGrid(
position: index,
duration: const Duration(milliseconds: 375),
columnCount: _calculateCrossAxisCount(context),
child: ScaleAnimation(
child: FadeInAnimation(
child: DashboardStatCard(
title: card['title'] as String,
value: card['value'].toString(),
icon: card['icon'] as IconData,
iconColor: card['color'] as Color,
valueColor: (card['color'] as Color),
),
),
),
);
},
),
),
const SizedBox(height: 20),
Text("الإجراءات السريعة",
style: Theme.of(context)
.textTheme
.titleLarge
?.copyWith(fontWeight: FontWeight.bold)),
const SizedBox(height: 10),
// --- Admin Actions List Section ---
AnimationLimiter(
child: ListView.builder(
itemCount: actionItems.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
final item = actionItems[index];
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 375),
child: SlideAnimation(
verticalOffset: 50.0,
child: FadeInAnimation(
child: AdminActionTile(
title: item['title'] as String,
icon: item['icon'] as IconData,
onPressed: item['onPressed'] as void Function(),
iconColor: item['iconColor'] as Color?,
),
),
),
);
},
),
),
],
),
);
}),
],
isleading: false,
);
}
void _showWhatsAppDialog(BuildContext context) {
Get.dialog(
AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
title: Text('تأكيد إرسال الرسائل؟'),
content: MyTextForm(
controller: _messageController,
label: 'الرسالة',
hint: 'أدخل نص الرسالة هنا',
type: TextInputType.text,
),
actions: [
TextButton(
onPressed: () {
_messageController.clear();
Get.back();
},
child: Text('إلغاء'),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: AppColor.primaryColor),
onPressed: () async {
if (_messageController.text.isNotEmpty) {
Get.back(); // Close dialog first
var driverPhones =
box.read(BoxName.tokensDrivers)['message'] as List?;
if (driverPhones == null || driverPhones.isEmpty) {
Get.snackbar('خطأ', 'لم يتم العثور على أرقام هواتف للسائقين.',
snackPosition: SnackPosition.BOTTOM);
return;
}
for (var driverData in driverPhones) {
if (driverData['phone'] != null) {
await CRUD().sendWhatsAppAuth(
driverData['phone'].toString(),
_messageController.text,
);
// Random delay to avoid being flagged as spam
await Future.delayed(
Duration(seconds: Random().nextInt(5) + 2));
}
}
_messageController.clear();
Get.snackbar(
'نجاح',
'تم إرسال الرسائل بنجاح',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.green.shade100,
colorText: Colors.black,
);
}
},
child: Text('إرسال', style: TextStyle(color: Colors.white)),
),
],
),
barrierDismissible: false,
);
}
}
// Renamed for clarity and improved design
class AdminActionTile extends StatelessWidget {
const AdminActionTile({
super.key,
required this.title,
required this.onPressed,
required this.icon,
this.iconColor,
});
final String title;
final VoidCallback onPressed;
final IconData icon;
final Color? iconColor;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 6.0),
child: Material(
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(12.0),
child: InkWell(
onTap: onPressed,
borderRadius: BorderRadius.circular(12.0),
child: Container(
padding:
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 18.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
border: Border.all(color: Colors.grey.withOpacity(0.2))),
child: Row(
children: [
Icon(
icon,
size: 26,
color: iconColor ?? AppColor.primaryColor,
),
const SizedBox(width: 16),
Expanded(
child: Text(
title,
style: AppStyle.title.copyWith(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
),
const Icon(
Icons.arrow_forward_ios,
size: 16,
color: Colors.grey,
),
],
),
),
),
),
);
}
}

View File

@@ -0,0 +1,223 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../constant/colors.dart';
import '../../../constant/style.dart';
import '../../../controller/admin/captain_admin_controller.dart';
import '../../../controller/functions/encrypt_decrypt.dart';
import '../../widgets/elevated_btn.dart';
import '../../widgets/my_scafold.dart';
import '../../widgets/my_textField.dart';
import '../../widgets/mycircular.dart';
import 'captain_details.dart';
import 'form_captain.dart';
class Captain extends StatelessWidget {
Captain({super.key});
final CaptainAdminController captainAdminController =
Get.put(CaptainAdminController());
@override
Widget build(BuildContext context) {
return MyScafolld(
title: 'Captain'.tr,
body: [
GetBuilder<CaptainAdminController>(
builder: (captainAdminController) => Column(
children: [
captainAdminController.isLoading
? const MyCircularProgressIndicator()
: Column(
children: [
Padding(
padding: const EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
captainAdmin(
captainAdminController,
'Captains Count',
'countPassenger',
),
MyElevatedButton(
title: 'Add Prize to Gold Captains',
onPressed: () {
var date = DateTime.now();
var day = date.weekday;
if (day == 6) {
// Saturday is 6
Get.defaultDialog(
title:
'Add Prize to Gold Captains',
titleStyle: AppStyle.title,
content: Column(
children: [
Text(
'Add Points to their wallet as prize'
.tr,
style: AppStyle.title,
),
Form(
key: captainAdminController
.formCaptainPrizeKey,
child: MyTextForm(
controller:
captainAdminController
.captainPrizeController,
label:
'Count of prize'
.tr,
hint: 'Count of prize'
.tr,
type: TextInputType
.number))
],
),
confirm: MyElevatedButton(
title: 'Add',
onPressed: () async {
if (captainAdminController
.formCaptainPrizeKey
.currentState!
.validate()) {
captainAdminController
.addCaptainsPrizeToWalletSecure();
}
},
),
);
} else {
Get.defaultDialog(
title:
'This day is not allowed',
titleStyle: AppStyle.title,
middleText:
'Saturday only Allowed day',
middleTextStyle: AppStyle.title,
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.back();
}));
}
})
],
),
),
const SizedBox(
height: 10,
),
InkWell(
onTap: () {
//todo search
},
child: Padding(
padding: const EdgeInsets.all(3),
child: Container(
width: Get.width,
height: 110,
decoration: BoxDecoration(
border: Border.all(
width: 2,
color: AppColor.greenColor)),
child: formSearchCaptain()
// ],
// ),
),
),
),
SizedBox(
height: Get.height * .5,
child: ListView.builder(
itemCount: captainAdminController
.captainData['message'].length,
itemBuilder: (context, index) {
final user = captainAdminController
.captainData['message'][index];
return InkWell(
onTap: () {
Get.to(const CaptainsDetailsPage(),
arguments: {
'data': user,
});
},
child: Padding(
padding: const EdgeInsets.all(3),
child: Container(
decoration: BoxDecoration(
border: Border.all(width: 2)),
child: ListTile(
title: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(
'Name : ${(user['first_name'])} ${(user['last_name'])}',
style: AppStyle.title,
),
Text(
'Rating : ${user['ratingPassenger']}',
style: AppStyle.title,
),
],
),
subtitle: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(
'Count Trip : ${user['countPassengerRide']}',
style: AppStyle.title,
),
Text(
'Count Driver Rate : ${user['countDriverRate']}',
style: AppStyle.title,
),
],
),
),
),
),
);
},
),
),
],
),
],
))
],
isleading: true,
);
}
Container captainAdmin(CaptainAdminController captainAdminController,
String title, String jsonField) {
return Container(
height: Get.height * .1,
decoration: BoxDecoration(border: Border.all(width: 2)),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {},
child: Column(
children: [
Text(
title.tr,
style: AppStyle.title,
),
Text(
captainAdminController.captainData['message'][0][jsonField]
.toString(),
style: AppStyle.title,
),
],
),
),
),
);
}
}

View File

@@ -0,0 +1,167 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../constant/colors.dart';
import '../../../constant/style.dart';
import '../../../controller/admin/captain_admin_controller.dart';
import '../../../controller/firebase/firbase_messge.dart';
import '../../widgets/elevated_btn.dart';
import '../../widgets/my_scafold.dart';
import '../../widgets/my_textField.dart';
class CaptainsDetailsPage extends StatelessWidget {
const CaptainsDetailsPage({super.key});
@override
Widget build(BuildContext context) {
final arguments = Get.arguments;
final Map<String, dynamic> data = arguments['data'];
var key = Get.find<CaptainAdminController>().formCaptainPrizeKey;
var titleNotify = Get.find<CaptainAdminController>().titleNotify;
var bodyNotify = Get.find<CaptainAdminController>().bodyNotify;
return MyScafolld(
title: data['first_name'] + ' ' + data['last_name'],
body: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Email is ${data['email']}',
style: AppStyle.title,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Phone is ${data['phone']}',
style: AppStyle.title,
),
Text(
'gender is ${data['gender']}',
style: AppStyle.title,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'status is ${data['status']}',
style: AppStyle.title,
),
Text(
'birthdate is ${data['birthdate']}',
style: AppStyle.title,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'site is ${data['site']}',
style: AppStyle.title,
),
// Text(
// 'sosPhone is ${data['sosPhone']}',
// style: AppStyle.title,
// ),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Count Feedback is ${data['countFeedback']}',
style: AppStyle.title,
),
Text(
'Count Driver Rate is ${data['countDriverRate']}',
style: AppStyle.title,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Count Cancel is ${data['countPassengerCancel']}',
style: AppStyle.title,
),
Text(
'Count Ride is ${data['countPassengerRide']}',
style: AppStyle.title,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Rating Captain Avarage is ${data['passengerAverageRating']}',
style: AppStyle.title,
),
Text(
'Rating is ${data['ratingPassenger']}',
style: AppStyle.title,
),
],
),
Container(
decoration: BoxDecoration(
border: Border.all(width: 3, color: AppColor.yellowColor)),
child: TextButton(
onPressed: () async {
Get.defaultDialog(
title: 'Send Notification'.tr,
titleStyle: AppStyle.title,
content: Form(
key: key,
child: Column(
children: [
MyTextForm(
controller: titleNotify,
label: 'title'.tr,
hint: 'title notificaton'.tr,
type: TextInputType.name),
const SizedBox(
height: 10,
),
MyTextForm(
controller: bodyNotify,
label: 'body'.tr,
hint: 'body notificaton'.tr,
type: TextInputType.name)
],
),
),
confirm: MyElevatedButton(
title: 'Send',
onPressed: () {
if (key.currentState!.validate()) {
FirebaseMessagesController()
.sendNotificationToAnyWithoutData(
titleNotify.text,
bodyNotify.text,
data['passengerToken'],
'order.wav');
Get.back();
}
}));
},
child: Text(
"Send Notificaion to Captains ".tr,
style: AppStyle.title,
),
),
)
],
),
)
],
isleading: true,
);
}
}

View File

@@ -0,0 +1,54 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_admin1/views/admin/captain/register_captain.dart';
import 'package:sefer_admin1/views/widgets/my_scafold.dart';
import '../../../constant/colors.dart';
import '../../../controller/admin/register_captain_controller.dart';
class DriversCantRegister extends StatelessWidget {
const DriversCantRegister({super.key});
@override
Widget build(BuildContext context) {
Get.put(RegisterCaptainController());
return MyScafolld(
title: 'drivers cant register'.tr,
body: [
GetBuilder<RegisterCaptainController>(builder: (mainController) {
return ListView.builder(
itemCount: mainController.driverNotCompleteRegistration.length,
itemBuilder: (context, index) {
final driver =
mainController.driverNotCompleteRegistration[index];
return Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () {
Get.to(() => RegisterCaptain(), arguments: {
"phone_number": driver['phone_number'].toString(),
'driverId': driver['driverId'].toString(),
'email': driver['email'].toString(),
});
},
child: Container(
color: driver['note'] == null
? AppColor.greenColor
: AppColor.accentColor,
child: Column(
children: [
Text(driver['phone_number'].toString()),
Text(driver['driverId'].toString()),
Text(driver['email'].toString()),
],
),
),
),
);
},
);
}),
],
isleading: true);
}
}

View File

@@ -0,0 +1,84 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../constant/colors.dart';
import '../../../constant/style.dart';
import '../../../controller/admin/captain_admin_controller.dart';
import '../../widgets/elevated_btn.dart';
import 'captain_details.dart';
GetBuilder<CaptainAdminController> formSearchCaptain() {
// DbSql sql = DbSql.instance;
return GetBuilder<CaptainAdminController>(
builder: (controller) => Column(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Container(
decoration:
const BoxDecoration(color: AppColor.secondaryColor),
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(
borderRadius: BorderRadius.only(),
gapPadding: 4,
borderSide: BorderSide(
color: AppColor.redColor,
width: 2,
)),
suffixIcon: InkWell(
onTap: () async {
if (controller.captainController.text.length > 4) {
await controller.getCaptains();
Get.defaultDialog(
title: controller.captain['message'][0]
['email'],
titleStyle: AppStyle.title,
content: Column(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'Name is ${controller.captain['message'][0]['first_name']} ${controller.captain['message'][0]['last_name']}',
style: AppStyle.title,
),
Text(
'phone is ${controller.captain['message'][0]['phone']}',
style: AppStyle.title,
),
],
),
confirm: MyElevatedButton(
title: 'Go To Details'.tr,
onPressed: () {
Get.to(
() => const CaptainsDetailsPage(),
arguments: {
'data': controller
.captain['message'][0],
});
}));
}
},
child: const Icon(Icons.search)),
hintText: 'Search for Passenger'.tr,
hintStyle: AppStyle.title,
hintMaxLines: 1,
prefixIcon: IconButton(
onPressed: () async {
controller.captainController.clear();
// controller.clearPlaces();
},
icon: Icon(
Icons.clear,
color: Colors.red[300],
),
),
),
controller: controller.captainController,
),
),
)
],
));
}

View File

@@ -0,0 +1,982 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_admin1/controller/admin/register_captain_controller.dart';
import '../../../../constant/colors.dart';
import '../../../../constant/links.dart';
import '../../../../constant/style.dart';
import '../../widgets/elevated_btn.dart';
import '../../widgets/my_scafold.dart';
import '../../widgets/mycircular.dart';
class RegisterCaptain extends StatelessWidget {
RegisterCaptain({super.key});
@override
Widget build(BuildContext context) {
final controller = Get.put(RegisterCaptainController());
// String text = '';
controller.driveInit();
return MyScafolld(
title: 'Documents check'.tr,
action: GetBuilder<RegisterCaptainController>(builder: (controller) {
return IconButton(
onPressed: () {
controller.isLoading = false;
controller.update();
},
icon: const Icon(Icons.refresh),
);
}),
body: [
GetBuilder<RegisterCaptainController>(builder: (controller) {
return controller.isLoading
? const MyCircularProgressIndicator()
: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
(controller.responseIdCardDriverEgyptBack.isNotEmpty &&
controller.responseIdCardDriverEgyptFront
.isNotEmpty &&
controller.responseIdEgyptFront.isNotEmpty &&
controller.responseIdEgyptBack.isNotEmpty &&
controller
.responseIdEgyptDriverLicense.isNotEmpty
// &&
// controller
// .responseCriminalRecordEgypt.isNotEmpty
)
? MyElevatedButton(
title: 'Next'.tr,
onPressed: () {
controller.addDriverAndCarEgypt();
})
: const SizedBox(),
SizedBox(
height:
(controller.responseIdCardDriverEgyptBack
.isNotEmpty &&
controller.responseIdCardDriverEgyptFront
.isNotEmpty &&
controller
.responseIdEgyptFront.isNotEmpty &&
controller
.responseIdEgyptBack.isNotEmpty &&
controller.responseIdEgyptDriverLicense
.isNotEmpty
// &&
// controller.responseCriminalRecordEgypt
// .isNotEmpty
)
? Get.height * .7
: Get.height * .85,
child: ListView(
children: [
egyptDriverLicense(),
egyptCarLicenceFront(),
egyptCarLicenceBack(),
egyptDriverIDFront(),
egyptDriverIDBack(),
// egyptCriminalRecord(),
],
),
),
],
),
);
}),
],
isleading: true);
}
GetBuilder<RegisterCaptainController> egyptDriverLicense() {
return GetBuilder<RegisterCaptainController>(
builder: (ai) {
if (ai.responseIdEgyptDriverLicense.isNotEmpty) {
final expiryDate = ai.responseIdEgyptDriverLicense['expiry_date'];
// Check if the expiry date is before today
final today = DateTime.now();
// Try parsing the expiry date. If it fails, set it to null.
final expiryDateTime = DateTime.tryParse(expiryDate);
final isExpired =
expiryDateTime != null && expiryDateTime.isBefore(today);
return Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Driver\'s License'.tr, style: AppStyle.headTitle2),
IconButton(
onPressed: () async {
await ai.allMethodForAI("""
Write a JSON object from the following information extracted from the provided Arabic text:
{
"license_type": "",
"national_number": "",
"name_arabic": "",
"name_english": "",
"firstName": "",
"lastName": "",
"address": "",
"issue_date": "", // Format: YYYY-MM-DD using Latin numerals (0-9)
"expiry_date": "", // Format: YYYY-MM-DD using Latin numerals (0-9)
"employmentType": "",
"license_categories": []
}
Important notes:
1. Ensure all dates are in the format YYYY-MM-DD using Latin (Western) numerals (0-9), not Arabic numerals.
2. The 'license_categories' should be an array, even if there's only one category.
3. Fill in all fields based on the information provided in the Arabic text.
4. If any information is missing, leave the field as an empty string or empty array as appropriate.
""", 'driver_license', ai.driverId); //egypt
},
icon: const Icon(Icons.refresh),
),
],
),
const SizedBox(height: 8.0),
const Divider(color: AppColor.accentColor),
const SizedBox(height: 8.0),
Text(
'${'License Type'.tr}: ${ai.responseIdEgyptDriverLicense['license_type']}',
style: AppStyle.title,
),
const SizedBox(height: 8.0),
Text(
'${'National Number'.tr}: ${ai.responseIdEgyptDriverLicense['national_number']}',
style: AppStyle.title.copyWith(
color: ai.responseIdEgyptDriverLicense[
'national_number'] ==
ai.responseIdEgyptBack['nationalID']
? AppColor.greenColor
: AppColor.redColor),
),
const SizedBox(height: 8.0),
Text(
'${'Name (Arabic)'.tr}: ${ai.responseIdEgyptDriverLicense['name_arabic']}',
),
const SizedBox(height: 8.0),
Text(
'${'Name (English)'.tr}: ${ai.responseIdEgyptDriverLicense['name_english']}',
),
const SizedBox(height: 8.0),
Text(
'${'Address'.tr}: ${ai.responseIdEgyptDriverLicense['address']}',
),
const SizedBox(height: 8.0),
Text(
'${'Issue Date'.tr}: ${ai.responseIdEgyptDriverLicense['issue_date']}',
),
const SizedBox(height: 8.0),
Text(
'${'Expiry Date'.tr}: ${ai.responseIdEgyptDriverLicense['expiry_date']}',
style: AppStyle.title.copyWith(
color:
!isExpired ? AppColor.greenColor : AppColor.redColor,
),
),
const SizedBox(height: 8.0),
Text(
'${'License Categories'.tr}: ${ai.responseIdEgyptDriverLicense['license_categories']}',
),
],
),
),
);
}
return Card(
child: InkWell(
onTap: () async {
await ai.allMethodForAI("""
Write a JSON object from the following information extracted from the provided Arabic text:
{
"license_type": "",
"national_number": "",
"name_arabic": "",
"name_english": "",
"firstName": "",
"lastName": "",
"address": "",
"issue_date": "", // Format: YYYY-MM-DD using Latin numerals (0-9)
"expiry_date": "", // Format: YYYY-MM-DD using Latin numerals (0-9)
"employmentType": "",
"license_categories": []
}
Important notes:
1. Ensure all dates are in the format YYYY-MM-DD using Latin (Western) numerals (0-9), not Arabic numerals.
2. The 'license_categories' should be an array, even if there's only one category.
3. Fill in all fields based on the information provided in the Arabic text.
4. If any information is missing, leave the field as an empty string or empty array as appropriate.
""", 'driver_license', ai.driverId); //egypt
},
child: Column(
children: [
Image.network(
'${AppLink.server}/card_image/driver_license-${ai.driverId}.jpg',
height: Get.height * .25,
width: double.maxFinite,
fit: BoxFit.fitHeight,
),
Text(
'Capture an Image of Your Driver License'.tr,
style: AppStyle.title,
),
],
),
),
);
},
);
}
GetBuilder<RegisterCaptainController> egyptDriverIDBack() {
return GetBuilder<RegisterCaptainController>(
builder: (ai) {
if (ai.responseIdEgyptBack.isNotEmpty) {
final taxExpiryDate = ai.responseIdEgyptBack['expirationDate'];
// Check if the tax expiry date is before today
final today = DateTime.now();
// Try parsing the tax expiry date. If it fails, set it to null.
final taxExpiryDateTime = DateTime.tryParse(taxExpiryDate);
final isExpired =
taxExpiryDateTime != null && taxExpiryDateTime.isBefore(today);
return Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('ID Documents Back'.tr, style: AppStyle.headTitle2),
IconButton(
onPressed: () async {
await ai.allMethodForAI("""
Write a JSON from the following information extracted from the provided Arabic text:
- nationalID(in Latin numerals)
- issueDate (in format YYYY-MM-DD using Latin numerals)
- occupation
- gender
- religion
- maritalStatus
- fullNameMarital (if maritalStatus is "أعزب", set this to "none")
- expirationDate (in format YYYY-MM-DD using Latin numerals)
Please ensure all date fields use Latin (Western) numerals (0-9) instead of Arabic numerals. For example, use "2023-04-03" instead of "٢٠٢٣-٠٤-٠٣".
""", 'id_back', ai.driverId); //egypt
},
icon: const Icon(Icons.refresh),
),
],
),
const SizedBox(height: 8.0),
const Divider(color: AppColor.accentColor),
const SizedBox(height: 8.0),
// Assuming these keys exist in ai.responseIdEgyptFront
Text(
'${'National ID'.tr}: ${ai.responseIdEgyptBack['nationalID']}',
style: AppStyle.title.copyWith(
color: ai.responseIdEgyptDriverLicense[
'national_number'] ==
ai.responseIdEgyptBack['nationalID']
? AppColor.greenColor
: AppColor.redColor),
),
const SizedBox(height: 8.0),
Text(
'${'Occupation'.tr}: ${ai.responseIdEgyptBack['occupation']}', // Assuming 'occupation' exists
),
const SizedBox(height: 8.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${'Issue Date'.tr}: ${ai.responseIdEgyptBack['issueDate']}', // Assuming 'issueDate' exists
),
Text(
'${'Gender'.tr}: ${ai.responseIdEgyptBack['gender']}', // Assuming 'gender' exists
),
],
),
const SizedBox(height: 8.0),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// Text(
// '${'Religion'.tr}: ${ai.responseIdEgyptBack['religion']}', // Assuming 'religion' exists
// ),
// Text(
// '${'Marital Status'.tr}: ${ai.responseIdEgyptBack['maritalStatus']}', // Assuming 'maritalStatus' exists
// ),
// ],
// ),
// const SizedBox(height: 8.0),
// Text(
// '${'Full Name (Marital)'.tr}: ${ai.responseIdEgyptBack['fullNameMaritial']}', // Assuming 'fullNameMaritial' exists
// ),
// const SizedBox(height: 8.0),
Text(
'${'Expiration Date'.tr}: ${ai.responseIdEgyptBack['expirationDate']}', // Assuming 'expirationDate' exists
style: AppStyle.title.copyWith(
color: !isExpired
? AppColor.greenColor
: AppColor.redColor),
),
],
),
),
);
}
return Card(
child: InkWell(
onTap: () async {
await ai.allMethodForAI('''
Write a JSON object from the following information extracted from the provided Arabic text:
{
"nationalID": "",//(in Latin numerals)
"issueDate": "", // Format: YYYY-MM-DD using Latin numerals (0-9)
"occupation": "",
"gender": "",
"religion": "",
"maritalStatus": "",
"fullNameMaritial": "", // Set to "none" if maritalStatus is "أعزب"
"expirationDate": "" // Format: YYYY-MM-DD using Latin numerals (0-9)
}
Important notes:
1. Ensure all dates (issueDate and expirationDate) are in the format YYYY-MM-DD using Latin (Western) numerals (0-9), not Arabic numerals.
2. If maritalStatus is "أعزب" (single), set fullNameMaritial to "none".
3. Fill in all fields based on the information provided in the Arabic text.
4. If any information is missing, leave the field as an empty string.
''', 'id_back', ai.driverId); //egypt
},
child: Column(
children: [
Image.network(
'${AppLink.server}/card_image/id_back-${ai.driverId}.jpg',
height: Get.height * .25,
width: double.maxFinite,
fit: BoxFit.fitHeight,
),
Text(
'Capture an Image of Your ID Document Back'.tr,
style: AppStyle.title,
),
],
),
),
);
},
);
}
GetBuilder<RegisterCaptainController> egyptDriverIDFront() {
return GetBuilder<RegisterCaptainController>(
builder: (ai) {
if (ai.responseIdEgyptFront.isNotEmpty) {
return Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('ID Documents Front'.tr, style: AppStyle.headTitle2),
IconButton(
onPressed: () async {
await ai.allMethodForAI('''
Write a JSON object from the following information extracted from the provided Arabic text:
{
"first_name": "", // The word next to "بطاقة تحقيق الشخصية" (National Identification Card)
"full_name": "", // The full name on the next line after the first name
"address": "", // The complete address spanning the next two lines
"national_number": "", // The National ID number before the last line (convert Arabic numerals to Latin)
"card_id": "", // The card ID in English on the last line
"dob": "" // Year of birth only, in Latin numerals (YYYY format)
}
Important notes:
1. For 'first_name', extract the word immediately following "بطاقة تحقيق الشخصية".
2. 'full_name' should be the complete name found on the line after the first name.
3. 'address' should combine information from two consecutive lines.
4. Convert the 'national_number' from Arabic numerals to Latin numerals (0-9).
5. 'card_id' should be extracted as-is from the last line (it's already in English).
6. For 'dob', include only the year of birth in YYYY format using Latin numerals.
7. If any information is missing, leave the field as an empty string.
''', 'id_front', ai.driverId); //egypt
},
icon: const Icon(Icons.refresh),
),
],
),
const SizedBox(height: 8.0),
const Divider(color: AppColor.accentColor),
const SizedBox(height: 8.0),
// Removed Make, Model, etc. as they are not available
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${'First Name'.tr}: ${ai.responseIdEgyptFront['first_name']}',
),
Text(
'${'CardID'.tr}: ${ai.responseIdEgyptFront['card_id']}',
),
],
),
const SizedBox(height: 8.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${'Full Name'.tr}: ${ai.responseIdEgyptFront['full_name']}',
),
Text(
'${'DOB'.tr}: ${ai.responseIdEgyptFront['dob']}',
),
],
),
const SizedBox(height: 8.0),
Text(
'${'Address'.tr}: ${ai.responseIdEgyptFront['address']}',
),
const SizedBox(height: 8.0),
// Text(
// '${'National Number'.tr}: ${ai.responseIdEgyptFront['national_number']}',
// ),
// const SizedBox(height: 8.0),
// Removed Inspection Date as it's not available
],
),
),
);
}
return Card(
child: InkWell(
onTap: () async {
await ai.allMethodForAI(""""
Write a JSON object from the following information extracted from the provided Arabic text:
{
"first_name": "", // The word next to "بطاقة تحقيق الشخصية" (National Identification Card)
"full_name": "", // The full name on the next line after the first name
"address": "", // The complete address spanning the next two lines
"national_number": "", // The National ID number before the last line (convert Arabic numerals to Latin)
"card_id": "", // The card ID in English on the last line
"dob": "" // Year of birth only, in Latin numerals (YYYY format)
}
Important notes:
1. For 'first_name', extract the word immediately following "بطاقة تحقيق الشخصية".
2. 'full_name' should be the complete name found on the line after the first name.
3. 'address' should combine information from two consecutive lines.
4. Convert the 'national_number' from Arabic numerals to Latin numerals (0-9).
5. 'card_id' should be extracted as-is from the last line (it's already in English).
6. For 'dob', include only the year of birth in YYYY format using Latin numerals.
7. If any information is missing, leave the field as an empty string.
""", 'id_front', ai.driverId); //egypt
},
child: Column(
children: [
Image.network(
'${AppLink.server}/card_image/id_front-${ai.driverId}.png',
height: Get.height * .25,
width: double.maxFinite,
fit: BoxFit.fitHeight,
),
Text(
'Capture an Image of Your ID Document front'.tr,
style: AppStyle.title,
),
],
),
),
);
},
);
}
GetBuilder<RegisterCaptainController> egyptCarLicenceFront() {
return GetBuilder<RegisterCaptainController>(
builder: (ai) {
if (ai.responseIdCardDriverEgyptFront.isNotEmpty) {
// No need to access ai.responseIdCardDriverEgyptBack anymore
final licenseExpiryDate = DateTime.parse(
ai.responseIdCardDriverEgyptFront['LicenseExpirationDate']);
// Check if license has expired
final today = DateTime.now();
final isLicenseExpired = licenseExpiryDate.isBefore(today);
return Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text('Vehicle Details Front'.tr,
style: AppStyle.headTitle2),
IconButton(
onPressed: () async {
ai.allMethodForAI("""
Extract the following details from the provided car license data and format them into a JSON object:
License Expiration Date
Car Plate
Owner
Address
Car License Data:
JSON Format:
{
"LicenseExpirationDate": "YYYY-MM-DD",
"car_plate": "[Car plate number]",//the car plate is line next to line contain 'ادارة مرور' for bot numbers and letters in arabic with partition like| but you remove |
"owner": "[Owner's full name]",
"address": "[Address if available, otherwise 'Not provided']"
}
Important notes:
1. For the LicenseExpirationDate, ensure the date is in YYYY-MM-DD format using Latin numerals (0-9).
2. Replace all occurrences of '|' (pipe character) with a space in all fields.
3. If any information is missing, leave the corresponding field as an empty string.
4. Ensure all text is properly formatted and spaces are used correctly.
Please fill in the JSON object with the extracted information, following these guidelines.
""", 'car_front', ai.driverId);
},
icon: const Icon(Icons.refresh),
),
],
),
const SizedBox(height: 8.0),
const Divider(color: AppColor.accentColor),
const SizedBox(height: 8.0),
// Removed Make, Model, etc. as they are not available
Text(
'${'Plate Number'.tr}: ${ai.responseIdCardDriverEgyptFront['car_plate']}',
),
const SizedBox(height: 8.0),
Text(
'${'Owner Name'.tr}: ${ai.responseIdCardDriverEgyptFront['owner']}',
),
const SizedBox(height: 8.0),
Text(
'${'Address'.tr}: ${ai.responseIdCardDriverEgyptFront['address']}',
),
const SizedBox(height: 8.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${'License Expiry Date'.tr}: ${licenseExpiryDate.toString().substring(0, 10)}',
style: TextStyle(
color: isLicenseExpired ? Colors.red : Colors.green,
),
),
// Removed Fuel as it's not available
],
),
// Removed Inspection Date as it's not available
],
),
),
);
}
return Card(
child: InkWell(
onTap: () async {
ai.allMethodForAI("""
Extract the following details from the provided car license data and format them into a JSON object:
License Expiration Date
Car Plate
Owner
Address
Car License Data:
JSON Format:
{
"LicenseExpirationDate": "YYYY-MM-DD",
"car_plate": "[Car plate number]",//the car plate is line next to line contain 'ادارة مرور' for bot numbers and letters in arabic with partition like| but you remove |
"owner": "[Owner's full name]",
"address": "[Address if available, otherwise 'Not provided']"
}
Important notes:
1. For the LicenseExpirationDate, ensure the date is in YYYY-MM-DD format using Latin numerals (0-9).
2. Replace all occurrences of '|' (pipe character) with a space in all fields.
3. If any information is missing, leave the corresponding field as an empty string.
4. Ensure all text is properly formatted and spaces are used correctly.
Please fill in the JSON object with the extracted information, following these guidelines.
""", 'car_front', ai.driverId);
},
child: Column(
children: [
Image.network(
'${AppLink.server}/card_image/car_front-${ai.driverId}.jpg',
height: Get.height * .25,
width: double.maxFinite,
fit: BoxFit.fitHeight,
),
Text(
'Capture an Image of Your car license front '.tr,
style: AppStyle.title,
),
],
),
),
);
},
);
}
GetBuilder<RegisterCaptainController> egyptCarLicenceBack() {
return GetBuilder<RegisterCaptainController>(
builder: (ai) {
if (ai.responseIdCardDriverEgyptBack.isNotEmpty) {
// Get the tax expiry date from the response
final taxExpiryDate = ai.responseIdCardDriverEgyptBack['tax_expiry'];
// final displacement = ai.responseIdCardDriverEgyptBack['displacement'];
// if (int.parse(displacement) < 1000) {}
// Get the inspection date from the response
final inspectionDate =
ai.responseIdCardDriverEgyptBack['inspection_date'];
final year = int.parse(inspectionDate.split('-')[0]);
// Set inspectionDateTime to December 31st of the given year
final inspectionDateTime = DateTime(year, 12, 31);
String carBackLicenseExpired =
inspectionDateTime.toString().split(' ')[0];
// Get the current date
final today = DateTime.now();
// Try parsing the tax expiry date. If it fails, set it to null.
final taxExpiryDateTime = DateTime.tryParse(taxExpiryDate ?? '');
final isExpired =
taxExpiryDateTime != null && taxExpiryDateTime.isBefore(today);
// Check if the inspection date is before today
bool isInspectionExpired = inspectionDateTime.isBefore(today);
return Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Vehicle Details Back'.tr,
style: AppStyle.headTitle2),
IconButton(
onPressed: () async {
ai.allMethodForAI("""
Analyze the extracted car license information and create a JSON object with the following keys:
{
"make": "",
"year": "",
"chassis": "",
"model": "",
"engine": "",
"displacement": "",
"cylinders": "",
"fuel": "",
"color": "",
"color_hex": "",
"inspection_date": "",
"assuranceNumber": "",
"tax_expiry": ""
}
Important notes:
1. For dates (inspection_date and tax_expiry), use the format YYYY-MM-DD with Latin numerals (0-9).
2. Convert the color name to its corresponding hex color code for the 'color_hex' field.
3. Ensure all numeric values (year, displacement, cylinders) are in Latin numerals.
4. If any information is missing, leave the corresponding field as an empty string.
5. Do not include any explanatory text in the JSON fields, only the extracted values.
displacement in the line contain (سم٣ )
Please fill in the JSON object with the extracted information, following these guidelines.
""", 'car_back', ai.driverId);
},
icon: const Icon(Icons.refresh),
),
],
),
const SizedBox(height: 8.0),
const Divider(color: AppColor.accentColor),
const SizedBox(height: 8.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${'Make'.tr}: ${ai.responseIdCardDriverEgyptBack['make']}'),
Text(
'${'Model'.tr}: ${ai.responseIdCardDriverEgyptBack['model']}'),
],
),
const SizedBox(height: 8.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${'Year'.tr}: ${ai.responseIdCardDriverEgyptBack['year']}'),
Text(
'${'Chassis'.tr}: ${ai.responseIdCardDriverEgyptBack['chassis']}'),
],
),
const SizedBox(height: 8.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${'Color'.tr}: ${ai.responseIdCardDriverEgyptBack['color']}'),
Text(
'${'Displacement'.tr}: ${ai.responseIdCardDriverEgyptBack['displacement']} cc'),
],
),
const SizedBox(height: 8.0),
Text(
'${'Fuel'.tr}: ${ai.responseIdCardDriverEgyptBack['fuel']}'),
const SizedBox(height: 8.0),
if (taxExpiryDateTime != null)
Text(
'${'Tax Expiry Date'.tr}: $taxExpiryDate',
style: TextStyle(
color: isExpired ? Colors.red : Colors.green,
),
),
const SizedBox(height: 8.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${'Inspection Date'.tr}: $carBackLicenseExpired',
style: TextStyle(
color:
isInspectionExpired ? Colors.red : Colors.green,
),
),
],
),
],
),
),
);
}
return Card(
child: InkWell(
onTap: () async {
ai.allMethodForAI("""
Analyze the extracted car license information and create a JSON object with the following keys:
{
"make": "",
"year": "",
"chassis": "",
"model": "",
"engine": "",
"displacement": "",
"cylinders": "",
"fuel": "",
"color": "",
"color_hex": "",
"inspection_date": "",
"assuranceNumber": "",
"tax_expiry": ""
}
Important notes:
1. For dates (inspection_date and tax_expiry), use the format YYYY-MM-DD with Latin numerals (0-9).
2. Convert the color name to its corresponding hex color code for the 'color_hex' field.
3. Ensure all numeric values (year, displacement, cylinders) are in Latin numerals.
4. If any information is missing, leave the corresponding field as an empty string.
5. Do not include any explanatory text in the JSON fields, only the extracted values.
Please fill in the JSON object with the extracted information, following these guidelines.
""", 'car_back', ai.driverId);
},
child: Column(
children: [
Image.network(
'${AppLink.server}/card_image/car_back-${ai.driverId}.jpg',
height: Get.height * .25,
width: double.maxFinite,
fit: BoxFit.fitHeight,
),
Text(
'Capture an Image of Your car license back'.tr,
style: AppStyle.title,
),
],
),
),
);
},
);
}
GetBuilder<RegisterCaptainController> egyptCriminalRecord() {
return GetBuilder<RegisterCaptainController>(
builder: (ai) {
if (ai.responseCriminalRecordEgypt.isNotEmpty) {
return Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Criminal Record'.tr, style: AppStyle.headTitle2),
IconButton(
onPressed: () async {
await ai.allMethodForAI("""
Write a JSON object from the following information extracted from the provided Arabic text:
{
"InspectionResult": "",
"NationalID": "",
"FullName": "",
"IssueDate": "" // Format: YYYY-MM-DD
}
Important notes:
1. For the IssueDate, ensure the date is in YYYY-MM-DD format using Latin numerals (0-9).
2. Add appropriate spaces in all text fields to ensure readability.
3. If any information is missing, leave the corresponding field as an empty string.
4. Ensure all text is properly formatted and spaces are used correctly.
5. Convert any Arabic numerals to Latin numerals (0-9) where applicable.
Please fill in the JSON object with the extracted information, following these guidelines.
""", 'criminalRecord', ai.driverId);
},
icon: const Icon(Icons.refresh),
),
],
),
const SizedBox(height: 8.0),
const Divider(color: AppColor.accentColor),
const SizedBox(height: 8.0),
Text(
'${'InspectionResult'.tr}: ${ai.responseCriminalRecordEgypt['InspectionResult']}'),
const SizedBox(height: 8.0),
Text(
'${'FullName'.tr}: ${ai.responseCriminalRecordEgypt['FullName']}',
style: AppStyle.title.copyWith(
color: ai.responseCriminalRecordEgypt['FullName'] ==
ai.responseIdEgyptDriverLicense['name_arabic']
? AppColor.greenColor
: AppColor.redColor),
),
const SizedBox(height: 8.0),
Text(
'${'NationalID'.tr}: ${ai.responseCriminalRecordEgypt['NationalID']}'),
const SizedBox(height: 8.0),
Text(
'${'IssueDate'.tr}: ${ai.responseCriminalRecordEgypt['IssueDate']}'),
],
),
),
);
}
return Card(
child: InkWell(
onTap: () async {
await ai.allMethodForAI("""
Write a JSON object from the following information extracted from the provided Arabic text:
{
"InspectionResult": "",
"NationalID": "",
"FullName": "",
"IssueDate": "" // Format: YYYY-MM-DD
}
Important notes:
1. For the IssueDate, ensure the date is in YYYY-MM-DD format using Latin numerals (0-9).
2. Add appropriate spaces in all text fields to ensure readability.
3. If any information is missing, leave the corresponding field as an empty string.
4. Ensure all text is properly formatted and spaces are used correctly.
5. Convert any Arabic numerals to Latin numerals (0-9) where applicable.
Please fill in the JSON object with the extracted information, following these guidelines.
""", 'criminalRecord', ai.driverId);
},
child: Column(
children: [
Image.network(
'${AppLink.server}/card_image/6.png',
height: Get.height * .25,
width: double.maxFinite,
fit: BoxFit.fitHeight,
),
Text(
'Capture an Image of Your Criminal Record'.tr,
style: AppStyle.title,
),
],
),
),
);
},
);
}
}

View File

@@ -0,0 +1,94 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart'; // For Get.width if needed, and .tr
import 'package:sefer_admin1/constant/colors.dart'; // Assuming AppColor is here
import 'package:sefer_admin1/constant/style.dart'; // Assuming AppStyle is here
class DashboardStatCard extends StatelessWidget {
final String title;
final String value;
final IconData? icon;
final Color? iconColor;
final Color? backgroundColor;
final Color? valueColor;
const DashboardStatCard({
Key? key,
required this.title,
required this.value,
this.icon,
this.iconColor,
this.backgroundColor,
this.valueColor,
}) : super(key: key);
@override
Widget build(BuildContext context) {
// Attempt to use AppStyle.boxDecoration1 properties if it's a BoxDecoration
BoxDecoration? baseDecoration = AppStyle.boxDecoration1;
Color? finalBackgroundColor =
backgroundColor ?? baseDecoration?.color ?? Theme.of(context).cardColor;
BorderRadius? finalBorderRadius =
baseDecoration?.borderRadius?.resolve(Directionality.of(context)) ??
BorderRadius.circular(12.0);
return Container(
padding: const EdgeInsets.symmetric(horizontal: 14.0, vertical: 12.0),
decoration: BoxDecoration(
color: finalBackgroundColor,
borderRadius: finalBorderRadius,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.1),
spreadRadius: 1,
blurRadius: 6,
offset: const Offset(0, 2),
),
],
// If AppStyle.boxDecoration1 includes a border, you might want to add it here too
// border: baseDecoration?.border,
),
child: Column(
mainAxisAlignment:
MainAxisAlignment.center, // Center content vertically
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
child: Text(
title.tr,
style: AppStyle.title.copyWith(
fontSize: 13,
fontWeight: FontWeight.w500,
color: Theme.of(context).textTheme.bodySmall?.color,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
if (icon != null)
Icon(
icon,
size: 24,
color: iconColor ?? AppColor.primaryColor.withOpacity(0.7),
),
],
),
const SizedBox(height: 6),
Text(
value,
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: valueColor ?? AppColor.primaryColor,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
);
}
}

View File

@@ -0,0 +1,69 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_admin1/constant/links.dart';
import 'package:sefer_admin1/controller/functions/crud.dart';
import 'package:sefer_admin1/controller/functions/wallet.dart';
import 'package:sefer_admin1/views/widgets/my_scafold.dart';
import '../../../controller/drivers/driverthebest.dart';
class DriverTheBestAlexandria extends StatelessWidget {
const DriverTheBestAlexandria({super.key});
@override
Widget build(BuildContext context) {
Get.put(DriverTheBestAlexandriaController(), permanent: true);
return MyScafolld(
title: 'Alexandria'.tr,
body: [
GetBuilder<DriverTheBestAlexandriaController>(builder: (driverthebest) {
return driverthebest.driver.isNotEmpty
? ListView.builder(
itemCount: driverthebest.driver.length,
itemBuilder: (context, index) {
final driver = driverthebest.driver[index];
return ListTile(
leading: CircleAvatar(
child: Text(
((driver['driver_count'] * 5) / 3600)
.toStringAsFixed(0),
),
),
title: Text(driver['name_arabic'] ?? 'Unknown Name'),
subtitle: Text('Phone: ${driver['phone'] ?? 'N/A'}'),
trailing: IconButton(
onPressed: () async {
Get.defaultDialog(
title:
'are you sure to pay to this driver gift'.tr,
middleText: '',
onConfirm: () async {
final wallet = Get.put(WalletController());
await wallet.addPaymentToDriver('100',
driver['id'].toString(), driver['token']);
await wallet.addSeferWallet(
'100', driver['id'].toString());
await CRUD().post(
link: AppLink.deleteRecord,
payload: {
'driver_id': driver['id'].toString()
});
driverthebest.driver.removeAt(index);
driverthebest.update();
},
onCancel: () => Get.back());
},
icon: const Icon(Icons.wallet_giftcard_rounded),
),
);
},
)
: const Center(
child: Text('No drivers available.'),
);
})
],
isleading: true,
);
}
}

View File

@@ -0,0 +1,103 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_admin1/constant/links.dart';
import 'package:sefer_admin1/controller/functions/crud.dart';
import 'package:sefer_admin1/controller/functions/encrypt_decrypt.dart';
import 'package:sefer_admin1/controller/functions/wallet.dart';
import 'package:sefer_admin1/views/widgets/elevated_btn.dart';
import 'package:sefer_admin1/views/widgets/my_scafold.dart';
import '../../../controller/drivers/driverthebest.dart';
import 'alexandria.dart';
import 'giza.dart';
class DriverTheBest extends StatelessWidget {
const DriverTheBest({super.key});
@override
Widget build(BuildContext context) {
Get.put(Driverthebest(), permanent: true);
return MyScafolld(
title: 'Best Drivers'.tr,
body: [
GetBuilder<Driverthebest>(builder: (driverthebest) {
return driverthebest.driver.isNotEmpty
? Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
MyElevatedButton(
title: 'Giza',
onPressed: () {
Get.to(() => DriverTheBestGiza());
}),
MyElevatedButton(
title: 'Alexandria',
onPressed: () {
Get.to(() => DriverTheBestAlexandria());
}),
],
),
SizedBox(
height: Get.height * .7,
child: ListView.builder(
itemCount: driverthebest.driver.length,
itemBuilder: (context, index) {
final driver = driverthebest.driver[index];
return ListTile(
leading: CircleAvatar(
child: Text(
(int.parse(driver['driver_count']) * 5 / 3600)
.toStringAsFixed(
0), // Perform division first, then convert to string
),
),
title:
Text((driver['name_arabic']) ?? 'Unknown Name'),
subtitle:
Text('Phone: ${(driver['phone']) ?? 'N/A'}'),
trailing: IconButton(
onPressed: () async {
Get.defaultDialog(
title:
'are you sure to pay to this driver gift'
.tr,
middleText: '',
onConfirm: () async {
final wallet =
Get.put(WalletController());
await wallet.addPaymentToDriver(
'200',
driver['id'].toString(),
driver['token']);
await wallet.addSeferWallet(
'200', driver['id'].toString());
await CRUD().post(
link: AppLink.deleteRecord,
payload: {
'driver_id': driver['id'].toString()
});
driverthebest.driver.removeAt(index);
driverthebest.update();
Get.back();
},
onCancel: () => Get.back());
},
icon: const Icon(Icons.wallet_giftcard_rounded),
),
);
},
),
),
],
)
: const Center(
child: Text('No drivers available.'),
);
})
],
isleading: true,
);
}
}

View File

@@ -0,0 +1,69 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_admin1/constant/links.dart';
import 'package:sefer_admin1/controller/functions/crud.dart';
import 'package:sefer_admin1/controller/functions/wallet.dart';
import 'package:sefer_admin1/views/widgets/my_scafold.dart';
import '../../../controller/drivers/driverthebest.dart';
class DriverTheBestGiza extends StatelessWidget {
const DriverTheBestGiza({super.key});
@override
Widget build(BuildContext context) {
Get.put(DriverTheBestGizaController(), permanent: true);
return MyScafolld(
title: 'Giza'.tr,
body: [
GetBuilder<DriverTheBestGizaController>(builder: (driverthebest) {
return driverthebest.driver.isNotEmpty
? ListView.builder(
itemCount: driverthebest.driver.length,
itemBuilder: (context, index) {
final driver = driverthebest.driver[index];
return ListTile(
leading: CircleAvatar(
child: Text(
((driver['driver_count'] * 5) / 3600)
.toStringAsFixed(0),
),
),
title: Text(driver['name_arabic'] ?? 'Unknown Name'),
subtitle: Text('Phone: ${driver['phone'] ?? 'N/A'}'),
trailing: IconButton(
onPressed: () async {
Get.defaultDialog(
title:
'are you sure to pay to this driver gift'.tr,
middleText: '',
onConfirm: () async {
final wallet = Get.put(WalletController());
await wallet.addPaymentToDriver('100',
driver['id'].toString(), driver['token']);
await wallet.addSeferWallet(
'100', driver['id'].toString());
await CRUD().post(
link: AppLink.deleteRecord,
payload: {
'driver_id': driver['id'].toString()
});
driverthebest.driver.removeAt(index);
driverthebest.update();
},
onCancel: () => Get.back());
},
icon: const Icon(Icons.wallet_giftcard_rounded),
),
);
},
)
: const Center(
child: Text('No drivers available.'),
);
})
],
isleading: true,
);
}
}

View File

@@ -0,0 +1,186 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_admin1/constant/colors.dart';
import 'package:sefer_admin1/constant/style.dart';
import 'package:sefer_admin1/controller/employee_controller/employee_controller.dart';
import 'package:sefer_admin1/controller/functions/launch.dart';
import 'package:sefer_admin1/views/widgets/elevated_btn.dart';
import 'package:sefer_admin1/views/widgets/my_scafold.dart';
import 'package:sefer_admin1/views/widgets/my_textField.dart';
import '../../../constant/links.dart';
import '../../../controller/functions/upload_image copy.dart';
class EmployeePage extends StatelessWidget {
const EmployeePage({super.key});
@override
Widget build(BuildContext context) {
Get.put(EmployeeController());
return GetBuilder<EmployeeController>(builder: (employeeController) {
return Scaffold(
appBar: AppBar(
title: Text('Employee Page'.tr),
),
body: ListView.builder(
itemCount: employeeController
.employee.length, // Set the item count based on the employee list
itemBuilder: (context, index) {
// Get the employee data for the current index
var employee = employeeController.employee[index];
// Return a widget to display the employee information
return Padding(
padding: const EdgeInsets.all(3.0),
child: Container(
decoration: AppStyle.boxDecoration1,
child: ListTile(
trailing: IconButton(
onPressed: () {
Get.to(() => EmployeeDetails(
index: index,
));
},
icon: Icon(
Icons.shop_two,
color: employee['status'].toString().contains('ممتاز')
? AppColor.greenColor
: AppColor.accentColor,
),
),
title: Column(
children: [
Text(employee['name']),
Text(
'Phone: ${employee['phone']}\nEducation: ${employee['education']}'),
Text('Status: ${employee['status']}'),
],
), // Display employee name
onTap: () {
// Add any action you want when the employee is tapped
},
leading: IconButton(
onPressed: () {
makePhoneCall(employee['phone'].toString());
// launchCommunication(
// 'phone', employee['phone'].toString(), '');
},
icon: const Icon(Icons.phone),
),
),
),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
employeeController.id = employeeController.generateRandomId(8);
Get.to(
employeeFields(employeeController),
);
}, // Icon to display
backgroundColor: Colors.blue, // Button color (optional)
tooltip: 'Add Employee',
child: const Icon(Icons.add), // Tooltip text when long-pressed
),
);
});
}
Scaffold employeeFields(EmployeeController employeeController) {
return Scaffold(
appBar: AppBar(),
body: Form(
key: employeeController.formKey,
child: SizedBox(
height: 500,
child: ListView(
children: [
MyElevatedButton(
title: 'front id',
onPressed: () async {
await ImageController().choosImage(AppLink.uploadEgypt,
'idFrontEmployee', employeeController.id);
}),
MyElevatedButton(
title: 'back id',
onPressed: () async {
await ImageController().choosImage(AppLink.uploadEgypt,
'idbackEmployee', employeeController.id);
}),
MyTextForm(
controller: employeeController.name,
label: 'name',
hint: 'name',
type: TextInputType.name),
MyTextForm(
controller: employeeController.education,
label: 'education',
hint: 'education',
type: TextInputType.name),
MyTextForm(
controller: employeeController.site,
label: 'site',
hint: 'site',
type: TextInputType.name),
MyTextForm(
controller: employeeController.phone,
label: 'phone',
hint: 'phone',
type: TextInputType.phone),
MyTextForm(
controller: employeeController.status,
label: 'status',
hint: 'status',
type: TextInputType.name),
],
),
),
),
bottomNavigationBar: MyElevatedButton(
title: 'upload',
onPressed: () async {
if (employeeController.formKey.currentState!.validate()) {
await employeeController.addEmployee();
}
},
),
);
}
}
class EmployeeDetails extends StatelessWidget {
const EmployeeDetails({super.key, required this.index});
final int index;
@override
Widget build(BuildContext context) {
return MyScafolld(
title: 'Details',
isleading: true,
body: [
GetBuilder<EmployeeController>(builder: (employeeController) {
return Column(
children: [
SizedBox(
height: 200,
width: 400,
child: Image.network(
// https: //server.sefer.click/sefer.click/sefer/card_image/idFrontEmployee-GC15188P.jpg
'https://server.sefer.click/sefer.click/sefer/card_image/idFrontEmployee-${employeeController.employee[index]['id']}.jpg'),
),
const SizedBox(
height: 10,
),
SizedBox(
height: 200,
width: 400,
child: Image.network(
'https://server.sefer.click/sefer.click/sefer/card_image/idFrontEmployee-${employeeController.employee[index]['id']}.jpg'),
)
],
);
})
],
);
}
}

View File

@@ -0,0 +1,107 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:sefer_admin1/constant/links.dart';
import 'package:sefer_admin1/controller/functions/crud.dart';
import 'package:sefer_admin1/views/widgets/my_textField.dart';
import '../../print.dart';
class PackageUpdateScreen extends StatelessWidget {
final PackageController packageController = Get.put(PackageController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Package Update'),
),
body: GetBuilder<PackageController>(builder: (packageController) {
return Center(
child: ListView.builder(
itemCount: packageController.packages.length,
itemBuilder: (context, index) {
var package = packageController.packages[index];
return ListTile(
title: Text(package['appName']),
subtitle: Text(
'Platform: ${package['platform']} \nVersion: ${package['version']}'),
trailing: const Icon(Icons.update),
onTap: () {
Get.defaultDialog(
title: 'Update',
middleText: '',
content: Column(
children: [
Text(package['appName']),
Text(package['platform']),
Text(package['version']),
MyTextForm(
controller: packageController.versionController,
label: package['version'].toString(),
hint: package['version'].toString(),
type: const TextInputType.numberWithOptions(
decimal: true),
),
],
),
onConfirm: () async {
await packageController.updatePackages(
package['id'].toString(),
packageController.versionController.text.toString(),
);
},
onCancel: () {},
);
},
);
},
),
);
}),
);
}
}
class PackageController extends GetxController {
List packages = []; // Observable list to hold package info
var isLoading = false.obs;
final versionController = TextEditingController();
final formKey = GlobalKey<FormState>();
@override
void onInit() {
super.onInit();
fetchPackages();
}
// Method to fetch package data from API
fetchPackages() async {
var response = await CRUD().get(link: AppLink.getPackages, payload: {});
if (response != 'failure') {
var jsonData = jsonDecode(response);
packages = jsonData['message'];
update();
Log.print('jsonData: ${jsonData}');
}
}
updatePackages(String id, version) async {
var response = await CRUD().post(
link: AppLink.updatePackages,
payload: {
"id": id,
"version": version,
},
);
Log.print('response: ${response}');
if (response != 'failure') {
Get.back();
fetchPackages();
} else {
Get.snackbar('error', 'message');
}
}
}

View File

@@ -0,0 +1,86 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../constant/colors.dart';
import '../../../constant/style.dart';
import '../../../controller/admin/passenger_admin_controller.dart';
import '../../widgets/elevated_btn.dart';
import 'passenger_details_page.dart';
GetBuilder<PassengerAdminController> formSearchPassengers() {
// DbSql sql = DbSql.instance;
return GetBuilder<PassengerAdminController>(
builder: (controller) => Column(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Container(
decoration:
const BoxDecoration(color: AppColor.secondaryColor),
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(
borderRadius: BorderRadius.only(),
gapPadding: 4,
borderSide: BorderSide(
color: AppColor.redColor,
width: 2,
)),
suffixIcon: InkWell(
onTap: () async {
if (controller.passengerController.text.length >
4) {
await controller.getPassengers();
Get.defaultDialog(
title: controller.passengers['message'][0]
['email'],
titleStyle: AppStyle.title,
content: Column(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'Name is ${controller.passengers['message'][0]['first_name']} ${controller.passengers['message'][0]['last_name']}',
style: AppStyle.title,
),
Text(
'phone is ${controller.passengers['message'][0]['phone']}',
style: AppStyle.title,
),
],
),
confirm: MyElevatedButton(
title: 'Go To Details'.tr,
onPressed: () {
Get.to(
() => const PassengerDetailsPage(),
arguments: {
'data': controller
.passengers['message'][0],
});
}));
}
},
child: const Icon(Icons.search)),
hintText: 'Search for Passenger'.tr,
hintStyle: AppStyle.title,
hintMaxLines: 1,
prefixIcon: IconButton(
onPressed: () async {
controller.passengerController.clear();
controller.clearPlaces();
},
icon: Icon(
Icons.clear,
color: Colors.red[300],
),
),
),
controller: controller.passengerController,
),
),
)
],
));
}

View File

@@ -0,0 +1,205 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_admin1/controller/functions/encrypt_decrypt.dart';
import '../../../constant/style.dart';
import '../../../controller/admin/passenger_admin_controller.dart';
import '../../widgets/elevated_btn.dart';
import '../../widgets/my_scafold.dart';
import '../../widgets/my_textField.dart';
import '../../widgets/mycircular.dart';
import 'form_passenger.dart';
import 'passenger_details_page.dart';
class Passengrs extends StatelessWidget {
Passengrs({super.key});
final PassengerAdminController passengerAdminController =
Get.put(PassengerAdminController());
@override
Widget build(BuildContext context) {
return MyScafolld(
title: 'Passengrs'.tr,
isleading: true,
body: [
GetBuilder<PassengerAdminController>(
builder: (passengerAdminController) => Column(
children: [
passengerAdminController.isLoading
? const MyCircularProgressIndicator()
: Column(
children: [
Padding(
padding: const EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
passengerAdmin(
passengerAdminController,
'Passengers Count',
'countPassenger',
),
MyElevatedButton(
title: 'Add Prize to Gold Passengers',
onPressed: () {
var date = DateTime.now();
var day = date.weekday;
if (day == 6) {
// Saturday is 6
Get.defaultDialog(
title:
'Add Prize to Gold Passengers',
titleStyle: AppStyle.title,
content: Column(
children: [
Text(
'Add Points to their wallet as prize'
.tr,
style: AppStyle.title,
),
Form(
key:
passengerAdminController
.formPrizeKey,
child: MyTextForm(
controller:
passengerAdminController
.passengerPrizeController,
label:
'Count of prize'
.tr,
hint: 'Count of prize'
.tr,
type: TextInputType
.number))
],
),
confirm: MyElevatedButton(
title: 'Add',
onPressed: () async {
if (passengerAdminController
.formPrizeKey
.currentState!
.validate()) {
passengerAdminController
.addPassengerPrizeToWalletSecure();
}
},
),
);
} else {
Get.defaultDialog(
title:
'This day is not allowed',
titleStyle: AppStyle.title,
middleText:
'Saturday only Allowed day',
middleTextStyle: AppStyle.title,
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.back();
}));
}
})
],
),
),
const SizedBox(
height: 10,
),
formSearchPassengers(),
SizedBox(
height: Get.height * .5,
child: ListView.builder(
itemCount: passengerAdminController
.passengersData['message'].length,
itemBuilder: (context, index) {
final user = passengerAdminController
.passengersData['message'][index];
return InkWell(
onTap: () {
Get.to(const PassengerDetailsPage(),
arguments: {
'data': user,
});
},
child: Padding(
padding: const EdgeInsets.all(3),
child: Container(
decoration: BoxDecoration(
border: Border.all(width: 2)),
child: ListTile(
title: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(
'Name : ${(user['first_name'])} ${(user['last_name'])}',
style: AppStyle.title,
),
Text(
'Rating : ${user['ratingPassenger']}',
style: AppStyle.title,
),
],
),
subtitle: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(
'Count Trip : ${user['countPassengerRide']}',
style: AppStyle.title,
),
Text(
'Count Driver Rate : ${user['countDriverRate']}',
style: AppStyle.title,
),
],
),
),
),
),
);
},
),
),
],
),
],
))
],
);
}
Container passengerAdmin(PassengerAdminController passengerAdminController,
String title, String jsonField) {
return Container(
height: Get.height * .1,
decoration: BoxDecoration(border: Border.all(width: 2)),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {},
child: Column(
children: [
Text(
title.tr,
style: AppStyle.title,
),
Text(
passengerAdminController.passengersData['message'][0][jsonField]
.toString(),
style: AppStyle.title,
),
],
),
),
),
);
}
}

View File

@@ -0,0 +1,167 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../constant/colors.dart';
import '../../../constant/style.dart';
import '../../../controller/admin/passenger_admin_controller.dart';
import '../../../controller/firebase/firbase_messge.dart';
import '../../widgets/elevated_btn.dart';
import '../../widgets/my_scafold.dart';
import '../../widgets/my_textField.dart';
class PassengerDetailsPage extends StatelessWidget {
const PassengerDetailsPage({super.key});
@override
Widget build(BuildContext context) {
final arguments = Get.arguments;
final Map<String, dynamic> data = arguments['data'];
var key = Get.find<PassengerAdminController>().formPrizeKey;
var titleNotify = Get.find<PassengerAdminController>().titleNotify;
var bodyNotify = Get.find<PassengerAdminController>().bodyNotify;
return MyScafolld(
title: data['first_name'],
body: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Email is ${data['email']}',
style: AppStyle.title,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Phone is ${data['phone']}',
style: AppStyle.title,
),
Text(
'gender is ${data['gender']}',
style: AppStyle.title,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'status is ${data['status']}',
style: AppStyle.title,
),
Text(
'birthdate is ${data['birthdate']}',
style: AppStyle.title,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'site is ${data['site']}',
style: AppStyle.title,
),
Text(
'sosPhone is ${data['sosPhone']}',
style: AppStyle.title,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Count Feedback is ${data['countFeedback']}',
style: AppStyle.title,
),
Text(
'Count Driver Rate is ${data['countDriverRate']}',
style: AppStyle.title,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Count Cancel is ${data['countPassengerCancel']}',
style: AppStyle.title,
),
Text(
'Count Ride is ${data['countPassengerRide']}',
style: AppStyle.title,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Rating Captain Avarage is ${data['passengerAverageRating']}',
style: AppStyle.title,
),
Text(
'Rating is ${data['ratingPassenger']}',
style: AppStyle.title,
),
],
),
Container(
decoration: BoxDecoration(
border: Border.all(width: 3, color: AppColor.yellowColor)),
child: TextButton(
onPressed: () async {
Get.defaultDialog(
title: 'Send Notification'.tr,
titleStyle: AppStyle.title,
content: Form(
key: key,
child: Column(
children: [
MyTextForm(
controller: titleNotify,
label: 'title'.tr,
hint: 'title notificaton'.tr,
type: TextInputType.name),
const SizedBox(
height: 10,
),
MyTextForm(
controller: bodyNotify,
label: 'body'.tr,
hint: 'body notificaton'.tr,
type: TextInputType.name)
],
),
),
confirm: MyElevatedButton(
title: 'Send',
onPressed: () {
if (key.currentState!.validate()) {
FirebaseMessagesController()
.sendNotificationToAnyWithoutData(
titleNotify.text,
bodyNotify.text,
data['passengerToken'],
'order.wav');
Get.back();
}
}));
},
child: Text(
"Send Notificaion to Passenger ".tr,
style: AppStyle.title,
),
),
)
],
),
)
],
isleading: true,
);
}
}

View File

@@ -0,0 +1,236 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../constant/colors.dart';
import '../../../constant/style.dart';
import '../../../controller/admin/ride_admin_controller.dart';
import '../../widgets/my_scafold.dart';
import '../../widgets/mycircular.dart';
class Rides extends StatelessWidget {
Rides({super.key});
RideAdminController rideAdminController = Get.put(RideAdminController());
@override
Widget build(BuildContext context) {
return MyScafolld(title: 'Rides'.tr, isleading: true, body: [
GetBuilder<RideAdminController>(
builder: (rideAdminController) => rideAdminController.isLoading
? const Center(child: MyCircularProgressIndicator())
: Column(
children: [
SizedBox(
height: Get.height * .4,
child: LineChart(
duration: const Duration(milliseconds: 150),
curve: Curves.ease,
LineChartData(
lineBarsData: [
LineChartBarData(
spots: rideAdminController.chartData,
isCurved: true,
color: Colors.deepPurpleAccent, // Custom color
barWidth: 3, // Thinner line
dotData: const FlDotData(
show: true), // Show dots on each point
belowBarData: BarAreaData(
// Add gradient fill below the line
show: true,
color: AppColor.deepPurpleAccent,
),
isStrokeJoinRound: true,
shadow: const BoxShadow(
color: AppColor.yellowColor,
blurRadius: 4,
offset: Offset(2, 2),
),
),
],
showingTooltipIndicators: const [],
titlesData: FlTitlesData(
show: true,
topTitles: AxisTitles(
axisNameWidget: Text(
'Days',
style: AppStyle.title,
),
axisNameSize: 30,
sideTitles: const SideTitles(
reservedSize: 30, showTitles: true)),
bottomTitles: AxisTitles(
axisNameWidget: Text(
'Total Trips on month'.tr,
style: AppStyle.title,
),
axisNameSize: 30,
sideTitles: const SideTitles(
reservedSize: 30, showTitles: true)),
leftTitles: AxisTitles(
axisNameWidget: Text(
'Counts of Trips on month'.tr,
style: AppStyle.title,
),
axisNameSize: 30,
sideTitles: const SideTitles(
reservedSize: 30, showTitles: true)),
),
gridData: const FlGridData(
show: true,
),
borderData: FlBorderData(
show: true,
border: const Border(
bottom: BorderSide(color: AppColor.accentColor),
left: BorderSide(color: AppColor.accentColor),
),
),
),
),
),
// SizedBox(
// height: Get.height * .4,
// child: PieChart(
// PieChartData(
// sectionsSpace: 4, // Adjust spacing between sections
// centerSpaceRadius:
// 40, // Adjust radius of center space
// sections: [
// for (final rideData in rideAdminController.rideData)
// PieChartSectionData(
// value: rideData.ridesCount.toDouble(),
// title: '${rideData.day}', showTitle: true,
// titleStyle:
// AppStyle.subtitle, // Display day as title
// radius: 60, // Adjust radius of each section
// color:
// AppColor.deepPurpleAccent, // Custom color
// ),
// ],
// ),
// ),
// ),
// SizedBox(
// // height: 400,
// child: SfCartesianChart(
// legend: const Legend(
// isVisible: true,
// position: LegendPosition.bottom,
// overflowMode: LegendItemOverflowMode.wrap,
// textStyle: TextStyle(
// color: Colors.white,
// fontSize: 12,
// fontWeight: FontWeight.bold,
// ),
// ),
// borderWidth: 2,
// borderColor: AppColor.blueColor,
// plotAreaBorderColor: AppColor.deepPurpleAccent,
// enableAxisAnimation: true,
// primaryXAxis: CategoryAxis(
// borderColor: AppColor.accentColor, borderWidth: 2,
// title: AxisTitle(
// text: 'Total Trips on month'.tr,
// textStyle: AppStyle.title,
// ),
// // labelRotation: 45,
// majorGridLines: const MajorGridLines(width: 0),
// ),
// primaryYAxis: const NumericAxis(isVisible: false),
// series: <LineSeries<ChartDataS, String>>[
// LineSeries<ChartDataS, String>(
// dataSource: rideAdminController.chartDatasync,
// xValueMapper: (ChartDataS data, _) => '${data.day}',
// yValueMapper: (ChartDataS data, _) =>
// data.ridesCount,
// dataLabelSettings:
// const DataLabelSettings(isVisible: true),
// ),
// ],
// ),
// ),
const SizedBox(
height: 20,
),
Card(
elevation: 4,
color: AppColor.deepPurpleAccent,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Total Trips on this Month is ${rideAdminController.jsonResponse['message'][0]['current_month_rides_count']}',
style: AppStyle.title,
),
),
),
const SizedBox(
height: 20,
),
Card(
elevation: 4,
color: AppColor.yellowColor,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(
'Driver Average Duration: ${rideAdminController.ridesDetails[0]['driver_avg_duration']}',
style: AppStyle.subtitle,
),
Text(
'Number of Drivers: ${rideAdminController.ridesDetails[0]['num_Driver']}',
style: AppStyle.subtitle,
),
Text(
'Total Rides: ${rideAdminController.ridesDetails[0]['total_rides']}',
style: AppStyle.subtitle,
),
Text(
'Ongoing Rides: ${rideAdminController.ridesDetails[0]['ongoing_rides']}',
style: AppStyle.subtitle,
),
Text(
'Completed Rides: ${rideAdminController.ridesDetails[0]['completed_rides']}',
style: AppStyle.subtitle,
),
Text(
'Cancelled Rides: ${rideAdminController.ridesDetails[0]['cancelled_rides']}',
style: AppStyle.subtitle,
),
Text(
'Longest Duration: ${rideAdminController.ridesDetails[0]['longest_duration']}',
style: AppStyle.subtitle,
),
Text(
'Total Distance: ${rideAdminController.ridesDetails[0]['total_distance']} km',
style: AppStyle.subtitle,
),
Text(
'Average Distance: ${rideAdminController.ridesDetails[0]['average_distance']} km',
style: AppStyle.subtitle,
),
Text(
'Longest Distance: ${rideAdminController.ridesDetails[0]['longest_distance']} km',
style: AppStyle.subtitle,
),
Text(
'Total Driver Earnings: \$${rideAdminController.ridesDetails[0]['total_driver_earnings']}',
style: AppStyle.subtitle,
),
Text(
'Total Company Earnings: \$${rideAdminController.ridesDetails[0]['total_company_earnings']}',
style: AppStyle.subtitle,
),
Text(
'Company Percentage: ${rideAdminController.ridesDetails[0]['companyPercent']} %',
style: AppStyle.subtitle,
),
],
),
),
)
],
))
]);
}
}

View File

@@ -0,0 +1,575 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_admin1/constant/style.dart';
import 'package:sefer_admin1/controller/admin/static_controller.dart';
import 'package:sefer_admin1/views/widgets/mycircular.dart';
import '../../../constant/colors.dart';
import '../../widgets/my_scafold.dart';
class StaticDash extends StatelessWidget {
const StaticDash({super.key});
@override
Widget build(BuildContext context) {
Get.put(StaticController());
return MyScafolld(
title: 'Static Dash'.tr,
action: IconButton(
onPressed: () async {
await Get.put(StaticController()).getAll();
},
icon: const Icon(
Icons.replay_circle_filled_rounded,
color: AppColor.greenColor,
),
),
body: [
GetBuilder<StaticController>(builder: (staticController) {
return staticController.isLoading
? const MyCircularProgressIndicator()
: ListView(
children: [
SizedBox(
height: Get.height * .3,
width: double.maxFinite,
// decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(6),
child: Container(
decoration: AppStyle.boxDecoration1,
height: MediaQuery.of(context).size.height * 0.4,
child: LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
isStepLineChart: true,
spots:
staticController.chartDataPassengers,
isCurved: true,
color: Colors.blue, // Custom color
barWidth: 3, // Thinner line
dotData: const FlDotData(
show:
true), // Show dots on each point
belowBarData: BarAreaData(
show: true,
color: Colors.deepPurpleAccent
.withOpacity(
0.3), // Custom gradient color
),
isStrokeJoinRound: true,
shadow: const BoxShadow(
color: Colors.yellow,
blurRadius: 4,
offset: Offset(2, 2),
),
),
],
showingTooltipIndicators: const [],
titlesData: FlTitlesData(
show: true,
topTitles: AxisTitles(
axisNameWidget: Text(
'Days'.tr,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold),
),
axisNameSize: 30,
),
bottomTitles: AxisTitles(
axisNameWidget: Text(
'Total passengers on month ${staticController.totalMonthlyPassengers}'
.tr,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold),
),
axisNameSize: 30,
sideTitles: const SideTitles(
reservedSize: 30,
showTitles: true,
),
),
leftTitles: AxisTitles(
axisNameWidget: Text(
'Counts of Passengers on days'.tr,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold),
),
axisNameSize: 30,
sideTitles: const SideTitles(
reservedSize: 30,
showTitles: true,
),
),
),
gridData: const FlGridData(show: true),
borderData: FlBorderData(
show: true,
border: const Border(
bottom:
BorderSide(color: Colors.blueAccent),
left:
BorderSide(color: Colors.blueAccent),
),
),
),
),
),
)),
const SizedBox(
height: 5,
),
SizedBox(
height: Get.height * .3,
width: double.maxFinite,
// decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(6),
child: Container(
decoration: AppStyle.boxDecoration1,
height: MediaQuery.of(context).size.height * 0.4,
child: LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
isStepLineChart: true,
spots: staticController.chartDataDrivers,
isCurved: true,
color: Colors.blue, // Custom color
barWidth: 3, // Thinner line
dotData: const FlDotData(
show:
true), // Show dots on each point
belowBarData: BarAreaData(
show: true,
color: Colors.deepPurpleAccent
.withOpacity(
0.3), // Custom gradient color
),
isStrokeJoinRound: true,
shadow: const BoxShadow(
color: Colors.yellow,
blurRadius: 4,
offset: Offset(2, 2),
),
),
],
showingTooltipIndicators: const [],
titlesData: FlTitlesData(
show: true,
topTitles: AxisTitles(
axisNameWidget: Text(
'Days'.tr,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold),
),
axisNameSize: 30,
),
bottomTitles: AxisTitles(
axisNameWidget: Text(
'Total Drivers on month ${staticController.totalMonthlyDrivers}'
.tr,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold),
),
axisNameSize: 30,
sideTitles: const SideTitles(
reservedSize: 30,
showTitles: true,
),
),
leftTitles: AxisTitles(
axisNameWidget: Text(
'Counts of Drivers on days'.tr,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold),
),
axisNameSize: 30,
sideTitles: const SideTitles(
reservedSize: 30,
showTitles: true,
),
),
),
gridData: const FlGridData(show: true),
borderData: FlBorderData(
show: true,
border: const Border(
bottom:
BorderSide(color: Colors.blueAccent),
left:
BorderSide(color: Colors.blueAccent),
),
),
),
),
),
)),
const SizedBox(
height: 5,
),
SizedBox(
height: Get.height * .3,
width: double.maxFinite,
// decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(6),
child: Container(
decoration: AppStyle.boxDecoration1,
height: MediaQuery.of(context).size.height * 0.4,
child: LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
isStepLineChart: true,
spots: staticController.chartDataRides,
isCurved: true,
color: const Color.fromARGB(
255, 84, 181, 182), // Custom color
barWidth: 3, // Thinner line
dotData: const FlDotData(
show:
true), // Show dots on each point
belowBarData: BarAreaData(
show: true,
color: const Color.fromARGB(
255, 65, 144, 86)
.withOpacity(
0.3), // Custom gradient color
),
isStrokeJoinRound: true,
shadow: const BoxShadow(
color: Colors.yellow,
blurRadius: 4,
offset: Offset(2, 2),
),
),
],
showingTooltipIndicators: const [],
titlesData: FlTitlesData(
show: true,
topTitles: AxisTitles(
axisNameWidget: Text(
'Days'.tr,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold),
),
axisNameSize: 30,
),
bottomTitles: AxisTitles(
axisNameWidget: Text(
'Total Rides on month ${staticController.totalMonthlyRides}'
.tr,
style: AppStyle.subtitle,
),
axisNameSize: 30,
sideTitles: const SideTitles(
reservedSize: 30,
showTitles: true,
),
),
leftTitles: AxisTitles(
axisNameWidget: Text(
'Counts of Rides on days'.tr,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold),
),
axisNameSize: 30,
sideTitles: const SideTitles(
reservedSize: 30,
showTitles: true,
),
),
),
gridData: const FlGridData(show: true),
borderData: FlBorderData(
show: true,
border: const Border(
bottom:
BorderSide(color: Colors.blueAccent),
left:
BorderSide(color: Colors.blueAccent),
),
),
),
),
),
)),
const SizedBox(
height: 5,
),
SizedBox(
height: Get.height * .3,
width: double.maxFinite,
child: Padding(
padding: const EdgeInsets.all(6),
child: Container(
decoration: AppStyle.boxDecoration1,
height: MediaQuery.of(context).size.height * 0.4,
child: LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
spots: staticController
.chartDataEmployeeMaryam,
isCurved: true,
color:
Colors.blue, // Custom color for Maryam
barWidth: 3,
dotData: const FlDotData(show: true),
belowBarData: BarAreaData(
show: true,
color: Colors.blue.withOpacity(0.3)),
),
LineChartBarData(
spots:
staticController.chartDataEmployeeRawda,
isCurved: true,
color: Colors.red, // Custom color for Rawda
barWidth: 3,
dotData: const FlDotData(show: true),
belowBarData: BarAreaData(
show: true,
color: Colors.red.withOpacity(0.3)),
),
LineChartBarData(
spots:
staticController.chartDataEmployeeMena,
isCurved: true,
color:
Colors.green, // Custom color for Mena
barWidth: 3,
dotData: const FlDotData(show: true),
belowBarData: BarAreaData(
show: true,
color: Colors.green.withOpacity(0.3)),
),
LineChartBarData(
spots: staticController
.chartDataEmployeeSefer4,
isCurved: true,
color:
Colors.yellow, // Custom color for Mena
barWidth: 3,
dotData: const FlDotData(show: true),
belowBarData: BarAreaData(
show: true,
color: Colors.yellow.withOpacity(0.3)),
),
],
titlesData: const FlTitlesData(
bottomTitles: AxisTitles(
sideTitles: SideTitles(showTitles: true),
),
leftTitles: AxisTitles(
sideTitles: SideTitles(showTitles: true),
),
),
gridData: const FlGridData(show: true),
borderData: FlBorderData(show: true),
),
),
),
),
),
// SizedBox(
// height: Get.height * .3,
// width: double.maxFinite,
// // decoration: AppStyle.boxDecoration1,
// child: Padding(
// padding: const EdgeInsets.all(6),
// child: Container(
// decoration: AppStyle.boxDecoration1,
// height: MediaQuery.of(context).size.height * 0.4,
// child: LineChart(
// LineChartData(
// lineBarsData: [
// LineChartBarData(
// isStepLineChart: true,
// spots: staticController
// .chartDataDriversCalling,
// isCurved: true,
// color: Colors
// .deepPurpleAccent, // Custom color
// barWidth: 3, // Thinner line
// dotData: const FlDotData(
// show:
// true), // Show dots on each point
// belowBarData: BarAreaData(
// show: true,
// color: Colors.deepPurpleAccent
// .withOpacity(
// 0.3), // Custom gradient color
// ),
// isStrokeJoinRound: true,
// shadow: const BoxShadow(
// color: Colors.yellow,
// blurRadius: 4,
// offset: Offset(2, 2),
// ),
// ),
// ],
// showingTooltipIndicators: const [],
// titlesData: FlTitlesData(
// show: true,
// topTitles: AxisTitles(
// axisNameWidget: Text(
// 'Days'.tr,
// style: const TextStyle(
// fontSize: 14,
// fontWeight: FontWeight.bold),
// ),
// axisNameSize: 30,
// ),
// bottomTitles: AxisTitles(
// axisNameWidget: Text(
// 'Total Drivers on month are Calliing ${staticController.staticList[0]['totalMonthlyCallingDrivers']}'
// .tr,
// style: AppStyle.subtitle,
// ),
// axisNameSize: 30,
// sideTitles: const SideTitles(
// reservedSize: 30,
// showTitles: true,
// ),
// ),
// leftTitles: AxisTitles(
// axisNameWidget: Text(
// 'Counts of Drivers on days'.tr,
// style: const TextStyle(
// fontSize: 14,
// fontWeight: FontWeight.bold),
// ),
// axisNameSize: 30,
// sideTitles: const SideTitles(
// reservedSize: 30,
// showTitles: true,
// ),
// ),
// ),
// gridData: const FlGridData(show: true),
// borderData: FlBorderData(
// show: true,
// border: const Border(
// bottom:
// BorderSide(color: Colors.blueAccent),
// left:
// BorderSide(color: Colors.blueAccent),
// ),
// ),
// ),
// ),
// ),
// )),
// const SizedBox(
// height: 5,
// ),
SizedBox(
height: Get.height * .3,
width: double.maxFinite,
// decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(6),
child: Container(
decoration: AppStyle.boxDecoration1,
height: MediaQuery.of(context).size.height * 0.4,
child: LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
isStepLineChart: true,
spots: staticController
.chartDataDriversMatchingNotes,
isCurved: true,
color: Colors
.deepPurpleAccent, // Custom color
barWidth: 3, // Thinner line
dotData: const FlDotData(
show:
true), // Show dots on each point
belowBarData: BarAreaData(
show: true,
color: Colors.deepPurpleAccent
.withOpacity(
0.3), // Custom gradient color
),
isStrokeJoinRound: true,
shadow: const BoxShadow(
color: Colors.yellow,
blurRadius: 4,
offset: Offset(2, 2),
),
),
],
showingTooltipIndicators: const [],
titlesData: FlTitlesData(
show: true,
topTitles: AxisTitles(
axisNameWidget: Text(
'Days'.tr,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold),
),
axisNameSize: 30,
),
bottomTitles: AxisTitles(
axisNameWidget: Text(
'Total Drivers on month are register after calling ${staticController.staticList[0]['totalMonthlyMatchingNotes']}'
.tr,
style: AppStyle.subtitle,
),
axisNameSize: 30,
sideTitles: const SideTitles(
reservedSize: 30,
showTitles: true,
),
),
leftTitles: AxisTitles(
axisNameWidget: Text(
'Counts of Drivers on days'.tr,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold),
),
axisNameSize: 30,
sideTitles: const SideTitles(
reservedSize: 30,
showTitles: true,
),
),
),
gridData: const FlGridData(show: true),
borderData: FlBorderData(
show: true,
border: const Border(
bottom:
BorderSide(color: Colors.blueAccent),
left:
BorderSide(color: Colors.blueAccent),
),
),
),
),
),
)),
const SizedBox(
height: 5,
),
],
);
})
],
isleading: true);
}
}

View File

@@ -0,0 +1,83 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_admin1/constant/style.dart';
import 'package:sefer_admin1/views/widgets/elevated_btn.dart';
import 'package:sefer_admin1/views/widgets/mycircular.dart';
import '../../../controller/admin/wallet_admin_controller.dart';
import '../../widgets/my_scafold.dart';
class Wallet extends StatelessWidget {
Wallet({super.key});
WalletAdminController walletAdminController =
Get.put(WalletAdminController());
@override
Widget build(BuildContext context) {
return MyScafolld(
title: 'Wallet'.tr,
body: [
GetBuilder<WalletAdminController>(builder: (walletAdminController) {
return Center(
child: walletAdminController.isLoading
? const MyCircularProgressIndicator()
: Column(
children: [
MyElevatedButton(
title: 'Pay to them to banks'.tr,
onPressed: () async {
await walletAdminController.payToBankDriverAll();
}),
SizedBox(
height: Get.height * .8,
child: ListView.builder(
itemCount:
walletAdminController.driversWalletPoints.length,
itemBuilder: (BuildContext context, int index) {
var res = walletAdminController
.driversWalletPoints[index];
if (res != null && res['name_arabic'] != null) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: Container(
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'driver name: ${res['name_arabic'].toString()}'),
Text(
'Amount: ${res['total_amount'].toString()}'),
],
),
),
),
);
} else {
return Container(); // Return an empty container if the data is null
}
},
),
)
],
),
);
})
],
isleading: true,
action: IconButton(
onPressed: () async {
walletAdminController.getWalletForEachDriverToPay();
},
icon: const Icon(
Icons.refresh,
color: Colors.black,
),
),
);
}
}