first commit
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}Team Tryout Management{% endblock %}</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🏆</text></svg>">
|
||||
</head>
|
||||
<body>
|
||||
{% if current_user.is_authenticated %}
|
||||
<nav class="sidebar" id="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<div class="logo">
|
||||
<i class="fas fa-trophy"></i>
|
||||
<span>TryoutPro</span>
|
||||
</div>
|
||||
<div class="user-badge">
|
||||
<div class="user-avatar">
|
||||
{{ current_user.full_name[:2] | upper }}
|
||||
</div>
|
||||
<div class="user-info">
|
||||
<span class="user-name">{{ current_user.full_name }}</span>
|
||||
<span class="user-role role-{{ current_user.role }}">{{ current_user.role | capitalize }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="nav-links">
|
||||
<li>
|
||||
<a href="{{ url_for('main.dashboard') }}" class="{% if request.endpoint and 'dashboard' in request.endpoint %}active{% endif %}">
|
||||
<i class="fas fa-th-large"></i>
|
||||
<span>Dashboard</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ url_for('tryouts.list_tryouts') }}" class="{% if request.endpoint and 'tryouts' in request.endpoint and request.endpoint != 'tryouts.create_tryout' %}active{% endif %}">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<span>Tryouts</span>
|
||||
</a>
|
||||
</li>
|
||||
{% if current_user.can_evaluate() %}
|
||||
<li>
|
||||
<a href="{{ url_for('evaluations.list_evaluations') }}" class="{% if request.endpoint and 'evaluations' in request.endpoint %}active{% endif %}">
|
||||
<i class="fas fa-clipboard-check"></i>
|
||||
<span>Evaluations</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="{{ url_for('teams.list_teams') }}" class="{% if request.endpoint and 'teams' in request.endpoint %}active{% endif %}">
|
||||
<i class="fas fa-users-cog"></i>
|
||||
<span>Teams</span>
|
||||
</a>
|
||||
</li>
|
||||
{% if current_user.can_manage_users() %}
|
||||
<li>
|
||||
<a href="{{ url_for('users.list_users') }}" class="{% if request.endpoint and 'users' in request.endpoint and request.endpoint != 'users.profile' %}active{% endif %}">
|
||||
<i class="fas fa-users-cog"></i>
|
||||
<span>Manage Users</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="{{ url_for('users.profile') }}" class="{% if request.endpoint == 'users.profile' %}active{% endif %}">
|
||||
<i class="fas fa-user"></i>
|
||||
<span>My Profile</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-divider"></li>
|
||||
<li>
|
||||
<a href="{{ url_for('auth.logout') }}" class="logout-link">
|
||||
<i class="fas fa-sign-out-alt"></i>
|
||||
<span>Logout</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div class="main-content" id="mainContent">
|
||||
<header class="top-bar">
|
||||
<button class="sidebar-toggle" id="sidebarToggle" onclick="toggleSidebar()">
|
||||
<i class="fas fa-bars"></i>
|
||||
</button>
|
||||
<div class="page-header">
|
||||
<h1>{% block page_title %}Dashboard{% endblock %}</h1>
|
||||
{% block breadcrumb %}{% endblock %}
|
||||
</div>
|
||||
{% block header_actions %}{% endblock %}
|
||||
</header>
|
||||
<div class="flash-messages">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="alert alert-{{ category }} alert-dismissible">
|
||||
<span>{{ message }}</span>
|
||||
<button type="button" class="alert-close" onclick="this.parentElement.remove()">×</button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
<div class="content">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="auth-wrapper">
|
||||
<div class="flash-messages">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="alert alert-{{ category }} alert-dismissible">
|
||||
<span>{{ message }}</span>
|
||||
<button type="button" class="alert-close" onclick="this.parentElement.remove()">×</button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
<div class="auth-container">
|
||||
<div class="auth-header">
|
||||
<i class="fas fa-trophy"></i>
|
||||
<h2>TryoutPro</h2>
|
||||
<p>Team Tryout Management System</p>
|
||||
</div>
|
||||
{% block auth_content %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,53 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Create Tryout - TryoutPro{% endblock %}
|
||||
{% block page_title %}Create Tryout{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / <a href="{{ url_for('tryouts.list_tryouts') }}">Tryouts</a> / Create</span>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ url_for('tryouts.create_tryout') }}" class="form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-12">
|
||||
<label for="title">Tryout Title</label>
|
||||
<input type="text" id="title" name="title" placeholder="e.g., Spring Season Tryouts" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-6">
|
||||
<label for="date">Date</label>
|
||||
<input type="date" id="date" name="date" required>
|
||||
</div>
|
||||
<div class="form-group col-6">
|
||||
<label for="location">Location</label>
|
||||
<input type="text" id="location" name="location" placeholder="e.g., Main Field">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-6">
|
||||
<label for="max_players">Max Players</label>
|
||||
<input type="number" id="max_players" name="max_players" placeholder="Leave blank for unlimited" min="1">
|
||||
</div>
|
||||
<div class="form-group col-6">
|
||||
<label for="target_org_team_id">Target Team</label>
|
||||
<select id="target_org_team_id" name="target_org_team_id" class="form-select">
|
||||
<option value="">-- No target team --</option>
|
||||
{% for team in org_teams %}
|
||||
<option value="{{ team.id }}">{{ team.name }}{% if team.coach %} (Coach: {{ team.coach.full_name }}){% endif %}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<textarea id="description" name="description" rows="4" placeholder="Enter any details about the tryout..."></textarea>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<a href="{{ url_for('tryouts.list_tryouts') }}" class="btn btn-secondary">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">Create Tryout</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,52 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Create User - TryoutPro{% endblock %}
|
||||
{% block page_title %}Create User{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / <a href="{{ url_for('users.list_users') }}">Users</a> / Create</span>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ url_for('users.create_user') }}" class="form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-6">
|
||||
<label for="full_name">Full Name</label>
|
||||
<input type="text" id="full_name" name="full_name" placeholder="Enter full name" required>
|
||||
</div>
|
||||
<div class="form-group col-6">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" id="username" name="username" placeholder="Choose username" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-6">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" id="email" name="email" placeholder="Enter email" required>
|
||||
</div>
|
||||
<div class="form-group col-3">
|
||||
<label for="phone">Phone</label>
|
||||
<input type="tel" id="phone" name="phone" placeholder="Phone number">
|
||||
</div>
|
||||
<div class="form-group col-3">
|
||||
<label for="role">Role</label>
|
||||
<select id="role" name="role" required>
|
||||
{% for r in roles %}
|
||||
<option value="{{ r }}">{{ r | capitalize }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-6">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" placeholder="Set password" required minlength="6">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<a href="{{ url_for('users.list_users') }}" class="btn btn-secondary">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">Create User</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,330 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Dashboard - TryoutPro{% endblock %}
|
||||
{% block page_title %}Dashboard{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / Dashboard</span>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="dashboard">
|
||||
{% if user.role == 'president' %}
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-primary">
|
||||
<i class="fas fa-users"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.total_users }}</h3>
|
||||
<p>Total Users</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-success">
|
||||
<i class="fas fa-user-friends"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.total_players }}</h3>
|
||||
<p>Players</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-warning">
|
||||
<i class="fas fa-calendar-check"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.total_tryouts }}</h3>
|
||||
<p>Total Tryouts</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-info">
|
||||
<i class="fas fa-clipboard-list"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.total_evaluations }}</h3>
|
||||
<p>Evaluations</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-danger">
|
||||
<i class="fas fa-play-circle"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.active_tryouts }}</h3>
|
||||
<p>Active Tryouts</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-secondary">
|
||||
<i class="fas fa-clock"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.upcoming_tryouts }}</h3>
|
||||
<p>Upcoming</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-grid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-user-plus"></i> Recent Users</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr><th>Name</th><th>Role</th><th>Joined</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for u in stats.recent_users %}
|
||||
<tr>
|
||||
<td>{{ u.full_name }}</td>
|
||||
<td><span class="badge badge-{{ u.role }}">{{ u.role }}</span></td>
|
||||
<td>{{ u.created_at.strftime('%m/%d/%Y') }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-calendar-alt"></i> Recent Tryouts</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr><th>Title</th><th>Date</th><th>Status</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for t in stats.recent_tryouts %}
|
||||
<tr>
|
||||
<td><a href="{{ url_for('tryouts.view_tryout', tryout_id=t.id) }}">{{ t.title }}</a></td>
|
||||
<td>{{ t.date.strftime('%m/%d/%Y') }}</td>
|
||||
<td><span class="badge badge-{{ t.status }}">{{ t.status }}</span></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% elif user.role == 'manager' %}
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-primary">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.total_tryouts }}</h3>
|
||||
<p>My Tryouts</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-success">
|
||||
<i class="fas fa-play-circle"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.active_tryouts }}</h3>
|
||||
<p>Active</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-info">
|
||||
<i class="fas fa-clipboard-check"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.total_evaluations }}</h3>
|
||||
<p>My Evaluations</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-calendar"></i> My Tryouts</h3>
|
||||
<a href="{{ url_for('tryouts.create_tryout') }}" class="btn btn-sm btn-primary">+ New Tryout</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr><th>Title</th><th>Date</th><th>Status</th><th>Players</th><th>Actions</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for t in stats.my_tryouts %}
|
||||
<tr>
|
||||
<td>{{ t.title }}</td>
|
||||
<td>{{ t.date.strftime('%m/%d/%Y') }}</td>
|
||||
<td><span class="badge badge-{{ t.status }}">{{ t.status }}</span></td>
|
||||
<td>{{ t.registrations.count() }}</td>
|
||||
<td><a href="{{ url_for('tryouts.view_tryout', tryout_id=t.id) }}" class="btn btn-sm btn-outline">View</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if not stats.my_tryouts %}
|
||||
<tr><td colspan="5" class="text-center">No tryouts yet. <a href="{{ url_for('tryouts.create_tryout') }}">Create one</a></td></tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% elif user.role == 'coach' %}
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-primary">
|
||||
<i class="fas fa-clipboard-check"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.my_evaluations }}</h3>
|
||||
<p>Evaluations Done</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-warning">
|
||||
<i class="fas fa-hourglass-half"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.pending_evaluations }}</h3>
|
||||
<p>Pending</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-history"></i> Recent Evaluations</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr><th>Player</th><th>Tryout</th><th>Score</th><th>Date</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for e in stats.my_recent_evaluations %}
|
||||
<tr>
|
||||
<td>{{ e.player.full_name }}</td>
|
||||
<td>{{ e.tryout.title }}</td>
|
||||
<td><span class="score">{{ e.overall_score }}</span></td>
|
||||
<td>{{ e.created_at.strftime('%m/%d/%Y') }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% elif user.role == 'player' %}
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-primary">
|
||||
<i class="fas fa-calendar-check"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.my_tryouts }}</h3>
|
||||
<p>My Tryouts</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-success">
|
||||
<i class="fas fa-star"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ "%.1f"|format(stats.average_score) if stats.average_score else 'N/A' }}</h3>
|
||||
<p>Avg Score</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-info">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.my_evaluations }}</h3>
|
||||
<p>Evaluations</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dashboard-grid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-clipboard-list"></i> My Registrations</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead><tr><th>Tryout</th><th>Date</th><th>Status</th></tr></thead>
|
||||
<tbody>
|
||||
{% for r in stats.my_registrations %}
|
||||
<tr>
|
||||
<td><a href="{{ url_for('tryouts.view_tryout', tryout_id=r.tryout.id) }}">{{ r.tryout.title }}</a></td>
|
||||
<td>{{ r.tryout.date.strftime('%m/%d/%Y') }}</td>
|
||||
<td><span class="badge badge-{{ r.status }}">{{ r.status }}</span></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-star"></i> My Evaluations</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead><tr><th>Tryout</th><th>Evaluator</th><th>Score</th><th>Date</th></tr></thead>
|
||||
<tbody>
|
||||
{% for e in stats.my_eval_list %}
|
||||
<tr>
|
||||
<td>{{ e.tryout.title }}</td>
|
||||
<td>{{ e.evaluator.full_name }}</td>
|
||||
<td><span class="score">{{ e.overall_score }}</span></td>
|
||||
<td>{{ e.created_at.strftime('%m/%d/%Y') }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% elif user.role == 'scout' %}
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-primary">
|
||||
<i class="fas fa-user-friends"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.total_players }}</h3>
|
||||
<p>Total Players</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon bg-info">
|
||||
<i class="fas fa-clipboard-list"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ stats.total_evaluations }}</h3>
|
||||
<p>Total Evaluations</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-trophy"></i> Top Rated Players</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead><tr><th>#</th><th>Player</th><th>Avg Score</th></tr></thead>
|
||||
<tbody>
|
||||
{% for player, score in stats.top_players %}
|
||||
<tr>
|
||||
<td>{{ loop.index }}</td>
|
||||
<td>{{ player.full_name }}</td>
|
||||
<td><span class="score">{{ score }}</span></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if not stats.top_players %}
|
||||
<tr><td colspan="3" class="text-center">No evaluations yet.</td></tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,75 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Edit Profile - TryoutPro{% endblock %}
|
||||
{% block page_title %}Edit Profile{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / <a href="{{ url_for('users.profile') }}">Profile</a> / Edit</span>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ url_for('users.edit_profile') }}" class="form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-6">
|
||||
<label for="full_name">Full Name</label>
|
||||
<input type="text" id="full_name" name="full_name" value="{{ user.full_name }}" required>
|
||||
</div>
|
||||
<div class="form-group col-6">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" id="email" name="email" value="{{ user.email }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-6">
|
||||
<label for="phone">Phone</label>
|
||||
<input type="tel" id="phone" name="phone" value="{{ user.phone or '' }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="section-divider">
|
||||
<h4 class="section-title"><i class="fas fa-gamepad"></i> E-Sports Profile</h4>
|
||||
<p class="text-muted small">Update your competitive gaming profile for tryouts.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label><i class="fas fa-headset"></i> Games You Play</label>
|
||||
<div class="checkbox-grid">
|
||||
{% for game in esport_games %}
|
||||
{% set games_list = user.get_games_list() %}
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" name="games" value="{{ game }}" {% if game in games_list %}checked{% endif %}>
|
||||
<span>{{ game }}</span>
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<small class="form-text text-muted">Select all games you're signing in for.</small>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-4">
|
||||
<label for="trn_username"><i class="fas fa-chart-line"></i> TRN Username</label>
|
||||
<input type="text" id="trn_username" name="trn_username" value="{{ user.trn_username or '' }}" placeholder="Your Tracker Network username">
|
||||
<small class="form-text text-muted">Others can click your TRN to view your stats on tracker.gg.</small>
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<label for="discord_username"><i class="fab fa-discord"></i> Discord Username</label>
|
||||
<input type="text" id="discord_username" name="discord_username" value="{{ user.discord_username or '' }}" placeholder="e.g. Name#1234">
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<label for="league_os_profile"><i class="fas fa-link"></i> League OS Connection</label>
|
||||
<input type="text" id="league_os_profile" name="league_os_profile" value="{{ user.league_os_profile or '' }}" placeholder="League OS profile link or ID">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="section-divider">
|
||||
<h4 class="section-title"><i class="fas fa-lock"></i> Change Password</h4>
|
||||
<p class="text-muted small">Leave blank to keep your current password.</p>
|
||||
<div class="form-group">
|
||||
<label for="password">New Password</label>
|
||||
<input type="password" id="password" name="password" placeholder="Enter new password">
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<a href="{{ url_for('users.profile') }}" class="btn btn-secondary">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,55 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Edit Tryout - TryoutPro{% endblock %}
|
||||
{% block page_title %}Edit Tryout{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / <a href="{{ url_for('tryouts.list_tryouts') }}">Tryouts</a> / <a href="{{ url_for('tryouts.view_tryout', tryout_id=tryout.id) }}">{{ tryout.title }}</a> / Edit</span>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ url_for('tryouts.edit_tryout', tryout_id=tryout.id) }}" class="form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-12">
|
||||
<label for="title">Tryout Title</label>
|
||||
<input type="text" id="title" name="title" value="{{ tryout.title }}" placeholder="e.g., Spring Season Tryouts" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-6">
|
||||
<label for="date">Date</label>
|
||||
<input type="date" id="date" name="date" value="{{ tryout.date.strftime('%Y-%m-%d') }}" required>
|
||||
</div>
|
||||
<div class="form-group col-6">
|
||||
<label for="location">Location</label>
|
||||
<input type="text" id="location" name="location" value="{{ tryout.location or '' }}" placeholder="e.g., Main Field">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-6">
|
||||
<label for="max_players">Max Players</label>
|
||||
<input type="number" id="max_players" name="max_players" value="{{ tryout.max_players or '' }}" placeholder="Leave blank for unlimited" min="1">
|
||||
</div>
|
||||
<div class="form-group col-6">
|
||||
<label for="target_org_team_id">Target Team</label>
|
||||
<select id="target_org_team_id" name="target_org_team_id" class="form-select">
|
||||
<option value="">-- No target team --</option>
|
||||
{% for team in org_teams %}
|
||||
<option value="{{ team.id }}" {% if tryout.target_org_team_id == team.id %}selected{% endif %}>
|
||||
{{ team.name }}{% if team.coach %} (Coach: {{ team.coach.full_name }}){% endif %}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<textarea id="description" name="description" rows="4" placeholder="Enter any details about the tryout...">{{ tryout.description or '' }}</textarea>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<a href="{{ url_for('tryouts.view_tryout', tryout_id=tryout.id) }}" class="btn btn-secondary">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,83 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Edit {{ user.full_name }} - TryoutPro{% endblock %}
|
||||
{% block page_title %}Edit User{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / <a href="{{ url_for('users.list_users') }}">Users</a> / Edit</span>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ url_for('users.edit_user', user_id=user.id) }}" class="form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-6">
|
||||
<label for="full_name">Full Name</label>
|
||||
<input type="text" id="full_name" name="full_name" value="{{ user.full_name }}" required>
|
||||
</div>
|
||||
<div class="form-group col-6">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" id="email" name="email" value="{{ user.email }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-4">
|
||||
<label for="phone">Phone</label>
|
||||
<input type="tel" id="phone" name="phone" value="{{ user.phone or '' }}">
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<label for="role">Role</label>
|
||||
<select id="role" name="role" required>
|
||||
{% for r in roles %}
|
||||
<option value="{{ r }}" {% if user.role == r %}selected{% endif %}>{{ r | capitalize }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<label for="is_active_account">
|
||||
<input type="checkbox" id="is_active_account" name="is_active_account" {% if user.is_active_account %}checked{% endif %}>
|
||||
Active Account
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="section-divider">
|
||||
<h4 class="section-title"><i class="fas fa-gamepad"></i> E-Sports Profile</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Games</label>
|
||||
<div class="checkbox-grid">
|
||||
{% for game in esport_games %}
|
||||
{% set games_list = user.get_games_list() %}
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" name="games" value="{{ game }}" {% if game in games_list %}checked{% endif %}>
|
||||
<span>{{ game }}</span>
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-4">
|
||||
<label for="trn_username">TRN (Tracker Network) Username</label>
|
||||
<input type="text" id="trn_username" name="trn_username" value="{{ user.trn_username or '' }}" placeholder="Tracker Network username">
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<label for="discord_username">Discord Username</label>
|
||||
<input type="text" id="discord_username" name="discord_username" value="{{ user.discord_username or '' }}" placeholder="e.g. Name#1234">
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<label for="league_os_profile">League OS Connection</label>
|
||||
<input type="text" id="league_os_profile" name="league_os_profile" value="{{ user.league_os_profile or '' }}" placeholder="League OS profile link or ID">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password">New Password <small>(leave blank to keep current)</small></label>
|
||||
<input type="password" id="password" name="password" placeholder="Enter new password">
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<a href="{{ url_for('users.list_users') }}" class="btn btn-secondary">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">Update User</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,120 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Evaluate {{ player.full_name }} - TryoutPro{% endblock %}
|
||||
{% block page_title %}Evaluate {{ player.full_name }}{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / <a href="{{ url_for('tryouts.view_tryout', tryout_id=tryout.id) }}">{{ tryout.title }}</a> / Evaluate</span>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="dashboard-grid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-clipboard-list"></i> Player Evaluation</h3>
|
||||
<span class="badge badge-info">{{ tryout.title }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="eval-player-info mb-4">
|
||||
<div class="user-avatar avatar-lg">{{ player.full_name[:2] | upper }}</div>
|
||||
<div>
|
||||
<h3>{{ player.full_name }}</h3>
|
||||
<p class="text-muted">{{ player.email }} | {{ player.phone or 'No phone' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if existing_eval %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle"></i> You have already evaluated this player. Your previous scores are shown below.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="POST" action="{{ url_for('evaluations.evaluate_player', tryout_id=tryout.id, player_id=player.id) }}" class="form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-4">
|
||||
<label for="speed_score">Speed (1-10)</label>
|
||||
<div class="score-input">
|
||||
<input type="range" id="speed_score" name="speed_score" min="1" max="10" value="{{ existing_eval.speed_score or 5 }}" oninput="this.nextElementSibling.textContent = this.value">
|
||||
<span class="range-value">{{ existing_eval.speed_score or 5 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<label for="agility_score">Agility (1-10)</label>
|
||||
<div class="score-input">
|
||||
<input type="range" id="agility_score" name="agility_score" min="1" max="10" value="{{ existing_eval.agility_score or 5 }}" oninput="this.nextElementSibling.textContent = this.value">
|
||||
<span class="range-value">{{ existing_eval.agility_score or 5 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<label for="technique_score">Technique (1-10)</label>
|
||||
<div class="score-input">
|
||||
<input type="range" id="technique_score" name="technique_score" min="1" max="10" value="{{ existing_eval.technique_score or 5 }}" oninput="this.nextElementSibling.textContent = this.value">
|
||||
<span class="range-value">{{ existing_eval.technique_score or 5 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-4">
|
||||
<label for="teamwork_score">Teamwork (1-10)</label>
|
||||
<div class="score-input">
|
||||
<input type="range" id="teamwork_score" name="teamwork_score" min="1" max="10" value="{{ existing_eval.teamwork_score or 5 }}" oninput="this.nextElementSibling.textContent = this.value">
|
||||
<span class="range-value">{{ existing_eval.teamwork_score or 5 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<label for="attitude_score">Attitude (1-10)</label>
|
||||
<div class="score-input">
|
||||
<input type="range" id="attitude_score" name="attitude_score" min="1" max="10" value="{{ existing_eval.attitude_score or 5 }}" oninput="this.nextElementSibling.textContent = this.value">
|
||||
<span class="range-value">{{ existing_eval.attitude_score or 5 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<label for="position_recommendation">Recommended Position</label>
|
||||
<input type="text" id="position_recommendation" name="position_recommendation" value="{{ existing_eval.position_recommendation or '' }}" placeholder="e.g., Forward, Defense">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="comments">Comments</label>
|
||||
<textarea id="comments" name="comments" rows="4" placeholder="Enter your evaluation notes...">{{ existing_eval.comments or '' }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<a href="{{ url_for('tryouts.view_tryout', tryout_id=tryout.id) }}" class="btn btn-secondary">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save"></i> {% if existing_eval %}Update Evaluation{% else %}Submit Evaluation{% endif %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if evaluators %}
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-users"></i> All Evaluations for {{ player.full_name }}</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr><th>Evaluator</th><th>Speed</th><th>Agility</th><th>Technique</th><th>Teamwork</th><th>Attitude</th><th>Overall</th><th>Position</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for entry in evaluators %}
|
||||
<tr>
|
||||
<td>{{ entry.evaluator.full_name }}</td>
|
||||
<td>{{ entry.eval.speed_score or '-' }}</td>
|
||||
<td>{{ entry.eval.agility_score or '-' }}</td>
|
||||
<td>{{ entry.eval.technique_score or '-' }}</td>
|
||||
<td>{{ entry.eval.teamwork_score or '-' }}</td>
|
||||
<td>{{ entry.eval.attitude_score or '-' }}</td>
|
||||
<td><span class="score">{{ entry.eval.overall_score or '-' }}</span></td>
|
||||
<td>{{ entry.eval.position_recommendation or '-' }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,81 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Evaluations - TryoutPro{% endblock %}
|
||||
{% block page_title %}Evaluations{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / Evaluations</span>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if current_user.role == 'president' and player_scores %}
|
||||
<div class="stats-grid mb-4">
|
||||
{% for pid, data in player_scores.items() %}
|
||||
<div class="stat-card stat-card-sm">
|
||||
<div class="stat-icon bg-info">
|
||||
<i class="fas fa-user"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<h3>{{ data.player.full_name[:12] }}</h3>
|
||||
<p>Avg: <strong>{{ data.avg }}</strong> / {{ data.count }} evals</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-clipboard-list"></i>
|
||||
{% if current_user.role == 'player' %}
|
||||
My Evaluations
|
||||
{% else %}
|
||||
All Evaluations
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-container">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Tryout</th>
|
||||
<th>Player</th>
|
||||
<th>Evaluator</th>
|
||||
<th>Speed</th>
|
||||
<th>Agility</th>
|
||||
<th>Technique</th>
|
||||
<th>Teamwork</th>
|
||||
<th>Attitude</th>
|
||||
<th>Overall</th>
|
||||
<th>Position</th>
|
||||
<th>Date</th>
|
||||
</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.speed_score or '-' }}</td>
|
||||
<td>{{ eval.agility_score or '-' }}</td>
|
||||
<td>{{ eval.technique_score or '-' }}</td>
|
||||
<td>{{ eval.teamwork_score or '-' }}</td>
|
||||
<td>{{ eval.attitude_score or '-' }}</td>
|
||||
<td><span class="score">{{ eval.overall_score or '-' }}</span></td>
|
||||
<td><span class="badge badge-info">{{ eval.position_recommendation or 'N/A' }}</span></td>
|
||||
<td>{{ eval.created_at.strftime('%m/%d/%Y') }}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="11" class="text-center">
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-clipboard"></i>
|
||||
<h3>No evaluations yet</h3>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,17 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Login - TryoutPro{% endblock %}
|
||||
{% block auth_content %}
|
||||
<form method="POST" action="{{ url_for('auth.login') }}" class="auth-form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div class="form-group">
|
||||
<label for="username"><i class="fas fa-user"></i> Username</label>
|
||||
<input type="text" id="username" name="username" placeholder="Enter your username" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password"><i class="fas fa-lock"></i> Password</label>
|
||||
<input type="password" id="password" name="password" placeholder="Enter your password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-block">Sign In</button>
|
||||
<p class="auth-link">Don't have an account? <a href="{{ url_for('auth.register') }}">Register here</a></p>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,59 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Players to Evaluate - TryoutPro{% endblock %}
|
||||
{% block page_title %}Players to Evaluate{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / <a href="{{ url_for('tryouts.view_tryout', tryout_id=tryout.id) }}">{{ tryout.title }}</a> / Evaluate</span>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-users"></i> Players in {{ tryout.title }}</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-container">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Player</th>
|
||||
<th>Contact</th>
|
||||
<th>Attendance</th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for entry in players %}
|
||||
<tr>
|
||||
<td>
|
||||
<div class="user-mini">
|
||||
<div class="avatar-sm">{{ entry.player.full_name[:2] | upper }}</div>
|
||||
<span>{{ entry.player.full_name }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ entry.player.email }}</td>
|
||||
<td>
|
||||
<span class="badge badge-{{ entry.registration.status }}">{{ entry.registration.status }}</span>
|
||||
</td>
|
||||
<td>
|
||||
{% if entry.evaluated %}
|
||||
<span class="badge badge-success">Evaluated</span>
|
||||
{% else %}
|
||||
<span class="badge badge-warning">Not Evaluated</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ url_for('evaluations.evaluate_player', tryout_id=tryout.id, player_id=entry.player.id) }}" class="btn btn-sm btn-primary">
|
||||
<i class="fas fa-clipboard"></i> {% if entry.evaluated %}View/Edit{% else %}Evaluate{% endif %}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="5" class="text-center">No players registered for this tryout.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,147 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}My Profile - TryoutPro{% endblock %}
|
||||
{% block page_title %}My Profile{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / Profile</span>{% endblock %}
|
||||
|
||||
{% block header_actions %}
|
||||
<div class="header-actions">
|
||||
<a href="{{ url_for('users.edit_profile') }}" class="btn btn-sm btn-primary">
|
||||
<i class="fas fa-edit"></i> Edit Profile
|
||||
</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="dashboard-grid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-user-circle"></i> Account Information</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="profile-header">
|
||||
<div class="user-avatar avatar-xl">{{ user.full_name[:2] | upper }}</div>
|
||||
<div class="profile-info">
|
||||
<h2>{{ user.full_name }}</h2>
|
||||
<span class="badge badge-{{ user.role }} badge-lg">{{ user.role | capitalize }}</span>
|
||||
<p class="text-muted">Member since {{ user.created_at.strftime('%B %Y') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-grid mt-4">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Username</span>
|
||||
<span class="detail-value">{{ user.username }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Email</span>
|
||||
<span class="detail-value">{{ user.email }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Phone</span>
|
||||
<span class="detail-value">{{ user.phone or 'Not provided' }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Account Status</span>
|
||||
<span class="detail-value">
|
||||
{% if user.is_active_account %}
|
||||
<span class="badge badge-success">Active</span>
|
||||
{% else %}
|
||||
<span class="badge badge-danger">Inactive</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- E-Sports Profile Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-gamepad"></i> E-Sports Profile</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="detail-grid">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label"><i class="fas fa-headset"></i> Games</span>
|
||||
<span class="detail-value">
|
||||
{% set games_list = user.get_games_list() %}
|
||||
{% if games_list %}
|
||||
{% for game in games_list %}
|
||||
<span class="badge badge-esport">{{ game }}</span>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<span class="text-muted">Not specified</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label"><i class="fas fa-chart-line"></i> TRN (Tracker Network)</span>
|
||||
<span class="detail-value">
|
||||
{% if user.trn_username %}
|
||||
<a href="https://tracker.gg" target="_blank" rel="noopener noreferrer" class="trn-link">
|
||||
<i class="fas fa-external-link-alt"></i> {{ user.trn_username }}
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="text-muted">Not connected</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label"><i class="fab fa-discord"></i> Discord</span>
|
||||
<span class="detail-value">
|
||||
{% if user.discord_username %}
|
||||
{{ user.discord_username }}
|
||||
{% else %}
|
||||
<span class="text-muted">Not connected</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label"><i class="fas fa-link"></i> League OS</span>
|
||||
<span class="detail-value">
|
||||
{% if user.league_os_profile %}
|
||||
<a href="{{ user.league_os_profile }}" target="_blank" rel="noopener noreferrer" class="trn-link">
|
||||
<i class="fas fa-external-link-alt"></i> {{ user.league_os_profile }}
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="text-muted">Not connected</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-chart-bar"></i> My Statistics</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if user.role == 'player' %}
|
||||
<div class="profile-stats">
|
||||
<div class="stat-item">
|
||||
<h4>{{ user.tryout_registrations.count() }}</h4>
|
||||
<p>Tryouts Registered</p>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<h4>{{ user.evaluations_received.count() }}</h4>
|
||||
<p>Evaluations Received</p>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<h4>{{ user.team_assignments.count() }}</h4>
|
||||
<p>Team Assignments</p>
|
||||
</div>
|
||||
</div>
|
||||
{% elif user.can_evaluate() %}
|
||||
<div class="profile-stats">
|
||||
<div class="stat-item">
|
||||
<h4>{{ user.evaluations_given.count() }}</h4>
|
||||
<p>Evaluations Given</p>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-muted">No statistics available for this role.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,66 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Register - TryoutPro{% endblock %}
|
||||
{% block auth_content %}
|
||||
<form method="POST" action="{{ url_for('auth.register') }}" class="auth-form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div class="form-group">
|
||||
<label for="full_name"><i class="fas fa-id-card"></i> Full Name</label>
|
||||
<input type="text" id="full_name" name="full_name" placeholder="Enter your full name" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="username"><i class="fas fa-user"></i> Username</label>
|
||||
<input type="text" id="username" name="username" placeholder="Choose a username" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email"><i class="fas fa-envelope"></i> Email</label>
|
||||
<input type="email" id="email" name="email" placeholder="Enter your email" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="phone"><i class="fas fa-phone"></i> Phone (Optional)</label>
|
||||
<input type="tel" id="phone" name="phone" placeholder="Enter your phone number">
|
||||
</div>
|
||||
|
||||
<hr class="section-divider">
|
||||
<h4 class="section-title"><i class="fas fa-gamepad"></i> E-Sports Profile</h4>
|
||||
<p class="text-muted small">Set up your competitive gaming profile for tryouts.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label><i class="fas fa-headset"></i> Games You Play</label>
|
||||
<div class="checkbox-grid">
|
||||
{% for game in esport_games %}
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" name="games" value="{{ game }}">
|
||||
<span>{{ game }}</span>
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<small class="form-text text-muted">Select all games you're signing in for.</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="trn_username"><i class="fas fa-chart-line"></i> TRN (Tracker Network) Username</label>
|
||||
<input type="text" id="trn_username" name="trn_username" placeholder="e.g. YourTrackerGGUsername">
|
||||
<small class="form-text text-muted">Your public Tracker Network profile name. Others can click it to view your stats.</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="discord_username"><i class="fab fa-discord"></i> Discord Username</label>
|
||||
<input type="text" id="discord_username" name="discord_username" placeholder="e.g. YourName#1234">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="league_os_profile"><i class="fas fa-link"></i> League OS Connection</label>
|
||||
<input type="text" id="league_os_profile" name="league_os_profile" placeholder="League OS profile link or ID">
|
||||
<small class="form-text text-muted">Connect your League OS profile for organized play.</small>
|
||||
</div>
|
||||
|
||||
<hr class="section-divider">
|
||||
<div class="form-group">
|
||||
<label for="password"><i class="fas fa-lock"></i> Password</label>
|
||||
<input type="password" id="password" name="password" placeholder="Create a password" required minlength="6">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="confirm_password"><i class="fas fa-check-circle"></i> Confirm Password</label>
|
||||
<input type="password" id="confirm_password" name="confirm_password" placeholder="Confirm your password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-block">Create Account</button>
|
||||
<p class="auth-link">Already have an account? <a href="{{ url_for('auth.login') }}">Sign in</a></p>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,230 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Teams - TryoutPro{% endblock %}
|
||||
{% block page_title %}Teams{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / Teams</span>{% endblock %}
|
||||
|
||||
{% block header_actions %}
|
||||
{% if can_manage %}
|
||||
<button class="btn btn-primary" onclick="showCreateForm()">
|
||||
<i class="fas fa-plus"></i> New Team
|
||||
</button>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if can_manage %}
|
||||
<div id="createTeamForm" class="card mb-4 {% if not form_visible %}hidden{% endif %}">
|
||||
<div class="card-header">
|
||||
<h3>Create New Team</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ url_for('teams.create_team') }}" class="form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-6">
|
||||
<label for="name">Team Name</label>
|
||||
<input type="text" id="name" name="name" placeholder="e.g., Varsity, JV, U14" required>
|
||||
</div>
|
||||
<div class="form-group col-6">
|
||||
<label for="coach_id">Assigned Coach</label>
|
||||
<select id="coach_id" name="coach_id" class="form-select">
|
||||
<option value="">-- No coach assigned --</option>
|
||||
{% for coach in coaches %}
|
||||
<option value="{{ coach.id }}">{{ coach.full_name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn btn-secondary" onclick="hideCreateForm()">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Create Team</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% for team in teams %}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-users-cog"></i> {{ team.name }}</h3>
|
||||
<div class="card-actions">
|
||||
{% if team.coach %}
|
||||
<span class="text-muted">Coach: {{ team.coach.full_name }}</span>
|
||||
{% else %}
|
||||
<span class="text-muted">No coach assigned</span>
|
||||
{% endif %}
|
||||
{% if can_manage %}
|
||||
<button class="btn btn-sm btn-outline edit-team-btn" data-team-id="{{ team.id }}" data-team-name="{{ team.name }}" data-coach-id="{{ team.coach_id or '' }}">
|
||||
<i class="fas fa-edit"></i> Edit
|
||||
</button>
|
||||
<form method="POST" action="{{ url_for('teams.delete_team', team_id=team.id) }}" class="inline-form" onsubmit="return confirm('Delete team {{ team.name }}? This will unassign it from any linked tryouts.')">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<button type="submit" class="btn btn-sm btn-danger">
|
||||
<i class="fas fa-trash"></i> Delete
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-container">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Player</th>
|
||||
<th>Position / Role</th>
|
||||
<th>Email</th>
|
||||
<th>Phone</th>
|
||||
{% if can_manage %}
|
||||
<th>Actions</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for player in team.players %}
|
||||
<tr>
|
||||
<td>
|
||||
<div class="user-mini">
|
||||
<div class="avatar-sm">{{ player.full_name[:2] | upper }}</div>
|
||||
<span>{{ player.full_name }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ player.role | capitalize }}</td>
|
||||
<td>{{ player.email }}</td>
|
||||
<td>{{ player.phone or '-' }}</td>
|
||||
{% if can_manage %}
|
||||
<td>
|
||||
<form method="POST" action="{{ url_for('teams.remove_player', team_id=team.id, player_id=player.id) }}" class="inline-form" onsubmit="return confirm('Remove {{ player.full_name }} from {{ team.name }}?')">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<button type="submit" class="btn btn-sm btn-danger">
|
||||
<i class="fas fa-user-minus"></i> Remove
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="{% if can_manage %}5{% else %}4{% endif %}" class="text-center">
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-users-slash"></i>
|
||||
<h4>No players assigned</h4>
|
||||
{% if can_manage %}
|
||||
<p>Add players to this team using the form below.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% if can_manage %}
|
||||
<hr class="my-3">
|
||||
<div class="add-player-section">
|
||||
<h5 class="mb-2"><i class="fas fa-user-plus"></i> Add Player to {{ team.name }}</h5>
|
||||
<form method="POST" action="{{ url_for('teams.add_player', team_id=team.id) }}" class="form-inline">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<select name="player_id" class="form-select" required>
|
||||
<option value="">-- Select a player --</option>
|
||||
{% for p in all_players %}
|
||||
{% if p.team_id != team.id %}
|
||||
<option value="{{ p.id }}">{{ p.full_name }} {% if p.org_team %}(currently in {{ p.org_team.name }}){% endif %}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button type="submit" class="btn btn-sm btn-primary ml-2">
|
||||
<i class="fas fa-plus"></i> Add to Team
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="card">
|
||||
<div class="card-body text-center">
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-users-cog"></i>
|
||||
<h3>No teams yet</h3>
|
||||
{% if can_manage %}
|
||||
<p>Create organization teams and assign coaches to manage tryouts.</p>
|
||||
<button class="btn btn-primary" onclick="showCreateForm()">Create Team</button>
|
||||
{% else %}
|
||||
<p>There are no teams to display.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<!-- Edit Team Modal -->
|
||||
<div id="editTeamModal" class="modal hidden">
|
||||
<div class="modal-backdrop" onclick="hideEditForm()"></div>
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>Edit Team</h3>
|
||||
<button class="modal-close" onclick="hideEditForm()">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="editTeamForm" method="POST" action="" class="form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div class="form-group">
|
||||
<label for="edit_name">Team Name</label>
|
||||
<input type="text" id="edit_name" name="name" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="edit_coach_id">Assigned Coach</label>
|
||||
<select id="edit_coach_id" name="coach_id" class="form-select">
|
||||
<option value="">-- No coach assigned --</option>
|
||||
{% for coach in coaches %}
|
||||
<option value="{{ coach.id }}">{{ coach.full_name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn btn-secondary" onclick="hideEditForm()">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showCreateForm() {
|
||||
document.getElementById('createTeamForm').classList.remove('hidden');
|
||||
}
|
||||
|
||||
function hideCreateForm() {
|
||||
document.getElementById('createTeamForm').classList.add('hidden');
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.querySelectorAll('.edit-team-btn').forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
var teamId = this.getAttribute('data-team-id');
|
||||
var teamName = this.getAttribute('data-team-name');
|
||||
var coachId = this.getAttribute('data-coach-id');
|
||||
document.getElementById('editTeamForm').action = '/teams/' + teamId + '/edit';
|
||||
document.getElementById('edit_name').value = teamName;
|
||||
document.getElementById('edit_coach_id').value = coachId || '';
|
||||
document.getElementById('editTeamModal').classList.remove('hidden');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function showEditForm(teamId, teamName, coachId) {
|
||||
document.getElementById('editTeamForm').action = '/teams/' + teamId + '/edit';
|
||||
document.getElementById('edit_name').value = teamName;
|
||||
document.getElementById('edit_coach_id').value = coachId || '';
|
||||
document.getElementById('editTeamModal').classList.remove('hidden');
|
||||
}
|
||||
|
||||
function hideEditForm() {
|
||||
document.getElementById('editTeamModal').classList.add('hidden');
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,75 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Tryouts - TryoutPro{% endblock %}
|
||||
{% block page_title %}Tryouts{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / Tryouts</span>{% endblock %}
|
||||
|
||||
{% block header_actions %}
|
||||
{% if current_user.can_manage_tryouts() %}
|
||||
<a href="{{ url_for('tryouts.create_tryout') }}" class="btn btn-primary">
|
||||
<i class="fas fa-plus"></i> New Tryout
|
||||
</a>
|
||||
{% endif %}
|
||||
{% 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>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,68 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}Manage Users - TryoutPro{% endblock %}
|
||||
{% block page_title %}Manage Users{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / Users</span>{% endblock %}
|
||||
|
||||
{% block header_actions %}
|
||||
<a href="{{ url_for('users.create_user') }}" class="btn btn-primary">
|
||||
<i class="fas fa-user-plus"></i> Add User
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="table-container">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Username</th>
|
||||
<th>Email</th>
|
||||
<th>Role</th>
|
||||
<th>Status</th>
|
||||
<th>Joined</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for u in users %}
|
||||
<tr>
|
||||
<td>
|
||||
<div class="user-mini">
|
||||
<div class="avatar-sm">{{ u.full_name[:2] | upper }}</div>
|
||||
<span>{{ u.full_name }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ u.username }}</td>
|
||||
<td>{{ u.email }}</td>
|
||||
<td><span class="badge badge-{{ u.role }}">{{ u.role | capitalize }}</span></td>
|
||||
<td>
|
||||
{% if u.is_active_account %}
|
||||
<span class="badge badge-success">Active</span>
|
||||
{% else %}
|
||||
<span class="badge badge-danger">Inactive</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ u.created_at.strftime('%m/%d/%Y') }}</td>
|
||||
<td>
|
||||
<a href="{{ url_for('users.edit_user', user_id=u.id) }}" class="btn btn-sm btn-outline">
|
||||
<i class="fas fa-edit"></i> Edit
|
||||
</a>
|
||||
{% if u.id != current_user.id %}
|
||||
<form method="POST" action="{{ url_for('users.delete_user', user_id=u.id) }}" class="inline-form" onsubmit="return confirm('Delete {{ u.full_name }}? This cannot be undone.');">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<button type="submit" class="btn btn-sm btn-danger">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,278 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
{% block title %}{{ tryout.title }} - TryoutPro{% endblock %}
|
||||
{% block page_title %}{{ tryout.title }}{% endblock %}
|
||||
{% block breadcrumb %}<span class="breadcrumb">Home / <a href="{{ url_for('tryouts.list_tryouts') }}">Tryouts</a> / {{ tryout.title }}</span>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="tryout-detail">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<h3>Tryout Details</h3>
|
||||
<div class="card-actions">
|
||||
{% if current_user.can_manage_tryouts() %}
|
||||
<form method="POST" action="{{ url_for('tryouts.update_status', tryout_id=tryout.id) }}" class="inline-form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<select name="status" onchange="this.form.submit()" class="form-select">
|
||||
<option value="upcoming" {% if tryout.status == 'upcoming' %}selected{% endif %}>Upcoming</option>
|
||||
<option value="in_progress" {% if tryout.status == 'in_progress' %}selected{% endif %}>In Progress</option>
|
||||
<option value="completed" {% if tryout.status == 'completed' %}selected{% endif %}>Completed</option>
|
||||
</select>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if can_edit %}
|
||||
<a href="{{ url_for('tryouts.edit_tryout', tryout_id=tryout.id) }}" class="btn btn-sm btn-primary">
|
||||
<i class="fas fa-edit"></i> Edit
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="detail-grid">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Date</span>
|
||||
<span class="detail-value">{{ tryout.date.strftime('%A, %B %d, %Y') }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Location</span>
|
||||
<span class="detail-value">{{ tryout.location or 'Not specified' }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Status</span>
|
||||
<span class="detail-value">
|
||||
<span class="badge badge-{{ tryout.status }}">{{ tryout.status | replace('_', ' ') | title }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Target Team</span>
|
||||
<span class="detail-value">{{ tryout.target_org_team.name if tryout.target_org_team else 'Not specified' }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Registered Players</span>
|
||||
<span class="detail-value">{{ registered_players | length }}</span>
|
||||
</div>
|
||||
{% if tryout.description %}
|
||||
<div class="detail-item full-width">
|
||||
<span class="detail-label">Description</span>
|
||||
<span class="detail-value">{{ tryout.description }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if current_user.role == 'player' and not is_registered and tryout.status in ['upcoming', 'in_progress'] %}
|
||||
<div class="card mb-4">
|
||||
<div class="card-body text-center">
|
||||
<form method="POST" action="{{ url_for('tryouts.register_for_tryout', tryout_id=tryout.id) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<button type="submit" class="btn btn-primary btn-lg">
|
||||
<i class="fas fa-user-plus"></i> Register for this Tryout
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if current_user.can_manage_tryouts() %}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-user-plus"></i> Add Player to Tryout</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ url_for('tryouts.register_player', tryout_id=tryout.id) }}" class="form-inline">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<select name="player_id" class="form-select" required>
|
||||
<option value="">-- Select a player --</option>
|
||||
{% for p in all_players %}
|
||||
{% set is_already = registrations | selectattr('player_id', 'equalto', p.id) | list | length > 0 %}
|
||||
<option value="{{ p.id }}" {% if is_already %}disabled class="text-muted"{% endif %}>{{ p.full_name }}{% if is_already %} (already registered){% endif %}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button type="submit" class="btn btn-sm btn-primary ml-2">
|
||||
<i class="fas fa-plus"></i> Register Player
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="dashboard-grid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-users"></i> Registered Players ({{ registered_players | length }})</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-container">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Player</th>
|
||||
<th>Status</th>
|
||||
{% if current_user.can_evaluate() %}
|
||||
<th>Evaluation</th>
|
||||
<th>Actions</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for p in registered_players %}
|
||||
{% set reg = registrations | selectattr('player_id', 'equalto', p.id) | first %}
|
||||
<tr>
|
||||
<td>
|
||||
<div class="user-mini">
|
||||
<div class="avatar-sm">{{ p.full_name[:2] | upper }}</div>
|
||||
<span>{{ p.full_name }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{% if current_user.can_manage_tryouts() %}
|
||||
<form method="POST" action="{{ url_for('tryouts.update_registration_status', tryout_id=tryout.id, player_id=p.id) }}" class="inline-form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<select name="status" onchange="this.form.submit()" class="form-select form-select-sm">
|
||||
<option value="registered" {% if reg.status == 'registered' %}selected{% endif %}>Registered</option>
|
||||
<option value="attended" {% if reg.status == 'attended' %}selected{% endif %}>Attended</option>
|
||||
<option value="no_show" {% if reg.status == 'no_show' %}selected{% endif %}>No Show</option>
|
||||
</select>
|
||||
</form>
|
||||
{% else %}
|
||||
<span class="badge badge-{{ reg.status }}">{{ reg.status }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% if current_user.can_evaluate() %}
|
||||
<td>
|
||||
{% if player_eval_status.get(p.id) %}
|
||||
<span class="badge badge-success">Evaluated</span>
|
||||
{% else %}
|
||||
<span class="badge badge-warning">Pending</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ url_for('evaluations.evaluate_player', tryout_id=tryout.id, player_id=p.id) }}" class="btn btn-sm btn-primary">
|
||||
<i class="fas fa-edit"></i> {% if player_eval_status.get(p.id) %}Edit{% else %}Evaluate{% endif %}
|
||||
</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="{% if current_user.can_evaluate() %}4{% else %}2{% endif %}" class="text-center">
|
||||
No players registered yet.
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-users-cog"></i> Teams</h3>
|
||||
{% if current_user.can_manage_tryouts() %}
|
||||
<button class="btn btn-sm btn-primary" onclick="showCreateTeam()">
|
||||
<i class="fas fa-plus"></i> New Team
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if current_user.can_manage_tryouts() %}
|
||||
<div id="createTeamForm" class="hidden mb-3">
|
||||
<form method="POST" action="{{ url_for('tryouts.create_team', tryout_id=tryout.id) }}" class="form-inline">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<input type="text" name="team_name" placeholder="Team name" required class="form-input mr-2">
|
||||
<button type="submit" class="btn btn-sm btn-success">Create</button>
|
||||
<button type="button" class="btn btn-sm btn-secondary" onclick="hideCreateTeam()">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% for team in team_data %}
|
||||
<div class="team-card mb-3">
|
||||
<h4 class="team-name">{{ team.team.name }}</h4>
|
||||
<ul class="team-members">
|
||||
{% for member in team.members %}
|
||||
<li>
|
||||
<div class="avatar-sm">{{ member.player.full_name[:2] | upper }}</div>
|
||||
<span>{{ member.player.full_name }}</span>
|
||||
{% if member.position %}
|
||||
<span class="position-tag">{{ member.position }}</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="text-muted">No players assigned yet.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if current_user.can_manage_tryouts() and registered_players %}
|
||||
<form method="POST" action="{{ url_for('tryouts.add_to_team', tryout_id=tryout.id, team_id=team.team.id) }}" class="form-inline mt-2">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<select name="player_id" class="form-select" required>
|
||||
<option value="">Select player...</option>
|
||||
{% for p in registered_players %}
|
||||
{% if p.id not in team.members | map(attribute='player') | map(attribute='id') | list %}
|
||||
<option value="{{ p.id }}">{{ p.full_name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
<input type="text" name="position" placeholder="Position" class="form-input mx-2">
|
||||
<button type="submit" class="btn btn-sm btn-primary">Add</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-muted text-center">No teams created yet.</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-4">
|
||||
<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>Speed</th>
|
||||
<th>Agility</th>
|
||||
<th>Technique</th>
|
||||
<th>Teamwork</th>
|
||||
<th>Attitude</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.speed_score or '-' }}</td>
|
||||
<td>{{ eval.agility_score or '-' }}</td>
|
||||
<td>{{ eval.technique_score or '-' }}</td>
|
||||
<td>{{ eval.teamwork_score or '-' }}</td>
|
||||
<td>{{ eval.attitude_score or '-' }}</td>
|
||||
<td><span class="score">{{ eval.overall_score or '-' }}</span></td>
|
||||
<td>{{ eval.position_recommendation or '-' }}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="9" class="text-center">No evaluations yet.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showCreateTeam() { document.getElementById('createTeamForm').classList.remove('hidden'); }
|
||||
function hideCreateTeam() { document.getElementById('createTeamForm').classList.add('hidden'); }
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user