import 'package:local_auth/local_auth.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:siro_driver/constant/finance_design_system.dart'; import 'package:siro_driver/controller/home/payment/captain_wallet_controller.dart'; import 'package:siro_driver/views/widgets/mycircular.dart'; import 'package:siro_driver/views/widgets/elevated_btn.dart'; import 'package:siro_driver/views/widgets/my_textField.dart'; import 'package:siro_driver/views/widgets/mydialoug.dart'; import 'package:siro_driver/views/widgets/error_snakbar.dart'; import 'package:siro_driver/constant/box_name.dart'; import 'package:siro_driver/constant/links.dart'; import 'package:siro_driver/controller/functions/crud.dart'; import 'package:siro_driver/main.dart'; import 'package:siro_driver/views/home/my_wallet/payment_history_driver_page.dart'; import 'package:siro_driver/controller/payment/driver_payment_controller.dart'; // Import new widgets import 'points_captain.dart'; import 'transfer_budget_page.dart'; import 'widgets/balance_card.dart'; import 'widgets/quick_actions.dart'; import 'widgets/financial_summary_card.dart'; import 'widgets/promo_gamification_card.dart'; import 'widgets/transaction_preview_item.dart'; class WalletCaptainRefactored extends StatelessWidget { WalletCaptainRefactored({super.key}); final CaptainWalletController controller = Get.put(CaptainWalletController()); @override Widget build(BuildContext context) { controller.refreshCaptainWallet(); return Scaffold( backgroundColor: FinanceDesignSystem.backgroundColor, appBar: AppBar( title: Text('Driver Balance'.tr, style: TextStyle( fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), backgroundColor: Colors.transparent, elevation: 0, centerTitle: true, leading: IconButton( icon: Icon(Icons.arrow_back_ios_new_rounded, color: FinanceDesignSystem.primaryDark, size: 20), onPressed: () => Get.back(), ), actions: [ IconButton( icon: Icon(Icons.refresh_rounded, color: FinanceDesignSystem.primaryDark), onPressed: () => controller.refreshCaptainWallet(), tooltip: 'Refresh'.tr, ), ], ), body: GetBuilder( builder: (controller) { if (controller.isLoading) { return const Center(child: MyCircularProgressIndicator()); } return SingleChildScrollView( padding: const EdgeInsets.symmetric( horizontal: FinanceDesignSystem.horizontalPadding, vertical: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // 1. Header / Balance BalanceCard( balance: controller.totalPoints.toString(), isNegative: double.tryParse(controller.totalPoints.toString()) != null && double.parse(controller.totalPoints.toString()) < -30000, lastUpdated: "Just now".tr, ), const SizedBox( height: FinanceDesignSystem.verticalSectionPadding), // 2. Quick Actions QuickActionsGrid( onAddBalance: () => _showAddBalanceOptions(context, controller), onWithdraw: () => addSyrianPaymentMethod(controller), onTransfer: () => Get.to(() => TransferBudgetPage()), onHistory: () async { await Get.put(DriverWalletHistoryController()) .getArchivePayment(); Get.to(() => const PaymentHistoryDriverPage()); }, ), const SizedBox( height: FinanceDesignSystem.verticalSectionPadding), // 3. Earnings Summary FinancialSummaryCard( title: 'Earnings Summary'.tr, subtitle: 'ملخص الأرباح'.tr, items: [ SummaryItem( icon: Icons.money_rounded, label: 'Cash Earnings'.tr, amount: controller.totalAmount, color: FinanceDesignSystem.successGreen, ), SummaryItem( icon: Icons.credit_card_rounded, label: 'Card Earnings'.tr, amount: controller.totalAmountVisa, color: FinanceDesignSystem.accentBlue, ), ], ), const SizedBox( height: FinanceDesignSystem.verticalSectionPadding), // 3. Recharge Balance Packages Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Recharge Balance'.tr, style: FinanceDesignSystem.headingStyle), Icon(Icons.info_outline_rounded, size: 18, color: Colors.grey.shade400), ], ), const SizedBox(height: 12), SizedBox( height: 140, // Increased height for modern cards child: ListView( scrollDirection: Axis.horizontal, physics: const BouncingScrollPhysics(), children: [ PointsCaptain( kolor: Colors.blueGrey, pricePoint: 100, countPoint: '100'), PointsCaptain( kolor: Colors.brown, pricePoint: 200, countPoint: '210'), PointsCaptain( kolor: Colors.amber, pricePoint: 400, countPoint: '450'), PointsCaptain( kolor: Colors.orange, pricePoint: 1000, countPoint: '1100'), ], ), ), const SizedBox( height: FinanceDesignSystem.verticalSectionPadding), // 5. Promotions Text('Promotions'.tr, style: FinanceDesignSystem.headingStyle), const SizedBox(height: 12), PromoGamificationCard( title: 'Morning Promo'.tr, subtitle: "from 7:00am to 10:00am".tr, currentProgress: controller.walletDate['message']?[0] ?['morning_count'] ?? 0, targetProgress: 5, reward: "+50 SYP", onTap: () => controller.addDriverWalletFromPromo('Morning Promo', 50), ), const SizedBox(height: 16), PromoGamificationCard( title: 'Afternoon Promo'.tr, subtitle: "from 3:00pm to 6:00 pm".tr, currentProgress: controller.walletDate['message']?[0] ?['afternoon_count'] ?? 0, targetProgress: 5, reward: "+50 SYP", onTap: () => controller.addDriverWalletFromPromo( 'Afternoon Promo', 50), ), const SizedBox( height: FinanceDesignSystem.verticalSectionPadding), // 6. Transactions Preview Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Recent Transactions'.tr, style: FinanceDesignSystem.headingStyle), TextButton( onPressed: () async { await Get.put(DriverWalletHistoryController()) .getArchivePayment(); Get.to(() => const PaymentHistoryDriverPage()); }, child: Text('View All'.tr, style: TextStyle( color: FinanceDesignSystem.accentBlue, fontWeight: FontWeight.bold)), ), ], ), GetBuilder( init: DriverWalletHistoryController(), builder: (historyController) { if (historyController.archive.isEmpty) { return Padding( padding: const EdgeInsets.symmetric(vertical: 20), child: Center( child: Text("No transactions yet".tr, style: TextStyle(color: Colors.grey.shade400))), ); } // Show only last 3 final lastThree = historyController.archive.take(3).toList(); return Column( children: lastThree.map((tx) { final double amount = double.tryParse(tx['amount']?.toString() ?? '0') ?? 0; return TransactionPreviewItem( title: amount >= 0 ? 'Credit'.tr : 'Debit'.tr, subtitle: tx['created_at'] ?? '', amount: amount.abs().toStringAsFixed(0), date: tx['created_at']?.split(' ')[0] ?? '', type: amount >= 0 ? 'credit' : 'debit', onTap: () {}, ); }).toList(), ); }, ), const SizedBox(height: 40), ], ), ); }, ), ); } void _showAddBalanceOptions( BuildContext context, CaptainWalletController controller) { Get.bottomSheet( Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Add Balance".tr, style: FinanceDesignSystem.headingStyle), const SizedBox(height: 8), Text("Select how you want to charge your account".tr, style: FinanceDesignSystem.subHeadingStyle), const SizedBox(height: 24), ListTile( leading: Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: FinanceDesignSystem.accentBlue.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12)), child: Icon(Icons.account_balance_wallet_rounded, color: FinanceDesignSystem.accentBlue), ), title: Text("Pay from my budget".tr), subtitle: Text( "${'You have in account'.tr} ${controller.totalAmountVisa}"), onTap: () { Get.back(); _showPayFromBudgetDialog(controller); }, ), const Divider(), const SizedBox(height: 16), Text("Recharge Balance Packages".tr, style: FinanceDesignSystem.subHeadingStyle .copyWith(fontWeight: FontWeight.bold)), const SizedBox(height: 12), SizedBox( height: 140, child: ListView( scrollDirection: Axis.horizontal, physics: const BouncingScrollPhysics(), children: [ PointsCaptain( kolor: Colors.blueGrey, pricePoint: 100, countPoint: '100'), PointsCaptain( kolor: Colors.brown, pricePoint: 200, countPoint: '210'), PointsCaptain( kolor: Colors.amber, pricePoint: 400, countPoint: '450'), PointsCaptain( kolor: Colors.orange, pricePoint: 1000, countPoint: '1100'), ], ), ), ], ), ), ); } void _showPayFromBudgetDialog(CaptainWalletController controller) { Get.defaultDialog( title: 'Pay from my budget'.tr, content: Form( key: controller.formKey, child: MyTextForm( controller: controller.amountFromBudgetController, label: '${'You have in account'.tr} ${controller.totalAmountVisa}', hint: '${'You have in account'.tr} ${controller.totalAmountVisa}', type: TextInputType.number, ), ), confirm: MyElevatedButton( title: 'Pay'.tr, onPressed: () async { bool isAvailable = await LocalAuthentication().isDeviceSupported(); if (isAvailable) { bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'Use Touch ID or Face ID to confirm payment'.tr, biometricOnly: true, sensitiveTransaction: true, ); if (didAuthenticate) { if (double.parse(controller.amountFromBudgetController.text) < double.parse(controller.totalAmountVisa)) { await controller.payFromBudget(); } else { Get.back(); mySnackeBarError('Your Budget less than needed'.tr); } } else { MyDialog().getDialog( 'Authentication failed'.tr, ''.tr, () => Get.back()); } } else { MyDialog().getDialog( 'Biometric Authentication'.tr, 'You should use Touch ID or Face ID to confirm payment'.tr, () => Get.back()); } }, ), cancel: MyElevatedButton(title: 'Cancel'.tr, onPressed: () => Get.back()), ); } } Future addSyrianPaymentMethod( CaptainWalletController captainWalletController) { return Get.defaultDialog( title: "Insert Payment Details".tr, content: Form( key: captainWalletController.formKeyAccount, child: Column( children: [ Text( "Insert your mobile wallet details to receive your money weekly" .tr), MyTextForm( controller: captainWalletController.cardBank, label: "Insert mobile wallet number".tr, hint: '0912 345 678', type: TextInputType.phone), const SizedBox(height: 10), MyDropDownSyria() ], )), confirm: MyElevatedButton( title: 'Ok'.tr, onPressed: () async { if (captainWalletController.formKeyAccount.currentState! .validate()) { Get.back(); var res = await CRUD().post(link: AppLink.updateAccountBank, payload: { "paymentProvider": Get.find().dropdownValue.toString(), "accountNumber": captainWalletController.cardBank.text.toString(), "id": box.read(BoxName.driverID).toString() }); if (res != 'failure') { mySnackbarSuccess('Payment details added successfully'.tr); } } })); } class SyrianPayoutController extends GetxController { String dropdownValue = 'syriatel'; void changeValue(String? newValue) { if (newValue != null) { dropdownValue = newValue; update(); } } } class MyDropDownSyria extends StatelessWidget { const MyDropDownSyria({super.key}); @override Widget build(BuildContext context) { Get.put(SyrianPayoutController()); final theme = Theme.of(context); return GetBuilder(builder: (controller) { return DropdownButton( value: controller.dropdownValue, icon: const Icon(Icons.arrow_drop_down), elevation: 16, isExpanded: true, dropdownColor: theme.cardColor, style: TextStyle(color: theme.textTheme.bodyLarge?.color), underline: Container(height: 2, color: theme.primaryColor), onChanged: (String? newValue) => controller.changeValue(newValue), items: ['syriatel', 'mtn'] .map>((String value) { return DropdownMenuItem(value: value, child: Text(value.tr)); }).toList(), ); }); } }