Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e65b092
:recycle: :: MatchListEvent 의 μƒνƒœλ₯Ό LoadItems둜 λ³€κ²½
answad May 28, 2025
c68d1da
:sparkles: :: item Loading κΈ°λŠ₯이 μžˆλŠ” MatchListBloc 생성
answad May 28, 2025
87fe2f0
:recycle: :: MatchListScreen 이 stageId, 년도, 달, 일, 을 받도둝 μˆ˜μ •
answad May 28, 2025
53a8b0f
:recycle: :: MatchListScreen을 blocκ³Ό μ—°κ²°
answad May 28, 2025
74e588f
:recycle: :: matchList λΌμš°νŒ… μ„€μ •
answad May 29, 2025
8f4f865
Merge branch 'develop' of https://github.com/team-gogo/GOGO-App into …
iloveuhyeon May 29, 2025
86ffa72
:recycle: :: Match Participant widget μˆ˜μ •
iloveuhyeon May 29, 2025
24cf4f8
:recycle: :: Community main screen, match list screen에 λ‘œλ”© μΈλ””κ²Œμ΄ν„° μΆ”κ°€
iloveuhyeon May 30, 2025
a3d8425
:sparkles: :: batting state μΆ”κ°€
answad May 30, 2025
0820ec9
:sparkles: :: batting event μΆ”κ°€
answad May 30, 2025
d111c1e
:recycle: :: _onBettingMatch ν•¨μˆ˜ μΆ”κ°€
answad May 30, 2025
90b2717
:recycle: :: MatchBattingStatusDialogκ°€ μ™ΈλΆ€μ—μ„œ bettingControllerλ₯Ό λ°›μ•„μ„œ μ‚¬μš©β€¦
answad Jun 2, 2025
eed6a9b
:recycle: :: showDialogMatchBatting ν•¨μˆ˜μ—μ„œ μ‹€μ œλ‘œ λ°°νŒ…μ„ ν•  수 μžˆλ„λ‘ μˆ˜μ •
answad Jun 2, 2025
42077cd
:recycle: :: BettingMatch event 와 _onBettingMatch ν•¨μˆ˜λ₯Ό μ—°κ²°
answad Jun 2, 2025
46ea73f
:recycle: :: batting 후에 μžλ™μœΌλ‘œ λ‘œμ»¬μ—μ„œ λ°°νŒ… κΈˆμ•‘μ„ μ˜¬λ¦¬λ„λ‘ μˆ˜μ •
answad Jun 2, 2025
637e238
Merge remote-tracking branch 'origin/develop' into feature/#174-match…
answad Jun 3, 2025
8c258d7
Merge remote-tracking branch 'origin/feature/#174-matchlistpage-batti…
answad Jun 3, 2025
1f3bf09
:recycle: :: BettingRepository을 get instance에 μΆ”κ°€
answad Jun 3, 2025
6fba73d
:recycle: :: BettingDataSourceλ₯Ό get instance에 μΆ”κ°€
answad Jun 3, 2025
5583368
:recycle: :: selectedTeam을 μƒμœ„ μœ„μ ―μ—μ„œ κ΄€λ¦¬ν•˜λ„λ‘ λ³€κ²½ν•˜κ³  μ„ νƒλœ μœ„μ ―μ— λ”°λΌμ„œ 색이 λ³€ν•˜κ²Œ λ³€κ²½
answad Jun 3, 2025
6f139a3
:recycle: :: λ°°νŒ…μ΄ λ‘œμ»¬μ—μ„œ λ°”λ‘œλ°”λ‘œ μ μš©λ˜λ„λ‘ μˆ˜μ •
answad Jun 3, 2025
15c1831
:recycle: :: λ°°νŒ… λͺ¨λ‹¬μ—μ„œ λ°°νŒ… 후에 λ°°νŒ… λͺ¨λ‹¬μ΄ λ‹«νžˆμ§€ μ•Šλ„λ‘ μˆ˜μ •
answad Jun 4, 2025
71b92b3
:recycle: :: home screenμ—μ„œ λ°°νŒ…μ΄ κ°€λŠ₯ν•˜λ„λ‘ λ°°νŒ…λͺ¨λ‹¬ μΆ”κ°€
answad Jun 4, 2025
b9bc804
:recycle: :: μ—λŸ¬ μˆ˜μ • 및 퍼블리싱 μˆ˜μ •
iloveuhyeon Jun 4, 2025
3742d02
:recycle: :: 둜컬 포인트 볡ꡬ
answad Jun 4, 2025
5b3c33b
:recycle: :: μ˜ˆμ™Έμ²˜λ¦¬ ν† μŠ€νŠΈ μΆ”κ°€
answad Jun 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 21 additions & 22 deletions lib/presentation/community/screen/community_main_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'package:gogo_app/presentation/community/screen/community_detail_screen.d
import 'package:gogo_app/presentation/community/widgets/community_filter_popup.dart';
import 'package:gogo_app/presentation/community/widgets/community_item.dart';
import 'package:go_router/go_router.dart';
import 'package:gogo_app/presentation/loading/widgets/loading_indicator.dart';
import 'dart:math';
import '../../../design_system/component/tag/gogo_tag_component.dart';
import '../../../design_system/component/top_bar/gogo_top_bar.dart';
Expand Down Expand Up @@ -130,23 +131,25 @@ class _CommunityMainScreenContentState
),
const SizedBox(width: 12),
GestureDetector(
onTap: state is CommunityLoadedState ? () async {
final result = await filterDialog(
context,
gameType,
sortType,
state is CommunityLoadedState
? state.gameTypes
: [],
);
if (gameType == result['gameType'] &&
sortType == result['sortType']) {
return;
}
gameType = result['gameType'];
sortType = result['sortType'];
_fetchCommunity();
} : null,
onTap: state is CommunityLoadedState
? () async {
final result = await filterDialog(
context,
gameType,
sortType,
state is CommunityLoadedState
? state.gameTypes
: [],
);
if (gameType == result['gameType'] &&
sortType == result['sortType']) {
return;
}
gameType = result['gameType'];
sortType = result['sortType'];
_fetchCommunity();
}
: null,
child: GogoTagComponent(
color: GogoColors.main500,
text: 'ν•„ν„°',
Expand Down Expand Up @@ -217,11 +220,7 @@ class _CommunityMainScreenContentState
builder: (context, state) {
if (state is CommunityLoadingState) {
return Expanded(
child: Center(
child: CircularProgressIndicator(
color: GogoColors.main500,
),
),
child: Center(child: LoadingIndicator()),
);
} else if (state is CommunityLoadedState) {
final totalPage = state.response.info.totalPage;
Expand Down
2 changes: 1 addition & 1 deletion lib/presentation/home/widgets/appbar/home_appbar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class HomeAppbar extends StatefulWidget {
}

class _HomeAppbarState extends State<HomeAppbar> {
final now = DateTime(2025,04,20);
final now = DateTime.now();
final ScrollController scrollController = ScrollController();

@override
Expand Down
38 changes: 22 additions & 16 deletions lib/presentation/home/widgets/match_card/match_card_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -183,28 +183,34 @@ class MatchCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
spacing: 16,
children: [
Text(
"${matchDto.ateam.teamName}νŒ€",
style: GogoTypography.body1Extrabold.copyWith(
color: matchDto.betting.isBetting &&
matchDto.betting.predictedWinTeamId ==
matchDto.ateam.teamId
? GogoColors.main500
: GogoColors.white),
Expanded(
child: Text(
"${matchDto.ateam.teamName}νŒ€",
overflow: TextOverflow.ellipsis,
style: GogoTypography.body1Extrabold.copyWith(
color: matchDto.betting.isBetting &&
matchDto.betting.predictedWinTeamId ==
matchDto.ateam.teamId
? GogoColors.main500
: GogoColors.white),
),
),
Text(
"VS",
style: GogoTypography.body2Extrabold
.copyWith(color: GogoColors.gray500),
),
Text(
"${matchDto.bteam.teamName}νŒ€",
style: GogoTypography.body1Extrabold.copyWith(
color: matchDto.betting.isBetting &&
matchDto.betting.predictedWinTeamId ==
matchDto.bteam.teamId
? GogoColors.main500
: GogoColors.white,
Expanded(
child: Text(
"${matchDto.bteam.teamName}νŒ€",
overflow: TextOverflow.ellipsis,
style: GogoTypography.body1Extrabold.copyWith(
color: matchDto.betting.isBetting &&
matchDto.betting.predictedWinTeamId ==
matchDto.bteam.teamId
? GogoColors.main500
: GogoColors.white,
),
),
),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class MatchParticipantWidget extends StatelessWidget {
right: redOrBlue == TeamColor.red ? x : null,
top: y,
child: MatchParticipantItem(
redOrBlue: TeamColor.red,
redOrBlue: redOrBlue,
name: name,
),
);
Expand Down
57 changes: 57 additions & 0 deletions lib/presentation/match_list/bloc/match_list_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get_it/get_it.dart';
import 'package:gogo_app/data/models/stage/enum_type/game_type.dart';
import '../../../data/repositories/stage/stage_repository.dart';
import 'match_list_event.dart';
import 'match_list_state.dart';
import '../../../data/models/common/match_dto.dart';

class MatchListBloc extends Bloc<MatchListEvent, MatchListState> {
final StageRepository _stageRepository = GetIt.instance<StageRepository>();

final int stageId;
final int year;
final int month;
final int day;
GameType? gameType;

MatchListBloc({
required this.stageId,
required this.year,
required this.month,
required this.day,
}) : super(InitMatchList()) {
on<LoadItems>(_onLoadItems);
}

Future<void> _onLoadItems(
LoadItems event, Emitter<MatchListState> emit) async {
emit(LoadingMatchList());

try {
final matchesResponse = await _stageRepository.searchMatch(
stageId,
year,
month,
day,
);
List<MatchDto> filtered = matchesResponse.matches;

if (event.gameType != null) {
filtered =
filtered.where((e) => event.gameType == event.gameType).toList();
Copy link

Copilot AI May 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The filter predicate compares event.gameType to itself, which is always true. It should compare each item's gameType, e.g., e.gameType == event.gameType.

Suggested change
filtered.where((e) => event.gameType == event.gameType).toList();
filtered.where((e) => e.gameType == event.gameType).toList();

Copilot uses AI. Check for mistakes.
}
if (event.sortOrder != null) {
filtered.sort((a, b) {
return event.sortOrder == SortOrder.ascending
? a.startDate.compareTo(b.startDate)
: b.startDate.compareTo(a.startDate);
});
}

emit(LoadedMatchList(matchList: filtered, hasReachedMax: true));
} catch (e) {
emit(InitMatchList());
}
}
}
17 changes: 9 additions & 8 deletions lib/presentation/match_list/bloc/match_list_event.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import 'package:gogo_app/data/models/stage/enum_type/game_type.dart';

abstract class MatchListEvent {}

class GetMatchList extends MatchListEvent {
final int page;
final int pageSize;
class LoadItems extends MatchListEvent {
final GameType? gameType;
final SortOrder? sortOrder;

LoadItems({this.gameType, this.sortOrder});
}

GetMatchList({
required this.page,
required this.pageSize,
});
}
enum SortOrder { ascending, descending }
164 changes: 115 additions & 49 deletions lib/presentation/match_list/screen/match_list_screen.dart
Original file line number Diff line number Diff line change
@@ -1,66 +1,132 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:gogo_app/data/models/common/match_dto.dart';
import 'package:gogo_app/design_system/component/tag/gogo_tag_component.dart';
import 'package:gogo_app/design_system/component/top_bar/gogo_top_bar.dart';
import 'package:gogo_app/design_system/theme/color.dart';

import '../../../data/models/stage/enum_type/game_type.dart';
import '../../../data/models/stage/enum_type/match_round.dart';
import '../../../data/models/stage/enum_type/system_type.dart';
import '../../../data/models/stage/search_stage/search_betting_stage_response.dart';
import '../../../design_system/theme/icon.dart';
import 'package:gogo_app/design_system/theme/icon.dart';
import 'package:gogo_app/presentation/loading/widgets/loading_indicator.dart';
import '../../home/widgets/match_batting_status_dialog.dart';
import '../../home/widgets/match_card/match_card_component.dart';
import '../bloc/match_list_bloc.dart';
import '../bloc/match_list_event.dart';
import '../bloc/match_list_state.dart';

class MatchListScreen extends StatelessWidget {
const MatchListScreen({super.key});
final int stageId;
final int year;
final int month;
final int day;

const MatchListScreen(
{super.key,
required this.stageId,
required this.year,
required this.month,
required this.day});

@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
child: Column(
children: [
GogoTopBar(title: "맀치 λͺ©λ‘", onBackTap: ()=> context.pop()),
SizedBox(height: 12),
SizedBox(
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GogoTagComponent(
color: GogoColors.main500,
text: "ν•„ν„°",
icon: GogoIcons.filter(
color: GogoColors.main500,
width: 16,
height: 16,
),
)
],
),
return BlocProvider<MatchListBloc>(
create: (_) => MatchListBloc(
stageId: stageId,
year: year,
month: month,
day: day,
)..add(LoadItems(
gameType: null,
sortOrder: SortOrder.descending,
)),
child: Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
child: Column(
children: [
GogoTopBar(title: "맀치 λͺ©λ‘", onBackTap: () => context.pop()),
const SizedBox(height: 12),
SizedBox(
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GogoTagComponent(
color: GogoColors.main500,
text: "ν•„ν„°",
icon: GogoIcons.filter(
color: GogoColors.main500,
width: 16,
height: 16,
),
),
],
),
),
const SizedBox(height: 25),
Expanded(
child: BlocBuilder<MatchListBloc, MatchListState>(
builder: (context, state) {
if (state is LoadingMatchList) {
return const Center(child: LoadingIndicator());
} else if (state is LoadedMatchList) {
if (state.matchList.isEmpty) {
return Align(
alignment: Alignment.center,
child: Stack(
children: [
Text(
"였늘\nλ§€μΉ˜κ°€ μ—†μŠ΅λ‹ˆλ‹€",
style: TextStyle(
fontFamily: 'GmarketSans',
fontSize: 48,
foreground: Paint()
..style = PaintingStyle.stroke
..strokeWidth = 1
..color = GogoColors.main600,
),
textAlign: TextAlign.center,
),
Transform.translate(
offset: Offset(5, -3),
child: Text(
"였늘\nλ§€μΉ˜κ°€ μ—†μŠ΅λ‹ˆλ‹€",
style: TextStyle(
fontFamily: 'GmarketSans',
fontSize: 48,
color: GogoColors.main600,
),
textAlign: TextAlign.center,
),
),
],
),
);
}
return ListView.separated(
itemCount: state.matchList.length,
separatorBuilder: (_, __) =>
const SizedBox(height: 12),
itemBuilder: (context, index) {
final matchDto = state.matchList[index];
return MatchCard(
matchDto: matchDto,
width: double.infinity,
onBattingClick: () {
showDialogMatchBatting(context, matchDto);
},
);
},
);
} else {
return const SizedBox();
}
},
),
),
],
),
SizedBox(height: 25),
// Expanded(
// child: ListView.separated(
// itemCount: list.length,
// separatorBuilder: (context, index) =>
// SizedBox(height: 12), // 간격 μΆ”κ°€
// itemBuilder: (context, index) {
// final matchDto = list[index];
// return MatchCard(
// matchDto: matchDto,
// width: double.infinity,
// onBattingClick: () {
// showDialogMatchBatting(context, matchDto);
// },
// );
// },
// ),
// )
],
),
),
),
);
Expand Down
Loading