import 'package:flutter/material.dart'; import 'package:descope/descope.dart'; import 'package:go_router/go_router.dart'; import '../../../../core/services/auth_proxy_service.dart'; class ApproveQrScreen extends StatefulWidget { final String? pendingRef; const ApproveQrScreen({super.key, this.pendingRef}); @override State createState() => _ApproveQrScreenState(); } class _ApproveQrScreenState extends State { bool _isLoading = false; String? _message; bool _success = false; Future _handleApprove() async { if (widget.pendingRef == null) return; final session = Descope.sessionManager.session; if (session == null || session.refreshToken.isExpired) { setState(() => _message = "Please log in on your phone first."); context.go('/signin'); // Redirect to login return; } setState(() { _isLoading = true; _message = null; }); // jwt 유효성 확인 try { await AuthProxyService.approveQrLogin( widget.pendingRef!, session.sessionToken.jwt, ); setState(() { _success = true; _message = "Login Approved! Your browser should now be logged in."; }); // Automatically go to dashboard after a short delay Future.delayed(const Duration(seconds: 1), () { if (mounted) context.go('/'); }); } catch (e) { setState(() => _message = "Error: $e"); } finally { setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { final isLoggedIn = Descope.sessionManager.session?.refreshToken.isExpired == false; return Scaffold( appBar: AppBar(title: const Text("QR Login Approval")), body: Center( child: Padding( padding: const EdgeInsets.all(24.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.phonelink_lock, size: 80, color: Colors.blue), const SizedBox(height: 24), const Text( "Web Login Request", style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold), ), const SizedBox(height: 16), Text( "A computer is trying to log in using this QR code.", textAlign: TextAlign.center, style: TextStyle(color: Colors.grey.shade600), ), const SizedBox(height: 40), if (_message != null) Padding( padding: const EdgeInsets.only(bottom: 20), child: Text( _message!, style: TextStyle(color: _success ? Colors.green : Colors.red, fontWeight: FontWeight.bold), textAlign: TextAlign.center, ), ), if (!_success) FilledButton.icon( onPressed: _isLoading || !isLoggedIn ? null : _handleApprove, icon: const Icon(Icons.check_circle), label: const Text("Approve Login"), style: FilledButton.styleFrom( minimumSize: const Size.fromHeight(60), backgroundColor: Colors.blue, ), ), if (!isLoggedIn && !_success) Padding( padding: const EdgeInsets.only(top: 16), child: TextButton( onPressed: () => context.go('/signin'), child: const Text("Login on this device first"), ), ), if (_success) FilledButton( onPressed: () => context.go('/'), child: const Text("Go to My Dashboard"), ), ], ), ), ), ); } }