diff --git a/lib/config/config.dart b/lib/config/config.dart index dfa25e9..e32da6c 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -7,7 +7,7 @@ class Config { static const String adUnitId = 'ca-app-pub-6461991944599918~9492697896'; // static const String adUnitId = 'ca-app-pub-3940256099942544/6300978111'; // 서버 주소 - static const String baseUrl = 'https://eldsoft.com:8097'; + static const String baseUrl = 'https://d2zcnlqji5t7mh.cloudfront.net'; // 이미지 업로드 주소 static const String uploadImageUrl = '$baseUrl/user/update/profile/img'; diff --git a/lib/dialogs/user_info_finish_dialog.dart b/lib/dialogs/user_info_finish_dialog.dart index 7f92265..7417a3c 100644 --- a/lib/dialogs/user_info_finish_dialog.dart +++ b/lib/dialogs/user_info_finish_dialog.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'response_dialog.dart'; // Not used here, just referencing import '../../plugins/api.dart'; // Not used here, just referencing +import '../config/config.dart'; class UserInfoFinishDialog extends StatelessWidget { final Map userData; @@ -18,6 +19,9 @@ class UserInfoFinishDialog extends StatelessWidget { final intro = (userData['introduce_myself'] ?? '').toString().trim(); // 자기소개 + // 서버 주소 + final baseUrl = Config.baseUrl; + return Dialog( backgroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), @@ -52,7 +56,7 @@ class UserInfoFinishDialog extends StatelessWidget { child: ClipOval( child: (profileImg.isNotEmpty) ? Image.network( - 'https://eldsoft.com:8097/images$profileImg', + '$baseUrl/images$profileImg', fit: BoxFit.cover, errorBuilder: (ctx, err, st) => const Center( child: Text( diff --git a/lib/dialogs/user_info_private_dialog.dart b/lib/dialogs/user_info_private_dialog.dart index 0c0389c..f09b6cc 100644 --- a/lib/dialogs/user_info_private_dialog.dart +++ b/lib/dialogs/user_info_private_dialog.dart @@ -3,6 +3,7 @@ import 'response_dialog.dart'; import '../../plugins/api.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:auto_size_text/auto_size_text.dart'; +import '../config/config.dart'; class UserInfoPrivateDialog extends StatefulWidget { final Map userData; @@ -173,6 +174,8 @@ class _UserInfoPrivateDialogState extends State { final department = widget.userData['department'] ?? 'No Department Info' /* '소속정보없음' */; final profileImg = widget.userData['profile_img'] ?? ''; + // 서버 주소 + final baseUrl = Config.baseUrl; return Dialog( backgroundColor: Colors.white, @@ -204,7 +207,7 @@ class _UserInfoPrivateDialogState extends State { borderRadius: BorderRadius.circular(16), child: (profileImg.isNotEmpty) ? Image.network( - 'https://eldsoft.com:8097/images$profileImg', + '$baseUrl/images$profileImg', fit: BoxFit.cover, errorBuilder: (ctx, err, st) => const Center( child: Text( diff --git a/lib/dialogs/user_info_team_dialog.dart b/lib/dialogs/user_info_team_dialog.dart index 7301fe3..13a97e6 100644 --- a/lib/dialogs/user_info_team_dialog.dart +++ b/lib/dialogs/user_info_team_dialog.dart @@ -3,6 +3,7 @@ import 'response_dialog.dart'; import '../../plugins/api.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:auto_size_text/auto_size_text.dart'; +import '../config/config.dart'; class UserInfoTeamDialog extends StatefulWidget { final Map userData; @@ -188,6 +189,9 @@ class _UserInfoTeamDialogState extends State { final department = widget.userData['department'] ?? 'No Department Info' /* '소속정보 없음' */; + // 서버 주소 + final baseUrl = Config.baseUrl; + return Dialog( backgroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), @@ -220,7 +224,7 @@ class _UserInfoTeamDialogState extends State { borderRadius: BorderRadius.circular(16), child: (profileImg.isNotEmpty) ? Image.network( - 'https://eldsoft.com:8097/images$profileImg', + '$baseUrl/images$profileImg', fit: BoxFit.cover, errorBuilder: (ctx, err, st) => const Center( child: Text( diff --git a/lib/survey/survey_page.dart b/lib/survey/survey_page.dart index 4729a56..0cfe1c2 100644 --- a/lib/survey/survey_page.dart +++ b/lib/survey/survey_page.dart @@ -26,15 +26,16 @@ class SurveyPage extends StatefulWidget { class _SurveyPageState extends State { int _currentIndex = 0; - /* 현재 페이지 인덱스 (0~4) */ + /* 현재 페이지 인덱스 (0~5) */ List _questions = []; - /* 전체 질문 목록 (5개 예시) */ + /* 전체 질문 목록 (이제 6개) */ List _questionsOriginal = []; - /* 질문의 한글 원본 목록 */ + /* 질문의 한글 원본 목록 (6개) */ - final List _answers = List.filled(5, null, growable: false); - /* 사용자가 입력한 답변(5개) */ + // 변경 포인트: 5 -> 6개 + final List _answers = List.filled(6, null, growable: false); + /* 사용자가 입력한 답변(6개) */ final Map _selectedRadioValue = {}; /* 각 페이지별 라디오 선택 값 */ @@ -45,26 +46,18 @@ class _SurveyPageState extends State { void initState() { super.initState(); - // Set questions (질문 설정) _questions = [ - "Q1. How old are you, ${widget.nickname}?", - /* "Q1. ${widget.nickname}님의 나이는 어떻게 되나요?" */ - - "Q2. What is your occupation, ${widget.nickname}?", - /* "Q2. ${widget.nickname}님의 직업이 무엇인가요?" */ - - "Q3. How did you hear about ALLSCORE, ${widget.nickname}?", - /* "Q3. ${widget.nickname}님은 올스코어 앱을 어떻게 알게 됐나요?" */ - - "Q4. Where have you experienced ALLSCORE, ${widget.nickname}?", - /* "Q4. ${widget.nickname}님은 올스코어 앱을 어디서 경험하셨나요?" */ - - "Q5. Do you plan to keep using ALLSCORE?", - /* "Q5. 올스코어를 계속 사용할 의사가 있나요?" */ + "Q1. Which country do you live in, ${widget.nickname}?", + "Q2. How old are you, ${widget.nickname}?", + "Q3. What is your occupation, ${widget.nickname}?", + "Q4. How did you hear about ALLSCORE, ${widget.nickname}?", + "Q5. Where have you experienced ALLSCORE, ${widget.nickname}?", + "Q6. Do you plan to keep using ALLSCORE?", ]; - // Original Korean questions (원래 한글 질문 목록) + // 한글 원본 질문도 6개 _questionsOriginal = [ + "당신이 거주하는 국가는 어디인가요?", "나이는 어떻게 되나요?", "직업이 무엇인가요?", "올스코어 앱을 어떻게 알게 됐나요?", @@ -72,8 +65,7 @@ class _SurveyPageState extends State { "올스코어를 계속 사용할 의사가 있나요?", ]; - // Initialize TextEditingController for each page - // (페이지마다 TextEditingController 초기화) + // 페이지마다 TextEditingController 초기화 for (int i = 0; i < _questions.length; i++) { _textControllers[i] = TextEditingController(); } @@ -101,8 +93,7 @@ class _SurveyPageState extends State { void _onNext() { if (!_validateCurrentPage()) { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('Please fill in all required fields.' - /* '값을 모두 입력해 주세요.' */)), + const SnackBar(content: Text('Please fill in all required fields.')), ); return; } @@ -127,8 +118,7 @@ class _SurveyPageState extends State { Future _onSubmit() async { if (!_validateCurrentPage()) { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('Please fill in all required fields.' - /* '값을 모두 입력해 주세요.' */)), + const SnackBar(content: Text('Please fill in all required fields.')), ); return; } @@ -136,10 +126,8 @@ class _SurveyPageState extends State { // body: {"QNA": ["질문1","답변1","질문2","답변2", ... ]} final List qnaList = []; for (int i = 0; i < _questionsOriginal.length; i++) { - qnaList.add(_questionsOriginal[i]); - /* 한글 질문 넣기 */ - qnaList.add(_answers[i] ?? ''); - /* 사용자 답변 */ + qnaList.add(_questionsOriginal[i]); // 한글 질문 + qnaList.add(_answers[i] ?? ''); // 사용자 답변 } final requestBody = { @@ -151,10 +139,9 @@ class _SurveyPageState extends State { if (response['result'] == 'OK') { final resp = response['response'] ?? {}; if (resp['result'] == 'OK') { - // Survey submitted (설문 제출 성공) + // Survey submitted ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('Your survey has been submitted. Thank you!' - /* '설문이 제출되었습니다. 감사합니다!' */)), + const SnackBar(content: Text('Your survey has been submitted. Thank you!')), ); Navigator.pushAndRemoveUntil( context, @@ -162,16 +149,13 @@ class _SurveyPageState extends State { (route) => false, ); } else { - showResponseDialog(context, 'Error' /* 오류 */, 'Failed to submit the survey.' - /* '설문 제출 실패' */); + showResponseDialog(context, 'Error', 'Failed to submit the survey.'); } } else { - showResponseDialog(context, 'Error' /* 오류 */, 'Failed to submit the survey.' - /* '설문 제출 실패' */); + showResponseDialog(context, 'Error', 'Failed to submit the survey.'); } } catch (e) { - showResponseDialog(context, 'Error' /* 오류 */, 'Failed to submit the survey.' - /* '설문 제출 실패' */); + showResponseDialog(context, 'Error', 'Failed to submit the survey.'); } } @@ -182,16 +166,24 @@ class _SurveyPageState extends State { switch (index) { case 0: - // Age (나이) - final txt = _textControllers[index]?.text.trim() ?? ''; - if (txt.isEmpty) { + // [새 질문] 거주 국가 + final txtCountry = _textControllers[index]?.text.trim() ?? ''; + if (txtCountry.isEmpty) { return false; } - answer = '$txt yrs old' - /* '$txt 세' */; + answer = txtCountry; break; case 1: + // Age (나이) + final txtAge = _textControllers[index]?.text.trim() ?? ''; + if (txtAge.isEmpty) { + return false; + } + answer = '$txtAge yrs old'; + break; + + case 2: // Occupation (직업) final selected = _selectedRadioValue[index]; if (selected == null || selected.isEmpty) { @@ -200,26 +192,25 @@ class _SurveyPageState extends State { answer = selected; break; - case 2: + case 3: // How did you hear about ALLSCORE? (앱 알게된 경로) final selected2 = _selectedRadioValue[index]; if (selected2 == null || selected2.isEmpty) { return false; } - if (selected2 == 'Others' /* '기타' */) { + if (selected2 == 'Others') { final etc = _textControllers[index]?.text.trim() ?? ''; if (etc.isEmpty) { return false; } - answer = "Others($etc)" - /* "기타($etc)" */; + answer = "Others($etc)"; } else { answer = selected2; } break; - case 3: - // Where have you experienced? (어디서 경험?) + case 4: + // Where have you experienced ALLSCORE? (어디서 경험?) final sel3 = _selectedRadioValue[index]; if (sel3 == null || sel3.isEmpty) { return false; @@ -227,15 +218,14 @@ class _SurveyPageState extends State { answer = sel3; break; - case 4: + case 5: // Will you continue using ALLSCORE? (계속 사용할 의사?) final sel4 = _selectedRadioValue[index]; if (sel4 == null || sel4.isEmpty) { return false; } final comment = _textControllers[index]?.text.trim() ?? ''; - answer = sel4 + (comment.isNotEmpty ? " / comment: $comment" - /* "/ 의견: $comment" */ : ""); + answer = sel4 + (comment.isNotEmpty ? " / comment: $comment" : ""); break; default: @@ -249,7 +239,6 @@ class _SurveyPageState extends State { @override Widget build(BuildContext context) { final questionText = _questions[_currentIndex]; - /* 현재 페이지 질문 */ final pageNumber = _currentIndex + 1; final totalPage = _questions.length; @@ -264,13 +253,11 @@ class _SurveyPageState extends State { leading: TextButton( onPressed: _onExitSurvey, child: const Text( - 'Stop Survey' - /* '설문 그만하기' */, + 'Stop Survey', style: TextStyle(color: Colors.white), ), ), - title: Text('Survey ($pageNumber/$totalPage)' - /* '설문조사 ($pageNumber/$totalPage)' */), + title: Text('Survey ($pageNumber/$totalPage)'), backgroundColor: Colors.black, ), body: SingleChildScrollView( @@ -278,17 +265,15 @@ class _SurveyPageState extends State { alignment: Alignment.center, padding: const EdgeInsets.all(16), child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, children: [ - // Question text (질문) + // 현재 페이지의 질문 Text( questionText, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), textAlign: TextAlign.center, ), const SizedBox(height: 24), - // Page-specific UI (페이지별 UI) + // 페이지별 UI _buildSurveyPage(_currentIndex), ], ), @@ -304,8 +289,7 @@ class _SurveyPageState extends State { child: ElevatedButton( style: ElevatedButton.styleFrom(backgroundColor: Colors.grey), onPressed: _onPrev, - child: const Text('Previous' - /* '이전' */), + child: const Text('Previous'), ), ), if (_currentIndex > 0) const SizedBox(width: 8), @@ -314,7 +298,7 @@ class _SurveyPageState extends State { style: ElevatedButton.styleFrom(backgroundColor: Colors.black), onPressed: (_currentIndex < totalPage - 1) ? _onNext : _onSubmit, child: Text( - (_currentIndex < totalPage - 1) ? 'Next' /* 다음 */ : 'Submit' /* 제출하기 */, + (_currentIndex < totalPage - 1) ? 'Next' : 'Submit', style: const TextStyle(color: Colors.white), ), ), @@ -330,23 +314,19 @@ class _SurveyPageState extends State { Widget _buildSurveyPage(int index) { switch (index) { case 0: - // Age input (나이 입력) + // [새 질문] 거주 국가 return Column( children: [ const Text( - '(e.g. Please enter your age in digits.)' - /* '(예: 나이를 숫자로 입력해 주세요.)' */, + '(Please enter the country you live in.)', textAlign: TextAlign.center, ), const SizedBox(height: 16), TextField( controller: _textControllers[index], - keyboardType: TextInputType.number, - inputFormatters: [FilteringTextInputFormatter.digitsOnly], textAlign: TextAlign.center, decoration: const InputDecoration( - labelText: 'Age' - /* '나이' */, + labelText: 'Your country', border: OutlineInputBorder(), ), ), @@ -354,16 +334,38 @@ class _SurveyPageState extends State { ); case 1: - // Occupation (직업) + // [기존] 나이 입력 + return Column( + children: [ + const Text( + '(e.g. Please enter your age in digits.)', + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), + TextField( + controller: _textControllers[index], + keyboardType: TextInputType.number, + inputFormatters: [FilteringTextInputFormatter.digitsOnly], + textAlign: TextAlign.center, + decoration: const InputDecoration( + labelText: 'Age', + border: OutlineInputBorder(), + ), + ), + ], + ); + + case 2: + // [기존] 직업 final jobs = [ - 'Student' /* '학생' */, - 'Office Worker' /* '회사원' */, - 'Professional' /* '전문직' */, - 'Professor/Teacher' /* '교수/교사' */, - 'Technical' /* '기술직' */, - 'Government Official' /* '공무원' */, - 'Art/Sports' /* '예술/스포츠' */, - 'Others' /* '기타' */, + 'Student', + 'Office Worker', + 'Professional', + 'Professor/Teacher', + 'Technical', + 'Government Official', + 'Art/Sports', + 'Others', ]; return Column( mainAxisSize: MainAxisSize.min, @@ -381,14 +383,14 @@ class _SurveyPageState extends State { }).toList(), ); - case 2: - // How did you hear about ALLSCORE? (앱 알게된 경로) + case 3: + // [기존] 앱 알게된 경로 final paths = [ - 'Friend/Acquaintance' /* '친구/지인 추천' */, - 'Social Media' /* '소셜 미디어' */, - 'Blog/Online Review' /* '블로그/온라인 리뷰' */, - 'School/Workplace' /* '학교나 직장' */, - 'Others' /* '기타' */, + 'Friend/Acquaintance', + 'Social Media', + 'Blog/Online Review', + 'School/Workplace', + 'Others', ]; return Column( mainAxisSize: MainAxisSize.min, @@ -405,16 +407,14 @@ class _SurveyPageState extends State { }, ); }).toList(), - if (_selectedRadioValue[index] == 'Others' - /* '기타' */) + if (_selectedRadioValue[index] == 'Others') Padding( padding: const EdgeInsets.only(top: 8.0), child: TextField( controller: _textControllers[index], textAlign: TextAlign.center, decoration: const InputDecoration( - labelText: 'Please specify.' - /* '기타 내용을 입력해 주세요.' */, + labelText: 'Please specify.', border: OutlineInputBorder(), ), ), @@ -422,16 +422,16 @@ class _SurveyPageState extends State { ], ); - case 3: - // Where have you experienced ALLSCORE? (어디서 경험?) + case 4: + // [기존] 어디서 경험? final places = [ - 'With Family' /* '가족과 함께' */, - 'With Friends' /* '친구들과 모임' */, - 'School (for education)' /* '학교 교육 목적' */, - 'Work Club' /* '직장 동호회' */, - 'Cafe or Public Space' /* '카페나 공공장소' */, - 'Travel' /* '여행 중' */, - 'Others' /* '기타' */, + 'With Family', + 'With Friends', + 'School (for education)', + 'Work Club', + 'Cafe or Public Space', + 'Travel', + 'Others', ]; return Column( mainAxisSize: MainAxisSize.min, @@ -449,14 +449,14 @@ class _SurveyPageState extends State { }).toList(), ); - case 4: - // Will you continue using ALLSCORE? (계속 사용할 의사?) + case 5: + // [기존] 계속 사용할 의사? return Column( mainAxisSize: MainAxisSize.min, children: [ RadioListTile( - title: const Text('Yes' /* '네' */, textAlign: TextAlign.center), - value: 'Yes' /* '네' */, + title: const Text('Yes', textAlign: TextAlign.center), + value: 'Yes', groupValue: _selectedRadioValue[index], onChanged: (val) { setState(() { @@ -465,8 +465,8 @@ class _SurveyPageState extends State { }, ), RadioListTile( - title: const Text('No' /* '아니오' */, textAlign: TextAlign.center), - value: 'No' /* '아니오' */, + title: const Text('No', textAlign: TextAlign.center), + value: 'No', groupValue: _selectedRadioValue[index], onChanged: (val) { setState(() { @@ -476,8 +476,7 @@ class _SurveyPageState extends State { ), const SizedBox(height: 16), const Text( - 'If you have any additional comments, feel free to write them here.' - /* '추가 의견이 있다면 자유롭게 작성해 주세요.' */, + 'If you have any additional comments, feel free to write them here.', textAlign: TextAlign.center, ), const SizedBox(height: 8), @@ -486,8 +485,7 @@ class _SurveyPageState extends State { maxLines: 3, textAlign: TextAlign.center, decoration: const InputDecoration( - hintText: 'e.g. inconveniences, improvement ideas, etc.' - /* 'ex) 불편사항, 개선 아이디어 등' */, + hintText: 'e.g. inconveniences, improvement ideas, etc.', border: OutlineInputBorder(), ), ), @@ -495,11 +493,7 @@ class _SurveyPageState extends State { ); default: - return const Text( - 'Survey question error' - /* '설문 문항 오류' */, - textAlign: TextAlign.center - ); + return const Text('Survey question error', textAlign: TextAlign.center); } } } diff --git a/lib/views/login/id_finding_page.dart b/lib/views/login/id_finding_page.dart index 9b25126..b89408c 100644 --- a/lib/views/login/id_finding_page.dart +++ b/lib/views/login/id_finding_page.dart @@ -5,6 +5,8 @@ import 'dart:convert' show utf8; import 'login_page.dart'; import 'pw_finding_page.dart'; import 'signup_page.dart'; +import '../../dialogs/response_dialog.dart'; +import '../../plugins/api.dart'; /* 모바일 광고 */ import '../../plugins/admob.dart'; @@ -44,26 +46,21 @@ class _IdFindingPageState extends State { ); try { - final response = await http - .post( - Uri.parse('https://eldsoft.com:8097/user/find/id'), - headers: { - 'Content-Type': 'application/json', - }, - body: jsonEncode({ + final serverResponse = await Api.serverRequest(uri: '/user/find/id', body: { 'nickname': nickname, 'user_email': email, - }), - ) - .timeout(const Duration(seconds: 10)); // 10초 타임아웃 설정 - - String responseBody = utf8.decode(response.bodyBytes); - - Navigator.of(context).pop(); // Close loading indicator (로딩 인디케이터 닫기) - - if (response.statusCode == 200) { - final Map jsonResponse = jsonDecode(responseBody); + }); + Navigator.of(context).pop(); + if (serverResponse == null) { + showResponseDialog( + context, + 'Find ID Failed' /* ID 찾기 실패 */, + 'No response from server.' /* 서버 응답이 없습니다. */ + ); + } + + if (serverResponse['result'] == 'OK') { // Reset messages (오류 메시지, ID 메시지 등) setState(() { nicknameErrorMessage = ''; @@ -71,48 +68,54 @@ class _IdFindingPageState extends State { foundIdMessage = ''; }); - if (jsonResponse['response_info']['msg_title'] == '닉네임 확인') /* "닉네임 확인" */ { - setState(() { - nicknameErrorMessage = 'Please check your nickname again.' - /* 닉네임을 다시 확인해주세요 */; - }); - } else if (jsonResponse['response_info']['msg_title'] == '이메일 확인') /* "이메일 확인" */ { - setState(() { - emailErrorMessage = 'Please check your email again.' - /* 이메일을 다시 확인해주세요 */; - }); - } else if (jsonResponse['result'] == 'OK') { + final serverResponse1 = serverResponse['response']; + + if (serverResponse1['result'] == 'OK') { + await showResponseDialog( + context, + 'Find ID Success' /* ID 찾기 성공 */, + 'Your ID has been successfully found.' + /* ID가 찾아졌습니다. */ + ); /* ID 찾기 성공 시 */ setState(() { - foundIdMessage = 'Your ID is ${jsonResponse['data']['user_id']}.' - /* 당신의 ID는 ${jsonResponse['data']['user_id']} 입니다 */; - authId = jsonResponse['data']['auth']; + foundIdMessage = 'Your ID is ${serverResponse1['data']['user_id']}.' + /* 당신의 ID는 ${serverResponse1['data']['user_id']} 입니다 */; + authId = serverResponse1['data']['auth']; }); } else { - _showErrorDialog( - jsonResponse['response_info']['msg_title'], - jsonResponse['response_info']['msg_content'], - 'STAY', - ); + if (serverResponse1['response_info']['msg_title'] == 'Nickname Check') /* "닉네임 확인" */ { + setState(() { + nicknameErrorMessage = 'Please check your nickname again.' + /* 닉네임을 다시 확인해주세요 */; + }); + } else if (serverResponse1['response_info']['msg_title'] == 'Email Check') /* "이메일 확인" */ { + setState(() { + emailErrorMessage = 'Please check your email again.' + /* 이메일을 다시 확인해주세요 */; + }); + } else { + showResponseDialog( + context, + 'Find ID Failed' /* ID 찾기 실패 */, + 'Failed to find ID.' /* ID를 찾을 수 없습니다. */ + ); + } } } else { - // 요청 실패 - _showErrorDialog( - 'Error' - /* 오류 */, - 'Request failed. Please contact the administrator.' - /* 요청이 실패했습니다. 관리자에게 문의해주세요. */, - 'STAY', + showResponseDialog( + context, + 'Find ID Failed' /* ID 찾기 실패 */, + 'Failed to find ID.' /* ID를 찾을 수 없습니다. */ ); } } catch (e) { Navigator.of(context).pop(); - _showErrorDialog( - 'Error' - /* 오류 */, + showResponseDialog( + context, + 'Error' /* 오류 */, 'Request failed. Please contact the administrator.' - /* 요청이 실패했습니다. 관리자에게 문의해주세요. */, - 'STAY', + /* 요청이 실패했습니다. 관리자에게 문의해주세요. */ ); } } @@ -140,114 +143,52 @@ class _IdFindingPageState extends State { ); try { - final response = await http - .post( - Uri.parse('https://eldsoft.com:8097/user/find/id/full'), - headers: { - 'Content-Type': 'application/json', - }, - body: jsonEncode({'auth': authId}), - ) - .timeout(const Duration(seconds: 10)); // 10초 타임아웃 + final serverResponse = await Api.serverRequest(uri: '/user/find/id/full', body: {'auth': authId}); + Navigator.of(context).pop(); - String responseBody = utf8.decode(response.bodyBytes); - - Navigator.of(context).pop(); // Close loading indicator (로딩 인디케이터 닫기) - - if (response.statusCode == 200) { - final Map jsonResponse = jsonDecode(responseBody); - - if (jsonResponse['result'] == 'OK') { + if (serverResponse == null) { + showResponseDialog( + context, + 'Find All IDs Failed' /* ID 전체 찾기 실패 */, + 'No response from server.' /* 서버 응답이 없습니다. */ + ); + } + + if (serverResponse['result'] == 'OK') { + final serverResponse1 = serverResponse['response']; + if (serverResponse1['result'] == 'OK') { // 성공 - _showSuccessDialog( + showResponseDialog( + context, + 'Find All IDs Success' /* ID 전체 찾기 성공 */, 'We have sent all IDs to your email.' - /* 이메일로 전체 ID를 발송했습니다. */, + /* 이메일로 전체 ID를 발송했습니다. */ ); } else { - _showErrorDialog( - jsonResponse['response_info']['msg_title'], - jsonResponse['response_info']['msg_content'], - 'STAY', + showResponseDialog( + context, + serverResponse1['response_info']['msg_title'] /* ID 전체 찾기 실패 */, + serverResponse1['response_info']['msg_content'] /* 전체 ID를 찾을 수 없습니다. */ ); } } else { - // 요청 실패 - _showErrorDialog( - 'Error' - /* 오류 */, - 'Request failed. Please contact the administrator.' - /* 요청이 실패했습니다. 관리자에게 문의해주세요. */, - 'STAY', + showResponseDialog( + context, + 'Find All IDs Failed' /* ID 전체 찾기 실패 */, + 'Failed to find all IDs.' /* 전체 ID를 찾을 수 없습니다. */ ); } } catch (e) { Navigator.of(context).pop(); - _showErrorDialog( - 'Error' - /* 오류 */, + showResponseDialog( + context, + 'Error' /* 오류 */, 'Request failed. Please contact the administrator.' - /* 요청이 실패했습니다. 관리자에게 문의해주세요. */, - 'STAY', + /* 요청이 실패했습니다. 관리자에게 문의해주세요. */ ); } } - void _showErrorDialog(String title, String content, String action) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - backgroundColor: Colors.white, - title: Text(title, style: const TextStyle(color: Colors.black)), - content: Text(content, style: const TextStyle(color: Colors.black)), - actions: [ - Center( - child: TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.black, - foregroundColor: Colors.white, - ), - child: const Text('OK' - /* 확인 */), - onPressed: () { - Navigator.of(context).pop(); - if (action == 'LOGIN') { - Navigator.of(context).pop(); - /* 로그인 페이지로 이동 */ - } - }, - ), - ), - ], - ); - }, - ); - } - - void _showSuccessDialog(String message) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('Success' - /* 성공 */), - content: Text(message), - actions: [ - TextButton( - child: const Text('OK' - /* 확인 */), - onPressed: () { - Navigator.of(context).pop(); - Navigator.of(context).pop(); - /* 로그인 페이지로 이동 */ - }, - ), - ], - ); - }, - ); - } - @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/views/login/pw_finding_page.dart b/lib/views/login/pw_finding_page.dart index 67deaea..c1317ea 100644 --- a/lib/views/login/pw_finding_page.dart +++ b/lib/views/login/pw_finding_page.dart @@ -5,6 +5,8 @@ import 'dart:convert' show utf8; import 'login_page.dart'; // 로그인 페이지 임포트 import 'signup_page.dart'; // 회원가입 페이지 임포트 import 'id_finding_page.dart'; // ID 찾기 페이지 임포트 +import '../../dialogs/response_dialog.dart'; +import '../../plugins/api.dart'; // Mobile ads (모바일 광고) import '../../plugins/admob.dart'; @@ -38,25 +40,19 @@ class _PwFindingPageState extends State { ); try { - final response = await http - .post( - Uri.parse('https://eldsoft.com:8097/user/find/password'), - headers: { - 'Content-Type': 'application/json', - }, - body: jsonEncode({ - 'user_id': id, - 'user_email': email, - }), - ) - .timeout(const Duration(seconds: 10)); // 10초 타임아웃 + final serverResponse = await Api.serverRequest(uri: '/user/find/password', body: {'user_id': id, 'user_email': email}); + Navigator.of(context).pop(); - String responseBody = utf8.decode(response.bodyBytes); + if (serverResponse == null) { + showResponseDialog( + context, + 'Find Password Failed' /* PW 찾기 실패 */, + 'No response from server.' /* 서버 응답이 없습니다. */ + ); + } - Navigator.of(context).pop(); // Close loading indicator (로딩 인디케이터 닫기) - - if (response.statusCode == 200) { - final Map jsonResponse = jsonDecode(responseBody); + if (serverResponse['result'] == 'OK') { + final serverResponse1 = serverResponse['response']; // Reset error messages (오류 메시지 초기화) setState(() { @@ -64,86 +60,50 @@ class _PwFindingPageState extends State { idErrorMessage = ''; }); - if (jsonResponse['response_info']['msg_title'] == '아이디 확인') { - /* 아이디 확인 */ - setState(() { - idErrorMessage = 'Please check your ID again.' - /* 아이디를 다시 확인해주세요 */; - }); - } else if (jsonResponse['response_info']['msg_title'] == '이메일 확인') { - /* 이메일 확인 */ - setState(() { - emailErrorMessage = 'Please check your email again.' - /* 이메일을 다시 확인해주세요 */; - }); - } else if (jsonResponse['result'] == 'OK') { - /* 성공 시 */ - _showDialog( - 'Password Recovery Notice' - /* 비밀번호 찾기 안내 */, - 'An interim password has been sent to your email.' - /* 임시 비밀번호가 입력하신 이메일로 발송되었습니다. */, - 'LOGIN', + if (serverResponse1['result'] == 'OK') { + // 성공 + showResponseDialog( + context, + 'Find Password Success' /* PW 찾기 성공 */, + 'An interim password has been sent to your email.' /* 임시 비밀번호가 입력하신 이메일로 발송되었습니다. */ ); } else { - // 실패 시 - _showDialog( - jsonResponse['response_info']['msg_title'], - jsonResponse['response_info']['msg_content'], - 'STAY', - ); + if (serverResponse1['response_info']['msg_title'] == 'ID Check') { + setState(() { + idErrorMessage = 'Please check your ID again.' + /* 아이디를 다시 확인해주세요 */; + }); + } else if (serverResponse1['response_info']['msg_title'] == 'Email Check') { + setState(() { + emailErrorMessage = 'Please check your email again.' + /* 이메일을 다시 확인해주세요 */; + }); + } else { + showResponseDialog( + context, + serverResponse1['response_info']['msg_title'] /* PW 찾기 실패 */, + serverResponse1['response_info']['msg_content'] /* 비밀번호를 찾을 수 없습니다. */ + ); + } } } else { - // 요청 실패 - _showDialog( - 'Error' /* 오류 */, - 'Request failed. Please contact the administrator.' - /* 요청이 실패했습니다. 관리자에게 문의해주세요. */, - 'STAY', + showResponseDialog( + context, + 'Find Password Failed' /* PW 찾기 실패 */, + 'Failed to find password.' /* 비밀번호를 찾을 수 없습니다. */ ); } } catch (e) { - Navigator.of(context).pop(); - _showDialog( - 'Error' /* 오류 */, - 'Request failed. Please contact the administrator.' - /* 요청이 실패했습니다. 관리자에게 문의해주세요. */, - 'STAY', + Navigator.of(context).pop(); + showResponseDialog( + context, + 'Error' /* 오류 */, + 'Request failed. Please contact the administrator.' + /* 요청이 실패했습니다. 관리자에게 문의해주세요. */ ); } } - void _showDialog(String title, String content, String action) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - backgroundColor: Colors.white, - title: Text(title, style: const TextStyle(color: Colors.black)), - content: Text(content, style: const TextStyle(color: Colors.black)), - actions: [ - Center( - child: TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.black, - foregroundColor: Colors.white, - ), - child: const Text('OK' /* 확인 */), - onPressed: () { - Navigator.of(context).pop(); - if (action == 'LOGIN') { - Navigator.of(context).pop(); - /* 로그인 페이지로 이동 */ - } - }, - ), - ), - ], - ); - }, - ); - } - @override void initState() { super.initState(); diff --git a/lib/views/login/signup_page.dart b/lib/views/login/signup_page.dart index defa73d..892548f 100644 --- a/lib/views/login/signup_page.dart +++ b/lib/views/login/signup_page.dart @@ -5,6 +5,9 @@ import 'login_page.dart'; // 로그인 페이지 임포트 추가 import 'dart:convert' show utf8; // UTF-8 디코딩을 위해 임포트 import 'package:crypto/crypto.dart'; // crypto 패키지 임포트 import '../../config/config.dart'; // config 패키지 임포트 +import '../../dialogs/response_dialog.dart'; +import '../../plugins/api.dart'; + class SignUpPage extends StatefulWidget { const SignUpPage({Key? key}) : super(key: key); @@ -61,8 +64,6 @@ class _SignUpPageState extends State { // 회원가입 요청 (Sign-up request) Future _signUp() async { - final url = 'https://eldsoft.com:8097/user/signup'; - // 체크박스 상태에 따라 mandatory_terms_yn 값 설정 final mandatoryTermsYn = _isAgreed ? 'Y' : 'N'; // 비밀번호 해싱 (SHA-256) @@ -79,31 +80,49 @@ class _SignUpPageState extends State { }; try { - final response = await http.post( - Uri.parse(url), - headers: {'Content-Type': 'application/json'}, - body: json.encode(body), - ); + final serverResponse = await Api.serverRequest(uri: '/user/signup', body: body); + Navigator.of(context).pop(); - // 응답을 UTF-8로 디코딩 - final resBody = json.decode(utf8.decode(response.bodyBytes)); + if (serverResponse == null) { + showResponseDialog( + context, + 'Sign-up Failed' /* 회원가입 실패 */, + 'No response from server.' /* 서버 응답이 없습니다. */ + ); + } - if (response.statusCode == 200) { - if (resBody['result'] == 'OK') { - if (resBody['response_info']['msg_type'] == 'OK') { - _showDialog('Sign-up Success', 'Your account has been created successfully.'); - } else { - _showDialog('Sign-up Failed', '${resBody['response_info']['msg_content']}'); - } + if (serverResponse['result'] == 'OK') { + final serverResponse1 = serverResponse['response']; + if (serverResponse1['result'] == 'OK') { + // 성공 + showResponseDialog( + context, + 'Sign-up Success' /* 회원가입 성공 */, + 'Your account has been created successfully.' + /* 계정이 성공적으로 생성되었습니다. */ + ); } else { - _showDialog('Sign-up Failed', '${resBody['response_info']['msg_content']}'); + showResponseDialog( + context, + serverResponse1['response_info']['msg_title'] /* 회원가입 실패 */, + serverResponse1['response_info']['msg_content'] /* 계정 생성 실패 */ + ); } } else { - final errorData = json.decode(response.body); - _showDialog('Sign-up Failed', errorData['message'] ?? 'Sign-up failed.'); + showResponseDialog( + context, + 'Sign-up Failed' /* 회원가입 실패 */, + 'Failed to create an account.' /* 계정 생성 실패 */ + ); } - } catch (error) { - _showDialog('Network Error', 'Network error: $error'); + } catch (e) { + Navigator.of(context).pop(); + showResponseDialog( + context, + 'Error' /* 오류 */, + 'Request failed. Please contact the administrator.' + /* 요청이 실패했습니다. 관리자에게 문의해주세요. */ + ); } } @@ -114,51 +133,6 @@ class _SignUpPageState extends State { return digest.toString(); } - // 모달 다이얼로그 - void _showDialog(String title, String message) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - backgroundColor: Colors.white, - title: Text( - title, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Colors.black, - ), - ), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - message, - style: const TextStyle(fontSize: 16, color: Colors.black), - ), - const SizedBox(height: 20), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - if (title == 'Sign-up Success') { - // 회원가입 성공이면 로그인 페이지로 - Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const LoginPage())); - } - }, - style: TextButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: Colors.black, - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), - ), - child: const Text('OK'), - ), - ], - ), - ); - }, - ); - } - // 입력필드 공용 위젯 (label에 따라 유효성 검사) Widget _buildTextField(String label, Function(String) onChanged, { bool obscureText = false, diff --git a/lib/views/room/finish_private_page.dart b/lib/views/room/finish_private_page.dart index c4cec0f..36b0d17 100644 --- a/lib/views/room/finish_private_page.dart +++ b/lib/views/room/finish_private_page.dart @@ -6,6 +6,8 @@ import '../../dialogs/response_dialog.dart'; import '../../dialogs/room_setting_finish_dialog.dart'; import '../../dialogs/user_info_finish_dialog.dart'; +import '../../config/config.dart'; + import 'main_page.dart'; class FinishPrivatePage extends StatefulWidget { @@ -202,7 +204,7 @@ class _FinishPrivatePageState extends State { child: ClipOval( child: (profileImg.isNotEmpty) ? Image.network( - 'https://eldsoft.com:8097/images$profileImg', + '${Config.baseUrl}/images$profileImg', fit: BoxFit.cover, errorBuilder: (_, __, ___) => const Center(child: Text('ERR')), ) diff --git a/lib/views/room/finish_team_page.dart b/lib/views/room/finish_team_page.dart index 68cc3a3..f61c0f5 100644 --- a/lib/views/room/finish_team_page.dart +++ b/lib/views/room/finish_team_page.dart @@ -6,6 +6,8 @@ import '../../dialogs/response_dialog.dart'; import '../../dialogs/room_setting_finish_dialog.dart'; import '../../dialogs/user_info_finish_dialog.dart'; +import '../../config/config.dart'; + import 'main_page.dart'; class FinishTeamPage extends StatefulWidget { @@ -265,7 +267,7 @@ class _FinishTeamPageState extends State { ), child: ClipOval( child: Image.network( - 'https://eldsoft.com:8097/images$profileImg', + '${Config.baseUrl}/images$profileImg', fit: BoxFit.cover, errorBuilder: (ctx, err, st) => const Center( child: Text('ERR', style: TextStyle(fontSize: 8)), diff --git a/lib/views/room/playing_private_page.dart b/lib/views/room/playing_private_page.dart index 9b92712..18cd301 100644 --- a/lib/views/room/playing_private_page.dart +++ b/lib/views/room/playing_private_page.dart @@ -423,7 +423,7 @@ class _PlayingPrivatePageState extends State { ) : ClipOval( child: Image.network( - 'https://eldsoft.com:8097/images${user['profile_img']}', + '${Config.baseUrl}/images${user['profile_img']}', fit: BoxFit.cover, errorBuilder: (_, __, ___) => const Center(child: Text('ERR', style: TextStyle(fontSize: 8))), diff --git a/lib/views/room/playing_team_page.dart b/lib/views/room/playing_team_page.dart index f35a7ab..9070d66 100644 --- a/lib/views/room/playing_team_page.dart +++ b/lib/views/room/playing_team_page.dart @@ -608,7 +608,7 @@ class _PlayingTeamPageState extends State { ) : ClipOval( child: Image.network( - profileImg.isNotEmpty ? 'https://eldsoft.com:8097/images$profileImg' : '', + profileImg.isNotEmpty ? '${Config.baseUrl}/images$profileImg' : '', fit: BoxFit.cover, errorBuilder: (ctx, err, st) => const Center( child: Text( diff --git a/lib/views/room/waiting_room_private_page.dart b/lib/views/room/waiting_room_private_page.dart index 36ba79a..891bb34 100644 --- a/lib/views/room/waiting_room_private_page.dart +++ b/lib/views/room/waiting_room_private_page.dart @@ -727,6 +727,7 @@ class _WaitingRoomPrivatePageState extends State { } else if (isAdmin) { roleIcon = '☆ '; // 사회자 } + print('profileImg: ${Config.baseUrl}/images$profileImg'); final displayName = '$roleIcon$userName'; @@ -792,7 +793,7 @@ class _WaitingRoomPrivatePageState extends State { ), ) : Image.network( - 'https://eldsoft.com:8097/images$profileImg', + '${Config.baseUrl}/images$profileImg', fit: BoxFit.cover, errorBuilder: (_, __, ___) => const Center( child: Text( diff --git a/lib/views/room/waiting_room_team_page.dart b/lib/views/room/waiting_room_team_page.dart index 6a96f6e..7b563d5 100644 --- a/lib/views/room/waiting_room_team_page.dart +++ b/lib/views/room/waiting_room_team_page.dart @@ -945,7 +945,7 @@ class _WaitingRoomTeamPageState extends State { ), ) : Image.network( - 'https://eldsoft.com:8097/images$profileImg', + '${Config.baseUrl}/images$profileImg', fit: BoxFit.cover, errorBuilder: (_, __, ___) => const Center( child: Text( diff --git a/lib/views/user/my_page.dart b/lib/views/user/my_page.dart index 9033b53..2eca2dd 100644 --- a/lib/views/user/my_page.dart +++ b/lib/views/user/my_page.dart @@ -9,6 +9,7 @@ import '../../plugins/utils.dart'; import 'withdrawal_page.dart'; import 'package:image_picker/image_picker.dart'; import 'dart:io'; +import '../../config/config.dart'; import '../room/main_page.dart'; class MyPage extends StatefulWidget { @@ -595,7 +596,7 @@ class _MyPageState extends State { child: ClipRRect( borderRadius: BorderRadius.circular(20), child: Image.network( - 'https://eldsoft.com:8097/images$user_profile_image', + '${Config.baseUrl}/images$user_profile_image', fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return const Center(