Add player injury status display feature
- Added injury status processing in app.py to check multiple Sleeper API fields - Filter out 'Active' status to only display actual injury conditions - Added injury status display in dashboard template with red styling - Added CSS styling for injury status badges with red color and border - Only non-active injury statuses (IR, SUS, PUP, DNI, Questionable, OUT) will be shown 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
9589a69c9b
commit
10f8e07ed4
4 changed files with 120 additions and 18 deletions
95
app.py
95
app.py
|
|
@ -1,4 +1,4 @@
|
|||
from flask import Flask, render_template, jsonify
|
||||
from flask import Flask, render_template, jsonify, request, session, redirect, url_for
|
||||
from datetime import datetime
|
||||
import os
|
||||
import sys
|
||||
|
|
@ -28,7 +28,11 @@ def get_league_color(league_index):
|
|||
@app.context_processor
|
||||
def inject_apis():
|
||||
"""Make API and version available to all templates"""
|
||||
return dict(sleeper_api=sleeper_api, app_version=app.config['VERSION'])
|
||||
return dict(
|
||||
sleeper_api=sleeper_api,
|
||||
app_version=app.config['VERSION'],
|
||||
current_theme=session.get('theme', 'light')
|
||||
)
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
|
|
@ -36,6 +40,40 @@ def index():
|
|||
print("DEBUG: Index route accessed", flush=True)
|
||||
return render_template('index.html')
|
||||
|
||||
@app.route('/dashboard')
|
||||
def dashboard_form():
|
||||
"""Handle form submission from homepage"""
|
||||
username = request.args.get('username')
|
||||
if username:
|
||||
return dashboard_current(username.strip())
|
||||
else:
|
||||
return redirect(url_for('index'))
|
||||
|
||||
# Add theme handling route
|
||||
@app.route('/toggle_theme', methods=['POST'])
|
||||
def toggle_theme():
|
||||
"""Toggle between light and dark theme"""
|
||||
current_theme = session.get('theme', 'light')
|
||||
new_theme = 'dark' if current_theme == 'light' else 'light'
|
||||
session['theme'] = new_theme
|
||||
|
||||
# Get return URL from form or default to index
|
||||
return_url = request.form.get('return_url', url_for('index'))
|
||||
return redirect(return_url)
|
||||
|
||||
# Add timezone handling route
|
||||
@app.route('/set_timezone', methods=['POST'])
|
||||
def set_timezone():
|
||||
"""Set user's timezone preference"""
|
||||
timezone = request.form.get('timezone')
|
||||
if timezone:
|
||||
session['user_timezone'] = timezone
|
||||
print(f"DEBUG: Set user timezone to: {timezone}", flush=True)
|
||||
|
||||
# Get return URL from form or default to index
|
||||
return_url = request.form.get('return_url', url_for('index'))
|
||||
return redirect(return_url)
|
||||
|
||||
@app.route('/<username>')
|
||||
def dashboard_current(username):
|
||||
"""Dashboard for current NFL week"""
|
||||
|
|
@ -89,10 +127,12 @@ def dashboard(username, week):
|
|||
for i, league in enumerate(leagues):
|
||||
print(f"DEBUG: League {i+1}: ID={league.get('league_id')}, Name='{league.get('name')}'", flush=True)
|
||||
|
||||
# Get NFL game schedule for the week
|
||||
# Get NFL game schedule for the week with user's timezone
|
||||
user_timezone = session.get('user_timezone', 'America/Los_Angeles') # Default to PST
|
||||
print(f"DEBUG: Using timezone: {user_timezone}", flush=True)
|
||||
print(f"DEBUG: Calling get_week_schedule() for week {week}, season {season}", flush=True)
|
||||
try:
|
||||
schedule = espn_api.get_week_schedule(week, season)
|
||||
schedule = espn_api.get_week_schedule(week, season, user_timezone)
|
||||
print(f"DEBUG: Schedule retrieved successfully", flush=True)
|
||||
except Exception as e:
|
||||
print(f"ERROR: ESPN schedule fetch failed: {str(e)}", flush=True)
|
||||
|
|
@ -110,6 +150,7 @@ def dashboard(username, week):
|
|||
matchups = sleeper_api.get_matchups(league_id, week)
|
||||
print(f"DEBUG: Found {len(matchups) if matchups else 0} matchups", flush=True)
|
||||
|
||||
|
||||
# Get rosters to find user's team
|
||||
print(f"DEBUG: Calling get_rosters() for league {league_id}", flush=True)
|
||||
rosters = sleeper_api.get_rosters(league_id)
|
||||
|
|
@ -141,21 +182,56 @@ def dashboard(username, week):
|
|||
opponent_user = sleeper_api.get_user_by_id(opponent_owner_id)
|
||||
print(f"DEBUG: Opponent user: {opponent_user.get('display_name') if opponent_user else 'None'}", flush=True)
|
||||
|
||||
# Get all players on user's roster for calendar
|
||||
# Get all players on user's roster for calendar with starter info
|
||||
all_players = []
|
||||
if user_roster and user_roster.get('players'):
|
||||
if user_roster and user_roster.get('players') and user_matchup:
|
||||
players_list = user_roster['players']
|
||||
print(f"DEBUG: Processing {len(players_list)} total players for calendar", flush=True)
|
||||
starters_list = user_matchup.get('starters', [])
|
||||
print(f"DEBUG: Processing {len(players_list)} total players, {len(starters_list)} starters", flush=True)
|
||||
|
||||
for player_id in players_list:
|
||||
try:
|
||||
# Get player details from Sleeper API
|
||||
player = sleeper_api.get_player_info(player_id)
|
||||
if player:
|
||||
# Add starter status to player data
|
||||
player['is_starter'] = player_id in starters_list
|
||||
|
||||
# Check multiple possible injury status fields
|
||||
injury_status = (
|
||||
player.get('injury_status') or
|
||||
player.get('status') or
|
||||
player.get('injury_designation') or
|
||||
player.get('practice_participation')
|
||||
)
|
||||
|
||||
# Only show injury status if it's not "Active" or None
|
||||
if injury_status and injury_status.lower() != 'active':
|
||||
player['injury_status'] = injury_status
|
||||
else:
|
||||
player['injury_status'] = None
|
||||
|
||||
# Print any player with injury status (only non-Active)
|
||||
if player['injury_status']:
|
||||
player_name = f"{player.get('first_name', '')} {player.get('last_name', '')}".strip()
|
||||
print(f"DEBUG: {player_name} has injury status: {player['injury_status']}", flush=True)
|
||||
|
||||
all_players.append(player)
|
||||
except Exception as e:
|
||||
print(f"ERROR: Failed to get player info for {player_id}: {str(e)}", flush=True)
|
||||
|
||||
# Calculate winning/losing status
|
||||
user_points = user_matchup['points'] if user_matchup else 0
|
||||
opponent_points = opponent_matchup['points'] if opponent_matchup else 0
|
||||
|
||||
# Determine status
|
||||
if user_points > opponent_points:
|
||||
match_status = 'winning'
|
||||
elif user_points < opponent_points:
|
||||
match_status = 'losing'
|
||||
else:
|
||||
match_status = 'tied'
|
||||
|
||||
# Store processed league data
|
||||
league_info = {
|
||||
'league': league,
|
||||
|
|
@ -164,7 +240,10 @@ def dashboard(username, week):
|
|||
'opponent_matchup': opponent_matchup,
|
||||
'opponent_user': opponent_user,
|
||||
'user_roster': user_roster,
|
||||
'all_players': all_players
|
||||
'all_players': all_players,
|
||||
'match_status': match_status,
|
||||
'user_points': user_points,
|
||||
'opponent_points': opponent_points
|
||||
}
|
||||
league_data.append(league_info)
|
||||
print(f"DEBUG: League '{league['name']}' processed successfully", flush=True)
|
||||
|
|
|
|||
|
|
@ -69,4 +69,7 @@ class SleeperAPI:
|
|||
def get_player_info(self, player_id):
|
||||
"""Get specific player info"""
|
||||
players = self.get_players()
|
||||
return players.get(str(player_id))
|
||||
player_info = players.get(str(player_id))
|
||||
|
||||
|
||||
return player_info
|
||||
|
|
|
|||
|
|
@ -1097,4 +1097,18 @@ body {
|
|||
padding: 0 12px 12px 12px;
|
||||
}
|
||||
|
||||
/* Player Injury Status Styling */
|
||||
.injury-status {
|
||||
color: #dc2626 !important; /* Red color */
|
||||
font-weight: 700;
|
||||
font-size: 10px;
|
||||
margin-left: 4px;
|
||||
padding: 1px 3px;
|
||||
background-color: rgba(220, 38, 38, 0.1);
|
||||
border: 1px solid #dc2626;
|
||||
border-radius: 3px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
<!-- Compact league scores at top -->
|
||||
<section class="scores-summary">
|
||||
{% for league_info in league_data %}
|
||||
<div class="score-row {{ league_info.match_status }}">
|
||||
<div class="score-row">
|
||||
<div class="league-info">
|
||||
<!-- League color dot -->
|
||||
<span class="league-dot" style="background-color: {{ league_info.league_color }};"></span>
|
||||
|
|
@ -31,16 +31,13 @@
|
|||
</div>
|
||||
<div class="score-compact">
|
||||
<!-- Win/Loss indicator -->
|
||||
<span class="match-indicator {{ league_info.match_status }}">
|
||||
<span class="match-indicator">
|
||||
{% if league_info.match_status == 'winning' %}
|
||||
<span class="indicator-icon">↗️</span>
|
||||
<span class="indicator-text">W</span>
|
||||
{% elif league_info.match_status == 'losing' %}
|
||||
<span class="indicator-icon">↘️</span>
|
||||
<span class="indicator-text">L</span>
|
||||
{% else %}
|
||||
<span class="indicator-icon">↔️</span>
|
||||
<span class="indicator-text">T</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
|
||||
|
|
@ -61,10 +58,11 @@
|
|||
<!-- Main calendar section -->
|
||||
<section class="schedule-section">
|
||||
<h2>Week {{ week }} Games
|
||||
<br>
|
||||
{% if session.get('user_timezone') %}
|
||||
<span class="timezone-info">({{ session.get('user_timezone')|replace('_', ' ')|replace('America/', '') }})</span>
|
||||
<span class="timezone-info">timezone: ({{ session.get('user_timezone') }})</span>
|
||||
{% else %}
|
||||
<span class="timezone-info">(PST/PDT)</span>
|
||||
<span class="timezone-info">timezone: (PST/PDT)</span>
|
||||
{% endif %}
|
||||
</h2>
|
||||
<div class="calendar-rows">
|
||||
|
|
@ -127,7 +125,11 @@
|
|||
{% for player in starters %}
|
||||
<div class="player-pill starter {{ player.fantasy_positions[0]|lower if player.fantasy_positions else 'flex' }}">
|
||||
<span class="pos">{{ player.fantasy_positions[0] if player.fantasy_positions else 'FLEX' }}</span>
|
||||
<span class="name">{{ player.last_name }}</span>
|
||||
<span class="name">{{ player.last_name }}
|
||||
{% if player.injury_status %}
|
||||
<span class="injury-status">{{ player.injury_status }}</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
@ -139,7 +141,11 @@
|
|||
{% for player in bench_players %}
|
||||
<div class="player-pill bench {{ player.fantasy_positions[0]|lower if player.fantasy_positions else 'flex' }}">
|
||||
<span class="pos">{{ player.fantasy_positions[0] if player.fantasy_positions else 'FLEX' }}</span>
|
||||
<span class="name">{{ player.last_name }}</span>
|
||||
<span class="name">{{ player.last_name }}
|
||||
{% if player.injury_status %}
|
||||
<span class="injury-status">{{ player.injury_status }}</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue