changement des notes légers: rendu le pipeline plus fluide et ai effacé des pages redondantes ou encombrantes

This commit is contained in:
cedrick2711
2026-07-16 21:28:43 -04:00
parent 24fcc9a048
commit c795df8e60
10 changed files with 289 additions and 43 deletions
+10
View File
@@ -0,0 +1,10 @@
---
name: test
description: Describe what this custom agent does and when to use it.
argument-hint: The inputs this agent expects, e.g., "a task to implement" or "a question to answer".
# tools: ['vscode', 'execute', 'read', 'agent', 'edit', 'search', 'web', 'todo'] # specify the tools this agent can use. If not set, all enabled tools are allowed.
---
<!-- Tip: Use /create-agent in chat to generate content with agent assistance -->
Define what this custom agent does, including its behavior, capabilities, and any specific instructions for its operation.
Binary file not shown.
Binary file not shown.
+64 -5
View File
@@ -8,7 +8,7 @@ import os
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify, send_file from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify, send_file
from flask_login import login_required, current_user from flask_login import login_required, current_user
from extensions import db, hash_password from extensions import db, hash_password
from models import User, ROLES, ESPORT_GAMES, PlayerDisponibility, UserGamertag, GAME_PLATFORMS, Contract, OrgTeam, CoachAvailability, TeamNote, PersonalNote, OneOnOneRequest, Match, Team, TeamMember, MatchParticipant, Tryout from models import User, ROLES, ESPORT_GAMES, PlayerDisponibility, UserGamertag, GAME_PLATFORMS, Contract, OrgTeam, CoachAvailability, TeamNote, PersonalNote, OneOnOneRequest, Match, Team, TeamMember, MatchParticipant, Tryout, TryoutRegistration
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from datetime import datetime, timedelta, date as date_type from datetime import datetime, timedelta, date as date_type
import requests import requests
@@ -1132,6 +1132,60 @@ def manage_personal_notes():
org_team=org_team) org_team=org_team)
@users_bp.route('/notes', methods=['GET'])
@login_required
def notes_dashboard():
"""Unified notes dashboard for coaches.
GET: Render the combined notes management page with both team and personal notes forms.
Returns:
Response: Rendered notes dashboard template.
"""
if current_user.role != 'coach':
flash('Only coaches can manage notes.', 'danger')
return redirect(url_for('main.dashboard'))
# Get the coach's team
org_team = OrgTeam.query.filter_by(coach_id=current_user.id).first()
players = []
if org_team:
players = User.query.filter_by(role='player', team_id=org_team.id).order_by(User.full_name).all()
# Get existing team notes
team_notes = []
latest_team_note = None
if org_team:
team_notes = TeamNote.query.filter_by(org_team_id=org_team.id).order_by(TeamNote.created_at.desc()).all()
latest_team_note = team_notes[0] if team_notes else None
# Get all personal notes for players on this team
personal_notes = []
if org_team:
personal_notes = PersonalNote.query.filter(
PersonalNote.player_id.in_([p.id for p in players])
).order_by(PersonalNote.created_at.desc()).all()
# Get available matches and tryouts for context
matches = []
tryouts = []
teams = []
if current_user.role == 'coach' and org_team:
tryouts = Tryout.query.filter_by(target_org_team_id=org_team.id).order_by(Tryout.date.desc()).all()
matches = Match.query.join(Tryout).filter(Tryout.target_org_team_id == org_team.id).order_by(Match.date.desc()).all()
teams = Team.query.order_by(Team.name).all()
return render_template('pages/notes.html',
org_team=org_team,
players=players,
team_notes=team_notes,
latest_team_note=latest_team_note,
personal_notes=personal_notes,
matches=matches,
tryouts=tryouts,
teams=teams)
# Note source types for filtering # Note source types for filtering
NOTE_SOURCE_MATCH = 'match' NOTE_SOURCE_MATCH = 'match'
NOTE_SOURCE_TRYOUT = 'tryout' NOTE_SOURCE_TRYOUT = 'tryout'
@@ -1256,7 +1310,7 @@ def add_personal_note():
db.session.add(note) db.session.add(note)
db.session.commit() db.session.commit()
flash('Personal note added successfully!', 'success') flash('Personal note added successfully!', 'success')
return redirect(url_for('users.my_notes')) return redirect(url_for('users.notes_dashboard'))
return render_template('pages/add_personal_note.html', return render_template('pages/add_personal_note.html',
players=players, players=players,
@@ -1362,6 +1416,7 @@ def add_note_from_tryout(tryout_id):
tryout = Tryout.query.get_or_404(tryout_id) tryout = Tryout.query.get_or_404(tryout_id)
# Check permissions # Check permissions
org_team = None
if current_user.role == 'coach': if current_user.role == 'coach':
org_team = OrgTeam.query.filter_by(coach_id=current_user.id).first() org_team = OrgTeam.query.filter_by(coach_id=current_user.id).first()
if not org_team or (tryout.target_org_team_id and tryout.target_org_team_id != org_team.id): if not org_team or (tryout.target_org_team_id and tryout.target_org_team_id != org_team.id):
@@ -1372,8 +1427,8 @@ def add_note_from_tryout(tryout_id):
registrations = TryoutRegistration.query.filter_by(tryout_id=tryout_id).all() registrations = TryoutRegistration.query.filter_by(tryout_id=tryout_id).all()
player_ids = [r.player_id for r in registrations] player_ids = [r.player_id for r in registrations]
# If coach, filter to only their team players # If coach, filter to only their team players; otherwise include all
if current_user.role == 'coach' and org_team: if org_team:
players = User.query.filter(User.id.in_(player_ids), User.team_id == org_team.id).order_by(User.full_name).all() players = User.query.filter(User.id.in_(player_ids), User.team_id == org_team.id).order_by(User.full_name).all()
else: else:
players = User.query.filter(User.id.in_(player_ids)).order_by(User.full_name).all() players = User.query.filter(User.id.in_(player_ids)).order_by(User.full_name).all()
@@ -1403,7 +1458,11 @@ def add_note_from_tryout(tryout_id):
flash('Personal note added successfully!', 'success') flash('Personal note added successfully!', 'success')
return redirect(url_for('tryouts.view_tryout', tryout_id=tryout_id)) return redirect(url_for('tryouts.view_tryout', tryout_id=tryout_id))
# Allow pre-selecting a player via query parameter
preselected_player_id = request.args.get('player_id', type=int)
return render_template('pages/add_note_from_tryout.html', return render_template('pages/add_note_from_tryout.html',
tryout=tryout, tryout=tryout,
players=players, players=players,
team_notes=team_notes) team_notes=team_notes,
preselected_player_id=preselected_player_id)
+2 -8
View File
@@ -95,15 +95,9 @@
</a> </a>
</li> </li>
<li> <li>
<a href="{{ url_for('users.manage_team_notes') }}" class="{% if request.endpoint == 'users.manage_team_notes' %}active{% endif %}"> <a href="{{ url_for('users.notes_dashboard') }}" class="{% if request.endpoint == 'users.notes_dashboard' or request.endpoint == 'users.manage_team_notes' or request.endpoint == 'users.manage_personal_notes' %}active{% endif %}">
<i class="fas fa-users"></i>
<span>Team Notes</span>
</a>
</li>
<li>
<a href="{{ url_for('users.manage_personal_notes') }}" class="{% if request.endpoint == 'users.manage_personal_notes' %}active{% endif %}">
<i class="fas fa-sticky-note"></i> <i class="fas fa-sticky-note"></i>
<span>Personal Notes</span> <span>Notes</span>
</a> </a>
</li> </li>
{% endif %} {% endif %}
+1 -1
View File
@@ -18,7 +18,7 @@
<select name="player_id" id="player_id" class="form-select" required> <select name="player_id" id="player_id" class="form-select" required>
<option value="">-- Select a Player --</option> <option value="">-- Select a Player --</option>
{% for player in players %} {% for player in players %}
<option value="{{ player.id }}">{{ player.full_name }}</option> <option value="{{ player.id }}" {% if preselected_player_id == player.id %}selected{% endif %}>{{ player.full_name }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
+3
View File
@@ -127,6 +127,9 @@
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i> {% if existing_eval %}Update Evaluation{% else %}Submit Evaluation{% endif %} <i class="fas fa-save"></i> {% if existing_eval %}Update Evaluation{% else %}Submit Evaluation{% endif %}
</button> </button>
<a href="{{ url_for('users.notes_dashboard') }}" class="btn btn-outline" title="Add note for this player">
<i class="fas fa-sticky-note"></i> Add Note
</a>
</div> </div>
</form> </form>
</div> </div>
+172
View File
@@ -0,0 +1,172 @@
{% extends "layouts/base.html" %}
{% block title %}Notes - TryoutPro{% endblock %}
{% block page_title %}Notes{% endblock %}
{% block breadcrumb %}<span class="breadcrumb">Home / Notes</span>{% endblock %}
{% block content %}
<div class="dashboard-grid">
<!-- Add Team Notes Section -->
{% if org_team %}
<div class="card">
<div class="card-header">
<h3><i class="fas fa-users"></i> Team Notes</h3>
<span class="badge badge-esport">{{ org_team.name }}</span>
</div>
<div class="card-body">
<form method="POST" action="{{ url_for('users.manage_team_notes') }}" class="form" id="teamNotesForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<div class="form-group">
<label for="team_notes_content">Team Notes Content</label>
<textarea name="content" id="team_notes_content" class="form-textarea" rows="4" placeholder="Enter improvement suggestions and notes for your team...">{{ latest_team_note.content if latest_team_note else '' }}</textarea>
<p class="form-text">These notes will be visible to all players on your team.</p>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i> {% if latest_team_note %}Update{% else %}Add{% endif %} Team Notes
</button>
</div>
</form>
</div>
</div>
{% endif %}
<!-- Add Personal Note Section -->
<div class="card">
<div class="card-header">
<h3><i class="fas fa-user-friends"></i> Add Personal Note</h3>
{% if org_team %}
<span class="badge badge-esport">{{ org_team.name }}</span>
{% endif %}
</div>
<div class="card-body">
<form method="POST" action="{{ url_for('users.add_personal_note') }}" class="form" id="personalNoteForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<div class="form-group">
<label for="player_id">Select Player</label>
<select name="player_id" id="player_id" class="form-select" required>
<option value="">-- Select a Player --</option>
{% for player in players %}
<option value="{{ player.id }}">{{ player.full_name }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="note_content">Note Content</label>
<textarea name="content" id="note_content" class="form-textarea" rows="3" placeholder="Enter personal feedback or coaching tips for this player..." required></textarea>
<p class="form-text">These notes will only be visible to the selected player.</p>
</div>
<div class="form-group">
<label for="context">Context (Optional)</label>
<p class="form-text text-muted">Link this note to a specific match, tryout, or team for better organization.</p>
<div class="form-row">
<div class="form-group">
<label for="note_match_id">Match</label>
<select name="match_id" id="note_match_id" class="form-select">
<option value="">-- Select Match --</option>
{% for match in matches %}
<option value="{{ match.id }}">{{ match.title }} - {{ match.date.strftime('%m/%d/%Y') }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="note_tryout_id">Tryout</label>
<select name="tryout_id" id="note_tryout_id" class="form-select">
<option value="">-- Select Tryout --</option>
{% for tryout in tryouts %}
<option value="{{ tryout.id }}">{{ tryout.title }} - {{ tryout.date.strftime('%m/%d/%Y') }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="note_team_id">Team</label>
<select name="team_id" id="note_team_id" class="form-select">
<option value="">-- Select Team --</option>
{% for team in teams %}
<option value="{{ team.id }}">{{ team.name }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i> Add Note
</button>
</div>
</form>
</div>
</div>
</div>
<div class="dashboard-grid mt-4">
<!-- Team Notes History -->
{% if org_team and team_notes %}
<div class="card">
<div class="card-header">
<h3><i class="fas fa-history"></i> Team Notes History</h3>
</div>
<div class="card-body">
<table class="table">
<thead>
<tr>
<th>Last Updated</th>
<th>Content Preview</th>
</tr>
</thead>
<tbody>
{% for note in team_notes %}
<tr>
<td>{{ note.updated_at.strftime('%B %d, %Y at %I:%M %p') if note.updated_at else 'Unknown date' }}</td>
<td>{{ note.content[:100] if note.content else '' }}{% if note.content and note.content|length > 100 %}...{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
<!-- Personal Notes History -->
{% if personal_notes %}
<div class="card">
<div class="card-header">
<h3><i class="fas fa-sticky-note"></i> Recent Personal Notes</h3>
</div>
<div class="card-body">
<div class="detail-grid">
{% for note in personal_notes %}
<div class="detail-item full-width mb-4">
<span class="detail-label">
<i class="fas fa-user"></i> {{ note.player.full_name if note.player else 'Unknown Player' }} -
<span class="text-muted">{{ note.created_at.strftime('%B %d, %Y') if note.created_at else 'Unknown date' }}</span>
</span>
<span class="detail-value">{{ note.content | nl2br if note.content else '' }}</span>
<span class="detail-label text-muted small">From: {{ note.coach.full_name if note.coach else 'Unknown Coach' }}</span>
{% if note.match_id or note.team_id or note.tryout_id %}
<div class="mt-2">
{% if note.match_id and note.match %}
<span class="badge badge-info" title="From match"><i class="fas fa-futbol"></i> {{ note.match.title }}</span>
{% endif %}
{% if note.team_id and note.team %}
<span class="badge badge-warning" title="From team"><i class="fas fa-users"></i> {{ note.team.name }}</span>
{% endif %}
{% if note.tryout_id and note.tryout %}
<span class="badge badge-success" title="From tryout"><i class="fas fa-calendar-alt"></i> {{ note.tryout.title }}</span>
{% endif %}
</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}
</div>
{% endblock %}
+5
View File
@@ -66,6 +66,11 @@
</button> </button>
</form> </form>
{% endif %} {% endif %}
{% if current_user.role == 'coach' and team.coach_id == current_user.id %}
<a href="{{ url_for('users.notes_dashboard') }}" class="btn btn-sm btn-primary" title="Add Notes">
<i class="fas fa-sticky-note"></i> Notes
</a>
{% endif %}
</div> </div>
</div> </div>
<div class="card-body"> <div class="card-body">
+5 -2
View File
@@ -155,10 +155,13 @@
<span class="badge badge-warning">Pending</span> <span class="badge badge-warning">Pending</span>
{% endif %} {% endif %}
</td> </td>
<td> <td class="eval-actions">
<a href="{{ url_for('evaluations.evaluate_player', tryout_id=tryout.id, player_id=p.id) }}" class="btn btn-sm btn-primary"> <a href="{{ url_for('evaluations.evaluate_player', tryout_id=tryout.id, player_id=p.id) }}" class="btn btn-sm btn-primary" title="Evaluate player">
<i class="fas fa-edit"></i> {% if player_eval_status.get(p.id) %}Edit{% else %}Evaluate{% endif %} <i class="fas fa-edit"></i> {% if player_eval_status.get(p.id) %}Edit{% else %}Evaluate{% endif %}
</a> </a>
<a href="{{ url_for('users.add_note_from_tryout', tryout_id=tryout.id) }}?player_id={{ p.id }}" class="btn btn-sm btn-outline" title="Add note for {{ p.full_name }}">
<i class="fas fa-sticky-note"></i>
</a>
</td> </td>
{% endif %} {% endif %}
</tr> </tr>