import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; // Import screenutil import 'identity_verification_screen.dart'; import '../services/auth_service.dart'; // Import AuthService import '../data/terms_data.dart'; class TermsAgreementScreen extends StatefulWidget { final bool isViewOnly; final String? idToken; const TermsAgreementScreen({ super.key, this.isViewOnly = false, this.idToken, }); @override State createState() => _TermsAgreementScreenState(); } class _TermsAgreementScreenState extends State { final List _checks = [false, false, false, false, false, false]; bool get _isAllChecked => _checks.every((completed) => completed); bool get _isRequiredChecked => _checks[0] && _checks[1] && _checks[2] && _checks[3]; void _toggleAll() { setState(() { bool newValue = !_isAllChecked; for (int i = 0; i < _checks.length; i++) { _checks[i] = newValue; } }); } void _toggleItem(int index) { setState(() { _checks[index] = !_checks[index]; }); } String _getTermContent(int index) { if (index >= 0 && index < TermsData.terms.length) { return TermsData.terms[index]['content'] ?? '내용이 없습니다.'; } return '내용이 없습니다.'; } void _showTermDetail(BuildContext context, String title, int index) { showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (context) { return DraggableScrollableSheet( initialChildSize: 0.7, minChildSize: 0.5, maxChildSize: 0.9, builder: (_, controller) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(20.r)), ), padding: EdgeInsets.all(20.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: Container( width: 40.w, height: 4.h, decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(2.r), ), ), ), SizedBox(height: 20.h), Text( title, style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.bold, fontFamily: 'SCDream', ), ), SizedBox(height: 20.h), Expanded( child: SingleChildScrollView( controller: controller, child: Text( _getTermContent(index), style: TextStyle( fontSize: 15.sp, height: 1.6, fontFamily: 'SCDream', color: Colors.black87, ), ), ), ), SizedBox(height: 20.h), SizedBox( width: double.infinity, height: 52.h, child: ElevatedButton( onPressed: () => Navigator.pop(context), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFFFF7500), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30.r), ), elevation: 0, ), child: Text( '확인', style: TextStyle( color: Colors.white, fontSize: 16.sp, fontWeight: FontWeight.bold, fontFamily: 'SCDream', ), ), ), ), ], ), ); }, ); }, ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( backgroundColor: Colors.white, elevation: 0, leading: IconButton( icon: Icon(Icons.arrow_back_ios, color: Colors.black, size: 20.w), onPressed: () => Navigator.pop(context), ), title: Text( widget.isViewOnly ? '이용 약관' : '회원가입', style: TextStyle( color: Colors.black, fontSize: 16.sp, fontWeight: FontWeight.w600, fontFamily: 'SCDream', ), ), centerTitle: true, ), body: SafeArea( child: Column( children: [ Expanded( child: SingleChildScrollView( padding: EdgeInsets.symmetric(horizontal: 20.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 20.h), // Header Area Row( children: [ Image.asset( 'assets/img/foot.png', width: 24.w, height: 24.h, ), SizedBox(width: 8.w), Text( '서비스 이용 약관', style: TextStyle( fontSize: 22.sp, fontWeight: FontWeight.bold, fontFamily: 'SCDream', color: Colors.black, ), ), ], ), SizedBox(height: 8.h), Text( widget.isViewOnly ? 'RUP 서비스의 이용 약관 내용입니다.' : '서비스 이용을 위해 약관에 동의해주세요.', style: TextStyle( fontSize: 15.sp, color: Colors.black54, fontFamily: 'SCDream', ), ), SizedBox(height: 30.h), // All Agree Box - *ViewOnly 모드에서는 숨김* if (!widget.isViewOnly) ...[ InkWell( onTap: () => _toggleAll(), borderRadius: BorderRadius.circular(8.r), child: Container( padding: EdgeInsets.symmetric( vertical: 16.h, horizontal: 16.w, ), decoration: BoxDecoration( border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(8.r), ), child: Row( children: [ Icon( _isAllChecked ? Icons.radio_button_checked : Icons.radio_button_off, color: _isAllChecked ? const Color(0xFFFF7500) : Colors.grey, ), SizedBox(width: 12.w), Text( '모든 약관에 동의합니다.', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.bold, fontFamily: 'SCDream', ), ), ], ), ), ), SizedBox(height: 20.h), Divider(height: 1.h, color: const Color(0xFFEEEEEE)), SizedBox(height: 10.h), ], // Individual Items _buildTermItem(0, '이용약관 동의', isRequired: true), _buildTermItem(1, '개인정보 수집 및 이용 동의', isRequired: true), _buildTermItem(2, '제 3자 제공 동의', isRequired: true), _buildTermItem(3, '만 14세 이상 사용자', isRequired: true), _buildTermItem(4, '위치정보 이용 동의', isRequired: false), _buildTermItem(5, '마케팅 수신 동의', isRequired: false), ], ), ), ), // Bottom Button Padding( padding: EdgeInsets.fromLTRB(20.w, 10.h, 20.w, 20.h), child: SizedBox( width: double.infinity, height: 52.h, child: ElevatedButton( onPressed: widget.isViewOnly ? () => Navigator.pop(context) : (_isRequiredChecked ? () async { if (widget.idToken != null) { // 실제 가입 요청 (DB 생성) final success = await AuthService() .registerWithGoogle(widget.idToken!); if (success && context.mounted) { Navigator.push( context, MaterialPageRoute( builder: (context) => const IdentityVerificationScreen(), ), ); } else if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('회원가입 처리에 실패했습니다.'), ), ); } } else { // idToken이 없는 경우 (테스트 등) - 그냥 진행 Navigator.push( context, MaterialPageRoute( builder: (context) => const IdentityVerificationScreen(), ), ); } } : null), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFFFF7500), disabledBackgroundColor: Colors.grey[300], shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30.r), ), elevation: 0, ), child: Text( widget.isViewOnly ? '닫기' : '동의하고 본인 인증하기', style: TextStyle( color: Colors.white, fontSize: 16.sp, fontWeight: FontWeight.bold, fontFamily: 'SCDream', ), ), ), ), ), ], ), ), ); } Widget _buildTermItem(int index, String title, {required bool isRequired}) { // ViewOnly 모드에서는 체크박스 숨김 // ViewOnly 모드에서는 텍스트 클릭 시 모달 띄우기 (토글 X) return Padding( padding: EdgeInsets.symmetric(vertical: 4.h), child: Row( children: [ Expanded( child: InkWell( onTap: () { if (!widget.isViewOnly) { _toggleItem(index); } else { // ViewOnly일 땐 텍스트 눌러도 모달 띄우기 (편의성) _showTermDetail(context, title, index); } }, borderRadius: BorderRadius.circular(8.r), child: Padding( padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 8.w), child: Row( children: [ // 체크 Icon - *ViewOnly 모드에서는 숨김* if (!widget.isViewOnly) ...[ Icon( Icons.check, size: 20.w, color: _checks[index] ? const Color(0xFFFF7500) : Colors.grey[300], ), SizedBox(width: 12.w), ], Text( isRequired ? '필수' : '선택', style: TextStyle( color: isRequired ? const Color(0xFFFF7500) : Colors.grey, fontWeight: FontWeight.bold, fontSize: 14.sp, fontFamily: 'SCDream', ), ), SizedBox(width: 8.w), Expanded( child: Text( title, style: TextStyle( fontSize: 15.sp, color: Colors.black87, fontFamily: 'SCDream', ), ), ), ], ), ), ), ), IconButton( onPressed: () => _showTermDetail(context, title, index), icon: Icon( Icons.arrow_forward_ios, size: 14.w, color: Colors.black, ), splashRadius: 20.r, padding: EdgeInsets.all(12.w), constraints: const BoxConstraints(), ), ], ), ); } }