Files
Shogi/Shogi.UI/Pages/Play/GameBoard/GameBoardPresentation.razor
2024-10-20 22:27:08 -05:00

174 lines
4.9 KiB
Plaintext

@using Shogi.Contracts.Types;
@using System.Text.Json;
<article class="game-board">
@if (IsSpectating)
{
<aside class="icons">
<div title="You are spectating.">
<span>Camera icon</span>
</div>
</aside>
}
<!-- Game board -->
<section class="board" data-perspective="@Perspective">
@for (var rank = 1; rank < 10; rank++)
{
foreach (var file in Files)
{
var position = $"{file}{rank}";
var piece = Session?.BoardState.Board[position];
var isSelected = piece != null && SelectedPosition == position;
<div class="tile" @onclick="OnClickTileInternal(piece, position)"
data-position="@(position)"
data-selected="@(isSelected)"
style="grid-area: @position">
@if (piece != null)
{
<GamePiece Piece="piece" Perspective="Perspective" />
}
</div>
}
}
<div class="ruler vertical" style="grid-area: rank">
<span>9</span>
<span>8</span>
<span>7</span>
<span>6</span>
<span>5</span>
<span>4</span>
<span>3</span>
<span>2</span>
<span>1</span>
</div>
<div class="ruler" style="grid-area: file">
<span>A</span>
<span>B</span>
<span>C</span>
<span>D</span>
<span>E</span>
<span>F</span>
<span>G</span>
<span>H</span>
<span>I</span>
</div>
</section>
<!-- Side board -->
@if (Session != null && UseSideboard == true)
{
<aside class="side-board PrimaryTheme ThemeVariant--Contrast">
<div class="player-area">
<div class="hand">
@if (opponentHand.Any())
{
@foreach (var piece in opponentHand)
{
<div class="tile">
<GamePiece Piece="piece" Perspective="Perspective" />
</div>
}
}
</div>
<p class="text-center">Opponent Hand</p>
</div>
<div class="place-self-center">
<PlayerName Name="@opponentName" IsTurn="!IsMyTurn" />
<hr />
<PlayerName Name="@userName" IsTurn="IsMyTurn" />
</div>
<div class="player-area">
@if (this.OnClickJoinGame != null && string.IsNullOrEmpty(Session.Player2) && !string.IsNullOrEmpty(Session.Player1))
{
<div class="place-self-center">
<button @onclick="OnClickJoinGameInternal">Join Game</button>
</div>
}
else
{
<p class="text-center">Hand</p>
<div class="hand">
@if (userHand.Any())
{
@foreach (var piece in userHand)
{
<div @onclick="OnClickHandInternal(piece)"
class="tile"
data-selected="@(piece.WhichPiece == SelectedPieceFromHand)">
<GamePiece Piece="piece" Perspective="Perspective" />
</div>
}
}
</div>
}
</div>
</aside>
}
</article>
@code {
static readonly string[] Files = new[] { "A", "B", "C", "D", "E", "F", "G", "H", "I" };
/// <summary>
/// When true, an icon is displayed indicating that the user is spectating.
/// </summary>
[Parameter] public bool IsSpectating { get; set; } = false;
[Parameter] public WhichPlayer Perspective { get; set; }
[Parameter] public Session? Session { get; set; }
[Parameter] public string? SelectedPosition { get; set; }
[Parameter] public WhichPiece? SelectedPieceFromHand { get; set; }
// TODO: Exchange these OnClick actions for events like "SelectionChangedEvent" and "MoveFromBoardEvent" and "MoveFromHandEvent".
[Parameter] public Func<Piece?, string, Task>? OnClickTile { get; set; }
[Parameter] public Func<Piece, Task>? OnClickHand { get; set; }
[Parameter] public Func<Task>? OnClickJoinGame { get; set; }
[Parameter] public bool IsMyTurn { get; set; }
[Parameter] public bool UseSideboard { get; set; } = true;
private IReadOnlyCollection<Piece> opponentHand;
private IReadOnlyCollection<Piece> userHand;
private string? userName;
private string? opponentName;
public GameBoardPresentation()
{
opponentHand = Array.Empty<Piece>();
userHand = Array.Empty<Piece>();
userName = string.Empty;
opponentName = string.Empty;
}
protected override void OnParametersSet()
{
base.OnParametersSet();
if (Session == null)
{
opponentHand = Array.Empty<Piece>();
userHand = Array.Empty<Piece>();
userName = string.Empty;
opponentName = string.Empty;
}
else
{
opponentHand = Perspective == WhichPlayer.Player1
? this.Session.BoardState.Player2Hand
: this.Session.BoardState.Player1Hand;
userHand = Perspective == WhichPlayer.Player1
? this.Session.BoardState.Player1Hand
: this.Session.BoardState.Player2Hand;
userName = Perspective == WhichPlayer.Player1
? this.Session.Player1
: this.Session.Player2 ?? "Empty Seat";
opponentName = Perspective == WhichPlayer.Player1
? this.Session.Player2 ?? "Empty Seat"
: this.Session.Player1;
}
}
private Action OnClickTileInternal(Piece? piece, string position) => () => OnClickTile?.Invoke(piece, position);
private Action OnClickHandInternal(Piece piece) => () => OnClickHand?.Invoke(piece);
private void OnClickJoinGameInternal() => OnClickJoinGame?.Invoke();
}