feat: Implemented LiveEditView
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 44s
Pull Request Pipeline / lint (pull_request) Successful in 52s

This commit is contained in:
2026-05-21 21:10:07 +02:00
parent 12b7bcdc6c
commit 46134a4f5c
3 changed files with 184 additions and 135 deletions

View File

@@ -0,0 +1,89 @@
import 'package:flutter/material.dart';
import 'package:tallee/data/models/match.dart';
import 'package:tallee/data/models/player.dart';
import 'package:tallee/data/models/team.dart';
import 'package:tallee/presentation/widgets/buttons/haptic_icon_button.dart';
import 'package:tallee/presentation/widgets/tiles/match_result_view/live_edit_list_tile.dart';
class LiveEditView extends StatefulWidget {
const LiveEditView({super.key, required this.match});
final Match match;
@override
State<LiveEditView> createState() => _LiveEditViewState();
}
class _LiveEditViewState extends State<LiveEditView> {
List<Team> get allTeams =>
(widget.match.teams ?? [])..sort((a, b) => a.name.compareTo(b.name));
List<Player> get allPlayers =>
widget.match.players..sort((a, b) => a.name.compareTo(b.name));
List<int> scores = [];
@override
void initState() {
super.initState();
if (widget.match.isTeamMatch) {
scores = List.generate(
allTeams.length,
(index) => allTeams[index].score ?? 0,
);
} else {
scores = List.generate(
allPlayers.length,
(index) => widget.match.scores[allPlayers[index].id]?.score ?? 0,
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.match.name),
leading: HapticIconButton(
onPressed: () => Navigator.pop(context, scores),
icon: const Icon(Icons.close),
),
),
body: Column(
children: [
Expanded(child: buildLiveEditWidget(widget.match.isTeamMatch)),
],
),
);
}
Widget buildLiveEditWidget(bool isTeamMatch) {
if (isTeamMatch) {
return ListView.builder(
itemCount: allTeams.length,
itemBuilder: (context, index) {
return LiveEditListTile(
title: allTeams[index].name,
onChanged: (value) {
scores[index] = value;
},
value: scores[index],
);
},
);
} else {
return ListView.builder(
itemCount: allPlayers.length,
itemBuilder: (context, index) {
return LiveEditListTile(
title: allPlayers[index].name,
onChanged: (value) {
setState(() {
scores[index] = value;
});
},
value: scores[index],
);
},
);
}
}
}

View File

