Implementierung der Games #203

Merged
flixcoo merged 34 commits from feature/119-implementierung-der-games-2 into development 2026-05-09 17:13:46 +00:00
2 changed files with 168 additions and 60 deletions
Showing only changes of commit b664bcacda - Show all commits

View File

@@ -0,0 +1,151 @@
import 'package:flutter/material.dart';
import 'package:tallee/core/common.dart';
import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/core/enums.dart';
class GameTile extends StatelessWidget {
/// A list tile widget that displays a title and description, with optional highlighting and badge.
/// - [title]: The title text displayed on the tile.
/// - [description]: The description text displayed below the title.
/// - [onTap]: The callback invoked when the tile is tapped.
/// - [onLongPress]: The callback invoked when the tile is tapped.
/// - [isHighlighted]: A boolean to determine if the tile should be highlighted.
/// - [badgeText]: Optional text to display in a badge on the right side of the title.
/// - [badgeColor]: Optional color for the badge background.
const GameTile({
super.key,
required this.title,
required this.description,
this.onTap,
this.onLongPress,
this.isHighlighted = false,
this.badgeText,
this.badgeColor,
});
/// The title text displayed on the tile.
final String title;
/// The description text displayed below the title.
final String description;
/// The callback invoked when the tile is tapped.
final VoidCallback? onTap;
/// The callback invoked when the tile is long-pressed.
final VoidCallback? onLongPress;
/// A boolean to determine if the tile should be highlighted.
final bool isHighlighted;
/// Optional text to display in a badge on the right side of the title.
final String? badgeText;
/// Optional color for the badge background.
final Color? badgeColor;
@override
Widget build(BuildContext context) {
final badgeTextColor = badgeColor != null
? (badgeColor!.computeLuminance() > 0.5 ? Colors.black : Colors.white)
: Colors.white;
final gameColor = badgeColor ?? getColorFromGameColor(GameColor.orange);
return GestureDetector(
onTap: onTap,
onLongPress: onLongPress,
child: AnimatedContainer(
margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
decoration: !isHighlighted
? CustomTheme.standardBoxDecoration
: CustomTheme.highlightedBoxDecoration.copyWith(
border: Border.all(
color: gameColor.withValues(alpha: 0.9),
width: 2,
),
),
duration: const Duration(milliseconds: 200),
child: Stack(
children: [
// Gradient overlay
Positioned.fill(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
gameColor.withValues(alpha: 0.08),
gameColor.withValues(alpha: 0.02),
Colors.transparent,
],
stops: const [0.0, 0.5, 1.0],
),
),
),
),
// Content
Padding(
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
// Title
Text(
title,
overflow: TextOverflow.ellipsis,
maxLines: 1,
softWrap: false,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
// Badge
if (badgeText != null) ...[
const SizedBox(height: 5),
Container(
constraints: const BoxConstraints(maxWidth: 250),
padding: const EdgeInsets.symmetric(
vertical: 2,
horizontal: 6,
),
decoration: BoxDecoration(
color: gameColor,
borderRadius: BorderRadius.circular(4),
),
child: Text(
badgeText!,
overflow: TextOverflow.ellipsis,
maxLines: 1,
softWrap: false,
style: TextStyle(
color: badgeTextColor,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
),
],
// Description
if (description.isNotEmpty) ...[
const SizedBox(height: 10),
Text(description, style: const TextStyle(fontSize: 14)),
const SizedBox(height: 2.5),
],
],
),
),
],
),
),
);
}
}

View File

@@ -2,23 +2,17 @@ import 'package:flutter/material.dart';
import 'package:tallee/core/custom_theme.dart'; import 'package:tallee/core/custom_theme.dart';
class TitleDescriptionListTile extends StatelessWidget { class TitleDescriptionListTile extends StatelessWidget {
/// A list tile widget that displays a title and description, with optional highlighting and badge. /// A list tile widget that displays a title and description
/// - [title]: The title text displayed on the tile. /// - [title]: The title text displayed on the tile.
/// - [description]: The description text displayed below the title. /// - [description]: The description text displayed below the title.
/// - [onTap]: The callback invoked when the tile is tapped. /// - [onTap]: The callback invoked when the tile is tapped.
/// - [onLongPress]: The callback invoked when the tile is tapped.
/// - [isHighlighted]: A boolean to determine if the tile should be highlighted. /// - [isHighlighted]: A boolean to determine if the tile should be highlighted.
/// - [badgeText]: Optional text to display in a badge on the right side of the title.
/// - [badgeColor]: Optional color for the badge background.
const TitleDescriptionListTile({ const TitleDescriptionListTile({
super.key, super.key,
required this.title, required this.title,
required this.description, required this.description,
this.onTap, this.onTap,
this.onLongPress,
this.isHighlighted = false, this.isHighlighted = false,
this.badgeText,
this.badgeColor,
}); });
/// The title text displayed on the tile. /// The title text displayed on the tile.
@@ -30,23 +24,13 @@ class TitleDescriptionListTile extends StatelessWidget {
/// The callback invoked when the tile is tapped. /// The callback invoked when the tile is tapped.
final VoidCallback? onTap; final VoidCallback? onTap;
/// The callback invoked when the tile is long-pressed.
final VoidCallback? onLongPress;
/// A boolean to determine if the tile should be highlighted. /// A boolean to determine if the tile should be highlighted.
final bool isHighlighted; final bool isHighlighted;
/// Optional text to display in a badge on the right side of the title.
final String? badgeText;
/// Optional color for the badge background.
final Color? badgeColor;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GestureDetector( return GestureDetector(
onTap: onTap, onTap: onTap,
onLongPress: onLongPress,
child: AnimatedContainer( child: AnimatedContainer(
margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12), padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
@@ -57,53 +41,26 @@ class TitleDescriptionListTile extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [ children: [
Row( // Title
mainAxisAlignment: MainAxisAlignment.start, SizedBox(
crossAxisAlignment: CrossAxisAlignment.center, width: 230,
children: [ child: Text(
SizedBox( title,
width: 230, overflow: TextOverflow.ellipsis,
child: Text( maxLines: 1,
title, softWrap: false,
overflow: TextOverflow.ellipsis, style: const TextStyle(
maxLines: 1, fontWeight: FontWeight.bold,
softWrap: false, fontSize: 18,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
), ),
if (badgeText != null) ...[ ),
const Spacer(),
Container(
constraints: const BoxConstraints(maxWidth: 115),
padding: const EdgeInsets.symmetric(
vertical: 2,
horizontal: 6,
),
decoration: BoxDecoration(
color: badgeColor ?? CustomTheme.primaryColor,
borderRadius: BorderRadius.circular(4),
),
child: Text(
badgeText!,
overflow: TextOverflow.ellipsis,
maxLines: 1,
softWrap: false,
style: const TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
),
],
],
), ),
// Description
if (description.isNotEmpty) ...[ if (description.isNotEmpty) ...[
const SizedBox(height: 5), const SizedBox(height: 10),
Text(description, style: const TextStyle(fontSize: 14)), Text(description, style: const TextStyle(fontSize: 14)),
const SizedBox(height: 2.5), const SizedBox(height: 2.5),
], ],