Ui/PlacementPanel.razor

UI component for the placement panel. Displays contextual information, validation status, and interaction notes based on the current match phase or selected card.

@namespace CitySim
@using CitySim.DesignSystem
@using CitySim.Punchboard
@inherits MatchPanel

<root class="placement"><PlotterSurface Title=@(GameText.Get("ui.placement_panel.placement"))><ChildContent>
@if (City.Match?.Phase == CitySim.Match.MatchPhase.Bid) { <div class="placement-heading">@(GameText.Get("ui.placement_panel.build_after_the_market"))</div><div class="placement-note">@(GameText.Get("ui.placement_panel.keep_unplayed_cards_for_later_rounds"))</div> }
else if (City.RenovationArmed) {
<div class="placement-heading">@(GameText.Get("ui.placement_panel.renovation", City.RenovationReplacement?.Name ?? GameText.Get("ui.placement_panel.choose_a_building")))</div>
<div class="@(City.Player.HoveredValid ? "placement-valid" : "placement-invalid")">@(City.Player.HoveredValid ? $"✓{VpText}" : $"⊘ {GameText.Plain(City.Player.HoveredReason)}")</div>
@foreach (var interaction in City.Player.Interactions) { <div class="interaction-note">@(GameText.Plain(interaction.Detail))</div> }
<div class="placement-note">@(GameText.Get("ui.placement_panel.choose_one_of_your_buildings"))</div> }
else if (City.SelectedCard is { } card) {
<div class="placement-heading">@(GameText.Get("ui.placement_panel.selected", card.Name))</div>
<div class="@(City.Player.HoveredValid ? "placement-valid" : "placement-invalid")">@(City.Player.HoveredValid ? City.SelectedCardId == "land-claim" ? GameText.Get("ui.placement_panel.reserve_until_next_round") : $"✓{VpText}" : $"⊘ {GameText.Plain(City.Player.HoveredReason)}")</div>
@foreach (var interaction in City.Player.Interactions) { <div class="interaction-note">@(GameText.Plain(interaction.Detail))</div> }
<div class="placement-note"><CardRuleContent City=@City [email protected] /></div>
<div class="placement-note">@(card.Id == "street" ? GameText.Get("ui.placement_panel.must_touch_a_road_or_the_board_edge") : card.NeedsRoad ? GameText.Get("ui.placement_panel.must_touch_a_road") : GameText.Get("ui.placement_panel.no_road_needed"))</div> }
else { <div class="placement-note">@(GameText.Get("ui.placement_panel.select_a_card_to_build"))</div> }
</ChildContent></PlotterSurface></root>

@code {
	string VpText => City.Player.HoveredGain == 0 ? "" : GameText.Get("ui.placement_panel.vp", City.Player.HoveredGain);
	protected override void Subscribe() { if (City?.Player != null) City.Player.PreviewChanged += Refresh; if (City != null) City.UiChanged += Refresh; }
	protected override void Unsubscribe() { if (City?.Player != null) City.Player.PreviewChanged -= Refresh; if (City != null) City.UiChanged -= Refresh; }
}