finals stats moved out of regular season stats
This commit is contained in:
@@ -513,6 +513,7 @@ func GetAllLeaguePlayerStats(
|
|||||||
WHERE fr.finalized = true
|
WHERE fr.finalized = true
|
||||||
AND f.season_id = ?
|
AND f.season_id = ?
|
||||||
AND f.league_id = ?
|
AND f.league_id = ?
|
||||||
|
AND f.round > 0
|
||||||
AND frps.period_num = 3
|
AND frps.period_num = 3
|
||||||
AND frps.player_id IS NOT NULL
|
AND frps.player_id IS NOT NULL
|
||||||
GROUP BY frps.player_id, COALESCE(p.name, frps.player_username)
|
GROUP BY frps.player_id, COALESCE(p.name, frps.player_username)
|
||||||
@@ -583,6 +584,7 @@ func GetTopGoalScorers(
|
|||||||
WHERE fr.finalized = true
|
WHERE fr.finalized = true
|
||||||
AND f.season_id = ?
|
AND f.season_id = ?
|
||||||
AND f.league_id = ?
|
AND f.league_id = ?
|
||||||
|
AND f.round > 0
|
||||||
AND frps.period_num = 3
|
AND frps.period_num = 3
|
||||||
AND frps.player_id IS NOT NULL
|
AND frps.player_id IS NOT NULL
|
||||||
GROUP BY frps.player_id, COALESCE(p.name, frps.player_username)
|
GROUP BY frps.player_id, COALESCE(p.name, frps.player_username)
|
||||||
@@ -655,6 +657,7 @@ func GetTopAssisters(
|
|||||||
WHERE fr.finalized = true
|
WHERE fr.finalized = true
|
||||||
AND f.season_id = ?
|
AND f.season_id = ?
|
||||||
AND f.league_id = ?
|
AND f.league_id = ?
|
||||||
|
AND f.round > 0
|
||||||
AND frps.period_num = 3
|
AND frps.period_num = 3
|
||||||
AND frps.player_id IS NOT NULL
|
AND frps.player_id IS NOT NULL
|
||||||
GROUP BY frps.player_id, COALESCE(p.name, frps.player_username)
|
GROUP BY frps.player_id, COALESCE(p.name, frps.player_username)
|
||||||
@@ -727,6 +730,7 @@ func GetTopSavers(
|
|||||||
WHERE fr.finalized = true
|
WHERE fr.finalized = true
|
||||||
AND f.season_id = ?
|
AND f.season_id = ?
|
||||||
AND f.league_id = ?
|
AND f.league_id = ?
|
||||||
|
AND f.round > 0
|
||||||
AND frps.period_num = 3
|
AND frps.period_num = 3
|
||||||
AND frps.player_id IS NOT NULL
|
AND frps.player_id IS NOT NULL
|
||||||
GROUP BY frps.player_id, COALESCE(p.name, frps.player_username)
|
GROUP BY frps.player_id, COALESCE(p.name, frps.player_username)
|
||||||
|
|||||||
256
internal/db/playoff_stats.go
Normal file
256
internal/db/playoff_stats.go
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/uptrace/bun"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetPlayoffPlayerStats returns aggregated player stats from playoff fixtures only
|
||||||
|
// (fixtures with round < 0) for a season-league.
|
||||||
|
// Reuses the same LeaguePlayerStats struct as regular season stats.
|
||||||
|
func GetPlayoffPlayerStats(
|
||||||
|
ctx context.Context,
|
||||||
|
tx bun.Tx,
|
||||||
|
seasonID, leagueID int,
|
||||||
|
) ([]*LeaguePlayerStats, error) {
|
||||||
|
if seasonID == 0 {
|
||||||
|
return nil, errors.New("seasonID not provided")
|
||||||
|
}
|
||||||
|
if leagueID == 0 {
|
||||||
|
return nil, errors.New("leagueID not provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
var stats []*LeaguePlayerStats
|
||||||
|
err := tx.NewRaw(`
|
||||||
|
SELECT
|
||||||
|
agg.player_id,
|
||||||
|
agg.player_name,
|
||||||
|
COALESCE(tr.team_id, 0) AS team_id,
|
||||||
|
COALESCE(t.name, '') AS team_name,
|
||||||
|
COALESCE(t.color, '') AS team_color,
|
||||||
|
agg.games_played,
|
||||||
|
agg.total_periods_played,
|
||||||
|
agg.total_goals,
|
||||||
|
agg.total_assists,
|
||||||
|
agg.total_primary_assists,
|
||||||
|
agg.total_secondary_assists,
|
||||||
|
agg.total_saves,
|
||||||
|
agg.total_shots,
|
||||||
|
agg.total_blocks,
|
||||||
|
agg.total_passes,
|
||||||
|
agg.total_score
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
frps.player_id AS player_id,
|
||||||
|
COALESCE(p.name, frps.player_username) AS player_name,
|
||||||
|
COUNT(DISTINCT frps.fixture_result_id) AS games_played,
|
||||||
|
COALESCE(SUM(frps.periods_played), 0) AS total_periods_played,
|
||||||
|
COALESCE(SUM(frps.goals), 0) AS total_goals,
|
||||||
|
COALESCE(SUM(frps.assists), 0) AS total_assists,
|
||||||
|
COALESCE(SUM(frps.primary_assists), 0) AS total_primary_assists,
|
||||||
|
COALESCE(SUM(frps.secondary_assists), 0) AS total_secondary_assists,
|
||||||
|
COALESCE(SUM(frps.saves), 0) AS total_saves,
|
||||||
|
COALESCE(SUM(frps.shots), 0) AS total_shots,
|
||||||
|
COALESCE(SUM(frps.blocks), 0) AS total_blocks,
|
||||||
|
COALESCE(SUM(frps.passes), 0) AS total_passes,
|
||||||
|
COALESCE(SUM(frps.score), 0) AS total_score
|
||||||
|
FROM fixture_result_player_stats frps
|
||||||
|
JOIN fixture_results fr ON fr.id = frps.fixture_result_id
|
||||||
|
JOIN fixtures f ON f.id = fr.fixture_id
|
||||||
|
LEFT JOIN players p ON p.id = frps.player_id
|
||||||
|
WHERE fr.finalized = true
|
||||||
|
AND f.season_id = ?
|
||||||
|
AND f.league_id = ?
|
||||||
|
AND f.round < 0
|
||||||
|
AND frps.period_num = 3
|
||||||
|
AND frps.player_id IS NOT NULL
|
||||||
|
GROUP BY frps.player_id, COALESCE(p.name, frps.player_username)
|
||||||
|
) agg
|
||||||
|
LEFT JOIN team_rosters tr
|
||||||
|
ON tr.player_id = agg.player_id
|
||||||
|
AND tr.season_id = ?
|
||||||
|
AND tr.league_id = ?
|
||||||
|
LEFT JOIN teams t ON t.id = tr.team_id
|
||||||
|
ORDER BY agg.total_score DESC
|
||||||
|
`, seasonID, leagueID, seasonID, leagueID).Scan(ctx, &stats)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "tx.NewRaw")
|
||||||
|
}
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPlayoffTopGoalScorers returns the top 10 goal scorers from playoff fixtures.
|
||||||
|
func GetPlayoffTopGoalScorers(
|
||||||
|
ctx context.Context,
|
||||||
|
tx bun.Tx,
|
||||||
|
seasonID, leagueID int,
|
||||||
|
) ([]*LeagueTopGoalScorer, error) {
|
||||||
|
if seasonID == 0 {
|
||||||
|
return nil, errors.New("seasonID not provided")
|
||||||
|
}
|
||||||
|
if leagueID == 0 {
|
||||||
|
return nil, errors.New("leagueID not provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
var stats []*LeagueTopGoalScorer
|
||||||
|
err := tx.NewRaw(`
|
||||||
|
SELECT
|
||||||
|
agg.player_id,
|
||||||
|
agg.player_name,
|
||||||
|
COALESCE(tr.team_id, 0) AS team_id,
|
||||||
|
COALESCE(t.name, '') AS team_name,
|
||||||
|
COALESCE(t.color, '') AS team_color,
|
||||||
|
agg.total_goals,
|
||||||
|
agg.total_periods_played,
|
||||||
|
agg.total_shots
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
frps.player_id AS player_id,
|
||||||
|
COALESCE(p.name, frps.player_username) AS player_name,
|
||||||
|
COALESCE(SUM(frps.goals), 0) AS total_goals,
|
||||||
|
COALESCE(SUM(frps.periods_played), 0) AS total_periods_played,
|
||||||
|
COALESCE(SUM(frps.shots), 0) AS total_shots
|
||||||
|
FROM fixture_result_player_stats frps
|
||||||
|
JOIN fixture_results fr ON fr.id = frps.fixture_result_id
|
||||||
|
JOIN fixtures f ON f.id = fr.fixture_id
|
||||||
|
LEFT JOIN players p ON p.id = frps.player_id
|
||||||
|
WHERE fr.finalized = true
|
||||||
|
AND f.season_id = ?
|
||||||
|
AND f.league_id = ?
|
||||||
|
AND f.round < 0
|
||||||
|
AND frps.period_num = 3
|
||||||
|
AND frps.player_id IS NOT NULL
|
||||||
|
GROUP BY frps.player_id, COALESCE(p.name, frps.player_username)
|
||||||
|
ORDER BY total_goals DESC, total_periods_played ASC, total_shots ASC
|
||||||
|
LIMIT 10
|
||||||
|
) agg
|
||||||
|
LEFT JOIN team_rosters tr
|
||||||
|
ON tr.player_id = agg.player_id
|
||||||
|
AND tr.season_id = ?
|
||||||
|
AND tr.league_id = ?
|
||||||
|
LEFT JOIN teams t ON t.id = tr.team_id
|
||||||
|
ORDER BY agg.total_goals DESC, agg.total_periods_played ASC, agg.total_shots ASC
|
||||||
|
`, seasonID, leagueID, seasonID, leagueID).Scan(ctx, &stats)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "tx.NewRaw")
|
||||||
|
}
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPlayoffTopAssisters returns the top 10 assisters from playoff fixtures.
|
||||||
|
func GetPlayoffTopAssisters(
|
||||||
|
ctx context.Context,
|
||||||
|
tx bun.Tx,
|
||||||
|
seasonID, leagueID int,
|
||||||
|
) ([]*LeagueTopAssister, error) {
|
||||||
|
if seasonID == 0 {
|
||||||
|
return nil, errors.New("seasonID not provided")
|
||||||
|
}
|
||||||
|
if leagueID == 0 {
|
||||||
|
return nil, errors.New("leagueID not provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
var stats []*LeagueTopAssister
|
||||||
|
err := tx.NewRaw(`
|
||||||
|
SELECT
|
||||||
|
agg.player_id,
|
||||||
|
agg.player_name,
|
||||||
|
COALESCE(tr.team_id, 0) AS team_id,
|
||||||
|
COALESCE(t.name, '') AS team_name,
|
||||||
|
COALESCE(t.color, '') AS team_color,
|
||||||
|
agg.total_assists,
|
||||||
|
agg.total_periods_played,
|
||||||
|
agg.total_primary_assists
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
frps.player_id AS player_id,
|
||||||
|
COALESCE(p.name, frps.player_username) AS player_name,
|
||||||
|
COALESCE(SUM(frps.assists), 0) AS total_assists,
|
||||||
|
COALESCE(SUM(frps.periods_played), 0) AS total_periods_played,
|
||||||
|
COALESCE(SUM(frps.primary_assists), 0) AS total_primary_assists
|
||||||
|
FROM fixture_result_player_stats frps
|
||||||
|
JOIN fixture_results fr ON fr.id = frps.fixture_result_id
|
||||||
|
JOIN fixtures f ON f.id = fr.fixture_id
|
||||||
|
LEFT JOIN players p ON p.id = frps.player_id
|
||||||
|
WHERE fr.finalized = true
|
||||||
|
AND f.season_id = ?
|
||||||
|
AND f.league_id = ?
|
||||||
|
AND f.round < 0
|
||||||
|
AND frps.period_num = 3
|
||||||
|
AND frps.player_id IS NOT NULL
|
||||||
|
GROUP BY frps.player_id, COALESCE(p.name, frps.player_username)
|
||||||
|
ORDER BY total_assists DESC, total_periods_played ASC, total_primary_assists DESC
|
||||||
|
LIMIT 10
|
||||||
|
) agg
|
||||||
|
LEFT JOIN team_rosters tr
|
||||||
|
ON tr.player_id = agg.player_id
|
||||||
|
AND tr.season_id = ?
|
||||||
|
AND tr.league_id = ?
|
||||||
|
LEFT JOIN teams t ON t.id = tr.team_id
|
||||||
|
ORDER BY agg.total_assists DESC, agg.total_periods_played ASC, agg.total_primary_assists DESC
|
||||||
|
`, seasonID, leagueID, seasonID, leagueID).Scan(ctx, &stats)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "tx.NewRaw")
|
||||||
|
}
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPlayoffTopSavers returns the top 10 savers from playoff fixtures.
|
||||||
|
func GetPlayoffTopSavers(
|
||||||
|
ctx context.Context,
|
||||||
|
tx bun.Tx,
|
||||||
|
seasonID, leagueID int,
|
||||||
|
) ([]*LeagueTopSaver, error) {
|
||||||
|
if seasonID == 0 {
|
||||||
|
return nil, errors.New("seasonID not provided")
|
||||||
|
}
|
||||||
|
if leagueID == 0 {
|
||||||
|
return nil, errors.New("leagueID not provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
var stats []*LeagueTopSaver
|
||||||
|
err := tx.NewRaw(`
|
||||||
|
SELECT
|
||||||
|
agg.player_id,
|
||||||
|
agg.player_name,
|
||||||
|
COALESCE(tr.team_id, 0) AS team_id,
|
||||||
|
COALESCE(t.name, '') AS team_name,
|
||||||
|
COALESCE(t.color, '') AS team_color,
|
||||||
|
agg.total_saves,
|
||||||
|
agg.total_periods_played,
|
||||||
|
agg.total_blocks
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
frps.player_id AS player_id,
|
||||||
|
COALESCE(p.name, frps.player_username) AS player_name,
|
||||||
|
COALESCE(SUM(frps.saves), 0) AS total_saves,
|
||||||
|
COALESCE(SUM(frps.periods_played), 0) AS total_periods_played,
|
||||||
|
COALESCE(SUM(frps.blocks), 0) AS total_blocks
|
||||||
|
FROM fixture_result_player_stats frps
|
||||||
|
JOIN fixture_results fr ON fr.id = frps.fixture_result_id
|
||||||
|
JOIN fixtures f ON f.id = fr.fixture_id
|
||||||
|
LEFT JOIN players p ON p.id = frps.player_id
|
||||||
|
WHERE fr.finalized = true
|
||||||
|
AND f.season_id = ?
|
||||||
|
AND f.league_id = ?
|
||||||
|
AND f.round < 0
|
||||||
|
AND frps.period_num = 3
|
||||||
|
AND frps.player_id IS NOT NULL
|
||||||
|
GROUP BY frps.player_id, COALESCE(p.name, frps.player_username)
|
||||||
|
ORDER BY total_saves DESC, total_periods_played ASC, total_blocks DESC
|
||||||
|
LIMIT 10
|
||||||
|
) agg
|
||||||
|
LEFT JOIN team_rosters tr
|
||||||
|
ON tr.player_id = agg.player_id
|
||||||
|
AND tr.season_id = ?
|
||||||
|
AND tr.league_id = ?
|
||||||
|
LEFT JOIN teams t ON t.id = tr.team_id
|
||||||
|
ORDER BY agg.total_saves DESC, agg.total_periods_played ASC, agg.total_blocks DESC
|
||||||
|
`, seasonID, leagueID, seasonID, leagueID).Scan(ctx, &stats)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "tx.NewRaw")
|
||||||
|
}
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
// SeasonLeagueFinalsPage renders the finals tab of a season league page.
|
// SeasonLeagueFinalsPage renders the finals tab of a season league page.
|
||||||
// Displays different content based on season status:
|
// Displays different content based on season status:
|
||||||
// - In Progress: "Regular Season in Progress" with optional "Begin Finals" button
|
// - In Progress: "Regular Season in Progress" with optional "Begin Finals" button
|
||||||
// - Finals Soon/Finals/Completed: The playoff bracket
|
// - Finals Soon/Finals/Completed: The playoff bracket + finals stats
|
||||||
func SeasonLeagueFinalsPage(
|
func SeasonLeagueFinalsPage(
|
||||||
s *hws.Server,
|
s *hws.Server,
|
||||||
conn *db.DB,
|
conn *db.DB,
|
||||||
@@ -34,6 +34,10 @@ func SeasonLeagueFinalsPage(
|
|||||||
var season *db.Season
|
var season *db.Season
|
||||||
var league *db.League
|
var league *db.League
|
||||||
var bracket *db.PlayoffBracket
|
var bracket *db.PlayoffBracket
|
||||||
|
var topGoals []*db.LeagueTopGoalScorer
|
||||||
|
var topAssists []*db.LeagueTopAssister
|
||||||
|
var topSaves []*db.LeagueTopSaver
|
||||||
|
var allStats []*db.LeaguePlayerStats
|
||||||
|
|
||||||
if ok := conn.WithReadTx(s, w, r, func(ctx context.Context, tx bun.Tx) (bool, error) {
|
if ok := conn.WithReadTx(s, w, r, func(ctx context.Context, tx bun.Tx) (bool, error) {
|
||||||
var err error
|
var err error
|
||||||
@@ -54,15 +58,35 @@ func SeasonLeagueFinalsPage(
|
|||||||
return false, errors.Wrap(err, "db.GetPlayoffBracket")
|
return false, errors.Wrap(err, "db.GetPlayoffBracket")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load playoff stats if bracket exists
|
||||||
|
if bracket != nil {
|
||||||
|
topGoals, err = db.GetPlayoffTopGoalScorers(ctx, tx, season.ID, league.ID)
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.Wrap(err, "db.GetPlayoffTopGoalScorers")
|
||||||
|
}
|
||||||
|
topAssists, err = db.GetPlayoffTopAssisters(ctx, tx, season.ID, league.ID)
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.Wrap(err, "db.GetPlayoffTopAssisters")
|
||||||
|
}
|
||||||
|
topSaves, err = db.GetPlayoffTopSavers(ctx, tx, season.ID, league.ID)
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.Wrap(err, "db.GetPlayoffTopSavers")
|
||||||
|
}
|
||||||
|
allStats, err = db.GetPlayoffPlayerStats(ctx, tx, season.ID, league.ID)
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.Wrap(err, "db.GetPlayoffPlayerStats")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}); !ok {
|
}); !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Method == "GET" {
|
if r.Method == "GET" {
|
||||||
renderSafely(seasonsview.SeasonLeagueFinalsPage(season, league, bracket), s, r, w)
|
renderSafely(seasonsview.SeasonLeagueFinalsPage(season, league, bracket, topGoals, topAssists, topSaves, allStats), s, r, w)
|
||||||
} else {
|
} else {
|
||||||
renderSafely(seasonsview.SeasonLeagueFinals(season, league, bracket), s, r, w)
|
renderSafely(seasonsview.SeasonLeagueFinals(season, league, bracket, topGoals, topAssists, topSaves, allStats), s, r, w)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,20 +5,43 @@ import "git.haelnorr.com/h/oslstats/internal/contexts"
|
|||||||
import "git.haelnorr.com/h/oslstats/internal/permissions"
|
import "git.haelnorr.com/h/oslstats/internal/permissions"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
templ SeasonLeagueFinalsPage(season *db.Season, league *db.League, bracket *db.PlayoffBracket) {
|
templ SeasonLeagueFinalsPage(
|
||||||
|
season *db.Season,
|
||||||
|
league *db.League,
|
||||||
|
bracket *db.PlayoffBracket,
|
||||||
|
topGoals []*db.LeagueTopGoalScorer,
|
||||||
|
topAssists []*db.LeagueTopAssister,
|
||||||
|
topSaves []*db.LeagueTopSaver,
|
||||||
|
allStats []*db.LeaguePlayerStats,
|
||||||
|
) {
|
||||||
@SeasonLeagueLayout("finals", season, league) {
|
@SeasonLeagueLayout("finals", season, league) {
|
||||||
@SeasonLeagueFinals(season, league, bracket)
|
@SeasonLeagueFinals(season, league, bracket, topGoals, topAssists, topSaves, allStats)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
templ SeasonLeagueFinals(season *db.Season, league *db.League, bracket *db.PlayoffBracket) {
|
templ SeasonLeagueFinals(
|
||||||
|
season *db.Season,
|
||||||
|
league *db.League,
|
||||||
|
bracket *db.PlayoffBracket,
|
||||||
|
topGoals []*db.LeagueTopGoalScorer,
|
||||||
|
topAssists []*db.LeagueTopAssister,
|
||||||
|
topSaves []*db.LeagueTopSaver,
|
||||||
|
allStats []*db.LeaguePlayerStats,
|
||||||
|
) {
|
||||||
{{
|
{{
|
||||||
permCache := contexts.Permissions(ctx)
|
permCache := contexts.Permissions(ctx)
|
||||||
canManagePlayoffs := permCache != nil && permCache.HasPermission(permissions.PlayoffsManage)
|
canManagePlayoffs := permCache != nil && permCache.HasPermission(permissions.PlayoffsManage)
|
||||||
|
hasStats := len(topGoals) > 0 || len(topAssists) > 0 || len(topSaves) > 0 || len(allStats) > 0
|
||||||
}}
|
}}
|
||||||
<div id="finals-content">
|
<div id="finals-content">
|
||||||
if bracket != nil {
|
if bracket != nil {
|
||||||
@PlayoffBracketView(season, league, bracket)
|
@PlayoffBracketView(season, league, bracket)
|
||||||
|
<!-- Finals Stats Section -->
|
||||||
|
if hasStats {
|
||||||
|
<div class="mt-8">
|
||||||
|
@finalsStatsSection(season, league, topGoals, topAssists, topSaves, allStats)
|
||||||
|
</div>
|
||||||
|
}
|
||||||
} else if canManagePlayoffs {
|
} else if canManagePlayoffs {
|
||||||
@finalsNotYetConfigured(season, league)
|
@finalsNotYetConfigured(season, league)
|
||||||
} else {
|
} else {
|
||||||
@@ -27,6 +50,43 @@ templ SeasonLeagueFinals(season *db.Season, league *db.League, bracket *db.Playo
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
templ finalsStatsSection(
|
||||||
|
season *db.Season,
|
||||||
|
league *db.League,
|
||||||
|
topGoals []*db.LeagueTopGoalScorer,
|
||||||
|
topAssists []*db.LeagueTopAssister,
|
||||||
|
topSaves []*db.LeagueTopSaver,
|
||||||
|
allStats []*db.LeaguePlayerStats,
|
||||||
|
) {
|
||||||
|
<script src="/static/js/sortable-table.js"></script>
|
||||||
|
<div class="space-y-8">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="text-yellow">★</span>
|
||||||
|
<h2 class="text-xl font-bold text-text">Finals Stats</h2>
|
||||||
|
</div>
|
||||||
|
<!-- Trophy Leaders -->
|
||||||
|
if len(topGoals) > 0 || len(topAssists) > 0 || len(topSaves) > 0 {
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h3 class="text-lg font-bold text-text text-center">Trophy Leaders</h3>
|
||||||
|
<div class="flex flex-col items-center gap-6 w-full">
|
||||||
|
<div class="flex flex-col lg:flex-row gap-6 justify-center items-stretch w-full lg:w-auto">
|
||||||
|
@topGoalScorersTable(season, league, topGoals)
|
||||||
|
@topAssistersTable(season, league, topAssists)
|
||||||
|
</div>
|
||||||
|
@topSaversTable(season, league, topSaves)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<!-- All Finals Stats -->
|
||||||
|
if len(allStats) > 0 {
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h3 class="text-lg font-bold text-text text-center">All Finals Stats</h3>
|
||||||
|
@allStatsTable(season, league, allStats)
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
templ finalsNotYetConfigured(season *db.Season, league *db.League) {
|
templ finalsNotYetConfigured(season *db.Season, league *db.League) {
|
||||||
<div class="bg-surface0 border border-surface1 rounded-lg p-8 text-center">
|
<div class="bg-surface0 border border-surface1 rounded-lg p-8 text-center">
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
|
|||||||
Reference in New Issue
Block a user