added ParticipantsMode.FreeToChoose:
Neue Datei erstellt: - src/Koogle.Web/Components/Game/PlayerSelectorDialog.razor - Dialog zur manuellen Spielerauswahl Geändert: - src/Koogle.Web/Components/Pages/Days/DayDetails.razor:863-891 - ShowPlayerSelector implementiert Funktionsweise: 1. Bei ParticipantsMode.FreeToChoose zeigt GameInputPanel.razor:23-32 den Button "Spieler wechseln" 2. Der neue Dialog listet alle Spieler aus Participants.PlayerIds 3. Bei DeathBox werden ausgeschiedene Spieler standardmäßig ausgeblendet (Toggle verfügbar) 4. Bei Spielerauswahl wird SetCurrentPlayerAction dispatcht Features: - Aktueller Spieler ist markiert (grün) - Ausgeschiedene Spieler sind durchgestrichen mit "Ausgeschieden"-Badge - Optional können ausgeschiedene Spieler eingeblendet werden (falls nötig) - Funktioniert mit allen Game-Typen (DeathBox, Shit, Training)
This commit is contained in:
parent
39d4629e72
commit
587b92409d
|
|
@ -23,7 +23,7 @@
|
||||||
@if (GameState.Value.Participants.Mode == ParticipantsMode.FreeToChoose)
|
@if (GameState.Value.Participants.Mode == ParticipantsMode.FreeToChoose)
|
||||||
{
|
{
|
||||||
<MudButton Variant="Variant.Outlined"
|
<MudButton Variant="Variant.Outlined"
|
||||||
Color="Color.Primary"
|
Color="Color.Warning"
|
||||||
Size="Size.Small"
|
Size="Size.Small"
|
||||||
OnClick="ShowPlayerSelector"
|
OnClick="ShowPlayerSelector"
|
||||||
StartIcon="@Icons.Material.Filled.SwapHoriz">
|
StartIcon="@Icons.Material.Filled.SwapHoriz">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
@using Koogle.Application.Games.DeathBox
|
||||||
|
@using Koogle.Domain.Enums
|
||||||
|
|
||||||
|
<MudDialog>
|
||||||
|
<TitleContent>
|
||||||
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||||
|
<MudIcon Icon="@Icons.Material.Filled.Person" />
|
||||||
|
<MudText Typo="Typo.h6">Spieler auswählen</MudText>
|
||||||
|
</MudStack>
|
||||||
|
</TitleContent>
|
||||||
|
<DialogContent>
|
||||||
|
@if (FilterByGameLogic && HasEliminatedPlayers)
|
||||||
|
{
|
||||||
|
<MudSwitch @bind-Value="_showEliminatedPlayers"
|
||||||
|
Color="Color.Secondary"
|
||||||
|
Label="Ausgeschiedene anzeigen"
|
||||||
|
Class="mb-3" />
|
||||||
|
}
|
||||||
|
|
||||||
|
<MudList T="PlayerInfo" Dense="false" Class="player-selector-list">
|
||||||
|
@foreach (var player in FilteredPlayers)
|
||||||
|
{
|
||||||
|
<MudListItem T="PlayerInfo"
|
||||||
|
Class="@GetPlayerClass(player)"
|
||||||
|
OnClick="@(() => SelectPlayer(player))"
|
||||||
|
Disabled="@(player.IsEliminated && !_showEliminatedPlayers)">
|
||||||
|
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Style="width: 100%">
|
||||||
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||||
|
<MudAvatar Size="Size.Medium"
|
||||||
|
Color="@(player.IsCurrentPlayer ? Color.Success : (player.IsEliminated ? Color.Default : Color.Primary))">
|
||||||
|
@player.Name[0]
|
||||||
|
</MudAvatar>
|
||||||
|
<MudText Style="@(player.IsEliminated ? "text-decoration: line-through; opacity: 0.6" : "")">
|
||||||
|
@player.Name
|
||||||
|
</MudText>
|
||||||
|
@if (player.IsCurrentPlayer)
|
||||||
|
{
|
||||||
|
<MudChip T="string" Size="Size.Small" Color="Color.Success" Variant="Variant.Outlined">
|
||||||
|
Aktuell
|
||||||
|
</MudChip>
|
||||||
|
}
|
||||||
|
@if (player.IsEliminated)
|
||||||
|
{
|
||||||
|
<MudChip T="string" Size="Size.Small" Color="Color.Error" Variant="Variant.Outlined">
|
||||||
|
Ausgeschieden
|
||||||
|
</MudChip>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
</MudStack>
|
||||||
|
</MudListItem>
|
||||||
|
}
|
||||||
|
</MudList>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MudButton OnClick="Cancel" Color="Color.Default">Abbrechen</MudButton>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.player-selector-list .mud-list-item {
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player-selector-list .mud-list-item:hover:not(.mud-list-item-disabled) {
|
||||||
|
background-color: var(--mud-palette-action-default-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.player-selector-list .current-player {
|
||||||
|
border: 2px solid var(--mud-palette-success);
|
||||||
|
background-color: var(--mud-palette-success-lighten);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
/// <summary>
|
||||||
|
/// Player IDs in the game (in turn order).
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public Guid[] PlayerIds { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Current player ID.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public Guid? CurrentPlayerId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Function to resolve player names by ID.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public Func<Guid, string>? PlayerNameResolver { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Game model for determining eliminated players.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public object? GameModel { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to filter by game logic (hide eliminated players by default).
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public bool FilterByGameLogic { get; set; } = true;
|
||||||
|
|
||||||
|
[CascadingParameter]
|
||||||
|
private IMudDialogInstance MudDialog { get; set; } = null!;
|
||||||
|
|
||||||
|
private bool _showEliminatedPlayers;
|
||||||
|
|
||||||
|
private record PlayerInfo(Guid Id, string Name, bool IsCurrentPlayer, bool IsEliminated);
|
||||||
|
|
||||||
|
private HashSet<Guid> EliminatedPlayerIds => GetEliminatedPlayerIds();
|
||||||
|
|
||||||
|
private bool HasEliminatedPlayers => EliminatedPlayerIds.Count > 0;
|
||||||
|
|
||||||
|
private IEnumerable<PlayerInfo> AllPlayers => PlayerIds.Select(id => new PlayerInfo(
|
||||||
|
id,
|
||||||
|
PlayerNameResolver?.Invoke(id) ?? "Unbekannt",
|
||||||
|
id == CurrentPlayerId,
|
||||||
|
EliminatedPlayerIds.Contains(id)
|
||||||
|
));
|
||||||
|
|
||||||
|
private IEnumerable<PlayerInfo> FilteredPlayers =>
|
||||||
|
FilterByGameLogic && !_showEliminatedPlayers
|
||||||
|
? AllPlayers.Where(p => !p.IsEliminated)
|
||||||
|
: AllPlayers;
|
||||||
|
|
||||||
|
private HashSet<Guid> GetEliminatedPlayerIds()
|
||||||
|
{
|
||||||
|
return GameModel switch
|
||||||
|
{
|
||||||
|
DeathBoxGameModel deathBox => deathBox.EliminatedPlayers.ToHashSet(),
|
||||||
|
_ => []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetPlayerClass(PlayerInfo player)
|
||||||
|
{
|
||||||
|
return player.IsCurrentPlayer ? "current-player" : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectPlayer(PlayerInfo player)
|
||||||
|
{
|
||||||
|
if (player.IsEliminated && !_showEliminatedPlayers)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MudDialog.Close(DialogResult.Ok(player.Id));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cancel()
|
||||||
|
{
|
||||||
|
MudDialog.Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -862,9 +862,32 @@ else
|
||||||
|
|
||||||
private async Task ShowPlayerSelector()
|
private async Task ShowPlayerSelector()
|
||||||
{
|
{
|
||||||
// TODO: Implement player selector dialog
|
if (!GameState.Value.IsGameActive) return;
|
||||||
await Task.CompletedTask;
|
|
||||||
Snackbar.Add("Spieler-Auswahl noch nicht implementiert", Severity.Info);
|
var parameters = new DialogParameters
|
||||||
|
{
|
||||||
|
{ "PlayerIds", GameState.Value.Participants.PlayerIds },
|
||||||
|
{ "CurrentPlayerId", GameState.Value.Participants.CurrentPlayerId },
|
||||||
|
{ "PlayerNameResolver", (Func<Guid, string>)GetPlayerName },
|
||||||
|
{ "GameModel", GameState.Value.GameModel },
|
||||||
|
{ "FilterByGameLogic", true }
|
||||||
|
};
|
||||||
|
|
||||||
|
var options = new DialogOptions
|
||||||
|
{
|
||||||
|
MaxWidth = MaxWidth.Small,
|
||||||
|
FullWidth = true,
|
||||||
|
CloseOnEscapeKey = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialog = await DialogService.ShowAsync<PlayerSelectorDialog>("Spieler auswählen", parameters, options);
|
||||||
|
var result = await dialog.Result;
|
||||||
|
|
||||||
|
if (result != null && !result.Canceled && result.Data is Guid selectedPlayerId)
|
||||||
|
{
|
||||||
|
Dispatcher.Dispatch(new SetCurrentPlayerAction(selectedPlayerId));
|
||||||
|
Snackbar.Add($"Spieler gewechselt zu {GetPlayerName(selectedPlayerId)}", Severity.Success);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int TimerDurationSeconds = 3;
|
private const int TimerDurationSeconds = 3;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue