From b34802b894953554178a467ac0e0ad3e105c53c0 Mon Sep 17 00:00:00 2001 From: eld_master Date: Mon, 20 Jan 2025 14:45:55 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BD=94=EB=93=9C=201=EC=B0=A8=20=EC=B5=9C?= =?UTF-8?q?=EC=A2=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/build.gradle | 27 +++- lib/config/config.dart | 6 +- lib/dialogs/settings_dialog.dart | 17 +++ lib/plugins/api.dart | 5 +- lib/survey/survey_page.dart | 1 - .../inquiry/inquiry_to_manager_page.dart | 121 ++++++++++++++++++ lib/views/login/id_finding_page.dart | 5 +- lib/views/login/login_page.dart | 17 +-- lib/views/login/pw_finding_page.dart | 4 +- lib/views/login/signup_page.dart | 1 - lib/views/room/main_page.dart | 4 +- lib/views/room/playing_private_page.dart | 3 +- lib/views/room/playing_team_page.dart | 2 +- lib/views/room/room_search_home_page.dart | 6 +- lib/views/room/room_search_list_page.dart | 4 +- lib/views/room/waiting_room_private_page.dart | 15 ++- lib/views/room/waiting_room_team_page.dart | 8 +- lib/views/user/my_page.dart | 5 - lib/views/user/withdrawal_page.dart | 55 ++++++-- 19 files changed, 233 insertions(+), 73 deletions(-) create mode 100644 lib/views/inquiry/inquiry_to_manager_page.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index c9b2b8e..9b7d7c8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -6,6 +6,12 @@ plugins { id "dev.flutter.flutter-gradle-plugin" } +def keystoreProperties = new Properties() +def keystorePropertiesFile = rootProject.file('app/key.properties') +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) +} + android { namespace = "com.allscore_app" compileSdkVersion 34 @@ -20,9 +26,27 @@ android { // ... + signingConfigs { + release { + // key.properties 에서 키 불러오기 + keyAlias keystoreProperties["keyAlias"] + keyPassword keystoreProperties["keyPassword"] + storeFile keystoreProperties["storeFile"] ? file(keystoreProperties["storeFile"]) : null + storePassword keystoreProperties["storePassword"] + } + } + buildTypes { release { - signingConfig signingConfigs.debug + // signingConfig signingConfigs.debug + // 코드 난독화, 리소스 축소 등 필요 시 설정 + minifyEnabled false + shrinkResources false + // (중요) release 시 signing 적용 + signingConfig signingConfigs.release + } + debug { + // 기본 debug 서명 } } @@ -42,6 +66,7 @@ flutter { dependencies { // 기존 의존성 ... implementation 'com.google.android.gms:play-services-auth:20.6.0' + implementation 'com.google.android.gms:play-services-ads:23.6.0' } // (Firebase Auth, Crashlytics 등을 사용한다면, 아래 구문이 필요할 수 있습니다.) diff --git a/lib/config/config.dart b/lib/config/config.dart index f7aef9d..a177ef3 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -2,7 +2,11 @@ class Config { // 테스트 광고 단위 ID static const String testAdUnitId = 'ca-app-pub-3940256099942544/6300978111'; // 실제 광고 단위 ID - static const String realAdUnitId = 'ca-app-pub-3940256099942544/6300978111'; + static const String realAdUnitId = 'ca-app-pub-6461991944599918~9492697896'; + // 테스트 광고 단위 ID + static const String adUnitId = 'ca-app-pub-6461991944599918~9492697896'; // 서버 주소 static const String baseUrl = 'https://eldsoft.com:8097'; + // 이미지 업로드 주소 + static const String uploadImageUrl = '$baseUrl/user/update/profile/img'; } \ No newline at end of file diff --git a/lib/dialogs/settings_dialog.dart b/lib/dialogs/settings_dialog.dart index b7d77fa..b4c4394 100644 --- a/lib/dialogs/settings_dialog.dart +++ b/lib/dialogs/settings_dialog.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; // SharedPreferences 임포트 import '../views/login/login_page.dart'; // 로그인 페이지 임포트 (상위 디렉토리로 이동) import '../views/user/my_page.dart'; // 마이페이지 임포트 (상위 디렉토리로 이동) +import '../views/inquiry/inquiry_to_manager_page.dart'; // 문의하기 페이지 임포트 (상위 디렉토리로 이동) void showSettingsDialog(BuildContext context) { showDialog( @@ -62,6 +63,22 @@ void showSettingsDialog(BuildContext context) { ), ), const SizedBox(height: 10), + SizedBox( + width: double.infinity, + child: TextButton( + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => const InquiryToManagerPage()), // 문의하기 페이지로 이동 + ); + }, + style: ButtonStyle( + side: MaterialStateProperty.all(const BorderSide(color: Colors.black)), + foregroundColor: MaterialStateProperty.all(Colors.black), + ), + child: const Text('문의하기'), + ), + ), + const SizedBox(height: 10), SizedBox( width: double.infinity, child: TextButton( diff --git a/lib/plugins/api.dart b/lib/plugins/api.dart index 447ca83..4254314 100644 --- a/lib/plugins/api.dart +++ b/lib/plugins/api.dart @@ -53,7 +53,7 @@ class Api { SharedPreferences prefs = await SharedPreferences.getInstance(); String? authToken = prefs.getString('auth_token'); - final uri = Uri.parse('https://eldsoft.com:8097/user/update/profile/img'); + final uri = Uri.parse(Config.uploadImageUrl); final headers = { // 헤더 설정 'auth-token': authToken ?? '', }; @@ -81,8 +81,6 @@ class Api { final responseData = await response.stream.toBytes(); final responseString = utf8.decode(responseData); // UTF-8로 디코딩 final jsonResponse = json.decode(responseString); - print('응답: $jsonResponse'); - print('응답[result]: ${jsonResponse['result']}'); await prefs.setString('auth_token', jsonResponse['auth']['token']); res = { @@ -96,7 +94,6 @@ class Api { }; // 요청 실패 시 응답 반환 } } catch (e) { - print('업로드 중 오류 발생: $e'); res = { 'result': "FAIL", 'response': '', diff --git a/lib/survey/survey_page.dart b/lib/survey/survey_page.dart index ae7d0bb..74d28f7 100644 --- a/lib/survey/survey_page.dart +++ b/lib/survey/survey_page.dart @@ -132,7 +132,6 @@ class _SurveyPageState extends State { final requestBody = { "QNA": qnaList.toString(), }; - print('requestBody: $requestBody'); try { final response = await Api.serverRequest(uri: '/survey/collect', body: requestBody); diff --git a/lib/views/inquiry/inquiry_to_manager_page.dart b/lib/views/inquiry/inquiry_to_manager_page.dart new file mode 100644 index 0000000..e5a82c9 --- /dev/null +++ b/lib/views/inquiry/inquiry_to_manager_page.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import '../../plugins/api.dart'; +import '../../dialogs/response_dialog.dart'; +import '../room/main_page.dart'; + +class InquiryToManagerPage extends StatefulWidget { + const InquiryToManagerPage({Key? key}) : super(key: key); + + @override + _InquiryToManagerPageState createState() => _InquiryToManagerPageState(); +} + +class _InquiryToManagerPageState extends State { + final TextEditingController _titleController = TextEditingController(); + final TextEditingController _contentsController = TextEditingController(); + + @override + void dispose() { + _titleController.dispose(); + _contentsController.dispose(); + super.dispose(); + } + + void _handleSubmit() async { + final title = _titleController.text.trim(); + final contents = _contentsController.text.trim(); + + // 예시: 제목이나 내용이 비어있으면 막기 + if (title.isEmpty || contents.isEmpty) { + showResponseDialog(context, '안내', '제목과 내용을 입력해주세요.'); + return; + } + + // 서버에 제출 + try { + final requestBody = { + 'title': title, + 'contents': contents, + }; + final serverResponse = + await Api.serverRequest(uri: '/inquiry/request', body: requestBody); + + if (serverResponse == null) { + showResponseDialog(context, '문의 전송 실패', '서버 응답이 없습니다.'); + } + if (serverResponse['result'] == 'OK') { + final serverResponse1 = serverResponse['response']; + if (serverResponse1['result'] == 'OK') { + await showResponseDialog(context, '문의 전송 완료', '문의가 전송되었습니다.'); + Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute(builder: (context) => const MainPage()), + (route) => false, + ); + } else { + showResponseDialog(context, '문의 전송 실패', '문의 전송에 실패했습니다.'); + } + } else { + showResponseDialog(context, '문의 전송 실패', '문의 전송에 실패했습니다.'); + } + } catch (e) { + showResponseDialog(context, '문의 전송 실패', '문의 전송에 실패했습니다.'); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.black, + title: const Text('문의하기', style: TextStyle(color: Colors.white)), + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios, color: Colors.white), + onPressed: () => Navigator.pop(context), + ), + ), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // 문의 제목 입력 + TextField( + controller: _titleController, + maxLength: 100, + decoration: const InputDecoration( + labelText: '문의 제목', + border: OutlineInputBorder(), + ), + ), + const SizedBox(height: 16), + // 문의 내용 입력(여러 줄 입력 가능) + TextField( + controller: _contentsController, + maxLength: 1000, + maxLines: 10, // 원하는 높이에 맞게 조절 + decoration: const InputDecoration( + labelText: '문의 내용', + border: OutlineInputBorder(), + ), + ), + const SizedBox(height: 16), + // 제출하기 버튼 + SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: Colors.black), + onPressed: _handleSubmit, + child: const Text( + '제출하기', + style: TextStyle(color: Colors.white), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/views/login/id_finding_page.dart b/lib/views/login/id_finding_page.dart index 92d861c..6e68b8e 100644 --- a/lib/views/login/id_finding_page.dart +++ b/lib/views/login/id_finding_page.dart @@ -30,7 +30,7 @@ class _IdFindingPageState extends State { /// (1) 광고 배너 관련 변수 BannerAd? _bannerAd; bool _isBannerReady = false; // 광고 로드 완료 여부 - String adUnitId = Config.testAdUnitId; + String adUnitId = Config.adUnitId; Future _findId(String nickname, String email) async { @@ -62,7 +62,6 @@ class _IdFindingPageState extends State { if (response.statusCode == 200) { final Map jsonResponse = jsonDecode(responseBody); - print('ID 찾기 성공: $jsonResponse'); // 초기화 setState(() { @@ -130,7 +129,6 @@ class _IdFindingPageState extends State { Future _findAllId() async { // ID 전체 찾기 요청 처리 - print('ID 전체 찾기 요청 $authId'); // 요청 시 출력 // 로딩 인디케이터 표시 showDialog( @@ -158,7 +156,6 @@ class _IdFindingPageState extends State { if (response.statusCode == 200) { final Map jsonResponse = jsonDecode(responseBody); - print('ID 전체 찾기 성공: $jsonResponse'); if (jsonResponse['result'] == 'OK') { // 성공 시 모달 창 띄우기 diff --git a/lib/views/login/login_page.dart b/lib/views/login/login_page.dart index cb02c51..2950894 100644 --- a/lib/views/login/login_page.dart +++ b/lib/views/login/login_page.dart @@ -59,7 +59,7 @@ class _LoginPageState extends State { // ───────────────────────────────────────── BannerAd? _bannerAd; bool _isBannerReady = false; - String adUnitId = Config.testAdUnitId; + String adUnitId = Config.adUnitId; // 뒤로가기 처리 DateTime? _lastPressedTime; @@ -146,7 +146,6 @@ class _LoginPageState extends State { final resp = response['response'] ?? {}; if (resp['result'] == 'OK') { // 로그인 성공 - print('ID/PW 로그인 성공: $resp'); // (a) google_user_yn = N final prefs = await SharedPreferences.getInstance(); @@ -203,8 +202,7 @@ class _LoginPageState extends State { final User? user = userCredential.user; if (user == null) { - print('구글 로그인 실패: Firebase User가 null'); - _showAlert('로그인 오류', 'Firebase User가 null입니다.'); + showResponseDialog(context, '오류', '구글 로그인 오류. 관리자에게 문의해주세요.'); return; } @@ -662,17 +660,6 @@ Scaffold( alignment: Alignment.center, child: AdWidget(ad: _bannerAd!), ) - else - Container( - width: 300, - height: 50, - color: Colors.grey.shade400, - alignment: Alignment.center, - child: const Text( - '광고 로딩중', - style: TextStyle(color: Colors.black), - ), - ), ], ), ), diff --git a/lib/views/login/pw_finding_page.dart b/lib/views/login/pw_finding_page.dart index efdd017..fc15b93 100644 --- a/lib/views/login/pw_finding_page.dart +++ b/lib/views/login/pw_finding_page.dart @@ -28,11 +28,10 @@ class _PwFindingPageState extends State { /// (1) 광고 배너 관련 변수 BannerAd? _bannerAd; bool _isBannerReady = false; // 광고 로드 완료 여부 - String adUnitId = Config.testAdUnitId; + String adUnitId = Config.adUnitId; Future _findPassword(String id, String email) async { // PW 찾기 요청 처리 - print('PW 찾기 요청: ID: $id, 이메일: $email'); // 요청 시 출력 // 로딩 인디케이터 표시 showDialog( @@ -61,7 +60,6 @@ class _PwFindingPageState extends State { if (response.statusCode == 200) { final Map jsonResponse = jsonDecode(responseBody); - print('PW 찾기 성공: $jsonResponse'); // 추기화 setState(() { diff --git a/lib/views/login/signup_page.dart b/lib/views/login/signup_page.dart index 913f403..945bbbb 100644 --- a/lib/views/login/signup_page.dart +++ b/lib/views/login/signup_page.dart @@ -74,7 +74,6 @@ class _SignUpPageState extends State { if (response.statusCode == 200) { // result가 OK이어야만 성공여부 판단 가능 - print(resBody); if (resBody['result'] == 'OK') { if (resBody['response_info']['msg_type'] == 'OK') { _showDialog('회원가입 성공', '회원가입이 완료되었습니다.'); diff --git a/lib/views/room/main_page.dart b/lib/views/room/main_page.dart index dc0a5b3..ca657fc 100644 --- a/lib/views/room/main_page.dart +++ b/lib/views/room/main_page.dart @@ -36,7 +36,7 @@ class _MainPageState extends State { /// (1) 광고 배너 관련 변수 BannerAd? _bannerAd; bool _isBannerReady = false; // 광고 로드 완료 여부 - String adUnitId = Config.testAdUnitId; + String adUnitId = Config.adUnitId; // 뒤로가기 처리 DateTime? _lastPressedTime; @@ -75,10 +75,8 @@ class _MainPageState extends State { listener: BannerAdListener( onAdLoaded: (Ad ad) { setState(() => _isBannerReady = true); - debugPrint('배너 광고 로드 완료'); }, onAdFailedToLoad: (Ad ad, LoadAdError err) { - debugPrint('배너 광고 로드 실패: $err'); ad.dispose(); }, ), diff --git a/lib/views/room/playing_private_page.dart b/lib/views/room/playing_private_page.dart index 58b88ab..f1cc4be 100644 --- a/lib/views/room/playing_private_page.dart +++ b/lib/views/room/playing_private_page.dart @@ -64,7 +64,7 @@ class _PlayingPrivatePageState extends State { /// (1) 광고 배너 관련 변수 BannerAd? _bannerAd; bool _isBannerReady = false; // 광고 로드 완료 여부 - String adUnitId = Config.testAdUnitId; + String adUnitId = Config.adUnitId; @override void initState() { @@ -132,7 +132,6 @@ class _PlayingPrivatePageState extends State { } final data = snapshot.value as Map? ?? {}; - print('data111111111 $data'); final roomInfoData = data['roomInfo'] as Map? ?? {}; final userInfoData = data['userInfo'] as Map? ?? {}; final userListData = data['userList'] as Map? ?? {}; diff --git a/lib/views/room/playing_team_page.dart b/lib/views/room/playing_team_page.dart index aaeb567..1d7d66e 100644 --- a/lib/views/room/playing_team_page.dart +++ b/lib/views/room/playing_team_page.dart @@ -66,7 +66,7 @@ class _PlayingTeamPageState extends State { /// (1) 광고 배너 관련 변수 BannerAd? _bannerAd; bool _isBannerReady = false; // 광고 로드 완료 여부 - String adUnitId = Config.testAdUnitId; + String adUnitId = Config.adUnitId; @override void initState() { diff --git a/lib/views/room/room_search_home_page.dart b/lib/views/room/room_search_home_page.dart index 358cdec..38ea858 100644 --- a/lib/views/room/room_search_home_page.dart +++ b/lib/views/room/room_search_home_page.dart @@ -17,7 +17,7 @@ class RoomSearchHomePage extends StatefulWidget { class _RoomSearchHomePageState extends State { BannerAd? _bannerAd; bool _isBannerReady = false; // 광고 로드 완료 여부 - String adUnitId = Config.testAdUnitId; + String adUnitId = Config.adUnitId; @override void initState() { @@ -42,11 +42,9 @@ class _RoomSearchHomePageState extends State { listener: BannerAdListener( onAdLoaded: (Ad ad) { setState(() => _isBannerReady = true); - debugPrint('배너 광고 로드 완료'); }, onAdFailedToLoad: (Ad ad, LoadAdError err) { - debugPrint('배너 광고 로드 실패: $err'); - ad.dispose(); + // 광고 로드 실패 시 처리 }, ), request: const AdRequest(), diff --git a/lib/views/room/room_search_list_page.dart b/lib/views/room/room_search_list_page.dart index c3792c4..c32ec8d 100644 --- a/lib/views/room/room_search_list_page.dart +++ b/lib/views/room/room_search_list_page.dart @@ -40,7 +40,7 @@ class _RoomSearchListPageState extends State { // 배너 광고 관련 변수 BannerAd? _bannerAd; bool _isBannerReady = false; // 광고 로드 완료 여부 - String adUnitId = Config.testAdUnitId; + String adUnitId = Config.adUnitId; @override void initState() { @@ -71,10 +71,8 @@ class _RoomSearchListPageState extends State { listener: BannerAdListener( onAdLoaded: (Ad ad) { setState(() => _isBannerReady = true); - debugPrint('배너 광고 로드 완료'); }, onAdFailedToLoad: (Ad ad, LoadAdError err) { - debugPrint('배너 광고 로드 실패: $err'); ad.dispose(); }, ), diff --git a/lib/views/room/waiting_room_private_page.dart b/lib/views/room/waiting_room_private_page.dart index a7faea4..9072ea4 100644 --- a/lib/views/room/waiting_room_private_page.dart +++ b/lib/views/room/waiting_room_private_page.dart @@ -77,7 +77,7 @@ class _WaitingRoomPrivatePageState extends State { /// (1) 광고 배너 관련 변수 BannerAd? _bannerAd; bool _isBannerReady = false; // 광고 로드 완료 여부 - String adUnitId = Config.testAdUnitId; + String adUnitId = Config.adUnitId; // 방장 SEQ 저장 String _masterSeqString = '0'; @@ -124,14 +124,12 @@ class _WaitingRoomPrivatePageState extends State { Future _initRoomRef() async { final prefs = await SharedPreferences.getInstance(); mySeq = prefs.getInt('my_user_seq')?.toString() ?? '0'; - print('mySeq111111111 $mySeq'); final roomKey = 'korea-${widget.roomSeq}'; _roomRef = FirebaseDatabase.instance.ref('rooms/$roomKey'); // onDisconnect + connect_yn='Y' final myUserRef = _roomRef.child('userInfo').child('_${mySeq}'); - print('myUserRef111111111 $myUserRef'); if (_roomRef.child('userList').child(mySeq) == true) { myUserRef.onDisconnect().update({'connect_yn': 'N'}); } @@ -566,15 +564,18 @@ class _WaitingRoomPrivatePageState extends State { if (response['result'] == 'OK') { final resp = response['response'] ?? {}; if (resp['result'] == 'OK') { - print('게임 시작 요청 성공(개인전)'); + // 진행중 방으로 이동 } else { - // ... + // 오류 처리 + showResponseDialog(context, '오류', '게임 시작 실패했습니다.'); } } else { - // ... + // 오류 처리 + showResponseDialog(context, '오류', '게임 시작 실패했습니다.'); } } catch (e) { - // ... + // 오류 처리 + showResponseDialog(context, '오류', '게임 시작 실패했습니다.'); } } diff --git a/lib/views/room/waiting_room_team_page.dart b/lib/views/room/waiting_room_team_page.dart index 2bbec22..22c933c 100644 --- a/lib/views/room/waiting_room_team_page.dart +++ b/lib/views/room/waiting_room_team_page.dart @@ -79,7 +79,7 @@ class _WaitingRoomTeamPageState extends State { /// (1) 광고 배너 관련 변수 BannerAd? _bannerAd; bool _isBannerReady = false; // 광고 로드 완료 여부 - String adUnitId = Config.testAdUnitId; + String adUnitId = Config.adUnitId; // 방장 SEQ 저장 String _masterSeqString = '0'; @@ -127,10 +127,8 @@ class _WaitingRoomTeamPageState extends State { listener: BannerAdListener( onAdLoaded: (Ad ad) { setState(() => _isBannerReady = true); - debugPrint('배너 광고 로드 완료'); }, onAdFailedToLoad: (Ad ad, LoadAdError err) { - debugPrint('배너 광고 로드 실패: $err'); ad.dispose(); }, ), @@ -583,9 +581,9 @@ class _WaitingRoomTeamPageState extends State { if (response['result'] == 'OK') { final resp = response['response'] ?? {}; if (resp['result'] == 'OK') { - print('게임 시작 요청 성공(팀전)'); + // 진행중 방으로 이동 } else { - // 게임 시작 요청 실패 + // 오류 처리 showResponseDialog(context, response['response_info']['msg_title'], response['response_info']['msg_content']); } } else { diff --git a/lib/views/user/my_page.dart b/lib/views/user/my_page.dart index c72203d..f99aa09 100644 --- a/lib/views/user/my_page.dart +++ b/lib/views/user/my_page.dart @@ -606,7 +606,6 @@ class _MyPageState extends State { if (response['result'] == 'OK') { final jsonResponse = response['response']; - print('응답: $jsonResponse'); if (jsonResponse['result'] == 'OK') { SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setString('auth_token', jsonResponse['auth']['token']); @@ -866,8 +865,6 @@ class _MyPageState extends State { }, ); - print('serverResponse 응답: $serverResponse'); - // 응답이 null인지 확인 if (serverResponse == null) { throw Exception('서버 응답이 null입니다.'); @@ -882,7 +879,6 @@ class _MyPageState extends State { }; } } catch (e) { - print('serverResponse 오류: $e'); return { 'result': 'FAIL', }; @@ -908,7 +904,6 @@ class _MyPageState extends State { if (serverResponse['result'] == 'OK') { final serverResponse1 = serverResponse['response']; - print('응답: $serverResponse1'); if (serverResponse1['result'] == 'OK') { showResponseDialog(context, '업로드 성공', '프로필 이미지가 성공적으로 업로드되었습니다.'); diff --git a/lib/views/user/withdrawal_page.dart b/lib/views/user/withdrawal_page.dart index 270a8dd..77d301f 100644 --- a/lib/views/user/withdrawal_page.dart +++ b/lib/views/user/withdrawal_page.dart @@ -18,8 +18,27 @@ class _WithdrawalPageState extends State { bool _isAgreed = false; // 체크박스 상태를 관리하는 변수 final TextEditingController _passwordController = TextEditingController(); // 비밀번호 입력 컨트롤러 + String _oauthType = 'idpw'; + + @override + void initState() { + super.initState(); + _loadOAuthType(); // SharedPreferences에서 oauth_type 로드 + } + + /// SharedPreferences에서 oauth_type 불러오기 + Future _loadOAuthType() async { + final prefs = await SharedPreferences.getInstance(); + setState(() { + _oauthType = prefs.getString('oauth_type') ?? 'idpw'; + }); + } + @override Widget build(BuildContext context) { + // oauth_type == 'google' 인 경우 => 비밀번호 입력란 스킵 + final isGoogleUser = (_oauthType.toLowerCase() == 'google'); + return Scaffold( backgroundColor: Colors.white, appBar: AppBar( @@ -41,19 +60,22 @@ class _WithdrawalPageState extends State { style: TextStyle(fontSize: 18), ), const SizedBox(height: 20), - TextField( - controller: _passwordController, - obscureText: true, - decoration: InputDecoration( - hintText: '비밀번호 입력', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: const BorderSide(color: Colors.black), + // 구글 로그인 사용자면 비밀번호 입력 생략 + if (!isGoogleUser) ...[ + TextField( + controller: _passwordController, + obscureText: true, + decoration: InputDecoration( + hintText: '비밀번호 입력', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide(color: Colors.black), + ), + contentPadding: const EdgeInsets.all(10), ), - contentPadding: const EdgeInsets.all(10), ), - ), - const SizedBox(height: 20), + const SizedBox(height: 20), + ], Container( decoration: BoxDecoration( border: Border.all(color: Colors.black54, width: 1), // 테두리 설정 @@ -120,16 +142,23 @@ class _WithdrawalPageState extends State { return; } - if (password.isEmpty) { + // 구글 로그인 사용자면 비밀번호 입력 생략 + if (_oauthType != 'google' && password.isEmpty) { // 비밀번호가 입력되지 않은 경우 showResponseDialog(context, '비밀번호 확인', '비밀번호를 입력해야 합니다.'); return; } + // 구글 로그인으로 비밀번호값이 비어있다면 빈값으로 채워주기 + if (password.isEmpty) { + password = ''; + } + final response = await Api.serverRequest( uri: '/user/withdraw/user', body: { 'user_pw': Utils.hashPassword(password), // 입력한 비밀번호 + 'oauth_type': _oauthType, }, ); @@ -140,7 +169,7 @@ class _WithdrawalPageState extends State { SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.remove('auth_token'); // 토큰 초기화 - showResponseDialog(context, '회원탈퇴 완료', '회원탈퇴가 완료되었습니다.'); + await showResponseDialog(context, '회원탈퇴 완료', '회원탈퇴가 완료되었습니다.'); Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => const LoginPage()), // 로그인 페이지로 이동