MVP #141
@@ -1,37 +1,29 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:game_tracker/core/custom_theme.dart';
|
||||
import 'package:game_tracker/core/enums.dart';
|
||||
import 'package:game_tracker/presentation/widgets/tiles/ruleset_list_tile.dart';
|
||||
|
||||
class ChooseRulesetView extends StatefulWidget {
|
||||
const ChooseRulesetView({super.key});
|
||||
final List<(Ruleset, String, String)> rulesets;
|
||||
final int initialRulesetIndex;
|
||||
const ChooseRulesetView({
|
||||
super.key,
|
||||
required this.rulesets,
|
||||
required this.initialRulesetIndex,
|
||||
});
|
||||
|
||||
@override
|
||||
State<ChooseRulesetView> createState() => _ChooseRulesetViewState();
|
||||
}
|
||||
|
||||
class _ChooseRulesetViewState extends State<ChooseRulesetView> {
|
||||
List<(Ruleset, String, String)> rulesets = [
|
||||
(
|
||||
Ruleset.singleWinner,
|
||||
'Single Winner',
|
||||
'Exactly one winner is chosen; ties are resolved by a predefined tiebreaker.',
|
||||
),
|
||||
(
|
||||
Ruleset.singleLoser,
|
||||
'Single Loser',
|
||||
'Exactly one loser is determined; last place receives the penalty or consequence.',
|
||||
),
|
||||
(
|
||||
Ruleset.mostPoints,
|
||||
'Most Points',
|
||||
'Traditional ruleset: the player with the most points wins.',
|
||||
),
|
||||
(
|
||||
Ruleset.lastPoints,
|
||||
'Least Points',
|
||||
'Inverse scoring: the player with the fewest points wins.',
|
||||
),
|
||||
];
|
||||
late int selectedRulesetIndex;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
selectedRulesetIndex = widget.initialRulesetIndex;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -48,45 +40,22 @@ class _ChooseRulesetViewState extends State<ChooseRulesetView> {
|
||||
),
|
||||
body: ListView.builder(
|
||||
padding: const EdgeInsets.only(bottom: 85),
|
||||
itemCount: rulesets.length,
|
||||
itemCount: widget.rulesets.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return GestureDetector(
|
||||
onTap: () => Navigator.of(context).pop(rulesets[index].$1),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
||||
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: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
rulesets[index].$2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
rulesets[index].$3,
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
const SizedBox(height: 2.5),
|
||||
],
|
||||
),
|
||||
),
|
||||
return RulesetListTile(
|
||||
onPressed: () async {
|
||||
setState(() {
|
||||
selectedRulesetIndex = index;
|
||||
});
|
||||
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
if (!context.mounted) return;
|
||||
Navigator.of(context).pop(widget.rulesets[index].$1);
|
||||
});
|
||||
},
|
||||
title: widget.rulesets[index].$2,
|
||||
description: widget.rulesets[index].$3,
|
||||
isHighlighted: selectedRulesetIndex == index,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -28,9 +28,33 @@ class _CreateGameViewState extends State<CreateGameView> {
|
||||
Group? selectedGroup;
|
||||
int selectedGroupIndex = -1;
|
||||
Ruleset? selectedRuleset;
|
||||
int selectedRulesetIndex = -1;
|
||||
|
||||
bool isLoading = true;
|
||||
|
||||
List<(Ruleset, String, String)> rulesets = [
|
||||
(
|
||||
Ruleset.singleWinner,
|
||||
'Single Winner',
|
||||
'Exactly one winner is chosen; ties are resolved by a predefined tiebreaker.',
|
||||
),
|
||||
(
|
||||
Ruleset.singleLoser,
|
||||
'Single Loser',
|
||||
'Exactly one loser is determined; last place receives the penalty or consequence.',
|
||||
),
|
||||
(
|
||||
Ruleset.mostPoints,
|
||||
'Most Points',
|
||||
'Traditional ruleset: the player with the most points wins.',
|
||||
),
|
||||
(
|
||||
Ruleset.lastPoints,
|
||||
'Least Points',
|
||||
'Inverse scoring: the player with the fewest points wins.',
|
||||
),
|
||||
];
|
||||
|
||||
late final List<Player> skeletonData = List.filled(
|
||||
7,
|
||||
Player(name: 'Player 0'),
|
||||
@@ -90,9 +114,15 @@ class _CreateGameViewState extends State<CreateGameView> {
|
||||
onTap: () async {
|
||||
selectedRuleset = await Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const ChooseRulesetView(),
|
||||
builder: (context) => ChooseRulesetView(
|
||||
rulesets: rulesets,
|
||||
initialRulesetIndex: selectedRulesetIndex,
|
||||
),
|
||||
),
|
||||
);
|
||||
selectedRulesetIndex = rulesets.indexWhere(
|
||||
(r) => r.$1 == selectedRuleset,
|
||||
);
|
||||
setState(() {});
|
||||
},
|
||||
child: Container(
|
||||
@@ -132,7 +162,7 @@ class _CreateGameViewState extends State<CreateGameView> {
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ChooseGroupView(
|
||||
groups: groupsList,
|
||||
selectedGroupIndex: selectedGroupIndex,
|
||||
initialGroupIndex: selectedGroupIndex,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
56
lib/presentation/widgets/tiles/ruleset_list_tile.dart
Normal file
56
lib/presentation/widgets/tiles/ruleset_list_tile.dart
Normal file
@@ -0,0 +1,56 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:game_tracker/core/custom_theme.dart';
|
||||
|
||||
class RulesetListTile extends StatelessWidget {
|
||||
final String title;
|
||||
final String description;
|
||||
final VoidCallback? onPressed;
|
||||
final bool isHighlighted;
|
||||
|
||||
const RulesetListTile({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.description,
|
||||
this.onPressed,
|
||||
this.isHighlighted = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Use the callback directly so a null onPressed disables taps
|
||||
return GestureDetector(
|
||||
onTap: onPressed,
|
||||
child: AnimatedContainer(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
||||
decoration: isHighlighted
|
||||
? CustomTheme.highlightedBoxDecoration
|
||||
: CustomTheme.standardBoxDecoration,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
title,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(description, style: const TextStyle(fontSize: 14)),
|
||||
const SizedBox(height: 2.5),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user