diff --git a/src/Client/DynamoLeagueBlazor.Client.csproj b/src/Client/DynamoLeagueBlazor.Client.csproj index 83959c3..fce0355 100644 --- a/src/Client/DynamoLeagueBlazor.Client.csproj +++ b/src/Client/DynamoLeagueBlazor.Client.csproj @@ -10,6 +10,7 @@ + diff --git a/src/Client/Features/FreeAgents/BidCountdown.razor b/src/Client/Features/FreeAgents/BidCountdown.razor new file mode 100644 index 0000000..9f3a727 --- /dev/null +++ b/src/Client/Features/FreeAgents/BidCountdown.razor @@ -0,0 +1,3 @@ + + @_remainingTime + diff --git a/src/Client/Features/FreeAgents/BidCountdown.razor.cs b/src/Client/Features/FreeAgents/BidCountdown.razor.cs new file mode 100644 index 0000000..9476198 --- /dev/null +++ b/src/Client/Features/FreeAgents/BidCountdown.razor.cs @@ -0,0 +1,43 @@ +using Humanizer; +using Humanizer.Localisation; +using Microsoft.AspNetCore.Components; +using MudBlazor; +using System.Timers; +using Timer = System.Timers.Timer; + +namespace DynamoLeagueBlazor.Client.Features.FreeAgents; + +public partial class BidCountdown +{ + [Parameter, EditorRequired] public DateTime DateTime { get; set; } + + private readonly Timer _timer = new(1000); + private string _remainingTime = string.Empty; + private Color _color = Color.Warning; + + protected override void OnInitialized() + { + _timer.Elapsed += CountDown; + _timer.Enabled = true; + } + + private void CountDown(object? source, ElapsedEventArgs e) + { + var remainingTime = DateTime - DateTime.Now; + + if (remainingTime <= TimeSpan.FromDays(1)) + { + _color = Color.Error; + + if (remainingTime <= TimeSpan.Zero) + { + _timer.Enabled = false; + remainingTime = TimeSpan.Zero; + } + } + + _remainingTime = remainingTime.Humanize(4, maxUnit: TimeUnit.Day, minUnit: TimeUnit.Second); + + InvokeAsync(StateHasChanged); + } +} diff --git a/src/Client/Features/FreeAgents/Detail.razor b/src/Client/Features/FreeAgents/Detail.razor index fd84514..e464f95 100644 --- a/src/Client/Features/FreeAgents/Detail.razor +++ b/src/Client/Features/FreeAgents/Detail.razor @@ -35,11 +35,9 @@ else @_result.Position - Bidding Ends on - - - @_result.EndOfFreeAgency + Bidding Ends In + diff --git a/src/Server/Features/FreeAgents/Detail.cs b/src/Server/Features/FreeAgents/Detail.cs index 35c5fdd..ce622f2 100644 --- a/src/Server/Features/FreeAgents/Detail.cs +++ b/src/Server/Features/FreeAgents/Detail.cs @@ -59,7 +59,7 @@ public class DetailMappingProfile : Profile public DetailMappingProfile() { CreateMap() - .ForMember(d => d.EndOfFreeAgency, mo => mo.MapFrom(s => s.EndOfFreeAgency!.Value.ToShortDateString())) + .ForMember(d => d.EndOfFreeAgency, mo => mo.MapFrom(s => s.EndOfFreeAgency!.Value)) .ForMember(d => d.Team, mo => mo.MapFrom(s => s.Team.Name)) .ForMember(d => d.Bids, mo => mo.MapFrom(s => s.Bids.OrderByDescending(b => b.CreatedOn))); CreateMap() diff --git a/src/Shared/Features/FreeAgents/Detail.cs b/src/Shared/Features/FreeAgents/Detail.cs index 7635e33..8fa983d 100644 --- a/src/Shared/Features/FreeAgents/Detail.cs +++ b/src/Shared/Features/FreeAgents/Detail.cs @@ -6,7 +6,7 @@ public class FreeAgentDetailResult public string Position { get; set; } = null!; public string HeadShotUrl { get; set; } = null!; public string Team { get; set; } = null!; - public string EndOfFreeAgency { get; set; } = null!; + public DateTime EndOfFreeAgency { get; set; } public IEnumerable Bids { get; set; } = Enumerable.Empty(); diff --git a/src/Tests/Features/FreeAgents/BidCountdownTests.cs b/src/Tests/Features/FreeAgents/BidCountdownTests.cs new file mode 100644 index 0000000..7079675 --- /dev/null +++ b/src/Tests/Features/FreeAgents/BidCountdownTests.cs @@ -0,0 +1,43 @@ +using DynamoLeagueBlazor.Client.Features.FreeAgents; + +namespace DynamoLeagueBlazor.Tests.Features.FreeAgents; + +public class BidCountdownTests : UITestBase +{ + [Fact] + public void CountsDownEverySecondUntilZero() + { + var cut = RenderComponent(parameters => + { + parameters.Add(p => p.DateTime, DateTime.Now.AddSeconds(4)); + }); + + cut.WaitForState(() => cut.Markup.Contains("1 second"), TimeSpan.FromSeconds(4)); + cut.WaitForState(() => cut.Markup.Contains("0 seconds")); + + cut.Render(); + cut.Markup.Should().Contain("0 seconds"); + } + + [Fact] + public void GivenLessThanADayAway_ThenShowsRedText() + { + var cut = RenderComponent(parameters => + { + parameters.Add(p => p.DateTime, DateTime.Now.AddSeconds(1)); + }); + + cut.Markup.Contains("mud-text-error"); + } + + [Fact] + public void GivenMoreThanADayAway_ThenShowsYellowText() + { + var cut = RenderComponent(parameters => + { + parameters.Add(p => p.DateTime, DateTime.Now.AddDays(1)); + }); + + cut.Markup.Contains("mud-text-warning"); + } +} diff --git a/src/Tests/Features/FreeAgents/DetailTests.cs b/src/Tests/Features/FreeAgents/DetailTests.cs index 185a065..f9ba51a 100644 --- a/src/Tests/Features/FreeAgents/DetailTests.cs +++ b/src/Tests/Features/FreeAgents/DetailTests.cs @@ -49,7 +49,7 @@ public async Task GivenAnyAuthenticatedUser_WhenGivenValidPlayerId_ThenReturnsEx response.Position.Should().Be(mockFreeAgent.Position); response.Team.Should().Be(mockTeam.Name); response.HeadShotUrl.Should().Be(mockFreeAgent.HeadShotUrl); - response.EndOfFreeAgency.Should().Be(mockFreeAgent.EndOfFreeAgency!.Value.ToShortDateString()); + response.EndOfFreeAgency.Should().Be(mockFreeAgent.EndOfFreeAgency!.Value); response!.Bids.Should().HaveCount(1); var bid = response.Bids.First();