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
|
from datetime import datetime
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -28,7 +28,11 @@ def get_league_color(league_index):
|
||||||
@app.context_processor
|
@app.context_processor
|
||||||
def inject_apis():
|
def inject_apis():
|
||||||
"""Make API and version available to all templates"""
|
"""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('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
|
|
@ -36,6 +40,40 @@ def index():
|
||||||
print("DEBUG: Index route accessed", flush=True)
|
print("DEBUG: Index route accessed", flush=True)
|
||||||
return render_template('index.html')
|
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>')
|
@app.route('/<username>')
|
||||||
def dashboard_current(username):
|
def dashboard_current(username):
|
||||||
"""Dashboard for current NFL week"""
|
"""Dashboard for current NFL week"""
|
||||||
|
|
@ -89,10 +127,12 @@ def dashboard(username, week):
|
||||||
for i, league in enumerate(leagues):
|
for i, league in enumerate(leagues):
|
||||||
print(f"DEBUG: League {i+1}: ID={league.get('league_id')}, Name='{league.get('name')}'", flush=True)
|
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)
|
print(f"DEBUG: Calling get_week_schedule() for week {week}, season {season}", flush=True)
|
||||||
try:
|
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)
|
print(f"DEBUG: Schedule retrieved successfully", flush=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"ERROR: ESPN schedule fetch failed: {str(e)}", flush=True)
|
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)
|
matchups = sleeper_api.get_matchups(league_id, week)
|
||||||
print(f"DEBUG: Found {len(matchups) if matchups else 0} matchups", flush=True)
|
print(f"DEBUG: Found {len(matchups) if matchups else 0} matchups", flush=True)
|
||||||
|
|
||||||
|
|
||||||
# Get rosters to find user's team
|
# Get rosters to find user's team
|
||||||
print(f"DEBUG: Calling get_rosters() for league {league_id}", flush=True)
|
print(f"DEBUG: Calling get_rosters() for league {league_id}", flush=True)
|
||||||
rosters = sleeper_api.get_rosters(league_id)
|
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)
|
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)
|
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 = []
|
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']
|
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:
|
for player_id in players_list:
|
||||||
try:
|
try:
|
||||||
# Get player details from Sleeper API
|
# Get player details from Sleeper API
|
||||||
player = sleeper_api.get_player_info(player_id)
|
player = sleeper_api.get_player_info(player_id)
|
||||||
if player:
|
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)
|
all_players.append(player)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"ERROR: Failed to get player info for {player_id}: {str(e)}", flush=True)
|
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
|
# Store processed league data
|
||||||
league_info = {
|
league_info = {
|
||||||
'league': league,
|
'league': league,
|
||||||
|
|
@ -164,7 +240,10 @@ def dashboard(username, week):
|
||||||
'opponent_matchup': opponent_matchup,
|
'opponent_matchup': opponent_matchup,
|
||||||
'opponent_user': opponent_user,
|
'opponent_user': opponent_user,
|
||||||
'user_roster': user_roster,
|
'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)
|
league_data.append(league_info)
|
||||||
print(f"DEBUG: League '{league['name']}' processed successfully", flush=True)
|
print(f"DEBUG: League '{league['name']}' processed successfully", flush=True)
|
||||||
|
|
|
||||||
|
|
@ -69,4 +69,7 @@ class SleeperAPI:
|
||||||
def get_player_info(self, player_id):
|
def get_player_info(self, player_id):
|
||||||
"""Get specific player info"""
|
"""Get specific player info"""
|
||||||
players = self.get_players()
|
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;
|
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 -->
|
<!-- Compact league scores at top -->
|
||||||
<section class="scores-summary">
|
<section class="scores-summary">
|
||||||
{% for league_info in league_data %}
|
{% for league_info in league_data %}
|
||||||
<div class="score-row {{ league_info.match_status }}">
|
<div class="score-row">
|
||||||
<div class="league-info">
|
<div class="league-info">
|
||||||
<!-- League color dot -->
|
<!-- League color dot -->
|
||||||
<span class="league-dot" style="background-color: {{ league_info.league_color }};"></span>
|
<span class="league-dot" style="background-color: {{ league_info.league_color }};"></span>
|
||||||
|
|
@ -31,16 +31,13 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="score-compact">
|
<div class="score-compact">
|
||||||
<!-- Win/Loss indicator -->
|
<!-- Win/Loss indicator -->
|
||||||
<span class="match-indicator {{ league_info.match_status }}">
|
<span class="match-indicator">
|
||||||
{% if league_info.match_status == 'winning' %}
|
{% if league_info.match_status == 'winning' %}
|
||||||
<span class="indicator-icon">↗️</span>
|
<span class="indicator-icon">↗️</span>
|
||||||
<span class="indicator-text">W</span>
|
|
||||||
{% elif league_info.match_status == 'losing' %}
|
{% elif league_info.match_status == 'losing' %}
|
||||||
<span class="indicator-icon">↘️</span>
|
<span class="indicator-icon">↘️</span>
|
||||||
<span class="indicator-text">L</span>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="indicator-icon">↔️</span>
|
<span class="indicator-icon">↔️</span>
|
||||||
<span class="indicator-text">T</span>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|
@ -61,10 +58,11 @@
|
||||||
<!-- Main calendar section -->
|
<!-- Main calendar section -->
|
||||||
<section class="schedule-section">
|
<section class="schedule-section">
|
||||||
<h2>Week {{ week }} Games
|
<h2>Week {{ week }} Games
|
||||||
|
<br>
|
||||||
{% if session.get('user_timezone') %}
|
{% 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 %}
|
{% else %}
|
||||||
<span class="timezone-info">(PST/PDT)</span>
|
<span class="timezone-info">timezone: (PST/PDT)</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h2>
|
</h2>
|
||||||
<div class="calendar-rows">
|
<div class="calendar-rows">
|
||||||
|
|
@ -127,7 +125,11 @@
|
||||||
{% for player in starters %}
|
{% for player in starters %}
|
||||||
<div class="player-pill starter {{ player.fantasy_positions[0]|lower if player.fantasy_positions else 'flex' }}">
|
<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="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>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -139,7 +141,11 @@
|
||||||
{% for player in bench_players %}
|
{% for player in bench_players %}
|
||||||
<div class="player-pill bench {{ player.fantasy_positions[0]|lower if player.fantasy_positions else 'flex' }}">
|
<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="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>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue