inial impl
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
@namespace Faraon.Client.Components
|
||||
|
||||
<div class="player-hand-container">
|
||||
@if (SelectedCards.Count > 0 && IsMyTurn)
|
||||
{
|
||||
var firstSelected = SelectedCards[0];
|
||||
var lastSelected = SelectedCards[SelectedCards.Count - 1];
|
||||
var matchingHandCards = Player.Hand.Where(c => c.Rank == firstSelected.Rank).ToList();
|
||||
var canPlayCombo = CanPlayCards(SelectedCards);
|
||||
|
||||
<div class="hand-combo-action-bar animate-pop">
|
||||
<!-- Poradie vykladania kariet -->
|
||||
<div class="combo-sequence-container">
|
||||
<span class="combo-seq-label">Poradie:</span>
|
||||
<div class="combo-sequence-items">
|
||||
@for (int s = 0; s < SelectedCards.Count; s++)
|
||||
{
|
||||
var sc = SelectedCards[s];
|
||||
var isFinal = (s == SelectedCards.Count - 1 && SelectedCards.Count > 1);
|
||||
<span class="combo-seq-item @(isFinal ? "combo-seq-final" : "")" style="color: @sc.SuitColor;">
|
||||
<span class="seq-num">@(s + 1).</span>
|
||||
<span class="seq-symbol">@sc.SuitSymbol</span>
|
||||
<span class="seq-suit">@sc.SuitName</span>
|
||||
@if (isFinal)
|
||||
{
|
||||
<span class="seq-crown" title="Karta ostane na vrchu odhadzovacieho balíčka">👑</span>
|
||||
}
|
||||
</span>
|
||||
@if (s < SelectedCards.Count - 1)
|
||||
{
|
||||
<span class="combo-seq-arrow">➔</span>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tlačidlo na zahranie vybratých kariet -->
|
||||
@if (canPlayCombo)
|
||||
{
|
||||
<button class="btn btn-gold btn-combo-play" @onclick="PlaySelected">
|
||||
<span>⚡ Zahrať (@SelectedCards.Count @(SelectedCards.Count == 1 ? "kartu" : (SelectedCards.Count < 5 ? "karty" : "kariet")))</span>
|
||||
</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="combo-invalid-badge">
|
||||
<span>Nemožno zahrať na stôl</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Možnosť otočiť poradie kariet -->
|
||||
@if (SelectedCards.Count > 1)
|
||||
{
|
||||
<button class="btn btn-dark btn-combo-reverse" @onclick="ReverseSelectionOrder" title="Otočiť poradie kariet (zmení vrchnú kartu na stole)">
|
||||
<span>⇄ Otočiť</span>
|
||||
</button>
|
||||
}
|
||||
|
||||
<!-- Vybrať všetky karty danej hodnoty -->
|
||||
@if (matchingHandCards.Count > SelectedCards.Count)
|
||||
{
|
||||
<button class="btn btn-dark btn-combo-all" @onclick="SelectAllOfRank" title="Pridať všetky zostávajúce karty tejto hodnoty">
|
||||
<span>+ Všetky (@matchingHandCards.Count)</span>
|
||||
</button>
|
||||
}
|
||||
|
||||
<!-- Zrušenie výberu -->
|
||||
<button class="btn btn-dark btn-combo-clear" @onclick="ClearSelection" title="Zrušiť výber">
|
||||
<span>✕</span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="player-hand-fanning">
|
||||
@for (int i = 0; i < Player.Hand.Count; i++)
|
||||
{
|
||||
var card = Player.Hand[i];
|
||||
var selectedIdx = SelectedCards.IndexOf(card);
|
||||
var isSelected = selectedIdx >= 0;
|
||||
var isPlayable = IsMyTurn && (CanPlayCard(card) || (SelectedCards.Count > 0 && SelectedCards[0].Rank == card.Rank && CanPlayCards(new List<Card> { card })));
|
||||
|
||||
// Výpočet vejárovitého natočenia kariet v ruke
|
||||
int total = Player.Hand.Count;
|
||||
double mid = (total - 1) / 2.0;
|
||||
double offset = i - mid;
|
||||
double angle = total > 1 ? offset * (Math.Min(35.0 / total, 5.5)) : 0;
|
||||
double yOffset = Math.Abs(offset) * 4.0;
|
||||
double xOffset = offset * (total > 8 ? 26 : 38);
|
||||
|
||||
string fanSlotStyle = $"transform: translateX({xOffset}px) translateY({yOffset}px) rotate({angle}deg); z-index: {(isSelected ? 120 + i : i + 1)};";
|
||||
string selectedClass = isSelected ? "card-selected-combo" : "";
|
||||
|
||||
<div class="hand-card-slot" style="@fanSlotStyle">
|
||||
<CardView Card="card"
|
||||
Deck="@Deck"
|
||||
IsInteractive="@IsMyTurn"
|
||||
IsPlayable="@isPlayable"
|
||||
CustomClass="@selectedClass"
|
||||
OnCardClicked="HandleCardClick" />
|
||||
|
||||
@if (isSelected)
|
||||
{
|
||||
var orderNum = selectedIdx + 1;
|
||||
var isTopCard = (selectedIdx == SelectedCards.Count - 1 && SelectedCards.Count > 1);
|
||||
<div class="card-order-badge @(isTopCard ? "is-top-badge" : "")">
|
||||
<span class="order-number">@orderNum.</span>
|
||||
@if (isTopCard)
|
||||
{
|
||||
<span class="order-tag">👑 Vrch</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter, EditorRequired] public Player Player { get; set; } = default!;
|
||||
[Parameter] public string Deck { get; set; } = "original";
|
||||
[Parameter] public bool IsMyTurn { get; set; } = false;
|
||||
[Parameter] public Func<Card, bool> CanPlayCardFunc { get; set; } = _ => false;
|
||||
[Parameter] public Func<List<Card>, bool> CanPlayCardsFunc { get; set; } = _ => false;
|
||||
[Parameter] public EventCallback<List<Card>> OnPlayCards { get; set; }
|
||||
|
||||
private List<Card> SelectedCards = new();
|
||||
|
||||
private bool CanPlayCard(Card card) => CanPlayCardFunc(card);
|
||||
private bool CanPlayCards(List<Card> cards) => CanPlayCardsFunc(cards);
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
// Vyčistíme karty, ktoré hráč už nemá v ruke
|
||||
SelectedCards.RemoveAll(c => !Player.Hand.Contains(c));
|
||||
}
|
||||
|
||||
private async Task HandleCardClick(Card card)
|
||||
{
|
||||
if (!IsMyTurn) return;
|
||||
|
||||
var rankCount = Player.Hand.Count(c => c.Rank == card.Rank);
|
||||
|
||||
// Ak už máme vybraté karty inej hodnoty, zresetujeme výber
|
||||
if (SelectedCards.Count > 0 && SelectedCards[0].Rank != card.Rank)
|
||||
{
|
||||
SelectedCards.Clear();
|
||||
}
|
||||
|
||||
// Ak má hráč v ruke len 1 kartu danej hodnoty a žiadna nie je vybratá:
|
||||
if (rankCount == 1 && SelectedCards.Count == 0)
|
||||
{
|
||||
if (CanPlayCard(card))
|
||||
{
|
||||
await OnPlayCards.InvokeAsync(new List<Card> { card });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Ak je už karta v zozname vybratých -> odoberieme ju (deselect)
|
||||
if (SelectedCards.Contains(card))
|
||||
{
|
||||
SelectedCards.Remove(card);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pridáme na koniec zoznamu ako ďalšiu v poradí
|
||||
SelectedCards.Add(card);
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void ReverseSelectionOrder()
|
||||
{
|
||||
SelectedCards.Reverse();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void SelectAllOfRank()
|
||||
{
|
||||
if (SelectedCards.Count == 0) return;
|
||||
var rank = SelectedCards[0].Rank;
|
||||
foreach (var c in Player.Hand.Where(c => c.Rank == rank))
|
||||
{
|
||||
if (!SelectedCards.Contains(c))
|
||||
{
|
||||
SelectedCards.Add(c);
|
||||
}
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void ClearSelection()
|
||||
{
|
||||
SelectedCards.Clear();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task PlaySelected()
|
||||
{
|
||||
if (SelectedCards.Count > 0 && CanPlayCards(SelectedCards))
|
||||
{
|
||||
var cardsToPlay = new List<Card>(SelectedCards);
|
||||
SelectedCards.Clear();
|
||||
await OnPlayCards.InvokeAsync(cardsToPlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user