fix ChristmaTree: Select Number Action

This commit is contained in:
beo3000 2026-01-08 18:44:37 +01:00
parent 383db346eb
commit 56f3e63046
3 changed files with 133 additions and 4 deletions

View File

@ -453,7 +453,21 @@ public class ChristmasTreeGameLogicService : IGameLogicService
Icon = "TouchApp",
Color = "Primary",
Tooltip = $"Wähle eine Zahl zum Streichen: {string.Join(", ", availableNumbers)}",
Order = 1
Order = 1,
Parameters =
[
new ActionParameterDefinition
{
Key = "number",
Label = "Wähle eine Zahl",
Type = "select",
Options = availableNumbers.Select(n => new ActionParameterOption
{
Value = n,
Label = n.ToString()
}).ToList()
}
]
}
];
}

View File

@ -39,6 +39,53 @@ public record GameActionDescriptor
/// Display order for sorting (lower = first).
/// </summary>
public int Order { get; init; } = 100;
/// <summary>
/// Parameter definitions if action requires user input.
/// </summary>
public IReadOnlyList<ActionParameterDefinition>? Parameters { get; init; }
}
/// <summary>
/// Defines a parameter that must be collected from the user before executing an action.
/// </summary>
public record ActionParameterDefinition
{
/// <summary>
/// Parameter key (used in the parameters dictionary).
/// </summary>
public required string Key { get; init; }
/// <summary>
/// Display label for the parameter.
/// </summary>
public required string Label { get; init; }
/// <summary>
/// Parameter type: "select" for dropdown, "number" for numeric input.
/// </summary>
public string Type { get; init; } = "select";
/// <summary>
/// Available options for "select" type.
/// </summary>
public IReadOnlyList<ActionParameterOption>? Options { get; init; }
}
/// <summary>
/// An option for a select-type parameter.
/// </summary>
public record ActionParameterOption
{
/// <summary>
/// The value to use when this option is selected.
/// </summary>
public required object Value { get; init; }
/// <summary>
/// Display label for the option.
/// </summary>
public required string Label { get; init; }
}
/// <summary>

View File

@ -17,7 +17,7 @@
Color="@GetColor(action.Color)"
StartIcon="@GetIcon(action.Icon)"
Disabled="@(!action.IsEnabled || GameState.Value.IsSaving || GameState.Value.IsLoading)"
OnClick="@(() => ExecuteAction(action.ActionId))"
OnClick="@(() => OnActionClick(action))"
Title="@action.Tooltip"
Class="game-action-button">
@action.Label
@ -26,6 +26,40 @@
</div>
}
<MudDialog @bind-Visible="_dialogVisible" Options="_dialogOptions">
<TitleContent>
<MudText Typo="Typo.h6">@_currentAction?.Label</MudText>
</TitleContent>
<DialogContent>
@if (_currentAction?.Parameters != null)
{
@foreach (var param in _currentAction.Parameters)
{
@if (param.Type == "select" && param.Options != null)
{
<div class="parameter-select">
<MudText Typo="Typo.subtitle2" Class="mb-2">@param.Label</MudText>
<div class="d-flex flex-wrap gap-2">
@foreach (var option in param.Options)
{
<MudButton Variant="Variant.Outlined"
Color="Color.Primary"
OnClick="@(() => SelectOption(param.Key, option.Value))"
Class="parameter-option-button">
@option.Label
</MudButton>
}
</div>
</div>
}
}
}
</DialogContent>
<DialogActions>
<MudButton OnClick="CloseDialog">Abbrechen</MudButton>
</DialogActions>
</MudDialog>
<style>
.game-action-panel {
display: flex;
@ -40,10 +74,21 @@
.game-action-button {
min-width: 120px;
}
.parameter-select {
margin-bottom: 16px;
}
.parameter-option-button {
min-width: 60px;
}
</style>
@code {
private IReadOnlyList<GameActionDescriptor> _availableActions = [];
private bool _dialogVisible;
private GameActionDescriptor? _currentAction;
private readonly DialogOptions _dialogOptions = new() { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Small };
protected override void OnInitialized()
{
@ -81,9 +126,32 @@
}
}
private void ExecuteAction(string actionId)
private void OnActionClick(GameActionDescriptor action)
{
Dispatcher.Dispatch(new ExecuteGameActionAction(actionId));
if (action.Parameters is { Count: > 0 })
{
_currentAction = action;
_dialogVisible = true;
}
else
{
Dispatcher.Dispatch(new ExecuteGameActionAction(action.ActionId));
}
}
private void SelectOption(string paramKey, object value)
{
if (_currentAction == null) return;
var parameters = new Dictionary<string, object> { [paramKey] = value };
Dispatcher.Dispatch(new ExecuteGameActionAction(_currentAction.ActionId, parameters));
CloseDialog();
}
private void CloseDialog()
{
_dialogVisible = false;
_currentAction = null;
}
private static Color GetColor(string colorName) => colorName switch