UI/ScoreboardRow.razor
@using Sandbox;
@using Sandbox.UI;
@inherits Panel

<root class="row player">

	@if ( Connection is not null )
	{
		var steamId = Connection.SteamId;
		var data = PlayerData.For( Connection );
		bool isMuted = SandboxVoice.IsMuted( steamId );

		<img class="avatar" src="avatar:@steamId" />
		<div class="name">@Connection.DisplayName</div>
		<div class="stat">@(data?.Kills ?? 0)</div>
		<div class="stat">@(data?.Deaths ?? 0)</div>
		<div class="stat">@(Connection.Ping.CeilToInt())</div>
		@if ( Connection != Connection.Local )
		{
			<div class="mute-btn @(isMuted ? "muted" : "")" onclick="@( () => SandboxVoice.Mute( steamId ) )">
				<i>@(isMuted ? "volume_off" : "volume_up")</i>
			</div>
		}
		else
		{
			<div class="mute-spacer"></div>
		}
	}

</root>

@code
{
    public Connection Connection { get; set; }

    public override void Tick()
    {
        if ( Connection is null ) return;
        SetClass( "me", Connection == Connection.Local );
        SetClass( "friend", new Friend( Connection.SteamId ).IsFriend );
    }

    protected override int BuildHash()
    {
        if ( Connection is null ) return 0;
        var data = PlayerData.For( Connection );
        return System.HashCode.Combine( Connection.DisplayName, data?.Kills ?? 0, data?.Deaths ?? 0, Connection.Ping );
    }

    protected override void OnRightClick( MousePanelEvent e )
    {
        if ( Connection is null ) return;

        var steamId = Connection.SteamId;
        var menu = Sandbox.MenuPanel.Open( this );

        menu.AddOption( "content_copy", "Copy Steam ID", () =>
        {
            Clipboard.SetText( steamId.ToString() );
            Notices.AddNotice( "copy_all", Color.Cyan, $"Copied {Connection.DisplayName}'s SteamID to your clipboard", 5 );
        } );

		if ( Connection != Connection.Local )
		{
			bool isMuted = SandboxVoice.IsMuted( steamId );
			menu.AddOption( isMuted ? "volume_up" : "volume_off", isMuted ? "Unmute" : "Mute", () => SandboxVoice.Mute( steamId ) );

			if ( Connection.Local?.HasPermission( "admin" ) == true )
			{
				menu.AddSpacer();
				menu.AddOption( "person_remove", "Kick", () => OpenKickConfirm( Connection ) );
				menu.AddOption( "gavel", "Ban", () => OpenBanConfirm( Connection ) );
			}
		}

		e.StopPropagation();
	}

	void OpenKickConfirm( Connection connection )
	{
		var popup = new StringQueryPopup
		{
			Title = "Kick Player",
			Prompt = $"Why do you want to kick {connection.DisplayName}?",
			ConfirmLabel = "Kick",
			OnConfirm = x =>
			{
				GameManager.RpcKickPlayer( connection, x );
			}
		};
		popup.Parent = FindPopupPanel();
	}

	void OpenBanConfirm( Connection connection )
	{
		var popup = new StringQueryPopup
		{
			Title = "Ban Player",
			Prompt = $"Why do you want to ban {connection.DisplayName}?",
			ConfirmLabel = "Ban",
			OnConfirm = x => BanSystem.RpcBanPlayer( connection, x )
		};
		popup.Parent = FindPopupPanel();
	}
}