2 Commits

Author SHA1 Message Date
Yannick
32c7d45809 made game_history_tile prettier :)
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 2m13s
Pull Request Pipeline / lint (pull_request) Failing after 2m17s
2025-11-24 11:34:22 +01:00
Yannick
4341c2509e fix bug where only last 2 games were shown 2025-11-24 11:07:40 +01:00
2 changed files with 168 additions and 55 deletions

View File

@@ -19,7 +19,7 @@ class _GameHistoryViewState extends State<GameHistoryView> {
late final AppDatabase db;
late final List<Game> skeletonData = List.filled(
2,
10,
Game(
name: 'Skeleton Game',
group: Group(
@@ -30,6 +30,9 @@ class _GameHistoryViewState extends State<GameHistoryView> {
],
),
winner: Player(name: 'Skeleton Player 1'),
players: [
Player(name: 'Skeleton Player 3')
],
),
);
@@ -37,10 +40,11 @@ class _GameHistoryViewState extends State<GameHistoryView> {
void initState() {
super.initState();
db = Provider.of<AppDatabase>(context, listen: false);
_gameListFuture = Future.delayed(
const Duration(milliseconds: 250),
() => db.gameDao.getAllGames(),
);
_gameListFuture = db.gameDao.getAllGames();
Future.wait([_gameListFuture]).then((result) async {
await Future.delayed(const Duration(milliseconds: 250));
});
}
@override
@@ -69,7 +73,6 @@ class _GameHistoryViewState extends State<GameHistoryView> {
? skeletonData
: (snapshot.data ?? [])
..sort((a, b) => b.createdAt.compareTo(a.createdAt)))
.take(2)
.toList();
return Skeletonizer(

View File

@@ -1,21 +1,15 @@
import 'package:flutter/material.dart';
import 'package:game_tracker/core/custom_theme.dart';
import 'package:skeletonizer/skeletonizer.dart';
import 'package:game_tracker/data/dto/game.dart';
import 'package:game_tracker/presentation/widgets/tiles/text_icon_tile.dart';
import 'package:intl/intl.dart';
class GameHistoryTile extends StatefulWidget {
final String gameTitle;
final String gameType;
final String date;
final String groupName;
final String winner;
final Game game;
const GameHistoryTile({
super.key,
required this.gameTitle,
required this.gameType,
required this.date,
required this.groupName,
required this.winner,
required this.game,
});
@override
@@ -23,55 +17,171 @@ class GameHistoryTile extends StatefulWidget {
}
class _GameHistoryTileState extends State<GameHistoryTile> {
String _formatDate(DateTime dateTime) {
final now = DateTime.now();
final difference = now.difference(dateTime);
if (difference.inDays == 0) {
return 'Today at ${DateFormat('HH:mm').format(dateTime)}';
} else if (difference.inDays == 1) {
return 'Yesterday at ${DateFormat('HH:mm').format(dateTime)}';
} else if (difference.inDays < 7) {
return '${difference.inDays} days ago';
} else {
return DateFormat('MMM d, yyyy').format(dateTime);
}
}
List<dynamic> _getAllPlayers() {
final allPlayers = <dynamic>[];
final playerIds = <String>{};
// Add players from game.players
if (widget.game.players != null) {
for (var player in widget.game.players!) {
if (!playerIds.contains(player.id)) {
allPlayers.add(player);
playerIds.add(player.id);
}
}
}
// Add players from game.group.players
if (widget.game.group?.members != null) {
for (var player in widget.game.group!.members) {
if (!playerIds.contains(player.id)) {
allPlayers.add(player);
playerIds.add(player.id);
}
}
}
return allPlayers;
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
decoration: BoxDecoration(
color: CustomTheme.boxColor,
border: Border.all(color: CustomTheme.boxBorder),
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
Row(
children: [
Text(
widget.gameTitle,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
),
],
),
Row(
children: [
Text(
widget.date,
style: const TextStyle(fontSize: 14, color: Colors.grey),
textAlign: TextAlign.left,
),
const SizedBox(width: 5),
const Text('·'),
const SizedBox(width: 5),
Text(
widget.gameType,
style: const TextStyle(fontSize: 14, color: Colors.grey),
textAlign: TextAlign.left,
),
],
),
const SizedBox(height: 15),
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)
Row(
children: [
const Icon(
Icons.group,
size: 16,
color: Colors.grey,
),
const SizedBox(width: 6),
Expanded(
child: Text(
group.name,
style: const TextStyle(
fontSize: 14,
color: Colors.grey,
),
overflow: TextOverflow.ellipsis,
),
),
],
),
if (group != null) 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(
children: [
const Icon(
Icons.emoji_events,
size: 20,
color: Colors.amber,
),
const SizedBox(width: 8),
Text(
'Winner: ${winner.name}',
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
],
),
),
if (winner != null) 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) {
final isWinner = winner != null && player.id == winner.id;
return TextIconTile(
text: player.name,
iconEnabled: false,
);
}).toList(),
),
],
],
),
);
}
}