GameHistoryView anpassen #20
@@ -1,7 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:game_tracker/core/custom_theme.dart';
|
||||
import 'package:game_tracker/presentation/widgets/tiles/double_row_info_tile.dart';
|
||||
import 'package:game_tracker/data/db/database.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/create_group_view.dart';
|
||||
import 'package:game_tracker/presentation/widgets/tiles/game_history_tile.dart';
|
||||
import 'package:game_tracker/presentation/widgets/top_centered_message.dart';
|
||||
import 'package:game_tracker/presentation/widgets/app_skeleton.dart';
|
||||
import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart';
|
||||
|
gelbeinhalb marked this conversation as resolved
Outdated
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class GameHistoryView extends StatefulWidget {
|
||||
const GameHistoryView({super.key});
|
||||
@@ -11,119 +19,43 @@ class GameHistoryView extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _GameHistoryViewState extends State<GameHistoryView> {
|
||||
|
gelbeinhalb marked this conversation as resolved
Outdated
flixcoo
commented
Ich würde die Skeleton-Daten so anpassen, dass du nicht mehr machst als auf den Screen passen. Also bei mir sind das glaub ich so 5 Ich würde die Skeleton-Daten so anpassen, dass du nicht mehr machst als auf den Screen passen. Also bei mir sind das glaub ich so 5
gelbeinhalb
commented
ja save :) hab 10 eingestellt zum testen und dann vergessen zu ändern ja save :) hab 10 eingestellt zum testen und dann vergessen zu ändern
|
||||
final allGameData = [
|
||||
{
|
||||
'game': 'Schach',
|
||||
'title': 'Abendpartie',
|
||||
'players': 2,
|
||||
'group': 'Familie',
|
||||
'date': '01.06.2024',
|
||||
},
|
||||
{
|
||||
'game': 'Monopoly',
|
||||
'title': 'Wochenendspaß mit Gras du Saas',
|
||||
'players': 4,
|
||||
'group': 'Freunde',
|
||||
'date': '28.05.2024',
|
||||
},
|
||||
{
|
||||
'game': 'Catan',
|
||||
'title': 'Strategieabend',
|
||||
'players': 3,
|
||||
'group': 'Brettspieler',
|
||||
'date': '25.05.2024',
|
||||
},
|
||||
{
|
||||
'game': 'Uno',
|
||||
'title': 'Schnelle Runde',
|
||||
'players': 5,
|
||||
'group': 'Kollegen',
|
||||
'date': '22.05.2024',
|
||||
},
|
||||
{
|
||||
'game': 'Poker',
|
||||
'title': 'Freitagspoker',
|
||||
'players': 6,
|
||||
'group': 'Pokerclub',
|
||||
'date': '20.05.2024',
|
||||
},
|
||||
{
|
||||
'game': 'Scrabble',
|
||||
'title': 'Wortschlacht',
|
||||
'players': 4,
|
||||
'group': 'Familie',
|
||||
'date': '18.05.2024',
|
||||
},
|
||||
{
|
||||
'game': 'Risiko',
|
||||
'title': 'Weltherrschaft',
|
||||
'players': 5,
|
||||
'group': 'Strategiegruppe',
|
||||
'date': '15.05.2024',
|
||||
},
|
||||
{
|
||||
'game': 'Zug um Zug',
|
||||
'title': 'Zug-Abenteuer',
|
||||
'players': 4,
|
||||
'group': 'Reisende',
|
||||
'date': '12.05.2024',
|
||||
},
|
||||
{
|
||||
'game': 'Carcassonne',
|
||||
'title': 'Plättchenlegen',
|
||||
'players': 3,
|
||||
'group': 'Brettspieler',
|
||||
'date': '10.05.2024',
|
||||
},
|
||||
{
|
||||
'game': 'Pandemie',
|
||||
'title': 'Welt retten',
|
||||
'players': 4,
|
||||
'group': 'Koop-Team',
|
||||
'date': '08.05.2024',
|
||||
},
|
||||
{
|
||||
'game': 'Cluedo',
|
||||
'title': 'Krimiabend',
|
||||
'players': 6,
|
||||
'group': 'Detektive',
|
||||
'date': '05.05.2024',
|
||||
},
|
||||
{
|
||||
'game': 'Dixit',
|
||||
'title': 'Fantasiespiel',
|
||||
'players': 5,
|
||||
'group': 'Künstler',
|
||||
'date': '02.05.2024',
|
||||
},
|
||||
{
|
||||
'game': 'Azul',
|
||||
'title': 'Plättchenmeister',
|
||||
'players': 4,
|
||||
'group': 'Familie',
|
||||
'date': '30.04.2024',
|
||||
},
|
||||
{
|
||||
'game': 'Splendor',
|
||||
'title': 'Edelsteinhändler',
|
||||
'players': 3,
|
||||
'group': 'Freunde',
|
||||
'date': '28.04.2024',
|
||||
},
|
||||
{
|
||||
'game': '7 Wonders',
|
||||
'title': 'Antike Reiche',
|
||||
'players': 7,
|
||||
'group': 'Geschichtsfreunde',
|
||||
'date': '25.04.2024',
|
||||
},
|
||||
];
|
||||
late List<Map<String, dynamic>> suggestedGameData;
|
||||
late Future<List<Game>> _gameListFuture;
|
||||
late final AppDatabase db;
|
||||
late bool isLoading = true;
|
||||
|
||||
late final List<Game> skeletonData = List.filled(
|
||||
4,
|
||||
Game(
|
||||
name: 'Skeleton Game',
|
||||
group: Group(
|
||||
name: 'Skeleton Group',
|
||||
members: [
|
||||
Player(name: 'Player 1'),
|
||||
Player(name: 'Player 2'),
|
||||
Player(name: 'Player 3'),
|
||||
Player(name: 'Long Name Player 4'),
|
||||
Player(name: 'Player 5'),
|
||||
],
|
||||
),
|
||||
winner: Player(name: 'Skeleton Player 1'),
|
||||
players: [
|
||||
Player(name: 'Skeleton Player 6')
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
suggestedGameData = List.from(allGameData);
|
||||
db = Provider.of<AppDatabase>(context, listen: false);
|
||||
_gameListFuture = db.gameDao.getAllGames();
|
||||
|
||||
Future.wait([_gameListFuture]).then((result) async {
|
||||
await Future.delayed(const Duration(milliseconds: 250));
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -131,41 +63,70 @@ class _GameHistoryViewState extends State<GameHistoryView> {
|
||||
return Scaffold(
|
||||
backgroundColor: CustomTheme.backgroundColor,
|
||||
body: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Container(margin: const EdgeInsets.only(bottom: 75)),
|
||||
Expanded(
|
||||
child: gameHistoryListView(allGameData, suggestedGameData),
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
margin: const EdgeInsets.only(top: 10, bottom: 10, left: 10, right: 10),
|
||||
child: SearchBar(
|
||||
leading: const Icon(Icons.search),
|
||||
onChanged: (value) {
|
||||
if (value.isEmpty) {
|
||||
setState(() {
|
||||
suggestedGameData.clear();
|
||||
suggestedGameData.addAll(allGameData);
|
||||
});
|
||||
return;
|
||||
}
|
||||
final suggestions = allGameData.where((currentGame) {
|
||||
return currentGame['game'].toString().toLowerCase().contains(
|
||||
value.toLowerCase(),
|
||||
) ||
|
||||
currentGame['title'].toString().toLowerCase().contains(
|
||||
value.toLowerCase(),
|
||||
) ||
|
||||
currentGame['group'].toString().toLowerCase().contains(
|
||||
value.toLowerCase(),
|
||||
FutureBuilder<List<Game>>(
|
||||
future: _gameListFuture,
|
||||
builder: (BuildContext context, AsyncSnapshot<List<Game>> snapshot) {
|
||||
|
gelbeinhalb marked this conversation as resolved
Outdated
sneeex
commented
Errormessage anders, handelt sich ja nicht um recent games Errormessage anders, handelt sich ja nicht um recent games
gelbeinhalb
commented
jo jo
sneeex
commented
und besser standartisierte und besser standartisierte `top_centered_message` wie in GroupsView benutzen.
Außerdem sieht das Alignement komisch aus:

|
||||
if (snapshot.hasError) {
|
||||
return const Center(
|
||||
child: TopCenteredMessage(
|
||||
icon: Icons.report,
|
||||
|
gelbeinhalb marked this conversation as resolved
Outdated
flixcoo
commented
Die Skeleton-Zeit ist viel kürzer als bei allen anderen Screens. Ich glaube das liegt an dieser Zeile, weil du hier die Die Skeleton-Zeit ist viel kürzer als bei allen anderen Screens. Ich glaube das liegt an dieser Zeile, weil du hier die `isLoading` Variable setzt und nicht nach dem oben angegebenen 250ms delay.
gelbeinhalb
commented
okay danke :) guck ich mir an okay danke :) guck ich mir an
|
||||
title: 'Error',
|
||||
message: 'Game data could not be loaded',
|
||||
),
|
||||
);
|
||||
}
|
||||
if (snapshot.connectionState == ConnectionState.done &&
|
||||
(!snapshot.hasData || snapshot.data!.isEmpty)) {
|
||||
return const Center(
|
||||
child: TopCenteredMessage(
|
||||
icon: Icons.report,
|
||||
title: 'Error',
|
||||
message: 'No Games Available',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
gelbeinhalb marked this conversation as resolved
Outdated
flixcoo
commented
Bitte das Custom Widget Bitte das Custom Widget `AppSkeleton` aus `development` hier noch Implementieren
|
||||
|
||||
final List<Game> games = (isLoading
|
||||
? skeletonData
|
||||
: (snapshot.data ?? [])
|
||||
..sort((a, b) => b.createdAt.compareTo(a.createdAt)))
|
||||
.toList();
|
||||
|
||||
return AppSkeleton(
|
||||
enabled: isLoading,
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.only(bottom: 85),
|
||||
itemCount: games.length + 1,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
|
gelbeinhalb marked this conversation as resolved
Outdated
sneeex
commented
padding zu groß, zu viel platz unten ohne button, mit button evtl passend padding zu groß, zu viel platz unten ohne button, mit button evtl passend
|
||||
if (index == games.length) {
|
||||
return SizedBox(
|
||||
height: MediaQuery.paddingOf(context).bottom - 80,
|
||||
);
|
||||
});
|
||||
}
|
||||
return GameHistoryTile(game: games[index]); // Placeholder
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
gelbeinhalb marked this conversation as resolved
flixcoo
commented
Es fehlt noch der Create Game Button Es fehlt noch der Create Game Button
gelbeinhalb
commented
Der um ein Match zu erstellen? oder der um ein Game zu erstellen? Der um ein Match zu erstellen? oder der um ein Game zu erstellen?
flixcoo
commented
Digga xD der Button der zur Digga xD der Button der zur `CreateGameView` führt
sneeex
commented
Bitte customwidthbutton mit breite 0,9 wie bei groupsview machen Bitte customwidthbutton mit breite 0,9 wie bei groupsview machen
|
||||
Positioned(
|
||||
bottom: MediaQuery.paddingOf(context).bottom,
|
||||
child: CustomWidthButton(
|
||||
text: 'Create Game',
|
||||
sizeRelativeToWidth: 0.90,
|
||||
onPressed: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return const CreateGroupView();
|
||||
},
|
||||
),
|
||||
);
|
||||
setState(() {
|
||||
suggestedGameData.clear();
|
||||
suggestedGameData.addAll(suggestions);
|
||||
_gameListFuture = db.gameDao.getAllGames();
|
||||
});
|
||||
},
|
||||
),
|
||||
@@ -174,33 +135,4 @@ class _GameHistoryViewState extends State<GameHistoryView> {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget gameHistoryListView(allGameData, suggestedGameData) {
|
||||
if (suggestedGameData.isEmpty && allGameData.isEmpty) {
|
||||
return const TopCenteredMessage(
|
||||
icon: Icons.info,
|
||||
title: 'Info',
|
||||
message: 'Keine Spiele erstellt',
|
||||
);
|
||||
} else if (suggestedGameData.isEmpty) {
|
||||
return const TopCenteredMessage(
|
||||
icon: Icons.search,
|
||||
title: 'Info',
|
||||
message: 'Kein Spiel mit den Suchparametern gefunden.',
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
itemCount: suggestedGameData.length,
|
||||
itemBuilder: (context, index) {
|
||||
final currentGame = suggestedGameData[index];
|
||||
return doubleRowInfoTile(
|
||||
currentGame['game'] + ': ',
|
||||
currentGame['title'],
|
||||
"${currentGame['players']} Spieler",
|
||||
currentGame['group'],
|
||||
currentGame['date'],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:game_tracker/core/custom_theme.dart';
|
||||
|
||||
Widget doubleRowInfoTile(
|
||||
String titleOneUpperLeft,
|
||||
String titleTwoUpperLeft,
|
||||
String titleUpperRight,
|
||||
String titleLowerLeft,
|
||||
String titleLowerRight,
|
||||
) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: CustomTheme.secondaryColor,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 10,
|
||||
child: Text(
|
||||
'$titleOneUpperLeft $titleTwoUpperLeft',
|
||||
style: const TextStyle(fontSize: 20),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Text(
|
||||
titleUpperRight,
|
||||
style: const TextStyle(fontSize: 20),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.end,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 10,
|
||||
child: Text(
|
||||
titleLowerLeft,
|
||||
style: const TextStyle(fontSize: 20),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: Text(
|
||||
titleLowerRight,
|
||||
style: const TextStyle(fontSize: 20),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.end,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
191
lib/presentation/widgets/tiles/game_history_tile.dart
Normal file
@@ -0,0 +1,191 @@
|
||||
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/presentation/widgets/tiles/text_icon_tile.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
sneeex marked this conversation as resolved
sneeex
commented
Wofür intl? Wofür intl?
gelbeinhalb
commented
Zur berechnung vom datum :) idk ob das der optimalste weg ist Zur berechnung vom datum :) idk ob das der optimalste weg ist
sneeex
commented
Aber nutzt du da nicht nur datetime? Aber nutzt du da nicht nur datetime?
gelbeinhalb
commented
Die Die `DateFormat` klasse kommt daher:
```dart
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);
}
}
```
|
||||
|
||||
class GameHistoryTile extends StatefulWidget {
|
||||
|
gelbeinhalb marked this conversation as resolved
flixcoo
commented
(Code-Zeile ist falsch, weil die Datei wird nicht angezeigt) (Code-Zeile ist falsch, weil die Datei wird nicht angezeigt) `doubleRowInfoTile` entfernen, wird nicht mehr genutzt
gelbeinhalb
commented
check ich nicht. wo wird das denn verwendet? check ich nicht. wo wird das denn verwendet?
flixcoo
commented
Nirgendwo, deswegen kann es ja weg. Wurde vorher in Nirgendwo, deswegen kann es ja weg. Wurde vorher in `GameHistoryView` verwendet
gelbeinhalb
commented
nirgendwo in meinem code steht nirgendwo in meinem code steht `doubleRowInfoTile` 😭 oder ich bin blöd und finde es nicht
|
||||
final Game game;
|
||||
|
||||
const GameHistoryTile({
|
||||
super.key,
|
||||
required this.game,
|
||||
});
|
||||
|
||||
@override
|
||||
State<GameHistoryTile> createState() => _GameHistoryTileState();
|
||||
}
|
||||
|
||||
class _GameHistoryTileState extends State<GameHistoryTile> {
|
||||
|
||||
|
gelbeinhalb marked this conversation as resolved
Outdated
flixcoo
commented
Funktionen eines Widgets immer nach der Funktionen eines Widgets immer nach der `build()` Methode, diese soll in einem Widget immer als erstes kommen (nach den Variabel-Deklarationen)
gelbeinhalb
commented
👍 👍
|
||||
@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(
|
||||
|
gelbeinhalb marked this conversation as resolved
flixcoo
commented
Hier auch hinter Hier auch hinter `buid()` Methode schieben
gelbeinhalb
commented
👍 👍
|
||||
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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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,
|
||||
),
|
||||
|
gelbeinhalb marked this conversation as resolved
Outdated
flixcoo
commented
Entweder die beiden Group Widgets in ein Entweder die beiden Group Widgets in ein `Visibility` bzw `Offstage` Widget wrappen, oder in ein If-Statement zusammenführen:
```dart
if(group != null)
[...SizedBox(), Row()]
```
sneeex
commented
Von Docs: "Offstage can be used to measure the dimensions of a widget without bringing it on screen (yet). To hide a widget from view while it is not needed, prefer removing the widget from the tree entirely rather than keeping it alive in an Offstage subtree" also eher das if Von Docs: "Offstage can be used to measure the dimensions of a widget without bringing it on screen (yet). To hide a widget from view while it is not needed, prefer removing the widget from the tree entirely rather than keeping it alive in an Offstage subtree" also eher das if
flixcoo
commented
Ja dann mach das lieber mit If Ja dann mach das lieber mit If
|
||||
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: 12),
|
||||
],
|
||||
|
||||
if (allPlayers.isNotEmpty) ...[
|
||||
const Text(
|
||||
'Players',
|
||||
|
gelbeinhalb marked this conversation as resolved
Outdated
flixcoo
commented
Ggf. ohne Doppelpunkt? Da dass ja nur so ne Zwischenüberschrift ist und die Spielernamen ja nicht dahinter in der gleichen Zeile stehen Ggf. ohne Doppelpunkt? Da dass ja nur so ne Zwischenüberschrift ist und die Spielernamen ja nicht dahinter in der gleichen Zeile stehen
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.grey,
|
||||
|
gelbeinhalb marked this conversation as resolved
flixcoo
commented
Hier auch zusammenfassen oder Hier auch zusammenfassen oder `Visibility` bzw. `Offstage` Widget nutzen
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Wrap(
|
||||
spacing: 6,
|
||||
runSpacing: 6,
|
||||
children: allPlayers.map((player) {
|
||||
return TextIconTile(
|
||||
text: player.name,
|
||||
iconEnabled: false,
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
gelbeinhalb marked this conversation as resolved
Outdated
sneeex
commented
renderoverflow bei langen namen renderoverflow bei langen namen
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
gelbeinhalb marked this conversation as resolved
Outdated
sneeex
commented
is winenr wird nicht genutzt is winenr wird nicht genutzt
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,6 +24,7 @@ dependencies:
|
||||
json_schema: ^5.2.2
|
||||
file_saver: ^0.3.1
|
||||
clock: ^1.1.2
|
||||
intl: ^0.18.0
|
||||
|
sneeex marked this conversation as resolved
sneeex
commented
Wofür intl? Wofür intl?
gelbeinhalb
commented
siehe #20 (comment) siehe https://git.yannick-weigert.de/liquid-development/game-tracker/pulls/20#issuecomment-1170
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
Umbennenung zu
GameViewstand mal im Raum oder?Ist nicht ein GameView das was sich öffnet wenn man auf ein Game klickt?
@mathiskir hat die jetzt
GameResultViewgenannt, aber quatsch ihr euch da sonst nochmal abIch finde wir sollten beides von
Game....ViewinMatch...Viewumbenennen.Game = Das Spiel (Brettspiel, Kartenspiel)
Match = Eine Partie des Spiels
@flixcoo @mathiskir
Ja fand ich glaub ich sinnvoll. Dann müssten wir aber auch die entsprechenden Klassen umbenennen. Ich würde vorschlagen dass gesammelt in einem Ticket zu machen und deins so zu mergen
Ja würde ich auch sagen, weil dann ja sogar die Datenbank implementation geändert werden muss noch. Und auch unsere test json
ja, lass das hier erstmal rauslassen