MVP #141

Merged
flixcoo merged 705 commits from development into main 2026-01-09 12:55:50 +00:00
Showing only changes of commit 32c7d45809 - Show all commits

View File

@@ -1,21 +1,15 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:game_tracker/core/custom_theme.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 { class GameHistoryTile extends StatefulWidget {
final String gameTitle; final Game game;
final String gameType;
final String date;
final String groupName;
final String winner;
const GameHistoryTile({ const GameHistoryTile({
super.key, super.key,
required this.gameTitle, required this.game,
required this.gameType,
required this.date,
required this.groupName,
required this.winner,
}); });
@override @override
@@ -23,55 +17,171 @@ class GameHistoryTile extends StatefulWidget {
} }
class _GameHistoryTileState extends State<GameHistoryTile> { 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( final group = widget.game.group;
crossAxisAlignment: CrossAxisAlignment.start, final winner = widget.game.winner;
children: [ final allPlayers = _getAllPlayers();
Container(
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), return Container(
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration( padding: const EdgeInsets.all(16),
color: CustomTheme.boxColor, decoration: BoxDecoration(
border: Border.all(color: CustomTheme.boxBorder), color: CustomTheme.boxColor,
borderRadius: BorderRadius.circular(12), border: Border.all(color: CustomTheme.boxBorder),
), borderRadius: BorderRadius.circular(12),
child: Column( ),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Expanded(
children: [ child: Text(
Text( widget.game.name,
widget.gameTitle, style: const TextStyle(
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), fontSize: 18,
overflow: TextOverflow.ellipsis, 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,
),
), ),
Row( child: Row(
children: [ children: [
Text( const Icon(
widget.date, Icons.emoji_events,
style: const TextStyle(fontSize: 14, color: Colors.grey), size: 20,
textAlign: TextAlign.left, color: Colors.amber,
), ),
const SizedBox(width: 5), const SizedBox(width: 8),
const Text('·'),
const SizedBox(width: 5),
Text( Text(
widget.gameType, 'Winner: ${winner.name}',
style: const TextStyle(fontSize: 14, color: Colors.grey), style: const TextStyle(
textAlign: TextAlign.left, fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.white,
),
), ),
], ],
), ),
const SizedBox(height: 15), ),
] 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(),
),
],
],
),
); );
} }
}
}