387 lines
14 KiB
Dart
387 lines
14 KiB
Dart
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';
|
|
import '../widgets/common/custom_app_bar.dart';
|
|
|
|
class TermsAgreementScreen extends StatefulWidget {
|
|
final bool isViewOnly;
|
|
final String? idToken;
|
|
|
|
const TermsAgreementScreen({
|
|
super.key,
|
|
this.isViewOnly = false,
|
|
this.idToken,
|
|
});
|
|
|
|
@override
|
|
State<TermsAgreementScreen> createState() => _TermsAgreementScreenState();
|
|
}
|
|
|
|
class _TermsAgreementScreenState extends State<TermsAgreementScreen> {
|
|
final List<bool> _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: CustomAppBar(title: widget.isViewOnly ? '이용 약관' : '회원가입'),
|
|
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(),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|