종료 페이지 완료, 애드몹 전부 적용 완료, 설문조사 시작
This commit is contained in:
parent
f416094820
commit
a8445b70ed
@ -17,7 +17,16 @@ class RoomSettingFinishDialog extends StatelessWidget {
|
||||
final String openYn = (roomInfo['open_yn'] ?? 'Y') as String;
|
||||
final int maxPeople = (roomInfo['number_of_people'] ?? 0) as int;
|
||||
final int runningTime = (roomInfo['running_time'] ?? 0) as int;
|
||||
final String scoreOpen = (roomInfo['score_open_range'] ?? 'ALL') as String;
|
||||
final String tempScoreOpen = (roomInfo['score_open_range'] ?? 'ALL') as String;
|
||||
var scoreOpen = '';
|
||||
|
||||
if (tempScoreOpen == 'ALL' || tempScoreOpen == 'all') {
|
||||
scoreOpen = '전체 공개';
|
||||
} else if (tempScoreOpen == 'TEAM' || tempScoreOpen == 'team') {
|
||||
scoreOpen = '팀 공개';
|
||||
} else {
|
||||
scoreOpen = '개인 공개';
|
||||
}
|
||||
|
||||
final String openLabel = (openYn == 'Y') ? '공개' : '비공개';
|
||||
|
||||
|
111
lib/dialogs/survey_dialog.dart
Normal file
111
lib/dialogs/survey_dialog.dart
Normal file
@ -0,0 +1,111 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
// 예시: 설문 참여 버튼을 눌렀을 때 이동할 임시 설문 페이지
|
||||
// 실제 구현에서는 SurveyPage를 만들어 사용하시면 됩니다.
|
||||
class SurveyPage extends StatelessWidget {
|
||||
const SurveyPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('임시 설문 페이지'),
|
||||
backgroundColor: Colors.black,
|
||||
),
|
||||
body: const Center(
|
||||
child: Text('여기는 설문 페이지입니다 (임시).'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 팝업(모달) 자체를 보여주는 함수
|
||||
Future<void> showSurveyDialog(BuildContext context) async {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false, // 바깥 영역 터치로 닫기 방지
|
||||
builder: (_) => const SurveyDialog(),
|
||||
);
|
||||
}
|
||||
|
||||
/// 실제 AlertDialog 형태의 위젯
|
||||
class SurveyDialog extends StatefulWidget {
|
||||
const SurveyDialog({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<SurveyDialog> createState() => _SurveyDialogState();
|
||||
}
|
||||
|
||||
class _SurveyDialogState extends State<SurveyDialog> {
|
||||
bool _todayNotSee = false; // "오늘 하루 보지 않기" 체크 여부
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('설문 참여 안내'),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text(
|
||||
'안녕하세요, "올스코어" 앱을 이용해주셔서 감사합니다.\n\n'
|
||||
'더 나은 서비스 제공을 위해 간단한 설문조사를 준비했습니다.\n'
|
||||
'설문조사에 참여해주시면 앱 발전에 큰 도움이 됩니다!\n'
|
||||
'(약 1분 소요)',
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
// "오늘 하루 보지 않기" 체크박스
|
||||
Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: _todayNotSee,
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
_todayNotSee = val ?? false;
|
||||
});
|
||||
},
|
||||
),
|
||||
const Text('오늘 하루 보지 않기'),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
// "닫기" 버튼
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
// 오늘 하루 보지 않기를 체크했다면, SharedPreferences 저장
|
||||
if (_todayNotSee) {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
// 예: survey_popup_today = 'Y'
|
||||
await prefs.setString('survey_popup_today', 'Y');
|
||||
}
|
||||
Navigator.pop(context); // 팝업 닫기
|
||||
},
|
||||
style: TextButton.styleFrom(backgroundColor: Colors.grey),
|
||||
child: const Text('닫기', style: TextStyle(color: Colors.white)),
|
||||
),
|
||||
// "설문 참여" 버튼
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
// 오늘 하루 보지 않기를 체크했다면, SharedPreferences 저장
|
||||
if (_todayNotSee) {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('survey_popup_today', 'Y');
|
||||
}
|
||||
Navigator.pop(context); // 팝업 닫고
|
||||
// 임시 설문 페이지로 이동
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => const SurveyPage()),
|
||||
);
|
||||
},
|
||||
style: TextButton.styleFrom(backgroundColor: Colors.black),
|
||||
child: const Text('설문 참여', style: TextStyle(color: Colors.white)),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -6,14 +6,16 @@ import '../../dialogs/response_dialog.dart';
|
||||
import '../../dialogs/room_setting_finish_dialog.dart';
|
||||
import '../../dialogs/user_info_finish_dialog.dart';
|
||||
|
||||
import 'main_page.dart';
|
||||
|
||||
class FinishPrivatePage extends StatefulWidget {
|
||||
final int roomSeq;
|
||||
final bool fromPlayingPage; // 만약 대기/진행중에서 넘어온 경우 => 뒤로가기 시 메인으로
|
||||
final String enterType; // 대기/진행중에서 넘어온 경우 => 뒤로가기 시 메인으로
|
||||
|
||||
const FinishPrivatePage({
|
||||
Key? key,
|
||||
required this.roomSeq,
|
||||
this.fromPlayingPage = false,
|
||||
required this.enterType,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@ -28,10 +30,8 @@ class _FinishPrivatePageState extends State<FinishPrivatePage> {
|
||||
// userSeq → { user_seq, nickname, participant_type, score, ... }
|
||||
Map<String, dynamic> _userMap = {};
|
||||
|
||||
// 리스트로 만든 (관리자 제외) 참가자 목록 (점수 내림차순)
|
||||
// 리스트로 만든 참가자 목록 (점수 내림차순)
|
||||
List<Map<String, dynamic>> _playerList = [];
|
||||
// 별도 사회자(ADMIN) 목록 (개인전이라 1명이거나 없을 수 있음)
|
||||
List<Map<String, dynamic>> _adminList = [];
|
||||
|
||||
String _roomTitle = '';
|
||||
DateTime? _startDt;
|
||||
@ -87,17 +87,7 @@ class _FinishPrivatePageState extends State<FinishPrivatePage> {
|
||||
tempList.add(Map<String, dynamic>.from(val));
|
||||
});
|
||||
|
||||
// (1) 사회자(ADMIN) 분리
|
||||
final adminList = tempList.where((u) {
|
||||
final pType = (u['participant_type'] ?? '').toString().toUpperCase();
|
||||
return pType == 'ADMIN';
|
||||
}).toList();
|
||||
|
||||
// (2) 플레이어 목록 (ADMIN 제외) & 점수 내림차순
|
||||
final playerList = tempList.where((u) {
|
||||
final pType = (u['participant_type'] ?? '').toString().toUpperCase();
|
||||
return pType != 'ADMIN';
|
||||
}).toList();
|
||||
final playerList = tempList.toList();
|
||||
|
||||
// 점수 내림차순 정렬
|
||||
playerList.sort((a, b) {
|
||||
@ -107,7 +97,6 @@ class _FinishPrivatePageState extends State<FinishPrivatePage> {
|
||||
});
|
||||
|
||||
setState(() {
|
||||
_adminList = adminList;
|
||||
_playerList = playerList;
|
||||
_isLoading = false;
|
||||
});
|
||||
@ -128,9 +117,9 @@ class _FinishPrivatePageState extends State<FinishPrivatePage> {
|
||||
|
||||
/// (B) 뒤로가기
|
||||
Future<bool> _onWillPop() async {
|
||||
if (widget.fromPlayingPage) {
|
||||
// 진행중/대기중 등에서 넘어왔다면 => 메인으로
|
||||
Navigator.popUntil(context, (route) => route.isFirst);
|
||||
if (widget.enterType == 'game') {
|
||||
// 진행중에서 넘어왔다면 => 메인으로
|
||||
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (_) => const MainPage()), (route) => false);
|
||||
} else {
|
||||
// 검색 등에서 왔으면 => 한 단계 pop
|
||||
Navigator.pop(context);
|
||||
@ -163,9 +152,18 @@ class _FinishPrivatePageState extends State<FinishPrivatePage> {
|
||||
/// - 1등/2등/3등 금/은/동 메달
|
||||
Widget _buildPlayerItem(Map<String, dynamic> user, int index) {
|
||||
final score = (user['score'] ?? 0) as int;
|
||||
final nickname = user['nickname'] ?? '유저';
|
||||
var nickname = user['nickname'] ?? '유저';
|
||||
final profileImg = user['profile_img'] ?? '';
|
||||
final userSeq = user['user_seq'] ?? 0;
|
||||
final participantType = user['participant_type'] ?? '';
|
||||
|
||||
if (_masterUserSeq == userSeq) {
|
||||
// 방장 표시
|
||||
nickname = '★' + nickname;
|
||||
} else if (participantType == 'ADMIN') {
|
||||
// 관리자 표시
|
||||
nickname = '☆' + nickname;
|
||||
}
|
||||
|
||||
Widget medal = const SizedBox();
|
||||
if (index == 0) {
|
||||
@ -211,37 +209,6 @@ class _FinishPrivatePageState extends State<FinishPrivatePage> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 사회자 목록 (보통 1명 예상)
|
||||
Widget _buildAdminItem(Map<String, dynamic> admin) {
|
||||
final nickname = admin['nickname'] ?? '사회자';
|
||||
final profileImg = admin['profile_img'] ?? '';
|
||||
return GestureDetector(
|
||||
onTap: () => _onTapUser(admin),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 36, height: 36,
|
||||
margin: const EdgeInsets.only(right: 8),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.deepPurple),
|
||||
),
|
||||
child: ClipOval(
|
||||
child: (profileImg.isNotEmpty)
|
||||
? Image.network(
|
||||
'https://eldsoft.com:8097/images$profileImg',
|
||||
fit: BoxFit.cover,
|
||||
errorBuilder: (_, __, ___) => const Center(child: Text('ERR')),
|
||||
)
|
||||
: const Center(child: Text('No\nImg', textAlign: TextAlign.center, style: TextStyle(fontSize: 10))),
|
||||
),
|
||||
),
|
||||
Text(nickname, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: Colors.deepPurple)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 사용자 클릭 -> 새 유저 정보 모달
|
||||
Future<void> _onTapUser(Map<String, dynamic> userData) async {
|
||||
// user_info_finish_dialog.dart (새 모달)
|
||||
@ -290,25 +257,6 @@ class _FinishPrivatePageState extends State<FinishPrivatePage> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// (B) 사회자 목록
|
||||
if (_adminList.isNotEmpty) ...[
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.deepPurple),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Text('사회자: ', style: TextStyle(fontSize: 14, color: Colors.deepPurple)),
|
||||
..._adminList.map(_buildAdminItem),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
|
||||
// (C) 참가자 목록
|
||||
ListView.builder(
|
||||
primary: false,
|
||||
|
@ -6,14 +6,16 @@ import '../../dialogs/response_dialog.dart';
|
||||
import '../../dialogs/room_setting_finish_dialog.dart';
|
||||
import '../../dialogs/user_info_finish_dialog.dart';
|
||||
|
||||
import 'main_page.dart';
|
||||
|
||||
class FinishTeamPage extends StatefulWidget {
|
||||
final int roomSeq;
|
||||
final bool fromPlayingPage; // 진행중에서 넘어왔는지 여부
|
||||
final String enterType; // 대기/진행중에서 넘어온 경우 => 뒤로가기 시 메인으로
|
||||
|
||||
const FinishTeamPage({
|
||||
Key? key,
|
||||
required this.roomSeq,
|
||||
this.fromPlayingPage = false,
|
||||
required this.enterType,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@ -37,8 +39,6 @@ class _FinishTeamPageState extends State<FinishTeamPage> {
|
||||
// 팀별 점수
|
||||
Map<String, int> _teamScoreMap = {};
|
||||
|
||||
// 별도 사회자 목록
|
||||
List<Map<String, dynamic>> _adminList = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -86,17 +86,8 @@ class _FinishTeamPageState extends State<FinishTeamPage> {
|
||||
tempList.add(Map<String, dynamic>.from(val));
|
||||
});
|
||||
|
||||
// (1) 사회자(ADMIN) 분리
|
||||
final adminList = tempList.where((u) {
|
||||
final pType = (u['participant_type'] ?? '').toString().toUpperCase();
|
||||
return pType == 'ADMIN';
|
||||
}).toList();
|
||||
|
||||
// (2) 일반 참가자
|
||||
final players = tempList.where((u) {
|
||||
final pType = (u['participant_type'] ?? '').toString().toUpperCase();
|
||||
return pType != 'ADMIN';
|
||||
}).toList();
|
||||
final players = tempList.toList();
|
||||
|
||||
// (3) 팀명별 분류 + 점수 합
|
||||
final Map<String, List<Map<String, dynamic>>> tMap = {};
|
||||
@ -138,7 +129,6 @@ class _FinishTeamPageState extends State<FinishTeamPage> {
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_adminList = adminList;
|
||||
_userList = tempList; // 전체 필요하면 보관
|
||||
_teamMap = finalTeamMap;
|
||||
_teamScoreMap = finalScoreMap;
|
||||
@ -160,8 +150,8 @@ class _FinishTeamPageState extends State<FinishTeamPage> {
|
||||
}
|
||||
|
||||
Future<bool> _onWillPop() async {
|
||||
if (widget.fromPlayingPage) {
|
||||
Navigator.popUntil(context, (route) => route.isFirst);
|
||||
if (widget.enterType == 'game') {
|
||||
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (_) => const MainPage()), (route) => false);
|
||||
} else {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
@ -241,8 +231,18 @@ class _FinishTeamPageState extends State<FinishTeamPage> {
|
||||
/// 팀 멤버 표시
|
||||
Widget _buildTeamMember(Map<String, dynamic> user) {
|
||||
final score = (user['score'] ?? 0) as int;
|
||||
final nickname = user['nickname'] ?? '유저';
|
||||
var nickname = user['nickname'] ?? '유저';
|
||||
final profileImg = user['profile_img'] ?? '';
|
||||
final userSeq = user['user_seq'] ?? 0;
|
||||
final participantType = user['participant_type'] ?? '';
|
||||
|
||||
if (_masterUserSeq == userSeq) {
|
||||
// 방장 표시
|
||||
nickname = '★' + nickname;
|
||||
} else if (participantType == 'ADMIN') {
|
||||
// 관리자 표시
|
||||
nickname = '☆' + nickname;
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => _onTapUser(user),
|
||||
@ -278,63 +278,6 @@ class _FinishTeamPageState extends State<FinishTeamPage> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 팀전 사회자 목록 (ADMIN)
|
||||
Widget _buildAdminList() {
|
||||
final adminList = _adminList;
|
||||
if (adminList.isEmpty) return const SizedBox();
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.only(top: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border.all(color: Colors.deepPurple),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
color: Colors.black,
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: const Center(
|
||||
child: Text('사회자', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)),
|
||||
),
|
||||
),
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
primary: false,
|
||||
itemCount: adminList.length,
|
||||
itemBuilder: (ctx, i) {
|
||||
final user = adminList[i];
|
||||
return _buildAdminItem(user);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAdminItem(Map<String, dynamic> user) {
|
||||
final nickname = user['nickname'] ?? '사회자';
|
||||
final profileImg = user['profile_img'] ?? '';
|
||||
|
||||
return ListTile(
|
||||
onTap: () => _onTapUser(user),
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.white,
|
||||
backgroundImage: (profileImg.isNotEmpty)
|
||||
? NetworkImage('https://eldsoft.com:8097/images$profileImg')
|
||||
: null,
|
||||
child: (profileImg.isEmpty)
|
||||
? const Text('NoImg', style: TextStyle(fontSize: 10))
|
||||
: null,
|
||||
),
|
||||
title: Text(nickname),
|
||||
subtitle: const Text('사회자'),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onTapUser(Map<String, dynamic> userData) async {
|
||||
// 새 유저 정보 모달
|
||||
await showDialog(
|
||||
@ -388,8 +331,6 @@ class _FinishTeamPageState extends State<FinishTeamPage> {
|
||||
for (int i = 0; i < teamNames.length; i++)
|
||||
_buildTeamBox(teamNames[i], i),
|
||||
|
||||
// 사회자 목록
|
||||
_buildAdminList(),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -22,6 +22,9 @@ import 'package:fluttertoast/fluttertoast.dart'; // 뒤로가기 안내 문구
|
||||
// 설정
|
||||
import '../../config/config.dart';
|
||||
|
||||
// 설문조사
|
||||
import '../../dialogs/survey_dialog.dart';
|
||||
|
||||
class MainPage extends StatefulWidget {
|
||||
const MainPage({Key? key}) : super(key: key);
|
||||
|
||||
@ -55,6 +58,9 @@ class _MainPageState extends State<MainPage> {
|
||||
|
||||
// (C) 배너 광고 초기화
|
||||
_initBannerAd();
|
||||
|
||||
// (D) 설문조사 팝업 표시
|
||||
_checkSurveyPopup();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -86,6 +92,18 @@ class _MainPageState extends State<MainPage> {
|
||||
_bannerAd?.load();
|
||||
}
|
||||
|
||||
/// "오늘 하루 보지 않기" 체크 여부 확인 후, 모달 보여줄지 결정
|
||||
Future<void> _checkSurveyPopup() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final shownToday = prefs.getString('survey_popup_today') ?? 'N';
|
||||
if (shownToday == 'N') {
|
||||
// 아직 오늘은 안 봤으므로 팝업 띄우기
|
||||
Future.delayed(Duration.zero, () {
|
||||
showSurveyDialog(context);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> _onWillPop() async {
|
||||
final now = DateTime.now();
|
||||
if (_lastPressedTime == null ||
|
||||
|
@ -143,7 +143,7 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
||||
if (mounted) {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => FinishPrivatePage(roomSeq: widget.roomSeq)),
|
||||
MaterialPageRoute(builder: (_) => FinishPrivatePage(roomSeq: widget.roomSeq, enterType: 'game')),
|
||||
(route) => false,
|
||||
);
|
||||
}
|
||||
@ -175,9 +175,12 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
||||
final List<Map<String, dynamic>> rawList = [];
|
||||
userInfoData.forEach((uSeq, uData) {
|
||||
// 방장 표시
|
||||
if (uSeq.toString() == roomInfoData['master_user_seq'].toString()) uData['nickname'] = '★' + (uData['nickname'] ?? '유저');
|
||||
// 관리자 표시
|
||||
if ((uData['participant_type'] ?? '').toString().toUpperCase() == 'ADMIN') uData['nickname'] = '☆' + (uData['nickname'] ?? '유저');
|
||||
if (uSeq.toString() == roomInfoData['master_user_seq'].toString()) {
|
||||
uData['nickname'] = '★' + (uData['nickname'] ?? '유저');
|
||||
} else if ((uData['participant_type'] ?? '').toString().toUpperCase() == 'ADMIN') {
|
||||
// 관리자 표시
|
||||
uData['nickname'] = '☆' + (uData['nickname'] ?? '유저');
|
||||
}
|
||||
rawList.add({
|
||||
'user_seq': uSeq,
|
||||
'participant_type': (uData['participant_type'] ?? '').toString().toUpperCase(),
|
||||
@ -222,6 +225,7 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
||||
MaterialPageRoute(
|
||||
builder: (_) => FinishPrivatePage(
|
||||
roomSeq: widget.roomSeq,
|
||||
enterType: 'game',
|
||||
),
|
||||
),
|
||||
(route) => false,
|
||||
|
@ -146,7 +146,7 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
||||
if (mounted) {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => FinishTeamPage(roomSeq: widget.roomSeq)),
|
||||
MaterialPageRoute(builder: (_) => FinishTeamPage(roomSeq: widget.roomSeq, enterType: 'game')),
|
||||
(route) => false,
|
||||
);
|
||||
}
|
||||
@ -253,6 +253,7 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
||||
MaterialPageRoute(
|
||||
builder: (_) => FinishTeamPage(
|
||||
roomSeq: widget.roomSeq,
|
||||
enterType: 'game',
|
||||
),
|
||||
),
|
||||
(route) => false,
|
||||
|
@ -1,12 +1,61 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'room_search_list_page.dart';
|
||||
|
||||
/// 방 검색 홈 화면
|
||||
/// - "대기중/진행중/종료" 버튼 3개로 구분
|
||||
/// - 버튼 누르면 RoomSearchListPage로 이동 + 상태값 전달
|
||||
class RoomSearchHomePage extends StatelessWidget {
|
||||
// 설정
|
||||
import '../../config/config.dart';
|
||||
|
||||
// 광고
|
||||
import 'package:google_mobile_ads/google_mobile_ads.dart'; // ★ AdMob 패키지
|
||||
|
||||
class RoomSearchHomePage extends StatefulWidget {
|
||||
const RoomSearchHomePage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<RoomSearchHomePage> createState() => _RoomSearchHomePageState();
|
||||
}
|
||||
|
||||
class _RoomSearchHomePageState extends State<RoomSearchHomePage> {
|
||||
BannerAd? _bannerAd;
|
||||
bool _isBannerReady = false; // 광고 로드 완료 여부
|
||||
String adUnitId = Config.testAdUnitId;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
// (C) 배너 광고 초기화
|
||||
_initBannerAd();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_bannerAd?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// 배너 광고 초기화
|
||||
void _initBannerAd() {
|
||||
_bannerAd = BannerAd(
|
||||
size: AdSize.banner, // 일반 배너 사이즈
|
||||
// adUnitId: 'ca-app-pub-3940256099942544/6300978111' (테스트용)
|
||||
adUnitId: adUnitId, // 실제/테스트 배너 광고 단위 ID
|
||||
listener: BannerAdListener(
|
||||
onAdLoaded: (Ad ad) {
|
||||
setState(() => _isBannerReady = true);
|
||||
debugPrint('배너 광고 로드 완료');
|
||||
},
|
||||
onAdFailedToLoad: (Ad ad, LoadAdError err) {
|
||||
debugPrint('배너 광고 로드 실패: $err');
|
||||
ad.dispose();
|
||||
},
|
||||
),
|
||||
request: const AdRequest(),
|
||||
);
|
||||
|
||||
// load() 호출로 광고 요청
|
||||
_bannerAd?.load();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -23,13 +72,14 @@ class RoomSearchHomePage extends StatelessWidget {
|
||||
),
|
||||
|
||||
// 화면 하단 광고 영역
|
||||
bottomNavigationBar: Container(
|
||||
height: 50,
|
||||
color: Colors.grey.shade400,
|
||||
child: const Center(
|
||||
child: Text('구글 광고', style: TextStyle(color: Colors.black)),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: _isBannerReady && _bannerAd != null
|
||||
? Container(
|
||||
color: Colors.white,
|
||||
width: _bannerAd!.size.width.toDouble(),
|
||||
height: _bannerAd!.size.height.toDouble(),
|
||||
child: AdWidget(ad: _bannerAd!),
|
||||
)
|
||||
: SizedBox.shrink(), // 로딩 전엔 빈 공간 or 원하는 위젯
|
||||
|
||||
// 본문: 중앙에 3개 버튼 (대기중 / 진행중 / 종료)
|
||||
body: Center(
|
||||
|
@ -10,6 +10,12 @@ import '../../dialogs/room_detail_dialog.dart';
|
||||
import '../room/finish_private_page.dart';
|
||||
import '../room/finish_team_page.dart';
|
||||
|
||||
// 설정
|
||||
import '../../config/config.dart';
|
||||
|
||||
// 광고
|
||||
import 'package:google_mobile_ads/google_mobile_ads.dart'; // ★ AdMob 패키지
|
||||
|
||||
class RoomSearchListPage extends StatefulWidget {
|
||||
final String roomStatus; // WAIT / RUNNING / FINISH
|
||||
|
||||
@ -31,12 +37,20 @@ class _RoomSearchListPageState extends State<RoomSearchListPage> {
|
||||
|
||||
late ScrollController _scrollController;
|
||||
|
||||
// 배너 광고 관련 변수
|
||||
BannerAd? _bannerAd;
|
||||
bool _isBannerReady = false; // 광고 로드 완료 여부
|
||||
String adUnitId = Config.testAdUnitId;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_scrollController = ScrollController()..addListener(_onScroll);
|
||||
_fetchRoomList(isRefresh: true);
|
||||
|
||||
// (C) 배너 광고 초기화
|
||||
_initBannerAd();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -44,9 +58,33 @@ class _RoomSearchListPageState extends State<RoomSearchListPage> {
|
||||
_scrollController.removeListener(_onScroll);
|
||||
_scrollController.dispose();
|
||||
_searchController.dispose();
|
||||
_bannerAd?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// 배너 광고 초기화
|
||||
void _initBannerAd() {
|
||||
_bannerAd = BannerAd(
|
||||
size: AdSize.banner, // 일반 배너 사이즈
|
||||
// adUnitId: 'ca-app-pub-3940256099942544/6300978111' (테스트용)
|
||||
adUnitId: adUnitId, // 실제/테스트 배너 광고 단위 ID
|
||||
listener: BannerAdListener(
|
||||
onAdLoaded: (Ad ad) {
|
||||
setState(() => _isBannerReady = true);
|
||||
debugPrint('배너 광고 로드 완료');
|
||||
},
|
||||
onAdFailedToLoad: (Ad ad, LoadAdError err) {
|
||||
debugPrint('배너 광고 로드 실패: $err');
|
||||
ad.dispose();
|
||||
},
|
||||
),
|
||||
request: const AdRequest(),
|
||||
);
|
||||
|
||||
// load() 호출로 광고 요청
|
||||
_bannerAd?.load();
|
||||
}
|
||||
|
||||
void _onScroll() {
|
||||
if (!_scrollController.hasClients) return;
|
||||
final thresholdPixels = 200;
|
||||
@ -161,7 +199,7 @@ class _RoomSearchListPageState extends State<RoomSearchListPage> {
|
||||
MaterialPageRoute(
|
||||
builder: (_) => FinishPrivatePage(
|
||||
roomSeq: roomSeq,
|
||||
fromPlayingPage: false, // ← 검색에서 왔으므로 false
|
||||
enterType: 'search',
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -171,7 +209,7 @@ class _RoomSearchListPageState extends State<RoomSearchListPage> {
|
||||
MaterialPageRoute(
|
||||
builder: (_) => FinishTeamPage(
|
||||
roomSeq: roomSeq,
|
||||
fromPlayingPage: false,
|
||||
enterType: 'search',
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -199,6 +237,15 @@ class _RoomSearchListPageState extends State<RoomSearchListPage> {
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
),
|
||||
// 화면 하단 광고 영역
|
||||
bottomNavigationBar: _isBannerReady && _bannerAd != null
|
||||
? Container(
|
||||
color: Colors.white,
|
||||
width: _bannerAd!.size.width.toDouble(),
|
||||
height: _bannerAd!.size.height.toDouble(),
|
||||
child: AdWidget(ad: _bannerAd!),
|
||||
)
|
||||
: SizedBox.shrink(), // 로딩 전엔 빈 공간 or 원하는 위젯
|
||||
body: Column(
|
||||
children: [
|
||||
// 검색창
|
||||
@ -232,21 +279,6 @@ class _RoomSearchListPageState extends State<RoomSearchListPage> {
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: _buildRoomListView(),
|
||||
),
|
||||
|
||||
Container(
|
||||
height: 60,
|
||||
color: Colors.white,
|
||||
child: Center(
|
||||
child: Container(
|
||||
height: 50,
|
||||
width: 300,
|
||||
color: Colors.grey.shade400,
|
||||
child: const Center(
|
||||
child: Text('구글 광고', style: TextStyle(color: Colors.black)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -333,7 +333,7 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
||||
}
|
||||
|
||||
/// 뒤로가기 → 방 나가기
|
||||
Future<void> _onLeaveRoom() async {
|
||||
Future<bool> _onLeaveRoom() async {
|
||||
if (roomMasterYn == 'Y') {
|
||||
// 방장
|
||||
final confirm = await showDialog<bool>(
|
||||
@ -378,7 +378,7 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
||||
);
|
||||
},
|
||||
);
|
||||
if (confirm != true) return;
|
||||
if (confirm != true) return false;
|
||||
|
||||
// leave API
|
||||
setState(() {_roomExitYn = 'Y';});
|
||||
@ -388,6 +388,7 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
||||
setState(() {_roomExitYn = 'Y';});
|
||||
await _requestLeaveRoom();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int _toInt(dynamic val, int defaultVal) {
|
||||
@ -557,9 +558,11 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
||||
// 남은시간 (기본: 60:00 ~ 0:00)
|
||||
final countdownStr = _formatDuration(_remaining);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
return WillPopScope(
|
||||
onWillPop: () => _onLeaveRoom(),
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.black,
|
||||
elevation: 0,
|
||||
// 방 제목 + 남은시간 표시
|
||||
@ -580,7 +583,7 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
||||
),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
|
||||
onPressed: _onLeaveRoom,
|
||||
onPressed: () => _onLeaveRoom(),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: _isBannerReady && _bannerAd != null
|
||||
@ -602,43 +605,16 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
||||
_buildTopButtons(),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// const Text('사회자', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
||||
// const SizedBox(height: 8),
|
||||
// _buildAdminSection(),
|
||||
// const SizedBox(height: 20),
|
||||
|
||||
const Text('참가자', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 8),
|
||||
_buildPlayerSection(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Widget _buildAdminSection() {
|
||||
// final adminList = _userList.where((u) {
|
||||
// final t = (u['participant_type'] ?? '').toString().toUpperCase();
|
||||
// return t == 'ADMIN';
|
||||
// }).toList();
|
||||
|
||||
// return Container(
|
||||
// padding: const EdgeInsets.all(8),
|
||||
// decoration: BoxDecoration(
|
||||
// color: Colors.white,
|
||||
// border: Border.all(color: Colors.black),
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
// ),
|
||||
// child: adminList.isEmpty
|
||||
// ? const Text('사회자가 없습니다.')
|
||||
// : Wrap(
|
||||
// spacing: 16,
|
||||
// runSpacing: 8,
|
||||
// children: adminList.map(_buildSeat).toList(),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
|
||||
Widget _buildPlayerSection() {
|
||||
final playerList = _userList.where((u) {
|
||||
final t = (u['user_seq'] ?? null);
|
||||
|
@ -344,7 +344,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
||||
}
|
||||
|
||||
// 뒤로가기 -> 방 나가기
|
||||
Future<void> _onLeaveRoom() async {
|
||||
Future<bool> _onLeaveRoom() async {
|
||||
if (roomMasterYn == 'Y') {
|
||||
final confirm = await showDialog<bool>(
|
||||
context: context,
|
||||
@ -388,7 +388,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
||||
);
|
||||
},
|
||||
);
|
||||
if (confirm != true) return;
|
||||
if (confirm != true) return false;
|
||||
|
||||
// leave API
|
||||
setState(() {_roomExitYn = 'Y';});
|
||||
@ -397,6 +397,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
||||
setState(() {_roomExitYn = 'Y';});
|
||||
await _requestLeaveRoom();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int _toInt(dynamic val, int defaultVal) {
|
||||
@ -581,9 +582,11 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
||||
Widget build(BuildContext context) {
|
||||
final countdownStr = _formatDuration(_remaining);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
return WillPopScope(
|
||||
onWillPop: () => _onLeaveRoom(),
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.black,
|
||||
elevation: 0,
|
||||
// 방 제목 + 남은시간
|
||||
@ -604,7 +607,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
||||
),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
|
||||
onPressed: _onLeaveRoom,
|
||||
onPressed: () => _onLeaveRoom(),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: _isBannerReady && _bannerAd != null
|
||||
@ -625,11 +628,6 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
||||
_buildTopButtons(),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// const Text('사회자', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black)),
|
||||
// const SizedBox(height: 8),
|
||||
// _buildAdminSection(),
|
||||
// const SizedBox(height: 20),
|
||||
|
||||
const Text('팀별 참가자', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black)),
|
||||
const SizedBox(height: 8),
|
||||
_buildTeamSection(),
|
||||
@ -639,32 +637,10 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Widget _buildAdminSection() {
|
||||
// final adminList = _userList.where((u) {
|
||||
// final pType = (u['participant_type'] ?? '').toString().toUpperCase();
|
||||
// return pType == 'ADMIN';
|
||||
// }).toList();
|
||||
|
||||
// return Container(
|
||||
// padding: const EdgeInsets.all(8),
|
||||
// decoration: BoxDecoration(
|
||||
// color: Colors.white,
|
||||
// border: Border.all(color: Colors.black),
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
// ),
|
||||
// child: adminList.isEmpty
|
||||
// ? const Text('사회자가 없습니다.', style: TextStyle(color: Colors.black))
|
||||
// : Wrap(
|
||||
// spacing: 16,
|
||||
// runSpacing: 8,
|
||||
// children: adminList.map(_buildSeat).toList(),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
|
||||
Widget _buildTeamSection() {
|
||||
final players = _userList.where((u) {
|
||||
final t = (u['user_seq'] ?? null);
|
||||
|
Loading…
Reference in New Issue
Block a user