ajout de match régulier pour les équipes et de pratiques

Ajout d'un profil public cliquable pour les utilisateurs
déplacement du profil
This commit is contained in:
cedrick2711
2026-07-28 12:39:53 -04:00
parent 69b6e217ae
commit b982cd0318
20 changed files with 2132 additions and 225 deletions
+192 -110
View File
@@ -16,8 +16,8 @@ teams_bp = Blueprint('teams', __name__, url_prefix='/teams')
def list_teams():
"""List all organization teams visible to the current user.
Coaches see only their assigned team. Players and scouts see all teams.
Managers and presidents see all teams and can manage them.
Coaches and managers see only their assigned teams.
President sees all teams.
Returns:
Response: Rendered teams list template.
@@ -25,21 +25,87 @@ def list_teams():
can_manage = current_user.can_manage_teams()
if current_user.role == 'coach':
org_team = OrgTeam.query.filter_by(coach_id=current_user.id).first()
teams = [org_team] if org_team else []
elif current_user.role in ['player', 'scout'] or can_manage:
# Players and scouts can view all teams; managers/presidents can manage
teams = OrgTeam.query.order_by(OrgTeam.name).all()
teams = OrgTeam.query.filter(
db.or_(
OrgTeam.coaches.any(id=current_user.id),
OrgTeam.coach_id == current_user.id
)
).order_by(OrgTeam.name).all()
elif current_user.role == 'manager':
teams = OrgTeam.query.filter(
db.or_(
OrgTeam.managers.any(id=current_user.id),
OrgTeam.manager_id == current_user.id
)
).order_by(OrgTeam.name).all()
elif current_user.role in ['player', 'scout']:
flash('Use My Team(s) to view your teams.', 'info')
return redirect(url_for('teams.my_teams'))
else:
flash('You do not have permission to view teams.', 'danger')
return redirect(url_for('main.dashboard'))
coaches = User.query.filter_by(role='coach').order_by(User.username).all()
managers = User.query.filter_by(role='manager').order_by(User.username).all()
coaches = User.query.filter_by(role='coach', is_active_account=True).order_by(User.username).all()
managers = User.query.filter_by(role='manager', is_active_account=True).order_by(User.username).all()
all_players = User.query.filter_by(role='player').order_by(User.username).all()
return render_template('pages/teams.html', teams=teams, coaches=coaches, managers=managers, all_players=all_players, can_manage=can_manage)
@teams_bp.route('/my-teams')
@login_required
def my_teams():
"""View the player's own teams with upcoming matches.
Players can see their team rosters, coaches, managers, and
upcoming team matches with presence confirmation toggles.
Returns:
Response: Rendered my_teams template.
"""
if current_user.role != 'player':
flash('This page is for players.', 'info')
return redirect(url_for('teams.list_teams'))
from models import TeamMatch, TeamMatchParticipant
from datetime import datetime
player_teams = current_user.get_org_teams()
team_data = []
now = datetime.utcnow()
for org_team in player_teams:
matches = TeamMatch.query.filter(
TeamMatch.org_team_id == org_team.id,
TeamMatch.status == 'scheduled'
).order_by(TeamMatch.date.asc(), TeamMatch.start_time.asc()).all()
matches_data = []
for tm in matches:
confirmed, total = tm.get_confirmed_count()
participant = TeamMatchParticipant.query.filter_by(
team_match_id=tm.id,
player_id=current_user.id
).first()
matches_data.append({
'match': tm,
'participant_id': participant.id if participant else None,
'is_confirmed': participant.is_confirmed if participant else False,
'confirmed_count': confirmed,
'total_count': total
})
team_data.append({
'team': org_team,
'matches': matches_data,
'coaches': org_team.get_coaches(),
'managers': org_team.get_managers()
})
return render_template('pages/my_teams.html',
team_data=team_data,
now=now)
@teams_bp.route('/create', methods=['POST'])
@login_required
def create_team():
@@ -77,6 +143,17 @@ def create_team():
created_by=current_user.id
)
db.session.add(team)
db.session.flush()
if coach_id:
coach_user = User.query.get(int(coach_id))
if coach_user:
team.coaches.append(coach_user)
if manager_id:
manager_user = User.query.get(int(manager_id))
if manager_user:
team.managers.append(manager_user)
db.session.commit()
flash(f'Team "{name}" created successfully!', 'success')
return redirect(url_for('teams.list_teams'))
@@ -85,17 +162,7 @@ def create_team():
@teams_bp.route('/<int:team_id>/edit', methods=['POST'])
@login_required
def edit_team(team_id):
"""Edit an existing organization team.
Args:
team_id: The ID of the team to edit.
name: New team name from form.
coach_id: New coach assignment from form.
manager_id: New manager assignment from form.
Returns:
Response: Redirect to teams list with status message.
"""
"""Edit an existing organization team."""
team = OrgTeam.query.get_or_404(team_id)
if not current_user.can_manage_this_org_team(team):
flash('You do not have permission to edit this team.', 'danger')
@@ -117,6 +184,16 @@ def edit_team(team_id):
team.name = name
team.coach_id = int(coach_id) if coach_id else None
team.manager_id = int(manager_id) if manager_id else None
if coach_id:
coach_user = User.query.get(int(coach_id))
if coach_user and not team.coaches.filter_by(id=coach_user.id).first():
team.coaches.append(coach_user)
if manager_id:
manager_user = User.query.get(int(manager_id))
if manager_user and not team.managers.filter_by(id=manager_user.id).first():
team.managers.append(manager_user)
db.session.commit()
flash(f'Team "{name}" updated successfully!', 'success')
return redirect(url_for('teams.list_teams'))
@@ -125,17 +202,7 @@ def edit_team(team_id):
@teams_bp.route('/<int:team_id>/delete', methods=['POST'])
@login_required
def delete_team(team_id):
"""Delete an organization team.
Removes the team and clears its target_org_team_id reference from
any linked tryouts before deletion.
Args:
team_id: The ID of the team to delete.
Returns:
Response: Redirect to teams list with status message.
"""
"""Delete an organization team."""
if not current_user.can_manage_teams():
flash('You do not have permission to delete teams.', 'danger')
return redirect(url_for('teams.list_teams'))
@@ -143,7 +210,6 @@ def delete_team(team_id):
team = OrgTeam.query.get_or_404(team_id)
name = team.name
# Check if any tryouts are targeting this team
from models import Tryout
tryouts = Tryout.query.filter_by(target_org_team_id=team_id).all()
if tryouts:
@@ -151,7 +217,6 @@ def delete_team(team_id):
t.target_org_team_id = None
db.session.commit()
# Remove all team_players associations
TeamPlayer.query.filter_by(org_team_id=team_id).delete()
db.session.commit()
@@ -161,23 +226,88 @@ def delete_team(team_id):
return redirect(url_for('teams.list_teams'))
@teams_bp.route('/<int:team_id>/remove_coach', methods=['POST'])
@teams_bp.route('/<int:team_id>/add_coach', methods=['POST'])
@login_required
def remove_coach(team_id):
"""Remove the coach from an organization team.
Args:
team_id: The ID of the team.
Returns:
Response: Redirect to teams list with status message.
"""
def add_coach(team_id):
"""Add a coach to an organization team (many-to-many)."""
team = OrgTeam.query.get_or_404(team_id)
if not current_user.can_manage_this_org_team(team):
flash('Permission denied.', 'danger')
return redirect(url_for('teams.list_teams'))
coach_id = request.form.get('coach_id')
if not coach_id:
flash('Please select a coach.', 'danger')
return redirect(url_for('teams.list_teams'))
coach = User.query.get_or_404(int(coach_id))
if coach.role != 'coach':
flash('Only coaches can be assigned as coach.', 'danger')
return redirect(url_for('teams.list_teams'))
if team.coaches.filter_by(id=coach.id).first():
flash(f'{coach.username} is already a coach of {team.name}.', 'info')
return redirect(url_for('teams.list_teams'))
team.coaches.append(coach)
if not team.coach_id:
team.coach_id = coach.id
db.session.commit()
flash(f'{coach.username} added as coach of {team.name}.', 'success')
return redirect(url_for('teams.list_teams'))
team.coach_id = None
@teams_bp.route('/<int:team_id>/add_manager', methods=['POST'])
@login_required
def add_manager(team_id):
"""Add a manager to an organization team (many-to-many)."""
team = OrgTeam.query.get_or_404(team_id)
if not current_user.can_manage_this_org_team(team):
flash('Permission denied.', 'danger')
return redirect(url_for('teams.list_teams'))
manager_id = request.form.get('manager_id')
if not manager_id:
flash('Please select a manager.', 'danger')
return redirect(url_for('teams.list_teams'))
manager = User.query.get_or_404(int(manager_id))
if manager.role != 'manager':
flash('Only managers can be assigned as manager.', 'danger')
return redirect(url_for('teams.list_teams'))
if team.managers.filter_by(id=manager.id).first():
flash(f'{manager.username} is already a manager of {team.name}.', 'info')
return redirect(url_for('teams.list_teams'))
team.managers.append(manager)
if not team.manager_id:
team.manager_id = manager.id
db.session.commit()
flash(f'{manager.username} added as manager of {team.name}.', 'success')
return redirect(url_for('teams.list_teams'))
@teams_bp.route('/<int:team_id>/remove_coach', methods=['POST'])
@login_required
def remove_coach(team_id):
"""Remove a coach from an organization team."""
team = OrgTeam.query.get_or_404(team_id)
if not current_user.can_manage_this_org_team(team):
flash('Permission denied.', 'danger')
return redirect(url_for('teams.list_teams'))
coach_id = request.form.get('coach_id')
if coach_id:
coach = User.query.get(int(coach_id))
if coach and team.coaches.filter_by(id=coach.id).first():
team.coaches.remove(coach)
if team.coach_id == coach.id:
team.coach_id = None
else:
team.coaches = []
team.coach_id = None
db.session.commit()
flash(f'Coach removed from {team.name}.', 'success')
return redirect(url_for('teams.list_teams'))
@@ -186,20 +316,23 @@ def remove_coach(team_id):
@teams_bp.route('/<int:team_id>/remove_manager', methods=['POST'])
@login_required
def remove_manager(team_id):
"""Remove the manager from an organization team.
Args:
team_id: The ID of the team.
Returns:
Response: Redirect to teams list with status message.
"""
"""Remove a manager from an organization team."""
team = OrgTeam.query.get_or_404(team_id)
if not current_user.can_manage_this_org_team(team):
flash('Permission denied.', 'danger')
return redirect(url_for('teams.list_teams'))
team.manager_id = None
manager_id = request.form.get('manager_id')
if manager_id:
manager = User.query.get(int(manager_id))
if manager and team.managers.filter_by(id=manager.id).first():
team.managers.remove(manager)
if team.manager_id == manager.id:
team.manager_id = None
else:
team.managers = []
team.manager_id = None
db.session.commit()
flash(f'Manager removed from {team.name}.', 'success')
return redirect(url_for('teams.list_teams'))
@@ -208,18 +341,7 @@ def remove_manager(team_id):
@teams_bp.route('/<int:team_id>/add_player', methods=['POST'])
@login_required
def add_player(team_id):
"""Add a player to an organization team.
Players can now be in multiple teams.
Args:
team_id: The ID of the team to add the player to.
player_id: The ID of the player to add.
status: The player's status (starter or substitute).
Returns:
Response: Redirect to teams list with status message.
"""
"""Add a player to an organization team."""
team = OrgTeam.query.get_or_404(team_id)
if not current_user.can_manage_this_org_team(team):
flash('Permission denied.', 'danger')
@@ -236,13 +358,11 @@ def add_player(team_id):
flash('Can only assign players to teams.', 'danger')
return redirect(url_for('teams.list_teams'))
# Check if player is already on this team
existing = TeamPlayer.query.filter_by(player_id=player.id, org_team_id=team.id).first()
if existing:
flash(f'{player.username} is already on {team.name}.', 'info')
return redirect(url_for('teams.list_teams'))
# Add player to the team using TeamPlayer model (allows multiple teams)
tp = TeamPlayer(
player_id=player.id,
org_team_id=team.id,
@@ -257,15 +377,7 @@ def add_player(team_id):
@teams_bp.route('/<int:team_id>/remove_player/<int:player_id>', methods=['POST'])
@login_required
def remove_player(team_id, player_id):
"""Remove a player from an organization team.
Args:
team_id: The ID of the team.
player_id: The ID of the player to remove.
Returns:
Response: Redirect to teams list with status message.
"""
"""Remove a player from an organization team."""
team = OrgTeam.query.get_or_404(team_id)
if not current_user.can_manage_this_org_team(team):
flash('Permission denied.', 'danger')
@@ -287,15 +399,7 @@ def remove_player(team_id, player_id):
@teams_bp.route('/<int:team_id>/toggle_status/<int:player_id>', methods=['POST'])
@login_required
def toggle_player_status(team_id, player_id):
"""Toggle a player's status between starter and substitute.
Args:
team_id: The ID of the team.
player_id: The ID of the player.
Returns:
Response: JSON with new status.
"""
"""Toggle a player's status between starter and substitute."""
team = OrgTeam.query.get_or_404(team_id)
if not current_user.can_manage_this_org_team(team):
return jsonify({'error': 'Permission denied'}), 403
@@ -304,7 +408,6 @@ def toggle_player_status(team_id, player_id):
if not tp:
return jsonify({'error': 'Player not found on this team'}), 404
# Toggle status
tp.status = 'substitute' if tp.status == 'starter' else 'starter'
db.session.commit()
@@ -316,23 +419,12 @@ def toggle_player_status(team_id, player_id):
})
# Note actions from team page
@teams_bp.route('/<int:team_id>/add-team-note', methods=['POST'])
@login_required
def add_team_note(team_id):
"""Add a team improvement note from the team page (for coaches).
Args:
team_id: The ID of the team to add notes for.
Returns:
Response: Redirect to teams list with status message.
"""
"""Add a team improvement note from the team page (for coaches)."""
team = OrgTeam.query.get_or_404(team_id)
# Check if user can manage this team (president, manager, or coach)
if not current_user.can_manage_this_org_team(team):
flash('You do not have permission to add notes to this team.', 'danger')
return redirect(url_for('teams.list_teams'))
@@ -355,18 +447,9 @@ def add_team_note(team_id):
@teams_bp.route('/<int:team_id>/add-player-note/<int:player_id>', methods=['POST'])
@login_required
def add_player_note(team_id, player_id):
"""Add a personal note for a player from the team page (for coaches).
Args:
team_id: The ID of the team.
player_id: The ID of the player to add note for.
Returns:
Response: Redirect to teams list with status message.
"""
"""Add a personal note for a player from the team page (for coaches)."""
team = OrgTeam.query.get_or_404(team_id)
# Check if user can manage this team (president, manager, or coach)
if not current_user.can_manage_this_org_team(team):
flash('You do not have permission to add notes to this team.', 'danger')
return redirect(url_for('teams.list_teams'))
@@ -376,7 +459,6 @@ def add_player_note(team_id, player_id):
flash('Can only add notes for players.', 'danger')
return redirect(url_for('teams.list_teams'))
# Verify player belongs to this team
tp = TeamPlayer.query.filter_by(player_id=player_id, org_team_id=team_id).first()
if not tp:
flash(f'{player.username} is not on {team.name}.', 'danger')