ajouté dark mode et changer l'affichage des équipes dans les match. Changé les couleurs pour ressembler plus au couleur de l'udes
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+48
-1
@@ -1,8 +1,9 @@
|
||||
from flask import Blueprint, render_template, redirect, url_for, flash
|
||||
from flask_login import login_required, current_user
|
||||
from extensions import db
|
||||
from models import User, Tryout, Evaluation, TryoutRegistration, Team, TeamMember
|
||||
from models import User, Tryout, Evaluation, TryoutRegistration, Team, TeamMember, Match, MatchParticipant
|
||||
from sqlalchemy import func
|
||||
from datetime import datetime, date
|
||||
|
||||
main_bp = Blueprint('main', __name__)
|
||||
|
||||
@@ -48,6 +49,52 @@ def dashboard():
|
||||
stats['my_registrations'] = TryoutRegistration.query.filter_by(player_id=user.id).order_by(TryoutRegistration.registered_at.desc()).limit(5).all()
|
||||
stats['my_eval_list'] = Evaluation.query.filter_by(player_id=user.id).order_by(Evaluation.created_at.desc()).limit(5).all()
|
||||
|
||||
# Get next match for each tryout the player is in
|
||||
today = date.today()
|
||||
next_matches = []
|
||||
for reg in stats['my_registrations']:
|
||||
tryout = reg.tryout
|
||||
# Find matches where player participates (team membership or direct participant)
|
||||
player_teams = Team.query.join(TeamMember).filter(
|
||||
Team.tryout_id == tryout.id,
|
||||
TeamMember.player_id == user.id
|
||||
).all()
|
||||
|
||||
# Get matches for this tryout that include the player
|
||||
tryout_matches = Match.query.filter(
|
||||
Match.tryout_id == tryout.id,
|
||||
Match.status == 'scheduled'
|
||||
).order_by(Match.date, Match.start_time).all()
|
||||
|
||||
for match in tryout_matches:
|
||||
# Check if player is in this match
|
||||
is_participant = False
|
||||
if match.match_type == 'team_vs_team':
|
||||
# Check if player is on team1 or team2
|
||||
if match.team1_id in [t.id for t in player_teams] or match.team2_id in [t.id for t in player_teams]:
|
||||
is_participant = True
|
||||
else:
|
||||
# Check if player is in match participants
|
||||
participant = MatchParticipant.query.filter_by(
|
||||
match_id=match.id,
|
||||
player_id=user.id
|
||||
).first()
|
||||
if participant:
|
||||
is_participant = True
|
||||
|
||||
if is_participant:
|
||||
# Check if match is upcoming
|
||||
match_date = match.date
|
||||
if match_date >= today:
|
||||
next_matches.append({
|
||||
'tryout': tryout,
|
||||
'match': match,
|
||||
'team': player_teams[0] if player_teams else None
|
||||
})
|
||||
break # Only get the next match per tryout
|
||||
|
||||
stats['next_matches'] = next_matches
|
||||
|
||||
elif user.role == 'scout':
|
||||
stats['total_players'] = User.query.filter_by(role='player').count()
|
||||
stats['total_evaluations'] = Evaluation.query.count()
|
||||
|
||||
+2
-2
@@ -73,7 +73,7 @@ def api_events():
|
||||
|
||||
events.append({
|
||||
'id': f'match_{match.id}',
|
||||
'title': match.title + ' (' + participants_str + ')',
|
||||
'title': match.title,
|
||||
'date': match.date.strftime('%Y-%m-%d'),
|
||||
'type': 'match',
|
||||
'color': match_color,
|
||||
@@ -181,7 +181,7 @@ def api_events_for_tryout(tryout_id):
|
||||
|
||||
events.append({
|
||||
'id': f'match_{match.id}',
|
||||
'title': match.title + ' (' + participants_str + ')',
|
||||
'title': match.title,
|
||||
'date': match.date.strftime('%Y-%m-%d'),
|
||||
'type': 'match',
|
||||
'color': match_color,
|
||||
|
||||
+6
-6
@@ -172,13 +172,13 @@ def view_tryout(tryout_id):
|
||||
'team2_players': [{'name': m.player.full_name, 'position': m.position} for m in match.team2.members.all()] if match.team2 else []
|
||||
}
|
||||
elif match.match_type == 'player_vs_player':
|
||||
team1_players = [p.player.full_name for p in match.participants.filter_by(team_side=1).all()]
|
||||
team2_players = [p.player.full_name for p in match.participants.filter_by(team_side=2).all()]
|
||||
team1_players = [{'name': p.player.full_name, 'position': p.position} for p in match.participants.filter_by(team_side=1).all() if p.player]
|
||||
team2_players = [{'name': p.player.full_name, 'position': p.position} for p in match.participants.filter_by(team_side=2).all() if p.player]
|
||||
participants = {
|
||||
'team1': ', '.join(team1_players) if team1_players else 'TBD',
|
||||
'team2': ', '.join(team2_players) if team2_players else 'TBD',
|
||||
'team1_player_names': team1_players,
|
||||
'team2_player_names': team2_players
|
||||
'team1': 'Team 1',
|
||||
'team2': 'Team 2',
|
||||
'team1_players': team1_players,
|
||||
'team2_players': team2_players
|
||||
}
|
||||
else:
|
||||
participants = [p.player.full_name for p in match.participants.all()]
|
||||
|
||||
+360
-22
@@ -1,28 +1,29 @@
|
||||
:root {
|
||||
--primary: #4f46e5;
|
||||
--primary-dark: #4338ca;
|
||||
--primary-light: #eef2ff;
|
||||
--success: #10b981;
|
||||
--success-light: #ecfdf5;
|
||||
--warning: #f59e0b;
|
||||
--warning-light: #fffbeb;
|
||||
/* New Color Palette */
|
||||
--primary: #00984C;
|
||||
--primary-dark: #003E21;
|
||||
--primary-light: #E5A939;
|
||||
--success: #00984C;
|
||||
--success-light: #F0F2F2;
|
||||
--warning: #E5A939;
|
||||
--warning-light: #FEF9F0;
|
||||
--danger: #ef4444;
|
||||
--danger-light: #fef2f2;
|
||||
--info: #3b82f6;
|
||||
--info-light: #eff6ff;
|
||||
--secondary: #6b7280;
|
||||
--secondary-light: #f3f4f6;
|
||||
--dark: #1f2937;
|
||||
--gray-50: #f9fafb;
|
||||
--gray-100: #f3f4f6;
|
||||
--gray-200: #e5e7eb;
|
||||
--gray-300: #d1d5db;
|
||||
--gray-400: #9ca3af;
|
||||
--gray-500: #6b7280;
|
||||
--gray-600: #4b5563;
|
||||
--gray-700: #374151;
|
||||
--gray-800: #1f2937;
|
||||
--gray-900: #111827;
|
||||
--secondary-light: #F0F2F2;
|
||||
--dark: #12130F;
|
||||
--gray-50: #F0F2F2;
|
||||
--gray-100: #E8EAEB;
|
||||
--gray-200: #D1D5DB;
|
||||
--gray-300: #9CA3AF;
|
||||
--gray-400: #6B7280;
|
||||
--gray-500: #4B5563;
|
||||
--gray-600: #374151;
|
||||
--gray-700: #1F2937;
|
||||
--gray-800: #12130F;
|
||||
--gray-900: #0A0B0A;
|
||||
--sidebar-width: 260px;
|
||||
--sidebar-collapsed: 0px;
|
||||
--radius: 12px;
|
||||
@@ -33,6 +34,26 @@
|
||||
--transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
/* Dark Mode Variables */
|
||||
[data-theme="dark"] {
|
||||
--bg-primary: #12130F;
|
||||
--bg-secondary: #1A1D17;
|
||||
--bg-tertiary: #232820;
|
||||
--text-primary: #F0F2F2;
|
||||
--text-secondary: #D1D5DB;
|
||||
--text-muted: #9CA3AF;
|
||||
--border-color: #2D342A;
|
||||
--card-bg: #1A1D17;
|
||||
--sidebar-bg: #0A0B0A;
|
||||
--sidebar-text: #F0F2F2;
|
||||
--sidebar-hover: rgba(240, 242, 242, 0.08);
|
||||
--input-bg: #232820;
|
||||
--input-border: #2D342A;
|
||||
--shadow: 0 1px 3px rgba(0,0,0,0.3), 0 1px 2px rgba(0,0,0,0.2);
|
||||
--shadow-md: 0 4px 6px rgba(0,0,0,0.25), 0 2px 4px rgba(0,0,0,0.2);
|
||||
--shadow-lg: 0 10px 15px rgba(0,0,0,0.3), 0 4px 6px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
@@ -462,7 +483,7 @@ a:hover { color: var(--primary-dark); }
|
||||
.form-group textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 0 3px rgba(79,70,229,0.1);
|
||||
box-shadow: 0 0 0 3px rgba(0, 152, 76, 0.1);
|
||||
}
|
||||
|
||||
.form-group textarea { resize: vertical; min-height: 80px; }
|
||||
@@ -533,10 +554,14 @@ a:hover { color: var(--primary-dark); }
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
background: linear-gradient(135deg, #00984C 0%, #003E21 100%);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .auth-wrapper {
|
||||
background: linear-gradient(135deg, #003E21 0%, #12130F 100%);
|
||||
}
|
||||
|
||||
.auth-wrapper .flash-messages {
|
||||
width: 100%;
|
||||
max-width: 420px;
|
||||
@@ -606,7 +631,7 @@ a:hover { color: var(--primary-dark); }
|
||||
|
||||
.auth-form .form-group input:focus {
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 0 3px rgba(79,70,229,0.1);
|
||||
box-shadow: 0 0 0 3px rgba(0, 152, 76, 0.1);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@@ -989,6 +1014,49 @@ a:hover { color: var(--primary-dark); }
|
||||
color: var(--gray-600);
|
||||
}
|
||||
|
||||
/* Match Teams Display */
|
||||
.match-teams {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.match-team {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.match-team .team-name {
|
||||
font-weight: 600;
|
||||
color: var(--gray-800);
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 4px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.match-vs {
|
||||
font-weight: 700;
|
||||
color: var(--primary);
|
||||
font-size: 0.85rem;
|
||||
padding: 0 4px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.team-players-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.team-players-list li {
|
||||
padding: 2px 0;
|
||||
color: var(--gray-600);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.sidebar {
|
||||
width: var(--sidebar-collapsed);
|
||||
@@ -1161,3 +1229,273 @@ a:hover { color: var(--primary-dark); }
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Dark Mode Styles */
|
||||
[data-theme="dark"] body {
|
||||
background: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .sidebar {
|
||||
background: var(--sidebar-bg);
|
||||
border-right: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .sidebar-header {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .user-badge {
|
||||
background: rgba(240, 242, 242, 0.05);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .nav-links li a {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .nav-links li a:hover,
|
||||
[data-theme="dark"] .nav-links li a.active {
|
||||
background: var(--sidebar-hover);
|
||||
color: var(--sidebar-text);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .nav-divider {
|
||||
background: var(--border-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .top-bar {
|
||||
background: var(--bg-secondary);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .page-header h1 {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .content {
|
||||
background: var(--bg-primary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .card {
|
||||
background: var(--card-bg);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .card-header {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .stat-card,
|
||||
[data-theme="dark"] .team-card {
|
||||
background: var(--card-bg);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .stat-info h3,
|
||||
[data-theme="dark"] .team-name,
|
||||
[data-theme="dark"] .detail-value {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .stat-info p,
|
||||
[data-theme="dark"] .detail-label,
|
||||
[data-theme="dark"] .team-members li,
|
||||
[data-theme="dark"] .team-members-list li,
|
||||
[data-theme="dark"] .team-roster-display,
|
||||
[data-theme="dark"] .form-text,
|
||||
[data-theme="dark"] .time-selection-hint,
|
||||
[data-theme="dark"] .randomize-preview {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .stat-item {
|
||||
background: var(--bg-tertiary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .table th {
|
||||
color: var(--text-secondary);
|
||||
border-bottom: 2px solid var(--border-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .table td {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .table tbody tr:hover {
|
||||
background: var(--bg-tertiary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .form-group label {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .form-group input,
|
||||
[data-theme="dark"] .form-group select,
|
||||
[data-theme="dark"] .form-group textarea,
|
||||
[data-theme="dark"] .form-select,
|
||||
[data-theme="dark"] .form-input,
|
||||
[data-theme="dark"] .randomize-input {
|
||||
background: var(--input-bg);
|
||||
border-color: var(--input-border);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .form-group input::placeholder,
|
||||
[data-theme="dark"] .form-group textarea::placeholder {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .form-group input:focus,
|
||||
[data-theme="dark"] .form-group select:focus,
|
||||
[data-theme="dark"] .form-group textarea:focus {
|
||||
box-shadow: 0 0 0 3px rgba(0, 152, 76, 0.2);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .form-actions {
|
||||
border-top: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .modal-content {
|
||||
background: var(--card-bg);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .modal-header {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .modal-close {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .modal-close:hover {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .checkbox-label {
|
||||
background: var(--bg-tertiary);
|
||||
border-color: var(--border-color);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .checkbox-label:hover {
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .section-divider {
|
||||
border-top: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .section-title,
|
||||
[data-theme="dark"] .empty-state h3 {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .empty-state i,
|
||||
[data-theme="dark"] .empty-state p {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .auth-container {
|
||||
background: var(--card-bg);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .auth-header h2 {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .auth-header p,
|
||||
[data-theme="dark"] .auth-link {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .auth-form .form-group label {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .auth-form .form-group label i {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .auth-form .form-group input {
|
||||
background: var(--input-bg);
|
||||
border-color: var(--input-border);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .auth-form .form-group input:focus {
|
||||
box-shadow: 0 0 0 3px rgba(0, 152, 76, 0.2);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .position-tag {
|
||||
background: var(--bg-tertiary);
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .match-team .team-name {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .merged-disponibility-time-block {
|
||||
background: var(--bg-tertiary);
|
||||
border-color: var(--border-color);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .merged-disponibility-time-block:hover {
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .merged-disponibility-selected-display {
|
||||
background: var(--bg-tertiary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .randomize-section {
|
||||
background: var(--bg-tertiary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .btn-secondary {
|
||||
background: var(--bg-tertiary);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .btn-secondary:hover {
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .btn-outline {
|
||||
background: transparent;
|
||||
border-color: var(--border-color);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .btn-outline:hover {
|
||||
background: var(--bg-tertiary);
|
||||
}
|
||||
|
||||
/* Dark Mode Toggle Button */
|
||||
.dark-mode-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.1rem;
|
||||
color: var(--gray-500);
|
||||
cursor: pointer;
|
||||
padding: 6px 10px;
|
||||
border-radius: var(--radius-sm);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.dark-mode-toggle:hover {
|
||||
background: var(--gray-100);
|
||||
color: var(--gray-700);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .dark-mode-toggle {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .dark-mode-toggle:hover {
|
||||
background: var(--bg-tertiary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,33 @@
|
||||
// Dark Mode Toggle
|
||||
function toggleDarkMode() {
|
||||
const body = document.documentElement;
|
||||
const isDark = body.getAttribute('data-theme') === 'dark';
|
||||
const toggle = document.getElementById('darkModeToggle');
|
||||
|
||||
if (isDark) {
|
||||
body.removeAttribute('data-theme');
|
||||
localStorage.setItem('theme', 'light');
|
||||
toggle.innerHTML = '<i class="fas fa-moon"></i>';
|
||||
} else {
|
||||
body.setAttribute('data-theme', 'dark');
|
||||
localStorage.setItem('theme', 'dark');
|
||||
toggle.innerHTML = '<i class="fas fa-sun"></i>';
|
||||
}
|
||||
}
|
||||
|
||||
// Load saved theme preference
|
||||
function loadTheme() {
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
const toggle = document.getElementById('darkModeToggle');
|
||||
|
||||
if (savedTheme === 'dark') {
|
||||
document.documentElement.setAttribute('data-theme', 'dark');
|
||||
if (toggle) {
|
||||
toggle.innerHTML = '<i class="fas fa-sun"></i>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sidebar toggle for mobile
|
||||
function toggleSidebar() {
|
||||
const sidebar = document.getElementById('sidebar');
|
||||
@@ -17,6 +47,9 @@ document.addEventListener('click', function(event) {
|
||||
|
||||
// Auto-dismiss flash messages
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Load theme preference
|
||||
loadTheme();
|
||||
|
||||
const alerts = document.querySelectorAll('.alert-dismissible');
|
||||
alerts.forEach(function(alert) {
|
||||
setTimeout(function() {
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
</nav>
|
||||
|
||||
<div class="main-content" id="mainContent">
|
||||
<header class="top-bar">
|
||||
<header class="top-bar">
|
||||
<button class="sidebar-toggle" id="sidebarToggle" onclick="toggleSidebar()">
|
||||
<i class="fas fa-bars"></i>
|
||||
</button>
|
||||
@@ -92,6 +92,9 @@
|
||||
<h1>{% block page_title %}Dashboard{% endblock %}</h1>
|
||||
{% block breadcrumb %}{% endblock %}
|
||||
</div>
|
||||
<button class="dark-mode-toggle" id="darkModeToggle" onclick="toggleDarkMode()" title="Toggle dark mode">
|
||||
<i class="fas fa-moon"></i>
|
||||
</button>
|
||||
{% block header_actions %}{% endblock %}
|
||||
</header>
|
||||
<div class="flash-messages">
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<link href="https://cdn.jsdelivr.net/npm/[email protected]/index.global.min.css" rel="stylesheet">
|
||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/index.global.min.js"></script>
|
||||
<script>
|
||||
var canScheduleMatches = {{ 'true' if current_user.can_schedule_matches() else 'false' }};
|
||||
var canScheduleMatches = {% if current_user.can_schedule_matches() %}true{% else %}false{% endif %};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var calendarEl = document.getElementById('calendar');
|
||||
@@ -73,7 +73,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
events: '/matches/api/events',
|
||||
eventClick: function(info) {
|
||||
showEventModal(info.event);
|
||||
}
|
||||
},
|
||||
slotMinTime: '12:00:00',
|
||||
slotMaxTime: '24:00:00'
|
||||
});
|
||||
calendar.render();
|
||||
|
||||
@@ -95,8 +97,8 @@ function showEventModal(event) {
|
||||
|
||||
var content = '<div class="detail-grid">';
|
||||
content += '<div class="detail-item"><span class="detail-label">Type</span><span class="detail-value">';
|
||||
content += '<span class="badge badge-' + (type === 'tryout' ? 'info' : (props.match_type === 'team_vs_team' ? 'success' : 'warning')) + '">';
|
||||
content += (type === 'tryout' ? 'Tryout' : (props.match_type === 'team_vs_team' ? 'Team Match' : 'Player Scrim')) + '</span>';
|
||||
content += '<span class="badge badge-' + (type === 'tryout' ? 'info' : (props.match_type === 'team_vs_team' || props.match_type === 'player_vs_player' ? 'success' : 'warning')) + '">';
|
||||
content += (type === 'tryout' ? 'Tryout' : (props.match_type === 'team_vs_team' ? 'Team Match' : (props.match_type === 'player_vs_player' ? 'Player Match' : 'Player Scrim'))) + '</span>';
|
||||
content += '</span></div>';
|
||||
content += '<div class="detail-item"><span class="detail-label">Title</span><span class="detail-value">' + title + '</span></div>';
|
||||
content += '<div class="detail-item"><span class="detail-label">Date</span><span class="detail-value">' + date + '</span></div>';
|
||||
@@ -105,6 +107,41 @@ function showEventModal(event) {
|
||||
content += '<span class="badge badge-' + (props.status || 'scheduled') + '">' + (props.status || 'scheduled') + '</span>';
|
||||
content += '</span></div>';
|
||||
|
||||
// Add team separation for matches
|
||||
if (type === 'match' && props.participants) {
|
||||
content += '<div class="detail-item full-width"><span class="detail-label">Teams</span><span class="detail-value">';
|
||||
if (props.match_type === 'team_vs_team') {
|
||||
// For team vs team, participants is "Team1 vs Team2"
|
||||
var teams = props.participants.split(' vs ');
|
||||
if (teams.length >= 2) {
|
||||
content += '<div class="match-teams">';
|
||||
content += '<div class="match-team"><span class="team-name">' + teams[0] + '</span></div>';
|
||||
content += '<div class="match-vs">vs</div>';
|
||||
content += '<div class="match-team"><span class="team-name">' + teams[1] + '</span></div>';
|
||||
content += '</div>';
|
||||
} else {
|
||||
content += props.participants;
|
||||
}
|
||||
} else if (props.match_type === 'player_vs_player') {
|
||||
// For player vs player, we need to parse the participants
|
||||
// The format is "player1, player2 vs player3, player4"
|
||||
var parts = props.participants.split(' vs ');
|
||||
if (parts.length >= 2) {
|
||||
content += '<div class="match-teams">';
|
||||
content += '<div class="match-team"><span class="team-name">Team 1</span><ul class="team-players-list"><li>' + parts[0].split(', ').join('</li><li>') + '</li></ul></div>';
|
||||
content += '<div class="match-vs">vs</div>';
|
||||
content += '<div class="match-team"><span class="team-name">Team 2</span><ul class="team-players-list"><li>' + parts[1].split(', ').join('</li><li>') + '</li></ul></div>';
|
||||
content += '</div>';
|
||||
} else {
|
||||
content += props.participants;
|
||||
}
|
||||
} else {
|
||||
// For player scrim, just show the list
|
||||
content += props.participants;
|
||||
}
|
||||
content += '</span></div>';
|
||||
}
|
||||
|
||||
if (props.description) {
|
||||
content += '<div class="detail-item full-width"><span class="detail-label">Description</span><span class="detail-value">' + props.description + '</span></div>';
|
||||
}
|
||||
|
||||
@@ -194,9 +194,9 @@
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
// Time slots from 5pm (17:00) to 12am (24:00)
|
||||
// Time slots from 12pm (12:00) to 12am (24:00)
|
||||
var TIME_SLOTS = [];
|
||||
for (var h = 17; h <= 24; h++) {
|
||||
for (var h = 12; h <= 24; h++) {
|
||||
for (var m = 0; m < 60; m += 30) {
|
||||
if (h === 24 && m > 0) continue;
|
||||
var displayHour;
|
||||
|
||||
@@ -240,47 +240,84 @@
|
||||
</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>
|
||||
<div class="dashboard-grid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-futbol"></i> My Next Matches</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if stats.next_matches %}
|
||||
<table class="table">
|
||||
<thead><tr><th>Tryout</th><th>Match</th><th>Date & Time</th><th>Opponent</th></tr></thead>
|
||||
<tbody>
|
||||
{% for item in stats.next_matches %}
|
||||
<tr>
|
||||
<td><a href="{{ url_for('tryouts.view_tryout', tryout_id=item.tryout.id) }}">{{ item.tryout.title }}</a></td>
|
||||
<td>{{ item.match.title }}</td>
|
||||
<td>
|
||||
{{ item.match.date.strftime('%m/%d/%Y') }}
|
||||
{% if item.match.start_time %} at {{ item.match.start_time.strftime('%I:%M %p') }}{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.match.match_type == 'team_vs_team' and item.team %}
|
||||
{% if item.match.team1_id == item.team.id %}
|
||||
vs {{ item.match.team2.name if item.match.team2 else 'TBD' }}
|
||||
{% else %}
|
||||
vs {{ item.match.team1.name if item.match.team1 else 'TBD' }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="text-muted">No upcoming matches yet.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<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">
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
<div class="team-rosters mt-3">
|
||||
{% if match.team1 %}
|
||||
<div class="team-roster">
|
||||
<h5>{{ match.team1.name }} Players</h5>
|
||||
<h5>{{ match.team1.name }}</h5>
|
||||
<ul class="team-members-list">
|
||||
{% for member in match.team1.members %}
|
||||
<li>{{ member.player.full_name if member.player else 'Unknown Player' }}{% if member.position %} <span class="position-tag">{{ member.position }}</span>{% endif %}</li>
|
||||
@@ -124,7 +124,7 @@
|
||||
{% endif %}
|
||||
{% if match.team2 %}
|
||||
<div class="team-roster">
|
||||
<h5>{{ match.team2.name }} Players</h5>
|
||||
<h5>{{ match.team2.name }}</h5>
|
||||
<ul class="team-members-list">
|
||||
{% for member in match.team2.members %}
|
||||
<li>{{ member.player.full_name if member.player else 'Unknown Player' }}{% if member.position %} <span class="position-tag">{{ member.position }}</span>{% endif %}</li>
|
||||
@@ -224,9 +224,9 @@
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
// Time slots from 5pm (17:00) to 12am (24:00)
|
||||
// Time slots from 12pm (12:00) to 12am (24:00)
|
||||
var TIME_SLOTS = [];
|
||||
for (var h = 17; h <= 24; h++) {
|
||||
for (var h = 12; h <= 24; h++) {
|
||||
for (var m = 0; m < 60; m += 30) {
|
||||
if (h === 24 && m > 0) continue;
|
||||
var displayHour;
|
||||
|
||||
@@ -288,29 +288,59 @@
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ m.date.strftime('%m/%d/%Y') }}</td>
|
||||
<td>
|
||||
{% if m.match_type == 'team_vs_team' %}
|
||||
{{ participants.team1 }} vs {{ participants.team2 }}
|
||||
{% if participants.team1_players or participants.team2_players %}
|
||||
<div class="team-roster-display mt-1">
|
||||
{% if participants.team1_players %}
|
||||
<small><strong>{{ m.team1.name if m.team1 else 'Team 1' }}:</strong>
|
||||
{% for pl in participants.team1_players %}{{ pl.name }}{% if not loop.last %}, {% endif %}{% endfor %}
|
||||
</small><br>
|
||||
{% endif %}
|
||||
{% if participants.team2_players %}
|
||||
<small><strong>{{ m.team2.name if m.team2 else 'Team 2' }}:</strong>
|
||||
{% for pl in participants.team2_players %}{{ pl.name }}{% if not loop.last %}, {% endif %}{% endfor %}
|
||||
</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% elif m.match_type == 'player_vs_player' %}
|
||||
{{ participants.team1 }} vs {{ participants.team2 }}
|
||||
{% else %}
|
||||
{{ participants | join(', ') }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if m.match_type == 'team_vs_team' %}
|
||||
<div class="match-teams">
|
||||
<div class="match-team">
|
||||
<span class="team-name">{{ m.team1.name if m.team1 else 'Team 1' }}</span>
|
||||
{% if participants.team1_players %}
|
||||
<ul class="team-players-list">
|
||||
{% for pl in participants.team1_players %}
|
||||
<li>{{ pl.name }}{% if pl.position %} <span class="position-tag">{{ pl.position }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="match-vs">vs</div>
|
||||
<div class="match-team">
|
||||
<span class="team-name">{{ m.team2.name if m.team2 else 'Team 2' }}</span>
|
||||
{% if participants.team2_players %}
|
||||
<ul class="team-players-list">
|
||||
{% for pl in participants.team2_players %}
|
||||
<li>{{ pl.name }}{% if pl.position %} <span class="position-tag">{{ pl.position }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% elif m.match_type == 'player_vs_player' %}
|
||||
<div class="match-teams">
|
||||
<div class="match-team">
|
||||
<span class="team-name">Team 1</span>
|
||||
{% if participants.team1_players %}
|
||||
<ul class="team-players-list">
|
||||
{% for pl in participants.team1_players %}
|
||||
<li>{{ pl.name }}{% if pl.position %} <span class="position-tag">{{ pl.position }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="match-vs">vs</div>
|
||||
<div class="match-team">
|
||||
<span class="team-name">Team 2</span>
|
||||
{% if participants.team2_players %}
|
||||
<ul class="team-players-list">
|
||||
{% for pl in participants.team2_players %}
|
||||
<li>{{ pl.name }}{% if pl.position %} <span class="position-tag">{{ pl.position }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ participants | join(', ') }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if m.start_time and m.end_time %}
|
||||
{{ m.start_time.strftime('%H:%M') }} - {{ m.end_time.strftime('%H:%M') }}
|
||||
|
||||
Reference in New Issue
Block a user