diff --git a/internal/embedfs/web/css/output.css b/internal/embedfs/web/css/output.css index e04cc37..b856653 100644 --- a/internal/embedfs/web/css/output.css +++ b/internal/embedfs/web/css/output.css @@ -1152,6 +1152,9 @@ .py-4 { padding-block: calc(var(--spacing) * 4); } + .py-5 { + padding-block: calc(var(--spacing) * 5); + } .py-6 { padding-block: calc(var(--spacing) * 6); } @@ -2041,11 +2044,6 @@ scale: var(--tw-scale-x) var(--tw-scale-y); } } - .sm\:grid-cols-4 { - @media (width >= 40rem) { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - } .sm\:flex-row { @media (width >= 40rem) { flex-direction: row; @@ -2177,11 +2175,6 @@ grid-template-columns: repeat(3, minmax(0, 1fr)); } } - .lg\:grid-cols-8 { - @media (width >= 64rem) { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - } .lg\:items-end { @media (width >= 64rem) { align-items: flex-end; diff --git a/internal/handlers/season_league_team_detail.go b/internal/handlers/season_league_team_detail.go index 5d55c03..48e0bb3 100644 --- a/internal/handlers/season_league_team_detail.go +++ b/internal/handlers/season_league_team_detail.go @@ -35,6 +35,7 @@ func SeasonLeagueTeamDetailPage( var scheduleMap map[int]*db.FixtureSchedule var resultMap map[int]*db.FixtureResult var playerStats []*db.AggregatedPlayerStats + var leaderboard []*db.LeaderboardEntry if ok := conn.WithReadTx(s, w, r, func(ctx context.Context, tx bun.Tx) (bool, error) { var err error @@ -72,12 +73,51 @@ func SeasonLeagueTeamDetailPage( return false, errors.Wrap(err, "db.GetPlayersNotOnTeam") } + // Get all teams and all fixtures for the league to compute leaderboard + var allTeams []*db.Team + err = tx.NewSelect(). + Model(&allTeams). + Join("INNER JOIN team_participations AS tp ON tp.team_id = t.id"). + Where("tp.season_id = ? AND tp.league_id = ?", twr.Season.ID, twr.League.ID). + Scan(ctx) + if err != nil { + return false, errors.Wrap(err, "tx.NewSelect allTeams") + } + + allFixtures, err := db.GetAllocatedFixtures(ctx, tx, twr.Season.ID, twr.League.ID) + if err != nil { + return false, errors.Wrap(err, "db.GetAllocatedFixtures") + } + allFixtureIDs := make([]int, len(allFixtures)) + for i, f := range allFixtures { + allFixtureIDs[i] = f.ID + } + allResultMap, err := db.GetFinalizedResultsForFixtures(ctx, tx, allFixtureIDs) + if err != nil { + return false, errors.Wrap(err, "db.GetFinalizedResultsForFixtures allFixtures") + } + + leaderboard = db.ComputeLeaderboard(allTeams, allFixtures, allResultMap) + return true, nil }); !ok { return } - record := db.ComputeTeamRecord(teamID, fixtures, resultMap) - renderSafely(seasonsview.SeasonLeagueTeamDetailPage(twr, fixtures, available, scheduleMap, resultMap, record, playerStats), s, r, w) + // Find this team's position and record from the leaderboard + var position int + var record *db.TeamRecord + for _, entry := range leaderboard { + if entry.Team.ID == teamID { + position = entry.Position + record = entry.Record + break + } + } + if record == nil { + record = &db.TeamRecord{} + } + + renderSafely(seasonsview.SeasonLeagueTeamDetailPage(twr, fixtures, available, scheduleMap, resultMap, record, playerStats, position, len(leaderboard)), s, r, w) }) } diff --git a/internal/view/seasonsview/fixture_review_result.templ b/internal/view/seasonsview/fixture_review_result.templ index e01796b..c41e931 100644 --- a/internal/view/seasonsview/fixture_review_result.templ +++ b/internal/view/seasonsview/fixture_review_result.templ @@ -260,3 +260,20 @@ func intPtrStr(v *int) string { } return fmt.Sprint(*v) } + +func ordinal(n int) string { + suffix := "th" + if n%100 >= 11 && n%100 <= 13 { + // 11th, 12th, 13th + } else { + switch n % 10 { + case 1: + suffix = "st" + case 2: + suffix = "nd" + case 3: + suffix = "rd" + } + } + return fmt.Sprintf("%d%s", n, suffix) +} diff --git a/internal/view/seasonsview/season_league_team_detail.templ b/internal/view/seasonsview/season_league_team_detail.templ index c4420d0..3019d01 100644 --- a/internal/view/seasonsview/season_league_team_detail.templ +++ b/internal/view/seasonsview/season_league_team_detail.templ @@ -8,7 +8,7 @@ import "fmt" import "sort" import "time" -templ SeasonLeagueTeamDetailPage(twr *db.TeamWithRoster, fixtures []*db.Fixture, available []*db.Player, scheduleMap map[int]*db.FixtureSchedule, resultMap map[int]*db.FixtureResult, record *db.TeamRecord, playerStats []*db.AggregatedPlayerStats) { +templ SeasonLeagueTeamDetailPage(twr *db.TeamWithRoster, fixtures []*db.Fixture, available []*db.Player, scheduleMap map[int]*db.FixtureSchedule, resultMap map[int]*db.FixtureResult, record *db.TeamRecord, playerStats []*db.AggregatedPlayerStats, position int, totalTeams int) { {{ team := twr.Team season := twr.Season @@ -62,14 +62,48 @@ templ SeasonLeagueTeamDetailPage(twr *db.TeamWithRoster, fixtures []*db.Fixture,
No results yet.
-Match results will appear here once games are played.
-No upcoming fixtures.
-No results yet.
+Match results will appear here once games are played.
+No upcoming fixtures.
+No stats yet.
-Team statistics will appear here once games are played.
+No games played yet.
Position
+of { fmt.Sprint(totalTeams) } teams
+Points
+{ fmt.Sprint(record.Points) }
+| Player | -GP | -PP | -SC | -G | -A | -SV | -SH | -BL | -PA | + } + +} + +templ playerStatsSection(playerStats []*db.AggregatedPlayerStats) { +
|---|
| Player | +GP | +PP | +SC | +G | +A | +SV | +SH | +BL | +PA | +
|---|---|---|---|---|---|---|---|---|---|
| { ps.PlayerName } | +{ fmt.Sprint(ps.GamesPlayed) } | +{ fmt.Sprint(ps.PeriodsPlayed) } | +{ fmt.Sprint(ps.Score) } | +{ fmt.Sprint(ps.Goals) } | +{ fmt.Sprint(ps.Assists) } | +{ fmt.Sprint(ps.Saves) } | +{ fmt.Sprint(ps.Shots) } | +{ fmt.Sprint(ps.Blocks) } | +{ fmt.Sprint(ps.Passes) } |
| { ps.PlayerName } | -{ fmt.Sprint(ps.GamesPlayed) } | -{ fmt.Sprint(ps.PeriodsPlayed) } | -{ fmt.Sprint(ps.Score) } | -{ fmt.Sprint(ps.Goals) } | -{ fmt.Sprint(ps.Assists) } | -{ fmt.Sprint(ps.Saves) } | -{ fmt.Sprint(ps.Shots) } | -{ fmt.Sprint(ps.Blocks) } | -{ fmt.Sprint(ps.Passes) } | -