From e52afa186337f340fda4c9f805c478e4d6f8cc69 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Sat, 8 Aug 2026 17:42:04 +0300 Subject: [PATCH] Update: 2026-08-08 17:42:04 --- .../home/my_wallet/payment_screen_cliq.dart | 184 ++++++++++++++---- .../home/my_wallet/payment_screen_mtn.dart | 24 +++ .../views/home/my_wallet/points_captain.dart | 13 +- 3 files changed, 176 insertions(+), 45 deletions(-) diff --git a/siro_driver/lib/views/home/my_wallet/payment_screen_cliq.dart b/siro_driver/lib/views/home/my_wallet/payment_screen_cliq.dart index 3abb34f8..f0aa9d84 100644 --- a/siro_driver/lib/views/home/my_wallet/payment_screen_cliq.dart +++ b/siro_driver/lib/views/home/my_wallet/payment_screen_cliq.dart @@ -23,11 +23,12 @@ class PaymentScreenCliq extends StatefulWidget { State createState() => _PaymentScreenCliqState(); } -class _PaymentScreenCliqState extends State with SingleTickerProviderStateMixin { +class _PaymentScreenCliqState extends State + with SingleTickerProviderStateMixin { Timer? _pollingTimer; String _status = 'waiting'; // waiting, uploading, verifying, success, error final TextEditingController _proofController = TextEditingController(); - + late AnimationController _blinkController; late Animation _colorAnimation; late Animation _shadowAnimation; @@ -35,10 +36,15 @@ class _PaymentScreenCliqState extends State with SingleTicker @override void initState() { super.initState(); - _blinkController = AnimationController(duration: const Duration(milliseconds: 800), vsync: this)..repeat(reverse: true); - _colorAnimation = ColorTween(begin: Colors.red.shade700, end: Colors.red.shade100).animate(_blinkController); - _shadowAnimation = Tween(begin: 2.0, end: 15.0).animate(CurvedAnimation(parent: _blinkController, curve: Curves.easeInOut)); - + _blinkController = AnimationController( + duration: const Duration(milliseconds: 800), vsync: this) + ..repeat(reverse: true); + _colorAnimation = + ColorTween(begin: Colors.red.shade700, end: Colors.red.shade100) + .animate(_blinkController); + _shadowAnimation = Tween(begin: 2.0, end: 15.0).animate( + CurvedAnimation(parent: _blinkController, curve: Curves.easeInOut)); + _startPolling(); } @@ -54,8 +60,12 @@ class _PaymentScreenCliqState extends State with SingleTicker _pollingTimer = Timer.periodic(const Duration(seconds: 5), (timer) async { if (_status == 'success' || _status == 'verifying') return; try { - final res = await CRUD().postWallet(link: AppLink.checkCliqStatus, payload: {'invoice_number': widget.invoiceNumber}); - if (res != 'failure' && res['status'] == 'success' && res['invoice_status'] == 'completed') { + final res = await CRUD().postWallet( + link: AppLink.checkCliqStatus, + payload: {'invoice_number': widget.invoiceNumber}); + if (res != 'failure' && + res['status'] == 'success' && + res['invoice_status'] == 'completed') { timer.cancel(); if (mounted) setState(() => _status = 'success'); } @@ -65,26 +75,31 @@ class _PaymentScreenCliqState extends State with SingleTicker Future _submitProof() async { if (_proofController.text.trim().isEmpty) { - Get.snackbar('Error'.tr, 'Please paste the transfer message'.tr, backgroundColor: Colors.red); + Get.snackbar('Error'.tr, 'Please paste the transfer message'.tr, + backgroundColor: Colors.red); return; } setState(() => _status = 'verifying'); - + try { - final res = await CRUD().postWallet(link: AppLink.uploadCliqProof, payload: { + final res = + await CRUD().postWallet(link: AppLink.uploadCliqProof, payload: { 'invoice_number': widget.invoiceNumber, 'proof_text': _proofController.text.trim(), }); - + if (res != 'failure' && res['status'] == 'success') { if (mounted) setState(() => _status = 'success'); } else { if (mounted) setState(() => _status = 'error'); - Get.defaultDialog(title: 'Failed'.tr, content: Text(res['message']?.toString() ?? 'Verification failed')); + Get.defaultDialog( + title: 'Failed'.tr, + content: Text(res['message']?.toString() ?? 'Verification failed')); } } catch (e) { if (mounted) setState(() => _status = 'error'); - Get.defaultDialog(title: 'Error'.tr, content: Text('Error uploading proof'.tr)); + Get.defaultDialog( + title: 'Error'.tr, content: Text('Error uploading proof'.tr)); } } @@ -103,47 +118,124 @@ class _PaymentScreenCliqState extends State with SingleTicker Widget _buildWaitingUI() { final currencyFormat = NumberFormat.decimalPattern('ar_SY'); - + return SingleChildScrollView( child: Column( children: [ Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 15), - decoration: BoxDecoration(gradient: LinearGradient(colors: [Colors.blue.shade800, Colors.blue.shade600]), borderRadius: BorderRadius.circular(16)), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.blue.shade800, Colors.blue.shade600]), + borderRadius: BorderRadius.circular(16)), child: Column( children: [ - const Text("المبلغ المطلوب", style: TextStyle(color: Colors.white70, fontSize: 14)), + const Text("المبلغ المطلوب", + style: TextStyle(color: Colors.white70, fontSize: 14)), const SizedBox(height: 5), - Text('${widget.amount.toStringAsFixed(widget.amount == widget.amount.roundToDouble() ? 0 : 1)} JOD', - style: const TextStyle(color: Colors.white, fontSize: 32, fontWeight: FontWeight.w700, letterSpacing: 1)), + Text( + '${widget.amount.toStringAsFixed(widget.amount == widget.amount.roundToDouble() ? 0 : 1)} JOD', + style: const TextStyle( + color: Colors.white, + fontSize: 32, + fontWeight: FontWeight.w700, + letterSpacing: 1)), ], ), ), const SizedBox(height: 25), - AnimatedBuilder( animation: _blinkController, builder: (context, child) { return Container( padding: const EdgeInsets.all(20), - decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(16), border: Border.all(color: _colorAnimation.value ?? Colors.red, width: 3.0), boxShadow: [BoxShadow(color: (_colorAnimation.value ?? Colors.red).withOpacity(0.4), blurRadius: _shadowAnimation.value, spreadRadius: 2)]), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: _colorAnimation.value ?? Colors.red, width: 3.0), + boxShadow: [ + BoxShadow( + color: (_colorAnimation.value ?? Colors.red) + .withOpacity(0.4), + blurRadius: _shadowAnimation.value, + spreadRadius: 2) + ]), child: Column( children: [ - const Text("يرجى تحويل المبلغ إلى الاسم المستعار التالي (Alias):", textAlign: TextAlign.center, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + const Text( + "يرجى تحويل المبلغ إلى الاسم المستعار التالي (Alias):", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, fontWeight: FontWeight.bold)), + const SizedBox(height: 15), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.amber.shade50, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: Colors.amber.shade200)), + child: Column( + children: [ + const Text( + "⚠️ هام جداً: يجب إدخال رقم الفاتورة التالي في (ملاحظات التحويل) عند الدفع:", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14, + color: Colors.brown, + fontWeight: FontWeight.bold)), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(widget.invoiceNumber, + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.bold, + color: Colors.black)), + IconButton( + icon: const Icon(Icons.copy, + color: Colors.brown, size: 20), + onPressed: () { + Clipboard.setData(ClipboardData( + text: widget.invoiceNumber)); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text("تم نسخ رقم الفاتورة ✅", + textAlign: TextAlign.center), + backgroundColor: Colors.amber)); + }, + ), + ], + ), + ], + ), + ), const SizedBox(height: 15), InkWell( onTap: () { - Clipboard.setData(ClipboardData(text: widget.cliqAlias)); - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: const Text("تم نسخ الاسم ✅", textAlign: TextAlign.center), backgroundColor: Colors.green.shade600)); + Clipboard.setData( + ClipboardData(text: widget.cliqAlias)); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: const Text("تم نسخ الاسم ✅", + textAlign: TextAlign.center), + backgroundColor: Colors.green.shade600)); }, child: Container( padding: const EdgeInsets.all(15), - decoration: BoxDecoration(color: Colors.blue.shade50, borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.blue.shade200)), + decoration: BoxDecoration( + color: Colors.blue.shade50, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: Colors.blue.shade200)), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(widget.cliqAlias, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold, letterSpacing: 2.0)), + Text(widget.cliqAlias, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + letterSpacing: 2.0)), const Icon(Icons.copy, color: Colors.blue), ], ), @@ -154,16 +246,19 @@ class _PaymentScreenCliqState extends State with SingleTicker ); }, ), - const SizedBox(height: 30), - const Text("بعد إتمام التحويل، يرجى نسخ رسالة البنك النصية ولصقها هنا للتحقق التلقائي:", textAlign: TextAlign.center, style: TextStyle(fontSize: 14)), + const Text( + "بعد إتمام التحويل، يرجى نسخ رسالة البنك النصية ولصقها هنا للتحقق التلقائي:", + textAlign: TextAlign.center, + style: TextStyle(fontSize: 14)), const SizedBox(height: 10), TextField( controller: _proofController, maxLines: 4, decoration: InputDecoration( hintText: "قم بلصق نص رسالة التحويل هنا...", - border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), + border: + OutlineInputBorder(borderRadius: BorderRadius.circular(12)), filled: true, fillColor: Colors.white, ), @@ -173,15 +268,23 @@ class _PaymentScreenCliqState extends State with SingleTicker width: double.infinity, height: 50, child: ElevatedButton( - style: ElevatedButton.styleFrom(backgroundColor: Colors.blue.shade800, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12))), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue.shade800, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12))), onPressed: _status == 'verifying' ? null : _submitProof, - child: _status == 'verifying' - ? const CircularProgressIndicator(color: Colors.white) - : const Text("تحقق من الدفع", style: TextStyle(fontSize: 18, color: Colors.white, fontWeight: FontWeight.bold)), + child: _status == 'verifying' + ? const CircularProgressIndicator(color: Colors.white) + : const Text("تحقق من الدفع", + style: TextStyle( + fontSize: 18, + color: Colors.white, + fontWeight: FontWeight.bold)), ), ), const SizedBox(height: 20), - const Text("جاري فحص الفاتورة تلقائياً كل 5 ثوانٍ...", style: TextStyle(color: Colors.grey, fontSize: 12)), + const Text("جاري فحص الفاتورة تلقائياً كل 5 ثوانٍ...", + style: TextStyle(color: Colors.grey, fontSize: 12)), ], ), ); @@ -193,13 +296,20 @@ class _PaymentScreenCliqState extends State with SingleTicker children: [ const Icon(Icons.verified_rounded, color: Colors.green, size: 100), const SizedBox(height: 20), - const Text("تم الدفع بنجاح!", style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), + const Text("تم الدفع بنجاح!", + style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), const SizedBox(height: 40), SizedBox( width: double.infinity, child: ElevatedButton( - style: ElevatedButton.styleFrom(backgroundColor: Colors.green, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16)), - onPressed: () { Get.back(); Get.back(); }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.green, + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 16)), + onPressed: () { + Get.back(); + Get.back(); + }, child: const Text("متابعة", style: TextStyle(fontSize: 18)), ), ), diff --git a/siro_driver/lib/views/home/my_wallet/payment_screen_mtn.dart b/siro_driver/lib/views/home/my_wallet/payment_screen_mtn.dart index a4335710..b0616e0e 100644 --- a/siro_driver/lib/views/home/my_wallet/payment_screen_mtn.dart +++ b/siro_driver/lib/views/home/my_wallet/payment_screen_mtn.dart @@ -131,6 +131,30 @@ class _PaymentScreenMtnState extends State with SingleTickerPr children: [ const Text("يرجى تحويل المبلغ إلى الرقم التالي:", textAlign: TextAlign.center, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), const SizedBox(height: 15), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration(color: Colors.amber.shade50, borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.amber.shade200)), + child: Column( + children: [ + const Text("⚠️ هام جداً: يجب إدخال رقم الفاتورة التالي في (ملاحظات التحويل) عند الدفع:", textAlign: TextAlign.center, style: TextStyle(fontSize: 14, color: Colors.brown, fontWeight: FontWeight.bold)), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(widget.invoiceNumber, style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Colors.black)), + IconButton( + icon: const Icon(Icons.copy, color: Colors.brown, size: 20), + onPressed: () { + Clipboard.setData(ClipboardData(text: widget.invoiceNumber)); + ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("تم نسخ رقم الفاتورة ✅", textAlign: TextAlign.center), backgroundColor: Colors.amber)); + }, + ), + ], + ), + ], + ), + ), + const SizedBox(height: 15), InkWell( onTap: () { Clipboard.setData(ClipboardData(text: widget.mtnNumber)); diff --git a/siro_driver/lib/views/home/my_wallet/points_captain.dart b/siro_driver/lib/views/home/my_wallet/points_captain.dart index 925be6f2..3a6366e7 100755 --- a/siro_driver/lib/views/home/my_wallet/points_captain.dart +++ b/siro_driver/lib/views/home/my_wallet/points_captain.dart @@ -190,13 +190,7 @@ class PointsCaptain extends StatelessWidget { title: 'CliQ'.tr, subtitle: 'Pay via CliQ (Alias: siroapp)'.tr, color: Colors.purple, - onTap: () { - Get.back(); - MyDialog().getDialog( - 'CliQ Payment'.tr, - 'Please transfer the amount to alias: siroapp'.tr, - () => Get.back()); - }, + onTap: () => _showPhoneInputDialog(context, 'CliQ'), ), ], if (box.read(BoxName.countryCode) == 'Egypt') ...[ @@ -302,7 +296,7 @@ class PointsCaptain extends StatelessWidget { child: MyTextForm( controller: paymentController.walletphoneController, label: 'Phone Number'.tr, - hint: provider == 'Syriatel' ? '963991234567' : '963941234567', + hint: provider == 'Syriatel' ? '963991234567' : provider == 'CliQ' ? '0791234567' : '963941234567', type: TextInputType.phone, ), ), @@ -316,6 +310,9 @@ class PointsCaptain extends StatelessWidget { if (provider == 'Syriatel') { await payWithSyriaTelWallet( context, pricePoint.toString(), CurrencyHelper.currency); + } else if (provider == 'CliQ') { + captainWalletController.phoneWallet.text = paymentController.walletphoneController.text; + await captainWalletController.payWithClickWallet(context, pricePoint.toString(), CurrencyHelper.currency); } else { await payWithMTNWallet( context, pricePoint.toString(), CurrencyHelper.currency);