diff --git a/README.md b/README.md index 839039c5..d40156f8 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Khelo is an open-source Flutter project written in Dart using Firestore database ## Download App - + ## Screenshots diff --git a/data/lib/api/match/match_model.dart b/data/lib/api/match/match_model.dart index dc2f831f..d0fa99da 100644 --- a/data/lib/api/match/match_model.dart +++ b/data/lib/api/match/match_model.dart @@ -165,7 +165,8 @@ enum PitchType { enum MatchStatus { yetToStart(1), running(2), - finish(3); + finish(3), + abandoned(4); final int value; diff --git a/data/lib/api/match/match_model.g.dart b/data/lib/api/match/match_model.g.dart index 8dd50792..48e31f00 100644 --- a/data/lib/api/match/match_model.g.dart +++ b/data/lib/api/match/match_model.g.dart @@ -102,6 +102,7 @@ const _$MatchStatusEnumMap = { MatchStatus.yetToStart: 1, MatchStatus.running: 2, MatchStatus.finish: 3, + MatchStatus.abandoned: 4, }; const _$TossDecisionEnumMap = { diff --git a/khelo/assets/locales/app_en.arb b/khelo/assets/locales/app_en.arb index 94862381..38d84bdc 100644 --- a/khelo/assets/locales/app_en.arb +++ b/khelo/assets/locales/app_en.arb @@ -290,6 +290,7 @@ } } }, + "score_board_end_of_match_title": "End Match", "score_board_choose_fielder_title": "choose Fielder", "score_board_injured_tag_title": "Injured", "score_board_who_on_strike_title": "Who's on Strike?", @@ -310,6 +311,8 @@ "score_board_pause_title": "Pause", "score_board_more_options_title": "More Options", "score_board_pause_scoring_description_text": "are you sure you want to pause scoring?", + "score_board_end_match_title": "End Match", + "score_board_end_match_description_text": "are you sure you want to end match?", "score_board_need_run_text": "Need {run} in {ball}", "@score_board_need_run_text": { "description": "Need {run} in {ball}", @@ -347,6 +350,7 @@ "match_status_yet_to_start_title": "Yet to start", "match_status_running_title": "Running", "match_status_finish_title": "Finish", + "match_status_abandoned_title": "Abandoned", "wicket_type_bowled_title": "Bowled", "wicket_type_caught_title": "Caught", diff --git a/khelo/lib/domain/extensions/enum_extensions.dart b/khelo/lib/domain/extensions/enum_extensions.dart index c382b3f0..0cf4a05d 100644 --- a/khelo/lib/domain/extensions/enum_extensions.dart +++ b/khelo/lib/domain/extensions/enum_extensions.dart @@ -149,6 +149,8 @@ extension MatchStatusString on MatchStatus { return context.l10n.match_status_running_title; case MatchStatus.finish: return context.l10n.match_status_finish_title; + case MatchStatus.abandoned: + return context.l10n.match_status_abandoned_title; } } @@ -160,6 +162,8 @@ extension MatchStatusString on MatchStatus { return context.colorScheme.alert; case MatchStatus.finish: return context.colorScheme.positive; + case MatchStatus.abandoned: + return context.colorScheme.secondary; } } } diff --git a/khelo/lib/ui/flow/score_board/components/add_penalty_run_dialog.dart b/khelo/lib/ui/flow/score_board/components/add_penalty_run_dialog.dart index 2459f0b5..0a5b5d5e 100644 --- a/khelo/lib/ui/flow/score_board/components/add_penalty_run_dialog.dart +++ b/khelo/lib/ui/flow/score_board/components/add_penalty_run_dialog.dart @@ -16,7 +16,7 @@ class AddPenaltyRunDialog extends ConsumerStatefulWidget { BuildContext context, ) { return showDialog( - barrierDismissible: false, + barrierDismissible: true, context: context, builder: (context) { return const AddPenaltyRunDialog(); @@ -39,27 +39,31 @@ class _AddPenaltyRunDialogState extends ConsumerState { @override Widget build(BuildContext context) { final state = ref.watch(scoreBoardStateProvider); - return AlertDialog( - backgroundColor: context.colorScheme.containerLowOnSurface, - title: Text( - context.l10n.score_board_penalty_run_title, - style: AppTextStyle.subtitle1 - .copyWith(color: context.colorScheme.textPrimary), - ), - content: _addPenaltyContent(context, state), - actionsAlignment: MainAxisAlignment.spaceAround, - actions: [ - PrimaryButton( - context.l10n.common_okay_title, - enabled: isButtonEnable, - onPressed: () { - context.pop(( - teamId: selectedTeamId, - runs: int.parse(runController.text), - )); - }, + return Material( + type: MaterialType.transparency, + color: Colors.transparent, + child: AlertDialog.adaptive( + backgroundColor: context.colorScheme.containerLowOnSurface, + title: Text( + context.l10n.score_board_penalty_run_title, + style: AppTextStyle.subtitle1 + .copyWith(color: context.colorScheme.textPrimary), ), - ], + content: _addPenaltyContent(context, state), + actionsAlignment: MainAxisAlignment.spaceAround, + actions: [ + PrimaryButton( + context.l10n.common_okay_title, + enabled: isButtonEnable, + onPressed: () { + context.pop(( + teamId: selectedTeamId, + runs: int.parse(runController.text), + )); + }, + ), + ], + ), ); } diff --git a/khelo/lib/ui/flow/score_board/components/score_display_view.dart b/khelo/lib/ui/flow/score_board/components/score_display_view.dart index 70fd446f..c505471d 100644 --- a/khelo/lib/ui/flow/score_board/components/score_display_view.dart +++ b/khelo/lib/ui/flow/score_board/components/score_display_view.dart @@ -18,6 +18,10 @@ class ScoreDisplayView extends ConsumerWidget { return Expanded( child: ListView( children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: _teamName(context, state, true), + ), _matchScoreView(context, state), const SizedBox( height: 24, @@ -29,6 +33,28 @@ class ScoreDisplayView extends ConsumerWidget { ); } + Widget _teamName( + BuildContext context, ScoreBoardViewState state, bool batting) { + final String? battingTeam = state.match?.teams + .firstWhere( + (element) => element.team.id == state.currentInning?.team_id) + .team + .name; + final String? bowlingTeam = state.match?.teams + .firstWhere((element) => element.team.id == state.otherInning?.team_id) + .team + .name; + + return Text( + (batting ? battingTeam : bowlingTeam) ?? "", + textAlign: TextAlign.center, + style: AppTextStyle.header1.copyWith( + color: batting + ? context.colorScheme.primary + : context.colorScheme.textInversePrimary), + ); + } + Widget _matchScoreView( BuildContext context, ScoreBoardViewState state, @@ -223,6 +249,10 @@ class ScoreDisplayView extends ConsumerWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + _teamName(context, state, false), + const SizedBox( + height: 8, + ), _bowlerNameView( context, state.bowler?.player.name ?? @@ -241,10 +271,11 @@ class ScoreDisplayView extends ConsumerWidget { TextSpan( children: [ WidgetSpan( + alignment: PlaceholderAlignment.middle, child: Icon( - Icons.sports_baseball_outlined, - color: context.colorScheme.surface, - )), + Icons.sports_baseball_outlined, + color: context.colorScheme.surface, + )), TextSpan( text: ' $name', style: TextStyle( diff --git a/khelo/lib/ui/flow/score_board/score_board_screen.dart b/khelo/lib/ui/flow/score_board/score_board_screen.dart index 2e94f9ed..ab47e311 100644 --- a/khelo/lib/ui/flow/score_board/score_board_screen.dart +++ b/khelo/lib/ui/flow/score_board/score_board_screen.dart @@ -22,7 +22,6 @@ import 'package:khelo/ui/flow/score_board/components/select_wicket_taker_sheet.d import 'package:khelo/ui/flow/score_board/components/select_wicket_type_sheet.dart'; import 'package:khelo/ui/flow/score_board/components/striker_selection_dialog.dart'; import 'package:khelo/ui/flow/score_board/score_board_view_model.dart'; -import 'package:style/extensions/context_extensions.dart'; import 'package:style/indicator/progress_indicator.dart'; import 'components/inning_complete_dialog.dart'; @@ -285,6 +284,22 @@ class _ScoreBoardScreenState extends ConsumerState { }); } + void _observeEndMatchDialogue(BuildContext context, WidgetRef ref) { + ref.listen( + scoreBoardStateProvider.select( + (value) => value.showEndMatchDialog), (previous, next) { + if (next != null) { + ConfirmActionDialog.show( + context, + title: context.l10n.score_board_end_match_title, + description: context.l10n.score_board_end_match_description_text, + primaryButtonText: context.l10n.common_okay_title, + onConfirmation:notifier.abandonMatch, + ); + } + }); + } + void _observeInvalidUndoToast(BuildContext context, WidgetRef ref) { ref.listen( scoreBoardStateProvider.select((value) => value.invalidUndoToast), @@ -334,6 +349,7 @@ class _ScoreBoardScreenState extends ConsumerState { _observePop(context, ref); _observeShowPauseScoringDialog(context, ref); _observeShowAddPenaltyRunDialog(context, ref); + _observeEndMatchDialogue(context, ref); _observeInvalidUndoToast(context, ref); return PopScope( @@ -343,7 +359,7 @@ class _ScoreBoardScreenState extends ConsumerState { actions: [_moreOptionButton(context, notifier, state)], automaticallyImplyLeading: false, body: Padding( - padding: context.mediaQueryPadding, + padding: const EdgeInsets.symmetric(vertical: 16), child: _body(context, notifier, state), ), ), diff --git a/khelo/lib/ui/flow/score_board/score_board_view_model.dart b/khelo/lib/ui/flow/score_board/score_board_view_model.dart index 8516efd1..d2f83b8a 100644 --- a/khelo/lib/ui/flow/score_board/score_board_view_model.dart +++ b/khelo/lib/ui/flow/score_board/score_board_view_model.dart @@ -264,6 +264,8 @@ class ScoreBoardViewNotifier extends StateNotifier { state = state.copyWith(showPauseScoringDialog: DateTime.now()); case MatchOption.penaltyRun: state = state.copyWith(showAddPenaltyRunDialog: DateTime.now()); + case MatchOption.endMatch: + state = state.copyWith(showEndMatchDialog: DateTime.now()); default: return; } @@ -776,11 +778,22 @@ class ScoreBoardViewNotifier extends StateNotifier { showSelectPlayerSheet: DateTime.now()); } - Future endMatch() async { + Future abandonMatch() async { + await _updateInningAndTeamScore(); + state = state.copyWith(pop: true); + } + + Future endMatch({bool isComplete = true}) async { + List batsMan = []; if (state.batsMans?.isNotEmpty ?? false) { - var batsMan = state.batsMans! - .map((e) => e.copyWith(status: PlayerStatus.played)) - .toList(); + if (isComplete) { + batsMan = state.batsMans! + .map((e) => e.copyWith(status: PlayerStatus.played)) + .toList(); + } else { + batsMan = state.batsMans!; + } + await _updateMatchPlayerStatus(( teamId: state.currentInning?.team_id ?? "INVALID ID", players: batsMan @@ -856,7 +869,9 @@ class ScoreBoardViewNotifier extends StateNotifier { int batsManIndex = state.lastAssignedIndex + 1; if (statusUpdatedSquad.elementAt(index).index == null || - statusUpdatedSquad.elementAt(index).index == 0) { + statusUpdatedSquad.elementAt(index).index == 0 || + statusUpdatedSquad.elementAt(index).status == + PlayerStatus.injured) { statusUpdatedSquad[index] = statusUpdatedSquad .elementAt(index) .copyWith(index: batsManIndex, status: PlayerStatus.playing); @@ -879,7 +894,12 @@ class ScoreBoardViewNotifier extends StateNotifier { if (!(state.batsMans?.map((e) => e.player.id).contains(state.strikerId) ?? false)) { - _showStrikerSelectionDialog(); + if (batsMen != null && batsMen.length == 1) { + setOrSwitchStriker(batsMan: batsMen.first.player); + return; + } else { + _showStrikerSelectionDialog(); + } } } } @@ -912,6 +932,7 @@ class ScoreBoardViewState with _$ScoreBoardViewState { DateTime? showAddExtraDialogForFiveSeven, DateTime? showPauseScoringDialog, DateTime? showAddPenaltyRunDialog, + DateTime? showEndMatchDialog, DateTime? invalidUndoToast, @Default([]) List currentScoresList, @Default([]) List previousScoresList, @@ -977,7 +998,8 @@ enum MatchOption { changeStriker, penaltyRun, pauseScoring, - continueWithInjuredPlayer; + continueWithInjuredPlayer, + endMatch; String getTitle(BuildContext context) { switch (this) { @@ -989,6 +1011,8 @@ enum MatchOption { return context.l10n.score_board_pause_scoring_title; case MatchOption.continueWithInjuredPlayer: return context.l10n.score_board_continue_with_injured_player_title; + case MatchOption.endMatch: + return context.l10n.score_board_end_of_match_title; } } } diff --git a/khelo/lib/ui/flow/score_board/score_board_view_model.freezed.dart b/khelo/lib/ui/flow/score_board/score_board_view_model.freezed.dart index 875a81ea..d6fb0762 100644 --- a/khelo/lib/ui/flow/score_board/score_board_view_model.freezed.dart +++ b/khelo/lib/ui/flow/score_board/score_board_view_model.freezed.dart @@ -47,6 +47,7 @@ mixin _$ScoreBoardViewState { throw _privateConstructorUsedError; DateTime? get showPauseScoringDialog => throw _privateConstructorUsedError; DateTime? get showAddPenaltyRunDialog => throw _privateConstructorUsedError; + DateTime? get showEndMatchDialog => throw _privateConstructorUsedError; DateTime? get invalidUndoToast => throw _privateConstructorUsedError; List get currentScoresList => throw _privateConstructorUsedError; @@ -98,6 +99,7 @@ abstract class $ScoreBoardViewStateCopyWith<$Res> { DateTime? showAddExtraDialogForFiveSeven, DateTime? showPauseScoringDialog, DateTime? showAddPenaltyRunDialog, + DateTime? showEndMatchDialog, DateTime? invalidUndoToast, List currentScoresList, List previousScoresList, @@ -154,6 +156,7 @@ class _$ScoreBoardViewStateCopyWithImpl<$Res, $Val extends ScoreBoardViewState> Object? showAddExtraDialogForFiveSeven = freezed, Object? showPauseScoringDialog = freezed, Object? showAddPenaltyRunDialog = freezed, + Object? showEndMatchDialog = freezed, Object? invalidUndoToast = freezed, Object? currentScoresList = null, Object? previousScoresList = null, @@ -265,6 +268,10 @@ class _$ScoreBoardViewStateCopyWithImpl<$Res, $Val extends ScoreBoardViewState> ? _value.showAddPenaltyRunDialog : showAddPenaltyRunDialog // ignore: cast_nullable_to_non_nullable as DateTime?, + showEndMatchDialog: freezed == showEndMatchDialog + ? _value.showEndMatchDialog + : showEndMatchDialog // ignore: cast_nullable_to_non_nullable + as DateTime?, invalidUndoToast: freezed == invalidUndoToast ? _value.invalidUndoToast : invalidUndoToast // ignore: cast_nullable_to_non_nullable @@ -395,6 +402,7 @@ abstract class _$$ScoreBoardViewStateImplCopyWith<$Res> DateTime? showAddExtraDialogForFiveSeven, DateTime? showPauseScoringDialog, DateTime? showAddPenaltyRunDialog, + DateTime? showEndMatchDialog, DateTime? invalidUndoToast, List currentScoresList, List previousScoresList, @@ -453,6 +461,7 @@ class __$$ScoreBoardViewStateImplCopyWithImpl<$Res> Object? showAddExtraDialogForFiveSeven = freezed, Object? showPauseScoringDialog = freezed, Object? showAddPenaltyRunDialog = freezed, + Object? showEndMatchDialog = freezed, Object? invalidUndoToast = freezed, Object? currentScoresList = null, Object? previousScoresList = null, @@ -564,6 +573,10 @@ class __$$ScoreBoardViewStateImplCopyWithImpl<$Res> ? _value.showAddPenaltyRunDialog : showAddPenaltyRunDialog // ignore: cast_nullable_to_non_nullable as DateTime?, + showEndMatchDialog: freezed == showEndMatchDialog + ? _value.showEndMatchDialog + : showEndMatchDialog // ignore: cast_nullable_to_non_nullable + as DateTime?, invalidUndoToast: freezed == invalidUndoToast ? _value.invalidUndoToast : invalidUndoToast // ignore: cast_nullable_to_non_nullable @@ -641,12 +654,13 @@ class _$ScoreBoardViewStateImpl implements _ScoreBoardViewState { this.showAddExtraDialogForFiveSeven, this.showPauseScoringDialog, this.showAddPenaltyRunDialog, + this.showEndMatchDialog, this.invalidUndoToast, final List currentScoresList = const [], final List previousScoresList = const [], this.loading = false, this.pop = false, - this.continueWithInjuredPlayers = false, + this.continueWithInjuredPlayers = true, this.ballCount = 0, this.overCount = 1, this.totalRuns = 0, @@ -715,6 +729,8 @@ class _$ScoreBoardViewStateImpl implements _ScoreBoardViewState { @override final DateTime? showAddPenaltyRunDialog; @override + final DateTime? showEndMatchDialog; + @override final DateTime? invalidUndoToast; final List _currentScoresList; @override @@ -763,7 +779,7 @@ class _$ScoreBoardViewStateImpl implements _ScoreBoardViewState { @override String toString() { - return 'ScoreBoardViewState(error: $error, match: $match, currentInning: $currentInning, otherInning: $otherInning, bowler: $bowler, strikerId: $strikerId, batsMans: $batsMans, showSelectBatsManSheet: $showSelectBatsManSheet, showSelectBowlerSheet: $showSelectBowlerSheet, showSelectBowlerAndBatsManSheet: $showSelectBowlerAndBatsManSheet, showSelectPlayerSheet: $showSelectPlayerSheet, showSelectWicketTypeSheet: $showSelectWicketTypeSheet, showStrikerSelectionDialog: $showStrikerSelectionDialog, showUndoBallConfirmationDialog: $showUndoBallConfirmationDialog, showOverCompleteDialog: $showOverCompleteDialog, showInningCompleteDialog: $showInningCompleteDialog, showMatchCompleteDialog: $showMatchCompleteDialog, showBoundaryDialogForSix: $showBoundaryDialogForSix, showBoundaryDialogForFour: $showBoundaryDialogForFour, showAddExtraDialogForNoBall: $showAddExtraDialogForNoBall, showAddExtraDialogForLegBye: $showAddExtraDialogForLegBye, showAddExtraDialogForBye: $showAddExtraDialogForBye, showAddExtraDialogForFiveSeven: $showAddExtraDialogForFiveSeven, showPauseScoringDialog: $showPauseScoringDialog, showAddPenaltyRunDialog: $showAddPenaltyRunDialog, invalidUndoToast: $invalidUndoToast, currentScoresList: $currentScoresList, previousScoresList: $previousScoresList, loading: $loading, pop: $pop, continueWithInjuredPlayers: $continueWithInjuredPlayers, ballCount: $ballCount, overCount: $overCount, totalRuns: $totalRuns, wicketCount: $wicketCount, lastAssignedIndex: $lastAssignedIndex)'; + return 'ScoreBoardViewState(error: $error, match: $match, currentInning: $currentInning, otherInning: $otherInning, bowler: $bowler, strikerId: $strikerId, batsMans: $batsMans, showSelectBatsManSheet: $showSelectBatsManSheet, showSelectBowlerSheet: $showSelectBowlerSheet, showSelectBowlerAndBatsManSheet: $showSelectBowlerAndBatsManSheet, showSelectPlayerSheet: $showSelectPlayerSheet, showSelectWicketTypeSheet: $showSelectWicketTypeSheet, showStrikerSelectionDialog: $showStrikerSelectionDialog, showUndoBallConfirmationDialog: $showUndoBallConfirmationDialog, showOverCompleteDialog: $showOverCompleteDialog, showInningCompleteDialog: $showInningCompleteDialog, showMatchCompleteDialog: $showMatchCompleteDialog, showBoundaryDialogForSix: $showBoundaryDialogForSix, showBoundaryDialogForFour: $showBoundaryDialogForFour, showAddExtraDialogForNoBall: $showAddExtraDialogForNoBall, showAddExtraDialogForLegBye: $showAddExtraDialogForLegBye, showAddExtraDialogForBye: $showAddExtraDialogForBye, showAddExtraDialogForFiveSeven: $showAddExtraDialogForFiveSeven, showPauseScoringDialog: $showPauseScoringDialog, showAddPenaltyRunDialog: $showAddPenaltyRunDialog, showEndMatchDialog: $showEndMatchDialog, invalidUndoToast: $invalidUndoToast, currentScoresList: $currentScoresList, previousScoresList: $previousScoresList, loading: $loading, pop: $pop, continueWithInjuredPlayers: $continueWithInjuredPlayers, ballCount: $ballCount, overCount: $overCount, totalRuns: $totalRuns, wicketCount: $wicketCount, lastAssignedIndex: $lastAssignedIndex)'; } @override @@ -821,6 +837,7 @@ class _$ScoreBoardViewStateImpl implements _ScoreBoardViewState { showAddExtraDialogForFiveSeven) && (identical(other.showPauseScoringDialog, showPauseScoringDialog) || other.showPauseScoringDialog == showPauseScoringDialog) && (identical(other.showAddPenaltyRunDialog, showAddPenaltyRunDialog) || other.showAddPenaltyRunDialog == showAddPenaltyRunDialog) && + (identical(other.showEndMatchDialog, showEndMatchDialog) || other.showEndMatchDialog == showEndMatchDialog) && (identical(other.invalidUndoToast, invalidUndoToast) || other.invalidUndoToast == invalidUndoToast) && const DeepCollectionEquality().equals(other._currentScoresList, _currentScoresList) && const DeepCollectionEquality().equals(other._previousScoresList, _previousScoresList) && @@ -862,6 +879,7 @@ class _$ScoreBoardViewStateImpl implements _ScoreBoardViewState { showAddExtraDialogForFiveSeven, showPauseScoringDialog, showAddPenaltyRunDialog, + showEndMatchDialog, invalidUndoToast, const DeepCollectionEquality().hash(_currentScoresList), const DeepCollectionEquality().hash(_previousScoresList), @@ -910,6 +928,7 @@ abstract class _ScoreBoardViewState implements ScoreBoardViewState { final DateTime? showAddExtraDialogForFiveSeven, final DateTime? showPauseScoringDialog, final DateTime? showAddPenaltyRunDialog, + final DateTime? showEndMatchDialog, final DateTime? invalidUndoToast, final List currentScoresList, final List previousScoresList, @@ -973,6 +992,8 @@ abstract class _ScoreBoardViewState implements ScoreBoardViewState { @override DateTime? get showAddPenaltyRunDialog; @override + DateTime? get showEndMatchDialog; + @override DateTime? get invalidUndoToast; @override List get currentScoresList;