1
0
forked from baron/baron-sso

동의 화면 '취소' 기능 및 확인 다이얼로그 구현

This commit is contained in:
2026-02-03 15:04:14 +09:00
parent 5bb48191e8
commit 69b1257ad7

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:userfront/core/services/auth_proxy_service.dart'; import 'package:userfront/core/services/auth_proxy_service.dart';
import 'package:userfront/core/services/web_window.dart'; import 'package:userfront/core/services/web_window.dart';
@@ -103,27 +104,60 @@ class _ConsentScreenState extends State<ConsentScreen> {
); );
if (result['redirectTo'] != null) { if (result['redirectTo'] != null) {
html.window.location.href = result['redirectTo']; webWindow.redirectTo(result['redirectTo']);
} else { } else {
setState(() { setState(() {
_error = '동의가 처리되었으나, 리다이렉트 URL을 받지 못했습니다.'; _error = '동의가 처리되었으나, 리다이렉트 URL을 받지 못했습니다.';
_isLoading = false; _isSubmitting = false;
}); });
} }
} catch (e) { } catch (e) {
setState(() { setState(() {
_error = '동의 처리에 실패했습니다: $e'; _error = '동의 처리에 실패했습니다: $e';
_isLoading = false; _isSubmitting = false;
}); });
} }
} }
void _onCancel() { Future<void> _onCancel() async {
// 취소 시 동작 (창 닫기 시도 또는 알림) final confirmed = await showDialog<bool>(
// 실제 프로덕션에서는 Hydra reject API를 호출하고 리다이렉트 하는 것이 좋습니다. context: context,
// 현재는 요구사항에 따라 간단히 처리합니다. builder: (context) => AlertDialog(
html.window.alert('동의 취소했습니다. 창을 닫아주세요.'); title: const Text('동의 취소'),
// html.window.close(); // 브라우저 정책상 스크립트로 연 창이 아니면 닫히지 않을 수 있음 content: const Text('권한 동의를 취소하면 해당 서비스를 이용할 수 없습니다. 취소하시겠습니까?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('아니오'),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
style: TextButton.styleFrom(foregroundColor: Colors.red),
child: const Text('예, 취소합니다'),
),
],
),
);
if (confirmed == true) {
setState(() => _isSubmitting = true);
try {
final resp = await AuthProxyService.rejectConsent(widget.consentChallenge);
final redirectTo = resp['redirectTo'];
if (redirectTo != null) {
webWindow.redirectTo(redirectTo);
} else {
if (mounted) context.go('/');
}
} catch (e) {
setState(() => _isSubmitting = false);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('취소 처리 중 오류가 발생했습니다: $e')),
);
}
}
}
} }
@override @override
@@ -299,7 +333,7 @@ class _ConsentScreenState extends State<ConsentScreen> {
// 4. 버튼 영역 // 4. 버튼 영역
ElevatedButton( ElevatedButton(
onPressed: _acceptConsent, onPressed: _isSubmitting ? null : _acceptConsent,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16), padding: const EdgeInsets.symmetric(vertical: 16),
backgroundColor: const Color(0xFF1A1F2C), // 브랜드 컬러 backgroundColor: const Color(0xFF1A1F2C), // 브랜드 컬러
@@ -309,14 +343,23 @@ class _ConsentScreenState extends State<ConsentScreen> {
), ),
elevation: 0, elevation: 0,
), ),
child: const Text( child: _isSubmitting
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Colors.white,
),
)
: const Text(
'동의하고 계속하기', '동의하고 계속하기',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
), ),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
OutlinedButton( OutlinedButton(
onPressed: _onCancel, onPressed: _isSubmitting ? null : _onCancel,
style: OutlinedButton.styleFrom( style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16), padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(