aligning logic to backend workflows
This commit is contained in:
@@ -79,7 +79,7 @@ class _MyAppState extends State<MyApp> {
|
||||
themeMode: ThemeMode.light, // Force light mode regardless of OS setting
|
||||
debugShowCheckedModeBanner: false,
|
||||
routerConfig: GoRouter(
|
||||
initialLocation: '/',
|
||||
initialLocation: '/receipt',
|
||||
routes: [
|
||||
ShellRoute(
|
||||
builder: (context, state, child) {
|
||||
|
||||
@@ -57,6 +57,7 @@ class ConfirmController extends ChangeNotifier {
|
||||
model.isLoading = true;
|
||||
notifyListeners();
|
||||
|
||||
// todo: find out if we still need to update these fields
|
||||
transactionController
|
||||
.model
|
||||
.formData = transactionController.model.formData.copyWith(
|
||||
@@ -66,11 +67,14 @@ class ConfirmController extends ChangeNotifier {
|
||||
authType: transactionController.model.selectedPaymentProcessor.authType,
|
||||
);
|
||||
|
||||
dynamic response = await http.post(
|
||||
'/public/transaction/request',
|
||||
transactionController.model.formData,
|
||||
dynamic workflowResponse = await http.get(
|
||||
'/public/transaction/request/'
|
||||
'${transactionController.model.confirmationData['id']}/'
|
||||
'${transactionController.model.selectedPaymentProcessor.authType}'
|
||||
);
|
||||
logger.i(response.toString());
|
||||
logger.i(workflowResponse.toString());
|
||||
|
||||
dynamic response = workflowResponse['body'];
|
||||
|
||||
if (response['status'] != 'FAILED') {
|
||||
model.status = response['status'];
|
||||
@@ -133,4 +137,11 @@ class ConfirmController extends ChangeNotifier {
|
||||
await Future.delayed(const Duration(seconds: 5));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
model.isCancelled = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,8 +58,11 @@ class GatewayController extends ChangeNotifier {
|
||||
if (model.isCancelled) break;
|
||||
|
||||
try {
|
||||
dynamic response = await http.get('/public/transaction/poll/$uid');
|
||||
logger.i(response.toString());
|
||||
dynamic workflowResponse = await http.get('/public/transaction/poll/$uid');
|
||||
|
||||
logger.i(workflowResponse.toString());
|
||||
|
||||
dynamic response = workflowResponse['body'];
|
||||
|
||||
if (response['status'] == 'SUCCESS') {
|
||||
model.status = response['status'];
|
||||
|
||||
@@ -101,6 +101,10 @@ class _HomeScreenState extends State<HomeScreen>
|
||||
});
|
||||
}
|
||||
|
||||
if(prefs.getString("userId") == null) {
|
||||
prefs.setString("userId", Uuid().v4());
|
||||
};
|
||||
|
||||
await homeController.getTransactions(prefs.getString("userId")!);
|
||||
}
|
||||
|
||||
@@ -197,7 +201,7 @@ class _HomeScreenState extends State<HomeScreen>
|
||||
actions: [
|
||||
if(_isLoggedIn)
|
||||
IconButton(
|
||||
icon: const Icon(Icons.exit_to_app_sharp),
|
||||
icon: const Icon(Icons.turn_slight_right_sharp),
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
@@ -525,16 +529,16 @@ class _HomeScreenState extends State<HomeScreen>
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Icon(
|
||||
e['status'] == 'SUCCESS'
|
||||
e['integrationStatus'] == 'SUCCESS'
|
||||
? Icons.check_circle
|
||||
: e['status'] == 'PENDING'
|
||||
: e['integrationStatus'] == 'PENDING'
|
||||
? Icons.pending
|
||||
: Icons.cancel,
|
||||
size: 16,
|
||||
color:
|
||||
e['status'] == 'SUCCESS'
|
||||
e['integrationStatus'] == 'SUCCESS'
|
||||
? Colors.green
|
||||
: e['status'] == 'PENDING'
|
||||
: e['integrationStatus'] == 'PENDING'
|
||||
? Colors.orange
|
||||
: Colors.red,
|
||||
),
|
||||
|
||||
@@ -111,11 +111,13 @@ class PayController extends ChangeNotifier {
|
||||
productUid: model.selectedProduct?.uid,
|
||||
);
|
||||
|
||||
dynamic response = await http.post(
|
||||
dynamic workflowResponse = await http.post(
|
||||
'/public/transaction',
|
||||
transactionController.model.formData,
|
||||
);
|
||||
logger.i(response.toString());
|
||||
logger.i(workflowResponse.toString());
|
||||
|
||||
dynamic response = workflowResponse['body'];
|
||||
|
||||
if (response['status'] == 'SUCCESS') {
|
||||
model.status = response['status'];
|
||||
|
||||
@@ -73,7 +73,7 @@ class _PayScreenState extends State<PayScreen> with TickerProviderStateMixin {
|
||||
transactionController.model.formData.creditEmail ?? '';
|
||||
|
||||
// Initialize phone number and country code
|
||||
updatePhoneNumber(transactionController.model.formData.creditPhone ?? '');
|
||||
// updatePhoneNumber(transactionController.model.formData.creditPhone ?? '');
|
||||
|
||||
_controller = AnimationController(
|
||||
vsync: this,
|
||||
@@ -296,7 +296,7 @@ class _PayScreenState extends State<PayScreen> with TickerProviderStateMixin {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'Notification Phone Number',
|
||||
'Debit Phone Number',
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||
),
|
||||
TextButton(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:qpay/screens/gateway/gateway_controller.dart';
|
||||
import 'package:qpay/screens/transaction_controller.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:qpay/screens/receipt/receipt_controller.dart';
|
||||
@@ -17,6 +18,7 @@ class ReceiptScreen extends StatefulWidget {
|
||||
class _ReceiptScreenState extends State<ReceiptScreen>
|
||||
with TickerProviderStateMixin {
|
||||
late TransactionController transactionController;
|
||||
late GatewayController gatewayController;
|
||||
late Animation<double> _fadeAnimation;
|
||||
late Animation<Offset> _slideAnimation;
|
||||
late AnimationController _controller;
|
||||
@@ -34,7 +36,7 @@ class _ReceiptScreenState extends State<ReceiptScreen>
|
||||
context,
|
||||
listen: false,
|
||||
);
|
||||
|
||||
gatewayController = GatewayController(context);
|
||||
receiptController = ReceiptController(context);
|
||||
|
||||
receiptController.getReceiptData(
|
||||
@@ -81,6 +83,25 @@ class _ReceiptScreenState extends State<ReceiptScreen>
|
||||
}
|
||||
}
|
||||
|
||||
_retry() async {
|
||||
receiptController.setLoading(true);
|
||||
await gatewayController.pollTransaction(receiptController.model.receiptData?["id"]);
|
||||
if(gatewayController.model.status == "SUCCESS"){
|
||||
receiptController.getReceiptData(transactionController.model.receiptData?["id"]);
|
||||
}
|
||||
receiptController.setLoading(false);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
_controller.dispose();
|
||||
_tabController.dispose();
|
||||
gatewayController.dispose();
|
||||
receiptController.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@@ -174,12 +195,12 @@ class _ReceiptScreenState extends State<ReceiptScreen>
|
||||
Icon(
|
||||
transactionController
|
||||
.model
|
||||
.receiptData?["status"] ==
|
||||
.receiptData?["integrationStatus"] ==
|
||||
'SUCCESS'
|
||||
? Icons.check_circle
|
||||
: transactionController
|
||||
.model
|
||||
.receiptData?["status"] ==
|
||||
.receiptData?["integrationStatus"] ==
|
||||
'PENDING'
|
||||
? Icons.pending
|
||||
: Icons.cancel,
|
||||
@@ -187,12 +208,12 @@ class _ReceiptScreenState extends State<ReceiptScreen>
|
||||
color:
|
||||
transactionController
|
||||
.model
|
||||
.receiptData?["status"] ==
|
||||
.receiptData?["integrationStatus"] ==
|
||||
'SUCCESS'
|
||||
? Colors.green
|
||||
: transactionController
|
||||
.model
|
||||
.receiptData?["status"] ==
|
||||
.receiptData?["integrationStatus"] ==
|
||||
'PENDING'
|
||||
? Colors.orange
|
||||
: Colors.red,
|
||||
@@ -338,9 +359,9 @@ class _ReceiptScreenState extends State<ReceiptScreen>
|
||||
icon: Icon(
|
||||
Icons.share,
|
||||
color:
|
||||
Theme.of(
|
||||
context,
|
||||
).colorScheme.primary,
|
||||
Theme.of(
|
||||
context,
|
||||
).colorScheme.primary,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
@@ -355,6 +376,48 @@ class _ReceiptScreenState extends State<ReceiptScreen>
|
||||
),
|
||||
],
|
||||
),
|
||||
if(receiptController.model.receiptData?["integrationStatus"] == "PENDING" &&
|
||||
receiptController.model.receiptData?["paymentStatus"] == "SUCCESS")
|
||||
Column(
|
||||
children: [
|
||||
Container(
|
||||
width: 50,
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.white,
|
||||
border: Border.all(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary
|
||||
.withOpacity(0.3),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
_retry();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.redo,
|
||||
color:
|
||||
Theme.of(
|
||||
context,
|
||||
).colorScheme.primary,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Text(
|
||||
"Retry",
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -437,7 +500,7 @@ class _ReceiptScreenState extends State<ReceiptScreen>
|
||||
Text(
|
||||
transactionController
|
||||
.model
|
||||
.receiptData?["status"] ??
|
||||
.receiptData?["integrationStatus"] ??
|
||||
"",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
@@ -446,6 +509,49 @@ class _ReceiptScreenState extends State<ReceiptScreen>
|
||||
],
|
||||
),
|
||||
),
|
||||
if(transactionController
|
||||
.model
|
||||
.receiptData?["errorMessage"] != null &&
|
||||
transactionController.model.receiptData?["errorMessage"] != "")
|
||||
Column(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
Skeletonizer(
|
||||
enabled:
|
||||
receiptController
|
||||
.model
|
||||
.isLoading,
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Message",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight:
|
||||
FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
transactionController
|
||||
.model
|
||||
.receiptData?["errorMessage"] ??
|
||||
"",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
textAlign: TextAlign.end,
|
||||
softWrap: true,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Skeletonizer(
|
||||
enabled:
|
||||
|
||||
Reference in New Issue
Block a user