7 Commits

Author SHA1 Message Date
e3ac91bf48 remove todo
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m9s
Pull Request Pipeline / lint (pull_request) Successful in 2m11s
2025-12-05 19:41:01 +01:00
dba448b9c1 added const 2025-12-05 19:39:35 +01:00
d8551b3a27 add db functionality 2025-12-05 19:35:14 +01:00
8f2c7493d0 re-set gameListFuture to reload the games after changing the winner 2025-12-05 19:35:04 +01:00
f7f97fcdcb made tapping on game tile redirect to GameResultView 2025-12-05 19:26:47 +01:00
9ac6b6e04c added ontap feature & argument 2025-12-05 19:25:52 +01:00
e77896c1d4 removed settings icon leading to game result view 2025-12-05 19:25:31 +01:00
4 changed files with 140 additions and 139 deletions

View File

@@ -1,12 +1,9 @@
import 'package:flutter/material.dart';
import 'package:game_tracker/core/custom_theme.dart';
import 'package:game_tracker/data/dto/game.dart';
import 'package:game_tracker/data/dto/group.dart';
import 'package:game_tracker/data/dto/player.dart';
import 'package:game_tracker/presentation/views/main_menu/game_history_view.dart';
import 'package:game_tracker/presentation/views/main_menu/game_result_view.dart';
import 'package:game_tracker/presentation/views/main_menu/groups_view.dart';
import 'package:game_tracker/presentation/views/main_menu/home_view.dart';
import 'package:game_tracker/presentation/views/main_menu/settings_view.dart';
import 'package:game_tracker/presentation/views/main_menu/statistics_view.dart';
import 'package:game_tracker/presentation/widgets/navbar_item.dart';
@@ -59,26 +56,7 @@ class _CustomNavigationBarState extends State<CustomNavigationBar>
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (_) => GameResultView(
game: Game(
name: 'Test Game',
players: [
Player(name: 'Petrus'),
Player(name: 'Peter'),
Player(name: 'Petra'),
],
group: Group(
name: 'Die Petris',
members: [
Player(name: 'Petralia'),
Player(name: 'Petrenlia'),
Player(name: 'Petrumlia'),
],
),
),
),
), //TODO Replace with Settingsview
MaterialPageRoute(builder: (_) => const SettingsView()),
);
setState(() {
tabKeyCount++;

View File

@@ -5,6 +5,7 @@ import 'package:game_tracker/data/dto/game.dart';
import 'package:game_tracker/data/dto/group.dart';
import 'package:game_tracker/data/dto/player.dart';
import 'package:game_tracker/presentation/views/main_menu/create_group_view.dart';
import 'package:game_tracker/presentation/views/main_menu/game_result_view.dart';
import 'package:game_tracker/presentation/widgets/app_skeleton.dart';
import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart';
import 'package:game_tracker/presentation/widgets/tiles/game_history_tile.dart';
@@ -21,7 +22,6 @@ class GameHistoryView extends StatefulWidget {
class _GameHistoryViewState extends State<GameHistoryView> {
late Future<List<Game>> _gameListFuture;
late final AppDatabase db;
late bool isLoading = true;
late final List<Game> skeletonData = List.filled(
4,
@@ -50,9 +50,6 @@ class _GameHistoryViewState extends State<GameHistoryView> {
Future.wait([_gameListFuture]).then((result) async {
await Future.delayed(const Duration(milliseconds: 250));
setState(() {
isLoading = false;
});
});
}
@@ -86,14 +83,14 @@ class _GameHistoryViewState extends State<GameHistoryView> {
),
);
}
final bool isLoading =
snapshot.connectionState == ConnectionState.waiting;
final List<Game> games =
(isLoading ? skeletonData : (snapshot.data ?? [])
..sort(
(a, b) => b.createdAt.compareTo(a.createdAt),
))
.toList();
return AppSkeleton(
enabled: isLoading,
child: ListView.builder(
@@ -106,8 +103,20 @@ class _GameHistoryViewState extends State<GameHistoryView> {
);
}
return GameHistoryTile(
onTap: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
GameResultView(game: games[index]),
),
);
setState(() {
_gameListFuture = db.gameDao.getAllGames();
});
},
game: games[index],
); // Placeholder
);
},
),
);

View File

