코드 1차 최종

This commit is contained in:
eld_master 2025-01-20 14:45:55 +09:00
parent 858169fa8d
commit b34802b894
19 changed files with 233 additions and 73 deletions

View File

@ -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 , .)

View File

@ -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';
}

View File

@ -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(

View File

@ -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': '',

View File

@ -132,7 +132,6 @@ class _SurveyPageState extends State<SurveyPage> {
final requestBody = {
"QNA": qnaList.toString(),
};
print('requestBody: $requestBody');
try {
final response = await Api.serverRequest(uri: '/survey/collect', body: requestBody);

View File

@ -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<InquiryToManagerPage> {
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),
),
),
),
],
),
),
);
}
}

View File

@ -30,7 +30,7 @@ class _IdFindingPageState extends State<IdFindingPage> {
/// (1)
BannerAd? _bannerAd;
bool _isBannerReady = false; //
String adUnitId = Config.testAdUnitId;
String adUnitId = Config.adUnitId;
Future<void> _findId(String nickname, String email) async {
@ -62,7 +62,6 @@ class _IdFindingPageState extends State<IdFindingPage> {
if (response.statusCode == 200) {
final Map<String, dynamic> jsonResponse = jsonDecode(responseBody);
print('ID 찾기 성공: $jsonResponse');
//
setState(() {
@ -130,7 +129,6 @@ class _IdFindingPageState extends State<IdFindingPage> {
Future<void> _findAllId() async {
// ID
print('ID 전체 찾기 요청 $authId'); //
//
showDialog(
@ -158,7 +156,6 @@ class _IdFindingPageState extends State<IdFindingPage> {
if (response.statusCode == 200) {
final Map<String, dynamic> jsonResponse = jsonDecode(responseBody);
print('ID 전체 찾기 성공: $jsonResponse');
if (jsonResponse['result'] == 'OK') {
//

View File

@ -59,7 +59,7 @@ class _LoginPageState extends State<LoginPage> {
//
BannerAd? _bannerAd;
bool _isBannerReady = false;
String adUnitId = Config.testAdUnitId;
String adUnitId = Config.adUnitId;
//
DateTime? _lastPressedTime;
@ -146,7 +146,6 @@ class _LoginPageState extends State<LoginPage> {
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<LoginPage> {
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),
),
),
],
),
),

View File

@ -28,11 +28,10 @@ class _PwFindingPageState extends State<PwFindingPage> {
/// (1)
BannerAd? _bannerAd;
bool _isBannerReady = false; //
String adUnitId = Config.testAdUnitId;
String adUnitId = Config.adUnitId;
Future<void> _findPassword(String id, String email) async {
// PW
print('PW 찾기 요청: ID: $id, 이메일: $email'); //
//
showDialog(
@ -61,7 +60,6 @@ class _PwFindingPageState extends State<PwFindingPage> {
if (response.statusCode == 200) {
final Map<String, dynamic> jsonResponse = jsonDecode(responseBody);
print('PW 찾기 성공: $jsonResponse');
//
setState(() {

View File

@ -74,7 +74,6 @@ class _SignUpPageState extends State<SignUpPage> {
if (response.statusCode == 200) {
// result가 OK이어야만
print(resBody);
if (resBody['result'] == 'OK') {
if (resBody['response_info']['msg_type'] == 'OK') {
_showDialog('회원가입 성공', '회원가입이 완료되었습니다.');

View File

@ -36,7 +36,7 @@ class _MainPageState extends State<MainPage> {
/// (1)
BannerAd? _bannerAd;
bool _isBannerReady = false; //
String adUnitId = Config.testAdUnitId;
String adUnitId = Config.adUnitId;
//
DateTime? _lastPressedTime;
@ -75,10 +75,8 @@ class _MainPageState extends State<MainPage> {
listener: BannerAdListener(
onAdLoaded: (Ad ad) {
setState(() => _isBannerReady = true);
debugPrint('배너 광고 로드 완료');
},
onAdFailedToLoad: (Ad ad, LoadAdError err) {
debugPrint('배너 광고 로드 실패: $err');
ad.dispose();
},
),

View File

@ -64,7 +64,7 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
/// (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<PlayingPrivatePage> {
}
final data = snapshot.value as Map<dynamic, dynamic>? ?? {};
print('data111111111 $data');
final roomInfoData = data['roomInfo'] as Map<dynamic, dynamic>? ?? {};
final userInfoData = data['userInfo'] as Map<dynamic, dynamic>? ?? {};
final userListData = data['userList'] as Map<dynamic, dynamic>? ?? {};

View File

@ -66,7 +66,7 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
/// (1)
BannerAd? _bannerAd;
bool _isBannerReady = false; //
String adUnitId = Config.testAdUnitId;
String adUnitId = Config.adUnitId;
@override
void initState() {

View File

@ -17,7 +17,7 @@ class RoomSearchHomePage extends StatefulWidget {
class _RoomSearchHomePageState extends State<RoomSearchHomePage> {
BannerAd? _bannerAd;
bool _isBannerReady = false; //
String adUnitId = Config.testAdUnitId;
String adUnitId = Config.adUnitId;
@override
void initState() {
@ -42,11 +42,9 @@ class _RoomSearchHomePageState extends State<RoomSearchHomePage> {
listener: BannerAdListener(
onAdLoaded: (Ad ad) {
setState(() => _isBannerReady = true);
debugPrint('배너 광고 로드 완료');
},
onAdFailedToLoad: (Ad ad, LoadAdError err) {
debugPrint('배너 광고 로드 실패: $err');
ad.dispose();
//
},
),
request: const AdRequest(),

View File

@ -40,7 +40,7 @@ class _RoomSearchListPageState extends State<RoomSearchListPage> {
//
BannerAd? _bannerAd;
bool _isBannerReady = false; //
String adUnitId = Config.testAdUnitId;
String adUnitId = Config.adUnitId;
@override
void initState() {
@ -71,10 +71,8 @@ class _RoomSearchListPageState extends State<RoomSearchListPage> {
listener: BannerAdListener(
onAdLoaded: (Ad ad) {
setState(() => _isBannerReady = true);
debugPrint('배너 광고 로드 완료');
},
onAdFailedToLoad: (Ad ad, LoadAdError err) {
debugPrint('배너 광고 로드 실패: $err');
ad.dispose();
},
),

View File

@ -77,7 +77,7 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
/// (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<WaitingRoomPrivatePage> {
Future<void> _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<WaitingRoomPrivatePage> {
if (response['result'] == 'OK') {
final resp = response['response'] ?? {};
if (resp['result'] == 'OK') {
print('게임 시작 요청 성공(개인전)');
//
} else {
// ...
//
showResponseDialog(context, '오류', '게임 시작 실패했습니다.');
}
} else {
// ...
//
showResponseDialog(context, '오류', '게임 시작 실패했습니다.');
}
} catch (e) {
// ...
//
showResponseDialog(context, '오류', '게임 시작 실패했습니다.');
}
}

View File

@ -79,7 +79,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
/// (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<WaitingRoomTeamPage> {
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<WaitingRoomTeamPage> {
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 {

View File

@ -606,7 +606,6 @@ class _MyPageState extends State<MyPage> {
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<MyPage> {
},
);
print('serverResponse 응답: $serverResponse');
// null인지
if (serverResponse == null) {
throw Exception('서버 응답이 null입니다.');
@ -882,7 +879,6 @@ class _MyPageState extends State<MyPage> {
};
}
} catch (e) {
print('serverResponse 오류: $e');
return {
'result': 'FAIL',
};
@ -908,7 +904,6 @@ class _MyPageState extends State<MyPage> {
if (serverResponse['result'] == 'OK') {
final serverResponse1 = serverResponse['response'];
print('응답: $serverResponse1');
if (serverResponse1['result'] == 'OK') {
showResponseDialog(context, '업로드 성공', '프로필 이미지가 성공적으로 업로드되었습니다.');

View File

@ -18,8 +18,27 @@ class _WithdrawalPageState extends State<WithdrawalPage> {
bool _isAgreed = false; //
final TextEditingController _passwordController = TextEditingController(); //
String _oauthType = 'idpw';
@override
void initState() {
super.initState();
_loadOAuthType(); // SharedPreferences에서 oauth_type
}
/// SharedPreferences에서 oauth_type
Future<void> _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<WithdrawalPage> {
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<WithdrawalPage> {
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<WithdrawalPage> {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.remove('auth_token'); //
showResponseDialog(context, '회원탈퇴 완료', '회원탈퇴가 완료되었습니다.');
await showResponseDialog(context, '회원탈퇴 완료', '회원탈퇴가 완료되었습니다.');
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const LoginPage()), //