Files
mobile-app/lib/features/profile/presentation/screens/stripe_checkout_screen.dart

100 lines
3.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:real_estate_mobile/core/constants/app_colors.dart';
/// In-app WebView for Stripe Checkout / Billing Portal.
/// Pass [url] to load and [successUrlPattern] to detect completion.
class StripeCheckoutScreen extends StatefulWidget {
final String url;
final String title;
/// URL pattern that indicates checkout success (e.g. your success redirect URL).
final String? successUrlPattern;
const StripeCheckoutScreen({
super.key,
required this.url,
this.title = 'Checkout',
this.successUrlPattern,
});
@override
State<StripeCheckoutScreen> createState() => _StripeCheckoutScreenState();
}
class _StripeCheckoutScreenState extends State<StripeCheckoutScreen> {
late final WebViewController _controller;
bool _isLoading = true;
double _progress = 0;
@override
void initState() {
super.initState();
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onPageStarted: (_) {
if (mounted) setState(() => _isLoading = true);
},
onPageFinished: (_) {
if (mounted) setState(() => _isLoading = false);
},
onProgress: (progress) {
if (mounted) setState(() => _progress = progress / 100);
},
onNavigationRequest: (request) {
// Detect success redirect
if (widget.successUrlPattern != null &&
request.url.contains(widget.successUrlPattern!)) {
// Extract session_id if present
final uri = Uri.parse(request.url);
final sessionId = uri.queryParameters['session_id'];
Navigator.of(context).pop({'success': true, 'sessionId': sessionId});
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
),
)
..loadRequest(Uri.parse(widget.url));
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
leading: IconButton(
icon: const Icon(Icons.close, color: AppColors.primaryDark),
onPressed: () => Navigator.of(context).pop(null),
),
title: Text(
widget.title,
style: const TextStyle(
fontFamily: 'Fractul',
fontSize: 18,
fontWeight: FontWeight.w700,
color: AppColors.primaryDark,
),
),
centerTitle: true,
bottom: _isLoading
? PreferredSize(
preferredSize: const Size.fromHeight(3),
child: LinearProgressIndicator(
value: _progress,
backgroundColor: Colors.grey.shade200,
valueColor: const AlwaysStoppedAnimation<Color>(
AppColors.accentOrange),
),
)
: null,
),
body: WebViewWidget(controller: _controller),
);
}
}