@@ -1,10 +1,12 @@
import 'package:flutter/material.dart';
import 'package:game_tracker/core/custom_theme.dart';
import 'package:game_tracker/data/db/database.dart';
import 'package:game_tracker/data/dto/game.dart';
import 'package:game_tracker/data/dto/player.dart';
import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart';
import 'package:game_tracker/presentation/widgets/tiles/custom_radio_list_tile.dart';
import 'package:game_tracker/presentation/widgets/top_centered_message.dart';
import 'package:provider/provider.dart';
class GameResultView extends StatefulWidget {
final Game game;
@@ -17,11 +19,16 @@ class GameResultView extends StatefulWidget {
class _GameResultViewState extends State<GameResultView> {
late final List<Player> allPlayers;
Player? _player; //TODO: Set last winner as selected
late final AppDatabase db;
Player? _player;
@override
void initState() {
db = Provider.of<AppDatabase>(context, listen: false);
allPlayers = getAllPlayers(widget.game);
if (widget.game.winner != null) {
_player = allPlayers.firstWhere((p) => p.id == widget.game.winner!.id);
}
super.initState();
}
@@ -112,11 +119,29 @@ class _GameResultViewState extends State<GameResultView> {
text: 'Save',
sizeRelativeToWidth: 0.95,
onPressed: _player != null
? () {
print(
'Selected Winner: ${_player!.name}',
); //TODO: Add winner to db
Navigator.pop(context);
? () async {
print('Selected Winner: ${_player!.name}');
bool success = await db.gameDao.setWinner(
gameId: widget.game.id,
winnerId: _player!.id,
);
if (!context.mounted) return;
if (success) {
Navigator.pop(context);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: CustomTheme.boxColor,
content: const Center(
child: Text(
'Error while setting winner, please try again',
style: TextStyle(color: Colors.white),
),
),
),
);
}
setState(() {});
}
: null,
),

View File

@@ -6,142 +6,132 @@ import 'package:intl/intl.dart';
class GameHistoryTile extends StatefulWidget {
final Game game;
final VoidCallback onTap;
const GameHistoryTile({
super.key,
required this.game,
});
const GameHistoryTile({super.key, required this.game, required this.onTap});
@override
State<GameHistoryTile> createState() => _GameHistoryTileState();
}
class _GameHistoryTileState extends State<GameHistoryTile> {
@override
Widget build(BuildContext context) {
final group = widget.game.group;
final winner = widget.game.winner;
final allPlayers = _getAllPlayers();
return Container(
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: CustomTheme.boxColor,
border: Border.all(color: CustomTheme.boxBorder),
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
widget.game.name,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
overflow: TextOverflow.ellipsis,
),
),
Text(
_formatDate(widget.game.createdAt),
style: const TextStyle(
fontSize: 12,
color: Colors.grey,
),
),
],
),
const SizedBox(height: 8),
if (group != null) ...[
return GestureDetector(
onTap: widget.onTap,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: CustomTheme.boxColor,
border: Border.all(color: CustomTheme.boxBorder),
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Icon(
Icons.group,
size: 16,
color: Colors.grey,
),
const SizedBox(width: 6),
Expanded(
child: Text(
group.name,
widget.game.name,
style: const TextStyle(
fontSize: 14,
color: Colors.grey,
fontSize: 18,
fontWeight: FontWeight.bold,
),
overflow: TextOverflow.ellipsis,
),
),
Text(
_formatDate(widget.game.createdAt),
style: const TextStyle(fontSize: 12, color: Colors.grey),
),
],
),
const SizedBox(height: 12),
],
if (winner != null) ...[
Container(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
decoration: BoxDecoration(
color: Colors.green.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: Colors.green.withValues(alpha: 0.3),
width: 1,
),
),
child: Row(
const SizedBox(height: 8),
if (group != null) ...[
Row(
children: [
const Icon(
Icons.emoji_events,
size: 20,
color: Colors.amber,
),
const SizedBox(width: 8),
const Icon(Icons.group, size: 16, color: Colors.grey),
const SizedBox(width: 6),
Expanded(
child: Text(
'Winner: ${winner.name}',
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.white,
),
group.name,
style: const TextStyle(fontSize: 14, color: Colors.grey),
overflow: TextOverflow.ellipsis,
),
),
],
),
),
const SizedBox(height: 12),
],
const SizedBox(height: 12),
],
if (allPlayers.isNotEmpty) ...[
const Text(
'Players',
style: TextStyle(
fontSize: 13,
color: Colors.grey,
fontWeight: FontWeight.w500,
if (winner != null) ...[
Container(
padding: const EdgeInsets.symmetric(
vertical: 8,
horizontal: 12,
),
decoration: BoxDecoration(
color: Colors.green.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: Colors.green.withValues(alpha: 0.3),
width: 1,
),
),
child: Row(
children: [
const Icon(
Icons.emoji_events,
size: 20,
color: Colors.amber,
),
const SizedBox(width: 8),
Expanded(
child: Text(
'Winner: ${winner.name}',
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.white,
),
overflow: TextOverflow.ellipsis,
),
),
],
),
),
),
const SizedBox(height: 6),
Wrap(
spacing: 6,
runSpacing: 6,
children: allPlayers.map((player) {
return TextIconTile(
text: player.name,
iconEnabled: false,
);
}).toList(),
),
const SizedBox(height: 12),
],
if (allPlayers.isNotEmpty) ...[
const Text(
'Players',
style: TextStyle(
fontSize: 13,
color: Colors.grey,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 6),
Wrap(
spacing: 6,
runSpacing: 6,
children: allPlayers.map((player) {
return TextIconTile(text: player.name, iconEnabled: false);
}).toList(),
),
],
],
],
),
),
);
}
@@ -187,5 +177,4 @@ class _GameHistoryTileState extends State<GameHistoryTile> {
return allPlayers;
}
}
}