completed velocity integration

This commit is contained in:
2026-05-27 19:01:24 +02:00
parent fec46fb6e9
commit 6fdd3183fb
29 changed files with 2760 additions and 2293 deletions

View File

@@ -1,13 +1,16 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'package:qpay/models/responsive_policy.dart';
import 'package:qpay/screens/gateway/gateway_controller.dart';
import 'package:qpay/screens/transaction_controller.dart';
import 'package:skeletonizer/skeletonizer.dart';
import 'package:qpay/widgets/step_loading_widget.dart';
import 'package:web/web.dart' as web;
class PollScreen extends StatefulWidget {
const PollScreen({super.key});
final String? transactionId;
const PollScreen({super.key, this.transactionId});
@override
State<PollScreen> createState() => _PollScreenState();
@@ -17,8 +20,6 @@ class _PollScreenState extends State<PollScreen> {
late GatewayController controller;
late TransactionController transactionController;
bool integrating = false;
@override
void initState() {
super.initState();
@@ -28,21 +29,35 @@ class _PollScreenState extends State<PollScreen> {
listen: false,
);
controller.pollTransaction(transactionController.model.confirmationData['id']);
_startPolling();
}
void _showErrorSnackBar(String? message) {
WidgetsBinding.instance.addPostFrameCallback((_) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message.toString()),
behavior: SnackBarBehavior.floating,
backgroundColor: Colors.deepOrange,
),
);
});
}
void _startPolling() {
// Priority 1: transaction ID passed via route param (/poll/:id)
String? transactionId = widget.transactionId;
// Priority 2: localStorage (for when gateway redirect causes page reload
// and the route param path is not available due to hub redirect override)
if (transactionId == null && kIsWeb) {
transactionId = web.window.localStorage.getItem('pendingTransactionId');
web.window.localStorage.removeItem('pendingTransactionId');
}
// Priority 3: in-memory confirmation data (normal SPA navigation)
if (transactionId == null) {
try {
transactionId =
transactionController.model.confirmationData['id'] as String?;
} catch (_) {
// confirmationData is late and may not be initialized
// after a page reload -- ignore
}
}
if (transactionId != null && transactionId.isNotEmpty) {
controller.pollTransaction(transactionId);
}
}
@override
void dispose() {
@@ -55,6 +70,10 @@ class _PollScreenState extends State<PollScreen> {
return Scaffold(
appBar: AppBar(
title: const Text('Completing your transaction'),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => context.go('/'),
),
),
body: ListenableBuilder(
listenable: controller,
@@ -65,60 +84,19 @@ class _PollScreenState extends State<PollScreen> {
});
}
return Container(
padding: EdgeInsets.all(50),
child: Center(
child: LayoutBuilder(
builder: (context, constraints) {
return SizedBox(
width: double.parse(constraints.maxWidth > ResponsivePolicy.md ?
ResponsivePolicy.md.toString() :
constraints.maxWidth.toString()),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: 75),
Column(
children: [
Text(
'We\'re checking with our gateway if your transaction was successful. This won\'t take long',
style: TextStyle(fontSize: 20),
textAlign: TextAlign.center,
),
SizedBox(height: 50,),
Image.asset('assets/velocity-animation.gif', width: 150),
SizedBox(height: 50),
if(controller.model.status == 'FAILED')
Column(
children: [
Text(
'We failed to check your transaction status',
style: TextStyle(fontSize: 20),
textAlign: TextAlign.center,
),
SizedBox(height: 20,),
Skeletonizer(
enabled: controller.model.isLoading,
child: OutlinedButton(
child: Text('Retry'),
onPressed: () {
controller.model.isCancelled = false;
controller.pollTransaction(transactionController.model.confirmationData['id']);
},
),
),
],
),
],
),
],
),
);
}
),
),
return StepLoadingWidget(
currentStep: 1,
title: 'Verifying Payment',
subtitle:
'We\'re checking with our gateway if your transaction was '
'successful. This won\'t take long.',
status: controller.model.status,
isLoading: controller.model.isLoading,
errorMessage: 'We failed to check your transaction status',
onRetry: () {
controller.model.isCancelled = false;
_startPolling();
},
);
},
),