UI/DailyTrophyStandingsPanel.razor
@using Sandbox
@using Sandbox.UI
@using System
@using System.Linq
@inherits Panel
@namespace BlockParty
@attribute [StyleSheet( "MedalStandingsPanel.razor.scss" )]
<root class="daily-trophies @(Expanded ? "expanded" : "")">
<PixelTooltip @ref="TooltipLayer"></PixelTooltip>
@if ( Expanded )
{
<div class="shade" onclick=@Close></div>
}
@if ( !HasLetterbox && !Expanded )
{
<button class="compact-trigger" onclick=@Open>TROPHIES</button>
}
else
{
<div class="@(Expanded ? "standings-content" : "standings-rail")" style=@CardStyle>
<div class="medal-card trophy-card">
<div class="heading">
<label class="title">@(Expanded ? "TROPHIES" : "TROPHIES")</label>
@if ( Expanded )
{
<button class="square-btn i-close close" onclick=@Close><div class="img"></div></button>
}
</div>
@if ( Current is null )
{
<label class="notice">@(DailyTrophyStandings.Notice ?? "Loading trophies...")</label>
}
else if ( Current.Players.Count == 0 )
{
<label class="notice empty-medals">No trophies earned yet.</label>
}
else
{
<div class="columns">
<div class="column-spacer"></div>
<div class="medal"><TrophyIcon Place=@(1) OnHover=@Tip( AwardPoints.Tip( 1 ) ) Size=@(Expanded ? 44 : 32)></TrophyIcon></div>
<div class="medal"><TrophyIcon Place=@(2) OnHover=@Tip( AwardPoints.Tip( 2 ) ) Size=@(Expanded ? 44 : 32)></TrophyIcon></div>
<div class="medal"><TrophyIcon Place=@(3) OnHover=@Tip( AwardPoints.Tip( 3 ) ) Size=@(Expanded ? 44 : 32)></TrophyIcon></div>
@if ( Expanded ) { <div class="points"></div> }
</div>
<div class="medal-list">
@foreach ( var player in Current.Players.Take( Expanded ? Current.Players.Count : 5 ) )
{
<div class="medal-row @(player.AccountId == (long)Game.SteamId ? "you" : "")">
<label class="rank">@player.Rank</label>
<SteamAvatar [email protected] Size=@(Expanded ? 36 : 28)></SteamAvatar>
<LiteralLabel class="name" [email protected] />
<label class="medal gold @(player.Gold == 0 ? "zero" : "")">@player.Gold</label>
<label class="medal silver @(player.Silver == 0 ? "zero" : "")">@player.Silver</label>
<label class="medal bronze @(player.Bronze == 0 ? "zero" : "")">@player.Bronze</label>
@if ( Expanded ) { <label class="points" onmouseover=@Tip( "Total points" )>@player.Points</label> }
</div>
}
</div>
@if ( !Expanded && Current.Players.Skip( 5 ).FirstOrDefault( player => player.AccountId == (long)Game.SteamId ) is DailyTrophyPlayer me )
{
<div class="medal-row you personal">
<label class="rank">@me.Rank</label><label class="name">YOU</label>
<label class="medal gold @(me.Gold == 0 ? "zero" : "")">@me.Gold</label>
<label class="medal silver @(me.Silver == 0 ? "zero" : "")">@me.Silver</label>
<label class="medal bronze @(me.Bronze == 0 ? "zero" : "")">@me.Bronze</label>
</div>
}
}
@if ( Expanded && Current is not null )
{
<label class="freshness">@Freshness</label>
<label class="freshness">Latest day: @DailyChallenge.DisplayDate( Current.ThroughDay )</label>
@if ( DailyTrophyStandings.Notice is string notice )
{
<label class="freshness">@notice</label>
}
}
@if ( Current?.DaysPending > 0 )
{
<label class="freshness">@Current.DaysPending @(Current.DaysPending == 1 ? "day" : "days") pending</label>
}
@if ( !Expanded )
{
<button class="view-all" onclick=@Open>VIEW MORE</button>
}
</div>
</div>
}
</root>
@code
{
// Keep the tooltip outside the scrolling rows so it cannot be clipped.
private PixelTooltip TooltipLayer { get; set; }
private Panel _tipPanel;
private string _tipText;
private Action<PanelEvent> Tip( string text ) => e => { _tipPanel = e.This; _tipText = text; };
private void UpdateTooltip()
{
if ( _tipPanel.IsValid() && _tipPanel.HasHovered ) TooltipLayer?.Show( _tipText );
else TooltipLayer?.Hide();
}
public bool Expanded { get; private set; }
private DailyTrophySnapshot Current => DailyTrophyStandings.Current;
public override void OnMouseWheel( Vector2 value ) { }
private float ViewWidth => 1080f * Screen.Width / Math.Max( 1f, Screen.Height );
private float LetterboxWidth => (ViewWidth - 1080f) * 0.5f;
private bool HasLetterbox => LetterboxWidth >= 320f;
private double AgeMinutes => Current is null ? 0 : Math.Max( 0, (DateTimeOffset.UtcNow - Current.UpdatedAt).TotalMinutes );
private string Freshness => $"Updated {(AgeMinutes < 1 ? "just now" : AgeMinutes < 60 ? $"{(int)AgeMinutes}m ago" : $"{(int)(AgeMinutes / 60)}h ago")}";
private string CardStyle => Expanded
? $"width:{Px( Math.Min( 820f, ViewWidth - 64f ) )};"
: $"width:{Px( Math.Min( 360f, LetterboxWidth - 40f ) )};right:{Px( (LetterboxWidth - Math.Min( 360f, LetterboxWidth - 40f )) * 0.5f )};";
private static string Px( float value ) => value.ToString( "0.###", System.Globalization.CultureInfo.InvariantCulture ) + "px";
private void Open() { Expanded = true; StateHasChanged(); }
public void Close() { Expanded = false; StateHasChanged(); }
public override void Tick() { UpdateTooltip(); DailyTrophyStandings.Tick(); }
protected override int BuildHash() => HashCode.Combine( Expanded, DailyTrophyStandings.Revision, (int)ViewWidth, (int)AgeMinutes );
}