summaryrefslogtreecommitdiff
path: root/templates
diff options
context:
space:
mode:
Diffstat (limited to 'templates')
-rw-r--r--templates/admin.html138
-rw-r--r--templates/admin_edit_game.html66
-rw-r--r--templates/admin_manage_teams.html76
-rw-r--r--templates/base.html54
-rw-r--r--templates/game.html185
-rw-r--r--templates/login.html16
-rw-r--r--templates/season.html285
-rw-r--r--templates/team.html65
8 files changed, 885 insertions, 0 deletions
diff --git a/templates/admin.html b/templates/admin.html
new file mode 100644
index 0000000..19c7bd9
--- /dev/null
+++ b/templates/admin.html
@@ -0,0 +1,138 @@
+{% extends "base.html" %}
+
+{% block content %}
+ <h2>League Administration</h2>
+
+ <div style="display: flex; gap: 2rem; flex-wrap: wrap;">
+ <div style="flex: 1; min-width: 300px;">
+ <h3>Create New Season</h3>
+ <form method="POST">
+ <input type="hidden" name="action" value="create_season">
+ <div>
+ <label for="name">Season Name:</label>
+ <input type="text" id="name" name="name" required>
+ </div>
+ <button type="submit">Create Season</button>
+ </form>
+ </div>
+
+ <div style="flex: 1; min-width: 300px;">
+ <h3>Create Team/User</h3>
+ <form method="POST">
+ <input type="hidden" name="action" value="create_team">
+ <div>
+ <label for="username">Username:</label>
+ <input type="text" id="username" name="username" required>
+ </div>
+ <div>
+ <label for="password">Password:</label>
+ <input type="password" id="password" name="password" required>
+ </div>
+ <div>
+ <label for="team_name">Team Name:</label>
+ <input type="text" id="team_name" name="team_name" required>
+ </div>
+ <button type="submit">Create Team</button>
+ </form>
+ </div>
+ </div>
+
+ <div style="margin-top: 2rem;">
+ <h3>Manage Seasons</h3>
+ {% if seasons %}
+ <table>
+ <tr>
+ <th>ID</th>
+ <th>Name</th>
+ <th>Status</th>
+ <th>Actions</th>
+ </tr>
+ {% for season in seasons %}
+ <tr>
+ <td>{{ season.id }}</td>
+ <td>{{ season.name }}</td>
+ <td>{{ season.status }}</td>
+ <td>
+ <form method="GET" action="{{ url_for('admin_manage_teams', season_id=season.id) }}" style="display:inline;">
+ <button type="submit">Manage Teams</button>
+ </form>
+ <button onclick="toggleScheduleForm({{ season.id }})">Generate Schedule/Playoffs</button>
+
+ <div id="form-{{ season.id }}" style="display:none; background: #f0f0f0; padding: 1rem; border: 1px solid #ccc; margin-top: 10px; text-align: left;">
+ <form id="sched-form-{{ season.id }}" onsubmit="submitGenerate(event, {{ season.id }})">
+ <div>
+ <label>Total Games (per team):</label>
+ <input type="number" name="total_games" value="10" required style="width: 60px;">
+ </div>
+ <div>
+ <label>Games Per Week:</label>
+ <input type="number" name="games_per_week" value="3" required style="width: 60px;">
+ </div>
+ <div>
+ <label>Playoff Teams (2 or 4):</label>
+ <input type="number" name="playoff_teams" value="4" required style="width: 60px;">
+ </div>
+ <div>
+ <label>Series Length (1, 3, 5):</label>
+ <input type="number" name="playoff_series_length" value="3" required style="width: 60px;">
+ </div>
+ <button type="submit" style="margin-top: 10px;">Generate</button>
+ </form>
+ </div>
+ <form method="POST" action="{{ url_for('admin_delete_season', season_id=season.id) }}" style="display:inline;" onsubmit="return confirm('Are you sure you want to delete this season and all its games?')">
+ <button type="submit" style="background-color: #cc0000; color: white;">Delete</button>
+ </form>
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+
+ <script>
+ function toggleScheduleForm(id) {
+ var f = document.getElementById('form-' + id);
+ f.style.display = f.style.display === 'none' ? 'block' : 'none';
+ }
+
+ function submitGenerate(event, id, confirmed = false) {
+ event.preventDefault();
+ var form = document.getElementById('sched-form-' + id);
+ var formData = new FormData(form);
+ if (confirmed) formData.append('confirm', 'true');
+
+ fetch('/admin/season/' + id + '/generate_schedule', {
+ method: 'POST',
+ body: formData,
+ headers: {'X-Requested-With': 'XMLHttpRequest'}
+ })
+ .then(response => response.json())
+ .then(data => {
+ if (data.status === 'confirm_required') {
+ if (confirm(data.message)) {
+ submitGenerate(event, id, true);
+ }
+ } else if (data.status === 'success') {
+ window.location.href = data.redirect;
+ } else {
+ alert('An error occurred.');
+ }
+ });
+ }
+ </script>
+ {% else %}
+ <p>No seasons created yet.</p>
+ {% endif %}
+ </div>
+
+ <div style="margin-top: 2rem;">
+ <h3>Registered Teams</h3>
+ {% if teams %}
+ <ul>
+ {% for team in teams %}
+ <li>{{ team.team_name }} ({{ team.username }})</li>
+ {% endfor %}
+ </ul>
+ {% else %}
+ <p>No teams registered yet.</p>
+ {% endif %}
+ </div>
+{% endblock %} \ No newline at end of file
diff --git a/templates/admin_edit_game.html b/templates/admin_edit_game.html
new file mode 100644
index 0000000..2651185
--- /dev/null
+++ b/templates/admin_edit_game.html
@@ -0,0 +1,66 @@
+{% extends "base.html" %}
+
+{% block content %}
+ <h2>Admin: Edit Game {{ game.id }}</h2>
+ <p>Matchup: {{ game.away_team if game.away_team else 'TBD' }} @ {{ game.home_team if game.home_team else 'TBD' }}</p>
+
+ <form method="POST" style="max-width: 100%;">
+ <div style="background: var(--bg-primary); padding: 2rem; border: 1px solid var(--deco-border); width: 100%; box-sizing: border-box;">
+ <div style="display: flex; gap: 2rem; flex-wrap: wrap;">
+ <div style="flex: 1; min-width: 200px;">
+ <label for="scheduled_date">Scheduled Date (YYYY-MM-DD):</label>
+ <input type="text" id="scheduled_date" name="scheduled_date" value="{{ game.scheduled_date }}" style="width: 100%;">
+ </div>
+ <div style="flex: 1; min-width: 200px;">
+ <label for="status">Status:</label>
+ <select id="status" name="status" style="width: 100%;">
+ <option value="Scheduled" {% if game.status == 'Scheduled' %}selected{% endif %}>Scheduled</option>
+ <option value="Final" {% if game.status == 'Final' %}selected{% endif %}>Final</option>
+ <option value="TBD" {% if game.status == 'TBD' %}selected{% endif %}>TBD</option>
+ <option value="Canceled" {% if game.status == 'Canceled' %}selected{% endif %}>Canceled</option>
+ </select>
+ </div>
+ </div>
+
+ <div style="display: flex; gap: 2rem; margin-top: 1rem; flex-wrap: wrap;">
+ <div style="flex: 1; min-width: 200px;">
+ <label for="away_score">{{ game.away_team if game.away_team else 'Away' }} Score:</label>
+ <input type="number" id="away_score" name="away_score" value="{{ game.away_score if game.away_score is not none else '' }}" style="width: 100%;">
+ </div>
+ <div style="flex: 1; min-width: 200px;">
+ <label for="home_score">{{ game.home_team if game.home_team else 'Home' }} Score:</label>
+ <input type="number" id="home_score" name="home_score" value="{{ game.home_score if game.home_score is not none else '' }}" style="width: 100%;">
+ </div>
+ </div>
+
+ <div style="margin-top: 2rem; overflow-x: auto;">
+ <label style="display: block; margin-bottom: 0.5rem; font-weight: bold;">Box Score (Optional):</label>
+ <table style="width: 100%; border: 1px solid var(--deco-border); background: #fff; min-width: 600px;">
+ <tr style="background: #eee;">
+ <th>Team</th>
+ <th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th><th>Ex</th><th>R</th><th>H</th><th>E</th>
+ </tr>
+ <tr>
+ <td style="font-weight: bold; font-size: 0.8rem; padding: 5px;">{{ game.away_team if game.away_team else 'Away' }}</td>
+ {% set bs_a = game.box_score.away if game.box_score else [0,0,0,0,0,0,0,0,0,0,0,0,0] %}
+ {% for col in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "extra", "runs", "hits", "errors"] %}
+ <td style="padding: 2px;"><input type="number" name="away_inn_{{ col }}" value="{{ bs_a[loop.index0] }}" style="width: 35px; padding: 2px; text-align: center;"></td>
+ {% endfor %}
+ </tr>
+ <tr>
+ <td style="font-weight: bold; font-size: 0.8rem; padding: 5px;">{{ game.home_team if game.home_team else 'Home' }}</td>
+ {% set bs_h = game.box_score.home if game.box_score else [0,0,0,0,0,0,0,0,0,0,0,0,0] %}
+ {% for col in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "extra", "runs", "hits", "errors"] %}
+ <td style="padding: 2px;"><input type="number" name="home_inn_{{ col }}" value="{{ bs_h[loop.index0] }}" style="width: 35px; padding: 2px; text-align: center;"></td>
+ {% endfor %}
+ </tr>
+ </table>
+ </div>
+
+ <div style="margin-top: 2rem; display: flex; gap: 1rem;">
+ <button type="submit" style="padding: 10px 30px;">Update Game</button>
+ <a href="{{ url_for('game', game_id=game.id) }}" style="display: inline-block; background: #ddd; color: #333; padding: 10px 20px; text-decoration: none; font-family: var(--sans-font); font-weight: bold; border: 1px solid #ccc;">Cancel</a>
+ </div>
+ </div>
+ </form>
+{% endblock %} \ No newline at end of file
diff --git a/templates/admin_manage_teams.html b/templates/admin_manage_teams.html
new file mode 100644
index 0000000..669d622
--- /dev/null
+++ b/templates/admin_manage_teams.html
@@ -0,0 +1,76 @@
+{% extends "base.html" %}
+
+{% block content %}
+ <h2>Manage Teams for Season: {{ season.name }}</h2>
+
+ <div style="display: flex; gap: 2rem; flex-wrap: wrap;">
+ <!-- Left Column: Pending and Approved Teams -->
+ <div style="flex: 1; min-width: 300px;">
+ <h3>Pending Requests</h3>
+ {% if pending_teams %}
+ <ul style="list-style: none; padding: 0;">
+ {% for team in pending_teams %}
+ <li style="background: var(--bg-primary); padding: 1rem; margin-bottom: 0.5rem; border: 1px solid var(--deco-border); display: flex; justify-content: space-between; align-items: center;">
+ <span>{{ team.team_name }} ({{ team.username }})</span>
+ <div style="display: flex; gap: 0.5rem;">
+ <form method="POST" style="margin:0; width: auto;">
+ <input type="hidden" name="action" value="approve">
+ <input type="hidden" name="user_id" value="{{ team.id }}">
+ <button type="submit" style="background-color: green; font-size: 0.8rem; padding: 4px 8px;">Approve</button>
+ </form>
+ <form method="POST" style="margin:0; width: auto;">
+ <input type="hidden" name="action" value="deny">
+ <input type="hidden" name="user_id" value="{{ team.id }}">
+ <button type="submit" style="background-color: red; font-size: 0.8rem; padding: 4px 8px;">Deny</button>
+ </form>
+ </div>
+ </li>
+ {% endfor %}
+ </ul>
+ {% else %}
+ <p>No pending requests.</p>
+ {% endif %}
+
+ <h3 style="margin-top: 2rem;">Approved Teams</h3>
+ {% if approved_teams %}
+ <ul style="list-style: none; padding: 0;">
+ {% for team in approved_teams %}
+ <li style="background: var(--bg-primary); padding: 1rem; margin-bottom: 0.5rem; border: 1px solid var(--deco-border); display: flex; justify-content: space-between; align-items: center;">
+ <span>{{ team.team_name }} ({{ team.username }})</span>
+ <form method="POST" style="margin:0; width: auto;">
+ <input type="hidden" name="action" value="remove">
+ <input type="hidden" name="user_id" value="{{ team.id }}">
+ <button type="submit" style="background-color: red; font-size: 0.8rem; padding: 4px 8px;">Remove</button>
+ </form>
+ </li>
+ {% endfor %}
+ </ul>
+ {% else %}
+ <p>No approved teams.</p>
+ {% endif %}
+ </div>
+
+ <!-- Right Column: Add Teams Directly -->
+ <div style="flex: 1; min-width: 300px; background: var(--bg-primary); padding: 2rem; border: 1px solid var(--deco-border);">
+ <h3>Directly Add Teams</h3>
+ <p>Select teams to bypass the request process and approve immediately.</p>
+ <form method="POST">
+ <input type="hidden" name="action" value="add">
+ <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 1.5rem;">
+ {% for team in all_teams %}
+ {% if team.id not in enrolled_ids %}
+ <label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
+ <input type="checkbox" name="team_ids" value="{{ team.id }}">
+ {{ team.team_name }}
+ </label>
+ {% endif %}
+ {% endfor %}
+ </div>
+ <button type="submit">Add Selected Teams</button>
+ </form>
+ <div style="margin-top: 2rem;">
+ <a href="{{ url_for('admin') }}" style="color: var(--text-accent); text-decoration: underline; font-weight: bold;">&larr; Back to Admin Dashboard</a>
+ </div>
+ </div>
+ </div>
+{% endblock %} \ No newline at end of file
diff --git a/templates/base.html b/templates/base.html
new file mode 100644
index 0000000..9172079
--- /dev/null
+++ b/templates/base.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>The Orchard League</title>
+ <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
+</head>
+<body>
+ <img src="{{ url_for('static', filename='img/orchards_left.png') }}" class="side-image left">
+ <img src="{{ url_for('static', filename='img/orchards_right.png') }}" class="side-image right">
+ <header>
+ <div class="logo-container">
+ <img src="{{ url_for('static', filename='img/logo.png') }}"/>
+ <div class="text-wrap">
+ <h1>THE ORCHARD LEAGUE</h1>
+ <p class="subtitle">Established 2026</p>
+ </div>
+ </div>
+ <nav>
+ <a href="{{ url_for('index') }}">Seasons</a>
+ {% if current_user.is_authenticated %}
+ <a href="{{ url_for('team') }}">Team Management ({{ current_user.team_name }})</a>
+ {% if current_user.is_admin %}
+ <a href="{{ url_for('admin') }}">Admin</a>
+ {% endif %}
+ <a href="{{ url_for('logout') }}">Logout ({{ current_user.username }})</a>
+ {% else %}
+ <a href="{{ url_for('login') }}">Login</a>
+ {% endif %}
+ </nav>
+ </header>
+
+ <main>
+ <div class="flashes">
+ {% with messages = get_flashed_messages() %}
+ {% if messages %}
+ <ul class="flash-messages">
+ {% for message in messages %}
+ <li>{{ message }}</li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ {% endwith %}
+ </div>
+
+ {% block content %}{% endblock %}
+ </main>
+
+ <footer>
+ <p>&copy; Blessings; WWCH -Chairman of the Orchard League.</p>
+ </footer>
+</body>
+</html> \ No newline at end of file
diff --git a/templates/game.html b/templates/game.html
new file mode 100644
index 0000000..690e16d
--- /dev/null
+++ b/templates/game.html
@@ -0,0 +1,185 @@
+{% extends "base.html" %}
+
+{% block content %}
+ <div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem;">
+ <a href="{{ url_for('index', season_id=game.season_id, tab='schedule') }}"
+ style="text-decoration: none; background: #ddd; color: #333; padding: 5px 15px; font-family: var(--sans-font); font-weight: bold; border: 1px solid #ccc;">
+ &larr; Back to Schedule
+ </a>
+ <h2 style="margin: 0; flex: 1; border: none;">Game Details</h2>
+ </div>
+
+ {% if game %}
+ <div style="display: flex; justify-content: center; gap: 4rem; align-items: center; margin: 2rem 0; background: var(--bg-primary); padding: 2rem; border: 2px solid var(--deco-border);">
+ <div style="text-align: center;">
+ <h3>Away</h3>
+ {% set is_away_team = current_user.is_authenticated and current_user.id|string == game.away_team_id|string %}
+ {% if game.away_icon %}
+ <img src="{{ url_for('static', filename='uploads/' + game.away_icon) }}" style="width:100px; height:100px; border-radius:50%; border: {{ '5px solid gold' if is_away_team else '2px solid var(--text-accent)' }};">
+ {% else %}
+ <div style="width: 100px; height: 100px; border-radius: 50%; background-color: var(--deco-border); display: inline-block; border: {{ '5px solid gold' if is_away_team else 'none' }};"></div>
+ {% endif %}
+ <h4>{{ game.away_team if game.away_team else 'TBD' }}</h4>
+ <div style="font-size: 3rem; font-weight: bold; color: var(--deco-highlight);">{{ game.away_score if game.status == 'Final' else '-' }}</div>
+ </div>
+
+ <div style="text-align: center;">
+ <div style="color: var(--text-accent); font-size: 2rem; margin-bottom: 1rem;">VS</div>
+ <div style="color: var(--text-primary);">Date: {{ game.scheduled_date }}</div>
+ <div style="color: var(--deco-highlight); font-weight: bold; margin-top: 1rem; text-transform: uppercase;">
+ {{ game.status }}
+ {% if game.is_conditional %}<span class="conditional-game" title="Conditional Game">*</span>{% endif %}
+ </div>
+
+ {% if current_user.is_admin %}
+ <div style="margin-top: 1rem;">
+ <a href="{{ url_for('admin_edit_game', game_id=game.id) }}" style="background: var(--deco-border); color: var(--bg-primary); padding: 5px 10px; text-decoration: none;">&#9998; Edit Game</a>
+ </div>
+ {% endif %}
+ </div>
+
+ <div style="text-align: center;">
+ <h3>Home</h3>
+ {% set is_home_team = current_user.is_authenticated and current_user.id|string == game.home_team_id|string %}
+ {% if game.home_icon %}
+ <img src="{{ url_for('static', filename='uploads/' + game.home_icon) }}" style="width:100px; height:100px; border-radius:50%; border: {{ '5px solid gold' if is_home_team else '2px solid var(--text-accent)' }};">
+ {% else %}
+ <div style="width: 100px; height: 100px; border-radius: 50%; background-color: var(--deco-border); display: inline-block; border: {{ '5px solid gold' if is_home_team else 'none' }};"></div>
+ {% endif %}
+ <h4>{{ game.home_team if game.home_team else 'TBD' }}</h4>
+ <div style="font-size: 3rem; font-weight: bold; color: var(--deco-highlight);">{{ game.home_score if game.status == 'Final' else '-' }}</div>
+ </div>
+ </div>
+
+ {% if game.status == 'Final' and game.box_score and (game.box_score.away|sum + game.box_score.home|sum) > 0 %}
+ <div style="margin-top: 2rem; overflow-x: auto;">
+ <h3>Box Score</h3>
+ <table style="width: 100%; font-family: var(--sans-font); border: 2px solid #000;">
+ <tr style="background: #eee;">
+ <th>Team</th>
+ <th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th><th>Extra</th>
+ <th style="background: #ddd;">R</th><th>H</th><th>E</th>
+ </tr>
+ <tr>
+ <td style="font-weight: bold;">{{ game.away_team }}</td>
+ {% for val in game.box_score.away %}
+ <td style="{{ 'background: #f9f9f9; font-weight: bold;' if loop.index > 10 else '' }}">{{ val }}</td>
+ {% endfor %}
+ </tr>
+ <tr>
+ <td style="font-weight: bold;">{{ game.home_team }}</td>
+ {% for val in game.box_score.home %}
+ <td style="{{ 'background: #f9f9f9; font-weight: bold;' if loop.index > 10 else '' }}">{{ val }}</td>
+ {% endfor %}
+ </tr>
+ </table>
+ </div>
+ {% endif %}
+
+ {% if game.status != 'Final' and submissions %}
+ <div style="margin-top: 2rem;">
+ <h3>Active Proposals</h3>
+ {% for s in submissions %}
+ {% set show_score = s.away_score is not none and (s.away_score != game.away_score or s.home_score != game.home_score) %}
+ {% set show_date = s.proposed_date and s.proposed_date != game.scheduled_date %}
+
+ {% if show_score or show_date %}
+ <div style="background: #fff; border: 1px solid var(--deco-border); padding: 1rem; margin-bottom: 1rem; display: flex; justify-content: space-between; align-items: flex-start;">
+ <div>
+ <p style="margin: 0;"><strong>From:</strong> {{ s.team_name }} ({{ s.username }})</p>
+ {% if show_score %}
+ <p style="margin: 0.5rem 0 0 0;"><strong>Score:</strong> {{ game.away_team }} {{ s.away_score }} - {{ game.home_team }} {{ s.home_score }}</p>
+ {% if s.box_score %}
+ <details style="margin-top: 0.5rem;">
+ <summary style="cursor: pointer; font-size: 0.85rem; color: #555;">View Proposed Box Score</summary>
+ <table style="width: 100%; font-size: 0.75rem; margin-top: 0.5rem; border: 1px solid #ddd;">
+ <tr style="background: #f5f5f5;">
+ <th>Team</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th><th>Ex</th><th>R</th><th>H</th><th>E</th>
+ </tr>
+ <tr><td>Away</td>{% for v in s.box_score.away %}<td>{{ v }}</td>{% endfor %}</tr>
+ <tr><td>Home</td>{% for v in s.box_score.home %}<td>{{ v }}</td>{% endfor %}</tr>
+ </table>
+ </details>
+ {% endif %}
+ {% endif %}
+ {% if show_date %}
+ <p style="margin: 0.5rem 0 0 0;"><strong>Date Proposal:</strong> {{ s.proposed_date }}</p>
+ {% endif %}
+ </div>
+ <div style="display: flex; gap: 0.5rem;">
+ {% if current_user.id|string == s.submitted_by_id|string %}
+ <form method="POST" action="{{ url_for('retract_submission', game_id=game.id) }}">
+ <button type="submit" style="background-color: #cc0000; font-size: 0.8rem; padding: 5px 10px;">Retract</button>
+ </form>
+ {% elif current_user.is_authenticated and (current_user.id|string == game.away_team_id|string or current_user.id|string == game.home_team_id|string) %}
+ <form method="POST" action="{{ url_for('agree_submission', game_id=game.id, submission_id=s.id) }}">
+ <button type="submit" style="background-color: #008800; font-size: 0.8rem; padding: 5px 10px;">Agree & Finalize</button>
+ </form>
+ {% endif %}
+ </div>
+ </div>
+ {% endif %}
+ {% endfor %}
+ </div>
+ {% endif %}
+
+ {% if game.status != 'Final' and current_user.is_authenticated and (current_user.id|string == game.away_team_id|string or current_user.id|string == game.home_team_id|string) %}
+ <div style="margin-top: 2rem; display: flex; flex-direction: column; gap: 2rem;">
+ <!-- Score Submission Form (Full Width) -->
+ <div style="background: var(--bg-primary); padding: 2rem; border: 1px solid var(--deco-border);">
+ <h3>Submit Game Results</h3>
+ <form method="POST" action="{{ url_for('submit_game', game_id=game.id) }}" style="max-width: 100%;">
+ <div style="display: flex; gap: 1rem; margin-bottom: 1rem; max-width: 400px;">
+ <div style="flex: 1;">
+ <label for="away_score" style="display: block; margin-bottom: 0.5rem;">{{ game.away_team }} Score:</label>
+ <input type="number" id="away_score" name="away_score" required style="width: 100%;">
+ </div>
+ <div style="flex: 1;">
+ <label for="home_score" style="display: block; margin-bottom: 0.5rem;">{{ game.home_team }} Score:</label>
+ <input type="number" id="home_score" name="home_score" required style="width: 100%;">
+ </div>
+ </div>
+
+ <div style="margin-bottom: 1rem; overflow-x: auto;">
+ <label style="display: block; margin-bottom: 0.5rem;">Box Score (Optional):</label>
+ <table style="width: 100%; border: 1px solid var(--deco-border); background: #fff;">
+ <tr style="background: #eee;">
+ <th>Team</th>
+ <th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th><th>Extra</th><th>R</th><th>H</th><th>E</th>
+ </tr>
+ <tr>
+ <td style="font-weight: bold; font-size: 0.8rem;">{{ game.away_team if game.away_team else 'Away' }}</td>
+ {% for col in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "extra", "runs", "hits", "errors"] %}
+ <td><input type="number" name="away_inn_{{ col }}" value="0" style="width: 35px; padding: 2px; text-align: center;"></td>
+ {% endfor %}
+ </tr>
+ <tr>
+ <td style="font-weight: bold; font-size: 0.8rem;">{{ game.home_team if game.home_team else 'Home' }}</td>
+ {% for col in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "extra", "runs", "hits", "errors"] %}
+ <td><input type="number" name="home_inn_{{ col }}" value="0" style="width: 35px; padding: 2px; text-align: center;"></td>
+ {% endfor %}
+ </tr>
+ </table>
+ </div>
+
+ <button type="submit" style="width: 200px;">Submit Scores</button>
+ </form>
+ </div>
+
+ <!-- Date Change Form -->
+ <div style="background: var(--bg-primary); padding: 2rem; border: 1px solid var(--deco-border); max-width: 400px;">
+ <h3>Propose Date Change</h3>
+ <form method="POST" action="{{ url_for('submit_game', game_id=game.id) }}" style="max-width: 100%;">
+ <div style="margin-bottom: 1rem;">
+ <label for="proposed_date" style="display: block; margin-bottom: 0.5rem;">New Date:</label>
+ <input type="text" id="proposed_date" name="proposed_date" placeholder="YYYY-MM-DD" style="width: 100%;">
+ </div>
+ <button type="submit" style="width: 100%; background-color: var(--deco-highlight); color: white;">Propose Date</button>
+ </form>
+ </div>
+ </div>
+ {% endif %}
+ {% else %}
+ <p>Game not found.</p>
+ {% endif %}
+{% endblock %} \ No newline at end of file
diff --git a/templates/login.html b/templates/login.html
new file mode 100644
index 0000000..f8f19b6
--- /dev/null
+++ b/templates/login.html
@@ -0,0 +1,16 @@
+{% extends "base.html" %}
+
+{% block content %}
+ <h2>Team Owner Login</h2>
+ <form method="POST" action="{{ url_for('login') }}">
+ <div>
+ <label for="username">Username:</label>
+ <input type="text" id="username" name="username" required>
+ </div>
+ <div>
+ <label for="password">Password:</label>
+ <input type="password" id="password" name="password" required>
+ </div>
+ <button type="submit">Login</button>
+ </form>
+{% endblock %} \ No newline at end of file
diff --git a/templates/season.html b/templates/season.html
new file mode 100644
index 0000000..43ca0de
--- /dev/null
+++ b/templates/season.html
@@ -0,0 +1,285 @@
+{% extends "base.html" %}
+
+{% block content %}
+ <div style="margin-bottom: 2rem;">
+ <form method="GET" style="flex-direction: row; align-items: center; max-width: 100%; border: none; padding: 0;">
+ <label for="season_id" style="margin-right: 10px; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase;">Select Season:</label>
+ <select id="season_id" name="season_id" onchange="this.form.submit()" style="padding: 5px 10px;">
+ {% for season in seasons %}
+ <option value="{{ season.id }}" {% if season.id|string == selected_season_id|string %}selected{% endif %}>{{ season.name }}</option>
+ {% endfor %}
+ </select>
+ <input type="hidden" name="tab" value="{{ active_tab }}">
+ </form>
+ </div>
+
+ <!-- Tabs Navigation -->
+ <div style="border-bottom: 2px solid var(--text-accent); margin-bottom: 1rem; display: flex; gap: 5px;">
+ <a href="{{ url_for('index', season_id=selected_season_id, tab='overview') }}"
+ style="padding: 10px 20px; text-decoration: none; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase; border: 1px solid var(--deco-border); border-bottom: none; {{ 'background: white; color: black;' if active_tab == 'overview' else 'background: #ddd; color: #555;' }}">
+ Season Overview
+ </a>
+ <a href="{{ url_for('index', season_id=selected_season_id, tab='standings') }}"
+ style="padding: 10px 20px; text-decoration: none; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase; border: 1px solid var(--deco-border); border-bottom: none; {{ 'background: white; color: black;' if active_tab == 'standings' else 'background: #ddd; color: #555;' }}">
+ Standings
+ </a>
+ <a href="{{ url_for('index', season_id=selected_season_id, tab='schedule') }}"
+ style="padding: 10px 20px; text-decoration: none; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase; border: 1px solid var(--deco-border); border-bottom: none; {{ 'background: white; color: black;' if active_tab == 'schedule' else 'background: #ddd; color: #555;' }}">
+ Schedule
+ </a>
+ <a href="{{ url_for('index', season_id=selected_season_id, tab='playoffs') }}"
+ style="padding: 10px 20px; text-decoration: none; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase; border: 1px solid var(--deco-border); border-bottom: none; {{ 'background: white; color: black;' if active_tab == 'playoffs' else 'background: #ddd; color: #555;' }}">
+ Playoffs
+ </a>
+ </div>
+
+ {% if active_tab == 'overview' %}
+ <div class="tab-content">
+ <h3>{{ season_info.name }} - Overview</h3>
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; margin-top: 1rem;">
+ <div style="background: white; padding: 1.5rem; border: 1px solid var(--deco-border);">
+ <p><strong>Total Games (Per Team):</strong> {{ season_info.total_games }}</p>
+ <p><strong>Games Per Week:</strong> {{ season_info.games_per_week }}</p>
+ <p><strong>Season Start:</strong> {{ season_info.start_date }}</p>
+ <p><strong>Season End:</strong> {{ season_info.end_date }}</p>
+ {% if season_info.total_games %}
+ <p><strong>Playoff Teams:</strong> {{ season_info.playoff_teams }}</p>
+ {% endif %}
+ <p><strong>Status:</strong> {{ season_info.status }} {% if season_info.is_finished %}(Finished){% else %}(In Progress){% endif %}</p>
+ </div>
+
+ <div style="background: white; padding: 1.5rem; border: 1px solid var(--deco-border);">
+ {% if season_info.is_finished %}
+ <h4>Final Standings</h4>
+ {% if standings %}
+ <table style="margin-top: 0; width: 100%;">
+ {% for row in standings %}
+ <tr>
+ <td>{{ loop.index }}. <strong>{{ row.team_name }}</strong></td>
+ <td>{{ row.wins }} - {{ row.losses }}</td>
+ </tr>
+ {% endfor %}
+ </table>
+ {% else %}
+ <p>No teams enrolled.</p>
+ {% endif %}
+ {% else %}
+ <h4>League Action</h4>
+ <p>The season is currently active or upcoming.</p>
+
+ {% if current_user.is_authenticated and not current_user.is_admin %}
+ {% if user_season_status == 'Approved' %}
+ <div style="background: #f0fff0; border: 1px solid green; padding: 10px; margin-top: 10px;">
+ <p style="color: green; font-weight: bold; margin: 0;">You are currently enrolled in this season.</p>
+ </div>
+ {% elif user_season_status == 'Pending' %}
+ <div style="background: #fffbe6; border: 1px solid orange; padding: 10px; margin-top: 10px;">
+ <p style="color: orange; font-weight: bold; margin: 0;">Your request to join is pending approval.</p>
+ </div>
+ {% else %}
+ <form method="POST" action="{{ url_for('join_season', season_id=selected_season_id) }}">
+ <button type="submit" style="width: 100%; padding: 12px; font-size: 1.1rem;">Apply to Join Season</button>
+ </form>
+ {% endif %}
+ {% elif not current_user.is_authenticated %}
+ <p style="border: 1px solid #ccc; padding: 10px; background: #eee;">
+ <a href="{{ url_for('login') }}" style="font-weight: bold; color: black; text-decoration: underline;">Login</a> to apply for this season.
+ </p>
+ {% endif %}
+ {% endif %}
+ </div>
+ </div>
+ </div>
+
+ {% elif active_tab == 'standings' %}
+ <div class="tab-content">
+ <h3>{{ season_info.name }} - Standings</h3>
+ {% if standings %}
+ <table>
+ <tr>
+ <th>Team</th>
+ <th>Wins (W)</th>
+ <th>Losses (L)</th>
+ <th>Runs For (RF)</th>
+ <th>Runs Against (RA)</th>
+ <th>Games Back (GB)</th>
+ </tr>
+ {% for row in standings %}
+ {% set is_my_team = current_user.is_authenticated and current_user.id|string == row.user_id|string %}
+ {% set is_cutoff = loop.index == season_info.playoff_teams %}
+ <tr style="{{ 'background-color: #ffffcc;' if is_my_team else '' }} {{ 'border-bottom: 4px solid #333;' if is_cutoff else '' }}">
+ <td style="display: flex; align-items: center; justify-content: center; gap: 10px;">
+ {% if row.team_icon %}
+ <img src="{{ url_for('static', filename='uploads/' + row.team_icon) }}" alt="{{ row.team_name }}"
+ class="{{ 'team-icon-highlight' if is_my_team else '' }}"
+ style="width: 30px; height: 30px; border-radius: 50%; border: 1px solid var(--deco-border);">
+ {% else %}
+ <div class="{{ 'team-icon-highlight' if is_my_team else '' }}"
+ style="width: 30px; height: 30px; border-radius: 50%; background-color: var(--deco-highlight); display: inline-block;"></div>
+ {% endif %}
+ {{ row.team_name }}
+ {% if row.clinch %}<span class="clinch-marker" title="Clinched Playoff Spot {{ '(1st Seed)' if row.clinch == '**' else '' }}">{{ row.clinch }}</span>{% endif %}
+ </td>
+ <td>{{ row.wins }}</td>
+ <td>{{ row.losses }}</td>
+ <td>{{ row.runs_for }}</td>
+ <td>{{ row.runs_against }}</td>
+ <td>{{ row.games_back }}</td>
+ </tr>
+ {% endfor %}
+ </table>
+ {% else %}
+ <p>No standings available for the selected season.</p>
+ {% endif %}
+ </div>
+
+ {% elif active_tab == 'schedule' %}
+ <div class="tab-content">
+ <h3>{{ season_info.name }} - Schedule</h3>
+
+ <form method="GET" style="flex-direction: row; align-items: center; max-width: 100%; margin-bottom: 1.5rem; border: none; padding: 0;">
+ <input type="hidden" name="season_id" value="{{ selected_season_id }}">
+ <input type="hidden" name="tab" value="schedule">
+ <label for="team_id" style="margin-right: 10px; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase;">Filter by Team:</label>
+ <select id="team_id" name="team_id" onchange="this.form.submit()" style="padding: 5px 10px;">
+ <option value="all">All Teams</option>
+ {% for team in all_teams %}
+ <option value="{{ team.id }}" {% if team.id|string == selected_team_id|string %}selected{% endif %}>{{ team.team_name }}</option>
+ {% endfor %}
+ </select>
+ </form>
+
+ {% for month in months %}
+ <div class="calendar-month">
+ <h4>{{ month.name }}</h4>
+ <div class="calendar-grid">
+ {% for day in ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] %}
+ <div class="calendar-day-head">{{ day }}</div>
+ {% endfor %}
+
+ {% for week in month.weeks %}
+ {% for day in week %}
+ {% set date_str = "%04d-%02d-%02d" % (month.year, month.month, day) if day != 0 else "" %}
+ <div class="calendar-day {{ 'other-month' if day == 0 else '' }} {{ 'today' if date_str == today else '' }}">
+ {% if day != 0 %}
+ <span class="calendar-day-num">{{ day }}</span>
+ {% if date_str in games_by_date %}
+ {% for game in games_by_date[date_str] %}
+ {% set is_away_mine = current_user.is_authenticated and current_user.id|string == game.away_team_id|string %}
+ {% set is_home_mine = current_user.is_authenticated and current_user.id|string == game.home_team_id|string %}
+ <div class="calendar-game-item" onclick="window.location='{{ url_for('game', game_id=game.id) }}'">
+ <span title="{{ game.away_team if game.away_team else 'TBD' }} @ {{ game.home_team if game.home_team else 'TBD' }}">
+ {% if game.away_icon %}
+ <img src="{{ url_for('static', filename='uploads/' + game.away_icon) }}" class="team-icon-small {{ 'team-icon-highlight' if is_away_mine else '' }}">
+ {% else %}
+ <div class="team-icon-small {{ 'team-icon-highlight' if is_away_mine else '' }}" style="display:inline-block; background:#ccc;"></div>
+ {% endif %}
+ {{ game.away_score if game.status == 'Final' else '' }} @
+ {{ game.home_score if game.status == 'Final' else '' }}
+ {% if game.home_icon %}
+ <img src="{{ url_for('static', filename='uploads/' + game.home_icon) }}" class="team-icon-small {{ 'team-icon-highlight' if is_home_mine else '' }}">
+ {% else %}
+ <div class="team-icon-small {{ 'team-icon-highlight' if is_home_mine else '' }}" style="display:inline-block; background:#ccc;"></div>
+ {% endif %}
+ {% if game.is_conditional %}*{% endif %}
+ {% if game.pending_proposals > 0 %}
+ <span class="pending-icon" title="Game has pending proposals!">&#9888;</span>
+ {% endif %}
+ </span>
+ </div>
+ {% endfor %}
+ {% endif %}
+ {% endif %}
+ </div>
+ {% endfor %}
+ {% endfor %}
+ </div>
+ </div>
+ {% endfor %}
+
+ {% if games_by_date['TBD'] %}
+ <h3>TBD Games</h3>
+ <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem;">
+ {% for game in games_by_date['TBD'] %}
+ <div class="calendar-game-item" onclick="window.location='{{ url_for('game', game_id=game.id) }}'" style="padding: 1rem; font-size: 0.9rem;">
+ TBD @ TBD (Playoff)
+ </div>
+ {% endfor %}
+ </div>
+ {% endif %}
+ </div>
+ {% elif active_tab == 'playoffs' %}
+ <div class="tab-content">
+ <h3>{{ season_info.name }} - Playoffs</h3>
+
+ {% if bracket %}
+ <div class="bracket-container">
+ {% for round_games in bracket %}
+ <div class="bracket-round">
+ <h4 style="border: none; text-align: center; font-size: 0.9rem;">Round {{ loop.index }}</h4>
+ {% for g in round_games %}
+ <div class="bracket-game {{ 'winner' if g.status == 'Final' }}" onclick="window.location='{{ url_for('game', game_id=g.id) }}'" style="cursor: pointer;">
+ <div class="bracket-team">
+ <span>{{ g.away_team if g.away_team else 'TBD' }} {{ g.away_record if g.away_team else '' }}</span>
+ <span style="font-weight: bold; margin-left: 10px;">{{ g.away_series_wins }}</span>
+ </div>
+ <div class="bracket-team">
+ <span>{{ g.home_team if g.home_team else 'TBD' }} {{ g.home_record if g.home_team else '' }}</span>
+ <span style="font-weight: bold; margin-left: 10px;">{{ g.home_series_wins }}</span>
+ </div>
+ <div style="font-size: 0.6rem; color: #777; margin-top: 3px;">
+ Best of {{ season_info.playoff_series_length }}
+ </div>
+ </div>
+ {% endfor %}
+ </div>
+ {% endfor %}
+ </div>
+ {% else %}
+ <p>Playoff bracket not yet generated.</p>
+ {% endif %}
+
+ <h3>Playoff Schedule</h3>
+ {% if playoff_games %}
+ <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 1rem;">
+ {% for game in playoff_games %}
+ {% set is_away_mine = current_user.is_authenticated and current_user.id|string == game.away_team_id|string %}
+ {% set is_home_mine = current_user.is_authenticated and current_user.id|string == game.home_team_id|string %}
+ <div style="border: 1px solid var(--deco-border); padding: 1rem; background: white; cursor: pointer;"
+ onclick="window.location='{{ url_for('game', game_id=game.id) }}'">
+ <div style="font-size: 0.8rem; color: var(--deco-highlight); margin-bottom: 0.5rem; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase;">
+ {{ game.scheduled_date }} - {{ game.status }}
+ {% if game.is_conditional %}<span class="conditional-game">*</span>{% endif %}
+ {% if game.pending_proposals > 0 %}<span class="pending-icon">&#9888;</span>{% endif %}
+ </div>
+ <div style="display: flex; justify-content: space-between; align-items: center;">
+ <div style="text-align: center; flex: 1;">
+ {% if game.away_icon %}
+ <img src="{{ url_for('static', filename='uploads/' + game.away_icon) }}" class="team-icon-small {{ 'team-icon-highlight' if is_away_mine else '' }}">
+ {% else %}
+ <div class="team-icon-small {{ 'team-icon-highlight' if is_away_mine else '' }}" style="display:inline-block; background:#ccc; border-radius: 50%;"></div>
+ {% endif %}
+ <br><strong style="font-size: 0.8rem;">{{ game.away_team if game.away_team else 'TBD' }}</strong>
+ <br><span style="font-weight: bold;">{{ game.away_score if game.status == 'Final' else '-' }}</span>
+ </div>
+ <div style="font-weight: bold;">@</div>
+ <div style="text-align: center; flex: 1;">
+ {% if game.home_icon %}
+ <img src="{{ url_for('static', filename='uploads/' + game.home_icon) }}" class="team-icon-small {{ 'team-icon-highlight' if is_home_mine else '' }}">
+ {% else %}
+ <div class="team-icon-small {{ 'team-icon-highlight' if is_home_mine else '' }}" style="display:inline-block; background:#ccc; border-radius: 50%;"></div>
+ {% endif %}
+ <br><strong style="font-size: 0.8rem;">{{ game.home_team if game.home_team else 'TBD' }}</strong>
+ <br><span style="font-weight: bold;">{{ game.home_score if game.status == 'Final' else '-' }}</span>
+ </div>
+ </div>
+ </div>
+ {% endfor %}
+ </div>
+ {% else %}
+ <p>No playoff games scheduled.</p>
+ {% endif %}
+ </div>
+ {% endif %}
+
+{% endblock %} \ No newline at end of file
diff --git a/templates/team.html b/templates/team.html
new file mode 100644
index 0000000..e7098be
--- /dev/null
+++ b/templates/team.html
@@ -0,0 +1,65 @@
+{% extends "base.html" %}
+
+{% block content %}
+ <h2>Team Management: {{ current_user.team_name }}</h2>
+
+ {% if current_user.team_icon %}
+ <div style="margin-bottom: 1rem;">
+ <img src="{{ url_for('static', filename='uploads/' + current_user.team_icon) }}" alt="Team Icon" style="max-width: 150px; border: 1px solid var(--deco-border);">
+ </div>
+ {% endif %}
+
+ <div style="display: flex; gap: 2rem; flex-wrap: wrap;">
+ <div style="flex: 1; min-width: 300px;">
+ <h3>Update Profile</h3>
+ <form method="POST" enctype="multipart/form-data">
+ <div>
+ <label for="team_name">Team Name:</label>
+ <input type="text" id="team_name" name="team_name" value="{{ current_user.team_name }}">
+ </div>
+ <div>
+ <label for="new_password">New Password (leave blank to keep current):</label>
+ <input type="password" id="new_password" name="new_password">
+ </div>
+ <div>
+ <label for="team_icon">Upload Team Icon:</label>
+ <input type="file" id="team_icon" name="team_icon" accept="image/*">
+ </div>
+ <button type="submit">Save Changes</button>
+ </form>
+ </div>
+
+ <div style="flex: 1; min-width: 300px;">
+ <h3>Seasons</h3>
+ {% if seasons %}
+ <ul style="list-style: none; padding: 0;">
+ {% for season in seasons %}
+ <li style="background: var(--bg-primary); padding: 1rem; margin-bottom: 0.5rem; border: 1px solid var(--deco-border); display: flex; justify-content: space-between; align-items: center;">
+ <span><strong>{{ season.name }}</strong> ({{ season.status }})</span>
+
+ {% if not current_user.is_admin %}
+ {% if season.id in my_seasons %}
+ {% if my_seasons[season.id] == 'Approved' %}
+ <span style="color: green; font-weight: bold;">Joined</span>
+ {% else %}
+ <span style="color: orange; font-weight: bold;">Pending Approval</span>
+ {% endif %}
+ {% else %}
+ <form method="POST" action="{{ url_for('join_season', season_id=season.id) }}" style="margin: 0;">
+ <button type="submit" style="padding: 4px 8px; font-size: 0.8rem;">Request to Join</button>
+ </form>
+ {% endif %}
+ {% endif %}
+ </li>
+ {% endfor %}
+ </ul>
+ {% else %}
+ <p>No seasons available right now.</p>
+ {% endif %}
+
+ <h3 style="margin-top: 2rem;">Your Schedule</h3>
+ <p>Below is your team's schedule for the active season.</p>
+ <a href="{{ url_for('index', tab='schedule', team_id=current_user.id) }}" style="display: inline-block; background-color: var(--text-accent); color: white; padding: 8px 16px; text-decoration: none; font-weight: bold;">View Full Team Schedule</a>
+ </div>
+ </div>
+{% endblock %} \ No newline at end of file