From ad79bf2af85af77d5b95e0b75574275304115392 Mon Sep 17 00:00:00 2001 From: Prince Date: Thu, 11 Jun 2026 16:33:22 +0200 Subject: [PATCH] adding CityWallet functionality --- assets/city.png | Bin 0 -> 34597 bytes lib/screens/accounts/account_provider.dart | 0 lib/screens/confirm/confirm_controller.dart | 69 +++++++-- lib/screens/confirm/confirm_screen.dart | 130 ++++++++++++++++ lib/screens/gateway/gateway_controller.dart | 22 ++- lib/screens/pay/pay_screen.dart | 160 ++++++++++++-------- lib/screens/poll/poll_screen.dart | 4 +- 7 files changed, 301 insertions(+), 84 deletions(-) create mode 100644 assets/city.png create mode 100644 lib/screens/accounts/account_provider.dart diff --git a/assets/city.png b/assets/city.png new file mode 100644 index 0000000000000000000000000000000000000000..9b82e7dffe8347c6c0679ed9a2d291940d58046c GIT binary patch literal 34597 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 literal 0 HcmV?d00001 diff --git a/lib/screens/accounts/account_provider.dart b/lib/screens/accounts/account_provider.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/screens/confirm/confirm_controller.dart b/lib/screens/confirm/confirm_controller.dart index 8b9d82c..fed2a7d 100644 --- a/lib/screens/confirm/confirm_controller.dart +++ b/lib/screens/confirm/confirm_controller.dart @@ -1,3 +1,4 @@ +import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -54,19 +55,21 @@ class ConfirmController extends ChangeNotifier { notifyListeners(); // todo: find out if we still need to update these fields - transactionController + transactionController.model.formData = transactionController .model - .formData = transactionController.model.formData.copyWith( - type: "REQUEST", - trace: transactionController.model.confirmationData['trace'], - id: transactionController.model.confirmationData['id'], - authType: transactionController.model.selectedPaymentProcessor.authType, - ); + .formData + .copyWith( + type: "REQUEST", + trace: transactionController.model.confirmationData['trace'], + id: transactionController.model.confirmationData['id'], + authType: + transactionController.model.selectedPaymentProcessor.authType, + ); dynamic workflowResponse = await http.get( '/public/transaction/request/' - '${transactionController.model.confirmationData['id']}/' - '${transactionController.model.selectedPaymentProcessor.authType}' + '${transactionController.model.confirmationData['id']}/' + '${transactionController.model.selectedPaymentProcessor.authType}', ); logger.i(workflowResponse.toString()); @@ -82,7 +85,9 @@ class ConfirmController extends ChangeNotifier { } else { model.status = response['status']; model.errorMessage = response['errorMessage']; - return ApiResponse.failure(response['errorMessage'] ?? "Transaction failed"); + return ApiResponse.failure( + response['errorMessage'] ?? "Transaction failed", + ); } } catch (e) { logger.e(e); @@ -125,6 +130,50 @@ class ConfirmController extends ChangeNotifier { return ApiResponse.failure("Polling cancelled"); } + Future>> updateVelocityTransactionOtp( + String id, + Map transaction, + ) async { + try { + model.isLoading = true; + notifyListeners(); + + dynamic response = await http.put( + '/public/transaction/$id/velocity-otp', + transaction, + ); + + model.isLoading = false; + notifyListeners(); + + if (response['status'] == 'SUCCESS') { + return ApiResponse.success(Map.from(response)); + } else { + model.errorMessage = + response['errorMessage'] ?? + "Problem updating transaction. Please try again or contact support"; + return ApiResponse.failure(model.errorMessage!); + } + } on DioException catch (e, s) { + if (kDebugMode) { + logger.e(e); + logger.e(s); + } + model.isLoading = false; + notifyListeners(); + return ApiResponse.failure( + "Network error. Please try again or contact support", + ); + } catch (e, s) { + logger.e(s); + model.isLoading = false; + notifyListeners(); + return ApiResponse.failure( + "Problem updating that transaction. Please try again or contact support", + ); + } + } + @override void dispose() { // TODO: implement dispose diff --git a/lib/screens/confirm/confirm_screen.dart b/lib/screens/confirm/confirm_screen.dart index fe6b14a..b479e07 100644 --- a/lib/screens/confirm/confirm_screen.dart +++ b/lib/screens/confirm/confirm_screen.dart @@ -78,6 +78,41 @@ class _ConfirmScreenState extends State if (!mounted) return; + // Check if the selected payment processor is a wallet (e.g. Velocity) + if (controller + .transactionController + .model + .selectedPaymentProcessor + .label == + 'WALLET') { + final otp = await _showOtpBottomSheet(); + if (otp == null) return; // User cancelled or dismissed the bottom sheet + + if (!mounted) return; + + final transactionId = + controller.transactionController.model.confirmationData['id']; + final otpResponse = await controller.updateVelocityTransactionOtp( + transactionId, + {'verificationCode': otp}, + ); + + if (!otpResponse.isSuccess) { + if (context.mounted) { + AppSnackBar.showError( + context, + controller.model.errorMessage ?? + otpResponse.error ?? + "OTP verification failed", + ); + } + return; + } + + if (!mounted) return; + } + + // Proceed with normal flow after OTP step (or skip if not WALLET) if (controller .transactionController .model @@ -99,6 +134,101 @@ class _ConfirmScreenState extends State } } + Future _showOtpBottomSheet() { + final otpController = TextEditingController(); + final formKey = GlobalKey(); + + return showModalBottomSheet( + context: context, + isDismissible: false, + enableDrag: false, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + builder: (context) { + return Padding( + padding: EdgeInsets.only( + left: 24, + right: 24, + top: 24, + bottom: MediaQuery.of(context).viewInsets.bottom + 24, + ), + child: Form( + key: formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: Colors.grey.shade300, + borderRadius: BorderRadius.circular(2), + ), + ), + ), + const SizedBox(height: 20), + Text( + 'OTP Verification', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: Theme.of(context).colorScheme.primary, + ), + ), + const SizedBox(height: 8), + Text( + 'Please enter the OTP sent to your mobile/email', + style: TextStyle(fontSize: 14, color: Colors.grey.shade600), + ), + const SizedBox(height: 20), + TextFormField( + controller: otpController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + labelText: 'Enter OTP', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + validator: (value) { + if (value == null || value.trim().isEmpty) { + return 'Please enter the OTP'; + } + return null; + }, + ), + const SizedBox(height: 20), + SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: () { + if (formKey.currentState!.validate()) { + Navigator.of(context).pop(otpController.text.trim()); + } + }, + style: ElevatedButton.styleFrom( + padding: const EdgeInsets.symmetric(vertical: 16), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + child: const Text( + 'Submit OTP', + style: TextStyle(fontSize: 16), + ), + ), + ), + ], + ), + ), + ); + }, + ); + } + @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/screens/gateway/gateway_controller.dart b/lib/screens/gateway/gateway_controller.dart index 126e547..1e085bc 100644 --- a/lib/screens/gateway/gateway_controller.dart +++ b/lib/screens/gateway/gateway_controller.dart @@ -49,8 +49,9 @@ class GatewayController extends ChangeNotifier { Future>> poll(String uid) async { startLoading(); try { - dynamic workflowResponse = - await http.get('/public/transaction/poll/$uid'); + dynamic workflowResponse = await http.get( + '/public/transaction/poll/$uid', + ); logger.i(workflowResponse.toString()); @@ -62,6 +63,10 @@ class GatewayController extends ChangeNotifier { finishLoading(); if (model.status == 'SUCCESS') { transactionController.updateReceiptData(response); + } else { + model.status = 'FAILED'; + model.errorMessage = response['errorMessage']; + return ApiResponse.failure(response['errorMessage']); } notifyListeners(); return ApiResponse.success(Map.from(response)); @@ -79,7 +84,7 @@ class GatewayController extends ChangeNotifier { Future>> pollTransaction(String uid) async { // poll up to 30 times (~5 minutes at 10-second intervals) - int maxAttempts = 30; + int maxAttempts = 15; int attempt = 0; while (!model.isCancelled && attempt < maxAttempts) { @@ -103,6 +108,9 @@ class GatewayController extends ChangeNotifier { // Otherwise (e.g. PENDING), continue polling } else { // Network error — show failure UI and stop + model.isCancelled = true; + model.status = 'FAILED'; + model.errorMessage = result.error; return result; } } @@ -118,7 +126,8 @@ class GatewayController extends ChangeNotifier { // Alternative method using Timer instead of while loop Future>> pollTransactionWithTimer( - String uid) async { + String uid, + ) async { _pollTimer = Timer.periodic(const Duration(seconds: 5), (timer) async { if (model.isCancelled) { timer.cancel(); @@ -145,7 +154,8 @@ class GatewayController extends ChangeNotifier { // This returns immediately; the caller should use the timer callback approach. // Consider refactoring this to use poll(String uid) directly for a consistent API. return ApiResponse.failure( - "Polling via timer started; use a different flow for the result"); + "Polling via timer started; use a different flow for the result", + ); } @override @@ -154,4 +164,4 @@ class GatewayController extends ChangeNotifier { _pollTimer?.cancel(); // Cancel timer if it exists super.dispose(); } -} \ No newline at end of file +} diff --git a/lib/screens/pay/pay_screen.dart b/lib/screens/pay/pay_screen.dart index 208e839..ce2322c 100644 --- a/lib/screens/pay/pay_screen.dart +++ b/lib/screens/pay/pay_screen.dart @@ -306,8 +306,38 @@ class _PayScreenState extends State with TickerProviderStateMixin { const SizedBox(height: 7), _buildAmountField(), const SizedBox(height: 20), - ...controller.model.paymentProcessors.map( - (e) => _buildPaymentProcessorItem(e, context), + LayoutBuilder( + builder: (context, wrapConstraints) { + final effectiveWidth = + constraints.maxWidth > + ResponsivePolicy.md + ? ResponsivePolicy.md.toDouble() + : constraints.maxWidth; + final columns = + effectiveWidth > ResponsivePolicy.sm + ? 2 + : 1; + final itemWidth = + (effectiveWidth - (columns - 1) * 10) / + columns; + return Wrap( + spacing: 10, + runSpacing: 10, + children: controller + .model + .paymentProcessors + .map( + (e) => SizedBox( + width: itemWidth, + child: _buildPaymentProcessorItem( + e, + context, + ), + ), + ) + .toList(), + ); + }, ), ], ), @@ -716,77 +746,73 @@ class _PayScreenState extends State with TickerProviderStateMixin { } Widget _buildPaymentProcessorItem(PaymentProcessor e, BuildContext context) { - return Column( - children: [ - Skeletonizer( - enabled: controller.model.isLoading, - child: SlideTransition( - position: - _animations[controller.model.paymentProcessors.indexOf(e)], - child: Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.black87.withAlpha(20)), - borderRadius: BorderRadius.circular(12), - gradient: LinearGradient( - colors: [ - Theme.of( - context, - ).colorScheme.primary.withValues(alpha: 0.1), - Theme.of( - context, - ).colorScheme.tertiary.withValues(alpha: 0.05), - ], - stops: const [0.3, 0.7], - begin: Alignment.topRight, - end: Alignment.bottomLeft, - ), - ), - child: InkWell( - customBorder: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - onTap: () async { - if (_formKey.currentState!.validate()) { - if (controller.model.isLoading) return; + final rawIndex = controller.model.paymentProcessors.indexOf(e); + final animation = rawIndex < _animations.length + ? _animations[rawIndex] + : _animations.isNotEmpty + ? _animations.last + : Tween( + begin: Offset.zero, + end: Offset.zero, + ).animate(_controller); + return Skeletonizer( + enabled: controller.model.isLoading, + child: SlideTransition( + position: animation, + child: Container( + decoration: BoxDecoration( + border: Border.all(color: Colors.black87.withAlpha(20)), + borderRadius: BorderRadius.circular(12), + gradient: LinearGradient( + colors: [ + Theme.of(context).colorScheme.primary.withValues(alpha: 0.1), + Theme.of(context).colorScheme.tertiary.withValues(alpha: 0.05), + ], + stops: const [0.3, 0.7], + begin: Alignment.topRight, + end: Alignment.bottomLeft, + ), + ), + child: InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + onTap: () async { + if (_formKey.currentState!.validate()) { + if (controller.model.isLoading) return; - await _submitPayment(e, context); - } - }, - child: ListTile( - leading: Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: Theme.of( - context, - ).colorScheme.primary.withValues(alpha: 0.1), - shape: BoxShape.circle, - ), - child: Image(image: AssetImage("assets/${e.image}")), - ), - title: Text( - e.name, - style: TextStyle(fontWeight: FontWeight.bold), - ), - subtitle: Text( - e.description, - style: TextStyle( - fontWeight: FontWeight.normal, - fontSize: 10, - ), - ), - trailing: Icon( - Icons.chevron_right, - color: Theme.of( - context, - ).colorScheme.secondary.withValues(alpha: 0.7), - ), + await _submitPayment(e, context); + } + }, + child: ListTile( + leading: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: Theme.of( + context, + ).colorScheme.primary.withValues(alpha: 0.1), + shape: BoxShape.circle, ), + child: Image(image: AssetImage("assets/${e.image}")), + ), + title: Text( + e.name, + style: TextStyle(fontWeight: FontWeight.bold), + ), + subtitle: Text( + e.description, + style: TextStyle(fontWeight: FontWeight.normal, fontSize: 10), + ), + trailing: Icon( + Icons.chevron_right, + color: Theme.of( + context, + ).colorScheme.secondary.withValues(alpha: 0.7), ), ), ), ), - SizedBox(height: 10), - ], + ), ); } } diff --git a/lib/screens/poll/poll_screen.dart b/lib/screens/poll/poll_screen.dart index 982ab61..3ec6d14 100644 --- a/lib/screens/poll/poll_screen.dart +++ b/lib/screens/poll/poll_screen.dart @@ -92,7 +92,9 @@ class _PollScreenState extends State { 'successful. This won\'t take long.', status: controller.model.status, isLoading: controller.model.isLoading, - errorMessage: 'We failed to check your transaction status', + errorMessage: + controller.model.errorMessage ?? + 'We failed to check your transaction status', onRetry: () { controller.model.isCancelled = false; _startPolling();