2.0.0-rc1 : Profile and achievements update.

This commit is contained in:
2026-08-09 00:50:45 +08:00
parent 562775e5db
commit 3874bf57a9
31 changed files with 2618 additions and 108 deletions
+58 -17
View File
@@ -2,15 +2,19 @@ from flask import Blueprint, render_template, request, redirect, url_for, flash,
from web.services.web_service import WebService
from web.services.stats_service import StatsService
from web.services.feature_service import FeatureService
from web.services.roster_version_service import RosterVersionService
from web.services.team_performance_service import TeamPerformanceService
from web.services.narrative_service import NarrativeService
import json
import logging
bp = Blueprint('teams', __name__, url_prefix='/teams')
logger = logging.getLogger(__name__)
# --- API Endpoints ---
@bp.route('/api/search')
def api_search():
query = request.args.get('q', '').strip() # Strip whitespace
print(f"DEBUG: Search Query Received: '{query}'") # Debug Log
if len(query) < 2:
return jsonify([])
@@ -20,9 +24,7 @@ def api_search():
# Support sorting by matches for better "Find Player" experience
sort_by = request.args.get('sort', 'matches')
print(f"DEBUG: Calling StatsService.get_players with search='{query}'")
players, total = StatsService.get_players(page=1, per_page=50, search=query, sort_by=sort_by)
print(f"DEBUG: Found {len(players)} players (Total: {total})")
# Format for frontend
results = []
@@ -62,7 +64,6 @@ def api_search():
results.sort(key=lambda x: x['matches'], reverse=True)
print(f"DEBUG: Returning {len(results)} results")
return jsonify(results)
@bp.route('/api/roster', methods=['GET', 'POST'])
@@ -88,6 +89,7 @@ def api_roster():
current_ids = json.loads(target_team['player_ids_json'])
except:
pass
previous_ids = list(current_ids)
if action == 'add':
if steam_id not in current_ids:
@@ -95,20 +97,36 @@ def api_roster():
elif action == 'remove':
if steam_id in current_ids:
current_ids.remove(steam_id)
else:
return jsonify({'error': 'Unknown roster action'}), 400
# Pass lineup_id=target_team['id'] to update existing lineup
WebService.save_lineup(target_team['name'], target_team['description'], current_ids, lineup_id=target_team['id'])
WebService.save_lineup(
target_team['name'],
target_team['description'],
current_ids,
lineup_id=target_team['id'],
)
try:
version_id, created = RosterVersionService.snapshot_roster(
current_ids,
name=f"{target_team['name']} Roster",
)
except Exception:
WebService.save_lineup(
target_team['name'],
target_team['description'],
previous_ids,
lineup_id=target_team['id'],
)
raise
return jsonify({'status': 'success', 'roster': current_ids})
# GET: Return detailed player info
try:
print(f"DEBUG: api_roster GET - Target Team: {target_team.get('id')}")
p_ids_json = target_team.get('player_ids_json', '[]')
p_ids = json.loads(p_ids_json)
print(f"DEBUG: Player IDs: {p_ids}")
players = StatsService.get_players_by_ids(p_ids)
print(f"DEBUG: Players fetched: {len(players) if players else 0}")
# Add extra stats needed for cards
enriched = []
@@ -130,9 +148,10 @@ def api_roster():
enriched.append(p_dict)
except Exception as inner_e:
print(f"ERROR: Processing player failed: {inner_e}")
import traceback
traceback.print_exc()
logger.exception(
"Failed to enrich roster player %s",
p.get('steam_id_64') if hasattr(p, 'get') else 'unknown',
)
return jsonify({
'status': 'success',
@@ -140,9 +159,7 @@ def api_roster():
'roster': enriched
})
except Exception as e:
print(f"CRITICAL ERROR in api_roster: {e}")
import traceback
traceback.print_exc()
logger.exception("Roster API failed")
return jsonify({'error': str(e)}), 500
# --- Views ---
@@ -151,6 +168,30 @@ def index():
# Directly render the Clubhouse SPA
return render_template('teams/clubhouse.html')
@bp.route('/performance')
def performance():
return render_template(
'teams/performance.html',
seasons=NarrativeService.get_seasons(),
**TeamPerformanceService.get_dashboard(),
)
@bp.route('/roster-role', methods=['POST'])
def roster_role():
if not session.get('is_admin'):
return "Unauthorized", 403
steam_id = request.form.get('steam_id')
member_role = request.form.get('member_role')
try:
RosterVersionService.update_current_member_role(
steam_id,
member_role,
)
flash('Roster role updated.', 'success')
except ValueError as exc:
flash(str(exc), 'error')
return redirect(url_for('teams.performance'))
# Deprecated routes (kept for compatibility if needed, but hidden)
@bp.route('/list')
def list_view():
@@ -228,5 +269,5 @@ def detail(lineup_id):
return render_template('teams/detail.html', lineup=lineup, players=players, agg_stats=agg_stats, shared_matches=shared_matches, radar_data=radar_data)
except Exception as e:
import traceback
return f"<pre>{traceback.format_exc()}</pre>", 500
logger.exception("Lineup detail failed for lineup_id=%s", lineup_id)
return "Unable to load lineup", 500