changement de l'affichage des tryouts et des matchs
This commit is contained in:
Binary file not shown.
@@ -88,7 +88,7 @@ def create_app():
|
||||
response.headers['X-Content-Type-Options'] = 'nosniff'
|
||||
response.headers['X-Frame-Options'] = 'DENY'
|
||||
response.headers['X-XSS-Protection'] = '1; mode=block'
|
||||
response.headers['Content-Security-Policy'] = "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; font-src 'self' https://cdnjs.cloudflare.com; img-src 'self' data:; connect-src 'self'; frame-ancestors 'none';"
|
||||
response.headers['Content-Security-Policy'] = "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://cdn.jsdelivr.net; font-src 'self' https://cdnjs.cloudflare.com; img-src 'self' data:; connect-src 'self'; frame-ancestors 'none';"
|
||||
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
|
||||
return response
|
||||
|
||||
@@ -133,5 +133,5 @@ def create_app():
|
||||
if __name__ == '__main__':
|
||||
app = create_app()
|
||||
# Debug mode should only be enabled via environment variable for security
|
||||
debug_mode = os.environ.get('FLASK_DEBUG', 'false').lower() == 'true'
|
||||
debug_mode = os.getenv('FLASK_DEBUG', 'false').lower() == 'true'
|
||||
app.run(debug=debug_mode, host='0.0.0.0', port=5000)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
-1
@@ -21,7 +21,7 @@ def is_safe_url(url):
|
||||
"""
|
||||
if not url:
|
||||
return False
|
||||
parsed = url_parse(url)
|
||||
parsed = urlparse(url)
|
||||
# Allow relative URLs (no netloc) or same-origin URLs
|
||||
return not parsed.netloc or parsed.netloc == request.host
|
||||
|
||||
|
||||
+59
-6
@@ -6,8 +6,9 @@ This module handles player evaluation creation, management, and viewing.
|
||||
from flask import Blueprint, render_template, redirect, url_for, flash, request
|
||||
from flask_login import login_required, current_user
|
||||
from extensions import db
|
||||
from models import User, Tryout, Evaluation, TryoutRegistration, GAME_POSITIONS
|
||||
from models import User, Tryout, Evaluation, TryoutRegistration, GAME_POSITIONS, OrgTeam
|
||||
from sqlalchemy import func
|
||||
from sqlalchemy.orm import aliased
|
||||
|
||||
evaluations_bp = Blueprint('evaluations', __name__, url_prefix='/evaluations')
|
||||
|
||||
@@ -41,13 +42,55 @@ def list_evaluations():
|
||||
Evaluators (coach/manager): Their given evaluations.
|
||||
Players: Their received evaluations.
|
||||
|
||||
Supports sorting by any column header via 'sort' and 'order' query parameters.
|
||||
|
||||
Returns:
|
||||
Response: Rendered evaluations list template.
|
||||
"""
|
||||
user = current_user
|
||||
|
||||
# Get sort parameters
|
||||
sort_column = request.args.get('sort', 'created_at')
|
||||
sort_order = request.args.get('order', 'desc')
|
||||
|
||||
# Validate sort_order
|
||||
if sort_order not in ('asc', 'desc'):
|
||||
sort_order = 'desc'
|
||||
|
||||
# Map sort columns to SQLAlchemy expressions using aliased User models for relationship sorting
|
||||
player_alias = aliased(User, name='eval_player')
|
||||
evaluator_alias = aliased(User, name='eval_evaluator')
|
||||
|
||||
sort_map = {
|
||||
'tryout': Tryout.title,
|
||||
'player': player_alias.full_name,
|
||||
'evaluator': evaluator_alias.full_name,
|
||||
'mecanics_score': Evaluation.mecanics_score,
|
||||
'cohesion_score': Evaluation.cohesion_score,
|
||||
'communication_score': Evaluation.communication_score,
|
||||
'gamesense_score': Evaluation.gamesense_score,
|
||||
'versatility_score': Evaluation.versatility_score,
|
||||
'discipline_score': Evaluation.discipline_score,
|
||||
'analysis_score': Evaluation.analysis_score,
|
||||
'sport_ethics_score': Evaluation.sport_ethics_score,
|
||||
'mental_score': Evaluation.mental_score,
|
||||
'overall_score': Evaluation.overall_score,
|
||||
'position_recommendation': Evaluation.position_recommendation,
|
||||
'created_at': Evaluation.created_at,
|
||||
}
|
||||
|
||||
sort_expr = sort_map.get(sort_column, Evaluation.created_at)
|
||||
if sort_order == 'asc':
|
||||
sort_expr = sort_expr.asc()
|
||||
else:
|
||||
sort_expr = sort_expr.desc()
|
||||
|
||||
if user.role == 'president':
|
||||
evaluations = Evaluation.query.order_by(Evaluation.created_at.desc()).all()
|
||||
evaluations = Evaluation.query \
|
||||
.outerjoin(Tryout, Evaluation.tryout_id == Tryout.id) \
|
||||
.outerjoin(player_alias, Evaluation.player_id == player_alias.id) \
|
||||
.outerjoin(evaluator_alias, Evaluation.evaluator_id == evaluator_alias.id) \
|
||||
.order_by(sort_expr).all()
|
||||
avg_scores = db.session.query(
|
||||
Evaluation.player_id,
|
||||
func.count(Evaluation.id).label('eval_count'),
|
||||
@@ -60,13 +103,23 @@ def list_evaluations():
|
||||
player_scores[p.id] = {'player': p, 'count': row.eval_count, 'avg': round(row.avg_score, 1) if row.avg_score else 0}
|
||||
|
||||
elif user.can_evaluate():
|
||||
evaluations = Evaluation.query.filter_by(evaluator_id=user.id).order_by(Evaluation.created_at.desc()).all()
|
||||
evaluations = Evaluation.query \
|
||||
.outerjoin(Tryout, Evaluation.tryout_id == Tryout.id) \
|
||||
.outerjoin(player_alias, Evaluation.player_id == player_alias.id) \
|
||||
.outerjoin(evaluator_alias, Evaluation.evaluator_id == evaluator_alias.id) \
|
||||
.filter(Evaluation.evaluator_id == user.id) \
|
||||
.order_by(sort_expr).all()
|
||||
player_scores = {}
|
||||
else:
|
||||
evaluations = Evaluation.query.filter_by(player_id=user.id).order_by(Evaluation.created_at.desc()).all()
|
||||
evaluations = Evaluation.query \
|
||||
.outerjoin(Tryout, Evaluation.tryout_id == Tryout.id) \
|
||||
.outerjoin(player_alias, Evaluation.player_id == player_alias.id) \
|
||||
.outerjoin(evaluator_alias, Evaluation.evaluator_id == evaluator_alias.id) \
|
||||
.filter(Evaluation.player_id == user.id) \
|
||||
.order_by(sort_expr).all()
|
||||
player_scores = {}
|
||||
|
||||
return render_template('pages/evaluations.html', evaluations=evaluations, player_scores=player_scores)
|
||||
return render_template('pages/evaluations.html', evaluations=evaluations, player_scores=player_scores, sort_column=sort_column, sort_order=sort_order)
|
||||
|
||||
|
||||
@evaluations_bp.route('/<int:tryout_id>/<int:player_id>', methods=['GET', 'POST'])
|
||||
@@ -219,4 +272,4 @@ def players_to_evaluate(tryout_id):
|
||||
).first()
|
||||
players.append({'player': p, 'evaluated': existing is not None, 'registration': reg})
|
||||
|
||||
return render_template('pages/players_to_evaluate.html', tryout=tryout, players=players)
|
||||
return render_template('pages/players_to_evaluate.html', tryout=tryout, players=players)
|
||||
|
||||
+41
-39
@@ -14,7 +14,7 @@ tryouts_bp = Blueprint('tryouts', __name__, url_prefix='/tryouts')
|
||||
|
||||
def can_manage():
|
||||
"""Check if current user can manage tryouts.
|
||||
|
||||
|
||||
Returns:
|
||||
bool: True if user is president or manager.
|
||||
"""
|
||||
@@ -25,13 +25,13 @@ def can_manage():
|
||||
@login_required
|
||||
def list_tryouts():
|
||||
"""List all tryouts visible to the current user.
|
||||
|
||||
|
||||
Shows tryouts filtered by user's role:
|
||||
- President: All tryouts
|
||||
- Manager: Only their created tryouts
|
||||
- Coach: Tryouts targeting their org team
|
||||
- Player: Upcoming and in-progress tryouts
|
||||
|
||||
- Player: Only tryouts they are registered for or participating in
|
||||
|
||||
Returns:
|
||||
Response: Rendered tryouts list template.
|
||||
"""
|
||||
@@ -47,7 +47,9 @@ def list_tryouts():
|
||||
else:
|
||||
tryouts = []
|
||||
elif current_user.role == 'player':
|
||||
tryouts = Tryout.query.filter(Tryout.status.in_(['upcoming', 'in_progress'])).order_by(Tryout.date.desc()).all()
|
||||
# Players only see tryouts they are registered for or participating in matches
|
||||
from routes.matches import get_visible_tryouts_for_user
|
||||
tryouts = get_visible_tryouts_for_user()
|
||||
else:
|
||||
tryouts = Tryout.query.order_by(Tryout.date.desc()).all()
|
||||
return render_template('pages/tryouts.html', tryouts=tryouts, now=datetime.utcnow())
|
||||
@@ -57,12 +59,12 @@ def list_tryouts():
|
||||
@login_required
|
||||
def create_tryout():
|
||||
"""Create a new tryout event.
|
||||
|
||||
|
||||
GET: Render the tryout creation form.
|
||||
POST: Create a tryout with the submitted details.
|
||||
|
||||
|
||||
Requires president or manager role.
|
||||
|
||||
|
||||
Returns:
|
||||
Response: Create form or redirect to the new tryout.
|
||||
"""
|
||||
@@ -110,15 +112,15 @@ def create_tryout():
|
||||
@login_required
|
||||
def edit_tryout(tryout_id):
|
||||
"""Edit an existing tryout event.
|
||||
|
||||
|
||||
GET: Render the tryout edit form with current data.
|
||||
POST: Update the tryout with submitted changes.
|
||||
|
||||
|
||||
Permission based on can_manage_this_tryout check.
|
||||
|
||||
|
||||
Args:
|
||||
tryout_id: The ID of the tryout to edit.
|
||||
|
||||
|
||||
Returns:
|
||||
Response: Edit form or redirect to tryout view.
|
||||
"""
|
||||
@@ -164,18 +166,18 @@ def edit_tryout(tryout_id):
|
||||
@login_required
|
||||
def view_tryout(tryout_id):
|
||||
"""View a specific tryout with all details.
|
||||
|
||||
|
||||
Displays tryout information, registered players, evaluations, teams,
|
||||
matches, and evaluation status information.
|
||||
|
||||
|
||||
Args:
|
||||
tryout_id: The ID of the tryout to view.
|
||||
|
||||
|
||||
Returns:
|
||||
Response: Rendered tryout detail template.
|
||||
"""
|
||||
tryout = Tryout.query.get_or_404(tryout_id)
|
||||
|
||||
|
||||
# Check if user has permission to view this tryout
|
||||
can_view = False
|
||||
if current_user.role == 'president':
|
||||
@@ -197,11 +199,11 @@ def view_tryout(tryout_id):
|
||||
can_view = is_registered or player_in_match
|
||||
elif current_user.role == 'scout':
|
||||
can_view = True
|
||||
|
||||
|
||||
if not can_view:
|
||||
flash('You do not have permission to view this tryout.', 'danger')
|
||||
return redirect(url_for('tryouts.list_tryouts'))
|
||||
|
||||
|
||||
registrations = TryoutRegistration.query.filter_by(tryout_id=tryout_id).all()
|
||||
registered_players = [User.query.get(r.player_id) for r in registrations if r.player_id]
|
||||
evaluations = Evaluation.query.filter_by(tryout_id=tryout_id).all()
|
||||
@@ -235,7 +237,7 @@ def view_tryout(tryout_id):
|
||||
|
||||
# Determine if current user can edit this tryout
|
||||
can_edit = current_user.can_manage_this_tryout(tryout)
|
||||
|
||||
|
||||
# Determine if current user can view the calendar (managers/coaches can always see it)
|
||||
# Players need to be registered or participating in a match
|
||||
can_view_calendar = can_edit
|
||||
@@ -245,16 +247,16 @@ def view_tryout(tryout_id):
|
||||
MatchParticipant.player_id == current_user.id,
|
||||
Match.tryout_id == tryout_id
|
||||
).first() is not None
|
||||
|
||||
|
||||
can_view_calendar = is_registered or player_in_match
|
||||
|
||||
# Only expose all_players to users who can manage players in this tryout
|
||||
all_players = None
|
||||
if can_edit:
|
||||
all_players = User.query.filter_by(role='player').order_by(User.full_name).all()
|
||||
|
||||
|
||||
# Get matches for this tryout with participant info
|
||||
matches = Match.query.filter_by(tryout_id=tryout_id).order_by(Match.date).all()
|
||||
matches = Match.query.filter_by(tryout_id=tryout_id).order_by(Match.date, Match.start_time).all()
|
||||
match_data = []
|
||||
for match in matches:
|
||||
if match.match_type == 'team_vs_team':
|
||||
@@ -279,7 +281,7 @@ def view_tryout(tryout_id):
|
||||
'match': match,
|
||||
'participants': participants
|
||||
})
|
||||
|
||||
|
||||
return render_template('pages/view_tryout.html',
|
||||
tryout=tryout,
|
||||
registered_players=registered_players,
|
||||
@@ -301,13 +303,13 @@ def view_tryout(tryout_id):
|
||||
@login_required
|
||||
def register_for_tryout(tryout_id):
|
||||
"""Register a player for a tryout.
|
||||
|
||||
|
||||
Allows players to register for tryouts. Validates that the tryout
|
||||
is accepting registrations and not at capacity.
|
||||
|
||||
|
||||
Args:
|
||||
tryout_id: The ID of the tryout to register for.
|
||||
|
||||
|
||||
Returns:
|
||||
Response: Redirect to tryout view with status message.
|
||||
"""
|
||||
@@ -342,12 +344,12 @@ def register_for_tryout(tryout_id):
|
||||
@login_required
|
||||
def update_status(tryout_id):
|
||||
"""Update the status of a tryout.
|
||||
|
||||
|
||||
Changes tryout status between upcoming, in_progress, and completed.
|
||||
|
||||
|
||||
Args:
|
||||
tryout_id: The ID of the tryout to update.
|
||||
|
||||
|
||||
Returns:
|
||||
Response: Redirect to tryout view.
|
||||
"""
|
||||
@@ -367,11 +369,11 @@ def update_status(tryout_id):
|
||||
@login_required
|
||||
def update_registration_status(tryout_id, player_id):
|
||||
"""Update the attendance status of a tryout registration.
|
||||
|
||||
|
||||
Args:
|
||||
tryout_id: The ID of the tryout.
|
||||
player_id: The ID of the player whose status to update.
|
||||
|
||||
|
||||
Returns:
|
||||
Response: Redirect to tryout view.
|
||||
"""
|
||||
@@ -393,12 +395,12 @@ def update_registration_status(tryout_id, player_id):
|
||||
@login_required
|
||||
def register_player(tryout_id):
|
||||
"""Manually register a player for a tryout (by managers/coaches).
|
||||
|
||||
|
||||
Allows authorized users to register players on their behalf.
|
||||
|
||||
|
||||
Args:
|
||||
tryout_id: The ID of the tryout.
|
||||
|
||||
|
||||
Returns:
|
||||
Response: Redirect to tryout view with status message.
|
||||
"""
|
||||
@@ -439,10 +441,10 @@ def register_player(tryout_id):
|
||||
@login_required
|
||||
def create_team(tryout_id):
|
||||
"""Create a tryout-specific team.
|
||||
|
||||
|
||||
Args:
|
||||
tryout_id: The ID of the tryout to create the team for.
|
||||
|
||||
|
||||
Returns:
|
||||
Response: Redirect to tryout view with status message.
|
||||
"""
|
||||
@@ -464,11 +466,11 @@ def create_team(tryout_id):
|
||||
@login_required
|
||||
def add_to_team(tryout_id, team_id):
|
||||
"""Add a player to a tryout team.
|
||||
|
||||
|
||||
Args:
|
||||
tryout_id: The ID of the tryout.
|
||||
team_id: The ID of the team to add the player to.
|
||||
|
||||
|
||||
Returns:
|
||||
Response: Redirect to tryout view with status message.
|
||||
"""
|
||||
@@ -490,4 +492,4 @@ def add_to_team(tryout_id, team_id):
|
||||
db.session.commit()
|
||||
flash('Player added to team!', 'success')
|
||||
|
||||
return redirect(url_for('tryouts.view_tryout', tryout_id=tryout_id))
|
||||
return redirect(url_for('tryouts.view_tryout', tryout_id=tryout_id))
|
||||
|
||||
@@ -1749,3 +1749,147 @@ a:hover { color: var(--primary-dark); }
|
||||
transform: translateY(-50%);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ===== Tryouts Grid (Card-based Layout) ===== */
|
||||
.tryouts-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.tryout-card {
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
border: 1px solid var(--border-color, #e0e0e0);
|
||||
}
|
||||
|
||||
.tryout-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.tryout-card .card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.tryout-title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tryout-info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.info-icon {
|
||||
width: 16px;
|
||||
text-align: center;
|
||||
color: var(--text-muted, #888);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-weight: 600;
|
||||
color: var(--text-secondary, #555);
|
||||
min-width: 50px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: var(--text-primary, #333);
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.tryout-description {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-secondary, #555);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.tryout-description p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tryout-card .card-footer {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
background: var(--bg-secondary, #f8f9fa);
|
||||
border-top: 1px solid var(--border-color, #e0e0e0);
|
||||
}
|
||||
|
||||
/* ===== Full-width Schedule Card ===== */
|
||||
.tryout-schedule-card {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* ===== Dark mode adjustments ===== */
|
||||
[data-theme="dark"] .tryout-card {
|
||||
border-color: var(--border-color, #333);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .tryout-card .card-footer {
|
||||
background: var(--bg-secondary, #2a2a2a);
|
||||
border-top-color: var(--border-color, #333);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .info-label {
|
||||
color: var(--text-secondary, #aaa);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Sortable Table Headers */
|
||||
.sort-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: var(--gray-500);
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.sort-link:hover {
|
||||
color: var(--gray-800);
|
||||
}
|
||||
|
||||
.sort-link .fas {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.sort-inactive {
|
||||
opacity: 0.3;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.sort-link:hover .sort-inactive {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .sort-link {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .sort-link:hover {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,23 @@
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / Evaluations</span>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% set sort_column = sort_column | default('created_at') %}
|
||||
{% set sort_order = sort_order | default('desc') %}
|
||||
|
||||
{% macro sort_link(column, label) %}
|
||||
<th>
|
||||
{% set new_order = 'asc' if (sort_column == column and sort_order == 'desc') else 'desc' %}
|
||||
<a href="{{ url_for('evaluations.list_evaluations', sort=column, order=new_order) }}" class="sort-link">
|
||||
{{ label }}
|
||||
{% if sort_column == column %}
|
||||
<i class="fas fa-arrow-{{ 'up' if sort_order == 'asc' else 'down' }}"></i>
|
||||
{% else %}
|
||||
<i class="fas fa-arrows-alt-v sort-inactive"></i>
|
||||
{% endif %}
|
||||
</a>
|
||||
</th>
|
||||
{% endmacro %}
|
||||
|
||||
{% if current_user.role == 'president' and player_scores %}
|
||||
<div class="stats-grid mb-4">
|
||||
{% for pid, data in player_scores.items() %}
|
||||
@@ -22,7 +39,7 @@
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-clipboard-list"></i>
|
||||
<h3><i class="fas fa-clipboard-list"></i>
|
||||
{% if current_user.role == 'player' %}
|
||||
My Evaluations
|
||||
{% else %}
|
||||
@@ -35,29 +52,29 @@
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Tryout</th>
|
||||
<th>Player</th>
|
||||
<th>Evaluator</th>
|
||||
<th>Mecanics</th>
|
||||
<th>Cohesion</th>
|
||||
<th>Communication</th>
|
||||
<th>Gamesense</th>
|
||||
<th>Versatility</th>
|
||||
<th>Discipline</th>
|
||||
<th>Analysis</th>
|
||||
<th>Sport Ethics</th>
|
||||
<th>Mental</th>
|
||||
<th>Overall</th>
|
||||
<th>Position</th>
|
||||
<th>Date</th>
|
||||
{{ sort_link('tryout', 'Tryout') }}
|
||||
{{ sort_link('player', 'Player') }}
|
||||
{{ sort_link('evaluator', 'Evaluator') }}
|
||||
{{ sort_link('mecanics_score', 'Mecanics') }}
|
||||
{{ sort_link('cohesion_score', 'Cohesion') }}
|
||||
{{ sort_link('communication_score', 'Communication') }}
|
||||
{{ sort_link('gamesense_score', 'Gamesense') }}
|
||||
{{ sort_link('versatility_score', 'Versatility') }}
|
||||
{{ sort_link('discipline_score', 'Discipline') }}
|
||||
{{ sort_link('analysis_score', 'Analysis') }}
|
||||
{{ sort_link('sport_ethics_score', 'Sport Ethics') }}
|
||||
{{ sort_link('mental_score', 'Mental') }}
|
||||
{{ sort_link('overall_score', 'Overall') }}
|
||||
{{ sort_link('position_recommendation', 'Position') }}
|
||||
{{ sort_link('created_at', 'Date') }}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for eval in evaluations %}
|
||||
<tr>
|
||||
<td>{{ eval.tryout.title }}</td>
|
||||
<td>{{ eval.player.full_name }}</td>
|
||||
<td>{{ eval.evaluator.full_name }}</td>
|
||||
<td>{{ eval.tryout.title if eval.tryout else 'Deleted Tryout' }}</td>
|
||||
<td>{{ eval.player.full_name if eval.player else 'Deleted Player' }}</td>
|
||||
<td>{{ eval.evaluator.full_name if eval.evaluator else 'Deleted Evaluator' }}</td>
|
||||
<td>{{ eval.mecanics_score or '-' }}</td>
|
||||
<td>{{ eval.cohesion_score or '-' }}</td>
|
||||
<td>{{ eval.communication_score or '-' }}</td>
|
||||
@@ -86,4 +103,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -77,22 +77,28 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label"><i class="fas fa-chart-line"></i> TRN (Tracker Network)</span>
|
||||
<span class="detail-label"><i class="fas fa-chart-line"></i> Games & TRN</span>
|
||||
<span class="detail-value">
|
||||
{% if user.gamertags %}
|
||||
{% set games_list = user.get_games_list() %}
|
||||
{% if games_list %}
|
||||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||||
{% for gamertag in user.gamertags %}
|
||||
{% for game in games_list %}
|
||||
{% set gt = user.gamertags | selectattr('game', 'equalto', game) | first %}
|
||||
<div>
|
||||
<span class="badge badge-esport" style="margin-right: 8px;">{{ gamertag.game }}</span>
|
||||
<a href="{{ gamertag.get_trn_url() }}" target="_blank" rel="noopener noreferrer" class="trn-link">
|
||||
<i class="fas fa-external-link-alt"></i> {{ gamertag.gamertag }}
|
||||
{% if gamertag.platform %}<small>({{ gamertag.platform }})</small>{% endif %}
|
||||
{% if gt and gt.get_trn_url() %}
|
||||
<a href="{{ gt.get_trn_url() }}" target="_blank" rel="noopener noreferrer" class="trn-link">
|
||||
<span class="badge badge-esport" style="margin-right: 8px;">{{ game }}</span>
|
||||
<i class="fas fa-external-link-alt"></i> {{ gt.gamertag }}
|
||||
{% if gt.platform %}<small>({{ gt.platform }})</small>{% endif %}
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="badge badge-esport">{{ game }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<span class="text-muted">Not connected</span>
|
||||
<span class="text-muted">Not specified</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -12,64 +12,87 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="table-container">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Target Team</th>
|
||||
<th>Date</th>
|
||||
<th>Location</th>
|
||||
<th>Status</th>
|
||||
<th>Players</th>
|
||||
<th>Evaluations</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for tryout in tryouts %}
|
||||
<tr>
|
||||
<td class="cell-title">{{ tryout.title }}</td>
|
||||
<td>{{ tryout.target_org_team.name if tryout.target_org_team else '-' }}</td>
|
||||
<td>{{ tryout.date.strftime('%b %d, %Y') }}</td>
|
||||
<td>{{ tryout.location or 'TBD' }}</td>
|
||||
<td>
|
||||
<span class="badge badge-{{ tryout.status }}">
|
||||
{{ tryout.status | replace('_', ' ') | title }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ tryout.registrations.count() }}</td>
|
||||
<td>{{ tryout.evaluations.count() }}</td>
|
||||
<td>
|
||||
<a href="{{ url_for('tryouts.view_tryout', tryout_id=tryout.id) }}" class="btn btn-sm btn-outline">
|
||||
<i class="fas fa-eye"></i> View
|
||||
</a>
|
||||
{% if current_user.can_evaluate() %}
|
||||
<a href="{{ url_for('evaluations.players_to_evaluate', tryout_id=tryout.id) }}" class="btn btn-sm btn-primary">
|
||||
<i class="fas fa-clipboard-check"></i> Evaluate
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="8" class="text-center">
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-calendar-times"></i>
|
||||
<h3>No tryouts found</h3>
|
||||
{% if current_user.can_manage_tryouts() %}
|
||||
<p>Get started by creating a new tryout.</p>
|
||||
<a href="{{ url_for('tryouts.create_tryout') }}" class="btn btn-primary">Create Tryout</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="tryouts-grid">
|
||||
{% for tryout in tryouts %}
|
||||
<div class="card tryout-card">
|
||||
<div class="card-header">
|
||||
<h3 class="tryout-title">{{ tryout.title }}</h3>
|
||||
<span class="badge badge-{{ tryout.status }}">{{ tryout.status | replace('_', ' ') | title }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="tryout-info-grid">
|
||||
<div class="info-item">
|
||||
<i class="fas fa-gamepad info-icon"></i>
|
||||
<span class="info-label">Game</span>
|
||||
<span class="info-value">{{ tryout.game }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<i class="fas fa-calendar info-icon"></i>
|
||||
<span class="info-label">Date</span>
|
||||
<span class="info-value">{{ tryout.date.strftime('%b %d, %Y') }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<i class="fas fa-map-marker-alt info-icon"></i>
|
||||
<span class="info-label">Location</span>
|
||||
<span class="info-value">{{ tryout.location or 'TBD' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<i class="fas fa-users info-icon"></i>
|
||||
<span class="info-label">Players</span>
|
||||
<span class="info-value">{{ tryout.registrations.count() }}</span>
|
||||
</div>
|
||||
{% if current_user.can_evaluate() %}
|
||||
<div class="info-item">
|
||||
<i class="fas fa-clipboard-check info-icon"></i>
|
||||
<span class="info-label">Evaluations</span>
|
||||
<span class="info-value">{{ tryout.evaluations.count() }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if tryout.target_org_team %}
|
||||
<div class="info-item">
|
||||
<i class="fas fa-flag info-icon"></i>
|
||||
<span class="info-label">Target Team</span>
|
||||
<span class="info-value">{{ tryout.target_org_team.name }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if tryout.max_players %}
|
||||
<div class="info-item">
|
||||
<i class="fas fa-user-friends info-icon"></i>
|
||||
<span class="info-label">Max Players</span>
|
||||
<span class="info-value">{{ tryout.max_players }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if tryout.description %}
|
||||
<div class="tryout-description mt-3">
|
||||
<p>{{ tryout.description | truncate(120) }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="{{ url_for('tryouts.view_tryout', tryout_id=tryout.id) }}" class="btn btn-sm btn-outline">
|
||||
<i class="fas fa-eye"></i> View Details
|
||||
</a>
|
||||
{% if current_user.can_evaluate() %}
|
||||
<a href="{{ url_for('evaluations.players_to_evaluate', tryout_id=tryout.id) }}" class="btn btn-sm btn-primary">
|
||||
<i class="fas fa-clipboard-check"></i> Evaluate
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="card" style="grid-column: 1 / -1;">
|
||||
<div class="card-body text-center">
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-calendar-times"></i>
|
||||
<h3>No tryouts found</h3>
|
||||
{% if current_user.can_manage_tryouts() %}
|
||||
<p>Get started by creating a new tryout.</p>
|
||||
<a href="{{ url_for('tryouts.create_tryout') }}" class="btn btn-primary">Create Tryout</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
+194
-192
@@ -246,204 +246,206 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if can_view_calendar %}
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-futbol"></i> Schedule</h3>
|
||||
{% if can_edit %}
|
||||
<div class="card-actions">
|
||||
<a href="{{ url_for('matches.create_match', tryout_id=tryout.id) }}" class="btn btn-sm btn-success">
|
||||
<i class="fas fa-plus"></i> Schedule Match
|
||||
</a>
|
||||
<a href="{{ url_for('users.add_note_from_tryout', tryout_id=tryout.id) }}" class="btn btn-sm btn-primary">
|
||||
<i class="fas fa-sticky-note"></i> Add Note
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if matches %}
|
||||
<!-- Mini Calendar -->
|
||||
<div id="mini-calendar" style="min-height: 300px;"></div>
|
||||
{% else %}
|
||||
<!-- No matches yet - show message -->
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-calendar-alt fa-3x text-muted mb-3"></i>
|
||||
<p class="text-muted">No matches scheduled yet. Check back later!</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if matches %}
|
||||
<!-- Matches Table -->
|
||||
<div class="table-container mt-3">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Match</th>
|
||||
<th>Type</th>
|
||||
<th>Date</th>
|
||||
<th>Participants</th>
|
||||
<th>Time</th>
|
||||
<th>Status</th>
|
||||
{% if can_edit %}
|
||||
<th>Actions</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in match_data %}
|
||||
{% set m = item.match %}
|
||||
{% set participants = item.participants %}
|
||||
<tr>
|
||||
<td class="cell-title">{{ m.title }}</td>
|
||||
<td>
|
||||
<span class="badge badge-{{ 'success' if m.match_type in ['team_vs_team', 'player_vs_player'] else 'warning' }}">
|
||||
{% if m.match_type == 'team_vs_team' %}
|
||||
Team vs Team
|
||||
{% elif m.match_type == 'player_vs_player' %}
|
||||
Player vs Player
|
||||
{% else %}
|
||||
Player Scrim
|
||||
{% endif %}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ m.date.strftime('%m/%d/%Y') }}</td>
|
||||
<td>
|
||||
{% if m.match_type == 'team_vs_team' %}
|
||||
<div class="match-teams">
|
||||
<div class="match-team">
|
||||
<span class="team-name">{{ m.team1.name if m.team1 else 'Team 1' }}</span>
|
||||
{% if participants.team1_players %}
|
||||
<ul class="team-players-list">
|
||||
{% for pl in participants.team1_players %}
|
||||
<li>{{ pl.name }}{% if pl.position %} <span class="position-tag">{{ pl.position }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="match-vs">vs</div>
|
||||
<div class="match-team">
|
||||
<span class="team-name">{{ m.team2.name if m.team2 else 'Team 2' }}</span>
|
||||
{% if participants.team2_players %}
|
||||
<ul class="team-players-list">
|
||||
{% for pl in participants.team2_players %}
|
||||
<li>{{ pl.name }}{% if pl.position %} <span class="position-tag">{{ pl.position }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% elif m.match_type == 'player_vs_player' %}
|
||||
<div class="match-teams">
|
||||
<div class="match-team">
|
||||
<span class="team-name">Team 1</span>
|
||||
{% if participants.team1_players %}
|
||||
<ul class="team-players-list">
|
||||
{% for pl in participants.team1_players %}
|
||||
<li>{{ pl.name }}{% if pl.position %} <span class="position-tag">{{ pl.position }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="match-vs">vs</div>
|
||||
<div class="match-team">
|
||||
<span class="team-name">Team 2</span>
|
||||
{% if participants.team2_players %}
|
||||
<ul class="team-players-list">
|
||||
{% for pl in participants.team2_players %}
|
||||
<li>{{ pl.name }}{% if pl.position %} <span class="position-tag">{{ pl.position }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ participants | join(', ') }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if m.start_time and m.end_time %}
|
||||
{{ m.start_time.strftime('%H:%M') }} - {{ m.end_time.strftime('%H:%M') }}
|
||||
{% else %}
|
||||
TBD
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge badge-{{ m.status }}">{{ m.status }}</span>
|
||||
</td>
|
||||
{% if can_edit %}
|
||||
<td>
|
||||
<a href="{{ url_for('matches.edit_match', match_id=m.id) }}" class="btn btn-sm btn-outline">
|
||||
<i class="fas fa-edit"></i> Edit
|
||||
</a>
|
||||
<a href="{{ url_for('users.add_note_from_match', match_id=m.id) }}" class="btn btn-sm btn-primary" title="Add Note for this Match">
|
||||
<i class="fas fa-sticky-note"></i> Note
|
||||
</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if can_view_calendar %}
|
||||
<div class="card tryout-schedule-card mb-4">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-futbol"></i> Schedule</h3>
|
||||
{% if can_edit %}
|
||||
<div class="card-actions">
|
||||
<a href="{{ url_for('matches.create_match', tryout_id=tryout.id) }}" class="btn btn-sm btn-success">
|
||||
<i class="fas fa-plus"></i> Schedule Match
|
||||
</a>
|
||||
<a href="{{ url_for('users.add_note_from_tryout', tryout_id=tryout.id) }}" class="btn btn-sm btn-primary">
|
||||
<i class="fas fa-sticky-note"></i> Add Note
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-star"></i> Evaluation Summary</h3>
|
||||
<div class="card-body">
|
||||
{% if matches %}
|
||||
<!-- Matches Table -->
|
||||
<div class="table-container">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Match</th>
|
||||
<th>Type</th>
|
||||
<th>Date</th>
|
||||
<th>Participants</th>
|
||||
<th>Time</th>
|
||||
<th>Status</th>
|
||||
{% if can_edit %}
|
||||
<th>Actions</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in match_data %}
|
||||
{% set m = item.match %}
|
||||
{% set participants = item.participants %}
|
||||
<tr>
|
||||
<td class="cell-title">{{ m.title }}</td>
|
||||
<td>
|
||||
<span class="badge badge-{{ 'success' if m.match_type in ['team_vs_team', 'player_vs_player'] else 'warning' }}">
|
||||
{% if m.match_type == 'team_vs_team' %}
|
||||
Team vs Team
|
||||
{% elif m.match_type == 'player_vs_player' %}
|
||||
Player vs Player
|
||||
{% else %}
|
||||
Player Scrim
|
||||
{% endif %}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ m.date.strftime('%m/%d/%Y') }}</td>
|
||||
<td>
|
||||
{% if m.match_type == 'team_vs_team' %}
|
||||
<div class="match-teams">
|
||||
<div class="match-team">
|
||||
<span class="team-name">{{ m.team1.name if m.team1 else 'Team 1' }}</span>
|
||||
{% if participants.team1_players %}
|
||||
<ul class="team-players-list">
|
||||
{% for pl in participants.team1_players %}
|
||||
<li>{{ pl.name }}{% if pl.position %} <span class="position-tag">{{ pl.position }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="match-vs">vs</div>
|
||||
<div class="match-team">
|
||||
<span class="team-name">{{ m.team2.name if m.team2 else 'Team 2' }}</span>
|
||||
{% if participants.team2_players %}
|
||||
<ul class="team-players-list">
|
||||
{% for pl in participants.team2_players %}
|
||||
<li>{{ pl.name }}{% if pl.position %} <span class="position-tag">{{ pl.position }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% elif m.match_type == 'player_vs_player' %}
|
||||
<div class="match-teams">
|
||||
<div class="match-team">
|
||||
<span class="team-name">Team 1</span>
|
||||
{% if participants.team1_players %}
|
||||
<ul class="team-players-list">
|
||||
{% for pl in participants.team1_players %}
|
||||
<li>{{ pl.name }}{% if pl.position %} <span class="position-tag">{{ pl.position }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="match-vs">vs</div>
|
||||
<div class="match-team">
|
||||
<span class="team-name">Team 2</span>
|
||||
{% if participants.team2_players %}
|
||||
<ul class="team-players-list">
|
||||
{% for pl in participants.team2_players %}
|
||||
<li>{{ pl.name }}{% if pl.position %} <span class="position-tag">{{ pl.position }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ participants | join(', ') }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if m.start_time and m.end_time %}
|
||||
{{ m.start_time.strftime('%H:%M') }} - {{ m.end_time.strftime('%H:%M') }}
|
||||
{% else %}
|
||||
TBD
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge badge-{{ m.status }}">{{ m.status }}</span>
|
||||
</td>
|
||||
{% if can_edit %}
|
||||
<td>
|
||||
<a href="{{ url_for('matches.edit_match', match_id=m.id) }}" class="btn btn-sm btn-outline">
|
||||
<i class="fas fa-edit"></i> Edit
|
||||
</a>
|
||||
<a href="{{ url_for('users.add_note_from_match', match_id=m.id) }}" class="btn btn-sm btn-primary" title="Add Note for this Match">
|
||||
<i class="fas fa-sticky-note"></i> Note
|
||||
</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-container">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Player</th>
|
||||
<th>Evaluator</th>
|
||||
<th>Mecanics</th>
|
||||
<th>Cohesion</th>
|
||||
<th>Communication</th>
|
||||
<th>Gamesense</th>
|
||||
<th>Versatility</th>
|
||||
<th>Discipline</th>
|
||||
<th>Analysis</th>
|
||||
<th>Sport Ethics</th>
|
||||
<th>Mental</th>
|
||||
<th>Overall</th>
|
||||
<th>Recommendation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for eval in evaluations %}
|
||||
<tr>
|
||||
<td>{{ eval.player.full_name }}</td>
|
||||
<td>{{ eval.evaluator.full_name }}</td>
|
||||
<td>{{ eval.mecanics_score or '-' }}</td>
|
||||
<td>{{ eval.cohesion_score or '-' }}</td>
|
||||
<td>{{ eval.communication_score or '-' }}</td>
|
||||
<td>{{ eval.gamesense_score or '-' }}</td>
|
||||
<td>{{ eval.versatility_score or '-' }}</td>
|
||||
<td>{{ eval.discipline_score or '-' }}</td>
|
||||
<td>{{ eval.analysis_score or '-' }}</td>
|
||||
<td>{{ eval.sport_ethics_score or '-' }}</td>
|
||||
<td>{{ eval.mental_score or '-' }}</td>
|
||||
<td><span class="score">{{ eval.overall_score or '-' }}</span></td>
|
||||
<td>{{ eval.position_recommendation or '-' }}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="13" class="text-center">No evaluations yet.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if matches %}
|
||||
<!-- Mini Calendar -->
|
||||
<div id="mini-calendar" style="min-height: 300px; margin-top: 20px;"></div>
|
||||
{% else %}
|
||||
<!-- No matches yet - show message -->
|
||||
<div class="text-center py-4">
|
||||
<i class="fas fa-calendar-alt fa-3x text-muted mb-3"></i>
|
||||
<p class="text-muted">No matches scheduled yet. Check back later!</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if current_user.can_evaluate() %}
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-star"></i> Evaluation Summary</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-container">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Player</th>
|
||||
<th>Evaluator</th>
|
||||
<th>Mecanics</th>
|
||||
<th>Cohesion</th>
|
||||
<th>Communication</th>
|
||||
<th>Gamesense</th>
|
||||
<th>Versatility</th>
|
||||
<th>Discipline</th>
|
||||
<th>Analysis</th>
|
||||
<th>Sport Ethics</th>
|
||||
<th>Mental</th>
|
||||
<th>Overall</th>
|
||||
<th>Recommendation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for eval in evaluations %}
|
||||
<tr>
|
||||
<td>{{ eval.player.full_name }}</td>
|
||||
<td>{{ eval.evaluator.full_name }}</td>
|
||||
<td>{{ eval.mecanics_score or '-' }}</td>
|
||||
<td>{{ eval.cohesion_score or '-' }}</td>
|
||||
<td>{{ eval.communication_score or '-' }}</td>
|
||||
<td>{{ eval.gamesense_score or '-' }}</td>
|
||||
<td>{{ eval.versatility_score or '-' }}</td>
|
||||
<td>{{ eval.discipline_score or '-' }}</td>
|
||||
<td>{{ eval.analysis_score or '-' }}</td>
|
||||
<td>{{ eval.sport_ethics_score or '-' }}</td>
|
||||
<td>{{ eval.mental_score or '-' }}</td>
|
||||
<td><span class="score">{{ eval.overall_score or '-' }}</span></td>
|
||||
<td>{{ eval.position_recommendation or '-' }}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="13" class="text-center">No evaluations yet.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -473,4 +475,4 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user