import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../core/auth_repository.dart'; import '../../core/session_controller.dart'; import '../../theme/toss_theme.dart'; /// New accounts only. Pre-seeded demo users (`alice@demo.msn`) are for sign-in, not registration. class RegisterPage extends ConsumerStatefulWidget { const RegisterPage({super.key}); @override ConsumerState createState() => _RegisterPageState(); } class _RegisterPageState extends ConsumerState { final _email = TextEditingController(); final _password = TextEditingController(); final _name = TextEditingController(); String? _error; bool _busy = false; @override void dispose() { _email.dispose(); _password.dispose(); _name.dispose(); super.dispose(); } Future _submit() async { setState(() { _busy = true; _error = null; }); try { final r = await ref.read(authRepositoryProvider).register( email: _email.text.trim(), password: _password.text, displayName: _name.text.trim().isEmpty ? null : _name.text.trim(), ); await ref.read(sessionProvider.notifier).applyLogin( userId: r.userId, email: _email.text.trim(), defaultContextId: r.defaultContextId, ); if (!mounted) return; context.go('/'); } catch (e) { setState(() => _error = e.toString()); } finally { if (mounted) setState(() => _busy = false); } } @override Widget build(BuildContext context) { final tt = Theme.of(context).textTheme; return Scaffold( backgroundColor: TossColors.bg, appBar: AppBar(title: const Text('회원가입')), body: SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text('새 계정 만들기', style: tt.headlineMedium), const SizedBox(height: 8), Text( '데모 계정은 로그인 화면에서 이용해 주세요.', style: tt.bodySmall, ), const SizedBox(height: 28), TextField( controller: _email, decoration: const InputDecoration( labelText: '이메일', prefixIcon: Icon(Icons.mail_outline_rounded, color: TossColors.textSecondary), ), keyboardType: TextInputType.emailAddress, ), const SizedBox(height: 12), TextField( controller: _password, decoration: const InputDecoration( labelText: '비밀번호', prefixIcon: Icon(Icons.lock_outline_rounded, color: TossColors.textSecondary), ), obscureText: true, ), const SizedBox(height: 12), TextField( controller: _name, decoration: const InputDecoration( labelText: '표시 이름 (선택)', prefixIcon: Icon(Icons.badge_outlined, color: TossColors.textSecondary), ), ), if (_error != null) ...[ const SizedBox(height: 12), Text( _error!, style: TextStyle(color: Theme.of(context).colorScheme.error, fontSize: 13), ), ], const SizedBox(height: 28), SizedBox( height: 52, child: FilledButton( onPressed: _busy ? null : _submit, child: _busy ? const SizedBox( height: 22, width: 22, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white), ) : const Text('가입하기'), ), ), TextButton( onPressed: _busy ? null : () => context.go('/login'), child: const Text('로그인으로 돌아가기'), ), ], ), ), ), ); } }