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 createState() => _StripeCheckoutScreenState(); } class _StripeCheckoutScreenState extends State { 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( AppColors.accentOrange), ), ) : null, ), body: WebViewWidget(controller: _controller), ); } }