added player stats to profile

This commit is contained in:
2026-03-06 20:48:21 +11:00
parent 788346d269
commit 060301f2c2
10 changed files with 817 additions and 78 deletions

View File

@@ -32,53 +32,155 @@ func ProfileRedirect(
})
}
// PlayerView renders the player profile page.
// If the player has no SlapID and the viewer is the player's owner, show the link prompt.
// If the player has no SlapID and the viewer is not the owner, show 404.
func PlayerView(
// resolvePlayerAndOwner is a helper that resolves the player from the URL path
// and determines if the current user is the owner of the player.
// Returns false from the outer handler if resolution failed (404 already thrown).
func resolvePlayerAndOwner(
s *hws.Server,
conn *db.DB,
w http.ResponseWriter,
r *http.Request,
) (player *db.Player, isOwner bool, ok bool) {
playerIDStr := r.PathValue("player_id")
playerID, err := strconv.Atoi(playerIDStr)
if err != nil {
throw.NotFound(s, w, r, r.URL.Path)
return nil, false, false
}
if ok := conn.WithReadTx(s, w, r, func(ctx context.Context, tx bun.Tx) (bool, error) {
var err error
player, err = db.GetPlayer(ctx, tx, playerID)
if err != nil {
if db.IsBadRequest(err) {
throw.NotFound(s, w, r, r.URL.Path)
return false, nil
}
return false, errors.Wrap(err, "db.GetPlayer")
}
user := db.CurrentUser(ctx)
if user != nil && player.UserID != nil && *player.UserID == user.ID {
isOwner = true
}
return true, nil
}); !ok {
return nil, false, false
}
// If player has no SlapID and viewer is not the owner, show 404
if player.SlapID == nil && !isOwner {
throw.NotFound(s, w, r, r.URL.Path)
return nil, false, false
}
return player, isOwner, true
}
// PlayerViewStats renders the player profile page with the stats tab active.
// GET renders the full page layout. POST renders just the tab content.
func PlayerViewStats(
s *hws.Server,
conn *db.DB,
) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
playerIDStr := r.PathValue("player_id")
playerID, err := strconv.Atoi(playerIDStr)
if err != nil {
throw.NotFound(s, w, r, r.URL.Path)
player, isOwner, ok := resolvePlayerAndOwner(s, conn, w, r)
if !ok {
return
}
var player *db.Player
var isOwner bool
var stats *db.PlayerAllTimeStats
var seasons []*db.Season
var teams []*db.Team
if ok := conn.WithReadTx(s, w, r, func(ctx context.Context, tx bun.Tx) (bool, error) {
var err error
player, err = db.GetPlayer(ctx, tx, playerID)
stats, err = db.GetPlayerAllTimeStats(ctx, tx, player.ID)
if err != nil {
if db.IsBadRequest(err) {
throw.NotFound(s, w, r, r.URL.Path)
return false, nil
}
return false, errors.Wrap(err, "db.GetPlayer")
return false, errors.Wrap(err, "db.GetPlayerAllTimeStats")
}
// Check if the current user owns this player
user := db.CurrentUser(ctx)
if user != nil && player.UserID != nil && *player.UserID == user.ID {
isOwner = true
seasons, err = db.GetPlayerSeasonsList(ctx, tx, player.ID)
if err != nil {
return false, errors.Wrap(err, "db.GetPlayerSeasonsList")
}
teams, err = db.GetPlayerTeamsList(ctx, tx, player.ID)
if err != nil {
return false, errors.Wrap(err, "db.GetPlayerTeamsList")
}
return true, nil
}); !ok {
return
}
// If player has no SlapID and viewer is not the owner, show 404
if player.SlapID == nil && !isOwner {
throw.NotFound(s, w, r, r.URL.Path)
if r.Method == "GET" {
renderSafely(playersview.PlayerStatsPage(player, isOwner, stats, seasons, teams), s, r, w)
} else {
renderSafely(playersview.PlayerStatsTab(player, stats, seasons, teams, "", 0), s, r, w)
}
})
}
// PlayerViewTeams renders the teams tab of the player profile page.
func PlayerViewTeams(
s *hws.Server,
conn *db.DB,
) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
player, isOwner, ok := resolvePlayerAndOwner(s, conn, w, r)
if !ok {
return
}
renderSafely(playersview.PlayerPage(player, isOwner), s, r, w)
var teamInfos []*db.PlayerTeamInfo
if ok := conn.WithReadTx(s, w, r, func(ctx context.Context, tx bun.Tx) (bool, error) {
var err error
teamInfos, err = db.GetPlayerTeams(ctx, tx, player.ID)
if err != nil {
return false, errors.Wrap(err, "db.GetPlayerTeams")
}
return true, nil
}); !ok {
return
}
if r.Method == "GET" {
renderSafely(playersview.PlayerTeamsPage(player, isOwner, teamInfos), s, r, w)
} else {
renderSafely(playersview.PlayerTeamsTab(teamInfos), s, r, w)
}
})
}
// PlayerViewSeasons renders the seasons tab of the player profile page.
func PlayerViewSeasons(
s *hws.Server,
conn *db.DB,
) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
player, isOwner, ok := resolvePlayerAndOwner(s, conn, w, r)
if !ok {
return
}
var seasonInfos []*db.PlayerSeasonInfo
if ok := conn.WithReadTx(s, w, r, func(ctx context.Context, tx bun.Tx) (bool, error) {
var err error
seasonInfos, err = db.GetPlayerSeasons(ctx, tx, player.ID)
if err != nil {
return false, errors.Wrap(err, "db.GetPlayerSeasons")
}
return true, nil
}); !ok {
return
}
if r.Method == "GET" {
renderSafely(playersview.PlayerSeasonsPage(player, isOwner, seasonInfos), s, r, w)
} else {
renderSafely(playersview.PlayerSeasonsTab(seasonInfos), s, r, w)
}
})
}