@@ -2,6 +2,7 @@ import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tallee/core/adaptive_page_route.dart';
import 'package:tallee/core/common.dart'; import 'package:tallee/core/common.dart';
import 'package:tallee/core/custom_theme.dart'; import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/core/enums.dart'; import 'package:tallee/core/enums.dart';
@@ -11,11 +12,11 @@ import 'package:tallee/data/models/player.dart';
import 'package:tallee/data/models/score_entry.dart'; import 'package:tallee/data/models/score_entry.dart';
import 'package:tallee/data/models/team.dart'; import 'package:tallee/data/models/team.dart';
import 'package:tallee/l10n/generated/app_localizations.dart'; import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/views/main_menu/match_view/create_match/match_result/live_edit_view.dart';
import 'package:tallee/presentation/widgets/buttons/animated_dialog_button.dart'; import 'package:tallee/presentation/widgets/buttons/animated_dialog_button.dart';
import 'package:tallee/presentation/widgets/buttons/haptic_icon_button.dart'; import 'package:tallee/presentation/widgets/buttons/haptic_icon_button.dart';
import 'package:tallee/presentation/widgets/tiles/match_result_view/custom_checkbox_list_tile.dart'; import 'package:tallee/presentation/widgets/tiles/match_result_view/custom_checkbox_list_tile.dart';
import 'package:tallee/presentation/widgets/tiles/match_result_view/custom_radio_list_tile.dart'; import 'package:tallee/presentation/widgets/tiles/match_result_view/custom_radio_list_tile.dart';
import 'package:tallee/presentation/widgets/tiles/match_result_view/live_edit_list_tile.dart';
import 'package:tallee/presentation/widgets/tiles/match_result_view/score_list_tile.dart'; import 'package:tallee/presentation/widgets/tiles/match_result_view/score_list_tile.dart';
import 'package:tallee/presentation/widgets/tiles/text_icon_list_tile.dart'; import 'package:tallee/presentation/widgets/tiles/text_icon_list_tile.dart';
@@ -38,8 +39,6 @@ class MatchResultView extends StatefulWidget {
class _MatchResultViewState extends State<MatchResultView> { class _MatchResultViewState extends State<MatchResultView> {
late final AppDatabase db; late final AppDatabase db;
bool isLiveEditMode = false;
late final Ruleset ruleset; late final Ruleset ruleset;
late final List<Player> allPlayers; late final List<Player> allPlayers;
@@ -92,33 +91,20 @@ class _MatchResultViewState extends State<MatchResultView> {
appBar: AppBar( appBar: AppBar(
automaticallyImplyLeading: true, automaticallyImplyLeading: true,
leading: HapticIconButton( leading: HapticIconButton(
icon: isLiveEditMode icon: const Icon(Icons.close),
? const Icon(Icons.arrow_back_ios) onPressed: () => {
: const Icon(Icons.close), widget.onWinnerChanged?.call(),
onPressed: isLiveEditMode Navigator.pop(context),
? () => setState(() { },
isLiveEditMode = false;
})
: () => {widget.onWinnerChanged?.call(), Navigator.pop(context)},
), ),
title: Text(widget.match.name), title: Text(widget.match.name),
), ),
body: Column( body: Column(
children: [ children: [
Expanded( Expanded(
child: isLiveEditMode child: Container(
// Live Edit Mode margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
? buildLiveEditWidet(isTeamMatch) padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
// Normal Container
: Container(
margin: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 10,
),
padding: const EdgeInsets.symmetric(
vertical: 10,
horizontal: 10,
),
decoration: BoxDecoration( decoration: BoxDecoration(
color: CustomTheme.boxColor, color: CustomTheme.boxColor,
border: Border.all(color: CustomTheme.boxBorderColor), border: Border.all(color: CustomTheme.boxBorderColor),
@@ -141,14 +127,10 @@ class _MatchResultViewState extends State<MatchResultView> {
if (rulesetSupportsPlayerSelection()) if (rulesetSupportsPlayerSelection())
if (ruleset == Ruleset.multipleWinners) if (ruleset == Ruleset.multipleWinners)
Expanded( Expanded(
child: buildMultipleWinnerSelectionWidget( child: buildMultipleWinnerSelectionWidget(isTeamMatch),
isTeamMatch,
),
) )
else else
Expanded( Expanded(child: buildPlayerSelectionWidget(isTeamMatch)),
child: buildPlayerSelectionWidget(isTeamMatch),
),
// Show score entry // Show score entry
if (rulesetSupportsScoreEntry()) if (rulesetSupportsScoreEntry())
@@ -162,14 +144,13 @@ class _MatchResultViewState extends State<MatchResultView> {
), ),
), ),
if (!isLiveEditMode) ...[
Padding( Padding(
padding: const EdgeInsets.fromLTRB(12, 0, 12, 20), padding: const EdgeInsets.fromLTRB(12, 0, 12, 20),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
// Live Edit Mode Button
if (rulesetSupportsScoreEntry()) ...[ if (rulesetSupportsScoreEntry()) ...[
// Button to switch to live edit mode
AnimatedDialogButton( AnimatedDialogButton(
buttonConstraints: const BoxConstraints( buttonConstraints: const BoxConstraints(
minWidth: double.infinity, minWidth: double.infinity,
@@ -177,9 +158,23 @@ class _MatchResultViewState extends State<MatchResultView> {
), ),
buttonText: loc.live_edit_mode, buttonText: loc.live_edit_mode,
buttonType: ButtonType.secondary, buttonType: ButtonType.secondary,
onPressed: () => setState(() { onPressed: () =>
isLiveEditMode = !isLiveEditMode; Navigator.push(
}), context,
adaptivePageRoute(
fullscreenDialog: true,
builder: (context) =>
LiveEditView(match: widget.match),
),
).then(
(scores) => {
if (scores != null)
{
for (int i = 0; i < scores.length; i++)
{controller[i].text = scores[i].toString()},
},
},
),
), ),
], ],
@@ -207,7 +202,6 @@ class _MatchResultViewState extends State<MatchResultView> {
), ),
), ),
], ],
],
), ),
); );
} }
@@ -847,38 +841,4 @@ class _MatchResultViewState extends State<MatchResultView> {
); );
} }
} }
Widget buildLiveEditWidet(bool isTeamMatch) {
if (isTeamMatch) {
return ListView.builder(
itemCount: allTeams.length,
itemBuilder: (context, index) {
return LiveEditListTile(
title: allTeams[index].name,
onChanged: (value) {
setState(() {
controller[index].text = value.toString();
});
},
value: int.tryParse(controller[index].text) ?? 0,
);
},
);
} else {
return ListView.builder(
itemCount: allPlayers.length,
itemBuilder: (context, index) {
return LiveEditListTile(
title: allPlayers[index].name,
onChanged: (value) {
setState(() {
controller[index].text = value.toString();
});
},
value: int.tryParse(controller[index].text) ?? 0,
);
},
);
}
}
} }

View File

@@ -1,7 +1,7 @@
name: tallee name: tallee
description: "Tracking App for Card Games" description: "Tracking App for Card Games"
publish_to: 'none' publish_to: 'none'
version: 0.0.30+330 version: 0.0.30+331
environment: environment:
sdk: ^3.8.1 sdk: ^3.8.1