diff --git a/README.md b/README.md
index 683115d..7821497 100644
--- a/README.md
+++ b/README.md
@@ -20,3 +20,15 @@ By default, a test account is created with administrator permissions with the fo
Username `test@gmail.com`
Password `hunter2`
+
+# Contributing
+
+Please make sure all tests pass before submitting a new pull request.
+
+## Adding a Migration
+
+New migrations can be added to the database by:
+
+1. Installing the dotnet ef tools via `dotnet tool install --global dotnet-ef`
+2. Running the following command with a command line while inside the `/src/Server` folder
+ `dotnet ef migrations add {YourMigrationName} -o ./Infrastructure/Migrations --context ApplicationDbContext --project DynamoLeagueBlazor.Server.csproj
\ No newline at end of file
diff --git a/src/Client/Features/Admin/StartSeason.razor b/src/Client/Features/Admin/StartSeason.razor
index b8e38dc..c327103 100644
--- a/src/Client/Features/Admin/StartSeason.razor
+++ b/src/Client/Features/Admin/StartSeason.razor
@@ -5,7 +5,16 @@
- Clicking the below button will begin a new season - all players who are eligble to be free agents will be set to a free agent status. Proceed with caution.
+ Clicking the below button will begin a new season. Beginning a new season includes
+
+
+ -
+ - All players who are eligble to be free agents will be set to a free agent status.
+
+ -
+ - All fines for the previous year will be removed.
+
+
diff --git a/src/Client/Features/Dashboard/Dashboard.razor b/src/Client/Features/Dashboard/Dashboard.razor
index 73e9b48..c89cdf5 100644
--- a/src/Client/Features/Dashboard/Dashboard.razor
+++ b/src/Client/Features/Dashboard/Dashboard.razor
@@ -1,5 +1,4 @@
@page "/"
-@using DynamoLeagueBlazor.Client.Features.Dashboard.TopOffenders
@_title
@@ -9,4 +8,7 @@
+
+
+
\ No newline at end of file
diff --git a/src/Client/Features/Dashboard/Shared/RankedCard.razor b/src/Client/Features/Dashboard/Shared/RankedCard.razor
new file mode 100644
index 0000000..5c806e1
--- /dev/null
+++ b/src/Client/Features/Dashboard/Shared/RankedCard.razor
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+ @RankedItem.Name
+
+
+ @RankedItem.Amount
+
+
+
+
+@code {
+ [Parameter, EditorRequired] public IRankedItem RankedItem { get; set; } = null!;
+ [Parameter, EditorRequired] public Typo NameTypo { get; set; }
+ [Parameter, EditorRequired] public Typo AmountTypo { get; set; }
+ [Parameter] public string? BackgroundColor { get; set; }
+}
diff --git a/src/Client/Features/Dashboard/Shared/RankedList.razor b/src/Client/Features/Dashboard/Shared/RankedList.razor
new file mode 100644
index 0000000..de0419b
--- /dev/null
+++ b/src/Client/Features/Dashboard/Shared/RankedList.razor
@@ -0,0 +1,30 @@
+@if(RankedItems.Count() > 2)
+{
+
+ @{
+ var first =RankedItems.First();
+ var second = RankedItems.Skip(1).First();
+ var third = RankedItems.Skip(2).First();
+ }
+
+
+
+
+ @foreach(var rankedItem in RankedItems.Skip(3))
+ {
+
+
+
+ }
+}
+else
+{
+
+ @NotEnoughItemsContent
+
+}
+
+@code {
+ [Parameter] public IEnumerable RankedItems { get; set; } = Array.Empty();
+ [Parameter, EditorRequired] public RenderFragment NotEnoughItemsContent { get; set; } = null!;
+}
diff --git a/src/Client/Features/Dashboard/TopOffenders.razor b/src/Client/Features/Dashboard/TopOffenders.razor
new file mode 100644
index 0000000..79649f9
--- /dev/null
+++ b/src/Client/Features/Dashboard/TopOffenders.razor
@@ -0,0 +1,38 @@
+@if(_result is null)
+{
+
+ @for(int i = 0; i < 3; i++)
+ {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+}
+else
+{
+
+
+
+ Top Offenders
+
+
+
+
+
+ There aren't enough players with fines quite yet. Check back later!
+
+
+
+}
\ No newline at end of file
diff --git a/src/Client/Features/Dashboard/TopOffenders/TopOffenders.razor.cs b/src/Client/Features/Dashboard/TopOffenders.razor.cs
similarity index 92%
rename from src/Client/Features/Dashboard/TopOffenders/TopOffenders.razor.cs
rename to src/Client/Features/Dashboard/TopOffenders.razor.cs
index 14e5d1b..9043ea2 100644
--- a/src/Client/Features/Dashboard/TopOffenders/TopOffenders.razor.cs
+++ b/src/Client/Features/Dashboard/TopOffenders.razor.cs
@@ -3,7 +3,7 @@
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System.Net.Http.Json;
-namespace DynamoLeagueBlazor.Client.Features.Dashboard.TopOffenders;
+namespace DynamoLeagueBlazor.Client.Features.Dashboard;
public sealed partial class TopOffenders : IDisposable
{
diff --git a/src/Client/Features/Dashboard/TopOffenders/PlayerCard.razor b/src/Client/Features/Dashboard/TopOffenders/PlayerCard.razor
deleted file mode 100644
index 128051f..0000000
--- a/src/Client/Features/Dashboard/TopOffenders/PlayerCard.razor
+++ /dev/null
@@ -1,22 +0,0 @@
-@using static DynamoLeagueBlazor.Shared.Features.Dashboard.TopOffendersResult
-
-
-
-
-
-
-
- @Player.Name
-
-
- @Player.TotalFineAmount
-
-
-
-
-@code {
- [Parameter, EditorRequired] public PlayerItem Player { get; set; } = null!;
- [Parameter, EditorRequired] public Typo NameTypo { get; set; }
- [Parameter, EditorRequired] public Typo FineAmountTypo { get; set; }
- [Parameter] public string? BackgroundColor { get; set; }
-}
diff --git a/src/Client/Features/Dashboard/TopOffenders/TopOffenders.razor b/src/Client/Features/Dashboard/TopOffenders/TopOffenders.razor
deleted file mode 100644
index 027db93..0000000
--- a/src/Client/Features/Dashboard/TopOffenders/TopOffenders.razor
+++ /dev/null
@@ -1,58 +0,0 @@
-@if(_result is null)
-{
-
- @for(int i = 0; i < 3; i++)
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
-}
-else
-{
-
-
-
- Top Offenders
-
-
-
- @if(_result.Players.Count() > 2)
- {
-
- @{
- var firstPlayer = _result.Players.First();
- var secondPlayer = _result.Players.Skip(1).First();
- var thirdPlayer = _result.Players.Skip(2).First();
- }
-
-
-
-
- @foreach(var player in _result.Players.Skip(3))
- {
-
-
-
- }
- }
- else
- {
-
- There aren't enough players with fines quite yet. Check back later!
-
- }
-
-}
diff --git a/src/Client/Features/Dashboard/TopTeamFines.razor b/src/Client/Features/Dashboard/TopTeamFines.razor
new file mode 100644
index 0000000..cfb4c88
--- /dev/null
+++ b/src/Client/Features/Dashboard/TopTeamFines.razor
@@ -0,0 +1,38 @@
+@if(_result is null)
+{
+
+ @for(int i = 0; i < 3; i++)
+ {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+}
+else
+{
+
+
+
+ Top Team Fines
+
+
+
+
+
+ There aren't enough teams with fines quite yet. Check back later!
+
+
+
+}
\ No newline at end of file
diff --git a/src/Client/Features/Dashboard/TopTeamFines.razor.cs b/src/Client/Features/Dashboard/TopTeamFines.razor.cs
new file mode 100644
index 0000000..87fbe7d
--- /dev/null
+++ b/src/Client/Features/Dashboard/TopTeamFines.razor.cs
@@ -0,0 +1,32 @@
+using DynamoLeagueBlazor.Shared.Features.Dashboard;
+using Microsoft.AspNetCore.Components;
+using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
+using System.Net.Http.Json;
+
+namespace DynamoLeagueBlazor.Client.Features.Dashboard;
+
+public sealed partial class TopTeamFines : IDisposable
+{
+ [Inject] private HttpClient HttpClient { get; set; } = null!;
+
+ private TopTeamFinesResult? _result;
+ private readonly CancellationTokenSource _cts = new();
+
+ protected override async Task OnInitializedAsync()
+ {
+ try
+ {
+ _result = await HttpClient.GetFromJsonAsync(TopTeamFinesRouteFactory.Uri, _cts.Token);
+ }
+ catch (AccessTokenNotAvailableException exception)
+ {
+ exception.Redirect();
+ }
+ }
+
+ public void Dispose()
+ {
+ _cts.Cancel();
+ _cts.Dispose();
+ }
+}
\ No newline at end of file
diff --git a/src/Client/Features/Dashboard/_Imports.razor b/src/Client/Features/Dashboard/_Imports.razor
new file mode 100644
index 0000000..e1c236a
--- /dev/null
+++ b/src/Client/Features/Dashboard/_Imports.razor
@@ -0,0 +1,2 @@
+@using DynamoLeagueBlazor.Client.Features.Dashboard.Shared
+@using DynamoLeagueBlazor.Shared.Features.Dashboard.Shared
diff --git a/src/Client/Features/Fines/List.razor b/src/Client/Features/Fines/List.razor
index 4e8a218..645439f 100644
--- a/src/Client/Features/Fines/List.razor
+++ b/src/Client/Features/Fines/List.razor
@@ -21,6 +21,7 @@
Name
+ Team
Reason
Amount
Status
@@ -34,7 +35,10 @@
-
+
+
+
+
@fineItem.Reason
@fineItem.Amount
diff --git a/src/Client/Features/Fines/List.razor.cs b/src/Client/Features/Fines/List.razor.cs
index 2b15112..9f8d701 100644
--- a/src/Client/Features/Fines/List.razor.cs
+++ b/src/Client/Features/Fines/List.razor.cs
@@ -56,7 +56,11 @@ private async void OpenManageFineDialog(int fineId)
var result = await dialog.Result;
- if (!result.Cancelled) await LoadDataAsync();
+ if (!result.Cancelled)
+ {
+ await LoadDataAsync();
+ StateHasChanged();
+ }
}
public void Dispose()
diff --git a/src/Client/Features/FreeAgents/List.razor b/src/Client/Features/FreeAgents/List.razor
index b29659d..37ef0c0 100644
--- a/src/Client/Features/FreeAgents/List.razor
+++ b/src/Client/Features/FreeAgents/List.razor
@@ -36,7 +36,7 @@
-
+
@context.Position
@context.Team
diff --git a/src/Client/Features/OfferMatching/List.razor b/src/Client/Features/OfferMatching/List.razor
index ef82d9e..c162c8e 100644
--- a/src/Client/Features/OfferMatching/List.razor
+++ b/src/Client/Features/OfferMatching/List.razor
@@ -23,7 +23,7 @@
-
+
@context.Position
@context.OfferingTeam
diff --git a/src/Client/Features/Players/List.razor b/src/Client/Features/Players/List.razor
index 81215a3..7c9f801 100644
--- a/src/Client/Features/Players/List.razor
+++ b/src/Client/Features/Players/List.razor
@@ -40,7 +40,7 @@
-
+
@context.Position
@context.Team
diff --git a/src/Client/Features/Teams/List.razor b/src/Client/Features/Teams/List.razor
index 1d68b6d..e043d4a 100644
--- a/src/Client/Features/Teams/List.razor
+++ b/src/Client/Features/Teams/List.razor
@@ -41,7 +41,7 @@ else
@foreach(var team in _result.Teams)
{
var detailHref = $"/teams/{team.Id}";
-
+