ajout d'un paneau admin

This commit is contained in:
cedrick2711
2026-08-25 13:29:22 -04:00
parent 9fc4ba0b98
commit 6232b77094
15 changed files with 1053 additions and 387 deletions
+95 -51
View File
@@ -708,6 +708,70 @@ def send_discord_notification(player_name, points, date_str, start_time_str, end
logger.warning(f"Failed to send Discord notification: {e}")
def _get_player_coach_options(player):
"""Build a deduplicated list of coaches (with their teams) for a player.
Returns a list of dicts:
[{'coach_id': int, 'coach_name': str, 'teams': [{'team_id': int, 'team_name': str}]}]
"""
coach_map = {}
for org_team in player.get_org_teams():
for coach in org_team.get_coaches():
entry = coach_map.setdefault(coach.id, {
'coach_id': coach.id,
'coach_name': coach.full_name or coach.username,
'teams': [],
})
entry['teams'].append({
'team_id': org_team.id,
'team_name': org_team.name,
})
return list(coach_map.values())
def _get_player_coach_ids(player):
"""Return the set of coach ids the player is allowed to request."""
return {c['coach_id'] for c in _get_player_coach_options(player)}
@users_bp.route('/one-on-one/coaches')
@login_required
def one_on_one_coaches():
"""API: list coaches (and their teams) available to the current player."""
if not isinstance(current_user, Player):
return jsonify({'error': 'Only players can request One on One sessions.'}), 403
coaches = _get_player_coach_options(current_user)
return jsonify({'coaches': coaches})
@users_bp.route('/one-on-one/coaches/<int:coach_id>/availability')
@login_required
def one_on_one_coach_availability(coach_id):
"""API: return a single coach's availability for the current player."""
if not isinstance(current_user, Player):
return jsonify({'error': 'Only players can request One on One sessions.'}), 403
if coach_id not in _get_player_coach_ids(current_user):
return jsonify({'error': 'Coach is not assigned to any of your teams.'}), 403
coach = User.query.get_or_404(coach_id)
availabilities = CoachAvailability.query.filter_by(coach_id=coach_id).all()
availability = [
{
'day_of_week': av.day_of_week,
'start_time': av.start_time.strftime('%H:%M'),
'end_time': av.end_time.strftime('%H:%M'),
}
for av in availabilities
]
return jsonify({
'coach_id': coach.id,
'coach_name': coach.full_name or coach.username,
'availability': availability,
})
@users_bp.route('/one-on-one', methods=['GET', 'POST'])
@login_required
def one_on_one():
@@ -716,41 +780,37 @@ def one_on_one():
flash('Only players can request One on One sessions.', 'danger')
return redirect(url_for('main.dashboard'))
org_teams = current_user.get_org_teams()
org_team = org_teams[0] if org_teams else None
coach = User.query.get(org_team.coach_id) if org_team and org_team.coach_id else None
if not coach:
flash('You do not have a coach assigned to your team.', 'info')
team_notes = []
if org_team:
team_notes = TeamNote.query.filter_by(org_team_id=org_team.id).order_by(TeamNote.created_at.desc()).all()
personal_notes = PersonalNote.query.filter_by(player_id=current_user.id).order_by(PersonalNote.created_at.desc()).all()
coach_availability = []
if coach:
availabilities = CoachAvailability.query.filter_by(coach_id=coach.id).all()
coach_availability = [
{
'day_of_week': av.day_of_week,
'start_time': av.start_time.strftime('%H:%M'),
'end_time': av.end_time.strftime('%H:%M'),
}
for av in availabilities
]
coach_options = _get_player_coach_options(current_user)
if request.method == 'POST':
coach_id = request.form.get('coach_id', type=int)
org_team_id = request.form.get('org_team_id', type=int)
date_str = request.form.get('date')
start_time_str = request.form.get('start_time')
end_time_str = request.form.get('end_time')
points = request.form.get('points', '').strip()
if not coach:
if not coach_options:
flash('Cannot request One on One - no coach assigned.', 'danger')
return redirect(url_for('users.one_on_one'))
if coach_id not in _get_player_coach_ids(current_user):
flash('Selected coach is not assigned to any of your teams.', 'danger')
return redirect(url_for('users.one_on_one'))
coach = User.query.get_or_404(coach_id)
# Validate org_team_id belongs to the player and includes this coach
org_team = None
if org_team_id:
org_team = OrgTeam.query.get(org_team_id)
if not org_team or org_team not in current_user.get_org_teams():
flash('Invalid team selection.', 'danger')
return redirect(url_for('users.one_on_one'))
if coach not in org_team.get_coaches():
flash('Selected coach is not part of the selected team.', 'danger')
return redirect(url_for('users.one_on_one'))
try:
date_obj = datetime.strptime(date_str, '%Y-%m-%d').date()
start_time = datetime.strptime(start_time_str, '%H:%M').time()
@@ -759,14 +819,14 @@ def one_on_one():
flash('Invalid date or time format.', 'danger')
return redirect(url_for('users.one_on_one'))
check_date = datetime.strptime(date_str, '%Y-%m-%d')
day_of_week = check_date.weekday()
day_of_week = date_obj.weekday()
availabilities = CoachAvailability.query.filter_by(coach_id=coach.id).all()
is_available = any(
av['day_of_week'] == day_of_week
and av['start_time'] <= start_time_str
and av['end_time'] >= end_time_str
for av in coach_availability
av.day_of_week == day_of_week
and av.start_time <= start_time
and av.end_time >= end_time
for av in availabilities
)
if not is_available:
@@ -796,30 +856,13 @@ def one_on_one():
flash('Your One on One request has been submitted!', 'success')
return redirect(url_for('users.one_on_one'))
# Build list of upcoming dates that have coach availability
from datetime import date as date_cls, timedelta as td
today = date_cls.today()
available_days = {av['day_of_week'] for av in coach_availability}
dates = []
for i in range(14): # Next 14 days
d = today + td(days=i)
if d.weekday() in available_days:
dates.append({
'value': d.strftime('%Y-%m-%d'),
'day_of_week': d.weekday(),
'display': d.strftime('%B %d, %Y (%A)'),
})
# Player's own One on One request history
my_requests = OneOnOneRequest.query.filter_by(
player_id=current_user.id
).order_by(OneOnOneRequest.created_at.desc()).all()
return render_template('pages/one_on_one.html',
org_team=org_team, coach=coach,
team_notes=team_notes, personal_notes=personal_notes,
coach_availability=coach_availability,
dates=dates,
coach_options=coach_options,
my_requests=my_requests)
@@ -1031,12 +1074,13 @@ def notes_dashboard():
coach_id=current_user.id,
).order_by(PersonalNote.created_at.desc()).all()
# One on One requests from team players
# One on One requests addressed to this coach from their team players
one_on_one_requests = []
if org_team and players:
player_ids_list = [p.id for p in players]
one_on_one_requests = OneOnOneRequest.query.filter(
OneOnOneRequest.player_id.in_(player_ids_list)
OneOnOneRequest.player_id.in_(player_ids_list),
OneOnOneRequest.coach_id == current_user.id,
).order_by(OneOnOneRequest.created_at.desc()).all()
# For context selectors in the form