230 lines
8.5 KiB
HTML
230 lines
8.5 KiB
HTML
{% extends "layouts/base.html" %}
|
|
{% block title %}Team Matches - UdeS team manager{% endblock %}
|
|
{% block page_title %}Team Matches{% endblock %}
|
|
{% block breadcrumb %}<span class="breadcrumb">Home / Team Matches</span>{% endblock %}
|
|
|
|
{% block header_actions %}
|
|
{% if teams %}
|
|
<div class="header-actions">
|
|
<select id="teamSelect" class="form-select" style="width:200px;" onchange="window.location.href='/team-matches/' + this.value + '/create'">
|
|
<option value="">+ Schedule Match</option>
|
|
{% for t in teams %}
|
|
<option value="{{ t.id }}">{{ t.name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
{% endif %}
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
{% if match_data %}
|
|
<div class="table-container">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Match</th>
|
|
<th>Team</th>
|
|
<th>Opponent</th>
|
|
<th>Date</th>
|
|
<th>Time</th>
|
|
<th>Location</th>
|
|
<th>Presence</th>
|
|
<th>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for item in match_data %}
|
|
{% set m = item.match %}
|
|
<tr>
|
|
<td class="cell-title">{{ m.title }}</td>
|
|
<td>
|
|
<span class="badge badge-info">{{ m.org_team.name }}</span>
|
|
</td>
|
|
<td>
|
|
{% if m.opponent %}
|
|
{{ m.opponent }}
|
|
{% else %}
|
|
<span class="badge badge-info">Practice</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>{{ m.date.strftime('%m/%d/%Y') }}</td>
|
|
<td>
|
|
{% if m.start_time and m.end_time %}
|
|
{{ m.start_time.strftime('%H:%M') }} - {{ m.end_time.strftime('%H:%M') }}
|
|
{% else %}
|
|
TBD
|
|
{% endif %}
|
|
</td>
|
|
<td>{{ m.location or '—' }}</td>
|
|
<td>
|
|
{% if item.total_count > 0 %}
|
|
<div class="presence-bar" title="{{ item.confirmed_count }} of {{ item.total_count }} confirmed">
|
|
<div class="presence-progress">
|
|
{% set pct = (item.confirmed_count / item.total_count * 100) | int %}
|
|
<div class="presence-fill" style="width: {{ pct }}%;"></div>
|
|
</div>
|
|
<span class="presence-text">
|
|
{% if item.confirmed_count == item.total_count and item.total_count > 0 %}
|
|
✅ {{ item.confirmed_count }}/{{ item.total_count }}
|
|
{% elif item.confirmed_count > 0 %}
|
|
⏳ {{ item.confirmed_count }}/{{ item.total_count }}
|
|
{% else %}
|
|
❌ 0/{{ item.total_count }}
|
|
{% endif %}
|
|
</span>
|
|
</div>
|
|
<!-- Player presence details -->
|
|
<div class="presence-players">
|
|
{% for p in item.participants %}
|
|
<span class="presence-player-tag {% if p.is_confirmed %}confirmed{% else %}pending{% endif %}"
|
|
title="{{ p.player.username }}{% if p.is_confirmed %} - Confirmed{% else %} - Pending{% endif %}">
|
|
{{ p.player.username[:2] | upper }} {{ p.player.username }}
|
|
{% if p.is_confirmed %}✅{% else %}⏳{% endif %}
|
|
</span>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<span class="text-muted">—</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
<span class="badge badge-{{ m.status }}">{{ m.status }}</span>
|
|
</td>
|
|
<td class="eval-actions">
|
|
{% set can_manage_this = (current_user.role in ['admin', 'manager']) or (current_user.role == 'coach' and m.org_team.coaches.filter_by(id=current_user.id).first()) or (current_user.role == 'coach' and m.org_team.coach_id == current_user.id) %}
|
|
{% if can_manage_this %}
|
|
<a href="{{ url_for('team_matches.edit_match', match_id=m.id) }}" class="btn btn-sm btn-outline" title="Edit Match">
|
|
<i class="fas fa-edit"></i>
|
|
</a>
|
|
<form method="POST" action="{{ url_for('team_matches.delete_match', match_id=m.id) }}" class="inline-form" onsubmit="return confirm('Delete this match?')">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
|
<button type="submit" class="btn btn-sm btn-danger" title="Delete Match">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</form>
|
|
{% endif %}
|
|
<!-- Toggle presence for each participant if user is player -->
|
|
{% if current_user.role == 'player' %}
|
|
{% for p in item.participants %}
|
|
{% if p.player.id == current_user.id %}
|
|
<button class="btn btn-sm {% if p.is_confirmed %}btn-success{% else %}btn-outline{% endif %} presence-toggle-btn"
|
|
data-match-id="{{ m.id }}"
|
|
data-participant-id="{{ p.id }}"
|
|
onclick="togglePresence(this)">
|
|
{% if p.is_confirmed %}✅ Confirmed{% else %}Confirm{% endif %}
|
|
</button>
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<div class="card">
|
|
<div class="card-body text-center py-5">
|
|
<div class="empty-state">
|
|
<i class="fas fa-futbol fa-3x text-muted mb-3"></i>
|
|
<h3>No Team Matches</h3>
|
|
<p class="text-muted">Regular season matches have not been scheduled yet.</p>
|
|
{% if teams %}
|
|
<div class="mt-3">
|
|
<select id="teamSelectEmpty" class="form-select" style="width:220px; display:inline;" onchange="window.location.href='/team-matches/' + this.value + '/create'">
|
|
<option value="">-- Schedule a Match --</option>
|
|
{% for t in teams %}
|
|
<option value="{{ t.id }}">{{ t.name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<script>
|
|
function togglePresence(btn) {
|
|
var matchId = btn.getAttribute('data-match-id');
|
|
var participantId = btn.getAttribute('data-participant-id');
|
|
|
|
fetch('/team-matches/' + matchId + '/toggle-presence/' + participantId, {
|
|
method: 'POST',
|
|
headers: {
|
|
'X-CSRFToken': '{{ csrf_token() }}',
|
|
'Content-Type': 'application/json'
|
|
}
|
|
})
|
|
.then(function(response) { return response.json(); })
|
|
.then(function(data) {
|
|
if (data.is_confirmed) {
|
|
btn.classList.add('btn-success');
|
|
btn.classList.remove('btn-outline');
|
|
btn.innerHTML = '✅ Confirmed';
|
|
} else {
|
|
btn.classList.remove('btn-success');
|
|
btn.classList.add('btn-outline');
|
|
btn.innerHTML = 'Confirm';
|
|
}
|
|
// Reload to update presence bar
|
|
location.reload();
|
|
})
|
|
.catch(function(error) {
|
|
console.error('Error:', error);
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.presence-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin-bottom: 4px;
|
|
}
|
|
.presence-progress {
|
|
width: 60px;
|
|
height: 6px;
|
|
background: #e5e7eb;
|
|
border-radius: 3px;
|
|
overflow: hidden;
|
|
}
|
|
.presence-fill {
|
|
height: 100%;
|
|
background: #10b981;
|
|
border-radius: 3px;
|
|
}
|
|
.presence-text {
|
|
font-size: 0.8rem;
|
|
font-weight: 600;
|
|
}
|
|
.presence-players {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 3px;
|
|
margin-top: 3px;
|
|
}
|
|
.presence-player-tag {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 2px;
|
|
padding: 1px 5px;
|
|
border-radius: 10px;
|
|
font-size: 0.7rem;
|
|
font-weight: 600;
|
|
}
|
|
.presence-player-tag.confirmed {
|
|
background: #d1fae5;
|
|
color: #065f46;
|
|
}
|
|
.presence-player-tag.pending {
|
|
background: #fef3c7;
|
|
color: #92400e;
|
|
}
|
|
.presence-toggle-btn {
|
|
margin-left: 4px;
|
|
}
|
|
</style>
|
|
{% endblock %} |