diff --git a/data/lib/api/match/match_model.dart b/data/lib/api/match/match_model.dart index 6832450b..fdf9f224 100644 --- a/data/lib/api/match/match_model.dart +++ b/data/lib/api/match/match_model.dart @@ -336,3 +336,105 @@ class TeamStat with _$TeamStat { @Default(0.0) double run_rate, }) = _TeamStat; } + +extension TeamStatExtension on List { + TeamStat teamStat(String teamId) { + if (isEmpty) return const TeamStat(); + + var runs = 0; + var wickets = 0; + var battingAverageTotal = 0.0; + var bowlingAverageTotal = 0.0; + var highestRuns = 0; + var lowestRuns = double.maxFinite.toInt(); + + for (final match in this) { + final team = _getTeam(match, teamId); + final opponentTeam = _getOpponentTeam(match, teamId); + + runs += team.run; + wickets += team.wicket; + + battingAverageTotal += + opponentTeam.wicket > 0 ? team.run / opponentTeam.wicket : 0; + if (team.wicket > 0) { + bowlingAverageTotal += opponentTeam.run / team.wicket; + } + + if (team.run > highestRuns) highestRuns = team.run; + if (team.run < lowestRuns) lowestRuns = team.run; + } + + final bowlingAverage = length > 0.0 ? bowlingAverageTotal / length : 0.0; + + return TeamStat( + played: length, + status: _teamMatchStatus(teamId), + run_rate: _runRate(teamId, runs), + runs: runs, + wickets: wickets, + batting_average: battingAverageTotal, + bowling_average: bowlingAverage, + highest_runs: highestRuns, + lowest_runs: lowestRuns == double.maxFinite.toInt() ? 0 : lowestRuns, + ); + } + + TeamMatchStatus _teamMatchStatus(String teamId) { + return fold( + const TeamMatchStatus(), + (status, match) { + final firstTeam = match.teams.firstWhere( + (team) => + team.team.id == + (match.toss_decision == TossDecision.bat + ? match.toss_winner_id + : match.teams + .firstWhere( + (team) => team.team.id != match.toss_winner_id, + ) + .team + .id), + ); + + final secondTeam = + match.teams.firstWhere((team) => team.team.id != firstTeam.team.id); + + if (firstTeam.run == secondTeam.run) { + return TeamMatchStatus( + win: status.win, + lost: status.lost, + tie: status.tie + 1, + ); + } else if ((firstTeam.run > secondTeam.run && + firstTeam.team.id == teamId) || + (firstTeam.run < secondTeam.run && secondTeam.team.id == teamId)) { + return TeamMatchStatus( + win: status.win + 1, + lost: status.lost, + tie: status.tie, + ); + } else { + return TeamMatchStatus( + win: status.win, + lost: status.lost + 1, + tie: status.tie, + ); + } + }, + ); + } + + MatchTeamModel _getTeam(MatchModel match, String teamId) => + match.teams.firstWhere((team) => team.team.id == teamId); + + MatchTeamModel _getOpponentTeam(MatchModel match, String teamId) => + match.teams.firstWhere((team) => team.team.id != teamId); + + double _runRate(String teamId, int runs) { + final totalOvers = map((match) => _getTeam(match, teamId)) + .fold(0.0, (total, team) => total + team.over); + + return totalOvers > 0 ? runs / totalOvers : 0; + } +} diff --git a/data/lib/service/tournament/tournament_service.dart b/data/lib/service/tournament/tournament_service.dart index 7e0655bf..2f66f1b7 100644 --- a/data/lib/service/tournament/tournament_service.dart +++ b/data/lib/service/tournament/tournament_service.dart @@ -141,8 +141,7 @@ class TournamentService { } } } - final keyStats = playerStatsList.getTopKeyStats() - ..sort((a, b) => b.value?.compareTo(a.value ?? 0) ?? 0); + final keyStats = playerStatsList.getTopKeyStats(); return keyStats.where((element) => element.player.isActive).toList(); } diff --git a/khelo/assets/locales/app_en.arb b/khelo/assets/locales/app_en.arb index a7f90edb..07ceeb2a 100644 --- a/khelo/assets/locales/app_en.arb +++ b/khelo/assets/locales/app_en.arb @@ -240,6 +240,14 @@ "tournament_detail_key_stat_most_fours_title": "Most Fours", "tournament_detail_key_stat_most_sixes_title": "Most Sixes", + "key_stat_filter_runs": "Runs", + "key_stat_filter_wickets": "Wickets", + "key_stat_filter_fours": "Fours", + "key_stat_filter_sixes": "Sixes", + "key_stat_filter_most_hundreds": "Most hundreds", + "key_stat_filter_most_fifties": "Most fifties", + "key_stat_filter_boundaries": "Boundaries", + "tournament_detail_points_table_points_title": "Points", "tournament_detail_points_table_empty_title": "No Points Yet!", "tournament_detail_points_table_empty_description": "The points table will be updated once matches begin. Stay tuned for the latest standings!", diff --git a/khelo/lib/ui/flow/matches/add_match/components/pitch_selection_view.dart b/khelo/lib/ui/flow/matches/add_match/components/pitch_selection_view.dart index 10e2f303..b3b60aab 100644 --- a/khelo/lib/ui/flow/matches/add_match/components/pitch_selection_view.dart +++ b/khelo/lib/ui/flow/matches/add_match/components/pitch_selection_view.dart @@ -3,9 +3,7 @@ import 'package:khelo/domain/extensions/context_extensions.dart'; import 'package:khelo/domain/extensions/enum_extensions.dart'; import 'package:khelo/ui/flow/matches/add_match/add_match_view_model.dart'; import 'package:khelo/ui/flow/matches/add_match/components/section_title.dart'; -import 'package:style/animations/on_tap_scale.dart'; -import 'package:style/extensions/context_extensions.dart'; -import 'package:style/text/app_text_style.dart'; +import 'package:style/button/chip_button.dart'; import 'package:data/api/match/match_model.dart'; class PitchSelectionView extends StatelessWidget { @@ -31,11 +29,13 @@ class PitchSelectionView extends StatelessWidget { padding: const EdgeInsets.only(left: 16, right: 8), child: Row( children: PitchType.values - .map((type) => _capsuleCell( - context: context, - title: type.getString(context), - isSelected: state.pitchType == type, - onTap: () => notifier.onPitchTypeSelection(type), + .map((type) => Padding( + padding: const EdgeInsets.only(right: 8), + child: ChipButton( + title: type.getString(context), + isSelected: state.pitchType == type, + onTap: () => notifier.onPitchTypeSelection(type), + ), )) .toList(), )), @@ -43,35 +43,4 @@ class PitchSelectionView extends StatelessWidget { ), ); } - - Widget _capsuleCell({ - required BuildContext context, - required String title, - required bool isSelected, - required VoidCallback onTap, - }) { - return Padding( - padding: const EdgeInsets.only(right: 8), - child: OnTapScale( - onTap: () => onTap(), - child: Chip( - label: Text( - title, - style: AppTextStyle.body2.copyWith( - color: isSelected - ? context.colorScheme.onPrimary - : context.colorScheme.textDisabled), - ), - backgroundColor: isSelected - ? context.colorScheme.primary - : context.colorScheme.containerLowOnSurface, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - side: const BorderSide(color: Colors.transparent), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(30), - ), - ), - ), - ); - } } diff --git a/khelo/lib/ui/flow/score_board/components/select_wicket_type_sheet.dart b/khelo/lib/ui/flow/score_board/components/select_wicket_type_sheet.dart index 63800e56..3c5aa90d 100644 --- a/khelo/lib/ui/flow/score_board/components/select_wicket_type_sheet.dart +++ b/khelo/lib/ui/flow/score_board/components/select_wicket_type_sheet.dart @@ -7,10 +7,9 @@ import 'package:khelo/domain/extensions/context_extensions.dart'; import 'package:khelo/domain/extensions/enum_extensions.dart'; import 'package:khelo/ui/flow/score_board/components/bottom_sheet_wrapper.dart'; import 'package:khelo/ui/flow/score_board/score_board_view_model.dart'; -import 'package:style/animations/on_tap_scale.dart'; +import 'package:style/button/chip_button.dart'; import 'package:style/button/primary_button.dart'; import 'package:style/extensions/context_extensions.dart'; -import 'package:style/text/app_text_style.dart'; class SelectWicketTypeSheet extends ConsumerStatefulWidget { static Future show(BuildContext context) { @@ -64,26 +63,10 @@ class _SelectWicketTypeSheetState extends ConsumerState { children: WicketType.values.map( (element) { final isSelected = selectedType == element; - return OnTapScale( + return ChipButton( + isSelected: isSelected, + title: element.getString(context), onTap: () => setState(() => selectedType = element), - child: Chip( - label: Text( - element.getString(context), - style: AppTextStyle.body2.copyWith( - color: isSelected - ? context.colorScheme.onPrimary - : context.colorScheme.textSecondary, - ), - ), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - side: const BorderSide(color: Colors.transparent), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(30), - ), - backgroundColor: isSelected - ? context.colorScheme.primary - : context.colorScheme.containerLowOnSurface, - ), ); }, ).toList(), diff --git a/khelo/lib/ui/flow/team/detail/team_detail_view_model.dart b/khelo/lib/ui/flow/team/detail/team_detail_view_model.dart index f73c53cd..affed5a0 100644 --- a/khelo/lib/ui/flow/team/detail/team_detail_view_model.dart +++ b/khelo/lib/ui/flow/team/detail/team_detail_view_model.dart @@ -58,126 +58,10 @@ class TeamDetailViewNotifier extends StateNotifier { } TeamStat _calculateTeamStat(String teamId, List matches) { - final finishedMatches = _filterFinishedMatches(matches); - if (finishedMatches.isEmpty) return const TeamStat(); - final totalRuns = _totalRuns(teamId, finishedMatches); - return TeamStat( - played: finishedMatches.length, - status: _teamMatchStatus(teamId, finishedMatches), - runs: totalRuns, - wickets: _wickets(teamId, finishedMatches), - batting_average: _battingAverage(teamId, finishedMatches), - bowling_average: _bowlingAverage(teamId, finishedMatches), - highest_runs: _highestAndLowestRuns(teamId, finishedMatches).$1, - lowest_runs: _highestAndLowestRuns(teamId, finishedMatches).$2, - run_rate: _runRate(teamId, finishedMatches, totalRuns), - ); - } - - List _filterFinishedMatches(List matches) { - return matches + final finishedMatches = matches .where((match) => match.match_status == MatchStatus.finish) .toList(); - } - - int _totalRuns(String teamId, List finishedMatches) { - return finishedMatches - .map((match) => _getTeam(match, teamId)) - .fold(0, (totalRuns, team) => totalRuns + team.run); - } - - int _wickets(String teamId, List finishedMatches) { - return finishedMatches - .map((match) => _getTeam(match, teamId)) - .fold(0, (totalWickets, team) => totalWickets + team.wicket); - } - - double _battingAverage(String teamId, List finishedMatches) { - return finishedMatches.fold( - 0, - (total, match) { - final team = _getTeam(match, teamId); - final opponentTeam = _getOpponentTeam(match, teamId); - - return total + - (opponentTeam.wicket > 0 ? team.run / opponentTeam.wicket : 0); - }, - ); - } - - MatchTeamModel _getTeam(MatchModel match, String teamId) => - match.teams.firstWhere((team) => team.team.id == teamId); - - MatchTeamModel _getOpponentTeam(MatchModel match, String teamId) => - match.teams.firstWhere((team) => team.team.id != teamId); - - double _bowlingAverage(String teamId, List finishedMatches) { - return finishedMatches.fold( - 0, - (total, match) { - final team = _getTeam(match, teamId); - final opponentTeam = _getOpponentTeam(match, teamId); - - return total + - (team.wicket > 0 ? opponentTeam.run / team.wicket : 0); - }, - ) / - finishedMatches.length; - } - - (int, int) _highestAndLowestRuns( - String teamId, List finishedMatches) { - final firstTeamRuns = - finishedMatches.map((match) => _getTeam(match, teamId).run).toList(); - if (firstTeamRuns.isEmpty) { - return (0, 0); - } - final highestRuns = firstTeamRuns - .reduce((value, element) => element > value ? element : value); - final lowestRuns = firstTeamRuns - .reduce((value, element) => element < value ? element : value); - return (highestRuns, lowestRuns); - } - - double _runRate(String teamId, List finishedMatches, int runs) { - final totalOvers = finishedMatches - .map((match) => _getTeam(match, teamId)) - .fold(0.0, (total, team) => total + team.over); - - return totalOvers > 0 ? runs / totalOvers : 0; - } - - TeamMatchStatus _teamMatchStatus( - String teamId, List finishedMatches) { - return finishedMatches.fold( - const TeamMatchStatus(), - (status, match) { - final firstTeam = match.teams.firstWhere((team) => - team.team.id == - (match.toss_decision == TossDecision.bat - ? match.toss_winner_id - : match.teams - .firstWhere((team) => team.team.id != match.toss_winner_id) - .team - .id)); - - final secondTeam = - match.teams.firstWhere((team) => team.team.id != firstTeam.team.id); - - if (firstTeam.run == secondTeam.run) { - return TeamMatchStatus( - win: status.win, lost: status.lost, tie: status.tie + 1); - } else if ((firstTeam.run > secondTeam.run && - firstTeam.team.id == teamId) || - (firstTeam.run < secondTeam.run && secondTeam.team.id == teamId)) { - return TeamMatchStatus( - win: status.win + 1, lost: status.lost, tie: status.tie); - } else { - return TeamMatchStatus( - win: status.win, lost: status.lost + 1, tie: status.tie); - } - }, - ); + return finishedMatches.teamStat(teamId); } void onTabChange(int tab) { diff --git a/khelo/lib/ui/flow/tournament/detail/tabs/tournament_detail_overview_tab.dart b/khelo/lib/ui/flow/tournament/detail/tabs/tournament_detail_overview_tab.dart index 0dab57e4..b2e09cfc 100644 --- a/khelo/lib/ui/flow/tournament/detail/tabs/tournament_detail_overview_tab.dart +++ b/khelo/lib/ui/flow/tournament/detail/tabs/tournament_detail_overview_tab.dart @@ -150,6 +150,9 @@ class _TournamentDetailOverviewTabState Widget _keyStatsView(BuildContext context, List keyStats) { if (keyStats.isEmpty) return SizedBox(); + final keyStatsList = List.of(keyStats) + ..sort((a, b) => b.value?.compareTo(a.value ?? 0) ?? 0); + return Padding( padding: const EdgeInsets.only(top: 24), child: Column( @@ -157,7 +160,7 @@ class _TournamentDetailOverviewTabState children: [ _header( context, - showViewAll: keyStats.length > 4, + showViewAll: keyStatsList.length > 4, title: context.l10n.tournament_detail_overview_key_stats_title, onViewAll: () {}, ), @@ -165,7 +168,7 @@ class _TournamentDetailOverviewTabState GridView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), - itemCount: keyStats.take(4).length, + itemCount: keyStatsList.take(4).length, padding: EdgeInsets.zero, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, @@ -174,7 +177,7 @@ class _TournamentDetailOverviewTabState mainAxisExtent: 115, ), itemBuilder: (context, index) => - _keyStatsCellView(context, keyStats[index]), + _keyStatsCellView(context, keyStatsList[index]), ) ], ), diff --git a/khelo/lib/ui/flow/tournament/detail/tabs/tournament_detail_stats_tab.dart b/khelo/lib/ui/flow/tournament/detail/tabs/tournament_detail_stats_tab.dart index 54a3b340..28ed3521 100644 --- a/khelo/lib/ui/flow/tournament/detail/tabs/tournament_detail_stats_tab.dart +++ b/khelo/lib/ui/flow/tournament/detail/tabs/tournament_detail_stats_tab.dart @@ -2,21 +2,22 @@ import 'package:data/api/match/match_model.dart'; import 'package:data/api/tournament/tournament_model.dart'; import 'package:data/api/user/user_models.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:khelo/domain/extensions/context_extensions.dart'; import 'package:khelo/domain/extensions/enum_extensions.dart'; +import 'package:style/button/chip_button.dart'; import 'package:style/extensions/context_extensions.dart'; import 'package:style/text/app_text_style.dart'; -import '../../../../../components/action_bottom_sheet.dart'; import '../../../../../components/empty_screen.dart'; import '../../../../../components/image_avatar.dart'; import '../components/filter_tab_view.dart'; import '../tournament_detail_view_model.dart'; class TournamentDetailStatsTab extends ConsumerWidget { - final Function(KeyStatTag) onFiltered; + final Function(KeyStatFilterTag) onFiltered; const TournamentDetailStatsTab({ super.key, @@ -43,10 +44,10 @@ class TournamentDetailStatsTab extends ConsumerWidget { title: context.l10n.tournament_detail_stats_tab, onFilter: () => showFilterOptionSelectionSheet( context, - keyStatFilter: state.statFilter, + selectedTag: state.selectedFilterTag, onTap: onFiltered, ), - filterValue: state.statFilter.getString(context), + filterValue: state.selectedFilterTag.getString(context), ), const SizedBox(height: 16), if (state.filteredStats.isNotEmpty) ...[ @@ -195,21 +196,41 @@ class TournamentDetailStatsTab extends ConsumerWidget { void showFilterOptionSelectionSheet( BuildContext context, { - required Function(KeyStatTag) onTap, - KeyStatTag? keyStatFilter, + required Function(KeyStatFilterTag) onTap, + KeyStatFilterTag? selectedTag, }) async { - return await showActionBottomSheet( - context: context, - items: KeyStatTag.values - .map((option) => BottomSheetAction( - title: option.getString(context), - enabled: keyStatFilter != option, - showCheck: keyStatFilter == option, + HapticFeedback.mediumImpact(); + return await showModalBottomSheet( + context: context, + showDragHandle: true, + enableDrag: true, + isScrollControlled: true, + useRootNavigator: true, + backgroundColor: context.colorScheme.surface, + builder: (context) { + return Container( + width: double.infinity, + padding: EdgeInsets.all(16) + .copyWith(bottom: context.mediaQueryPadding.bottom + 24), + child: Wrap( + alignment: WrapAlignment.start, + spacing: 8, + runSpacing: 8, + children: KeyStatFilterTag.values.map( + (element) { + return ChipButton( + title: element.getString(context), + isSelected: selectedTag == element, onTap: () { context.pop(); - onTap(option); + onTap(element); }, - )) - .toList()); + ); + }, + ).toList(), + ), + ); + }, + ); } } diff --git a/khelo/lib/ui/flow/tournament/detail/tournament_detail_view_model.dart b/khelo/lib/ui/flow/tournament/detail/tournament_detail_view_model.dart index c2a26422..8d213319 100644 --- a/khelo/lib/ui/flow/tournament/detail/tournament_detail_view_model.dart +++ b/khelo/lib/ui/flow/tournament/detail/tournament_detail_view_model.dart @@ -8,6 +8,7 @@ import 'package:data/storage/app_preferences.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:khelo/domain/extensions/context_extensions.dart'; part 'tournament_detail_view_model.freezed.dart'; @@ -115,20 +116,76 @@ class TournamentDetailStateViewNotifier } } - void onStatFilter(KeyStatTag? tag) { + void onStatFilter(KeyStatFilterTag? tag) { if (state.tournament == null) return; - final filteredStats = state.tournament!.keyStats - .where((element) => element.tag == (tag ?? state.statFilter)) - .toList(); + var filteredStats = state.tournament!.keyStats; + + filteredStats = filteredStats.where((e) { + switch (tag) { + case KeyStatFilterTag.runs: + return (e.stats.battingStat?.runScored ?? 0) > 0; + case KeyStatFilterTag.wickets: + return (e.stats.bowlingStat?.wicketTaken ?? 0.0) > 0.0; + case KeyStatFilterTag.battingAverage: + return (e.stats.battingStat?.average ?? 0.0) > 0.0; + case KeyStatFilterTag.bowlingAverage: + return (e.stats.bowlingStat?.average ?? 0.0) > 0.0; + case KeyStatFilterTag.mostHundreds: + return (e.stats.battingStat?.hundreds ?? 0) > 0; + case KeyStatFilterTag.mostFifties: + return (e.stats.battingStat?.fifties ?? 0) > 0; + case KeyStatFilterTag.sixes: + return (e.stats.battingStat?.sixes ?? 0) > 0; + case KeyStatFilterTag.fours: + return (e.stats.battingStat?.fours ?? 0) > 0; + case KeyStatFilterTag.boundaries: + return (e.stats.battingStat?.fours ?? 0) + + (e.stats.battingStat?.sixes ?? 0) > + 0; + case null: + return false; + } + }).toList(); + + if (tag == KeyStatFilterTag.mostHundreds || + tag == KeyStatFilterTag.mostFifties || + tag == KeyStatFilterTag.boundaries) { + filteredStats.sort((a, b) { + int compareByTag(PlayerKeyStat x, PlayerKeyStat y) { + switch (tag) { + case KeyStatFilterTag.mostHundreds: + return (y.stats.battingStat?.hundreds ?? 0) + .compareTo(x.stats.battingStat?.hundreds ?? 0); + case KeyStatFilterTag.mostFifties: + return (y.stats.battingStat?.fifties ?? 0) + .compareTo(x.stats.battingStat?.fifties ?? 0); + case KeyStatFilterTag.boundaries: + return ((y.stats.battingStat?.fours ?? 0) + + (y.stats.battingStat?.sixes ?? 0)) + .compareTo((x.stats.battingStat?.fours ?? 0) + + (x.stats.battingStat?.sixes ?? 0)); + default: + return 0; + } + } + + return compareByTag(a, b); + }); + } + state = state.copyWith( - filteredStats: filteredStats, statFilter: tag ?? state.statFilter); + filteredStats: filteredStats, + selectedFilterTag: tag ?? state.selectedFilterTag, + ); } List _calculatePointsTable(TournamentModel tournament) { List teamPoints = []; - final finishedMatches = _filterFinishedMatches(tournament.matches); + final finishedMatches = tournament.matches + .where((match) => match.match_status == MatchStatus.finish) + .toList(); if (finishedMatches.isEmpty) return []; @@ -136,7 +193,7 @@ class TournamentDetailStateViewNotifier final matches = finishedMatches .where((element) => element.team_ids.contains(team.id)) .toList(); - final teamStat = _teamStat(team.id, matches); + final teamStat = matches.teamStat(team.id); //If team has won then add 2 points and tie then add 1 point final points = teamStat.status.win * 2 + teamStat.status.tie; teamPoints.add(TeamPoint( @@ -149,69 +206,6 @@ class TournamentDetailStateViewNotifier return teamPoints..sort((a, b) => b.points.compareTo(a.points)); } - TeamStat _teamStat(String teamId, List matches) { - if (matches.isEmpty) return const TeamStat(); - return TeamStat( - played: matches.length, - status: _teamMatchStatus(teamId, matches), - run_rate: _runRate(teamId, matches), - ); - } - - List _filterFinishedMatches(List matches) { - return matches - .where((match) => match.match_status == MatchStatus.finish) - .toList(); - } - - double _runRate(String teamId, List finishedMatches) { - final runs = finishedMatches - .map((match) => _getTeam(match, teamId)) - .fold(0, (totalRuns, team) => totalRuns + team.run); - - final totalOvers = finishedMatches - .map((match) => _getTeam(match, teamId)) - .fold(0.0, (total, team) => total + team.over); - - return totalOvers > 0 ? runs / totalOvers : 0; - } - - MatchTeamModel _getTeam(MatchModel match, String teamId) => - match.teams.firstWhere((team) => team.team.id == teamId); - - TeamMatchStatus _teamMatchStatus( - String teamId, List finishedMatches) { - return finishedMatches.fold( - const TeamMatchStatus(), - (status, match) { - final firstTeam = match.teams.firstWhere((team) => - team.team.id == - (match.toss_decision == TossDecision.bat - ? match.toss_winner_id - : match.teams - .firstWhere((team) => team.team.id != match.toss_winner_id) - .team - .id)); - - final secondTeam = - match.teams.firstWhere((team) => team.team.id != firstTeam.team.id); - - if (firstTeam.run == secondTeam.run) { - return TeamMatchStatus( - win: status.win, lost: status.lost, tie: status.tie + 1); - } else if ((firstTeam.run > secondTeam.run && - firstTeam.team.id == teamId) || - (firstTeam.run < secondTeam.run && secondTeam.team.id == teamId)) { - return TeamMatchStatus( - win: status.win + 1, lost: status.lost, tie: status.tie); - } else { - return TeamMatchStatus( - win: status.win, lost: status.lost + 1, tie: status.tie); - } - }, - ); - } - @override void dispose() { _tournamentSubscription?.cancel(); @@ -230,8 +224,43 @@ class TournamentDetailState with _$TournamentDetailState { String? currentUserId, @Default(null) String? matchFilter, @Default([]) List filteredMatches, - @Default(KeyStatTag.mostRuns) KeyStatTag statFilter, + @Default(KeyStatFilterTag.runs) KeyStatFilterTag selectedFilterTag, @Default([]) List filteredStats, @Default([]) List teamPoints, }) = _TournamentDetailState; } + +enum KeyStatFilterTag { + runs, + wickets, + battingAverage, + bowlingAverage, + mostHundreds, + mostFifties, + sixes, + fours, + boundaries; + + String getString(BuildContext context) { + switch (this) { + case KeyStatFilterTag.runs: + return context.l10n.key_stat_filter_runs; + case KeyStatFilterTag.wickets: + return context.l10n.key_stat_filter_wickets; + case KeyStatFilterTag.battingAverage: + return context.l10n.common_batting_average_title; + case KeyStatFilterTag.bowlingAverage: + return context.l10n.common_bowling_average_title; + case KeyStatFilterTag.mostHundreds: + return context.l10n.key_stat_filter_most_hundreds; + case KeyStatFilterTag.mostFifties: + return context.l10n.key_stat_filter_most_fifties; + case KeyStatFilterTag.sixes: + return context.l10n.key_stat_filter_sixes; + case KeyStatFilterTag.fours: + return context.l10n.key_stat_filter_fours; + case KeyStatFilterTag.boundaries: + return context.l10n.key_stat_filter_boundaries; + } + } +} diff --git a/khelo/lib/ui/flow/tournament/detail/tournament_detail_view_model.freezed.dart b/khelo/lib/ui/flow/tournament/detail/tournament_detail_view_model.freezed.dart index 3a1c20f0..14c71a7e 100644 --- a/khelo/lib/ui/flow/tournament/detail/tournament_detail_view_model.freezed.dart +++ b/khelo/lib/ui/flow/tournament/detail/tournament_detail_view_model.freezed.dart @@ -24,7 +24,7 @@ mixin _$TournamentDetailState { String? get currentUserId => throw _privateConstructorUsedError; String? get matchFilter => throw _privateConstructorUsedError; List get filteredMatches => throw _privateConstructorUsedError; - KeyStatTag get statFilter => throw _privateConstructorUsedError; + KeyStatFilterTag get selectedFilterTag => throw _privateConstructorUsedError; List get filteredStats => throw _privateConstructorUsedError; List get teamPoints => throw _privateConstructorUsedError; @@ -50,7 +50,7 @@ abstract class $TournamentDetailStateCopyWith<$Res> { String? currentUserId, String? matchFilter, List filteredMatches, - KeyStatTag statFilter, + KeyStatFilterTag selectedFilterTag, List filteredStats, List teamPoints}); @@ -81,7 +81,7 @@ class _$TournamentDetailStateCopyWithImpl<$Res, Object? currentUserId = freezed, Object? matchFilter = freezed, Object? filteredMatches = null, - Object? statFilter = null, + Object? selectedFilterTag = null, Object? filteredStats = null, Object? teamPoints = null, }) { @@ -112,10 +112,10 @@ class _$TournamentDetailStateCopyWithImpl<$Res, ? _value.filteredMatches : filteredMatches // ignore: cast_nullable_to_non_nullable as List, - statFilter: null == statFilter - ? _value.statFilter - : statFilter // ignore: cast_nullable_to_non_nullable - as KeyStatTag, + selectedFilterTag: null == selectedFilterTag + ? _value.selectedFilterTag + : selectedFilterTag // ignore: cast_nullable_to_non_nullable + as KeyStatFilterTag, filteredStats: null == filteredStats ? _value.filteredStats : filteredStats // ignore: cast_nullable_to_non_nullable @@ -160,7 +160,7 @@ abstract class _$$TournamentDetailStateImplCopyWith<$Res> String? currentUserId, String? matchFilter, List filteredMatches, - KeyStatTag statFilter, + KeyStatFilterTag selectedFilterTag, List filteredStats, List teamPoints}); @@ -190,7 +190,7 @@ class __$$TournamentDetailStateImplCopyWithImpl<$Res> Object? currentUserId = freezed, Object? matchFilter = freezed, Object? filteredMatches = null, - Object? statFilter = null, + Object? selectedFilterTag = null, Object? filteredStats = null, Object? teamPoints = null, }) { @@ -221,10 +221,10 @@ class __$$TournamentDetailStateImplCopyWithImpl<$Res> ? _value._filteredMatches : filteredMatches // ignore: cast_nullable_to_non_nullable as List, - statFilter: null == statFilter - ? _value.statFilter - : statFilter // ignore: cast_nullable_to_non_nullable - as KeyStatTag, + selectedFilterTag: null == selectedFilterTag + ? _value.selectedFilterTag + : selectedFilterTag // ignore: cast_nullable_to_non_nullable + as KeyStatFilterTag, filteredStats: null == filteredStats ? _value._filteredStats : filteredStats // ignore: cast_nullable_to_non_nullable @@ -249,7 +249,7 @@ class _$TournamentDetailStateImpl implements _TournamentDetailState { this.currentUserId, this.matchFilter = null, final List filteredMatches = const [], - this.statFilter = KeyStatTag.mostRuns, + this.selectedFilterTag = KeyStatFilterTag.runs, final List filteredStats = const [], final List teamPoints = const []}) : _filteredMatches = filteredMatches, @@ -285,7 +285,7 @@ class _$TournamentDetailStateImpl implements _TournamentDetailState { @override @JsonKey() - final KeyStatTag statFilter; + final KeyStatFilterTag selectedFilterTag; final List _filteredStats; @override @JsonKey() @@ -306,7 +306,7 @@ class _$TournamentDetailStateImpl implements _TournamentDetailState { @override String toString() { - return 'TournamentDetailState(tournament: $tournament, loading: $loading, selectedTab: $selectedTab, error: $error, actionError: $actionError, currentUserId: $currentUserId, matchFilter: $matchFilter, filteredMatches: $filteredMatches, statFilter: $statFilter, filteredStats: $filteredStats, teamPoints: $teamPoints)'; + return 'TournamentDetailState(tournament: $tournament, loading: $loading, selectedTab: $selectedTab, error: $error, actionError: $actionError, currentUserId: $currentUserId, matchFilter: $matchFilter, filteredMatches: $filteredMatches, selectedFilterTag: $selectedFilterTag, filteredStats: $filteredStats, teamPoints: $teamPoints)'; } @override @@ -328,8 +328,8 @@ class _$TournamentDetailStateImpl implements _TournamentDetailState { other.matchFilter == matchFilter) && const DeepCollectionEquality() .equals(other._filteredMatches, _filteredMatches) && - (identical(other.statFilter, statFilter) || - other.statFilter == statFilter) && + (identical(other.selectedFilterTag, selectedFilterTag) || + other.selectedFilterTag == selectedFilterTag) && const DeepCollectionEquality() .equals(other._filteredStats, _filteredStats) && const DeepCollectionEquality() @@ -347,7 +347,7 @@ class _$TournamentDetailStateImpl implements _TournamentDetailState { currentUserId, matchFilter, const DeepCollectionEquality().hash(_filteredMatches), - statFilter, + selectedFilterTag, const DeepCollectionEquality().hash(_filteredStats), const DeepCollectionEquality().hash(_teamPoints)); @@ -371,7 +371,7 @@ abstract class _TournamentDetailState implements TournamentDetailState { final String? currentUserId, final String? matchFilter, final List filteredMatches, - final KeyStatTag statFilter, + final KeyStatFilterTag selectedFilterTag, final List filteredStats, final List teamPoints}) = _$TournamentDetailStateImpl; @@ -392,7 +392,7 @@ abstract class _TournamentDetailState implements TournamentDetailState { @override List get filteredMatches; @override - KeyStatTag get statFilter; + KeyStatFilterTag get selectedFilterTag; @override List get filteredStats; @override diff --git a/style/lib/button/chip_button.dart b/style/lib/button/chip_button.dart new file mode 100644 index 00000000..18d619b0 --- /dev/null +++ b/style/lib/button/chip_button.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:style/extensions/context_extensions.dart'; + +import '../animations/on_tap_scale.dart'; +import '../text/app_text_style.dart'; + +class ChipButton extends StatelessWidget { + final bool isSelected; + final String title; + final VoidCallback? onTap; + + const ChipButton({ + super.key, + this.isSelected = false, + required this.title, + this.onTap, + }); + + @override + Widget build(BuildContext context) { + return OnTapScale( + onTap: onTap, + child: Chip( + label: Text( + title, + style: AppTextStyle.body2.copyWith( + color: isSelected + ? context.colorScheme.onPrimary + : context.colorScheme.textSecondary, + ), + ), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + side: const BorderSide(color: Colors.transparent), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(30), + ), + backgroundColor: isSelected + ? context.colorScheme.primary + : context.colorScheme.containerLowOnSurface, + ), + ); + } +}