add new featurs like new stat page

This commit is contained in:
Hamza-Ayed
2026-05-08 22:44:55 +03:00
parent efbc921273
commit 8f555691b9
33 changed files with 1194 additions and 585 deletions

View File

@@ -18,7 +18,7 @@ class HistoryCaptain extends StatelessWidget {
body: GetBuilder<HistoryCaptainController>(
builder: (controller) {
if (controller.isloading) {
return const Center(
return Center(
child: CircularProgressIndicator(
color: FinanceDesignSystem.primaryDark),
);
@@ -49,7 +49,7 @@ class HistoryCaptain extends StatelessWidget {
fit: StackFit.expand,
children: [
Container(
decoration: const BoxDecoration(
decoration: BoxDecoration(
gradient: FinanceDesignSystem.balanceGradient,
),
),
@@ -59,7 +59,7 @@ class HistoryCaptain extends StatelessWidget {
child: Icon(
Icons.history_rounded,
size: 200,
color: Colors.white.withOpacity(0.05),
color: Colors.white.withValues(alpha: 0.05),
),
),
Column(
@@ -77,7 +77,7 @@ class HistoryCaptain extends StatelessWidget {
Text(
'Total Rides'.tr,
style: TextStyle(
color: Colors.white.withOpacity(0.7),
color: Colors.white.withValues(alpha: 0.7),
fontSize: 14,
fontWeight: FontWeight.w500,
),
@@ -203,7 +203,7 @@ class _TripHistoryCard extends StatelessWidget {
borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.04),
color: Colors.black.withValues(alpha: 0.04),
blurRadius: 15,
offset: const Offset(0, 8),
),
@@ -227,10 +227,10 @@ class _TripHistoryCard extends StatelessWidget {
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: FinanceDesignSystem.primaryDark
.withOpacity(0.05),
.withValues(alpha: 0.05),
borderRadius: BorderRadius.circular(12),
),
child: const Icon(
child: Icon(
Icons.receipt_long_rounded,
color: FinanceDesignSystem.primaryDark,
size: 20,
@@ -242,7 +242,7 @@ class _TripHistoryCard extends StatelessWidget {
children: [
Text(
'${'OrderId'.tr} #${trip['order_id']}',
style: const TextStyle(
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: FinanceDesignSystem.primaryDark,
@@ -269,14 +269,14 @@ class _TripHistoryCard extends StatelessWidget {
children: [
Column(
children: [
const Icon(Icons.circle,
Icon(Icons.circle,
size: 12, color: FinanceDesignSystem.accentBlue),
Container(
width: 2,
height: 20,
color: Colors.grey.shade200,
),
const Icon(Icons.location_on_rounded,
Icon(Icons.location_on_rounded,
size: 14, color: FinanceDesignSystem.dangerRed),
],
),
@@ -315,7 +315,7 @@ class _TripHistoryCard extends StatelessWidget {
children: [
Text(
'${trip['price']} ${'SYP'.tr}',
style: const TextStyle(
style: TextStyle(
fontWeight: FontWeight.w900,
fontSize: 16,
color: FinanceDesignSystem.primaryDark,
@@ -381,10 +381,10 @@ class _TripHistoryCard extends StatelessWidget {
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(20),
border: Border.all(color: color.withOpacity(0.3), width: 1),
border: Border.all(color: color.withValues(alpha: 0.3), width: 1),
boxShadow: [
BoxShadow(
color: color.withOpacity(0.1),
color: color.withValues(alpha: 0.1),
blurRadius: 4,
offset: const Offset(0, 2),
),

View File

@@ -106,10 +106,10 @@ class AppDrawer extends StatelessWidget {
color: Colors.cyan,
onTap: () => Get.to(() => HelpCaptain())),
DrawerItem(
title: 'Referral Center'.tr,
icon: Icons.card_giftcard_rounded,
title: 'Invite Driver'.tr,
icon: Icons.person_add_rounded,
color: Colors.indigo,
onTap: () => Get.to(() => ReferralCenterPage())),
onTap: () => Get.to(() => InviteScreen())),
// DrawerItem(
// title: 'Maintenance Center'.tr,
// icon: Icons.build,
@@ -227,7 +227,7 @@ class _DrawerItemTile extends StatelessWidget {
leading: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: item.color.withOpacity(0.1),
color: item.color.withValues(alpha: 0.1),
shape: BoxShape.circle,
),
child: Icon(item.icon, color: item.color, size: 24),
@@ -240,13 +240,13 @@ class _DrawerItemTile extends StatelessWidget {
?.copyWith(fontWeight: FontWeight.w500),
),
onTap: () {
Get.back(); // لإغلاق القائمة عند الضغط
Navigator.pop(context); // لإغلاق القائمة عند الضغط بشكل آمن
Future.delayed(const Duration(milliseconds: 250), () {
item.onTap(); // الانتقال للصفحة بعد تأخير بسيط لإظهار الأنيميشن
});
},
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
splashColor: item.color.withOpacity(0.2),
splashColor: item.color.withValues(alpha: 0.2),
),
);
}
@@ -327,7 +327,7 @@ class UserHeader extends StatelessWidget {
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 2),
boxShadow: [
BoxShadow(color: Colors.black.withOpacity(0.3), blurRadius: 5)
BoxShadow(color: Colors.black.withValues(alpha: 0.3), blurRadius: 5)
],
),
child: controller.isloading
@@ -377,19 +377,22 @@ class UserHeader extends StatelessWidget {
),
),
otherAccountsPictures: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
homeCaptainController.rating.toString(),
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 16),
),
const SizedBox(width: 4),
const Icon(Icons.star, color: Colors.amber, size: 20),
],
SizedBox(
width: 60,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
homeCaptainController.rating.toString(),
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 14),
),
const SizedBox(width: 2),
const Icon(Icons.star, color: Colors.amber, size: 16),
],
),
),
],
decoration: BoxDecoration(

View File

@@ -299,37 +299,38 @@ class _MapView extends StatelessWidget {
return GetBuilder<HomeCaptainController>(
builder: (ctrl) {
if (ctrl.isLoading) return const MyCircularProgressIndicator();
final s = Get.find<SettingController>();
return GetBuilder<LocationController>(
builder: (loc) => IntaleqMap(
apiKey: Env.mapSaasKey,
onMapCreated: ctrl.onMapCreated,
minMaxZoomPreference: const MinMaxZoomPreference(6, 18),
initialCameraPosition: CameraPosition(
target: (loc.myLocation.latitude == 0 ||
loc.myLocation.latitude.isNaN)
? ctrl.myLocation
: loc.myLocation,
zoom: 15,
return GetBuilder<SettingController>(
builder: (s) => GetBuilder<LocationController>(
builder: (loc) => IntaleqMap(
apiKey: Env.mapSaasKey,
onMapCreated: ctrl.onMapCreated,
minMaxZoomPreference: const MinMaxZoomPreference(6, 18),
initialCameraPosition: CameraPosition(
target: (loc.myLocation.latitude == 0 ||
loc.myLocation.latitude.isNaN)
? ctrl.myLocation
: loc.myLocation,
zoom: 15,
),
mapType:
s.isMapDarkMode ? IntaleqMapType.normal : IntaleqMapType.light,
polygons: ctrl.heatmapPolygons,
markers: {
Marker(
markerId: MarkerId('MyLocation'.tr),
position: loc.myLocation,
rotation: loc.heading,
flat: true,
anchor: const Offset(0.5, 0.5),
icon: ctrl.carIcon,
)
},
myLocationButtonEnabled: false,
myLocationEnabled: false,
compassEnabled: false,
zoomControlsEnabled: false,
),
mapType:
s.isMapDarkMode ? IntaleqMapType.normal : IntaleqMapType.light,
polygons: ctrl.heatmapPolygons,
markers: {
Marker(
markerId: MarkerId('MyLocation'.tr),
position: loc.myLocation,
rotation: loc.heading,
flat: true,
anchor: const Offset(0.5, 0.5),
icon: ctrl.carIcon,
)
},
myLocationButtonEnabled: false,
myLocationEnabled: false,
compassEnabled: false,
zoomControlsEnabled: false,
),
);
},

View File

@@ -12,9 +12,9 @@ class SchedulePage extends StatelessWidget {
return Scaffold(
backgroundColor: FinanceDesignSystem.backgroundColor,
appBar: AppBar(
title: Text('My Schedule'.tr, style: const TextStyle(fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)),
title: Text('My Schedule'.tr, style: TextStyle(fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)),
backgroundColor: Colors.transparent, elevation: 0, centerTitle: true,
leading: IconButton(icon: const Icon(Icons.arrow_back_ios_new_rounded, color: FinanceDesignSystem.primaryDark, size: 20), onPressed: () => Get.back()),
leading: IconButton(icon: Icon(Icons.arrow_back_ios_new_rounded, color: FinanceDesignSystem.primaryDark, size: 20), onPressed: () => Get.back()),
),
body: GetBuilder<ScheduleController>(builder: (sc) {
return SingleChildScrollView(
@@ -29,14 +29,14 @@ class SchedulePage extends StatelessWidget {
),
child: Row(children: [
Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text('Weekly Plan'.tr, style: TextStyle(color: Colors.white.withOpacity(0.7), fontSize: 14)),
Text('Weekly Plan'.tr, style: TextStyle(color: Colors.white.withValues(alpha: 0.7), fontSize: 14)),
const SizedBox(height: 8),
Text('${sc.totalWeeklyHours.toStringAsFixed(1)}h', style: const TextStyle(fontSize: 32, fontWeight: FontWeight.w900, color: Colors.white)),
Text('${sc.activeDays} ${'Days'.tr}', style: TextStyle(color: Colors.white.withOpacity(0.6), fontSize: 13)),
Text('${sc.activeDays} ${'Days'.tr}', style: TextStyle(color: Colors.white.withValues(alpha: 0.6), fontSize: 13)),
])),
Container(
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(color: Colors.white.withOpacity(0.15), borderRadius: BorderRadius.circular(14)),
decoration: BoxDecoration(color: Colors.white.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(14)),
child: const Icon(Icons.calendar_today_rounded, color: Colors.white, size: 28),
),
]),
@@ -61,7 +61,7 @@ class SchedulePage extends StatelessWidget {
decoration: BoxDecoration(
color: slot.isActive ? Colors.white : Colors.grey.shade50,
borderRadius: BorderRadius.circular(14),
boxShadow: slot.isActive ? [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 8, offset: const Offset(0, 3))] : null,
boxShadow: slot.isActive ? [BoxShadow(color: Colors.black.withValues(alpha: 0.03), blurRadius: 8, offset: const Offset(0, 3))] : null,
),
child: Row(children: [
// Toggle
@@ -71,7 +71,7 @@ class SchedulePage extends StatelessWidget {
duration: const Duration(milliseconds: 200),
width: 44, height: 44,
decoration: BoxDecoration(
color: slot.isActive ? FinanceDesignSystem.accentBlue.withOpacity(0.1) : Colors.grey.shade200,
color: slot.isActive ? FinanceDesignSystem.accentBlue.withValues(alpha: 0.1) : Colors.grey.shade200,
borderRadius: BorderRadius.circular(12),
),
child: Center(child: Text(
@@ -102,7 +102,7 @@ class SchedulePage extends StatelessWidget {
Switch(
value: slot.isActive,
onChanged: (_) => sc.toggleDay(slot.dayOfWeek),
activeColor: FinanceDesignSystem.accentBlue,
activeThumbColor: FinanceDesignSystem.accentBlue,
),
]),
);

View File

@@ -1,8 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:sefer_driver/constant/colors.dart';
import 'package:sefer_driver/constant/style.dart';
import 'package:sefer_driver/constant/finance_design_system.dart';
import 'package:sefer_driver/views/widgets/mycircular.dart';
import '../../../controller/payment/driver_payment_controller.dart';
@@ -19,12 +17,12 @@ class PaymentHistoryDriverPage extends StatelessWidget {
backgroundColor: FinanceDesignSystem.backgroundColor,
appBar: AppBar(
title: Text('Payment History'.tr,
style: const TextStyle(fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)),
style: TextStyle(fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)),
backgroundColor: Colors.transparent,
elevation: 0,
centerTitle: true,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios_new_rounded, color: FinanceDesignSystem.primaryDark, size: 20),
icon: Icon(Icons.arrow_back_ios_new_rounded, color: FinanceDesignSystem.primaryDark, size: 20),
onPressed: () => Get.back(),
),
),

View File

@@ -3,8 +3,6 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:local_auth/local_auth.dart';
import 'package:sefer_driver/constant/colors.dart';
import 'package:sefer_driver/constant/style.dart';
import 'package:sefer_driver/controller/home/payment/captain_wallet_controller.dart';
import 'package:sefer_driver/controller/payment/payment_controller.dart';
import 'package:sefer_driver/controller/payment/smsPaymnet/payment_services.dart';
@@ -45,7 +43,7 @@ class PointsCaptain extends StatelessWidget {
color: Colors.white,
borderRadius: BorderRadius.circular(20),
elevation: 4,
shadowColor: kolor.withOpacity(0.3),
shadowColor: kolor.withValues(alpha: 0.3),
child: InkWell(
onTap: () => _showPaymentOptions(context),
borderRadius: BorderRadius.circular(20),
@@ -58,11 +56,12 @@ class PointsCaptain extends StatelessWidget {
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
kolor.withOpacity(0.05),
kolor.withValues(alpha: 0.05),
Colors.white,
],
),
border: Border.all(color: kolor.withOpacity(0.2), width: 1.5),
border:
Border.all(color: kolor.withValues(alpha: 0.2), width: 1.5),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
@@ -70,7 +69,7 @@ class PointsCaptain extends StatelessWidget {
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: kolor.withOpacity(0.1),
color: kolor.withValues(alpha: 0.1),
shape: BoxShape.circle,
),
child: Icon(Icons.account_balance_wallet_rounded,
@@ -79,7 +78,7 @@ class PointsCaptain extends StatelessWidget {
const SizedBox(height: 10),
Text(
'$countPoint ${'SYP'.tr}',
style: const TextStyle(
style: TextStyle(
fontWeight: FontWeight.w900,
fontSize: 15,
color: FinanceDesignSystem.primaryDark,
@@ -110,9 +109,9 @@ class PointsCaptain extends StatelessWidget {
maxHeight: MediaQuery.of(context).size.height * 0.8,
),
padding: const EdgeInsets.fromLTRB(24, 24, 24, 32),
decoration: const BoxDecoration(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(32)),
borderRadius: const BorderRadius.vertical(top: Radius.circular(32)),
),
child: SingleChildScrollView(
child: Column(
@@ -131,8 +130,7 @@ class PointsCaptain extends StatelessWidget {
],
),
const SizedBox(height: 8),
Text(
"${'Amount to charge:'.tr} $countPoint ${'SYP'.tr}",
Text("${'Amount to charge:'.tr} $countPoint ${'SYP'.tr}",
style: FinanceDesignSystem.subHeadingStyle),
const SizedBox(height: 24),
_buildPaymentMethodTile(
@@ -211,7 +209,7 @@ class PointsCaptain extends StatelessWidget {
borderRadius: BorderRadius.circular(14),
boxShadow: [
BoxShadow(
color: color.withOpacity(0.1),
color: color.withValues(alpha: 0.1),
blurRadius: 10,
offset: const Offset(0, 4),
),
@@ -227,7 +225,7 @@ class PointsCaptain extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title,
style: const TextStyle(
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
color: FinanceDesignSystem.primaryDark)),
@@ -285,8 +283,7 @@ class PaymentScreen extends StatefulWidget {
final String countPrice;
const PaymentScreen(
{required this.iframeUrl, Key? key, required this.countPrice})
: super(key: key);
{required this.iframeUrl, super.key, required this.countPrice});
@override
State<PaymentScreen> createState() => _PaymentScreenState();
@@ -439,8 +436,7 @@ class PaymentScreenWallet extends StatefulWidget {
final String countPrice;
const PaymentScreenWallet(
{required this.iframeUrl, Key? key, required this.countPrice})
: super(key: key);
{required this.iframeUrl, super.key, required this.countPrice});
@override
State<PaymentScreenWallet> createState() => _PaymentScreenWalletState();
@@ -472,7 +468,7 @@ class _PaymentScreenWalletState extends State<PaymentScreenWallet> {
}
Future<void> _fetchPaymentStatus() async {
final String userId = '+963' + box.read(BoxName.phoneWallet);
final String userId = '+963${box.read(BoxName.phoneWallet)}';
await Future.delayed(const Duration(seconds: 2));
try {

View File

@@ -36,20 +36,20 @@ class WalletCaptainRefactored extends StatelessWidget {
backgroundColor: FinanceDesignSystem.backgroundColor,
appBar: AppBar(
title: Text('Driver Balance'.tr,
style: const TextStyle(
style: TextStyle(
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.primaryDark)),
backgroundColor: Colors.transparent,
elevation: 0,
centerTitle: true,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios_new_rounded,
icon: Icon(Icons.arrow_back_ios_new_rounded,
color: FinanceDesignSystem.primaryDark, size: 20),
onPressed: () => Get.back(),
),
actions: [
IconButton(
icon: const Icon(Icons.refresh_rounded,
icon: Icon(Icons.refresh_rounded,
color: FinanceDesignSystem.primaryDark),
onPressed: () => controller.refreshCaptainWallet(),
tooltip: 'Refresh'.tr,
@@ -204,7 +204,7 @@ class WalletCaptainRefactored extends StatelessWidget {
Get.to(() => const PaymentHistoryDriverPage());
},
child: Text('View All'.tr,
style: const TextStyle(
style: TextStyle(
color: FinanceDesignSystem.accentBlue,
fontWeight: FontWeight.bold)),
),
@@ -255,9 +255,9 @@ class WalletCaptainRefactored extends StatelessWidget {
Get.bottomSheet(
Container(
padding: const EdgeInsets.all(24),
decoration: const BoxDecoration(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
borderRadius: const BorderRadius.vertical(top: Radius.circular(24)),
),
child: Column(
mainAxisSize: MainAxisSize.min,
@@ -272,9 +272,10 @@ class WalletCaptainRefactored extends StatelessWidget {
leading: Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: FinanceDesignSystem.accentBlue.withOpacity(0.1),
color:
FinanceDesignSystem.accentBlue.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(12)),
child: const Icon(Icons.account_balance_wallet_rounded,
child: Icon(Icons.account_balance_wallet_rounded,
color: FinanceDesignSystem.accentBlue),
),
title: Text("Pay from my budget".tr),

View File

@@ -1,9 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:sefer_driver/constant/colors.dart';
import 'package:sefer_driver/constant/style.dart';
import 'package:get/get.dart';
import 'package:sefer_driver/constant/finance_design_system.dart';
import 'package:sefer_driver/views/widgets/mycircular.dart';
import '../../../controller/payment/driver_payment_controller.dart';
@@ -20,12 +17,15 @@ class WeeklyPaymentPage extends StatelessWidget {
backgroundColor: FinanceDesignSystem.backgroundColor,
appBar: AppBar(
title: Text('Weekly Summary'.tr,
style: const TextStyle(fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)),
style: TextStyle(
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.primaryDark)),
backgroundColor: Colors.transparent,
elevation: 0,
centerTitle: true,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios_new_rounded, color: FinanceDesignSystem.primaryDark, size: 20),
icon: Icon(Icons.arrow_back_ios_new_rounded,
color: FinanceDesignSystem.primaryDark, size: 20),
onPressed: () => Get.back(),
),
),
@@ -45,9 +45,11 @@ class WeeklyPaymentPage extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Row(
children: [
Text('Transactions this week'.tr, style: FinanceDesignSystem.headingStyle),
Text('Transactions this week'.tr,
style: FinanceDesignSystem.headingStyle),
const Spacer(),
Icon(Icons.list_rounded, color: Colors.grey.shade400, size: 20),
Icon(Icons.list_rounded,
color: Colors.grey.shade400, size: 20),
],
),
),
@@ -61,7 +63,9 @@ class WeeklyPaymentPage extends StatelessWidget {
itemCount: controller.weeklyList.length,
itemBuilder: (BuildContext context, int index) {
final tx = controller.weeklyList[index];
final double amount = double.tryParse(tx['amount']?.toString() ?? '0') ?? 0;
final double amount = double.tryParse(
tx['amount']?.toString() ?? '0') ??
0;
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 250),
@@ -69,10 +73,12 @@ class WeeklyPaymentPage extends StatelessWidget {
verticalOffset: 25,
child: FadeInAnimation(
child: TransactionPreviewItem(
title: amount >= 0 ? 'Credit'.tr : 'Debit'.tr,
title:
amount >= 0 ? 'Credit'.tr : 'Debit'.tr,
subtitle: tx['dateUpdated'] ?? '',
amount: amount.abs().toStringAsFixed(0),
date: tx['dateUpdated']?.split(' ')[0] ?? '',
date:
tx['dateUpdated']?.split(' ')[0] ?? '',
type: amount >= 0 ? 'credit' : 'debit',
method: tx['paymentMethod'],
onTap: () {},
@@ -95,7 +101,7 @@ class WeeklyPaymentPage extends StatelessWidget {
final totalAmount = controller.weeklyList.isEmpty
? '0.00'
: controller.weeklyList[0]['totalAmount']?.toString() ?? '0.00';
final double earnings = double.tryParse(totalAmount) ?? 0;
final int trips = controller.weeklyList.length;
final double commission = earnings * 0.15; // Example 15%
@@ -109,7 +115,7 @@ class WeeklyPaymentPage extends StatelessWidget {
borderRadius: BorderRadius.circular(24),
boxShadow: [
BoxShadow(
color: FinanceDesignSystem.primaryDark.withOpacity(0.3),
color: FinanceDesignSystem.primaryDark.withValues(alpha: 0.3),
blurRadius: 20,
offset: const Offset(0, 8),
),
@@ -118,17 +124,24 @@ class WeeklyPaymentPage extends StatelessWidget {
child: Column(
children: [
Text('Total Weekly Earnings'.tr,
style: TextStyle(color: Colors.white.withOpacity(0.8), fontSize: 14)),
style: TextStyle(
color: Colors.white.withValues(alpha: 0.8), fontSize: 14)),
const SizedBox(height: 8),
Text('${earnings.toStringAsFixed(0)} SYP',
style: const TextStyle(color: Colors.white, fontSize: 36, fontWeight: FontWeight.bold)),
style: const TextStyle(
color: Colors.white,
fontSize: 36,
fontWeight: FontWeight.bold)),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildStatItem('Total Trips'.tr, trips.toString(), Icons.directions_car_rounded),
_buildStatItem('Commission'.tr, '${commission.toStringAsFixed(0)}', Icons.percent_rounded),
_buildStatItem('Net Profit'.tr, '${netProfit.toStringAsFixed(0)}', Icons.account_balance_rounded),
_buildStatItem('Total Trips'.tr, trips.toString(),
Icons.directions_car_rounded),
_buildStatItem('Commission'.tr, commission.toStringAsFixed(0),
Icons.percent_rounded),
_buildStatItem('Net Profit'.tr, netProfit.toStringAsFixed(0),
Icons.account_balance_rounded),
],
),
],
@@ -141,12 +154,20 @@ class WeeklyPaymentPage extends StatelessWidget {
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(10)),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(10)),
child: Icon(icon, color: Colors.white, size: 18),
),
const SizedBox(height: 8),
Text(value, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 14)),
Text(label, style: TextStyle(color: Colors.white.withOpacity(0.6), fontSize: 10)),
Text(value,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 14)),
Text(label,
style: TextStyle(
color: Colors.white.withValues(alpha: 0.6), fontSize: 10)),
],
);
}
@@ -159,18 +180,27 @@ class WeeklyPaymentPage extends StatelessWidget {
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 10)],
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.02), blurRadius: 10)
],
),
child: Row(
children: [
IconButton(icon: const Icon(Icons.chevron_left_rounded), onPressed: () {}),
IconButton(
icon: const Icon(Icons.chevron_left_rounded), onPressed: () {}),
Expanded(
child: Center(
child: Text('Dec 15 - Dec 21, 2024'.tr,
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: FinanceDesignSystem.primaryDark)),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: FinanceDesignSystem.primaryDark)),
),
),
IconButton(icon: const Icon(Icons.chevron_right_rounded), onPressed: () {}),
IconButton(
icon: const Icon(Icons.chevron_right_rounded),
onPressed: () {}),
],
),
),
@@ -184,7 +214,9 @@ class WeeklyPaymentPage extends StatelessWidget {
children: [
Icon(Icons.bar_chart_rounded, size: 64, color: Colors.grey.shade300),
const SizedBox(height: 16),
Text('No transactions this week'.tr, style: const TextStyle(fontWeight: FontWeight.bold, color: Colors.grey)),
Text('No transactions this week'.tr,
style: const TextStyle(
fontWeight: FontWeight.bold, color: Colors.grey)),
],
),
);

View File

@@ -40,7 +40,7 @@ class FinancialSummaryCard extends StatelessWidget {
borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.03),
color: Colors.black.withValues(alpha: 0.03),
blurRadius: 10,
offset: const Offset(0, 4),
),
@@ -51,7 +51,7 @@ class FinancialSummaryCard extends StatelessWidget {
physics: const NeverScrollableScrollPhysics(),
itemCount: items.length,
separatorBuilder: (context, index) =>
Divider(color: Colors.grey.withOpacity(0.1), height: 24),
Divider(color: Colors.grey.withValues(alpha: 0.1), height: 24),
itemBuilder: (context, index) {
final item = items[index];
return Row(
@@ -59,7 +59,7 @@ class FinancialSummaryCard extends StatelessWidget {
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: item.color.withOpacity(0.1),
color: item.color.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(10),
),
child: Icon(item.icon, color: item.color, size: 20),
@@ -71,7 +71,7 @@ class FinancialSummaryCard extends StatelessWidget {
children: [
Text(
item.label,
style: const TextStyle(
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: FinanceDesignSystem.primaryDark,
@@ -93,7 +93,7 @@ class FinancialSummaryCard extends StatelessWidget {
children: [
Text(
"${item.amount} ${'SYP'.tr}",
style: const TextStyle(
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.primaryDark,

View File

@@ -50,7 +50,7 @@ class PromoGamificationCard extends StatelessWidget {
children: [
Text(
title,
style: const TextStyle(
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.primaryDark,

View File

@@ -96,7 +96,7 @@ class _ActionItem extends StatelessWidget {
const SizedBox(height: 8),
Text(
label,
style: const TextStyle(
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.primaryDark,

View File

@@ -59,7 +59,7 @@ class TransactionPreviewItem extends StatelessWidget {
children: [
Text(
title,
style: const TextStyle(
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.primaryDark,

View File

@@ -15,27 +15,36 @@ class BehaviorPage extends StatelessWidget {
return Scaffold(
backgroundColor: FinanceDesignSystem.backgroundColor,
appBar: AppBar(
title: Text('Driver Behavior'.tr, style: const TextStyle(fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)),
title: Text('Driver Behavior'.tr,
style: TextStyle(
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.primaryDark)),
centerTitle: true,
backgroundColor: FinanceDesignSystem.cardColor,
elevation: 0,
iconTheme: const IconThemeData(color: FinanceDesignSystem.primaryDark),
iconTheme: IconThemeData(color: FinanceDesignSystem.primaryDark),
),
body: Obx(() {
if (controller.isLoading.value) {
return const Center(child: CircularProgressIndicator(color: FinanceDesignSystem.accentBlue));
return Center(
child: CircularProgressIndicator(
color: FinanceDesignSystem.accentBlue));
}
double score = controller.overallScore.value;
bool isExcellent = score >= 90;
bool isGood = score >= 75 && score < 90;
Color statusColor = isExcellent ? Colors.green : (isGood ? Colors.orange : Colors.red);
String statusText = isExcellent ? 'Excellent'.tr : (isGood ? 'Good'.tr : 'Needs Improvement'.tr);
Color statusColor =
isExcellent ? Colors.green : (isGood ? Colors.orange : Colors.red);
String statusText = isExcellent
? 'Excellent'.tr
: (isGood ? 'Good'.tr : 'Needs Improvement'.tr);
return CustomScrollView(
slivers: [
SliverPadding(
padding: const EdgeInsets.all(FinanceDesignSystem.horizontalPadding),
padding:
const EdgeInsets.all(FinanceDesignSystem.horizontalPadding),
sliver: SliverList(
delegate: SliverChildListDelegate([
// Overall Score Card
@@ -44,11 +53,17 @@ class BehaviorPage extends StatelessWidget {
decoration: BoxDecoration(
color: FinanceDesignSystem.cardColor,
borderRadius: BorderRadius.circular(24),
boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 10, offset: Offset(0, 4))],
boxShadow: const [
BoxShadow(
color: Colors.black12,
blurRadius: 10,
offset: Offset(0, 4))
],
),
child: Column(
children: [
Icon(Icons.shield_rounded, size: 48, color: statusColor),
Icon(Icons.shield_rounded,
size: 48, color: statusColor),
const SizedBox(height: 16),
Text(
"Overall Behavior Score".tr,
@@ -65,33 +80,41 @@ class BehaviorPage extends StatelessWidget {
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 6),
decoration: BoxDecoration(
color: statusColor.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(20),
),
child: Text(
statusText,
style: TextStyle(color: statusColor, fontWeight: FontWeight.bold),
style: TextStyle(
color: statusColor,
fontWeight: FontWeight.bold),
),
),
],
),
),
const SizedBox(height: 30),
Text("Last 10 Trips".tr, style: FinanceDesignSystem.headingStyle),
Text("Last 10 Trips".tr,
style: FinanceDesignSystem.headingStyle),
const SizedBox(height: 16),
]),
),
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: FinanceDesignSystem.horizontalPadding),
padding: const EdgeInsets.symmetric(
horizontal: FinanceDesignSystem.horizontalPadding),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
var trip = controller.lastTrips[index];
double tripScore = double.tryParse(trip['behavior_score'].toString()) ?? 0;
Color tColor = tripScore >= 90 ? Colors.green : (tripScore >= 75 ? Colors.orange : Colors.red);
double tripScore =
double.tryParse(trip['behavior_score'].toString()) ?? 0;
Color tColor = tripScore >= 90
? Colors.green
: (tripScore >= 75 ? Colors.orange : Colors.red);
return Container(
margin: const EdgeInsets.only(bottom: 12),
@@ -118,7 +141,8 @@ class BehaviorPage extends StatelessWidget {
),
title: Text(
"Trip ID: ${trip['trip_id']}",
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 16),
),
subtitle: Padding(
padding: const EdgeInsets.only(top: 8.0),
@@ -126,9 +150,16 @@ class BehaviorPage extends StatelessWidget {
spacing: 12,
runSpacing: 8,
children: [
_buildBadge(Icons.speed, "${trip['max_speed']} km/h", Colors.blue),
_buildBadge(Icons.warning_amber_rounded, "${trip['hard_brakes']} ${'Hard Brakes'.tr}", Colors.orange),
_buildBadge(Icons.map_rounded, "${trip['total_distance']} km", Colors.purple),
_buildBadge(Icons.speed,
"${trip['max_speed']} km/h", Colors.blue),
_buildBadge(
Icons.warning_amber_rounded,
"${trip['hard_brakes']} ${'Hard Brakes'.tr}",
Colors.orange),
_buildBadge(
Icons.map_rounded,
"${trip['total_distance']} km",
Colors.purple),
],
),
),
@@ -137,9 +168,14 @@ class BehaviorPage extends StatelessWidget {
children: [
Text(
"${tripScore.toStringAsFixed(0)}",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20, color: tColor),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: tColor),
),
Text('Score'.tr, style: const TextStyle(fontSize: 10, color: Colors.grey)),
Text('Score'.tr,
style: const TextStyle(
fontSize: 10, color: Colors.grey)),
],
),
),
@@ -168,7 +204,9 @@ class BehaviorPage extends StatelessWidget {
children: [
Icon(icon, size: 14, color: color),
const SizedBox(width: 4),
Text(label, style: TextStyle(fontSize: 12, color: color, fontWeight: FontWeight.w600)),
Text(label,
style: TextStyle(
fontSize: 12, color: color, fontWeight: FontWeight.w600)),
],
),
);

View File

@@ -16,8 +16,7 @@ class StatisticsDashboard extends StatelessWidget {
final GamificationController gamController =
Get.put(GamificationController());
final StatisticsController statsController =
Get.put(StatisticsController());
final StatisticsController statsController = Get.put(StatisticsController());
@override
Widget build(BuildContext context) {
@@ -25,154 +24,160 @@ class StatisticsDashboard extends StatelessWidget {
backgroundColor: FinanceDesignSystem.backgroundColor,
body: GetBuilder<GamificationController>(
builder: (gc) {
if (gc.isLoading) {
return const Center(
child: CircularProgressIndicator(
color: FinanceDesignSystem.primaryDark),
);
}
return GetBuilder<StatisticsController>(
builder: (sc) {
if (gc.isLoading || sc.isLoading) {
return Center(
child: CircularProgressIndicator(
color: FinanceDesignSystem.primaryDark),
);
}
return CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: [
// ═══════ App Bar ═══════
SliverAppBar(
expandedHeight: 200,
pinned: true,
stretch: true,
backgroundColor: FinanceDesignSystem.primaryDark,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios_new_rounded,
color: Colors.white, size: 20),
onPressed: () => Get.back(),
),
actions: [
IconButton(
icon: const Icon(Icons.refresh_rounded,
color: Colors.white),
onPressed: () => gc.fetchGamificationData(),
),
],
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
title: Text(
'Statistics'.tr,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
return CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: [
// ═══════ App Bar ═══════
SliverAppBar(
expandedHeight: 200,
pinned: true,
stretch: true,
backgroundColor: Get.isDarkMode
? FinanceDesignSystem.primaryDark
: const Color(0xFF0A0E21),
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios_new_rounded,
color: Colors.white, size: 20),
onPressed: () => Get.back(),
),
),
background: Stack(
fit: StackFit.expand,
children: [
Container(
decoration: const BoxDecoration(
gradient: FinanceDesignSystem.balanceGradient,
),
),
// أيقونة زخرفية
Positioned(
right: -40,
top: -20,
child: Icon(
Icons.bar_chart_rounded,
size: 200,
color: Colors.white.withOpacity(0.04),
),
),
Positioned(
left: -30,
bottom: 20,
child: Icon(
Icons.emoji_events_rounded,
size: 120,
color: Colors.white.withOpacity(0.03),
),
),
// بطاقة المستوى في الهيدر
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 40),
Text(
gc.currentLevel.emoji,
style: const TextStyle(fontSize: 40),
),
const SizedBox(height: 4),
Text(
Get.locale?.languageCode == 'ar'
? gc.currentLevel.nameAr
: gc.currentLevel.nameEn,
style: TextStyle(
color: Colors.white.withOpacity(0.9),
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 2),
Text(
'${gc.unlockedCount}/${gc.totalAchievements} ${'Achievements'.tr}',
style: TextStyle(
color: Colors.white.withOpacity(0.5),
fontSize: 12,
),
),
],
),
actions: [
IconButton(
icon: const Icon(Icons.refresh_rounded,
color: Colors.white),
onPressed: () => gc.fetchGamificationData(),
),
],
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
title: Text(
'Statistics'.tr,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
background: Stack(
fit: StackFit.expand,
children: [
Container(
decoration: BoxDecoration(
gradient: FinanceDesignSystem.balanceGradient,
),
),
// أيقونة زخرفية
Positioned(
right: -40,
top: -20,
child: Icon(
Icons.bar_chart_rounded,
size: 200,
color: Colors.white.withOpacity(0.04),
),
),
Positioned(
left: -30,
bottom: 20,
child: Icon(
Icons.emoji_events_rounded,
size: 120,
color: Colors.white.withOpacity(0.03),
),
),
// بطاقة المستوى في الهيدر
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 40),
Text(
gc.currentLevel.emoji,
style: const TextStyle(fontSize: 40),
),
const SizedBox(height: 4),
Text(
Get.locale?.languageCode == 'ar'
? gc.currentLevel.nameAr
: gc.currentLevel.nameEn,
style: TextStyle(
color: Colors.white.withOpacity(0.9),
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 2),
Text(
'${gc.unlockedCount}/${gc.totalAchievements} ${'Achievements'.tr}',
style: TextStyle(
color: Colors.white.withOpacity(0.5),
fontSize: 12,
),
),
],
),
),
],
),
),
),
),
),
// ═══════ المحتوى ═══════
SliverPadding(
padding: const EdgeInsets.fromLTRB(16, 24, 16, 40),
sliver: SliverList(
delegate: SliverChildListDelegate([
// 1. بطاقات الإحصائيات الأربعة
_buildSummaryCards(gc),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// ═══════ المحتوى ═══════
SliverPadding(
padding: const EdgeInsets.fromLTRB(16, 24, 16, 40),
sliver: SliverList(
delegate: SliverChildListDelegate([
// 1. بطاقات الإحصائيات الأربعة
_buildSummaryCards(gc),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 2. الهدف اليومي
DailyGoalWidget(controller: gc),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 2. الهدف اليومي
DailyGoalWidget(controller: gc),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 3. تقدم المستوى
LevelProgressWidget(controller: gc),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 3. تقدم المستوى
LevelProgressWidget(controller: gc),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 4. إحصائيات اليوم
TodayChartWidget(),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 4. إحصائيات اليوم
TodayChartWidget(),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 5. الرسم البياني الأسبوعي
const WeeklyChartWidget(),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 5. الرسم البياني الأسبوعي
const WeeklyChartWidget(),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 6. التقرير الشهري
const MonthlyChartWidget(),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 6. التقرير الشهري
const MonthlyChartWidget(),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 7. تقييم سلوك القيادة
_buildBehaviorSection(gc),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 7. تقييم سلوك القيادة
_buildBehaviorSection(gc),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 8. الإنجازات
_buildAchievementsSection(gc),
]),
),
),
],
// 8. الإنجازات
_buildAchievementsSection(gc),
]),
),
),
],
);
},
);
},
),
@@ -221,21 +226,27 @@ class StatisticsDashboard extends StatelessWidget {
Widget _buildBehaviorSection(GamificationController gc) {
bool isExcellent = gc.behaviorScore >= 90;
bool isGood = gc.behaviorScore >= 75 && gc.behaviorScore < 90;
Color statusColor = isExcellent
? Colors.green
: isGood ? Colors.orange : Colors.red;
String statusText = isExcellent
? 'Excellent'.tr
: isGood ? 'Good'.tr : 'Needs Improvement'.tr;
Color statusColor = isExcellent
? Colors.green
: isGood
? Colors.orange
: Colors.red;
String statusText = isExcellent
? 'Excellent'.tr
: isGood
? 'Good'.tr
: 'Needs Improvement'.tr;
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: FinanceDesignSystem.cardColor,
borderRadius: BorderRadius.circular(24),
boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 10, offset: Offset(0, 4))],
boxShadow: const [
BoxShadow(color: Colors.black12, blurRadius: 10, offset: Offset(0, 4))
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -245,13 +256,16 @@ class StatisticsDashboard extends StatelessWidget {
children: [
Row(
children: [
const Icon(Icons.shield_rounded, color: FinanceDesignSystem.accentBlue),
Icon(Icons.shield_rounded,
color: FinanceDesignSystem.accentBlue),
const SizedBox(width: 8),
Text('Driving Behavior'.tr, style: FinanceDesignSystem.headingStyle),
Text('Driving Behavior'.tr,
style: FinanceDesignSystem.headingStyle),
],
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
padding:
const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: statusColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(20),
@@ -306,7 +320,11 @@ class StatisticsDashboard extends StatelessWidget {
);
}
Widget _behaviorStatItem({required String title, required String value, required IconData icon, required Color color}) {
Widget _behaviorStatItem(
{required String title,
required String value,
required IconData icon,
required Color color}) {
return Column(
children: [
Container(
@@ -318,18 +336,22 @@ class StatisticsDashboard extends StatelessWidget {
child: Icon(icon, color: color, size: 24),
),
const SizedBox(height: 8),
Text(value, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: FinanceDesignSystem.primaryDark)),
Text(title, style: const TextStyle(fontSize: 12, color: FinanceDesignSystem.textSecondary)),
Text(value,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
color: FinanceDesignSystem.primaryDark)),
Text(title,
style: TextStyle(
fontSize: 12, color: FinanceDesignSystem.textSecondary)),
],
);
}
// ═══════ قسم الإنجازات ═══════
Widget _buildAchievementsSection(GamificationController gc) {
final unlockedAch =
gc.achievements.where((a) => a.isUnlocked).toList();
final lockedAch =
gc.achievements.where((a) => !a.isUnlocked).toList();
final unlockedAch = gc.achievements.where((a) => a.isUnlocked).toList();
final lockedAch = gc.achievements.where((a) => !a.isUnlocked).toList();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -346,7 +368,7 @@ class StatisticsDashboard extends StatelessWidget {
),
child: Text(
'${gc.unlockedCount}/${gc.totalAchievements}',
style: const TextStyle(
style: TextStyle(
color: FinanceDesignSystem.accentBlue,
fontWeight: FontWeight.bold,
fontSize: 12,
@@ -397,9 +419,8 @@ class StatisticsDashboard extends StatelessWidget {
width: 50,
height: 50,
decoration: BoxDecoration(
color: unlocked
? ach.color.withOpacity(0.15)
: Colors.grey.shade200,
color:
unlocked ? ach.color.withOpacity(0.15) : Colors.grey.shade200,
borderRadius: BorderRadius.circular(14),
),
child: Icon(

View File

@@ -13,7 +13,7 @@ class DailyGoalWidget extends StatelessWidget {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
color: FinanceDesignSystem.cardColor,
borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius),
boxShadow: [
BoxShadow(
@@ -55,17 +55,17 @@ class DailyGoalWidget extends StatelessWidget {
children: [
Text(
'Daily Goal'.tr,
style: const TextStyle(
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.primaryDark,
),
),
Text(
'الهدف اليومي'.tr,
'Daily Goal'.tr,
style: TextStyle(
fontSize: 11,
color: Colors.grey.shade500,
color: FinanceDesignSystem.textSecondary,
),
),
],
@@ -80,13 +80,11 @@ class DailyGoalWidget extends StatelessWidget {
padding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.grey.shade100,
color: FinanceDesignSystem.backgroundColor,
borderRadius: BorderRadius.circular(8),
),
child: Text(
controller.dailyGoal > 0
? 'Edit'.tr
: 'Set Goal'.tr,
controller.dailyGoal > 0 ? 'Edit'.tr : 'Set Goal'.tr,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
@@ -121,7 +119,7 @@ class DailyGoalWidget extends StatelessWidget {
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.grey.shade400,
color: FinanceDesignSystem.textMuted,
),
),
],
@@ -135,7 +133,7 @@ class DailyGoalWidget extends StatelessWidget {
height: 12,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.grey.shade100,
color: FinanceDesignSystem.backgroundColor,
borderRadius: BorderRadius.circular(6),
),
),
@@ -197,7 +195,7 @@ class DailyGoalWidget extends StatelessWidget {
const SizedBox(width: 4),
Text(
'Goal Achieved!'.tr,
style: const TextStyle(
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.successGreen,
@@ -210,7 +208,7 @@ class DailyGoalWidget extends StatelessWidget {
'${'Remaining:'.tr} ${(controller.dailyGoal - controller.dailyEarnings).clamp(0, double.infinity).toStringAsFixed(0)} ${'SYP'.tr}',
style: TextStyle(
fontSize: 11,
color: Colors.grey.shade500,
color: FinanceDesignSystem.textSecondary,
),
),
],
@@ -228,6 +226,7 @@ class DailyGoalWidget extends StatelessWidget {
);
Get.defaultDialog(
backgroundColor: FinanceDesignSystem.cardColor,
title: 'Set Daily Goal'.tr,
titleStyle: FinanceDesignSystem.headingStyle,
content: Column(
@@ -252,13 +251,11 @@ class DailyGoalWidget extends StatelessWidget {
suffixText: 'SYP'.tr,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide:
BorderSide(color: Colors.grey.shade300),
borderSide: BorderSide(color: FinanceDesignSystem.borderColor),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide:
const BorderSide(color: FinanceDesignSystem.accentBlue),
borderSide: BorderSide(color: FinanceDesignSystem.accentBlue),
),
),
),
@@ -270,7 +267,8 @@ class DailyGoalWidget extends StatelessWidget {
return ActionChip(
label: Text('$goal'),
labelStyle: const TextStyle(fontSize: 12),
backgroundColor: FinanceDesignSystem.accentBlue.withOpacity(0.1),
backgroundColor:
FinanceDesignSystem.accentBlue.withOpacity(0.1),
side: BorderSide.none,
onPressed: () {
textController.text = goal.toString();
@@ -291,16 +289,15 @@ class DailyGoalWidget extends StatelessWidget {
style: ElevatedButton.styleFrom(
backgroundColor: FinanceDesignSystem.accentBlue,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12)),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
),
child: Text('Save'.tr),
),
cancel: TextButton(
onPressed: () => Get.back(),
child: Text('Cancel'.tr,
style: const TextStyle(color: Colors.grey)),
child: Text('Cancel'.tr, style: const TextStyle(color: Colors.grey)),
),
);
}

View File

@@ -17,8 +17,12 @@ class LevelProgressWidget extends StatelessWidget {
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [level.color.withOpacity(0.08), level.gradientEnd.withOpacity(0.04)],
begin: Alignment.topLeft, end: Alignment.bottomRight,
colors: [
level.color.withOpacity(0.08),
level.gradientEnd.withOpacity(0.04)
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius),
border: Border.all(color: level.color.withOpacity(0.2), width: 1.5),
@@ -29,17 +33,27 @@ class LevelProgressWidget extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Driver Level'.tr, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)),
Text('Driver Level'.tr,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.primaryDark)),
Container(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
padding:
const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
decoration: BoxDecoration(
gradient: LinearGradient(colors: [level.color, level.gradientEnd]),
gradient:
LinearGradient(colors: [level.color, level.gradientEnd]),
borderRadius: BorderRadius.circular(20),
),
child: Row(mainAxisSize: MainAxisSize.min, children: [
Text(level.emoji, style: const TextStyle(fontSize: 16)),
const SizedBox(width: 6),
Text(isAr ? level.nameAr : level.nameEn, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 13)),
Text(isAr ? level.nameAr : level.nameEn,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 13)),
]),
),
],
@@ -50,42 +64,94 @@ class LevelProgressWidget extends StatelessWidget {
final lvl = DriverLevels.all[i];
final isCurrent = lvl.id == level.id;
final isPast = DriverLevels.all.indexOf(level) > i;
return Expanded(child: Container(
margin: const EdgeInsets.symmetric(horizontal: 2), height: 8,
return Expanded(
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 2),
height: 8,
decoration: BoxDecoration(
color: isCurrent ? lvl.color : isPast ? lvl.color.withOpacity(0.6) : Colors.grey.shade200,
color: isCurrent
? lvl.color
: isPast
? lvl.color.withOpacity(0.6)
: FinanceDesignSystem.backgroundColor,
borderRadius: BorderRadius.circular(4),
),
));
}),
),
const SizedBox(height: 6),
Row(children: DriverLevels.all.map((l) => Expanded(child: Text(l.emoji, textAlign: TextAlign.center, style: TextStyle(fontSize: l.id == level.id ? 16 : 12)))).toList()),
Row(
children: DriverLevels.all
.map((l) => Expanded(
child: Text(l.emoji,
textAlign: TextAlign.center,
style:
TextStyle(fontSize: l.id == level.id ? 16 : 12))))
.toList()),
const SizedBox(height: 16),
if (next != null) ...[
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text('${'Next Level:'.tr} ${isAr ? next.nameAr : next.nameEn}', style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.grey.shade700)),
Text('${(controller.progressToNext * 100).toStringAsFixed(0)}%', style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold, color: level.color)),
Text('${'Next Level:'.tr} ${isAr ? next.nameAr : next.nameEn}',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: FinanceDesignSystem.textSecondary)),
Text('${(controller.progressToNext * 100).toStringAsFixed(0)}%',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: level.color)),
]),
const SizedBox(height: 8),
Stack(children: [
Container(height: 10, decoration: BoxDecoration(color: Colors.grey.shade100, borderRadius: BorderRadius.circular(5))),
LayoutBuilder(builder: (ctx, c) => AnimatedContainer(
duration: const Duration(milliseconds: 800), curve: Curves.easeOutCubic, height: 10,
width: c.maxWidth * controller.progressToNext,
decoration: BoxDecoration(gradient: LinearGradient(colors: [level.color, level.gradientEnd]), borderRadius: BorderRadius.circular(5)),
)),
Container(
height: 10,
decoration: BoxDecoration(
color: FinanceDesignSystem.backgroundColor,
borderRadius: BorderRadius.circular(5))),
LayoutBuilder(
builder: (ctx, c) => AnimatedContainer(
duration: const Duration(milliseconds: 800),
curve: Curves.easeOutCubic,
height: 10,
width: c.maxWidth * controller.progressToNext,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [level.color, level.gradientEnd]),
borderRadius: BorderRadius.circular(5)),
)),
]),
const SizedBox(height: 6),
Text('${controller.totalPoints} / ${next.minPoints} ${'Points'.tr}', style: TextStyle(fontSize: 11, color: Colors.grey.shade500, fontFamily: 'digit')),
Text('${controller.totalPoints} / ${next.minPoints} ${'Points'.tr}',
style: TextStyle(
fontSize: 11,
color: FinanceDesignSystem.textMuted,
fontFamily: 'digit')),
] else
Center(child: Text('🏆 ${'Maximum Level Reached!'.tr}', style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: level.color))),
Center(
child: Text('🏆 ${'Maximum Level Reached!'.tr}',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: level.color))),
const SizedBox(height: 16),
Wrap(spacing: 6, runSpacing: 6, children: level.perks.map((p) => Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(color: level.color.withOpacity(0.1), borderRadius: BorderRadius.circular(12)),
child: Text(p.tr, style: TextStyle(fontSize: 10, fontWeight: FontWeight.w600, color: level.color.withOpacity(0.8))),
)).toList()),
Wrap(
spacing: 6,
runSpacing: 6,
children: level.perks
.map((p) => Container(
padding: const EdgeInsets.symmetric(
horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: level.color.withOpacity(0.1),
borderRadius: BorderRadius.circular(12)),
child: Text(p.tr,
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w600,
color: level.color.withOpacity(0.8))),
))
.toList()),
],
),
);

View File

@@ -14,63 +14,114 @@ class MonthlyChartWidget extends StatelessWidget {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
color: FinanceDesignSystem.cardColor,
borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 10, offset: const Offset(0, 4))],
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.03),
blurRadius: 10,
offset: const Offset(0, 4))
],
),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text('Monthly Report'.tr, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)),
child:
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text('Monthly Report'.tr,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.primaryDark)),
const SizedBox(height: 16),
// Summary Row
Row(children: [
_summaryTile('Total Earnings'.tr, '${sc.monthlyTotalEarnings.toStringAsFixed(0)} ${'SYP'.tr}', FinanceDesignSystem.successGreen),
_summaryTile(
'Total Earnings'.tr,
'${sc.monthlyTotalEarnings.toStringAsFixed(0)} ${'SYP'.tr}',
FinanceDesignSystem.successGreen),
const SizedBox(width: 12),
_summaryTile('Total Trips'.tr, '${sc.monthlyTotalTrips}', FinanceDesignSystem.accentBlue),
_summaryTile('Total Trips'.tr, '${sc.monthlyTotalTrips}',
FinanceDesignSystem.accentBlue),
const SizedBox(width: 12),
_summaryTile('Best Day'.tr, '${sc.bestDay}', const Color(0xFFFFD700)),
_summaryTile(
'Best Day'.tr, '${sc.bestDay}', const Color(0xFFFFD700)),
]),
const SizedBox(height: 20),
// Monthly Earnings Line Chart
SizedBox(
height: 200,
child: sc.monthlyEarnings.isEmpty
? Center(child: Text('No data yet'.tr, style: TextStyle(color: Colors.grey.shade400)))
? Center(
child: Text('No data yet'.tr,
style: TextStyle(color: Colors.grey.shade400)))
: LineChart(LineChartData(
lineTouchData: LineTouchData(
enabled: true,
touchTooltipData: LineTouchTooltipData(
getTooltipItems: (spots) => spots.map((s) => LineTooltipItem(
'${s.y.toStringAsFixed(0)} ${'SYP'.tr}',
const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 12),
)).toList(),
getTooltipItems: (spots) => spots
.map((s) => LineTooltipItem(
'${s.y.toStringAsFixed(0)} ${'SYP'.tr}',
const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 12),
))
.toList(),
),
),
gridData: FlGridData(show: true, drawVerticalLine: false,
getDrawingHorizontalLine: (v) => FlLine(color: Colors.grey.shade100, strokeWidth: 1),
gridData: FlGridData(
show: true,
drawVerticalLine: false,
getDrawingHorizontalLine: (v) => FlLine(
color: FinanceDesignSystem.borderColor,
strokeWidth: 1),
),
titlesData: FlTitlesData(
bottomTitles: AxisTitles(sideTitles: SideTitles(showTitles: true, interval: 5,
getTitlesWidget: (v, m) => Padding(padding: const EdgeInsets.only(top: 8),
child: Text('${v.toInt()}', style: TextStyle(fontSize: 10, color: Colors.grey.shade500)),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
interval: 5,
getTitlesWidget: (v, m) => Padding(
padding: const EdgeInsets.only(top: 8),
child: Text('${v.toInt()}',
style: TextStyle(
fontSize: 10,
color: FinanceDesignSystem.textSecondary)),
),
)),
leftTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
leftTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false)),
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false)),
rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false)),
),
borderData: FlBorderData(show: false),
lineBarsData: [
LineChartBarData(
spots: sc.monthlyEarnings.map((e) => FlSpot(e.day.toDouble(), e.pricePerDay)).toList(),
isCurved: true, curveSmoothness: 0.3,
color: FinanceDesignSystem.accentBlue, barWidth: 3,
dotData: FlDotData(show: true, getDotPainter: (s, p, d, i) =>
FlDotCirclePainter(radius: 3, color: FinanceDesignSystem.accentBlue, strokeWidth: 1, strokeColor: Colors.white),
spots: sc.monthlyEarnings
.map((e) =>
FlSpot(e.day.toDouble(), e.pricePerDay))
.toList(),
isCurved: true,
curveSmoothness: 0.3,
color: FinanceDesignSystem.accentBlue,
barWidth: 3,
dotData: FlDotData(
show: true,
getDotPainter: (s, p, d, i) => FlDotCirclePainter(
radius: 3,
color: FinanceDesignSystem.accentBlue,
strokeWidth: 1,
strokeColor: Colors.white),
),
belowBarData: BarAreaData(
show: true,
gradient: LinearGradient(begin: Alignment.topCenter, end: Alignment.bottomCenter,
colors: [FinanceDesignSystem.accentBlue.withOpacity(0.2), FinanceDesignSystem.accentBlue.withOpacity(0.0)],
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
FinanceDesignSystem.accentBlue.withOpacity(0.2),
FinanceDesignSystem.accentBlue.withOpacity(0.0)
],
),
),
),
@@ -87,11 +138,20 @@ class MonthlyChartWidget extends StatelessWidget {
return Expanded(
child: Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(color: color.withOpacity(0.08), borderRadius: BorderRadius.circular(12)),
decoration: BoxDecoration(
color: color.withOpacity(0.08),
borderRadius: BorderRadius.circular(12)),
child: Column(children: [
Text(value, style: TextStyle(fontSize: 14, fontWeight: FontWeight.w800, color: color)),
Text(value,
style: TextStyle(
fontSize: 14, fontWeight: FontWeight.w800, color: color)),
const SizedBox(height: 2),
Text(label, style: TextStyle(fontSize: 9, color: Colors.grey.shade600), textAlign: TextAlign.center, maxLines: 1, overflow: TextOverflow.ellipsis),
Text(label,
style: TextStyle(
fontSize: 9, color: FinanceDesignSystem.textSecondary),
textAlign: TextAlign.center,
maxLines: 1,
overflow: TextOverflow.ellipsis),
]),
),
);

View File

@@ -20,7 +20,7 @@ class StatSummaryCard extends StatelessWidget {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
color: FinanceDesignSystem.cardColor,
borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius),
boxShadow: [
BoxShadow(
@@ -68,7 +68,7 @@ class StatSummaryCard extends StatelessWidget {
label,
style: TextStyle(
fontSize: 11,
color: Colors.grey.shade500,
color: FinanceDesignSystem.textSecondary,
fontWeight: FontWeight.w500,
),
maxLines: 1,

View File

@@ -13,26 +13,42 @@ class TodayChartWidget extends StatelessWidget {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
color: FinanceDesignSystem.cardColor,
borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius),
boxShadow: [
BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 10, offset: const Offset(0, 4)),
BoxShadow(
color: Colors.black.withOpacity(0.03),
blurRadius: 10,
offset: const Offset(0, 4)),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Today Overview'.tr, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)),
Text('Today Overview'.tr,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.primaryDark)),
const SizedBox(height: 4),
Text('نظرة عامة على اليوم'.tr, style: TextStyle(fontSize: 11, color: Colors.grey.shade500)),
Text('Summary of your daily activity'.tr,
style: TextStyle(
fontSize: 11, color: FinanceDesignSystem.textSecondary)),
const SizedBox(height: 20),
_buildRow(Icons.monetization_on_rounded, 'Earnings'.tr, '${hc.totalMoneyToday} ${'SYP'.tr}', FinanceDesignSystem.successGreen),
_buildRow(
Icons.monetization_on_rounded,
'Earnings'.tr,
'${hc.totalMoneyToday} ${'SYP'.tr}',
FinanceDesignSystem.successGreen),
const Divider(height: 24),
_buildRow(Icons.local_taxi_rounded, 'Rides'.tr, hc.countRideToday, FinanceDesignSystem.accentBlue),
_buildRow(Icons.local_taxi_rounded, 'Rides'.tr, hc.countRideToday,
FinanceDesignSystem.accentBlue),
const Divider(height: 24),
Obx(() => _buildRow(Icons.timer_rounded, 'Online Duration'.tr, hc.totalDurationDisplay.value, const Color(0xFFFF9800))),
Obx(() => _buildRow(Icons.timer_rounded, 'Online Duration'.tr,
hc.totalDurationDisplay.value, const Color(0xFFFF9800))),
const Divider(height: 24),
_buildRow(Icons.cancel_outlined, 'Refused'.tr, hc.countRefuse, FinanceDesignSystem.dangerRed),
_buildRow(Icons.cancel_outlined, 'Refused'.tr, hc.countRefuse,
FinanceDesignSystem.dangerRed),
],
),
);
@@ -45,12 +61,24 @@ class TodayChartWidget extends StatelessWidget {
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(10)),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(10)),
child: Icon(icon, color: color, size: 20),
),
const SizedBox(width: 14),
Expanded(child: Text(label, style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.grey.shade700))),
Text(value, style: TextStyle(fontSize: 16, fontWeight: FontWeight.w800, color: FinanceDesignSystem.primaryDark, fontFamily: 'digit')),
Expanded(
child: Text(label,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: FinanceDesignSystem.primaryDark))),
Text(value,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w800,
color: FinanceDesignSystem.primaryDark,
fontFamily: 'digit')),
],
);
}

View File

@@ -4,7 +4,6 @@ import 'package:fl_chart/fl_chart.dart';
import '../../../../constant/finance_design_system.dart';
import '../../../../controller/home/statistics/statistics_controller.dart';
class WeeklyChartWidget extends StatelessWidget {
const WeeklyChartWidget({super.key});
@@ -15,32 +14,56 @@ class WeeklyChartWidget extends StatelessWidget {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
color: FinanceDesignSystem.cardColor,
borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 10, offset: const Offset(0, 4))],
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.03),
blurRadius: 10,
offset: const Offset(0, 4))
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text('Weekly Earnings'.tr, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)),
Text('Weekly Earnings'.tr,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.primaryDark)),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(color: FinanceDesignSystem.successGreen.withOpacity(0.1), borderRadius: BorderRadius.circular(12)),
child: Text('${sc.weeklyEarnings.toStringAsFixed(0)} ${'SYP'.tr}', style: const TextStyle(fontSize: 12, fontWeight: FontWeight.bold, color: FinanceDesignSystem.successGreen)),
padding:
const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: FinanceDesignSystem.successGreen.withOpacity(0.1),
borderRadius: BorderRadius.circular(12)),
child: Text(
'${sc.weeklyEarnings.toStringAsFixed(0)} ${'SYP'.tr}',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.successGreen)),
),
]),
const SizedBox(height: 8),
Row(children: [
_miniStat(Icons.local_taxi_rounded, '${sc.weeklyTrips}', 'Rides'.tr, FinanceDesignSystem.accentBlue),
_miniStat(Icons.local_taxi_rounded, '${sc.weeklyTrips}',
'Rides'.tr, FinanceDesignSystem.accentBlue),
const SizedBox(width: 16),
_miniStat(Icons.timer_rounded, '${sc.weeklyHours.toStringAsFixed(1)}h', 'Hours'.tr, const Color(0xFFFF9800)),
_miniStat(
Icons.timer_rounded,
'${sc.weeklyHours.toStringAsFixed(1)}h',
'Hours'.tr,
const Color(0xFFFF9800)),
]),
const SizedBox(height: 20),
SizedBox(
height: 180,
child: sc.weeklyStats.isEmpty
? Center(child: Text('No data yet'.tr, style: TextStyle(color: Colors.grey.shade400)))
? Center(
child: Text('No data yet'.tr,
style: TextStyle(color: Colors.grey.shade400)))
: BarChart(
BarChartData(
alignment: BarChartAlignment.spaceAround,
@@ -48,24 +71,43 @@ class WeeklyChartWidget extends StatelessWidget {
barTouchData: BarTouchData(
enabled: true,
touchTooltipData: BarTouchTooltipData(
getTooltipItem: (group, gi, rod, ri) => BarTooltipItem(
getTooltipItem: (group, gi, rod, ri) =>
BarTooltipItem(
'${rod.toY.toStringAsFixed(0)} ${'SYP'.tr}',
const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 12),
const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 12),
),
),
),
titlesData: FlTitlesData(
show: true,
bottomTitles: AxisTitles(sideTitles: SideTitles(showTitles: true, getTitlesWidget: (v, m) {
final idx = v.toInt();
if (idx >= 0 && idx < sc.weeklyStats.length) {
return Padding(padding: const EdgeInsets.only(top: 8), child: Text(sc.weeklyStats[idx].dayName.tr, style: TextStyle(fontSize: 10, color: Colors.grey.shade500)));
}
return const SizedBox.shrink();
})),
leftTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: (v, m) {
final idx = v.toInt();
if (idx >= 0 &&
idx < sc.weeklyStats.length) {
return Padding(
padding:
const EdgeInsets.only(top: 8),
child: Text(
sc.weeklyStats[idx].dayName.tr,
style: TextStyle(
fontSize: 10,
color: FinanceDesignSystem
.textSecondary)));
}
return const SizedBox.shrink();
})),
leftTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false)),
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false)),
rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false)),
),
borderData: FlBorderData(show: false),
gridData: const FlGridData(show: false),
@@ -76,12 +118,22 @@ class WeeklyChartWidget extends StatelessWidget {
BarChartRodData(
toY: stat.earnings,
width: 20,
borderRadius: const BorderRadius.vertical(top: Radius.circular(6)),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(6)),
gradient: LinearGradient(
begin: Alignment.bottomCenter, end: Alignment.topCenter,
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: isToday
? [FinanceDesignSystem.accentBlue, const Color(0xFF82B1FF)]
: [FinanceDesignSystem.primaryDark.withOpacity(0.6), FinanceDesignSystem.primaryDark.withOpacity(0.3)],
? [
FinanceDesignSystem.accentBlue,
const Color(0xFF82B1FF)
]
: [
FinanceDesignSystem.primaryDark
.withOpacity(0.6),
FinanceDesignSystem.primaryDark
.withOpacity(0.3)
],
),
),
]);
@@ -100,9 +152,15 @@ class WeeklyChartWidget extends StatelessWidget {
return Row(children: [
Icon(icon, size: 16, color: color),
const SizedBox(width: 4),
Text(value, style: TextStyle(fontSize: 13, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)),
Text(value,
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: FinanceDesignSystem.primaryDark)),
const SizedBox(width: 4),
Text(label, style: TextStyle(fontSize: 11, color: Colors.grey.shade500)),
Text(label,
style: TextStyle(
fontSize: 11, color: FinanceDesignSystem.textSecondary)),
]);
}