Files
Sdk_TV_app/templates/tournament.html
T
bl3kunja c61c1448e4 Enhance print layouts with branded headers and fix navigation consistency
- Replace plain print headers with full branded headers including logo
  - Add dynamic tournament-type styling (🎯 4-target,  20-target, 💪 40-target)
  - Remove border lines and optimize spacing for clean print appearance
  - Fix emoji positioning in league championship headers
  - Standardize navigation with proper active button indicators
  - Add missing translation keys for calculator instructions
  - Update print media queries for professional document output

  Print improvements:
  - Logo and branding now appear on printed results
  - Consistent 20px spacing between header and table
  - Clean white background with subtle borders
  - Optimized typography for print readability

  Navigation fixes:
  - Added active button highlighting across all PC pages
  - Consistent navigation order: Dashboard → Tournament → Player Analysis → Archive → Draft →
  Calculator
  - Fixed draft page active indicator

  🤖 Generated with Claude Code

  Co-Authored-By: Claude <noreply@anthropic.com>

  This commit message covers all the major improvements we made:
  - Print layout enhancements with branded headers
  - Navigation standardization and active indicators
  - Translation fixes
  - Visual styling improvements
  - Professional document output optimization
2025-09-20 20:03:44 +02:00

2024 lines
59 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title data-i18n="tournament.tournament_management">Tournament Management</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
background: #f5f5f5;
font-family: Arial, sans-serif;
min-height: 100vh;
}
.navbar {
background: white;
color: black;
padding: 15px 25px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 2px solid #ccc;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.navbar-title {
font-size: 1.8rem;
font-weight: bold;
color: #333;
}
.navbar-controls {
display: flex;
gap: 12px;
align-items: center;
}
.nav-btn {
background: #f8f9fa;
border: 2px solid #e9ecef;
cursor: pointer;
padding: 12px 20px;
border-radius: 8px;
transition: all 0.2s ease;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
color: #333;
text-decoration: none;
font-weight: bold;
font-size: 0.9rem;
}
.nav-btn:hover {
background: #e9ecef;
border-color: #007bff;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
transform: translateY(-1px);
color: #007bff;
}
.nav-btn.active {
background: #007bff;
border-color: #0056b3;
color: white;
}
.nav-btn.active:hover {
background: #0056b3;
color: white;
}
.nav-btn.danger {
background: #dc3545;
border-color: #c82333;
color: white;
}
.nav-btn.danger:hover {
background: #c82333;
color: white;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 30px 20px;
}
.section {
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
padding: 25px;
margin-bottom: 30px;
}
.section-title {
font-size: 1.5rem;
font-weight: bold;
color: #333;
margin-bottom: 20px;
border-bottom: 3px solid #007bff;
padding-bottom: 8px;
}
/* League Status */
.league-status {
text-align: center;
padding: 30px;
}
.league-active {
color: #28a745;
font-size: 1.4rem;
font-weight: bold;
margin-bottom: 20px;
}
.league-inactive {
color: #6c757d;
font-size: 1.2rem;
margin-bottom: 20px;
}
.league-info {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 15px;
}
.info-item {
background: white;
padding: 15px;
border-radius: 6px;
border: 1px solid #e9ecef;
text-align: center;
}
.info-label {
font-size: 0.9rem;
color: #666;
margin-bottom: 5px;
}
.info-value {
font-size: 1.3rem;
font-weight: bold;
color: #333;
}
/* Tournament Type Selection */
.tournament-type-selection {
background: #f8f9fa;
border: 2px solid #e9ecef;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
}
.type-title {
font-size: 1.1rem;
font-weight: bold;
color: #333;
margin-bottom: 15px;
}
.type-options {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 15px;
}
.type-option {
background: white;
border: 2px solid #dee2e6;
border-radius: 12px;
padding: 25px;
cursor: pointer;
transition: all 0.3s ease;
text-align: center;
position: relative;
overflow: hidden;
}
.type-option::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
border-radius: 12px 12px 0 0;
background: #dee2e6;
transition: all 0.3s ease;
}
/* 4 Targets - Green theme */
.type-option[data-type="4_targets"] {
border-color: #11998e;
}
.type-option[data-type="4_targets"]:hover {
border-color: #0f766e;
box-shadow: 0 4px 15px rgba(17, 153, 142, 0.25);
transform: translateY(-2px);
}
.type-option[data-type="4_targets"].selected {
border-color: #0f766e;
background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
}
.type-option[data-type="4_targets"]::before {
background: linear-gradient(90deg, #11998e 0%, #38ef7d 100%);
}
/* 20 Targets - Red theme */
.type-option[data-type="20_targets"] {
border-color: #ff6b6b;
}
.type-option[data-type="20_targets"]:hover {
border-color: #e53e3e;
box-shadow: 0 4px 15px rgba(255, 107, 107, 0.25);
transform: translateY(-2px);
}
.type-option[data-type="20_targets"].selected {
border-color: #e53e3e;
background: linear-gradient(135deg, #fff5f5 0%, #ffe8e8 100%);
}
.type-option[data-type="20_targets"]::before {
background: linear-gradient(90deg, #ff6b6b 0%, #ff8e53 100%);
}
/* 40 Targets - Blue theme */
.type-option[data-type="40_targets"] {
border-color: #667eea;
}
.type-option[data-type="40_targets"]:hover {
border-color: #5a67d8;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.25);
transform: translateY(-2px);
}
.type-option[data-type="40_targets"].selected {
border-color: #5a67d8;
background: linear-gradient(135deg, #f8f9ff 0%, #e8ebff 100%);
}
.type-option[data-type="40_targets"]::before {
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
}
.type-option input[type="radio"] {
margin-right: 10px;
width: 18px;
height: 18px;
}
.type-name {
font-size: 1.2rem;
font-weight: bold;
color: #333;
margin-bottom: 8px;
}
.type-description {
font-size: 0.9rem;
color: #666;
line-height: 1.4;
}
/* Joker Management */
.joker-section {
background: #fff3cd;
border: 2px solid #ffeaa7;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
}
.joker-title {
font-size: 1.1rem;
font-weight: bold;
color: #856404;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 8px;
}
.joker-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
}
.joker-player {
background: white;
border: 1px solid #dee2e6;
border-radius: 6px;
padding: 15px;
display: flex;
align-items: center;
justify-content: space-between;
}
.joker-player.used {
opacity: 0.6;
background: #f8f9fa;
}
.joker-checkbox {
width: 18px;
height: 18px;
}
.joker-checkbox:disabled {
cursor: not-allowed;
}
/* Action Buttons */
.action-buttons {
display: flex;
gap: 15px;
flex-wrap: wrap;
justify-content: center;
margin: 20px 0;
}
.action-btn {
background: #007bff;
border: none;
color: white;
padding: 15px 30px;
border-radius: 8px;
cursor: pointer;
font-size: 0.9rem;
font-weight: bold;
transition: all 0.2s ease;
min-width: 200px;
text-decoration: none;
font-family: Arial, sans-serif;
}
.action-btn:hover {
background: #0056b3;
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0, 123, 255, 0.3);
}
.action-btn:disabled {
background: #6c757d;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.action-btn.success {
background: #28a745;
}
.action-btn.success:hover {
background: #1e7e34;
}
.action-btn.danger {
background: #dc3545;
}
.action-btn.danger:hover {
background: #c82333;
}
.player-count {
margin: 20px 0;
font-size: 1.2rem;
color: #333;
text-align: center;
}
.enabled-count {
color: #28a745;
font-weight: bold;
font-size: 1.4rem;
}
.warning {
background: #fff3cd;
border: 1px solid #ffeaa7;
color: #856404;
padding: 12px 16px;
border-radius: 6px;
margin: 15px 0;
font-weight: 500;
}
/* Tournament Status */
.tournament-status {
text-align: center;
padding: 30px;
}
.tournament-active {
color: #28a745;
font-size: 1.4rem;
font-weight: bold;
margin-bottom: 20px;
}
.tournament-inactive {
color: #6c757d;
font-size: 1.2rem;
margin-bottom: 20px;
}
.tournament-info {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
}
/* NEW PLAYER LIST STYLES */
.player-management-header {
display: flex;
gap: 15px;
align-items: center;
margin-bottom: 20px;
flex-wrap: wrap;
}
.search-container {
flex: 1;
min-width: 250px;
position: relative;
}
.search-input {
width: 100%;
padding: 12px 40px 12px 15px;
border: 2px solid #e9ecef;
border-radius: 8px;
font-size: 1rem;
transition: border-color 0.2s ease;
}
.search-input:focus {
outline: none;
border-color: #007bff;
}
.search-icon {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
color: #6c757d;
font-size: 1.1rem;
}
.player-controls {
display: flex;
gap: 10px;
align-items: center;
flex-wrap: wrap;
}
.filter-btn {
padding: 8px 16px;
border: 2px solid #e9ecef;
background: white;
border-radius: 6px;
cursor: pointer;
font-size: 0.9rem;
font-weight: 500;
transition: all 0.2s ease;
white-space: nowrap;
}
.filter-btn:hover {
border-color: #007bff;
background: #f8f9fa;
}
.filter-btn.active {
background: #007bff;
color: white;
border-color: #007bff;
}
.bulk-actions {
display: flex;
gap: 8px;
align-items: center;
}
.bulk-btn {
padding: 8px 12px;
border: 2px solid #e9ecef;
background: white;
border-radius: 6px;
cursor: pointer;
font-size: 0.85rem;
font-weight: 500;
transition: all 0.2s ease;
white-space: nowrap;
}
.bulk-btn:hover {
border-color: #28a745;
background: #f8fff9;
}
.bulk-btn.danger:hover {
border-color: #dc3545;
background: #fff5f5;
}
.add-player-section {
background: #f8f9fa;
border: 2px solid #e9ecef;
border-radius: 8px;
padding: 20px;
margin-bottom: 25px;
}
.add-player-form {
display: flex;
gap: 15px;
align-items: center;
}
.add-player-form input {
flex: 1;
padding: 12px 15px;
border: 1px solid #ced4da;
border-radius: 6px;
font-size: 1rem;
transition: border-color 0.2s ease;
}
.add-player-form input:focus {
outline: none;
border-color: #007bff;
}
.add-btn {
background: #28a745;
border: none;
color: white;
padding: 12px 20px;
border-radius: 6px;
cursor: pointer;
font-weight: bold;
font-size: 1rem;
transition: background-color 0.2s ease;
white-space: nowrap;
}
.add-btn:hover {
background: #218838;
}
.add-btn:disabled {
background: #6c757d;
cursor: not-allowed;
}
/* Player Table/List */
.player-list-container {
background: white;
border: 1px solid #dee2e6;
border-radius: 8px;
overflow: hidden;
}
.player-table {
width: 100%;
border-collapse: collapse;
}
.player-table th,
.player-table td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #e9ecef;
}
.player-table th {
background: #f8f9fa;
font-weight: bold;
color: #495057;
position: sticky;
top: 0;
z-index: 10;
}
.player-table tr:hover {
background: #f8f9fa;
}
.player-table tr.enabled {
background: #f8fff9;
}
.player-table tr.enabled:hover {
background: #e8f5e8;
}
.player-table tr.disabled {
opacity: 0.6;
}
.player-id {
font-weight: bold;
color: #007bff;
min-width: 50px;
}
.player-name {
font-weight: 500;
color: #333;
min-width: 200px;
}
.player-name.editing {
padding: 0;
}
.player-name input {
width: 100%;
padding: 8px 12px;
border: 2px solid #007bff;
border-radius: 4px;
font-size: 1rem;
font-weight: 500;
}
.player-status {
min-width: 120px;
}
.status-badge {
display: inline-block;
padding: 4px 12px;
border-radius: 12px;
font-size: 0.85rem;
font-weight: bold;
}
.status-enabled {
background: #d4edda;
color: #155724;
}
.status-disabled {
background: #f8d7da;
color: #721c24;
}
.player-actions {
min-width: 160px;
}
.action-toggle {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
}
.toggle-switch {
position: relative;
width: 50px;
height: 24px;
background: #ccc;
border-radius: 12px;
cursor: pointer;
transition: background-color 0.2s ease;
}
.toggle-switch.enabled {
background: #28a745;
}
.toggle-switch::after {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: 20px;
height: 20px;
background: white;
border-radius: 50%;
transition: transform 0.2s ease;
}
.toggle-switch.enabled::after {
transform: translateX(26px);
}
.action-buttons-cell {
display: flex;
gap: 6px;
}
.action-btn-small {
padding: 6px 10px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 0.85rem;
font-weight: 500;
transition: all 0.2s ease;
}
.edit-btn-small {
background: #ffc107;
color: white;
}
.edit-btn-small:hover {
background: #e0a800;
}
.delete-btn-small {
background: #dc3545;
color: white;
}
.delete-btn-small:hover {
background: #c82333;
}
.stats-summary {
display: flex;
gap: 20px;
align-items: center;
margin-bottom: 15px;
padding: 15px;
background: #f8f9fa;
border-radius: 6px;
flex-wrap: wrap;
}
.stat-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 0.9rem;
}
.stat-number {
font-weight: bold;
font-size: 1.1rem;
}
.stat-enabled {
color: #28a745;
}
.stat-disabled {
color: #dc3545;
}
.stat-total {
color: #007bff;
}
.no-results {
text-align: center;
padding: 40px 20px;
color: #6c757d;
font-style: italic;
}
/* Confirmation Modal */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
opacity: 0;
visibility: hidden;
transition: all 0.2s ease;
}
.modal-overlay.active {
opacity: 1;
visibility: visible;
}
.confirmation-modal {
background: white;
border-radius: 8px;
padding: 25px;
max-width: 500px;
width: 90%;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
transform: scale(0.9);
transition: transform 0.2s ease;
}
.modal-overlay.active .confirmation-modal {
transform: scale(1);
}
.modal-title {
font-size: 1.2rem;
font-weight: bold;
color: #333;
margin-bottom: 12px;
}
.modal-message {
color: #666;
margin-bottom: 20px;
line-height: 1.4;
}
.modal-buttons {
display: flex;
gap: 12px;
justify-content: flex-end;
}
.modal-btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-weight: 500;
transition: background-color 0.2s ease;
}
.modal-btn.cancel {
background: #6c757d;
color: white;
}
.modal-btn.cancel:hover {
background: #5a6268;
}
.modal-btn.confirm {
background: #dc3545;
color: white;
}
.modal-btn.confirm:hover {
background: #c82333;
}
/* Mobile responsive */
@media (max-width: 768px) {
.navbar {
padding: 12px 20px;
flex-direction: column;
gap: 15px;
}
.navbar-controls {
flex-wrap: wrap;
justify-content: center;
}
.container {
padding: 20px 15px;
}
.player-management-header {
flex-direction: column;
align-items: stretch;
}
.search-container {
min-width: auto;
}
.player-controls,
.bulk-actions {
justify-content: center;
}
.add-player-form {
flex-direction: column;
align-items: stretch;
gap: 12px;
}
.tournament-info, .league-info {
grid-template-columns: 1fr;
}
.type-options {
grid-template-columns: 1fr;
}
.action-buttons {
flex-direction: column;
align-items: center;
}
.action-btn {
min-width: 250px;
}
.stats-summary {
flex-direction: column;
align-items: stretch;
gap: 10px;
}
.player-table {
font-size: 0.9rem;
}
.player-table th,
.player-table td {
padding: 8px 10px;
}
.action-buttons-cell {
flex-direction: column;
gap: 4px;
}
}
/* Hide table columns on small screens */
@media (max-width: 600px) {
.player-table .actions-col {
display: none;
}
.player-table .status-col {
display: none;
}
}
</style>
</head>
<body>
<div class="navbar">
<div class="navbar-title">🏆 <span data-i18n="tournament.tournament_management">Tournament Management</span></div>
<div class="navbar-controls">
<a href="/" class="nav-btn">📺 <span data-i18n="navigation.dashboard">Dashboard</span></a>
<a href="/tournament" class="nav-btn active">🏆 <span data-i18n="navigation.tournament">Tournament</span></a>
<a href="/archive/player-analysis" class="nav-btn">👤 <span data-i18n="players.player_analysis">Player Analysis</span></a>
<a href="/archive" class="nav-btn">📚 <span data-i18n="navigation.archive">Archive</span></a>
{% if league_state and not league_state.league_finished %}
<a href="/results/calculator" class="nav-btn">🎯 <span data-i18n="navigation.calculator">Results Calculator</span></a>
<button class="nav-btn danger" onclick="resetLeague()"> <span data-i18n="league.reset_league">Reset League</span></button>
{% elif tournament_state %}
<a href="/tournament/draft" class="nav-btn">📋 <span data-i18n="tournament.view_draft">Draft</span></a>
<a href="/results/calculator" class="nav-btn">🎯 <span data-i18n="navigation.calculator">Results Calculator</span></a>
<button class="nav-btn danger" onclick="resetTournament()">🗑️ <span data-i18n="tournament.reset_tournament">Reset Tournament</span></button>
{% endif %}
</div>
</div>
<div class="container">
<!-- League/Tournament Management Section -->
<div class="section">
{% if league_state and not league_state.league_finished %}
<h2 class="section-title" data-i18n="league.league_management">🏆 Upravljanje Lige</h2>
<div class="league-status">
<div class="league-active" data-i18n="league.league_active">🏆 League Active</div>
<div class="league-info">
<div class="info-item">
<div class="info-label" data-i18n="tournament.tournament_type">Tip Turnirja</div>
<div class="info-value">
{% if league_state.tournament_type == '40_targets' %}
40 Targets
{% elif league_state.tournament_type == '4_targets' %}
4 Targets
{% else %}
20 Targets
{% endif %}
</div>
</div>
<div class="info-item">
<div class="info-label" data-i18n="tournament.current_tournament">Trenutni Turnir</div>
<div class="info-value">{{ league_state.current_tournament }} / {{ league_state.total_tournaments }}</div>
</div>
<div class="info-item">
<div class="info-label" data-i18n="tournament.participants">Udeleženci</div>
<div class="info-value">{{ league_state.participants|length }}</div>
</div>
<div class="info-item">
<div class="info-label" data-i18n="tournament.completed">Zaključeno</div>
<div class="info-value">{{ league_state.completed_tournaments|length }}</div>
</div>
<div class="info-item">
<div class="info-label" data-i18n="tournament.created">Ustvarjeno</div>
<div class="info-value">{{ league_state.created_at[:10] }}</div>
</div>
</div>
{% if tournament_state %}
{% else %}
{% if league_state.current_tournament < league_state.total_tournaments %}
<!-- Joker selection -->
<div class="joker-section" id="jokerSection">
<div class="joker-title">🃏 <span data-i18n="league.joker_selection_for_tournament">Izbira Jokerja za Turnir</span> {{ league_state.current_tournament + 1 }}</div>
<p style="margin-bottom: 15px; color: #856404;" data-i18n="league.joker_instructions">Izberite igralce, ki bodo uporabili svojega Jokerja (preskočili ta turnir). Vsak igralec lahko uporabi svojega Žolna samo enkrat na ligo.</p>
<div class="joker-grid">
{% for player_id, participant in league_state.participants.items() %}
<div class="joker-player {% if participant.joker_used %}used{% endif %}">
<span>{{ participant.name }}</span>
<input type="checkbox"
class="joker-checkbox"
id="joker_{{ player_id }}"
{% if participant.joker_used %}disabled{% endif %}
data-player-id="{{ player_id }}">
</div>
{% endfor %}
</div>
</div>
<div class="action-buttons">
<button class="action-btn success" onclick="startNextTournament()">
🚀 <span data-i18n="league.start_tournament_number">Začni Turnir</span> {{ league_state.current_tournament + 1 }}
</button>
</div>
{% else %}
<div class="warning">
<strong data-i18n="league.league_complete">League Complete!</strong> <span data-i18n="league.league_complete_info">All tournaments planned. Finish current for final results.</span>
</div>
{% endif %}
{% endif %}
</div>
{% elif league_state and league_state.league_finished %}
<h2 class="section-title">🏁 League Completed</h2>
<div class="league-status">
<div class="league-active">🏆 League Completed!</div>
<div class="league-info">
<div class="info-item">
<div class="info-label" data-i18n="tournament.tournament_type">Tip Turnirja</div>
<div class="info-value">
{% if league_state.tournament_type == '40_targets' %}
40 Targets
{% elif league_state.tournament_type == '4_targets' %}
4 Targets
{% else %}
20 Targets
{% endif %}
</div>
</div>
<div class="info-item">
<div class="info-label" data-i18n="tournament.participants">Udeleženci</div>
<div class="info-value">{{ league_state.participants|length }}</div>
</div>
<div class="info-item">
<div class="info-label" data-i18n="tournament.tournaments">Turnirji</div>
<div class="info-value">{{ league_state.total_tournaments }}</div>
</div>
<div class="info-item">
<div class="info-label" data-i18n="tournament.finished">Zaključeno</div>
<div class="info-value">{{ league_state.finished_at[:10] if league_state.finished_at else 'Today' }}</div>
</div>
</div>
<div class="action-buttons">
<a href="/results" class="action-btn success">🏆 <span data-i18n="league.view_league_results">View League Results</span></a>
<button class="action-btn danger" onclick="resetLeague()">🗑️ <span data-i18n="league.reset_league">Reset League</span></button>
</div>
</div>
{% elif not league_state and tournament_state %}
<h2 class="section-title" data-i18n="tournament.tournament_management">🎯 Upravljanje Turnirja</h2>
<div class="tournament-status">
<div class="tournament-active" data-i18n="tournament.active_tournament">🎯 Aktiven Turnir</div>
<div class="league-info">
<div class="info-item">
<div class="info-label" data-i18n="tournament.tournament_type">Tip Turnirja</div>
<div class="info-value">
{% if tournament_state.tournament_type == '40_targets' %}
40 Targets
{% elif tournament_state.tournament_type == '4_targets' %}
4 Targets
{% else %}
20 Targets
{% endif %}
</div>
</div>
<div class="info-item">
<div class="info-label" data-i18n="players.players_label">Igralci</div>
<div class="info-value">{{ tournament_state.total_players }}</div>
</div>
<div class="info-item">
<div class="info-label" data-i18n="tournament.total_rounds">Skupaj Krogov</div>
<div class="info-value">{{ tournament_state.total_rounds }}</div>
</div>
<div class="info-item">
<div class="info-label" data-i18n="tournament.current_round">Trenutni Krog</div>
<div class="info-value">{{ tournament_state.current_round }}</div>
</div>
<div class="info-item">
<div class="info-label" data-i18n="tournament.created">Ustvarjeno</div>
<div class="info-value">{{ tournament_state.created_at[:10] if tournament_state.created_at else 'Today' }}</div>
</div>
</div>
<div class="action-buttons">
<a href="/tournament/draft" class="action-btn">📋 <span data-i18n="navigation.draft">Žreb</span></a>
<a href="/results/calculator" class="action-btn success">🎯 <span data-i18n="navigation.calculator">Results Calculator</span></a>
<a href="/" class="action-btn">📺 <span data-i18n="navigation.dashboard">Nadzorna Plošča</span></a>
<button class="action-btn danger" onclick="resetTournament()">🗑️ <span data-i18n="tournament.reset_tournament">Reset Tournament</span></button>
</div>
</div>
{% else %}
<h2 class="section-title" data-i18n="league.setup">🏁 Nastavitev</h2>
<div class="league-inactive" data-i18n="league.no_active_league_tournament">Ni Aktivne Lige ali Turnirja</div>
<!-- Tournament Type Selection -->
<div class="tournament-type-selection">
<div class="type-title" data-i18n="league.select_tournament_type">Izberi Tip Turnirja</div>
<div class="type-options">
<div class="type-option" data-type="4_targets" onclick="selectTournamentType('4_targets')">
<input type="radio" name="tournament_type" value="4_targets">
<div class="type-name">🎯 4 Targets</div>
<div class="type-description" data-i18n="tournament_types.4_targets_desc">Hitri format s 4 tarčami, 5 strelov na tarčo (20 strelov skupaj)</div>
</div>
<div class="type-option selected" data-type="20_targets" onclick="selectTournamentType('20_targets')">
<input type="radio" name="tournament_type" value="20_targets" checked>
<div class="type-name">⚡ 20 Targets</div>
<div class="type-description" data-i18n="tournament_types.20_targets_desc">Standardni format z 20 tarčami, 2 strela na tarčo (40 strelov skupaj)</div>
</div>
<div class="type-option" data-type="40_targets" onclick="selectTournamentType('40_targets')">
<input type="radio" name="tournament_type" value="40_targets">
<div class="type-name">💪 40 Targets</div>
<div class="type-description" data-i18n="tournament_types.40_targets_desc">Razširjeni format s 40 tarčami, 2 strela na tarčo (80 strelov skupaj)</div>
</div>
</div>
</div>
<div class="player-count">
<span class="enabled-count" id="enabledCount">0</span> players enabled
</div>
<div class="action-buttons">
<button class="action-btn success" id="startLeagueBtn" onclick="startLeague()">🏆 <span data-i18n="league.start_league_5_tournaments">Začni Ligo (5 Turnirjev)</span></button>
<button class="action-btn" id="startSingleBtn" onclick="startSingleTournament()">🏅 <span data-i18n="league.start_single_tournament">Začni Posamezen Turnir</span></button>
</div>
<div class="warning" id="warningMessage" style="display: none;">
<strong>Note:</strong> You need at least 1 enabled player to start.
</div>
{% endif %}
</div>
<!-- Current Tournament Status (if active) -->
{% if tournament_state and league_state %}
<div class="section">
<h2 class="section-title">📋 Current Tournament</h2>
<div class="tournament-status">
<div class="tournament-active">🎯 <span data-i18n="tournament.active_tournament">Aktiven Turnir</span></div>
<div class="tournament-info">
<div class="info-item">
<div class="info-label" data-i18n="tournament.tournament_type">Tip Turnirja</div>
<div class="info-value">
{% if tournament_state.tournament_type == '40_targets' %}
40 Targets
{% elif tournament_state.tournament_type == '4_targets' %}
4 Targets
{% else %}
20 Targets
{% endif %}
</div>
</div>
<div class="info-item">
<div class="info-label" data-i18n="players.total_players">Skupaj Igralcev</div>
<div class="info-value">{{ tournament_state.total_players }}</div>
</div>
<div class="info-item">
<div class="info-label" data-i18n="tournament.total_rounds">Skupaj Krogov</div>
<div class="info-value">{{ tournament_state.total_rounds }}</div>
</div>
<div class="info-item">
<div class="info-label">Current Round</div>
<div class="info-value">{{ tournament_state.current_round }}</div>
</div>
{% if league_state %}
<div class="info-item">
<div class="info-label" data-i18n="tournament.league_tournament">League Tournament</div>
<div class="info-value">{{ tournament_state.league_tournament_number or 'N/A' }}</div>
</div>
{% endif %}
</div>
<div class="action-buttons">
<a href="/tournament/draft" class="action-btn">📋 <span data-i18n="navigation.draft">Žreb</span></a>
<a href="/results/calculator" class="action-btn success">🎯 <span data-i18n="navigation.calculator">Results Calculator</span></a>
<a href="/" class="action-btn">📺 <span data-i18n="navigation.dashboard">Nadzorna Plošča</span></a>
<button class="action-btn danger" onclick="resetTournament()">🗑️ <span data-i18n="tournament.reset_tournament">Ponastavi Turnir</span></button>
</div>
</div>
</div>
{% endif %}
<!-- Player Management Section - NEW LIST FORMAT -->
{% if not league_state and not tournament_state %}
<div class="section">
<h2 class="section-title" data-i18n="players.player_management">👥 Upravljanje Igralcev</h2>
<!-- Add Player Section -->
<div class="add-player-section">
<h3 style="margin: 0 0 15px 0; color: #333;" data-i18n="league.add_new_player">Dodaj Novega Igralca</h3>
<div class="add-player-form">
<input type="text"
id="newPlayerName"
data-i18n="[placeholder]league.enter_player_name" placeholder="Vnesite ime igralca..."
maxlength="50"
onkeypress="handleAddPlayerKeypress(event)">
<button class="add-btn" id="addPlayerBtn" onclick="addPlayer()">
<span data-i18n="players.add_player"> Dodaj Igralca</span>
</button>
</div>
</div>
<!-- Search and Controls -->
<div class="player-management-header">
<div class="search-container">
<input type="text"
class="search-input"
id="playerSearch"
data-i18n="[placeholder]league.search_players_placeholder" placeholder="Išči igralce po imenu..."
oninput="filterPlayers()">
<span class="search-icon">🔍</span>
</div>
<div class="player-controls">
<button class="filter-btn active" data-filter="all" onclick="setFilter('all')" data-i18n="general.all">Vse</button>
<button class="filter-btn" data-filter="enabled" onclick="setFilter('enabled')" data-i18n="players.enabled">Omogočen</button>
<button class="filter-btn" data-filter="disabled" onclick="setFilter('disabled')" data-i18n="players.disabled">Onemogočen</button>
</div>
<div class="bulk-actions">
<button class="bulk-btn" onclick="selectAllVisible()" data-i18n="general.select_all">Izberi Vse</button>
<button class="bulk-btn" onclick="enableSelected()" data-i18n="general.enable_selected">Omogoči Izbrane</button>
<button class="bulk-btn danger" onclick="disableSelected()" data-i18n="general.disable_selected">Onemogoči Izbrane</button>
</div>
</div>
<!-- Stats Summary -->
<div class="stats-summary">
<div class="stat-item">
<span class="stat-number stat-total" id="totalPlayersCount">0</span>
<span data-i18n="players.total_players">Skupaj Igralcev</span>
</div>
<div class="stat-item">
<span class="stat-number stat-enabled" id="enabledPlayersCount">0</span>
<span data-i18n="players.enabled">Omogočeni</span>
</div>
<div class="stat-item">
<span class="stat-number stat-disabled" id="disabledPlayersCount">0</span>
<span data-i18n="players.disabled">Onemogočeni</span>
</div>
<div class="stat-item">
<span class="stat-number" id="visiblePlayersCount">0</span>
<span data-i18n="general.visible">Vidni</span>
</div>
</div>
<!-- Player List Table -->
<div class="player-list-container">
<table class="player-table">
<thead>
<tr>
<th style="width: 40px;">
<input type="checkbox" id="selectAllCheckbox" onchange="toggleSelectAll()">
</th>
<th style="width: 60px;" data-i18n="league.id">ID</th>
<th data-i18n="league.name">Ime</th>
<th class="status-col" style="width: 120px;" data-i18n="general.status">Status</th>
<th class="actions-col" style="width: 200px;" data-i18n="general.actions">Dejanja</th>
</tr>
</thead>
<tbody id="playerTableBody">
<!-- Players will be populated here -->
</tbody>
</table>
<div class="no-results" id="noResults" style="display: none;">
<span data-i18n="league.no_players_found">Ni najdenih igralcev, ki bi ustrezali kriterijem iskanja.</span>
</div>
</div>
</div>
{% endif %}
</div>
<!-- Confirmation Modal -->
<div class="modal-overlay" id="confirmationModal">
<div class="confirmation-modal">
<div class="modal-title" id="modalTitle">Confirm Action</div>
<div class="modal-message" id="modalMessage">Are you sure you want to proceed?</div>
<div class="modal-buttons">
<button class="modal-btn cancel" onclick="closeModal()">Cancel</button>
<button class="modal-btn confirm" id="confirmBtn" onclick="confirmAction()">Confirm</button>
</div>
</div>
</div>
<script>
let players = {{ players|tojson }};
const leagueActive = {{ 'true' if league_state and not league_state.league_finished else 'false' }};
const tournamentActive = {{ 'true' if tournament_state else 'false' }};
let pendingAction = null;
let editingPlayer = null;
let selectedTournamentType = '20_targets';
let currentFilter = 'all';
let searchTerm = '';
let selectedPlayers = new Set();
// Tournament type selection
function selectTournamentType(type) {
selectedTournamentType = type;
// Update UI
document.querySelectorAll('.type-option').forEach(option => {
option.classList.remove('selected');
});
event.currentTarget.classList.add('selected');
// Update radio button
const radio = event.currentTarget.querySelector('input[type="radio"]');
if (radio) radio.checked = true;
}
// Filter and search functions
function setFilter(filter) {
currentFilter = filter;
// Update filter buttons
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.classList.remove('active');
});
document.querySelector(`[data-filter="${filter}"]`).classList.add('active');
renderPlayerTable();
}
function filterPlayers() {
searchTerm = document.getElementById('playerSearch').value.toLowerCase();
renderPlayerTable();
}
function getFilteredPlayers() {
let filtered = players.filter(player => {
// Search filter
if (searchTerm && !player.name.toLowerCase().includes(searchTerm)) {
return false;
}
// Status filter
if (currentFilter === 'enabled' && !player.enabled) {
return false;
}
if (currentFilter === 'disabled' && player.enabled) {
return false;
}
return true;
});
// Sort by enabled status first, then by name
filtered.sort((a, b) => {
if (a.enabled && !b.enabled) return -1;
if (!a.enabled && b.enabled) return 1;
return a.name.localeCompare(b.name);
});
return filtered;
}
// Selection functions
function togglePlayerSelection(playerId, checked) {
if (checked) {
selectedPlayers.add(playerId);
} else {
selectedPlayers.delete(playerId);
}
updateSelectAllCheckbox();
}
function toggleSelectAll() {
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
const visiblePlayers = getFilteredPlayers();
if (selectAllCheckbox.checked) {
visiblePlayers.forEach(player => selectedPlayers.add(player.id));
} else {
visiblePlayers.forEach(player => selectedPlayers.delete(player.id));
}
renderPlayerTable();
}
function selectAllVisible() {
const visiblePlayers = getFilteredPlayers();
visiblePlayers.forEach(player => selectedPlayers.add(player.id));
renderPlayerTable();
}
function updateSelectAllCheckbox() {
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
const visiblePlayers = getFilteredPlayers();
const selectedVisible = visiblePlayers.filter(p => selectedPlayers.has(p.id));
if (selectedVisible.length === 0) {
selectAllCheckbox.checked = false;
selectAllCheckbox.indeterminate = false;
} else if (selectedVisible.length === visiblePlayers.length) {
selectAllCheckbox.checked = true;
selectAllCheckbox.indeterminate = false;
} else {
selectAllCheckbox.checked = false;
selectAllCheckbox.indeterminate = true;
}
}
// Bulk actions
function enableSelected() {
if (selectedPlayers.size === 0) {
alert(t('league.no_players_selected'));
return;
}
if (!confirm(`Enable ${selectedPlayers.size} selected players?`)) {
return;
}
bulkUpdatePlayers(Array.from(selectedPlayers), true);
}
function disableSelected() {
if (selectedPlayers.size === 0) {
alert(t('league.no_players_selected'));
return;
}
if (!confirm(`Disable ${selectedPlayers.size} selected players?`)) {
return;
}
bulkUpdatePlayers(Array.from(selectedPlayers), false);
}
async function bulkUpdatePlayers(playerIds, enabled) {
try {
for (const playerId of playerIds) {
const response = await fetch(`/api/players/${playerId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ enabled: enabled })
});
if (response.ok) {
const player = players.find(p => p.id === playerId);
if (player) {
player.enabled = enabled;
}
}
}
selectedPlayers.clear();
renderPlayerTable();
updateStats();
} catch (error) {
console.error('Error bulk updating players:', error);
alert('Error updating players. Please try again.');
}
}
// Update stats display
function updateStats() {
const totalCount = players.length;
const enabledCount = players.filter(p => p.enabled).length;
const disabledCount = totalCount - enabledCount;
const visibleCount = getFilteredPlayers().length;
document.getElementById('totalPlayersCount').textContent = totalCount;
document.getElementById('enabledPlayersCount').textContent = enabledCount;
document.getElementById('disabledPlayersCount').textContent = disabledCount;
document.getElementById('visiblePlayersCount').textContent = visibleCount;
document.getElementById('enabledCount').textContent = enabledCount;
// Update button states
const startLeagueBtn = document.getElementById('startLeagueBtn');
const startSingleBtn = document.getElementById('startSingleBtn');
const warningMsg = document.getElementById('warningMessage');
if (startLeagueBtn && startSingleBtn && warningMsg) {
if (enabledCount < 1) {
startLeagueBtn.disabled = true;
startSingleBtn.disabled = true;
warningMsg.style.display = 'block';
} else {
startLeagueBtn.disabled = false;
startSingleBtn.disabled = false;
warningMsg.style.display = 'none';
}
}
}
// Render the player table
function renderPlayerTable() {
const tbody = document.getElementById('playerTableBody');
const noResults = document.getElementById('noResults');
const filteredPlayers = getFilteredPlayers();
tbody.innerHTML = '';
if (filteredPlayers.length === 0) {
noResults.style.display = 'block';
return;
} else {
noResults.style.display = 'none';
}
filteredPlayers.forEach(player => {
const row = document.createElement('tr');
row.className = player.enabled ? 'enabled' : 'disabled';
row.innerHTML = `
<td>
<input type="checkbox"
${selectedPlayers.has(player.id) ? 'checked' : ''}
onchange="togglePlayerSelection(${player.id}, this.checked)">
</td>
<td class="player-id">#${player.id}</td>
<td class="player-name" id="playerName${player.id}">
${player.name}
</td>
<td class="player-status status-col">
<span class="status-badge ${player.enabled ? 'status-enabled' : 'status-disabled'}">
${player.enabled ? '✓' : '✗'}
</span>
</td>
<td class="player-actions actions-col">
<div class="action-toggle">
<div class="toggle-switch ${player.enabled ? 'enabled' : ''}"
onclick="togglePlayer(${player.id})"></div>
<span style="font-size: 0.9rem; color: #666;">
${player.enabled ? 'Competing' : 'Not competing'}
</span>
</div>
<div class="action-buttons-cell">
<button class="action-btn-small edit-btn-small"
onclick="editPlayer(${player.id})"
title="Edit Player Name">
✏️ <span data-i18n="league.edit">Uredi</span>
</button>
<button class="action-btn-small delete-btn-small"
onclick="confirmDeletePlayer(${player.id})"
title="Delete Player">
🗑️ Delete
</button>
</div>
</td>
`;
tbody.appendChild(row);
});
updateSelectAllCheckbox();
updateStats();
}
// Add new player
async function addPlayer() {
const nameInput = document.getElementById('newPlayerName');
const name = nameInput.value.trim();
if (!name) {
alert('Please enter a player name');
return;
}
const addBtn = document.getElementById('addPlayerBtn');
addBtn.disabled = true;
addBtn.textContent = 'Adding...';
try {
const response = await fetch('/api/players/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: name })
});
if (response.ok) {
const result = await response.json();
players.push(result.player);
nameInput.value = '';
renderPlayerTable();
} else {
const error = await response.json();
alert('Failed to add player: ' + error.message);
}
} catch (error) {
console.error('Error adding player:', error);
alert('Error adding player. Please try again.');
} finally {
addBtn.disabled = false;
addBtn.innerHTML = '<span data-i18n="players.add_player"> Dodaj Igralca</span>';
translatePage();
}
}
// Handle Enter key in add player input
function handleAddPlayerKeypress(event) {
if (event.key === 'Enter') {
event.preventDefault();
addPlayer();
}
}
// Edit player name
function editPlayer(playerId) {
const player = players.find(p => p.id === playerId);
if (!player) return;
const nameElement = document.getElementById(`playerName${playerId}`);
if (editingPlayer === playerId) {
// Save changes
const input = nameElement.querySelector('input');
if (input) {
const newName = input.value.trim();
if (newName && newName !== player.name) {
updatePlayerName(playerId, newName);
} else {
editingPlayer = null;
renderPlayerTable();
}
}
} else {
// Start editing
editingPlayer = playerId;
nameElement.className = 'player-name editing';
nameElement.innerHTML = `
<input type="text" value="${player.name}" maxlength="50"
onblur="savePlayerName(${playerId})"
onkeypress="handleEditKeypress(event, ${playerId})"
autofocus>
`;
}
}
function savePlayerName(playerId) {
editPlayer(playerId);
}
function handleEditKeypress(event, playerId) {
if (event.key === 'Enter') {
event.preventDefault();
editPlayer(playerId);
} else if (event.key === 'Escape') {
editingPlayer = null;
renderPlayerTable();
}
}
// Update player name
async function updatePlayerName(playerId, newName) {
try {
const response = await fetch(`/api/players/${playerId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: newName.trim() })
});
if (response.ok) {
// Update local player data
const player = players.find(p => p.id === playerId);
if (player) {
player.name = newName.trim();
}
editingPlayer = null;
renderPlayerTable();
} else {
alert('Failed to update player name');
editingPlayer = null;
renderPlayerTable();
}
} catch (error) {
console.error('Error updating player:', error);
editingPlayer = null;
renderPlayerTable();
}
}
// Toggle player enabled/disabled
async function togglePlayer(playerId) {
const player = players.find(p => p.id === playerId);
if (!player) return;
const newEnabled = !player.enabled;
try {
const response = await fetch(`/api/players/${playerId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ enabled: newEnabled })
});
if (response.ok) {
player.enabled = newEnabled;
renderPlayerTable();
} else {
alert('Failed to update player status');
}
} catch (error) {
console.error('Error toggling player:', error);
alert('Error updating player. Please try again.');
}
}
// Confirm delete player
function confirmDeletePlayer(playerId) {
const player = players.find(p => p.id === playerId);
if (!player) return;
showModal(
'Delete Player',
`Are you sure you want to permanently delete "${player.name}"? This action cannot be undone.`,
() => deletePlayer(playerId)
);
}
// Delete player
async function deletePlayer(playerId) {
try {
const response = await fetch(`/api/players/${playerId}/delete`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
});
if (response.ok) {
players = players.filter(p => p.id !== playerId);
selectedPlayers.delete(playerId);
renderPlayerTable();
closeModal();
} else {
alert('Failed to delete player');
}
} catch (error) {
console.error('Error deleting player:', error);
alert('Error deleting player. Please try again.');
}
}
// Start league
async function startLeague() {
const enabledPlayers = players.filter(p => p.enabled);
if (enabledPlayers.length < 1) {
alert('Need at least 1 enabled player to start league');
return;
}
const formatText = selectedTournamentType === '40_targets' ? t('tournament_types.40_targets_full') :
selectedTournamentType === '4_targets' ? t('tournament_types.4_targets_full') :
t('tournament_types.20_targets_full');
if (!confirm(t('messages.confirm_start_league', { players: enabledPlayers.length, format: formatText }))) {
return;
}
const startBtn = document.getElementById('startLeagueBtn');
startBtn.disabled = true;
startBtn.textContent = 'Starting League...';
try {
const response = await fetch('/api/league/start', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ tournament_type: selectedTournamentType })
});
if (response.ok) {
const result = await response.json();
alert('League started successfully!');
window.location.reload();
} else {
const error = await response.json();
alert('Failed to start league: ' + error.message);
}
} catch (error) {
console.error('Error starting league:', error);
alert('Error starting league. Please try again.');
} finally {
startBtn.disabled = false;
startBtn.setAttribute('data-i18n', 'league.start_league_5_tournaments');
startBtn.textContent = '🎖️ Začni Ligo (5 Turnirjev)';
translatePage();
}
}
// Start single tournament
async function startSingleTournament() {
const enabledPlayers = players.filter(p => p.enabled);
if (enabledPlayers.length < 1) {
alert('Need at least 1 enabled player to start tournament');
return;
}
const formatText = selectedTournamentType === '40_targets' ? t('tournament_types.40_targets_full') :
selectedTournamentType === '4_targets' ? t('tournament_types.4_targets_full') :
t('tournament_types.20_targets_full');
if (!confirm(t('messages.confirm_start_tournament', { players: enabledPlayers.length, format: formatText }))) {
return;
}
const startBtn = document.getElementById('startSingleBtn');
startBtn.disabled = true;
startBtn.textContent = 'Starting...';
try {
const response = await fetch('/api/tournament/start', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ tournament_type: selectedTournamentType })
});
if (response.ok) {
const result = await response.json();
alert('Tournament started successfully!');
window.location.reload();
} else {
const error = await response.json();
alert('Failed to start tournament: ' + error.message);
}
} catch (error) {
console.error('Error starting tournament:', error);
alert('Error starting tournament. Please try again.');
} finally {
startBtn.disabled = false;
startBtn.textContent = '🎯 Start Single Tournament';
}
}
// Start next tournament in league
async function startNextTournament() {
// Get selected joker players
const jokerCheckboxes = document.querySelectorAll('.joker-checkbox:checked:not(:disabled)');
const jokerPlayers = Array.from(jokerCheckboxes).map(cb => parseInt(cb.dataset.playerId));
const confirmMessage = jokerPlayers.length === 1 ?
t('league.start_tournament_confirm_single') :
t('league.start_tournament_confirm_multiple').replace('{count}', jokerPlayers.length);
if (!confirm(confirmMessage)) {
return;
}
try {
const response = await fetch('/api/league/tournament/start', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ joker_players: jokerPlayers })
});
if (response.ok) {
const result = await response.json();
alert('Tournament started successfully!');
window.location.reload();
} else {
const error = await response.json();
alert('Failed to start tournament: ' + error.message);
}
} catch (error) {
console.error('Error starting tournament:', error);
alert('Error starting tournament. Please try again.');
}
}
// Reset league
async function resetLeague() {
if (!confirm('Are you sure you want to reset the league? This will delete all league and tournament data.')) {
return;
}
try {
const response = await fetch('/api/league/reset', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
});
if (response.ok) {
alert('League reset successfully!');
window.location.reload();
} else {
alert('Failed to reset league');
}
} catch (error) {
console.error('Error resetting league:', error);
alert('Error resetting league. Please try again.');
}
}
// Reset tournament
async function resetTournament() {
if (!confirm('Are you sure you want to reset the tournament? This will delete tournament data.')) {
return;
}
try {
const response = await fetch('/api/tournament/reset', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
});
if (response.ok) {
alert('Tournament reset successfully!');
window.location.reload();
} else {
alert('Failed to reset tournament');
}
} catch (error) {
console.error('Error resetting tournament:', error);
alert('Error resetting tournament. Please try again.');
}
}
// Modal functions
function showModal(title, message, confirmCallback) {
document.getElementById('modalTitle').textContent = title;
document.getElementById('modalMessage').textContent = message;
pendingAction = confirmCallback;
document.getElementById('confirmationModal').classList.add('active');
}
function closeModal() {
document.getElementById('confirmationModal').classList.remove('active');
pendingAction = null;
}
function confirmAction() {
if (pendingAction) {
pendingAction();
}
}
// Click outside modal to close
document.getElementById('confirmationModal').addEventListener('click', function(e) {
if (e.target === this) {
closeModal();
}
});
// Initialize page
document.addEventListener('DOMContentLoaded', function() {
renderPlayerTable();
// Focus on add player input if no active league/tournament
const nameInput = document.getElementById('newPlayerName');
if (nameInput && !leagueActive && !tournamentActive) {
nameInput.focus();
}
console.log('🏆 Tournament Management loaded');
console.log('League active:', leagueActive);
console.log('Tournament active:', tournamentActive);
});
</script>
<!-- Include i18n support -->
<script src="/static/js/i18n.js"></script>
<script>
// Initialize language selector and i18n
document.addEventListener('DOMContentLoaded', function() {
translatePage();
});
</script>
</body>
</html>