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:
+192
-110
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user